Commit 69c05819c5 for frr
commit 69c05819c512ad8684a6acfc5e834c3d2f39e15d
Author: Mark Stapp <mjs@cisco.com>
Date: Thu Oct 22 13:15:37 2026 -0400
lib: skip hash use in unique-mode prefix tables
A unique-mode table can do direct lookups in its rbtree: it
doesn't need to use the table's hashtable for direct lookups.
Signed-off-by: Mark Stapp <mjs@cisco.com>
diff --git a/lib/table.c b/lib/table.c
index 121f85c57c..23f72e2d76 100644
--- a/lib/table.c
+++ b/lib/table.c
@@ -114,7 +114,6 @@ static void route_table_free(struct route_table *rt)
if (rt->unique_mode) {
while ((node = rn_tree_pop(&rt->tree)) != NULL) {
node->lock = 0; /* to cause assert if unlocked after this */
- rn_hash_node_del(&rt->hash, node);
route_node_free(rt, node);
rt->count--;
}
@@ -236,7 +235,7 @@ struct route_node *route_node_match(struct route_table *table,
prefix_copy(&rn.p, pu.p);
apply_mask(&rn.p);
- matched = rn_hash_node_find(&table->hash, &rn);
+ matched = rn_tree_find(&table->tree, &rn);
if (matched && matched->info == NULL)
matched = NULL;
@@ -272,7 +271,10 @@ struct route_node *route_node_lookup(struct route_table *table,
prefix_copy(&rn.p, pu.p);
apply_mask(&rn.p);
- node = rn_hash_node_find(&table->hash, &rn);
+ if (table->unique_mode)
+ node = rn_tree_find(&table->tree, &rn);
+ else
+ node = rn_hash_node_find(&table->hash, &rn);
return (node && node->info) ? route_lock_node(node) : NULL;
}
@@ -284,7 +286,10 @@ struct route_node *route_node_lookup_maynull(struct route_table *table,
prefix_copy(&rn.p, pu.p);
apply_mask(&rn.p);
- node = rn_hash_node_find(&table->hash, &rn);
+ if (table->unique_mode)
+ node = rn_tree_find(&table->tree, &rn);
+ else
+ node = rn_hash_node_find(&table->hash, &rn);
return node ? route_lock_node(node) : NULL;
}
@@ -310,27 +315,34 @@ struct route_node *route_node_get(struct route_table *table,
uint16_t prefixlen = p->prefixlen;
const uint8_t *prefix = &p->u.prefix;
- node = rn_hash_node_find(&table->hash, &search);
- if (node && node->info) {
- if (p->family == AF_FLOWSPEC)
- prefix_flowspec_ptr_free(p);
- return route_lock_node(node);
- }
-
/* For unique-mode, just add an entry directly */
if (table->unique_mode) {
+ node = rn_tree_find(&table->tree, &search);
+ if (node && node->info) {
+ if (p->family == AF_FLOWSPEC)
+ prefix_flowspec_ptr_free(p);
+ return route_lock_node(node);
+ }
+
new = route_node_new(table);
prefix_copy(&new->p, p);
new->p.family = p->family;
new->table = table;
- rn_hash_node_add(&table->hash, new);
- /* Add to rbtree also */
+ /* Add to rbtree, skip the hashtable */
rn_tree_add(&table->tree, new);
goto done;
}
+ /* LPM matching table starts here, with a hash lookup */
+ node = rn_hash_node_find(&table->hash, &search);
+ if (node && node->info) {
+ if (p->family == AF_FLOWSPEC)
+ prefix_flowspec_ptr_free(p);
+ return route_lock_node(node);
+ }
+
match = NULL;
node = table->top;
while (node && node->p.prefixlen <= prefixlen
@@ -420,11 +432,11 @@ void route_node_delete(struct route_node *node)
} else
node->table->top = child;
+ rn_hash_node_del(&node->table->hash, node);
+
skip_tree:
node->table->count--;
- rn_hash_node_del(&node->table->hash, node);
-
/* WARNING: FRAGILE CODE!
* route_node_free may have the side effect of free'ing the entire
* table.