summaryrefslogtreecommitdiff
path: root/lib/table.c
diff options
context:
space:
mode:
authorDavid Lamparter <equinox@opensourcerouting.org>2017-07-06 17:30:04 +0200
committerDavid Lamparter <equinox@opensourcerouting.org>2017-07-11 13:47:31 +0200
commit736ac221d1e89f3f35703d5175057404de62b50b (patch)
tree8a0f11fb5de225b50ae2d02281d13d59ca8ec2dc /lib/table.c
parentbc7a2c035aa2d8d2820503fb8b7c8328b28bdde4 (diff)
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>
Diffstat (limited to 'lib/table.c')
-rw-r--r--lib/table.c44
1 files changed, 15 insertions, 29 deletions
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 (&copy, 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 &&