summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDavid Lamparter <equinox@opensourcerouting.org>2015-04-13 10:21:37 +0200
committerDonald Sharp <sharpd@cumulusnetworks.com>2015-11-03 05:54:27 -0800
commit20b8a998aa1be595b737c25d3fc0991628bfa3c2 (patch)
treeb7a6998d487d77d3dfc542cd892fdfa62a82a5e4 /lib
parent7e111b6b0de44a9d351cdfeda4c674224a65ec3b (diff)
lib: optimise prefix list setup
- 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@opensourcerouting.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/plist.c46
1 files changed, 36 insertions, 10 deletions
diff --git a/lib/plist.c b/lib/plist.c
index 2fdb0b33e8..63fd94c422 100644
--- a/lib/plist.c
+++ b/lib/plist.c
@@ -641,15 +641,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;
@@ -829,6 +834,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;
@@ -837,7 +846,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