mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-17 16:48:43 +00:00
Fixes another bug in rte_recalculate().
Previous bugfix revealed another hidden bug here.
This commit is contained in:
parent
ac07aacd2c
commit
c0973621bc
@ -427,23 +427,44 @@ rte_recalculate(rtable *table, net *net, struct proto *p, struct proto *src, rte
|
|||||||
|
|
||||||
rte_announce(table, RA_ANY, net, new, old, tmpa);
|
rte_announce(table, RA_ANY, net, new, old, tmpa);
|
||||||
|
|
||||||
if (new && rte_better(new, old_best)) /* It's a new optimal route => announce and relink it */
|
|
||||||
|
if (new && rte_better(new, old_best))
|
||||||
{
|
{
|
||||||
|
/* The first case - the new route is cleary optimal, we link it
|
||||||
|
at the first position and announce it */
|
||||||
|
|
||||||
rte_trace_in(D_ROUTES, p, new, "added [best]");
|
rte_trace_in(D_ROUTES, p, new, "added [best]");
|
||||||
rte_announce(table, RA_OPTIMAL, net, new, old_best, tmpa);
|
rte_announce(table, RA_OPTIMAL, net, new, old_best, tmpa);
|
||||||
new->next = net->routes;
|
new->next = net->routes;
|
||||||
net->routes = new;
|
net->routes = new;
|
||||||
}
|
}
|
||||||
else
|
else if (old == old_best)
|
||||||
{
|
{
|
||||||
if (old == old_best) /* It has _replaced_ the old optimal route */
|
/* The second case - the old best route disappeared, we add the
|
||||||
|
new route (if we have any) to the list (we don't care about
|
||||||
|
position) and then we elect the new optimal route and relink
|
||||||
|
that route at the first position and announce it. New optimal
|
||||||
|
route might be NULL if there is no more routes */
|
||||||
|
|
||||||
|
/* Add the new route to the list */
|
||||||
|
if (new)
|
||||||
{
|
{
|
||||||
r = new; /* Find new optimal route and announce it */
|
rte_trace_in(D_ROUTES, p, new, "added");
|
||||||
for(s=net->routes; s; s=s->next)
|
new->next = net->routes;
|
||||||
|
net->routes = new;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find new optimal route */
|
||||||
|
r = NULL;
|
||||||
|
for (s=net->routes; s; s=s->next)
|
||||||
if (rte_better(s, r))
|
if (rte_better(s, r))
|
||||||
r = s;
|
r = s;
|
||||||
|
|
||||||
|
/* Announce optimal route */
|
||||||
rte_announce(table, RA_OPTIMAL, net, r, old_best, tmpa);
|
rte_announce(table, RA_OPTIMAL, net, r, old_best, tmpa);
|
||||||
if (r) /* Re-link the new optimal route */
|
|
||||||
|
/* And relink it (if there is any) */
|
||||||
|
if (r)
|
||||||
{
|
{
|
||||||
k = &net->routes;
|
k = &net->routes;
|
||||||
while (s = *k)
|
while (s = *k)
|
||||||
@ -462,14 +483,23 @@ rte_recalculate(rtable *table, net *net, struct proto *p, struct proto *src, rte
|
|||||||
table->gc_time + table->config->gc_min_time <= now)
|
table->gc_time + table->config->gc_min_time <= now)
|
||||||
ev_schedule(table->gc_event);
|
ev_schedule(table->gc_event);
|
||||||
}
|
}
|
||||||
if (new) /* Link in the new non-optimal route */
|
else if (new)
|
||||||
{
|
{
|
||||||
|
/* The third case - the new route is not better than the old
|
||||||
|
best route (therefore old_best != NULL) and the old best
|
||||||
|
route was not removed (therefore old_best == net->routes).
|
||||||
|
We just link the new route after the old best route. */
|
||||||
|
|
||||||
|
ASSERT(net->routes != NULL);
|
||||||
new->next = net->routes->next;
|
new->next = net->routes->next;
|
||||||
net->routes->next = new;
|
net->routes->next = new;
|
||||||
rte_trace_in(D_ROUTES, p, new, "added");
|
rte_trace_in(D_ROUTES, p, new, "added");
|
||||||
}
|
}
|
||||||
else if (old && (p->debug & D_ROUTES))
|
else if (old && (p->debug & D_ROUTES))
|
||||||
{
|
{
|
||||||
|
/* Not really a case - the list of routes is correct, we just
|
||||||
|
log the route removal */
|
||||||
|
|
||||||
if (old != old_best)
|
if (old != old_best)
|
||||||
rte_trace_in(D_ROUTES, p, old, "removed");
|
rte_trace_in(D_ROUTES, p, old, "removed");
|
||||||
else if (net->routes)
|
else if (net->routes)
|
||||||
@ -477,7 +507,7 @@ rte_recalculate(rtable *table, net *net, struct proto *p, struct proto *src, rte
|
|||||||
else
|
else
|
||||||
rte_trace_in(D_ROUTES, p, old, "removed [sole]");
|
rte_trace_in(D_ROUTES, p, old, "removed [sole]");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (old)
|
if (old)
|
||||||
{
|
{
|
||||||
if (p->rte_remove)
|
if (p->rte_remove)
|
||||||
|
Loading…
Reference in New Issue
Block a user