mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Faizan Ali <faizana@nvidia.com>
To: Jeremy Kerr <jk@codeconstruct.com.au>,
	Matt Johnston <matt@codeconstruct.com.au>
Cc: <netdev@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
	Eric Dumazet <edumazet@google.com>,
	"David S . Miller" <davem@davemloft.net>,
	Simon Horman <horms@kernel.org>, Faizan Ali <faizana@nvidia.com>
Subject: [PATCH net-next] net: mctp: add MCTP_OPT_ROUTE_SRCADDR getsockopt
Date: Mon, 21 Sep 2026 09:21:18 +0530	[thread overview]
Message-ID: <20260921035118.1649687-1-faizana@nvidia.com> (raw)

Add a new socket option MCTP_OPT_ROUTE_SRCADDR that allows applications
to query which local EID the kernel would use as the source address
when sending to a given destination EID.

Applications such as PLDM need to advertise a local EID as the event
receiver address to remote endpoints. Previously this required a manual
multi-step lookup via the mctp tool (route show + addr show).
The kernel routing table is the authoritative
source for this mapping, so expose it directly via a socket option.

The caller fills in net and daddr in struct mctp_route_srcaddr before
calling getsockopt(SOL_MCTP, MCTP_OPT_ROUTE_SRCADDR); the kernel
performs the same route lookup used for actual packet output and
returns the resolved local EID in saddr.

Verified with the included kunit tests, and manually validated on
hardware that the resolved source EID matches mctp route show / addr
show output for both reachable and unreachable destinations.

Link: https://github.com/CodeConstruct/mctp/issues/147
Signed-off-by: Faizan Ali <faizana@nvidia.com>
---
 include/uapi/linux/mctp.h | 13 +++++++++
 net/mctp/af_mctp.c        | 31 ++++++++++++++++++++
 net/mctp/test/sock-test.c | 61 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 105 insertions(+)

diff --git a/include/uapi/linux/mctp.h b/include/uapi/linux/mctp.h
index 19ad12a0c..7c3d4a936 100644
--- a/include/uapi/linux/mctp.h
+++ b/include/uapi/linux/mctp.h
@@ -55,6 +55,19 @@ struct mctp_fq_addr {
 #define MCTP_TAG_PREALLOC	0x10
 
 #define MCTP_OPT_ADDR_EXT	1
+#define MCTP_OPT_ROUTE_SRCADDR	2
+
+/* Query structure for MCTP_OPT_ROUTE_SRCADDR getsockopt.
+ *
+ * Caller fills in @net and @daddr before calling getsockopt.
+ * Performs a route lookup and returns the local source EID in @saddr.
+ */
+struct mctp_route_srcaddr {
+	unsigned int	net;
+	mctp_eid_t	daddr;
+	mctp_eid_t	saddr;
+	__u8		__pad[2];
+};
 
 #define SIOCMCTPALLOCTAG	(SIOCPROTOPRIVATE + 0)
 #define SIOCMCTPDROPTAG		(SIOCPROTOPRIVATE + 1)
diff --git a/net/mctp/af_mctp.c b/net/mctp/af_mctp.c
index 8af5e2b3c..5c6077e03 100644
--- a/net/mctp/af_mctp.c
+++ b/net/mctp/af_mctp.c
@@ -425,6 +425,37 @@ static int mctp_getsockopt(struct socket *sock, int level, int optname,
 		return 0;
 	}
 
+	if (optname == MCTP_OPT_ROUTE_SRCADDR) {
+		struct mctp_route_srcaddr rsa;
+		struct mctp_dst dst;
+		unsigned int net;
+		int rc;
+
+		if (len != sizeof(rsa))
+			return -EINVAL;
+
+		if (copy_from_iter(&rsa, len, &opt->iter_in) != len)
+			return -EFAULT;
+
+		net = rsa.net;
+		if (net == MCTP_NET_ANY)
+			net = mctp_default_net(sock_net(sock->sk));
+
+		rc = mctp_route_lookup(sock_net(sock->sk), net, rsa.daddr, &dst);
+		if (rc)
+			return rc;
+
+		rsa.saddr = dst.saddr;
+		mctp_dst_release(&dst);
+
+		if (rsa.saddr == MCTP_ADDR_NULL)
+			return -EADDRNOTAVAIL;
+
+		if (copy_to_iter(&rsa, len, &opt->iter_out) != len)
+			return -EFAULT;
+		return 0;
+	}
+
 	return -ENOPROTOOPT;
 }
 
diff --git a/net/mctp/test/sock-test.c b/net/mctp/test/sock-test.c
index b0942deb5..b3ebc504b 100644
--- a/net/mctp/test/sock-test.c
+++ b/net/mctp/test/sock-test.c
@@ -379,10 +379,71 @@ static void mctp_test_assumptions(struct kunit *test)
 	KUNIT_ASSERT_EQ(test, mctp_default_net(&init_net), 1);
 }
 
+static void mctp_test_sockopt_init(sockopt_t *opt, struct kvec *vec,
+				   void *buf, size_t len)
+{
+	vec->iov_base = buf;
+	vec->iov_len = len;
+	iov_iter_kvec(&opt->iter_in, ITER_SOURCE, vec, 1, len);
+	iov_iter_kvec(&opt->iter_out, ITER_DEST, vec, 1, len);
+	opt->optlen = len;
+}
+
+static void mctp_test_getsockopt_route_srcaddr(struct kunit *test)
+{
+	struct mctp_route_srcaddr rsa = {
+		.net = MCTP_INITIAL_DEFAULT_NET,
+		.daddr = 9,
+	};
+	struct mctp_test_route *rt;
+	struct mctp_test_dev *dev;
+	struct socket *sock;
+	struct kvec vec;
+	sockopt_t opt;
+	int rc;
+
+	__mctp_sock_test_init(test, &dev, &rt, &sock);
+
+	/* Query the source EID for destination EID 9; the device has
+	 * local EID 8, so the route lookup should return saddr=8.
+	 */
+	mctp_test_sockopt_init(&opt, &vec, &rsa, sizeof(rsa));
+	rc = mctp_getsockopt(sock, SOL_MCTP, MCTP_OPT_ROUTE_SRCADDR, &opt);
+	KUNIT_EXPECT_EQ(test, rc, 0);
+	KUNIT_EXPECT_EQ(test, (int)rsa.saddr, 8);
+	KUNIT_EXPECT_EQ(test, opt.optlen, (int)sizeof(rsa));
+
+	__mctp_sock_test_fini(test, dev, rt, sock);
+}
+
+static void mctp_test_getsockopt_route_srcaddr_no_route(struct kunit *test)
+{
+	struct mctp_route_srcaddr rsa = {
+		.net = MCTP_INITIAL_DEFAULT_NET,
+		.daddr = 99,  /* no route for this EID */
+	};
+	struct mctp_test_route *rt;
+	struct mctp_test_dev *dev;
+	struct socket *sock;
+	struct kvec vec;
+	sockopt_t opt;
+	int rc;
+
+	__mctp_sock_test_init(test, &dev, &rt, &sock);
+
+	mctp_test_sockopt_init(&opt, &vec, &rsa, sizeof(rsa));
+	rc = mctp_getsockopt(sock, SOL_MCTP, MCTP_OPT_ROUTE_SRCADDR, &opt);
+	KUNIT_EXPECT_EQ(test, rc, -EHOSTUNREACH);
+
+	__mctp_sock_test_fini(test, dev, rt, sock);
+}
+
 static struct kunit_case mctp_test_cases[] = {
 	KUNIT_CASE(mctp_test_assumptions),
 	KUNIT_CASE(mctp_test_sock_sendmsg_extaddr),
 	KUNIT_CASE(mctp_test_sock_recvmsg_extaddr),
+	KUNIT_CASE(mctp_test_getsockopt_route_srcaddr),
+	KUNIT_CASE(mctp_test_getsockopt_route_srcaddr_no_route),
 	KUNIT_CASE_PARAM(mctp_test_bind_conflicts, mctp_bind_pair_gen_params),
 	KUNIT_CASE(mctp_test_bind_invalid),
 	{}
-- 
2.43.0


                 reply	other threads:[~2026-09-21  3:52 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=20260921035118.1649687-1-faizana@nvidia.com \
    --to=faizana@nvidia.com \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=horms@kernel.org \
    --cc=jk@codeconstruct.com.au \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.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

all inboxes | Powered by JetHome®