And just an idea. I've attached the patch as an example, although it should be functional too. I mentioned that functions krt_learn_async() and krt_learn_scan() are very similar and I thought that it may be useful to join them into a single function. If I did not make a mistake, all code pathes should be almost the same, with a couple of minor exceptions: 1) old_best is set in the beginning, but was earlier only for async version 2) g = NULL after rte_free(g) in one of the branches, but it does not affect anything and may be dropped
On Wed, Sep 21, 2022 at 6:00 PM Maria Matejka via Bird-users <bird-users@network.cz> wrote: > > Hello! > > Thank you for finding and fixing. Will check and include. > > Maria > > On 9/21/22 17:15, Alexander Zubkov via Bird-users wrote: > > I made a trivial patch for the case. > > > > On Tue, Sep 20, 2022 at 6:23 PM Alexander Zubkov <gr...@qrator.net> wrote: > >> > >> Hi, > >> > >> Bird from master branch ignores the default preference set in channel > >> for a kernel protocol, like that: > >> > >> protocol kernel { > >> learn yes; > >> ipv4 { > >> preference 200; > >> import all; > >> export none; > >> }; > >> } > >> > >> Version 2.0.10 seems ok. I suppose the change was introduced with this > >> commit: > >> > >> https://gitlab.nic.cz/labs/bird/-/commit/eb937358c087eaeb6f209660cc7ecfe6d6eff739 > >> > >> It adds setting of the preference to the krt_learn_async() function. > >> But as I understand when route is learned with netlink hook it is > >> processed like this: > >> nl_parse_route -> krt_got_route_async -> krt_learn_async > >> But when it is learned from scan, it is processed like this: > >> nl_parse_route -> krt_got_route -> krt_learn_scan > >> > >> And setting preference was not added to krt_learn_scan() function. > >> > >> I also saw that in my test - when I added a new route to the kernel > >> while bird was running, it appeared in bird with correct preference. > >> But some time after, the scan updated the route and it was replaced > >> with the default preference.
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index c4a3a4a8..e61efdfe 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -318,45 +318,6 @@ krt_learn_announce_delete(struct krt_proto *p, net *n) rte_update(&p->p, n->n.addr, NULL); } -/* Called when alien route is discovered during scan */ -static void -krt_learn_scan(struct krt_proto *p, rte *e) -{ - net *n0 = e->net; - net *n = net_get(p->krt_table, n0->n.addr); - rte *m, **mm; - - e->attrs = rta_lookup(e->attrs); - - for(mm=&n->routes; m = *mm; mm=&m->next) - if (krt_same_key(m, e)) - break; - if (m) - { - if (krt_uptodate(m, e)) - { - krt_trace_in_rl(&rl_alien, p, e, "[alien] seen"); - rte_free(e); - m->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"); - if (!m) - { - e->next = n->routes; - n->routes = e; - e->pflags |= KRT_REF_SEEN; - } -} - static void krt_learn_prune(struct krt_proto *p) { @@ -373,7 +334,7 @@ again: /* * 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(). + * the previous step, because it might be replaced in krt_learn_route(). * But in that case there is a new valid best route. */ @@ -431,13 +392,17 @@ again: p->reload = 0; } +/* sync = 0 : Called when alien route is discovered during scan */ static void -krt_learn_async(struct krt_proto *p, rte *e, int new) +krt_learn_route(struct krt_proto *p, rte *e, int async, int new) { net *n0 = e->net; net *n = net_get(p->krt_table, n0->n.addr); rte *g, **gg, *best, **bestp, *old_best; + if (async) + new = 1; + ASSERT(!e->attrs->cached); e->attrs->pref = p->p.main_channel->preference; @@ -453,19 +418,35 @@ krt_learn_async(struct krt_proto *p, rte *e, int new) { if (krt_uptodate(g, e)) { - krt_trace_in(p, e, "[alien async] same"); + if (async) + krt_trace_in(p, e, "[alien async] same"); + else + krt_trace_in_rl(&rl_alien, p, e, "[alien] seen"); rte_free(e); + if (!async) + g->pflags |= KRT_REF_SEEN; return; } - krt_trace_in(p, e, "[alien async] updated"); + if (async) + krt_trace_in(p, e, "[alien async] updated"); + else + krt_trace_in(p, e, "[alien] updated"); *gg = g->next; rte_free(g); + g = NULL; } else - krt_trace_in(p, e, "[alien async] created"); + { + if (async) + krt_trace_in(p, e, "[alien async] created"); + else + krt_trace_in(p, e, "[alien] created"); + } e->next = n->routes; n->routes = e; + if (!async) + e->pflags |= KRT_REF_SEEN; } else if (!g) { @@ -480,6 +461,10 @@ krt_learn_async(struct krt_proto *p, rte *e, int new) rte_free(e); rte_free(g); } + + if (!async) + return; + best = n->routes; bestp = &n->routes; for(gg=&n->routes; g=*gg; gg=&g->next) @@ -503,7 +488,7 @@ krt_learn_async(struct krt_proto *p, rte *e, int new) if (best != old_best) { - DBG("krt_learn_async: distributing change\n"); + DBG("krt_learn_route: distributing change\n"); if (best) krt_learn_announce_update(p, best); else @@ -641,7 +626,7 @@ krt_got_route(struct krt_proto *p, rte *e, s8 src) case KRT_SRC_ALIEN: if (KRT_CF->learn) - krt_learn_scan(p, e); + krt_learn_route(p, e, 0, 1); else { krt_trace_in_rl(&rl_alien, p, e, "[alien] ignored"); @@ -777,7 +762,7 @@ krt_got_route_async(struct krt_proto *p, rte *e, int new, s8 src) case KRT_SRC_ALIEN: if (KRT_CF->learn) { - krt_learn_async(p, e, new); + krt_learn_route(p, e, 1, new); return; } #endif