Commit d47c3d64 authored by Jan Moskyto Matejka's avatar Jan Moskyto Matejka
Browse files

MPLS: Label stack concatenation for recursive routes

parent d14f8c3c
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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];
};

+39 −10
Original line number Diff line number Diff line
@@ -1769,26 +1769,55 @@ 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;
}
+6 −1
Original line number Diff line number Diff line
@@ -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; }
+5 −1
Original line number Diff line number Diff line
@@ -128,7 +128,11 @@ drop:
    r->state |= STS_INSTALLED;
  
  if (r->dest == RTDX_RECURSIVE)
    {
      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 */