Nest: Keep multipath next hops sorted

This commit is contained in:
Ondrej Zajicek (work) 2016-08-30 17:17:27 +02:00
parent a1839f3c61
commit 84cac51a51
5 changed files with 39 additions and 8 deletions

View file

@ -506,6 +506,8 @@ int mpnh__same(struct mpnh *x, struct mpnh *y); /* Compare multipath nexthops */
static inline int mpnh_same(struct mpnh *x, struct mpnh *y) static inline int mpnh_same(struct mpnh *x, struct mpnh *y)
{ return (x == y) || mpnh__same(x, y); } { return (x == y) || mpnh__same(x, y); }
struct mpnh *mpnh_merge(struct mpnh *x, struct mpnh *y, int rx, int ry, int max, linpool *lp); struct mpnh *mpnh_merge(struct mpnh *x, struct mpnh *y, int rx, int ry, int max, linpool *lp);
void mpnh_insert(struct mpnh **n, struct mpnh *y);
int mpnh_is_sorted(struct mpnh *x);
void rta_init(void); void rta_init(void);
rta *rta_lookup(rta *); /* Get rta equivalent to this one, uc++ */ rta *rta_lookup(rta *); /* Get rta equivalent to this one, uc++ */

View file

@ -302,6 +302,34 @@ mpnh_merge(struct mpnh *x, struct mpnh *y, int rx, int ry, int max, linpool *lp)
return root; return root;
} }
void
mpnh_insert(struct mpnh **n, struct mpnh *x)
{
for (; *n; n = &((*n)->next))
{
int cmp = mpnh_compare_node(*n, x);
if (cmp < 0)
continue;
else if (cmp > 0)
break;
else
return;
}
x->next = *n;
*n = x;
}
int
mpnh_is_sorted(struct mpnh *x)
{
for (; x && x->next; x = x->next)
if (mpnh_compare_node(x, x->next) >= 0)
return 0;
return 1;
}
static struct mpnh * static struct mpnh *
mpnh_copy(struct mpnh *o) mpnh_copy(struct mpnh *o)

View file

@ -804,6 +804,13 @@ rte_validate(rte *e)
return 0; return 0;
} }
if ((e->attrs->dest == RTD_MULTIPATH) && !mpnh_is_sorted(e->attrs->nexthops))
{
log(L_WARN "Ignoring unsorted multipath route %I/%d received via %s",
n->n.prefix, n->n.pxlen, e->sender->proto->name);
return 0;
}
return 1; return 1;
} }

View file

@ -173,7 +173,6 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
{ {
/* ECMP route */ /* ECMP route */
struct mpnh *nhs = NULL; struct mpnh *nhs = NULL;
struct mpnh **nhp = &nhs;
int num = 0; int num = 0;
for (rt = en->routes; rt && (num < p->ecmp); rt = rt->next) for (rt = en->routes; rt && (num < p->ecmp); rt = rt->next)
@ -185,9 +184,7 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
nh->gw = rt->next_hop; nh->gw = rt->next_hop;
nh->iface = rt->from->nbr->iface; nh->iface = rt->from->nbr->iface;
nh->weight = rt->from->ifa->cf->ecmp_weight; nh->weight = rt->from->ifa->cf->ecmp_weight;
nh->next = NULL; mpnh_insert(&nhs, nh);
*nhp = nh;
nhp = &(nh->next);
num++; num++;
if (rt->tag != rt_tag) if (rt->tag != rt_tag)

View file

@ -81,7 +81,6 @@ static_install(struct proto *p, struct static_route *r, struct iface *ifa)
{ {
struct static_route *r2; struct static_route *r2;
struct mpnh *nhs = NULL; struct mpnh *nhs = NULL;
struct mpnh **nhp = &nhs;
for (r2 = r->mp_next; r2; r2 = r2->mp_next) for (r2 = r->mp_next; r2; r2 = r2->mp_next)
if (r2->installed) if (r2->installed)
@ -90,9 +89,7 @@ static_install(struct proto *p, struct static_route *r, struct iface *ifa)
nh->gw = r2->via; nh->gw = r2->via;
nh->iface = r2->neigh->iface; nh->iface = r2->neigh->iface;
nh->weight = r2->masklen; /* really */ nh->weight = r2->masklen; /* really */
nh->next = NULL; mpnh_insert(&nhs, nh);
*nhp = nh;
nhp = &(nh->next);
} }
/* There is at least one nexthop */ /* There is at least one nexthop */