]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Hostcache should use trie to filter relevant route changes.
authorOndrej Zajicek <santiago@crfreenet.org>
Tue, 27 Jul 2010 16:20:12 +0000 (18:20 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Tue, 27 Jul 2010 16:20:12 +0000 (18:20 +0200)
filter/trie.c
nest/route.h
nest/rt-table.c

index 522eb99ffe2af3be753d20d579cb9e9e5aa8b0b6..2f0edfa9970313dcf32fa37a6a4ab31164273a42 100644 (file)
@@ -114,8 +114,8 @@ attach_node(struct f_trie_node *parent, struct f_trie_node *child)
  * @h: prefix upper bound
  *
  * Adds prefix (prefix pattern) @px/@plen to trie @t.  @l and @h are lower
- * and upper bounds on accepted prefix lengths, both inclusive. 0 <=
- * l, h <= 32 (128 for IPv6).
+ * and upper bounds on accepted prefix lengths, both inclusive.
+ * 0 <= l, h <= 32 (128 for IPv6).
  */
 
 void
index 97678e18d924d79fe73ef1c8647e35ad803c9b51..45b78e38df0c915598b8a6f13cc4f2561542170e 100644 (file)
@@ -155,8 +155,9 @@ struct hostcache {
   unsigned hash_order, hash_shift;
   unsigned hash_max, hash_min;
   unsigned hash_items;
-
-  list hostentries;
+  linpool *lp;                         /* Linpool for trie */
+  struct f_trie *trie;                 /* Trie of prefixes that might affect hostentries */
+  list hostentries;                    /* List of all hostentries */
   byte update_hostcache;
 };
 
@@ -170,7 +171,6 @@ struct hostentry {
   struct iface *iface;                 /* Chosen outgoing interface */
   ip_addr gw;                          /* Chosen next hop */
   byte dest;                           /* Chosen route destination type (RTD_...) */
-  byte pxlen;                          /* Pxlen from net that matches route */
 };
 
 typedef struct rte {
index 8087769805fb49913168a611eca548d88161c40a..af1a920c25d3b7d9077912b00a660ed1154a6877 100644 (file)
@@ -1399,6 +1399,9 @@ rt_init_hostcache(rtable *tab)
   hc_alloc_table(hc, HC_DEF_ORDER);
   hc->slab = sl_new(rt_table_pool, sizeof(struct hostentry));
 
+  hc->lp = lp_new(rt_table_pool, 1008);
+  hc->trie = f_new_trie(hc->lp);
+
   tab->hostcache = hc;
 }
 
@@ -1416,6 +1419,7 @@ rt_free_hostcache(rtable *tab)
     }
 
   rfree(hc->slab);
+  rfree(hc->lp);
   mb_free(hc->hash_table);
   mb_free(hc);
 }
@@ -1428,17 +1432,8 @@ rt_notify_hostcache(rtable *tab, net *net)
   if (tab->hcu_scheduled)
     return;
 
-  node *n;
-  WALK_LIST(n, hc->hostentries)
-    {
-      struct hostentry *he = SKIP_BACK(struct hostentry, ln, n);
-      if (ipa_in_net(he->addr, net->n.prefix, net->n.pxlen) &&
-         (he->pxlen <= net->n.pxlen))
-       {
-         rt_schedule_hcu(tab);
-         return;
-       }
-    }
+  if (trie_match_prefix(hc->trie, net->n.prefix, net->n.pxlen))
+    rt_schedule_hcu(tab);
 }
 
 static int
@@ -1459,11 +1454,13 @@ rt_update_hostentry(rtable *tab, struct hostentry *he)
   struct iface *old_iface = he->iface;
   ip_addr old_gw = he->gw;
   byte old_dest = he->dest;
+  int pxlen = 0;
 
   net *n = fib_route(&tab->fib, he->addr, MAX_PREFIX_LENGTH);
   if (n && n->routes)
     {
       rta *a = n->routes->attrs;
+      pxlen = n->n.pxlen;
 
       if (a->dest == RTD_DEVICE)
        {
@@ -1491,8 +1488,6 @@ rt_update_hostentry(rtable *tab, struct hostentry *he)
          he->gw = a->gw;
          he->dest = a->dest;
        }
-
-      he->pxlen = n->n.pxlen;
     }
   else
     {
@@ -1500,10 +1495,11 @@ rt_update_hostentry(rtable *tab, struct hostentry *he)
       he->iface = NULL;
       he->gw = IPA_NONE;
       he->dest = RTD_UNREACHABLE;
-
-      he->pxlen = 0;
     }
 
+  /* Add a prefix range to the trie */
+  trie_add_prefix(tab->hostcache->trie, he->addr, MAX_PREFIX_LENGTH, pxlen, MAX_PREFIX_LENGTH);
+
   return hostentry_diff(he, old_iface, old_gw, old_dest);
 }
 
@@ -1514,6 +1510,10 @@ rt_update_hostcache(rtable *tab)
   struct hostentry *he;
   node *n, *x;
 
+  /* Reset the trie */
+  lp_flush(hc->lp);
+  hc->trie = f_new_trie(hc->lp);
+
   WALK_LIST_DELSAFE(n, x, hc->hostentries)
     {
       he = SKIP_BACK(struct hostentry, ln, n);