]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Netlink: Handle onlink flag on BSD-Netlink
authorOndrej Zajicek <santiago@crfreenet.org>
Thu, 12 Dec 2024 03:04:07 +0000 (04:04 +0100)
committerOndrej Zajicek <santiago@crfreenet.org>
Thu, 12 Dec 2024 03:04:07 +0000 (04:04 +0100)
On BSD, the onlink flag is not tracked or reported by kernel. We are
using an heuristic that assigns the onlink flag to routes scanned from
the kernel. We should use the same heuristic even in BSD-Netlink
case, as the onlink flag is not reported here too.

Thanks to Björn König for the original patch.

sysdep/bsd/krt-sock.c
sysdep/cf/README
sysdep/cf/bsd-netlink.h
sysdep/cf/bsd.h
sysdep/linux/netlink.c
sysdep/unix/krt.c
sysdep/unix/krt.h

index d13e20a3efc93436de4b8b10e52df05ad8ecc822..e8e555af7cb6171ad1c4161bfc460a408511c09a 100644 (file)
@@ -394,30 +394,6 @@ krt_replace_rte(struct krt_proto *p, net *n UNUSED, rte *new, rte *old)
   }
 }
 
-/**
- * krt_assume_onlink - check if routes on interface are considered onlink
- * @iface: The interface of the next hop
- * @ipv6: Switch to only consider IPv6 or IPv4 addresses.
- *
- * The BSD kernel does not support an onlink flag. If the interface has only
- * host addresses configured, all routes should be considered as onlink and
- * the function returns 1.
- */
-static int
-krt_assume_onlink(struct iface *iface, int ipv6)
-{
-  const u8 type = ipv6 ? NET_IP6 : NET_IP4;
-
-  struct ifa *ifa;
-  WALK_LIST(ifa, iface->addrs)
-  {
-    if ((ifa->prefix.type == type) && !(ifa->flags & IA_HOST))
-      return 0;
-  }
-
-  return 1;
-}
-
 #define SKIP(ARG...) do { DBG("KRT: Ignoring route - " ARG); return; } while(0)
 
 static void
index af65aaec49a3fc441127026000e41fff5566ea59..cdaf5da16797a0c7601ed29133054e11e27f819c 100644 (file)
@@ -5,6 +5,7 @@ CONFIG_AUTO_ROUTES      Device routes are added automagically by the kernel
 CONFIG_SELF_CONSCIOUS  We're able to recognize whether route was installed by us
 CONFIG_MULTIPLE_TABLES The kernel supports multiple routing tables
 CONFIG_SINGLE_ROUTE    There is only one route per network
+CONFIG_ASSUME_ONLINK   Assume ONLINK flag on scanned routes based on a heuristic
 
 CONFIG_MC_PROPER_SRC   Multicast packets have source address according to socket saddr field
 CONFIG_SKIP_MC_BIND    Don't call bind on multicast socket (def for *BSD)
index 6929786780ba85d9052dad7185f7b80c4a1c3987..a65106a371cf3250a08068aa836a8f14c93cf828 100644 (file)
@@ -10,6 +10,7 @@
 #define CONFIG_SELF_CONSCIOUS
 #define CONFIG_MULTIPLE_TABLES
 #define CONFIG_SINGLE_ROUTE
+#define CONFIG_ASSUME_ONLINK
 
 #define CONFIG_SKIP_MC_BIND
 #define CONFIG_NO_IFACE_BIND
index 22c54277283be1fd113d3564622b7703e55a0bbf..56ba0a1afd6e10e7e954baf10588db5d0d866697 100644 (file)
@@ -10,6 +10,7 @@
 #define CONFIG_SELF_CONSCIOUS
 #define CONFIG_MULTIPLE_TABLES
 #define CONFIG_SINGLE_ROUTE
+#define CONFIG_ASSUME_ONLINK
 
 #define CONFIG_SKIP_MC_BIND
 #define CONFIG_NO_IFACE_BIND
index 533cc26860b96d4a7a73a984c24bc0b93c59cadf..299f132fec9192d0e887c2ba9ebb15eedab7f13b 100644 (file)
@@ -788,6 +788,11 @@ nl_parse_multipath(struct nl_parse_state *s, struct krt_proto *p, const net_addr
 
       if (ipa_nonzero(rv->gw))
        {
+#ifdef CONFIG_ASSUME_ONLINK
+         if (krt_assume_onlink(rv->iface, ipa_is_ip6(rv->gw)))
+           rv->flags |= RNF_ONLINK;
+#endif
+
          neighbor *nbr;
          nbr = neigh_find(&p->p, rv->gw, rv->iface,
                           (rv->flags & RNF_ONLINK) ? NEF_ONLINK : 0);
@@ -1739,6 +1744,11 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
          if ((i->rtm_family == AF_INET6) && ipa_in_netX(ra->nh.gw, (net_addr *) &sit))
            return;
 
+#ifdef CONFIG_ASSUME_ONLINK
+         if (krt_assume_onlink(ra->nh.iface, ipa_is_ip6(ra->nh.gw)))
+           ra->nh.flags |= RNF_ONLINK;
+#endif
+
          neighbor *nbr;
          nbr = neigh_find(&p->p, ra->nh.gw, ra->nh.iface,
                           (ra->nh.flags & RNF_ONLINK) ? NEF_ONLINK : 0);
index 51d0718c150ac9b58e9d01509124ae8deab96a78..5baaf18b40fc6f238463fb94ad37e25a67fe276f 100644 (file)
@@ -909,6 +909,30 @@ krt_scan_timer_kick(struct krt_proto *p)
     tm_start(p->scan_timer, 0);
 }
 
+/**
+ * krt_assume_onlink - check if routes on interface are considered onlink
+ * @iface: The interface of the next hop
+ * @ipv6: Switch to only consider IPv6 or IPv4 addresses.
+ *
+ * The BSD kernel does not support an onlink flag. If the interface has only
+ * host addresses configured, all routes should be considered as onlink and
+ * the function returns 1. This is used when CONFIG_ASSUME_ONLINK is set.
+ */
+int
+krt_assume_onlink(struct iface *iface, int ipv6)
+{
+  const u8 type = ipv6 ? NET_IP6 : NET_IP4;
+
+  struct ifa *ifa;
+  WALK_LIST(ifa, iface->addrs)
+  {
+    if ((ifa->prefix.type == type) && !(ifa->flags & IA_HOST))
+      return 0;
+  }
+
+  return 1;
+}
+
 
 /*
  *     Updates
index e25f0b125f0e40d3982036d1312067cf7d808400..2b1dfa96df787389050a688e829e63ff9455eaf5 100644 (file)
@@ -83,6 +83,7 @@ void kif_request_scan(void);
 void krt_use_shared_scan(void);
 void krt_got_route(struct krt_proto *p, struct rte *e, s8 src);
 void krt_got_route_async(struct krt_proto *p, struct rte *e, int new, s8 src);
+int krt_assume_onlink(struct iface *iface, int ipv6);
 
 static inline int
 krt_get_sync_error(struct krt_proto *p, struct rte *e)