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)

Reply via email to