commit 73edc5b27930245b962be510e852912b3ca1ef83
Author: Alexander Zubkov <green@qrator.net>
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)
