]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Nexthop: Support for label stack in nest
authorJan Moskyto Matejka <mq@ucw.cz>
Fri, 10 Jun 2016 12:34:41 +0000 (14:34 +0200)
committerJan Moskyto Matejka <mq@ucw.cz>
Thu, 22 Dec 2016 12:23:52 +0000 (13:23 +0100)
nest/route.h
nest/rt-attr.c
nest/rt-table.c
proto/ospf/rt.c
proto/pipe/pipe.c
proto/static/static.c

index 154e027ec8e02e14fe65cf2b7363c6918477c8c0..d9a1737bab8152df8b003f3ae85ecebdf51a1a42 100644 (file)
@@ -338,6 +338,8 @@ struct nexthop {
   struct iface *iface;                 /* Outgoing interface */
   struct nexthop *next;
   byte weight;
+  byte labels;                         /* Number of labels appended */
+  u32 label[0];
 };
 
 struct rte_src {
@@ -510,16 +512,21 @@ uint ea_hash(ea_list *e); /* Calculate 16-bit hash value */
 ea_list *ea_append(ea_list *to, ea_list *what);
 void ea_format_bitfield(struct eattr *a, byte *buf, int bufsize, const char **names, int min, int max);
 
+#define NEXTHOP_MAX_LABEL_STACK 8
+
+static inline size_t nexthop_size(const struct nexthop *nh)
+{ return sizeof(struct nexthop) + sizeof(u32)*nh->labels; }
 int nexthop__same(struct nexthop *x, struct nexthop *y); /* Compare multipath nexthops */
 static inline int nexthop_same(struct nexthop *x, struct nexthop *y)
 { return (x == y) || nexthop__same(x, y); }
 struct nexthop *nexthop_merge(struct nexthop *x, struct nexthop *y, int rx, int ry, int max, linpool *lp);
 static inline void nexthop_link(struct rta *a, struct nexthop *from)
-{ a->nh.gw = from->gw; a->nh.iface = from->iface; a->nh.weight = from->weight; a->nh.next = from->next; }
+{ memcpy(&a->nh, from, nexthop_size(from)); }
 void nexthop_insert(struct nexthop *n, struct nexthop *y);
 int nexthop_is_sorted(struct nexthop *x);
 
 void rta_init(void);
+static inline size_t rta_size(const rta *a) { return sizeof(rta) + sizeof(u32)*a->nh.labels; }
 rta *rta_lookup(rta *);                        /* Get rta equivalent to this one, uc++ */
 static inline int rta_is_cached(rta *r) { return r->aflags & RTAF_CACHED; }
 static inline rta *rta_clone(rta *r) { r->uc++; return r; }
index e575ba4a61f3c26f5178257751dec17f71e4138b..d3671a53857e7f51ba5384375c70a01405b43b74 100644 (file)
@@ -60,8 +60,8 @@
 
 pool *rta_pool;
 
-static slab *rta_slab;
-static slab *nexthop_slab;
+static slab *rta_slab_[4];
+static slab *nexthop_slab_[4];
 static slab *rte_src_slab;
 
 static struct idm src_ids;
@@ -148,7 +148,11 @@ nexthop_hash(struct nexthop *x)
 {
   u32 h = 0;
   for (; x; x = x->next)
-    h ^= ipa_hash(x->gw);
+  {
+    h ^= ipa_hash(x->gw) ^ (h << 5) ^ (h >> 9);
+    for (int i=0; i<x->labels; i++)
+      h ^= x->label[i] ^ (h << 6) ^ (h >> 7);
+  }
 
   return h;
 }
@@ -157,10 +161,15 @@ int
 nexthop__same(struct nexthop *x, struct nexthop *y)
 {
   for (; x && y; x = x->next, y = y->next)
-    if (!ipa_equal(x->gw, y->gw) || (x->iface != y->iface) || (x->weight != y->weight))
+  {
+    if (!ipa_equal(x->gw, y->gw) || (x->iface != y->iface) || (x->weight != y->weight) || (x->labels != y->labels))
       return 0;
+    for (int i=0; i<x->labels; i++)
+      if (x->label[i] != y->label[i])
+       return 0;
+  }
 
-  return x == y;
+  return 1;
 }
 
 static int
@@ -182,17 +191,28 @@ nexthop_compare_node(struct nexthop *x, struct nexthop *y)
   if (r)
     return r;
 
+  r = ((int) y->labels) - ((int) x->labels);
+  if (r)
+    return r;
+
+  for (int i=0; i<y->labels; i++)
+  {
+    r = ((int) y->label[i]) - ((int) x->label[i]);
+    if (r)
+      return r;
+  }
+
   return ((int) x->iface->index) - ((int) y->iface->index);
 }
 
 static inline struct nexthop *
 nexthop_copy_node(const struct nexthop *src, linpool *lp)
 {
-  struct nexthop *n = lp_alloc(lp, sizeof(struct nexthop));
-  n->gw = src->gw;
-  n->iface = src->iface;
+  struct nexthop *n = lp_alloc(lp, nexthop_size(src));
+
+  memcpy(n, src, nexthop_size(src));
   n->next = NULL;
-  n->weight = src->weight;
+
   return n;
 }
 
@@ -291,6 +311,12 @@ nexthop_is_sorted(struct nexthop *x)
   return 1;
 }
 
+static inline slab *
+nexthop_slab(struct nexthop *nh)
+{
+  return nexthop_slab_[nh->labels > 2 ? 3 : nh->labels];
+}
+
 static struct nexthop *
 nexthop_copy(struct nexthop *o)
 {
@@ -299,7 +325,7 @@ nexthop_copy(struct nexthop *o)
 
   for (; o; o = o->next)
     {
-      struct nexthop *n = sl_alloc(nexthop_slab);
+      struct nexthop *n = sl_alloc(nexthop_slab(o));
       n->gw = o->gw;
       n->iface = o->iface;
       n->next = NULL;
@@ -320,7 +346,7 @@ nexthop_free(struct nexthop *o)
   while (o)
     {
       n = o->next;
-      sl_free(nexthop_slab, o);
+      sl_free(nexthop_slab(o), o);
       o = n;
     }
 }
@@ -1024,20 +1050,24 @@ rta_same(rta *x, rta *y)
          x->scope == y->scope &&
          x->dest == y->dest &&
          x->igp_metric == y->igp_metric &&
-         ipa_equal(x->nh.gw, y->nh.gw) &&
          ipa_equal(x->from, y->from) &&
-         x->nh.iface == y->nh.iface &&
          x->hostentry == y->hostentry &&
          nexthop_same(&(x->nh), &(y->nh)) &&
          ea_same(x->eattrs, y->eattrs));
 }
 
+static inline slab *
+rta_slab(rta *a)
+{
+  return rta_slab_[a->nh.labels > 2 ? 3 : a->nh.labels];
+}
+
 static rta *
 rta_copy(rta *o)
 {
-  rta *r = sl_alloc(rta_slab);
+  rta *r = sl_alloc(rta_slab(o));
 
-  memcpy(r, o, sizeof(rta));
+  memcpy(r, o, rta_size(o));
   r->uc = 1;
   r->nh.next = nexthop_copy(o->nh.next);
   r->eattrs = ea_list_copy(o->eattrs);
@@ -1138,14 +1168,14 @@ rta__free(rta *a)
   if (a->nh.next)
     nexthop_free(a->nh.next);
   ea_free(a->eattrs);
-  sl_free(rta_slab, a);
+  sl_free(rta_slab(a), a);
 }
 
 rta *
 rta_do_cow(rta *o, linpool *lp)
 {
-  rta *r = lp_alloc(lp, sizeof(rta));
-  memcpy(r, o, sizeof(rta));
+  rta *r = lp_alloc(lp, rta_size(o));
+  memcpy(r, o, rta_size(o));
   r->aflags = 0;
   r->uc = 0;
   return r;
@@ -1176,6 +1206,9 @@ rta_dump(rta *a)
     for (struct nexthop *nh = &(a->nh); nh; nh = nh->next)
       {
        if (ipa_nonzero(nh->gw)) debug(" ->%I", nh->gw);
+       if (nh->labels) debug(" L %d", nh->label[0]);
+       for (int i=1; i<nh->labels; i++)
+         debug("/%d", nh->label[i]);
        debug(" [%s]", nh->iface ? nh->iface->name : "???");
       }
   if (a->eattrs)
@@ -1233,8 +1266,17 @@ void
 rta_init(void)
 {
   rta_pool = rp_new(&root_pool, "Attributes");
-  rta_slab = sl_new(rta_pool, sizeof(rta));
-  nexthop_slab = sl_new(rta_pool, sizeof(struct nexthop));
+
+  rta_slab_[0] = sl_new(rta_pool, sizeof(rta));
+  rta_slab_[1] = sl_new(rta_pool, sizeof(rta) + sizeof(u32));
+  rta_slab_[2] = sl_new(rta_pool, sizeof(rta) + sizeof(u32)*2);
+  rta_slab_[3] = sl_new(rta_pool, sizeof(rta) + sizeof(u32)*NEXTHOP_MAX_LABEL_STACK);
+
+  nexthop_slab_[0] = sl_new(rta_pool, sizeof(struct nexthop));
+  nexthop_slab_[1] = sl_new(rta_pool, sizeof(struct nexthop) + sizeof(u32));
+  nexthop_slab_[2] = sl_new(rta_pool, sizeof(struct nexthop) + sizeof(u32)*2);
+  nexthop_slab_[3] = sl_new(rta_pool, sizeof(struct nexthop) + sizeof(u32)*NEXTHOP_MAX_LABEL_STACK);
+
   rta_alloc_hash();
   rte_src_init();
 }
index 46857d0dddb7c73e703b088a7ffeebb5f12645f4..a7ceddb8aaa17b516714a2f7d7836cd3f28944e2 100644 (file)
@@ -1782,7 +1782,7 @@ static inline rte *
 rt_next_hop_update_rte(rtable *tab UNUSED, rte *old)
 {
   rta a;
-  memcpy(&a, old->attrs, sizeof(rta));
+  memcpy(&a, old->attrs, rta_size(old->attrs));
   rta_apply_hostentry(&a, old->attrs->hostentry);
   a.aflags = 0;
 
index d28d463bef14abbe07af01a401d170cf9d2f0687..74f47810838ca8929e99e70d22523d38e90a15e9 100644 (file)
@@ -37,6 +37,7 @@ static inline struct nexthop *
 new_nexthop(struct ospf_proto *p, ip_addr gw, struct iface *iface, byte weight)
 {
   struct nexthop *nh = lp_alloc(p->nhpool, sizeof(struct nexthop));
+  nh->labels = 0;
   nh->gw = gw;
   nh->iface = iface;
   nh->next = NULL;
index 8924c2000f51d6feb158331c400e53800de170dc..a4d371fe735a676810766e5b1a8bb2b0f16c1dda 100644 (file)
@@ -43,6 +43,8 @@
 
 #include "pipe.h"
 
+#include <alloca.h>
+
 static void
 pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *old, ea_list *attrs)
 {
@@ -51,7 +53,7 @@ pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *o
   struct rte_src *src;
 
   rte *e;
-  rta a;
+  rta *a;
 
   if (!new && !old)
     return;
@@ -65,12 +67,13 @@ pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *o
 
   if (new)
     {
-      memcpy(&a, new->attrs, sizeof(rta));
+      a = alloca(rta_size(new->attrs));
+      memcpy(a, new->attrs, rta_size(new->attrs));
 
-      a.aflags = 0;
-      a.eattrs = attrs;
-      a.hostentry = NULL;
-      e = rte_get_temp(&a);
+      a->aflags = 0;
+      a->eattrs = attrs;
+      a->hostentry = NULL;
+      e = rte_get_temp(a);
       e->pflags = 0;
 
       /* Copy protocol specific embedded attributes. */
@@ -78,7 +81,7 @@ pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *o
       e->pref = new->pref;
       e->pflags = new->pflags;
 
-      src = a.src;
+      src = a->src;
     }
   else
     {
index a63d4d29088f8698c74e713bf36004f76abe8059..9ecf6df8023e12777ea78849a45314e12d55bbca 100644 (file)
@@ -88,6 +88,7 @@ static_install(struct proto *p, struct static_route *r)
            nh->gw = r2->via;
            nh->iface = r2->neigh->iface;
            nh->weight = r2->weight;
+           nh->labels = 0;
            if (a.nh.next)
              nexthop_insert(&(a.nh), nh);
            r2->state |= STS_INSTALLED;