public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
From: David Gibson <david@gibson.dropbear.id.au>
To: passt-dev@passt.top, Stefano Brivio <sbrivio@redhat.com>
Cc: Paul Holzinger <pholzing@redhat.com>,
	David Gibson <david@gibson.dropbear.id.au>
Subject: [PATCH 2/2] netlink: Ignore routes to link-local addresses for selecting interface
Date: Thu, 21 Mar 2024 15:04:49 +1100	[thread overview]
Message-ID: <20240321040449.1889385-3-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <20240321040449.1889385-1-david@gibson.dropbear.id.au>

Since f919dc7a4b1c ("conf, netlink: Don't require a default route to
start"), and since 639fdf06ede ("netlink: Fix selection of template
interface") less buggily, we haven't required a default route on the host
in order to operate.  Instead, if we lack a default route we'll pick an
interface with any route, as long as there's only one such interface.  If
there's more than one, we don't have a good criterion to pick, so we give
up with an informational message.

Paul Holzinger pointed out that this code considers it ambiguous even if
all but one of the interfaces has only routes to link-local addresses
(fe80::/10).  A route to link-local addresses isn't really useful from
pasta's point of view, so ignore them instead.  This removes a misleading
message in many cases, and a spurious failure in some cases.

Suggested-by: Paul Holzinger <pholzing@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 ip.h      |  9 +++++++++
 netlink.c | 15 ++++++++++++++-
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/ip.h b/ip.h
index b9aedf65..b8d4a5bf 100644
--- a/ip.h
+++ b/ip.h
@@ -24,6 +24,11 @@
 #define IN4ADDR_ANY_INIT \
 	{ .s_addr	= htonl_constant(INADDR_ANY) }
 
+#define IN4_IS_ADDR_LINKLOCAL(a)					\
+	((ntohl(((struct in_addr *)(a))->s_addr) >> 16) == 0xa9fe)
+#define IN4_IS_PREFIX_LINKLOCAL(a, len)					\
+	((len) >= 16 && IN4_IS_ADDR_LINKLOCAL(a))
+
 #define L2_BUF_IP4_INIT(proto)						\
 	{								\
 		.version	= 4,					\
@@ -40,6 +45,10 @@
 #define L2_BUF_IP4_PSUM(proto)	((uint32_t)htons_constant(0x4500) +	\
 				 (uint32_t)htons(0xff00 | (proto)))
 
+
+#define IN6_IS_PREFIX_LINKLOCAL(a, len)					\
+	((len) >= 10 && IN6_IS_ADDR_LINKLOCAL(a))
+
 #define L2_BUF_IP6_INIT(proto)						\
 	{								\
 		.priority	= 0,					\
diff --git a/netlink.c b/netlink.c
index b068aef2..a722d272 100644
--- a/netlink.c
+++ b/netlink.c
@@ -33,6 +33,7 @@
 #include "util.h"
 #include "passt.h"
 #include "log.h"
+#include "ip.h"
 #include "netlink.h"
 
 /* Netlink expects a buffer of at least 8kiB or the system page size,
@@ -270,6 +271,7 @@ unsigned int nl_get_ext_if(int s, sa_family_t af)
 	seq = nl_send(s, &req, RTM_GETROUTE, NLM_F_DUMP, sizeof(req));
 	nl_foreach_oftype(nh, status, s, buf, seq, RTM_NEWROUTE) {
 		struct rtmsg *rtm = (struct rtmsg *)NLMSG_DATA(nh);
+		const void *dst = NULL;
 		unsigned thisifi = 0;
 
 		if (rtm->rtm_family != af)
@@ -284,12 +286,23 @@ unsigned int nl_get_ext_if(int s, sa_family_t af)
 
 				rtnh = (struct rtnexthop *)RTA_DATA(rta);
 				thisifi = rtnh->rtnh_ifindex;
+			} else if (rta->rta_type == RTA_DST) {
+				dst = RTA_DATA(rta);
 			}
 		}
 
 		if (!thisifi)
 			continue; /* No interface for this route */
 
+		/* Skip routes to link-local addresses */
+		if (af == AF_INET && dst &&
+		    IN4_IS_PREFIX_LINKLOCAL(dst, rtm->rtm_dst_len))
+			continue;
+
+		if (af == AF_INET6 && dst &&
+		    IN6_IS_PREFIX_LINKLOCAL(dst, rtm->rtm_dst_len))
+			continue;
+
 		if (rtm->rtm_dst_len == 0) {
 			/* Default route */
 			ndef++;
@@ -322,7 +335,7 @@ unsigned int nl_get_ext_if(int s, sa_family_t af)
 	}
 
 	if (!nany)
-		info("No interfaces with %s routes", af_name(af));
+		info("No interfaces with usable %s routes", af_name(af));
 
 	return 0;
 }
-- 
@@ -33,6 +33,7 @@
 #include "util.h"
 #include "passt.h"
 #include "log.h"
+#include "ip.h"
 #include "netlink.h"
 
 /* Netlink expects a buffer of at least 8kiB or the system page size,
@@ -270,6 +271,7 @@ unsigned int nl_get_ext_if(int s, sa_family_t af)
 	seq = nl_send(s, &req, RTM_GETROUTE, NLM_F_DUMP, sizeof(req));
 	nl_foreach_oftype(nh, status, s, buf, seq, RTM_NEWROUTE) {
 		struct rtmsg *rtm = (struct rtmsg *)NLMSG_DATA(nh);
+		const void *dst = NULL;
 		unsigned thisifi = 0;
 
 		if (rtm->rtm_family != af)
@@ -284,12 +286,23 @@ unsigned int nl_get_ext_if(int s, sa_family_t af)
 
 				rtnh = (struct rtnexthop *)RTA_DATA(rta);
 				thisifi = rtnh->rtnh_ifindex;
+			} else if (rta->rta_type == RTA_DST) {
+				dst = RTA_DATA(rta);
 			}
 		}
 
 		if (!thisifi)
 			continue; /* No interface for this route */
 
+		/* Skip routes to link-local addresses */
+		if (af == AF_INET && dst &&
+		    IN4_IS_PREFIX_LINKLOCAL(dst, rtm->rtm_dst_len))
+			continue;
+
+		if (af == AF_INET6 && dst &&
+		    IN6_IS_PREFIX_LINKLOCAL(dst, rtm->rtm_dst_len))
+			continue;
+
 		if (rtm->rtm_dst_len == 0) {
 			/* Default route */
 			ndef++;
@@ -322,7 +335,7 @@ unsigned int nl_get_ext_if(int s, sa_family_t af)
 	}
 
 	if (!nany)
-		info("No interfaces with %s routes", af_name(af));
+		info("No interfaces with usable %s routes", af_name(af));
 
 	return 0;
 }
-- 
2.44.0


  parent reply	other threads:[~2024-03-21  4:04 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-21  4:04 [PATCH 0/2] Follow up improvements to external interface selection David Gibson
2024-03-21  4:04 ` [PATCH 1/2] util: Add helper to return name of address family David Gibson
2024-03-21  4:04 ` David Gibson [this message]
2024-04-05 18:07 ` [PATCH 0/2] Follow up improvements to external interface selection Stefano Brivio

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240321040449.1889385-3-david@gibson.dropbear.id.au \
    --to=david@gibson.dropbear.id.au \
    --cc=passt-dev@passt.top \
    --cc=pholzing@redhat.com \
    --cc=sbrivio@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://passt.top/passt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).