public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
From: Jeremy Kerr <jk@codeconstruct.com.au>
To: Matt Johnston <matt@codeconstruct.com.au>,
	 "David S. Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	 Jakub Kicinski <kuba@kernel.org>,
	Paolo Abeni <pabeni@redhat.com>,  Simon Horman <horms@kernel.org>
Cc: netdev@vger.kernel.org
Subject: [PATCH net-next 1/3] net: mctp: perform source address lookups when we populate our dst
Date: Tue, 31 Mar 2026 15:41:06 +0800	[thread overview]
Message-ID: <20260331-dev-mctp-null-eids-v1-1-b4d047372eaf@codeconstruct.com.au> (raw)
In-Reply-To: <20260331-dev-mctp-null-eids-v1-0-b4d047372eaf@codeconstruct.com.au>

Rather than querying the output device for its address in
mctp_local_output, set up the source address when we're populating the
dst structure. If no address is assigned, use MCTP_ADDR_NULL.

This will allow us more flexibility when routing for NULL-source-eid
cases. For now though, we still reject a NULL source address in the
output path.

We need to update the tests a little, so that addresses are assigned
before we do the dst lookups.

Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
---
 include/net/mctp.h         |  1 +
 net/mctp/route.c           | 51 +++++++++++++++++++++++++++++-----------------
 net/mctp/test/route-test.c | 23 +++++++++++----------
 net/mctp/test/utils.c      | 27 ++++++++++++++++++++++++
 net/mctp/test/utils.h      |  1 +
 5 files changed, 73 insertions(+), 30 deletions(-)

diff --git a/include/net/mctp.h b/include/net/mctp.h
index c3207ce98f07fcbb436e968d503bc45666794fdc..e1e0a69afdcef7f0924523757010e75ea53e8e7c 100644
--- a/include/net/mctp.h
+++ b/include/net/mctp.h
@@ -270,6 +270,7 @@ struct mctp_dst {
 	struct mctp_dev *dev;
 	unsigned int mtu;
 	mctp_eid_t nexthop;
+	mctp_eid_t saddr;
 
 	/* set for direct addressing */
 	unsigned char halen;
diff --git a/net/mctp/route.c b/net/mctp/route.c
index 021e04f1ea7c950af4c4e21d7afbc8c98d093186..f6a88e668e68a8431e58ccc46e7ebb7bf2303f71 100644
--- a/net/mctp/route.c
+++ b/net/mctp/route.c
@@ -880,6 +880,21 @@ static bool mctp_rt_compare_exact(struct mctp_route *rt1,
 		rt1->max == rt2->max;
 }
 
+static mctp_eid_t mctp_dev_saddr(struct mctp_dev *dev)
+{
+	mctp_eid_t addr = MCTP_ADDR_NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->addrs_lock, flags);
+	if (dev->num_addrs) {
+		/* use the outbound interface's first address as our source */
+		addr = dev->addrs[0];
+	}
+	spin_unlock_irqrestore(&dev->addrs_lock, flags);
+
+	return addr;
+}
+
 /* must only be called on a direct route, as the final output hop */
 static void mctp_dst_from_route(struct mctp_dst *dst, mctp_eid_t eid,
 				unsigned int mtu, struct mctp_route *route)
@@ -892,6 +907,7 @@ static void mctp_dst_from_route(struct mctp_dst *dst, mctp_eid_t eid,
 		dst->mtu = min(dst->mtu, mtu);
 	dst->halen = 0;
 	dst->output = route->output;
+	dst->saddr = mctp_dev_saddr(route->dev);
 }
 
 int mctp_dst_from_extaddr(struct mctp_dst *dst, struct net *net, int ifindex,
@@ -924,6 +940,7 @@ int mctp_dst_from_extaddr(struct mctp_dst *dst, struct net *net, int ifindex,
 	dst->halen = halen;
 	dst->output = mctp_dst_output;
 	dst->nexthop = 0;
+	dst->saddr = mctp_dev_saddr(dev);
 	memcpy(dst->haddr, haddr, halen);
 
 	rc = 0;
@@ -958,6 +975,7 @@ int mctp_route_lookup(struct net *net, unsigned int dnet,
 {
 	const unsigned int max_depth = 32;
 	unsigned int depth, mtu = 0;
+	struct mctp_dst dst_tmp;
 	int rc = -EHOSTUNREACH;
 
 	rcu_read_lock();
@@ -978,9 +996,15 @@ int mctp_route_lookup(struct net *net, unsigned int dnet,
 			mtu = mtu ?: rt->mtu;
 
 		if (rt->dst_type == MCTP_ROUTE_DIRECT) {
-			if (dst)
-				mctp_dst_from_route(dst, daddr, mtu, rt);
-			rc = 0;
+			mctp_dst_from_route(&dst_tmp, daddr, mtu, rt);
+			/* we need a source address */
+			if (dst_tmp.saddr == MCTP_ADDR_NULL) {
+				mctp_dst_release(&dst_tmp);
+			} else {
+				if (dst)
+					*dst = dst_tmp;
+				rc = 0;
+			}
 			break;
 
 		} else if (rt->dst_type == MCTP_ROUTE_GATEWAY) {
@@ -1116,26 +1140,15 @@ int mctp_local_output(struct sock *sk, struct mctp_dst *dst,
 	struct mctp_sock *msk = container_of(sk, struct mctp_sock, sk);
 	struct mctp_sk_key *key;
 	struct mctp_hdr *hdr;
-	unsigned long flags;
 	unsigned int netid;
-	mctp_eid_t saddr;
-	int rc;
+	int rc = 0;
 	u8 tag;
 
 	KUNIT_STATIC_STUB_REDIRECT(mctp_local_output, sk, dst, skb, daddr,
 				   req_tag);
 
-	rc = -ENODEV;
-
-	spin_lock_irqsave(&dst->dev->addrs_lock, flags);
-	if (dst->dev->num_addrs == 0) {
+	if (dst->saddr == MCTP_ADDR_NULL)
 		rc = -EHOSTUNREACH;
-	} else {
-		/* use the outbound interface's first address as our source */
-		saddr = dst->dev->addrs[0];
-		rc = 0;
-	}
-	spin_unlock_irqrestore(&dst->dev->addrs_lock, flags);
 	netid = READ_ONCE(dst->dev->net);
 
 	if (rc)
@@ -1146,8 +1159,8 @@ int mctp_local_output(struct sock *sk, struct mctp_dst *dst,
 			key = mctp_lookup_prealloc_tag(msk, netid, daddr,
 						       req_tag, &tag);
 		else
-			key = mctp_alloc_local_tag(msk, netid, saddr, daddr,
-						   false, &tag);
+			key = mctp_alloc_local_tag(msk, netid, dst->saddr,
+						   daddr, false, &tag);
 
 		if (IS_ERR(key)) {
 			rc = PTR_ERR(key);
@@ -1174,7 +1187,7 @@ int mctp_local_output(struct sock *sk, struct mctp_dst *dst,
 	hdr = mctp_hdr(skb);
 	hdr->ver = 1;
 	hdr->dest = daddr;
-	hdr->src = saddr;
+	hdr->src = dst->saddr;
 
 	/* route output functions consume the skb, even on error */
 	return mctp_do_fragment_route(dst, skb, dst->mtu, tag);
diff --git a/net/mctp/test/route-test.c b/net/mctp/test/route-test.c
index 61c989c43ec09c9e105de4e51b295d07bb93d6da..639b7c41c2a233fa78f789d0ef25b87a15fb702b 100644
--- a/net/mctp/test/route-test.c
+++ b/net/mctp/test/route-test.c
@@ -174,7 +174,9 @@ static void mctp_rx_input_test_to_desc(const struct mctp_rx_input_test *t,
 KUNIT_ARRAY_PARAM(mctp_rx_input, mctp_rx_input_tests,
 		  mctp_rx_input_test_to_desc);
 
-/* set up a local dev, route on EID 8, and a socket listening on type 0 */
+/* set up a local dev (with addr 8), route on EID 8, and a socket listening on
+ * type 0
+ */
 static void __mctp_route_test_init(struct kunit *test,
 				   struct mctp_test_dev **devp,
 				   struct mctp_dst *dst,
@@ -191,6 +193,10 @@ static void __mctp_route_test_init(struct kunit *test,
 	if (netid != MCTP_NET_ANY)
 		WRITE_ONCE(dev->mdev->net, netid);
 
+	dev->mdev->addrs = kmalloc_objs(u8, 1, GFP_KERNEL);
+	dev->mdev->num_addrs = 1;
+	dev->mdev->addrs[0] = 8;
+
 	mctp_test_dst_setup(test, dst, dev, 68);
 
 	rc = sock_create_kern(&init_net, AF_MCTP, SOCK_DGRAM, 0, &sock);
@@ -928,11 +934,6 @@ static void mctp_test_flow_init(struct kunit *test,
 	 */
 	__mctp_route_test_init(test, &dev, dst, sock, MCTP_NET_ANY);
 
-	/* Assign a single EID. ->addrs is freed on mctp netdev release */
-	dev->mdev->addrs = kmalloc(sizeof(u8), GFP_KERNEL);
-	dev->mdev->num_addrs = 1;
-	dev->mdev->addrs[0] = 8;
-
 	skb = alloc_skb(len + sizeof(struct mctp_hdr) + 1, GFP_KERNEL);
 	KUNIT_ASSERT_TRUE(test, skb);
 	__mctp_cb(skb);
@@ -1058,8 +1059,6 @@ static void mctp_test_route_output_key_create(struct kunit *test)
 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
 	WRITE_ONCE(dev->mdev->net, netid);
 
-	mctp_test_dst_setup(test, &dst, dev, 68);
-
 	rc = sock_create_kern(&init_net, AF_MCTP, SOCK_DGRAM, 0, &sock);
 	KUNIT_ASSERT_EQ(test, rc, 0);
 
@@ -1067,6 +1066,8 @@ static void mctp_test_route_output_key_create(struct kunit *test)
 	dev->mdev->num_addrs = 1;
 	dev->mdev->addrs[0] = src_eid;
 
+	mctp_test_dst_setup(test, &dst, dev, 68);
+
 	skb = alloc_skb(sizeof(struct mctp_hdr) + 1 + len, GFP_KERNEL);
 	KUNIT_ASSERT_TRUE(test, skb);
 	__mctp_cb(skb);
@@ -1165,7 +1166,7 @@ static void mctp_test_route_gw_lookup(struct kunit *test)
 	struct mctp_test_dev *dev;
 	int rc;
 
-	dev = mctp_test_create_dev();
+	dev = mctp_test_create_dev_with_addr(8);
 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
 
 	/* 8 (local) -> 10 (gateway) via 9 (direct) */
@@ -1195,7 +1196,7 @@ static void mctp_test_route_gw_loop(struct kunit *test)
 	struct mctp_test_dev *dev;
 	int rc;
 
-	dev = mctp_test_create_dev();
+	dev = mctp_test_create_dev_with_addr(8);
 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
 
 	/* two routes using each other as the gw */
@@ -1254,7 +1255,7 @@ static void mctp_test_route_gw_mtu(struct kunit *test)
 	unsigned int netid;
 	int rc;
 
-	dev = mctp_test_create_dev();
+	dev = mctp_test_create_dev_with_addr(8);
 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
 	dev->ndev->mtu = mtus->dev;
 	mdev = dev->mdev;
diff --git a/net/mctp/test/utils.c b/net/mctp/test/utils.c
index 97afe8cd2b05c9f047c4a6e8c9fb1b4496183cfe..2f79f8c1a2b44beb4917a9b92ffd72955a3a03c6 100644
--- a/net/mctp/test/utils.c
+++ b/net/mctp/test/utils.c
@@ -80,6 +80,26 @@ struct mctp_test_dev *mctp_test_create_dev(void)
 	return __mctp_test_create_dev(0, NULL);
 }
 
+struct mctp_test_dev *mctp_test_create_dev_with_addr(mctp_eid_t addr)
+{
+	struct mctp_test_dev *dev;
+
+	dev = __mctp_test_create_dev(0, NULL);
+	if (!dev)
+		return NULL;
+
+	dev->mdev->addrs = kmalloc_objs(u8, 1, GFP_KERNEL);
+	if (!dev->mdev->addrs) {
+		mctp_test_destroy_dev(dev);
+		return NULL;
+	}
+
+	dev->mdev->num_addrs = 1;
+	dev->mdev->addrs[0] = 8;
+
+	return dev;
+}
+
 struct mctp_test_dev *mctp_test_create_dev_lladdr(unsigned short lladdr_len,
 						  const unsigned char *lladdr)
 {
@@ -171,6 +191,8 @@ struct mctp_test_route *mctp_test_create_route_gw(struct net *net,
 void mctp_test_dst_setup(struct kunit *test, struct mctp_dst *dst,
 			 struct mctp_test_dev *dev, unsigned int mtu)
 {
+	unsigned long flags;
+
 	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, dev);
 
 	memset(dst, 0, sizeof(*dst));
@@ -179,6 +201,11 @@ void mctp_test_dst_setup(struct kunit *test, struct mctp_dst *dst,
 	__mctp_dev_get(dst->dev->dev);
 	dst->mtu = mtu;
 	dst->output = mctp_test_dst_output;
+	dst->saddr = MCTP_ADDR_NULL;
+	spin_lock_irqsave(&dev->mdev->addrs_lock, flags);
+	if (dev->mdev->num_addrs)
+		dst->saddr = dev->mdev->addrs[0];
+	spin_unlock_irqrestore(&dev->mdev->addrs_lock, flags);
 }
 
 void mctp_test_route_destroy(struct kunit *test, struct mctp_test_route *rt)
diff --git a/net/mctp/test/utils.h b/net/mctp/test/utils.h
index 4cc90c9da4d1bfe9c63b2cac5253f9e09be3b147..47603732e6a570f7bb7e138246071fdbc092f790 100644
--- a/net/mctp/test/utils.h
+++ b/net/mctp/test/utils.h
@@ -42,6 +42,7 @@ struct mctp_test_bind_setup {
 };
 
 struct mctp_test_dev *mctp_test_create_dev(void);
+struct mctp_test_dev *mctp_test_create_dev_with_addr(mctp_eid_t eid);
 struct mctp_test_dev *mctp_test_create_dev_lladdr(unsigned short lladdr_len,
 						  const unsigned char *lladdr);
 void mctp_test_destroy_dev(struct mctp_test_dev *dev);

-- 
2.39.5


  reply	other threads:[~2026-03-31  7:41 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-31  7:41 [PATCH net-next 0/3] net: mctp: improvements for NULL-EID addressing Jeremy Kerr
2026-03-31  7:41 ` Jeremy Kerr [this message]
2026-04-02 11:30   ` [PATCH net-next 1/3] net: mctp: perform source address lookups when we populate our dst Paolo Abeni
2026-04-02 11:48     ` Jeremy Kerr
2026-03-31  7:41 ` [PATCH net-next 2/3] net: mctp: allow local TX with no address assigned Jeremy Kerr
2026-03-31  7:41 ` [PATCH net-next 3/3] net: mctp: don't require a route for null-EID ingress Jeremy Kerr
2026-04-02 11:40 ` [PATCH net-next 0/3] net: mctp: improvements for NULL-EID addressing patchwork-bot+netdevbpf

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=20260331-dev-mctp-null-eids-v1-1-b4d047372eaf@codeconstruct.com.au \
    --to=jk@codeconstruct.com.au \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=horms@kernel.org \
    --cc=kuba@kernel.org \
    --cc=matt@codeconstruct.com.au \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@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.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox