mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-06 15:58:18 +00:00
lib: table: use hash for exact-match lookups
Most read accesses of route_table are actually exact matches where walking down the tree is wildly inefficient. Use a parallel hash structure instead. This significantly speeds up processes that are performance-bound by table accesses, e.g. BGP withdraw processing. In other locations, the improvement is not seen as strongly, e.g. when filter processing is the limiting factor. [includes fix to ignore prefix host bits in hash comparison] Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This commit is contained in:
parent
bc7a2c035a
commit
736ac221d1
44
lib/table.c
44
lib/table.c
@ -46,6 +46,12 @@ static unsigned route_table_hash_key(void *pp)
|
||||
return jhash (©, sizeof(copy), 0x55aa5a5a);
|
||||
}
|
||||
|
||||
static int route_table_hash_cmp(const void *a, const void *b)
|
||||
{
|
||||
const struct prefix *pa = a, *pb = b;
|
||||
return prefix_cmp(pa, pb) == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* route_table_init_with_delegate
|
||||
*/
|
||||
@ -57,7 +63,7 @@ route_table_init_with_delegate (route_table_delegate_t *delegate)
|
||||
rt = XCALLOC (MTYPE_ROUTE_TABLE, sizeof (struct route_table));
|
||||
rt->delegate = delegate;
|
||||
rt->hash = hash_create(route_table_hash_key,
|
||||
(int (*)(const void *, const void *)) prefix_same,
|
||||
route_table_hash_cmp,
|
||||
"route table hash");
|
||||
return rt;
|
||||
}
|
||||
@ -294,21 +300,9 @@ route_node_lookup (const struct route_table *table, union prefixconstptr pu)
|
||||
{
|
||||
const struct prefix *p = pu.p;
|
||||
struct route_node *node;
|
||||
u_char prefixlen = p->prefixlen;
|
||||
const u_char *prefix = &p->u.prefix;
|
||||
|
||||
node = table->top;
|
||||
|
||||
while (node && node->p.prefixlen <= prefixlen &&
|
||||
prefix_match (&node->p, p))
|
||||
{
|
||||
if (node->p.prefixlen == prefixlen)
|
||||
return node->info ? route_lock_node (node) : NULL;
|
||||
|
||||
node = node->link[prefix_bit(prefix, node->p.prefixlen)];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
node = hash_get (table->hash, (void *)p, NULL);
|
||||
return (node && node->info) ? route_lock_node (node) : NULL;
|
||||
}
|
||||
|
||||
/* Lookup same prefix node. Return NULL when we can't find route. */
|
||||
@ -317,21 +311,9 @@ route_node_lookup_maynull (const struct route_table *table, union prefixconstptr
|
||||
{
|
||||
const struct prefix *p = pu.p;
|
||||
struct route_node *node;
|
||||
u_char prefixlen = p->prefixlen;
|
||||
const u_char *prefix = &p->u.prefix;
|
||||
|
||||
node = table->top;
|
||||
|
||||
while (node && node->p.prefixlen <= prefixlen &&
|
||||
prefix_match (&node->p, p))
|
||||
{
|
||||
if (node->p.prefixlen == prefixlen)
|
||||
return route_lock_node (node);
|
||||
|
||||
node = node->link[prefix_bit(prefix, node->p.prefixlen)];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
node = hash_get (table->hash, (void *)p, NULL);
|
||||
return node ? route_lock_node (node) : NULL;
|
||||
}
|
||||
|
||||
/* Add node to routing table. */
|
||||
@ -346,6 +328,10 @@ route_node_get (struct route_table *const table, union prefixconstptr pu)
|
||||
u_char prefixlen = p->prefixlen;
|
||||
const u_char *prefix = &p->u.prefix;
|
||||
|
||||
node = hash_get (table->hash, (void *)p, NULL);
|
||||
if (node && node->info)
|
||||
return route_lock_node (node);
|
||||
|
||||
match = NULL;
|
||||
node = table->top;
|
||||
while (node && node->p.prefixlen <= prefixlen &&
|
||||
|
Loading…
Reference in New Issue
Block a user