diff options
-rw-r--r-- | conf/confbase.Y | 16 | ||||
-rw-r--r-- | lib/ip.h | 4 | ||||
-rw-r--r-- | lib/route.h | 5 | ||||
-rw-r--r-- | nest/rt-attr.c | 11 | ||||
-rw-r--r-- | nest/rt-table.c | 27 | ||||
-rw-r--r-- | nest/rt.h | 6 | ||||
-rw-r--r-- | proto/bgp/packets.c | 43 | ||||
-rw-r--r-- | proto/static/static.c | 28 | ||||
-rw-r--r-- | proto/static/static.h | 2 |
9 files changed, 69 insertions, 73 deletions
diff --git a/conf/confbase.Y b/conf/confbase.Y index 8a27c3d5..9a83083c 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -92,7 +92,7 @@ CF_DECLS struct proto_spec ps; struct channel_limit cl; struct timeformat *tf; - mpls_label_stack *mls; + struct adata *ad; struct bytestring *bs; } @@ -113,7 +113,7 @@ CF_DECLS %type <a> ipa %type <net> net_ip4_ net_ip6_ net_ip6 net_ip_ net_ip net_or_ipa %type <net_ptr> net_ net_any net_vpn4_ net_vpn6_ net_vpn_ net_roa4_ net_roa6_ net_roa_ net_ip6_sadr_ net_mpls_ -%type <mls> label_stack_start label_stack +%type <ad> label_stack_start label_stack %type <t> text opttext %type <s> symbol symbol_known toksym @@ -351,17 +351,19 @@ net_or_ipa: label_stack_start: NUM { - $$ = cfg_allocz(sizeof(mpls_label_stack)); - $$->len = 1; - $$->stack[0] = $1; + $$ = cfg_allocz(ADATA_SIZE(MPLS_MAX_LABEL_STACK * sizeof(u32))); + $$->length = sizeof(u32); + *((u32 *)$$->data) = $1; }; label_stack: label_stack_start | label_stack '/' NUM { - if ($1->len >= MPLS_MAX_LABEL_STACK) + if ($1->length >= MPLS_MAX_LABEL_STACK * sizeof(u32)) cf_error("Too many labels in stack"); - $1->stack[$1->len++] = $3; + + *((u32 *)($$->data + $1->length)) = $3; + $1->length += sizeof(u32); $$ = $1; } ; @@ -363,10 +363,6 @@ static inline ip6_addr ip6_ntoh(ip6_addr a) { return _MI6(ntohl(_I0(a)), ntohl(_I1(a)), ntohl(_I2(a)), ntohl(_I3(a))); } #define MPLS_MAX_LABEL_STACK 8 -typedef struct mpls_label_stack { - uint len; - u32 stack[MPLS_MAX_LABEL_STACK]; -} mpls_label_stack; static inline int mpls_get(const char *buf, int buflen, u32 *stack) diff --git a/lib/route.h b/lib/route.h index cfb08bbe..df648cf9 100644 --- a/lib/route.h +++ b/lib/route.h @@ -72,7 +72,6 @@ struct nexthop { struct nexthop *next; byte flags; byte weight; - byte labels_orig; /* Number of labels before hostentry was applied */ byte labels; /* Number of all labels */ u32 label[0]; }; @@ -316,6 +315,10 @@ extern struct ea_class ea_gen_source; static inline u32 rt_get_source_attr(const rte *rt) { return ea_get_int(rt->attrs->eattrs, &ea_gen_source, 0); } +/* MPLS labels: Use with a recursive nexthop specification + * to add additional labels to the resolved nexthop */ +extern struct ea_class ea_mpls_labels; + /* Next hop structures */ #define NEXTHOP_MAX_SIZE (sizeof(struct nexthop) + sizeof(u32)*MPLS_MAX_LABEL_STACK) diff --git a/nest/rt-attr.c b/nest/rt-attr.c index 39fd7db4..dc4fe785 100644 --- a/nest/rt-attr.c +++ b/nest/rt-attr.c @@ -108,6 +108,12 @@ struct ea_class ea_gen_source = { .format = ea_gen_source_format, }; +struct ea_class ea_mpls_labels = { + .name = "mpls_labels", + .type = T_CLIST, + .readonly = 1, +}; + const char * rta_dest_names[RTD_MAX] = { [RTD_NONE] = "", [RTD_UNICAST] = "unicast", @@ -220,7 +226,7 @@ nexthop__same(struct nexthop *x, struct nexthop *y) { if (!ipa_equal(x->gw, y->gw) || (x->iface != y->iface) || (x->flags != y->flags) || (x->weight != y->weight) || - (x->labels_orig != y->labels_orig) || (x->labels != y->labels)) + (x->labels != y->labels)) return 0; for (int i = 0; i < x->labels; i++) @@ -402,7 +408,6 @@ nexthop_copy(struct nexthop *o) n->next = NULL; n->flags = o->flags; n->weight = o->weight; - n->labels_orig = o->labels_orig; n->labels = o->labels; for (int i=0; i<o->labels; i++) n->label[i] = o->label[i]; @@ -1484,6 +1489,8 @@ rta_init(void) ea_register_init(&ea_gen_igp_metric); ea_register_init(&ea_gen_from); ea_register_init(&ea_gen_source); + + ea_register_init(&ea_mpls_labels); } /* diff --git a/nest/rt-table.c b/nest/rt-table.c index 3f3aee18..ba4f5115 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -2504,7 +2504,7 @@ rt_preconfig(struct config *c) */ void -rta_apply_hostentry(rta *a, struct hostentry *he, mpls_label_stack *mls) +rta_apply_hostentry(rta *a, struct hostentry *he) { a->hostentry = he; a->dest = he->dest; @@ -2516,15 +2516,12 @@ rta_apply_hostentry(rta *a, struct hostentry *he, mpls_label_stack *mls) /* No nexthop */ no_nexthop: a->nh = (struct nexthop) {}; - if (mls) - { /* Store the label stack for later changes */ - a->nh.labels_orig = a->nh.labels = mls->len; - memcpy(a->nh.label, mls->stack, mls->len * sizeof(u32)); - } return; } - if (((!mls) || (!mls->len)) && he->nexthop_linkable) + eattr *mls_ea = ea_find(a->eattrs, &ea_mpls_labels); + + if (!mls_ea && he->nexthop_linkable) { /* Just link the nexthop chain, no label append happens. */ memcpy(&(a->nh), &(he->src->nh), nexthop_size(&(he->src->nh))); return; @@ -2533,6 +2530,9 @@ no_nexthop: struct nexthop *nhp = NULL, *nhr = NULL; int skip_nexthop = 0; + const struct adata *mls = mls_ea ? mls_ea->u.ptr : NULL; + uint mls_cnt = mls ? mls->length / sizeof(u32) : 0; + for (struct nexthop *nh = &(he->src->nh); nh; nh = nh->next) { if (skip_nexthop) @@ -2549,17 +2549,16 @@ no_nexthop: if (mls) { - nhp->labels = nh->labels + mls->len; - nhp->labels_orig = mls->len; + nhp->labels = nh->labels + mls_cnt; if (nhp->labels <= MPLS_MAX_LABEL_STACK) { memcpy(nhp->label, nh->label, nh->labels * sizeof(u32)); /* First the hostentry labels */ - memcpy(&(nhp->label[nh->labels]), mls->stack, mls->len * sizeof(u32)); /* Then the bottom labels */ + memcpy(&(nhp->label[nh->labels]), mls->data, mls->length); /* Then the bottom labels */ } else { log(L_WARN "Sum of label stack sizes %d + %d = %d exceedes allowed maximum (%d)", - nh->labels, mls->len, nhp->labels, MPLS_MAX_LABEL_STACK); + nh->labels, mls_cnt, nhp->labels, MPLS_MAX_LABEL_STACK); skip_nexthop++; continue; } @@ -2567,7 +2566,6 @@ no_nexthop: else if (nh->labels) { nhp->labels = nh->labels; - nhp->labels_orig = 0; memcpy(nhp->label, nh->label, nh->labels * sizeof(u32)); } @@ -2620,10 +2618,7 @@ rt_next_hop_update_rte(rtable *tab, net *n, rte *old) rta *a = alloca(RTA_MAX_SIZE); memcpy(a, old->attrs, rta_size(old->attrs)); - mpls_label_stack mls = { .len = a->nh.labels_orig }; - memcpy(mls.stack, &a->nh.label[a->nh.labels - mls.len], mls.len * sizeof(u32)); - - rta_apply_hostentry(a, old->attrs->hostentry, &mls); + rta_apply_hostentry(a, old->attrs->hostentry); a->cached = 0; rte e0 = *old; @@ -439,12 +439,12 @@ struct rt_show_data_rtable * rt_show_add_table(struct rt_show_data *d, rtable *t #define RSEM_EXPORTED 4 /* Routes marked in export map */ struct hostentry * rt_get_hostentry(rtable *tab, ip_addr a, ip_addr ll, rtable *dep); -void rta_apply_hostentry(rta *a, struct hostentry *he, mpls_label_stack *mls); +void rta_apply_hostentry(rta *a, struct hostentry *he); static inline void -rta_set_recursive_next_hop(rtable *dep, rta *a, rtable *tab, ip_addr gw, ip_addr ll, mpls_label_stack *mls) +rta_set_recursive_next_hop(rtable *dep, rta *a, rtable *tab, ip_addr gw, ip_addr ll) { - rta_apply_hostentry(a, rt_get_hostentry(tab, gw, ll, dep), mls); + rta_apply_hostentry(a, rt_get_hostentry(tab, gw, ll, dep)); } /* diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 44a2f80a..a692c4dc 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -980,15 +980,18 @@ bgp_apply_next_hop(struct bgp_parse_state *s, rta *a, ip_addr gw, ip_addr ll) s->hostentry = rt_get_hostentry(tab, gw, ll, c->c.table); if (!s->mpls) - rta_apply_hostentry(a, s->hostentry, NULL); + rta_apply_hostentry(a, s->hostentry); /* With MPLS, hostentry is applied later in bgp_apply_mpls_labels() */ } } static void -bgp_apply_mpls_labels(struct bgp_parse_state *s, rta *a, u32 *labels, uint lnum) +bgp_apply_mpls_labels(struct bgp_parse_state *s, rta *a) { + u32 *labels = (u32 *) s->mpls_labels->data; + u32 lnum = s->mpls_labels->length / sizeof(u32); + if (lnum > MPLS_MAX_LABEL_STACK) { REPORT("Too many MPLS labels ($u)", lnum); @@ -1001,7 +1004,7 @@ bgp_apply_mpls_labels(struct bgp_parse_state *s, rta *a, u32 *labels, uint lnum) /* Handle implicit NULL as empty MPLS stack */ if ((lnum == 1) && (labels[0] == BGP_MPLS_NULL)) - lnum = 0; + lnum = s->mpls_labels->length = 0; if (s->channel->cf->gw_mode == GW_DIRECT) { @@ -1009,13 +1012,7 @@ bgp_apply_mpls_labels(struct bgp_parse_state *s, rta *a, u32 *labels, uint lnum) memcpy(a->nh.label, labels, 4*lnum); } else /* GW_RECURSIVE */ - { - mpls_label_stack ms; - - ms.len = lnum; - memcpy(ms.stack, labels, 4*lnum); - rta_apply_hostentry(a, s->hostentry, &ms); - } + rta_apply_hostentry(a, s->hostentry); } static void @@ -1419,7 +1416,13 @@ bgp_encode_mpls_labels(struct bgp_write_state *s UNUSED, const adata *mpls, byte static void bgp_decode_mpls_labels(struct bgp_parse_state *s, byte **pos, uint *len, uint *pxlen, rta *a) { - u32 labels[BGP_MPLS_MAX], label; + struct { + struct adata ad; + u32 labels[BGP_MPLS_MAX]; + } labels_adata; + + u32 *labels = labels_adata.labels; + u32 label; uint lnum = 0; do { @@ -1441,19 +1444,19 @@ bgp_decode_mpls_labels(struct bgp_parse_state *s, byte **pos, uint *len, uint *p if (!a) return; + labels_adata.ad.length = lnum * sizeof(u32); + /* Attach MPLS attribute unless we already have one */ if (!s->mpls_labels) - { - s->mpls_labels = lp_alloc_adata(s->pool, 4*BGP_MPLS_MAX); - bgp_set_attr_ptr(&(a->eattrs), BA_MPLS_LABEL_STACK, 0, s->mpls_labels); - } - - /* Overwrite data in the attribute */ - s->mpls_labels->length = 4*lnum; - memcpy(s->mpls_labels->data, labels, 4*lnum); + ea_set_attr(&(a->eattrs), + EA_LITERAL_DIRECT_ADATA(&ea_mpls_labels, 0, + (s->mpls_labels = tmp_store_adata(labels, BGP_MPLS_MAX * sizeof(u32))))); + else + /* Overwrite data in the attribute */ + memcpy(s->mpls_labels, &labels_adata, sizeof labels_adata); /* Update next hop entry in rta */ - bgp_apply_mpls_labels(s, a, labels, lnum); + bgp_apply_mpls_labels(s, a); /* Attributes were changed, invalidate cached entry */ rta_free(s->cached_rta); diff --git a/proto/static/static.c b/proto/static/static.c index f7eddedb..dffc4882 100644 --- a/proto/static/static.c +++ b/proto/static/static.c @@ -76,8 +76,8 @@ static_announce_rte(struct static_proto *p, struct static_route *r) nh->weight = r2->weight; if (r2->mls) { - nh->labels = r2->mls->len; - memcpy(nh->label, r2->mls->stack, r2->mls->len * sizeof(u32)); + nh->labels = r2->mls->length / sizeof(u32); + memcpy(nh->label, r2->mls->data, r2->mls->length); } nexthop_insert(&nhs, nh); @@ -92,7 +92,11 @@ static_announce_rte(struct static_proto *p, struct static_route *r) if (r->dest == RTDX_RECURSIVE) { rtable *tab = ipa_is_ip4(r->via) ? p->igp_table_ip4 : p->igp_table_ip6; - rta_set_recursive_next_hop(p->p.main_channel->table, a, tab, r->via, IPA_NONE, r->mls); + if (r->mls) + ea_set_attr(&a->eattrs, + EA_LITERAL_DIRECT_ADATA(&ea_mpls_labels, 0, r->mls)); + + rta_set_recursive_next_hop(p->p.main_channel->table, a, tab, r->via, IPA_NONE); } /* Already announced */ @@ -303,31 +307,17 @@ static_same_dest(struct static_route *x, struct static_route *y) (x->weight != y->weight) || (x->use_bfd != y->use_bfd) || (!x->mls != !y->mls) || - ((x->mls) && (y->mls) && (x->mls->len != y->mls->len))) + ((x->mls) && (y->mls) && adata_same(x->mls, y->mls))) return 0; - - if (!x->mls) - continue; - - for (uint i = 0; i < x->mls->len; i++) - if (x->mls->stack[i] != y->mls->stack[i]) - return 0; } return !x && !y; case RTDX_RECURSIVE: if (!ipa_equal(x->via, y->via) || (!x->mls != !y->mls) || - ((x->mls) && (y->mls) && (x->mls->len != y->mls->len))) + ((x->mls) && (y->mls) && adata_same(x->mls, y->mls))) return 0; - if (!x->mls) - return 1; - - for (uint i = 0; i < x->mls->len; i++) - if (x->mls->stack[i] != y->mls->stack[i]) - return 0; - return 1; default: diff --git a/proto/static/static.h b/proto/static/static.h index d99f7ebd..ea7ca33b 100644 --- a/proto/static/static.h +++ b/proto/static/static.h @@ -49,7 +49,7 @@ struct static_route { byte weight; /* Multipath next hop weight */ byte use_bfd; /* Configured to use BFD */ struct bfd_request *bfd_req; /* BFD request, if BFD is used */ - mpls_label_stack *mls; /* MPLS label stack; may be NULL */ + struct adata *mls; /* MPLS label stack; may be NULL */ }; /* |