From: David Lamparter Date: Thu, 6 Jul 2017 15:30:04 +0000 (+0200) Subject: lib: table: use hash for exact-match lookups X-Git-Tag: reindent-master-before~3^2~7 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=736ac221d1e89f3f35703d5175057404de62b50b;p=mirror%2Ffrr.git 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 --- diff --git a/lib/table.c b/lib/table.c index 1f01a29973..1095b03b76 100644 --- a/lib/table.c +++ b/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 &&