mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2025-01-05 08:31:53 +00:00
Nest: Change nexthop merging order to prefer earlier nexthops
When nexthop merge limit was applied, the old code used first N nexthops in the canonical ordering. Now the code prefers nexthops based on the order or routes in the network.
This commit is contained in:
parent
00cf501a0a
commit
5ae13e157f
@ -638,6 +638,7 @@ int nexthop__same(struct nexthop *x, struct nexthop *y); /* Compare multipath ne
|
|||||||
static inline int nexthop_same(struct nexthop *x, struct nexthop *y)
|
static inline int nexthop_same(struct nexthop *x, struct nexthop *y)
|
||||||
{ return (x == y) || nexthop__same(x, y); }
|
{ return (x == y) || nexthop__same(x, y); }
|
||||||
struct nexthop *nexthop_merge(struct nexthop *x, struct nexthop *y, int rx, int ry, int max, linpool *lp);
|
struct nexthop *nexthop_merge(struct nexthop *x, struct nexthop *y, int rx, int ry, int max, linpool *lp);
|
||||||
|
struct nexthop *nexthop_merge2(struct nexthop *x, struct nexthop *y, int ry, int *max, linpool *lp);
|
||||||
static inline void nexthop_link(struct rta *a, struct nexthop *from)
|
static inline void nexthop_link(struct rta *a, struct nexthop *from)
|
||||||
{ memcpy(&a->nh, from, nexthop_size(from)); }
|
{ memcpy(&a->nh, from, nexthop_size(from)); }
|
||||||
void nexthop_insert(struct nexthop **n, struct nexthop *y);
|
void nexthop_insert(struct nexthop **n, struct nexthop *y);
|
||||||
|
@ -285,6 +285,57 @@ nexthop_merge(struct nexthop *x, struct nexthop *y, int rx, int ry, int max, lin
|
|||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nexthop_merge2 - merge nexthop lists
|
||||||
|
* @x: list 1
|
||||||
|
* @y: list 2
|
||||||
|
* @ry: reusability of list @y
|
||||||
|
* @max: max number of added nexthops
|
||||||
|
* @lp: linpool for allocating nexthops
|
||||||
|
*
|
||||||
|
* The nexthop_merge2() function takes two nexthop lists @x and @y and merges
|
||||||
|
* them, eliminating possible duplicates. It is a variant of nexthop_merge()
|
||||||
|
* function differing in how @max limit is handled, here it limits just number
|
||||||
|
* of nexthops added from the second list @y. The @max value is decreased with
|
||||||
|
* each such nexthop, this return remaining 'unused' limit, which can be used in
|
||||||
|
* subsequent calls. The list @x is expected to be an accumulator and its
|
||||||
|
* reusability is implied. New nodes are allocated from linpool @lp.
|
||||||
|
*/
|
||||||
|
struct nexthop *
|
||||||
|
nexthop_merge2(struct nexthop *x, struct nexthop *y, int ry, int *max, linpool *lp)
|
||||||
|
{
|
||||||
|
struct nexthop *root = NULL;
|
||||||
|
struct nexthop **n = &root;
|
||||||
|
|
||||||
|
if (*max <= 0)
|
||||||
|
return x;
|
||||||
|
|
||||||
|
while (x || y)
|
||||||
|
{
|
||||||
|
int cmp = nexthop_compare_node(x, y);
|
||||||
|
if (cmp < 0)
|
||||||
|
{
|
||||||
|
*n = x;
|
||||||
|
x = x->next;
|
||||||
|
}
|
||||||
|
else if (cmp > 0)
|
||||||
|
{
|
||||||
|
*n = ry ? y : nexthop_copy_node(y, lp);
|
||||||
|
y = (--*max) ? y->next : NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*n = x;
|
||||||
|
x = x->next;
|
||||||
|
y = y->next;
|
||||||
|
}
|
||||||
|
n = &((*n)->next);
|
||||||
|
}
|
||||||
|
*n = NULL;
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nexthop_insert(struct nexthop **n, struct nexthop *x)
|
nexthop_insert(struct nexthop **n, struct nexthop *x)
|
||||||
{
|
{
|
||||||
|
@ -849,18 +849,13 @@ rt_notify_accepted(struct channel *c, net *net, rte *new_changed, rte *old_chang
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct nexthop *
|
|
||||||
nexthop_merge_rta(struct nexthop *nhs, rta *a, linpool *pool, int max)
|
|
||||||
{
|
|
||||||
return nexthop_merge(nhs, &(a->nh), 1, 0, max, pool);
|
|
||||||
}
|
|
||||||
|
|
||||||
rte *
|
rte *
|
||||||
rt_export_merged(struct channel *c, net *net, rte **rt_free, ea_list **tmpa, linpool *pool, int silent)
|
rt_export_merged(struct channel *c, net *net, rte **rt_free, ea_list **tmpa, linpool *pool, int silent)
|
||||||
{
|
{
|
||||||
// struct proto *p = c->proto;
|
// struct proto *p = c->proto;
|
||||||
struct nexthop *nhs = NULL;
|
struct nexthop *nhs = NULL;
|
||||||
rte *best0, *best, *rt0, *rt, *tmp;
|
rte *best0, *best, *rt0, *rt, *tmp;
|
||||||
|
int max = c->merge_limit;
|
||||||
|
|
||||||
best0 = net->routes;
|
best0 = net->routes;
|
||||||
*rt_free = NULL;
|
*rt_free = NULL;
|
||||||
@ -870,10 +865,12 @@ rt_export_merged(struct channel *c, net *net, rte **rt_free, ea_list **tmpa, lin
|
|||||||
|
|
||||||
best = export_filter_(c, best0, rt_free, tmpa, pool, silent);
|
best = export_filter_(c, best0, rt_free, tmpa, pool, silent);
|
||||||
|
|
||||||
if (!best || !rte_is_reachable(best))
|
if (!best || !rte_is_reachable(best) || !best0->next)
|
||||||
return best;
|
return best;
|
||||||
|
|
||||||
for (rt0 = best0->next; rt0; rt0 = rt0->next)
|
nhs = nexthop_merge2(NULL, &(best->attrs->nh), 0, &max, pool);
|
||||||
|
|
||||||
|
for (rt0 = best0->next; rt0 && max; rt0 = rt0->next)
|
||||||
{
|
{
|
||||||
if (!rte_mergable(best0, rt0))
|
if (!rte_mergable(best0, rt0))
|
||||||
continue;
|
continue;
|
||||||
@ -884,22 +881,14 @@ rt_export_merged(struct channel *c, net *net, rte **rt_free, ea_list **tmpa, lin
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (rte_is_reachable(rt))
|
if (rte_is_reachable(rt))
|
||||||
nhs = nexthop_merge_rta(nhs, rt->attrs, pool, c->merge_limit);
|
nhs = nexthop_merge2(nhs, &(rt->attrs->nh), 0, &max, pool);
|
||||||
|
|
||||||
if (tmp)
|
if (tmp)
|
||||||
rte_free(tmp);
|
rte_free(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nhs)
|
best = rte_cow_rta(best, pool);
|
||||||
{
|
nexthop_link(best->attrs, nhs);
|
||||||
nhs = nexthop_merge_rta(nhs, best->attrs, pool, c->merge_limit);
|
|
||||||
|
|
||||||
if (nhs->next)
|
|
||||||
{
|
|
||||||
best = rte_cow_rta(best, pool);
|
|
||||||
nexthop_link(best->attrs, nhs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (best != best0)
|
if (best != best0)
|
||||||
*rt_free = best;
|
*rt_free = best;
|
||||||
|
Loading…
Reference in New Issue
Block a user