0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-11-18 09:08:42 +00:00

Merge commit '575da88f' into haugesund

Conflicts:
	nest/rt-table.c
This commit is contained in:
Maria Matejka 2022-03-09 13:37:12 +01:00
commit 01c9f3d78e
2 changed files with 52 additions and 47 deletions

View File

@ -637,7 +637,7 @@ rte_mergable(rte *pri, rte *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 %uL %uG %s", log(L_TRACE "%s.%s %c %s %N %uL %uG %s",
c->proto->name, c->name ?: "?", dir, msg, e->net, e->src->private_id, e->src->global_id, c->proto->name, c->name ?: "?", dir, msg, e->net, e->src->private_id, e->src->global_id,
@ -645,14 +645,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);
@ -2516,50 +2516,53 @@ rt_flowspec_update_rte(rtable *tab, net *n, rte *r)
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 **k, *e, *new, *old_best, **new_best; struct rte_storage *new;
int count = 0; int count = 0;
int free_old_best = 0; int is_flow = net_is_flow(n->n.addr);
old_best = n->routes; struct rte_storage *old_best = n->routes;
if (!old_best) if (!old_best)
return 0; return 0;
for (k = &n->routes; e = *k; k = &e->next) for (struct rte_storage *e, **k = &n->routes; e = *k; k = &e->next)
{ if (is_flow || rta_next_hop_outdated(e->rte.attrs))
if (!net_is_flow(n->n.addr)) count++;
new = rt_next_hop_update_rte(tab, n, &e->rte);
else
new = rt_flowspec_update_rte(tab, n, &e->rte);
if (new)
{
new->next = e->next;
*k = new;
rte_trace_in(D_ROUTES, new->rte.sender, &new->rte, "updated");
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->rte.src->proto->rte_recalculate)
e->rte.src->proto->rte_recalculate(tab, n, &new->rte, &e->rte, NULL);
if (e != old_best)
rte_free(e, tab);
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 *e, **k = &n->routes; e = *k; k = &e->next)
if (is_flow || rta_next_hop_outdated(e->rte.attrs))
{
struct rte_storage *new = is_flow
? rt_flowspec_update_rte(tab, n, &e->rte)
: rt_next_hop_update_rte(tab, n, &e->rte);
/* Call a pre-comparison hook */
/* Not really an efficient way to compute this */
if (e->rte.src->proto->rte_recalculate)
e->rte.src->proto->rte_recalculate(tab, n, &new->rte, &e->rte, &old_best->rte);
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 (k = &n->routes; e = *k; k = &e->next) for (struct rte_storage *e, **k = &n->routes; e = *k; k = &e->next)
{ {
if (!new_best || rte_better(&e->rte, &(*new_best)->rte)) if (!new_best || rte_better(&e->rte, &(*new_best)->rte))
new_best = k; new_best = k;
@ -2574,15 +2577,17 @@ 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_trace_in(D_ROUTES, new->rte.sender, &new->rte, "updated [best]"); {
_Bool nb = (new == updates[i].new), ob = (old_best == updates[i].old);
const char *best_indicator[2][2] = { { "updated", "updated [-best]" }, { "updated [+best]", "updated [best]" } };
rte_trace_in(D_ROUTES, new->rte.sender, &updates[i].new->rte, best_indicator[nb][ob]);
rte_announce_i(tab, RA_UNDEF, n, updates[i].new, updates[i].old, new, 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, tab);
if (free_old_best)
rte_free(old_best, tab);
return count; return count;
} }

View File

@ -113,13 +113,13 @@ mrt_buffer_flush(buffer *b)
} }
#define MRT_DEFINE_TYPE(S, T) \ #define MRT_DEFINE_TYPE(S, T) \
static inline void mrt_put_##S##_(buffer *b, T x) \ UNUSED static inline void mrt_put_##S##_(buffer *b, T x) \
{ \ { \
put_##S(b->pos, x); \ put_##S(b->pos, x); \
b->pos += sizeof(T); \ b->pos += sizeof(T); \
} \ } \
\ \
static inline void mrt_put_##S(buffer *b, T x) \ UNUSED static inline void mrt_put_##S(buffer *b, T x) \
{ \ { \
mrt_buffer_need(b, sizeof(T)); \ mrt_buffer_need(b, sizeof(T)); \
put_##S(b->pos, x); \ put_##S(b->pos, x); \