mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 17:51:53 +00:00
All outstanding MPLS label stacks are stored as adata
This commit is contained in:
parent
1c30b689dd
commit
f2e725a768
@ -92,7 +92,7 @@ CF_DECLS
|
|||||||
struct proto_spec ps;
|
struct proto_spec ps;
|
||||||
struct channel_limit cl;
|
struct channel_limit cl;
|
||||||
struct timeformat *tf;
|
struct timeformat *tf;
|
||||||
mpls_label_stack *mls;
|
struct adata *ad;
|
||||||
struct bytestring *bs;
|
struct bytestring *bs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ CF_DECLS
|
|||||||
%type <a> ipa
|
%type <a> ipa
|
||||||
%type <net> net_ip4_ net_ip6_ net_ip6 net_ip_ net_ip net_or_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 <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 <t> text opttext
|
||||||
%type <s> symbol symbol_known toksym
|
%type <s> symbol symbol_known toksym
|
||||||
@ -351,17 +351,19 @@ net_or_ipa:
|
|||||||
|
|
||||||
label_stack_start: NUM
|
label_stack_start: NUM
|
||||||
{
|
{
|
||||||
$$ = cfg_allocz(sizeof(mpls_label_stack));
|
$$ = cfg_allocz(ADATA_SIZE(MPLS_MAX_LABEL_STACK * sizeof(u32)));
|
||||||
$$->len = 1;
|
$$->length = sizeof(u32);
|
||||||
$$->stack[0] = $1;
|
*((u32 *)$$->data) = $1;
|
||||||
};
|
};
|
||||||
|
|
||||||
label_stack:
|
label_stack:
|
||||||
label_stack_start
|
label_stack_start
|
||||||
| label_stack '/' NUM {
|
| 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");
|
cf_error("Too many labels in stack");
|
||||||
$1->stack[$1->len++] = $3;
|
|
||||||
|
*((u32 *)($$->data + $1->length)) = $3;
|
||||||
|
$1->length += sizeof(u32);
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
4
lib/ip.h
4
lib/ip.h
@ -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))); }
|
{ return _MI6(ntohl(_I0(a)), ntohl(_I1(a)), ntohl(_I2(a)), ntohl(_I3(a))); }
|
||||||
|
|
||||||
#define MPLS_MAX_LABEL_STACK 8
|
#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
|
static inline int
|
||||||
mpls_get(const char *buf, int buflen, u32 *stack)
|
mpls_get(const char *buf, int buflen, u32 *stack)
|
||||||
|
@ -70,7 +70,6 @@ struct nexthop {
|
|||||||
struct nexthop *next;
|
struct nexthop *next;
|
||||||
byte flags;
|
byte flags;
|
||||||
byte weight;
|
byte weight;
|
||||||
byte labels_orig; /* Number of labels before hostentry was applied */
|
|
||||||
byte labels; /* Number of all labels */
|
byte labels; /* Number of all labels */
|
||||||
u32 label[0];
|
u32 label[0];
|
||||||
};
|
};
|
||||||
@ -314,6 +313,10 @@ extern struct ea_class ea_gen_source;
|
|||||||
static inline u32 rt_get_source_attr(rte *rt)
|
static inline u32 rt_get_source_attr(rte *rt)
|
||||||
{ return ea_get_int(rt->attrs->eattrs, &ea_gen_source, 0); }
|
{ 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 */
|
/* Next hop structures */
|
||||||
|
|
||||||
#define NEXTHOP_MAX_SIZE (sizeof(struct nexthop) + sizeof(u32)*MPLS_MAX_LABEL_STACK)
|
#define NEXTHOP_MAX_SIZE (sizeof(struct nexthop) + sizeof(u32)*MPLS_MAX_LABEL_STACK)
|
||||||
|
@ -108,6 +108,12 @@ struct ea_class ea_gen_source = {
|
|||||||
.format = ea_gen_source_format,
|
.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] = {
|
const char * rta_dest_names[RTD_MAX] = {
|
||||||
[RTD_NONE] = "",
|
[RTD_NONE] = "",
|
||||||
[RTD_UNICAST] = "unicast",
|
[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) ||
|
if (!ipa_equal(x->gw, y->gw) || (x->iface != y->iface) ||
|
||||||
(x->flags != y->flags) || (x->weight != y->weight) ||
|
(x->flags != y->flags) || (x->weight != y->weight) ||
|
||||||
(x->labels_orig != y->labels_orig) || (x->labels != y->labels))
|
(x->labels != y->labels))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (int i = 0; i < x->labels; i++)
|
for (int i = 0; i < x->labels; i++)
|
||||||
@ -402,7 +408,6 @@ nexthop_copy(struct nexthop *o)
|
|||||||
n->next = NULL;
|
n->next = NULL;
|
||||||
n->flags = o->flags;
|
n->flags = o->flags;
|
||||||
n->weight = o->weight;
|
n->weight = o->weight;
|
||||||
n->labels_orig = o->labels_orig;
|
|
||||||
n->labels = o->labels;
|
n->labels = o->labels;
|
||||||
for (int i=0; i<o->labels; i++)
|
for (int i=0; i<o->labels; i++)
|
||||||
n->label[i] = o->label[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_igp_metric);
|
||||||
ea_register_init(&ea_gen_from);
|
ea_register_init(&ea_gen_from);
|
||||||
ea_register_init(&ea_gen_source);
|
ea_register_init(&ea_gen_source);
|
||||||
|
|
||||||
|
ea_register_init(&ea_mpls_labels);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2385,7 +2385,7 @@ rt_preconfig(struct config *c)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
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->hostentry = he;
|
||||||
a->dest = he->dest;
|
a->dest = he->dest;
|
||||||
@ -2397,15 +2397,12 @@ rta_apply_hostentry(rta *a, struct hostentry *he, mpls_label_stack *mls)
|
|||||||
/* No nexthop */
|
/* No nexthop */
|
||||||
no_nexthop:
|
no_nexthop:
|
||||||
a->nh = (struct 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;
|
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. */
|
{ /* Just link the nexthop chain, no label append happens. */
|
||||||
memcpy(&(a->nh), &(he->src->nh), nexthop_size(&(he->src->nh)));
|
memcpy(&(a->nh), &(he->src->nh), nexthop_size(&(he->src->nh)));
|
||||||
return;
|
return;
|
||||||
@ -2414,6 +2411,9 @@ no_nexthop:
|
|||||||
struct nexthop *nhp = NULL, *nhr = NULL;
|
struct nexthop *nhp = NULL, *nhr = NULL;
|
||||||
int skip_nexthop = 0;
|
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)
|
for (struct nexthop *nh = &(he->src->nh); nh; nh = nh->next)
|
||||||
{
|
{
|
||||||
if (skip_nexthop)
|
if (skip_nexthop)
|
||||||
@ -2430,17 +2430,16 @@ no_nexthop:
|
|||||||
|
|
||||||
if (mls)
|
if (mls)
|
||||||
{
|
{
|
||||||
nhp->labels = nh->labels + mls->len;
|
nhp->labels = nh->labels + mls_cnt;
|
||||||
nhp->labels_orig = mls->len;
|
|
||||||
if (nhp->labels <= MPLS_MAX_LABEL_STACK)
|
if (nhp->labels <= MPLS_MAX_LABEL_STACK)
|
||||||
{
|
{
|
||||||
memcpy(nhp->label, nh->label, nh->labels * sizeof(u32)); /* First the hostentry labels */
|
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
|
else
|
||||||
{
|
{
|
||||||
log(L_WARN "Sum of label stack sizes %d + %d = %d exceedes allowed maximum (%d)",
|
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++;
|
skip_nexthop++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -2448,7 +2447,6 @@ no_nexthop:
|
|||||||
else if (nh->labels)
|
else if (nh->labels)
|
||||||
{
|
{
|
||||||
nhp->labels = nh->labels;
|
nhp->labels = nh->labels;
|
||||||
nhp->labels_orig = 0;
|
|
||||||
memcpy(nhp->label, nh->label, nh->labels * sizeof(u32));
|
memcpy(nhp->label, nh->label, nh->labels * sizeof(u32));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2501,10 +2499,7 @@ rt_next_hop_update_rte(rtable *tab UNUSED, rte *old)
|
|||||||
rta *a = alloca(RTA_MAX_SIZE);
|
rta *a = alloca(RTA_MAX_SIZE);
|
||||||
memcpy(a, old->attrs, rta_size(old->attrs));
|
memcpy(a, old->attrs, rta_size(old->attrs));
|
||||||
|
|
||||||
mpls_label_stack mls = { .len = a->nh.labels_orig };
|
rta_apply_hostentry(a, old->attrs->hostentry);
|
||||||
memcpy(mls.stack, &a->nh.label[a->nh.labels - mls.len], mls.len * sizeof(u32));
|
|
||||||
|
|
||||||
rta_apply_hostentry(a, old->attrs->hostentry, &mls);
|
|
||||||
a->cached = 0;
|
a->cached = 0;
|
||||||
|
|
||||||
rte *e = sl_alloc(rte_slab);
|
rte *e = sl_alloc(rte_slab);
|
||||||
|
@ -281,12 +281,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 */
|
#define RSEM_EXPORTED 4 /* Routes marked in export map */
|
||||||
|
|
||||||
struct hostentry * rt_get_hostentry(rtable *tab, ip_addr a, ip_addr ll, rtable *dep);
|
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
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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);
|
s->hostentry = rt_get_hostentry(tab, gw, ll, c->c.table);
|
||||||
|
|
||||||
if (!s->mpls)
|
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() */
|
/* With MPLS, hostentry is applied later in bgp_apply_mpls_labels() */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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)
|
if (lnum > MPLS_MAX_LABEL_STACK)
|
||||||
{
|
{
|
||||||
REPORT("Too many MPLS labels ($u)", lnum);
|
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 */
|
/* Handle implicit NULL as empty MPLS stack */
|
||||||
if ((lnum == 1) && (labels[0] == BGP_MPLS_NULL))
|
if ((lnum == 1) && (labels[0] == BGP_MPLS_NULL))
|
||||||
lnum = 0;
|
lnum = s->mpls_labels->length = 0;
|
||||||
|
|
||||||
if (s->channel->cf->gw_mode == GW_DIRECT)
|
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);
|
memcpy(a->nh.label, labels, 4*lnum);
|
||||||
}
|
}
|
||||||
else /* GW_RECURSIVE */
|
else /* GW_RECURSIVE */
|
||||||
{
|
rta_apply_hostentry(a, s->hostentry);
|
||||||
mpls_label_stack ms;
|
|
||||||
|
|
||||||
ms.len = lnum;
|
|
||||||
memcpy(ms.stack, labels, 4*lnum);
|
|
||||||
rta_apply_hostentry(a, s->hostentry, &ms);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1418,7 +1415,13 @@ bgp_encode_mpls_labels(struct bgp_write_state *s UNUSED, const adata *mpls, byte
|
|||||||
static void
|
static void
|
||||||
bgp_decode_mpls_labels(struct bgp_parse_state *s, byte **pos, uint *len, uint *pxlen, rta *a)
|
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;
|
uint lnum = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@ -1440,19 +1443,19 @@ bgp_decode_mpls_labels(struct bgp_parse_state *s, byte **pos, uint *len, uint *p
|
|||||||
if (!a)
|
if (!a)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
labels_adata.ad.length = lnum * sizeof(u32);
|
||||||
|
|
||||||
/* Attach MPLS attribute unless we already have one */
|
/* Attach MPLS attribute unless we already have one */
|
||||||
if (!s->mpls_labels)
|
if (!s->mpls_labels)
|
||||||
{
|
ea_set_attr(&(a->eattrs),
|
||||||
s->mpls_labels = lp_alloc_adata(s->pool, 4*BGP_MPLS_MAX);
|
EA_LITERAL_DIRECT_ADATA(&ea_mpls_labels, 0,
|
||||||
bgp_set_attr_ptr(&(a->eattrs), BA_MPLS_LABEL_STACK, 0, s->mpls_labels);
|
(s->mpls_labels = tmp_store_adata(labels, BGP_MPLS_MAX * sizeof(u32)))));
|
||||||
}
|
else
|
||||||
|
|
||||||
/* Overwrite data in the attribute */
|
/* Overwrite data in the attribute */
|
||||||
s->mpls_labels->length = 4*lnum;
|
memcpy(s->mpls_labels, &labels_adata, sizeof labels_adata);
|
||||||
memcpy(s->mpls_labels->data, labels, 4*lnum);
|
|
||||||
|
|
||||||
/* Update next hop entry in rta */
|
/* 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 */
|
/* Attributes were changed, invalidate cached entry */
|
||||||
rta_free(s->cached_rta);
|
rta_free(s->cached_rta);
|
||||||
|
@ -76,8 +76,8 @@ static_announce_rte(struct static_proto *p, struct static_route *r)
|
|||||||
nh->weight = r2->weight;
|
nh->weight = r2->weight;
|
||||||
if (r2->mls)
|
if (r2->mls)
|
||||||
{
|
{
|
||||||
nh->labels = r2->mls->len;
|
nh->labels = r2->mls->length / sizeof(u32);
|
||||||
memcpy(nh->label, r2->mls->stack, r2->mls->len * sizeof(u32));
|
memcpy(nh->label, r2->mls->data, r2->mls->length);
|
||||||
}
|
}
|
||||||
|
|
||||||
nexthop_insert(&nhs, nh);
|
nexthop_insert(&nhs, nh);
|
||||||
@ -92,7 +92,11 @@ static_announce_rte(struct static_proto *p, struct static_route *r)
|
|||||||
if (r->dest == RTDX_RECURSIVE)
|
if (r->dest == RTDX_RECURSIVE)
|
||||||
{
|
{
|
||||||
rtable *tab = ipa_is_ip4(r->via) ? p->igp_table_ip4 : p->igp_table_ip6;
|
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 */
|
/* Already announced */
|
||||||
@ -314,14 +318,7 @@ static_same_dest(struct static_route *x, struct static_route *y)
|
|||||||
(x->weight != y->weight) ||
|
(x->weight != y->weight) ||
|
||||||
(x->use_bfd != y->use_bfd) ||
|
(x->use_bfd != y->use_bfd) ||
|
||||||
(!x->mls != !y->mls) ||
|
(!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 0;
|
||||||
}
|
}
|
||||||
return !x && !y;
|
return !x && !y;
|
||||||
@ -329,14 +326,7 @@ static_same_dest(struct static_route *x, struct static_route *y)
|
|||||||
case RTDX_RECURSIVE:
|
case RTDX_RECURSIVE:
|
||||||
if (!ipa_equal(x->via, y->via) ||
|
if (!ipa_equal(x->via, y->via) ||
|
||||||
(!x->mls != !y->mls) ||
|
(!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 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -49,7 +49,7 @@ struct static_route {
|
|||||||
byte weight; /* Multipath next hop weight */
|
byte weight; /* Multipath next hop weight */
|
||||||
byte use_bfd; /* Configured to use BFD */
|
byte use_bfd; /* Configured to use BFD */
|
||||||
struct bfd_request *bfd_req; /* BFD request, if BFD is used */
|
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 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user