1
0
mirror of https://gitlab.labs.nic.cz/labs/bird.git synced 2024-05-11 16:54:54 +00:00

Merge commit '9efaf6ba' into tmp-bad-learn

Also fixed forgotten best route selection among alien routes.
This commit is contained in:
Maria Matejka
2022-09-29 09:58:27 +02:00
32 changed files with 1214 additions and 1070 deletions

View File

@@ -302,241 +302,29 @@ krt_uptodate(rte *a, rte *b)
return (a->attrs == b->attrs);
}
static void
krt_learn_announce_update(struct krt_proto *p, rte *e)
{
rte e0 = {
.attrs = ea_clone(e->attrs),
.src = p->p.main_source,
};
rte_update(p->p.main_channel, e->net, &e0, p->p.main_source);
}
static void
krt_learn_announce_delete(struct krt_proto *p, net_addr *n)
{
rte_update(p->p.main_channel, n, NULL, p->p.main_source);
}
static struct rte_storage *
krt_store_async(struct krt_proto *p, net *n, rte *e)
{
ea_set_attr_u32(&e->attrs, &ea_gen_preference, 0, p->p.main_channel->preference);
e->src = p->p.main_source;
return rte_store(e, n, p->krt_table);
}
/* Called when alien route is discovered during scan */
static void
krt_learn_scan(struct krt_proto *p, rte *e)
{
net *n = net_get(p->krt_table, e->net);
struct rte_storage *m, **mm;
struct rte_storage *ee = krt_store_async(p, n, e);
rte e0 = {
.attrs = e->attrs,
.src = rt_get_source(&p->p, krt_metric(e)),
};
for(mm = &n->routes; m = *mm; mm = &m->next)
if (krt_same_key(&m->rte, e))
break;
if (m)
{
if (krt_uptodate(&m->rte, e))
{
krt_trace_in_rl(&rl_alien, p, e, "[alien] seen");
rte_free(ee);
m->rte.pflags |= KRT_REF_SEEN;
}
else
{
krt_trace_in(p, e, "[alien] updated");
*mm = m->next;
rte_free(m);
m = NULL;
}
}
else
krt_trace_in(p, e, "[alien] created");
ea_set_attr_u32(&e0.attrs, &ea_gen_preference, 0, p->p.main_channel->preference);
if (!m)
{
ee->next = n->routes;
n->routes = ee;
ee->rte.pflags |= KRT_REF_SEEN;
}
}
static void
krt_learn_prune(struct krt_proto *p)
{
struct fib *fib = &p->krt_table->fib;
struct fib_iterator fit;
KRT_TRACE(p, D_EVENTS, "Pruning inherited routes");
FIB_ITERATE_INIT(&fit, fib);
again:
FIB_ITERATE_START(fib, &fit, net, n)
{
struct rte_storage *e, **ee, *best, **pbest, *old_best;
/*
* Note that old_best may be NULL even if there was an old best route in
* the previous step, because it might be replaced in krt_learn_scan().
* But in that case there is a new valid best route.
*/
old_best = NULL;
best = NULL;
pbest = NULL;
ee = &n->routes;
while (e = *ee)
{
if (e->rte.pflags & KRT_REF_BEST)
old_best = e;
if (!(e->rte.pflags & KRT_REF_SEEN))
{
*ee = e->next;
rte_free(e);
continue;
}
if (!best || krt_metric(&best->rte) > krt_metric(&e->rte))
{
best = e;
pbest = ee;
}
e->rte.pflags &= ~(KRT_REF_SEEN | KRT_REF_BEST);
ee = &e->next;
}
if (!n->routes)
{
DBG("%I/%d: deleting\n", n->n.prefix, n->n.pxlen);
if (old_best)
krt_learn_announce_delete(p, n->n.addr);
FIB_ITERATE_PUT(&fit);
fib_delete(fib, n);
goto again;
}
best->rte.pflags |= KRT_REF_BEST;
*pbest = best->next;
best->next = n->routes;
n->routes = best;
if ((best != old_best) || p->reload)
{
DBG("%I/%d: announcing (metric=%d)\n", n->n.prefix, n->n.pxlen, krt_metric(&best->rte));
krt_learn_announce_update(p, &best->rte);
}
else
DBG("%I/%d: uptodate (metric=%d)\n", n->n.prefix, n->n.pxlen, krt_metric(&best->rte));
}
FIB_ITERATE_END;
p->reload = 0;
rte_update(p->p.main_channel, e->net, &e0, e0.src);
}
static void
krt_learn_async(struct krt_proto *p, rte *e, int new)
{
net *n = net_get(p->krt_table, e->net);
struct rte_storage *g, **gg, *best, **bestp, *old_best;
struct rte_storage *ee = krt_store_async(p, n, e);
old_best = n->routes;
for(gg=&n->routes; g = *gg; gg = &g->next)
if (krt_same_key(&g->rte, e))
break;
if (new)
{
if (g)
{
if (krt_uptodate(&g->rte, e))
{
krt_trace_in(p, e, "[alien async] same");
rte_free(ee);
return;
}
krt_trace_in(p, e, "[alien async] updated");
*gg = g->next;
rte_free(g);
}
else
krt_trace_in(p, e, "[alien async] created");
return krt_learn_scan(p, e);
ee->next = n->routes;
n->routes = ee;
}
else if (!g)
{
krt_trace_in(p, e, "[alien async] delete failed");
rte_free(ee);
return;
}
else
{
krt_trace_in(p, e, "[alien async] removed");
*gg = g->next;
rte_free(ee);
rte_free(g);
}
best = n->routes;
bestp = &n->routes;
for(gg=&n->routes; g=*gg; gg=&g->next)
{
if (krt_metric(&best->rte) > krt_metric(&g->rte))
{
best = g;
bestp = gg;
}
g->rte.pflags &= ~KRT_REF_BEST;
}
if (best)
{
best->rte.pflags |= KRT_REF_BEST;
*bestp = best->next;
best->next = n->routes;
n->routes = best;
}
if (best != old_best)
{
DBG("krt_learn_async: distributing change\n");
if (best)
krt_learn_announce_update(p, &best->rte);
else
krt_learn_announce_delete(p, n->n.addr);
}
}
static void
krt_learn_init(struct krt_proto *p)
{
if (KRT_CF->learn)
{
struct rtable_config *cf = mb_allocz(p->p.pool, sizeof(struct rtable_config));
cf->name = "Inherited";
cf->addr_type = p->p.net_type;
cf->internal = 1;
p->krt_table = rt_setup(p->p.pool, cf);
}
}
static void
krt_dump(struct proto *P)
{
struct krt_proto *p = (struct krt_proto *) P;
if (!KRT_CF->learn)
return;
debug("KRT: Table of inheritable routes\n");
rt_dump(p->krt_table);
struct rte_src *src = rt_find_source(&p->p, krt_metric(e));
if (src)
rte_update(p->p.main_channel, e->net, NULL, src);
}
#endif
@@ -743,11 +531,6 @@ krt_prune(struct krt_proto *p)
}
FIB_WALK_END;
#ifdef KRT_ALLOW_LEARN
if (KRT_CF->learn)
krt_learn_prune(p);
#endif
if (p->ready)
p->initialized = 1;
}
@@ -974,6 +757,14 @@ krt_feed_end(struct channel *C)
krt_scan_timer_kick(p);
}
static int
krt_rte_better(rte *new, rte *old)
{
u32 n = ea_get_int(new->attrs, &ea_krt_metric, IGP_METRIC_UNKNOWN);
u32 o = ea_get_int(old->attrs, &ea_krt_metric, IGP_METRIC_UNKNOWN);
return (n < o);
}
/*
* Protocol glue
@@ -1033,6 +824,7 @@ krt_init(struct proto_config *CF)
p->p.if_notify = krt_if_notify;
p->p.reload_routes = krt_reload_routes;
p->p.feed_end = krt_feed_end;
p->p.rte_better = krt_rte_better;
krt_sys_init(p);
return &p->p;
@@ -1058,10 +850,6 @@ krt_start(struct proto *P)
bmap_init(&p->seen_map, p->p.pool, 1024);
add_tail(&krt_proto_list, &p->krt_node);
#ifdef KRT_ALLOW_LEARN
krt_learn_init(p);
#endif
if (!krt_sys_start(p))
{
rem_node(&p->krt_node);
@@ -1177,9 +965,6 @@ struct protocol proto_unix_kernel = {
.shutdown = krt_shutdown,
.reconfigure = krt_reconfigure,
.copy_config = krt_copy_config,
#ifdef KRT_ALLOW_LEARN
.dump = krt_dump,
#endif
};
void