mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-09 20:58:44 +00:00
Recursive route nexthop updates now announced with valid new_best/old_best information
This commit is contained in:
parent
f23f014ef3
commit
ef95b3c7c8
@ -412,7 +412,7 @@ rte_mergable(struct rte_storage *pri, struct rte_storage *sec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rte_trace(struct channel *c, rte *e, int dir, char *msg)
|
rte_trace(struct channel *c, rte *e, int dir, const char *msg)
|
||||||
{
|
{
|
||||||
log(L_TRACE "%s.%s %c %s %N %s",
|
log(L_TRACE "%s.%s %c %s %N %s",
|
||||||
c->proto->name, c->name ?: "?", dir, msg, e->net,
|
c->proto->name, c->name ?: "?", dir, msg, e->net,
|
||||||
@ -420,14 +420,14 @@ rte_trace(struct channel *c, rte *e, int dir, char *msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
rte_trace_in(uint flag, struct channel *c, rte *e, char *msg)
|
rte_trace_in(uint flag, struct channel *c, rte *e, const char *msg)
|
||||||
{
|
{
|
||||||
if ((c->debug & flag) || (c->proto->debug & flag))
|
if ((c->debug & flag) || (c->proto->debug & flag))
|
||||||
rte_trace(c, e, '>', msg);
|
rte_trace(c, e, '>', msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
rte_trace_out(uint flag, struct channel *c, rte *e, char *msg)
|
rte_trace_out(uint flag, struct channel *c, rte *e, const char *msg)
|
||||||
{
|
{
|
||||||
if ((c->debug & flag) || (c->proto->debug & flag))
|
if ((c->debug & flag) || (c->proto->debug & flag))
|
||||||
rte_trace(c, e, '<', msg);
|
rte_trace(c, e, '<', msg);
|
||||||
@ -1954,9 +1954,8 @@ rt_next_hop_update_rte(struct rte_storage *old)
|
|||||||
static inline int
|
static inline int
|
||||||
rt_next_hop_update_net(rtable *tab, net *n)
|
rt_next_hop_update_net(rtable *tab, net *n)
|
||||||
{
|
{
|
||||||
struct rte_storage *new, **new_best;
|
struct rte_storage *new;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int free_old_best = 0;
|
|
||||||
|
|
||||||
struct rte_storage *old_best = n->routes;
|
struct rte_storage *old_best = n->routes;
|
||||||
if (!old_best)
|
if (!old_best)
|
||||||
@ -1964,32 +1963,40 @@ rt_next_hop_update_net(rtable *tab, net *n)
|
|||||||
|
|
||||||
for (struct rte_storage **k = &n->routes, *e; e = *k; k = &e->next)
|
for (struct rte_storage **k = &n->routes, *e; e = *k; k = &e->next)
|
||||||
if (rta_next_hop_outdated(e->attrs))
|
if (rta_next_hop_outdated(e->attrs))
|
||||||
{
|
count++;
|
||||||
new = rt_next_hop_update_rte(e);
|
|
||||||
new->next = e->next;
|
|
||||||
*k = new;
|
|
||||||
|
|
||||||
rte_announce_i(tab, RA_ANY, n, new, e, NULL, NULL);
|
|
||||||
|
|
||||||
/* Call a pre-comparison hook */
|
|
||||||
/* Not really an efficient way to compute this */
|
|
||||||
if (e->src->proto->rte_recalculate)
|
|
||||||
e->src->proto->rte_recalculate(tab, n, new, e, NULL);
|
|
||||||
|
|
||||||
if (e != old_best)
|
|
||||||
rte_free(e);
|
|
||||||
else /* Freeing of the old best rte is postponed */
|
|
||||||
free_old_best = 1;
|
|
||||||
|
|
||||||
e = new;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!count)
|
if (!count)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
struct rte_multiupdate {
|
||||||
|
struct rte_storage *old, *new;
|
||||||
|
} *updates = alloca(sizeof(struct rte_multiupdate) * count);
|
||||||
|
|
||||||
|
int pos = 0;
|
||||||
|
for (struct rte_storage **k = &n->routes, *e; e = *k; k = &e->next)
|
||||||
|
if (rta_next_hop_outdated(e->attrs))
|
||||||
|
{
|
||||||
|
struct rte_storage *new = rt_next_hop_update_rte(e);
|
||||||
|
|
||||||
|
/* Call a pre-comparison hook */
|
||||||
|
/* Not really an efficient way to compute this */
|
||||||
|
if (e->src->proto->rte_recalculate)
|
||||||
|
e->src->proto->rte_recalculate(tab, n, new, e, old_best);
|
||||||
|
|
||||||
|
updates[pos++] = (struct rte_multiupdate) {
|
||||||
|
.old = e,
|
||||||
|
.new = new,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Replace the route in the list */
|
||||||
|
new->next = e->next;
|
||||||
|
*k = e = new;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_DIE(pos == count);
|
||||||
|
|
||||||
/* Find the new best route */
|
/* Find the new best route */
|
||||||
new_best = NULL;
|
struct rte_storage **new_best = NULL;
|
||||||
for (struct rte_storage **k = &n->routes, *e; e = *k; k = &e->next)
|
for (struct rte_storage **k = &n->routes, *e; e = *k; k = &e->next)
|
||||||
{
|
{
|
||||||
if (!new_best || rte_better(e, *new_best))
|
if (!new_best || rte_better(e, *new_best))
|
||||||
@ -2005,18 +2012,18 @@ rt_next_hop_update_net(rtable *tab, net *n)
|
|||||||
n->routes = new;
|
n->routes = new;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Announce the new best route */
|
/* Announce the changes */
|
||||||
if (new != old_best)
|
for (int i=0; i<count; i++)
|
||||||
{
|
{
|
||||||
rte nloc = rte_copy(new);
|
_Bool nb = (*new_best == updates[i].new), ob = (old_best == updates[i].old);
|
||||||
rte_trace_in(D_ROUTES, new->sender, &nloc, "updated [best]");
|
const char *best_indicator[2][2] = { { "updated", "updated [-best]" }, { "updated [+best]", "updated [best]" } };
|
||||||
|
rte nloc = rte_copy(updates[i].new);
|
||||||
|
rte_trace_in(D_ROUTES, new->sender, &nloc, best_indicator[nb][ob]);
|
||||||
|
rte_announce_i(tab, RA_UNDEF, n, updates[i].new, updates[i].old, *new_best, old_best);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Propagate changes */
|
for (int i=0; i<count; i++)
|
||||||
rte_announce_i(tab, RA_UNDEF, n, NULL, NULL, n->routes, old_best);
|
rte_free(updates[i].old);
|
||||||
|
|
||||||
if (free_old_best)
|
|
||||||
rte_free(old_best);
|
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user