]> git.proxmox.com Git - mirror_frr.git/commitdiff
lib: table: use hash for exact-match lookups
authorDavid Lamparter <equinox@opensourcerouting.org>
Thu, 6 Jul 2017 15:30:04 +0000 (17:30 +0200)
committerDavid Lamparter <equinox@opensourcerouting.org>
Tue, 11 Jul 2017 11:47:31 +0000 (13:47 +0200)
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>
lib/table.c

index 1f01a299738fc83a39c5f858b807a341d2982ccb..1095b03b76253f459256e036634c25da2a27f5cd 100644 (file)
@@ -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 &&