]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
MPLS: Label stack concatenation for recursive routes
authorJan Moskyto Matejka <mq@ucw.cz>
Tue, 9 Aug 2016 12:47:51 +0000 (14:47 +0200)
committerJan Moskyto Matejka <mq@ucw.cz>
Thu, 22 Dec 2016 20:38:33 +0000 (21:38 +0100)
nest/route.h
nest/rt-table.c
proto/static/config.Y
proto/static/static.c

index a2fadf62a65038c308d4271fd31135e7573c3f10..eb98b609081a05d0de698d50e5d6f0733054f757 100644 (file)
@@ -338,7 +338,8 @@ struct nexthop {
   struct iface *iface;                 /* Outgoing interface */
   struct nexthop *next;
   byte weight;
-  byte labels;                         /* Number of labels appended */
+  byte labels_append;                  /* Number of labels before hostentry was applied */
+  byte labels;                         /* Number of labels prepended */
   u32 label[0];
 };
 
index 73b838bee2143fc4317c1968d9bb973bfb869064..ef402f2851632a56939e282e99546e292c22220d 100644 (file)
@@ -1768,27 +1768,56 @@ static inline void
 rta_apply_hostentry(rta *a, struct hostentry *he)
 {
   a->hostentry = he;
-
-  a->nh.gw = ipa_nonzero(he->nh->gw) ? he->nh->gw : he->link;
-  a->nh.iface = he->nh->iface;
-  a->nh.weight = he->nh->weight;
-  a->nh.next = he->nh->next;
   
   a->dest = he->dest;
   a->igp_metric = he->igp_metric;
+
+  if (a->nh.labels_append == 0)
+  {
+    a->nh = *(he->nh);
+    a->nh.labels_append = 0;
+    return;
+  }
+
+  int labels_append = a->nh.labels_append;
+  u32 label_stack[MPLS_MAX_LABEL_STACK];
+  memcpy(label_stack, a->nh.label, labels_append * sizeof(u32));
+
+  struct nexthop *nhp = NULL;
+  for (struct nexthop *nh = he->nh; nh; nh = nh->next)
+  {
+    nhp = nhp ? (nhp->next = lp_alloc(rte_update_pool, NEXTHOP_MAX_SIZE)) : &(a->nh);
+    nhp->gw = ipa_nonzero(nh->gw) ? nh->gw : he->link;
+    nhp->iface = nh->iface; /* FIXME: This is at least strange, if not utter nonsense. */
+    nhp->weight = nh->weight;
+    nhp->labels = nh->labels + labels_append;
+    nhp->labels_append = labels_append;
+    if (nhp->labels <= MPLS_MAX_LABEL_STACK)
+    {
+      memcpy(nhp->label, nh->label, nh->labels * sizeof(u32));
+      memcpy(&(nhp->label[nh->labels]), label_stack, labels_append * sizeof(u32));
+    }
+    else
+    {
+      log(L_WARN "Sum of label stack sizes %d + %d = %d exceedes allowed maximum (%d)",
+         nh->labels, labels_append, nhp->labels, MPLS_MAX_LABEL_STACK);
+      a->dest = RTD_UNREACHABLE;
+      break;
+    }
+  }
 }
 
 static inline rte *
 rt_next_hop_update_rte(rtable *tab UNUSED, rte *old)
 {
-  rta a;
-  memcpy(&a, old->attrs, rta_size(old->attrs));
-  rta_apply_hostentry(&a, old->attrs->hostentry);
-  a.aflags = 0;
+  rta *ap = alloca(RTA_MAX_SIZE);
+  memcpy(ap, old->attrs, rta_size(old->attrs));
+  rta_apply_hostentry(ap, old->attrs->hostentry);
+  ap->aflags = 0;
 
   rte *e = sl_alloc(rte_slab);
   memcpy(e, old, sizeof(rte));
-  e->attrs = rta_lookup(&a);
+  e->attrs = rta_lookup(ap);
 
   return e;
 }
index a461bd27566e61bb10409d9ef0382e3bd043c40a..2fb544483e8848699428bcffcb0a58ad8ce799ad 100644 (file)
@@ -105,7 +105,12 @@ stat_route:
       this_srt->dest = RTDX_RECURSIVE;
       this_srt->via = $3;
    }
-
+ | stat_route0 RECURSIVE ipa MPLS label_stack {
+      this_srt->dest = RTDX_RECURSIVE;
+      this_srt->via = $3;
+      this_srt->label_count = $5[0];
+      this_srt->label_stack = &($5[1]);
+   }
  | stat_route0 DROP            { this_srt->dest = RTD_BLACKHOLE; }
  | stat_route0 REJECT          { this_srt->dest = RTD_UNREACHABLE; }
  | stat_route0 BLACKHOLE       { this_srt->dest = RTD_BLACKHOLE; }
index 878248c1287ccdf21d657e9445ff3be3894d17c6..3e03708c35ecd017c343ac048dafc9a32408d2c6 100644 (file)
@@ -128,7 +128,11 @@ drop:
     r->state |= STS_INSTALLED;
   
   if (r->dest == RTDX_RECURSIVE)
-    rta_set_recursive_next_hop(p->main_channel->table, ap, p_igp_table(p), r->via, IPA_NONE);
+    {
+      ap->nh.labels_append = ap->nh.labels = r->label_count;
+      memcpy(ap->nh.label, r->label_stack, r->label_count * sizeof(u32));
+      rta_set_recursive_next_hop(p->main_channel->table, ap, p_igp_table(p), r->via, IPA_NONE);
+    }
 
   /* We skip rta_lookup() here */