[quagga-dev 12137] [PATCH 4/4] lib: optimise prefix list setup

David Lamparter equinox at opensourcerouting.org
Mon Apr 13 09:21:37 BST 2015


- duplicate prefix check can use the trie structure
- appending with a seq# beyond the end of the list can shortcut

Configuration load is now bottlenecked by cmd_element_match() and
strcmp().  For a real-world routeserver prefix list configuration
(38668 lines of config for multiple prefix lists):
  before: 4.73s
  after:  1.92s    x 2.46

Signed-off-by: David Lamparter <equinox at opensourcerouting.org>
---
 lib/plist.c | 46 ++++++++++++++++++++++++++++++++++++----------
 1 file changed, 36 insertions(+), 10 deletions(-)

diff --git a/lib/plist.c b/lib/plist.c
index 1181df1..038cd8d 100644
--- a/lib/plist.c
+++ b/lib/plist.c
@@ -635,15 +635,20 @@ prefix_list_entry_add (struct prefix_list *plist,
   if (pentry->seq == -1)
     pentry->seq = prefix_new_seq_get (plist);
 
-  /* Is there any same seq prefix list entry? */
-  replace = prefix_seq_check (plist, pentry->seq);
-  if (replace)
-    prefix_list_entry_delete (plist, replace, 0);
-
-  /* Check insert point. */
-  for (point = plist->head; point; point = point->next)
-    if (point->seq >= pentry->seq)
-      break;
+  if (plist->tail && pentry->seq > plist->tail->seq)
+    point = NULL;
+  else
+    {
+      /* Is there any same seq prefix list entry? */
+      replace = prefix_seq_check (plist, pentry->seq);
+      if (replace)
+        prefix_list_entry_delete (plist, replace, 0);
+
+      /* Check insert point. */
+      for (point = plist->head; point; point = point->next)
+        if (point->seq >= pentry->seq)
+          break;
+    }
 
   /* In case of this is the first element of the list. */
   pentry->next = point;
@@ -849,6 +854,10 @@ static struct prefix_list_entry *
 prefix_entry_dup_check (struct prefix_list *plist,
 			struct prefix_list_entry *new)
 {
+  size_t depth, maxdepth = plist->master->trie_depth;
+  uint8_t byte, *bytes = &new->prefix.u.prefix;
+  size_t validbits = new->prefix.prefixlen;
+  struct pltrie_table *table;
   struct prefix_list_entry *pentry;
   int seq = 0;
 
@@ -857,7 +866,24 @@ prefix_entry_dup_check (struct prefix_list *plist,
   else
     seq = new->seq;
 
-  for (pentry = plist->head; pentry; pentry = pentry->next)
+  table = plist->trie;
+  for (depth = 0; validbits > PLC_BITS && depth < maxdepth - 1; depth++)
+    {
+      byte = bytes[depth];
+      if (!table->entries[byte].next_table)
+        return NULL;
+
+      table = table->entries[byte].next_table;
+      validbits -= PLC_BITS;
+    }
+
+  byte = bytes[depth];
+  if (validbits > PLC_BITS)
+    pentry = table->entries[byte].final_chain;
+  else
+    pentry = table->entries[byte].up_chain;
+
+  for (; pentry; pentry = pentry->next_best)
     {
       if (prefix_same (&pentry->prefix, &new->prefix)
 	  && pentry->type == new->type
-- 
2.0.4





More information about the Quagga-dev mailing list