I made a patch for that. It works at least for my test case. I had to add additional parameter to nl_parse_multipath() function to pass information about this exception for dead routes. But may be there are better ways to do that. For example to set "s->krt_src" earlier, but I do not know if it will not break something else. Or may be it is even better to add additional field to "struct nl_parse_state" for that.
On Mon, Dec 27, 2021 at 5:35 PM Ondrej Zajicek <[email protected]> wrote: > > On Mon, Dec 27, 2021 at 02:51:34PM +0100, Alexander Zubkov wrote: > > Hi all, > > > > I'll pop up this old discussion. I've found a bug with bird handling > > its routes when ignore_routes_with_linkdown is enabled. And I suspect > > it is related to this patch. > > The problem is that bird does not replace or delete the routes it > > installed when they are marked as dead. For example if we stop it with > > "graceful restart", the routes are left in the table and after we > > start bird again with updated config, this old route remains in the > > table. I can reproduce it with bird compiled from master branch now. > > Now, that I have found this thread, I suppose, that this changes blind > > bird for all such routes during the scan. As a result bird also > > ignores its own routes (proto bird), which causes problems. I think > > there should be an exception for the routes that are installed by bird > > itself. > > Hi > > You are right, it makes sense to apply dead-flag handling only to > to non-bird routes. Will fix that. > > -- > Elen sila lumenn' omentielvo > > Ondrej 'Santiago' Zajicek (email: [email protected]) > OpenPGP encrypted e-mails preferred (KeyID 0x11DEADC3, wwwkeys.pgp.net) > "To err is human -- to blame it on a computer is even more so."
commit 73edc5b27930245b962be510e852912b3ca1ef83 Author: Alexander Zubkov <[email protected]> Date: Sat Jan 1 05:11:20 2022 +0100 Linux: do not ignore dead routes managed by bird Currently, bird ignores dead routes to consider them absent. But it also ignores its own routes and thus it can not corretly manage such routes in some cases. This patch makes an exception for routes with proto bird when ignoring dead routes. This routes are exported to the kernel by their nature. And they shall not be imported from kernel and exported to other protocols. So this exception does not affect the idea of ignoring dead routes. diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index fdf3f2db..d508e994 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -681,7 +681,7 @@ nl_add_multipath(struct nlmsghdr *h, uint bufsize, struct nexthop *nh, int af, e } static struct nexthop * -nl_parse_multipath(struct nl_parse_state *s, struct krt_proto *p, struct rtattr *ra, int af) +nl_parse_multipath(struct nl_parse_state *s, struct krt_proto *p, struct rtattr *ra, int af, int skipdead) { struct rtattr *a[BIRD_RTA_MAX]; struct rtnexthop *nh = RTA_DATA(ra); @@ -697,7 +697,7 @@ nl_parse_multipath(struct nl_parse_state *s, struct krt_proto *p, struct rtattr if ((len < sizeof(*nh)) || (len < nh->rtnh_len)) return NULL; - if (nh->rtnh_flags & RTNH_F_DEAD) + if (skipdead && nh->rtnh_flags & RTNH_F_DEAD) goto next; *last = rv = lp_allocz(s->pool, NEXTHOP_MAX_SIZE); @@ -1540,6 +1540,8 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) u32 def_scope = RT_SCOPE_UNIVERSE; int krt_src; + int skipdead = 1; + if (!(i = nl_checkin(h, sizeof(*i)))) return; @@ -1638,6 +1640,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) if (!s->scan) SKIP("echo\n"); krt_src = KRT_SRC_BIRD; + skipdead = 0; break; case RTPROT_BOOT: @@ -1675,7 +1678,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) if (a[RTA_MULTIPATH]) { - struct nexthop *nh = nl_parse_multipath(s, p, a[RTA_MULTIPATH], i->rtm_family); + struct nexthop *nh = nl_parse_multipath(s, p, a[RTA_MULTIPATH], i->rtm_family, skipdead); if (!nh) { log(L_ERR "KRT: Received strange multipath route %N", net->n.addr); @@ -1686,8 +1689,8 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) break; } - if (i->rtm_flags & RTNH_F_DEAD) - return; + if (skipdead && i->rtm_flags & RTNH_F_DEAD) + SKIP("ignore RTNH_F_DEAD\n"); ra->nh.iface = if_find_by_index(oif); if (!ra->nh.iface)
