* [PATCH net-next 0/3] net: mctp: improvements for NULL-EID addressing
@ 2026-03-31 7:41 Jeremy Kerr
2026-03-31 7:41 ` [PATCH net-next 1/3] net: mctp: perform source address lookups when we populate our dst Jeremy Kerr
` (3 more replies)
0 siblings, 4 replies; 7+ messages in thread
From: Jeremy Kerr @ 2026-03-31 7:41 UTC (permalink / raw)
To: Matt Johnston, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman
Cc: netdev
Currently, our focus for the MCTP routing implementation has been for
MCTP bus-owner devices. In this case, we will generally have an EID
assigned during local transmit, and have routes established before
expecting to receive.
We also want to handle non-bus-owner cases, where:
- we may need to send control protocol messages (like Discovery Notify)
before any local addresses have been assigned, particularly as part
of acquiring a local address assignment; and
- we will likely want to receive incoming messages before we have
routing established.
This series improves handling for these cases, by handling NULL EIDs
as source / destination addresses where possible.
Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
---
Jeremy Kerr (3):
net: mctp: perform source address lookups when we populate our dst
net: mctp: allow local TX with no address assigned
net: mctp: don't require a route for null-EID ingress
include/net/mctp.h | 1 +
net/mctp/route.c | 92 +++++++++++------------
net/mctp/test/route-test.c | 180 ++++++++++++++++++++++++++++++++++++++++++---
net/mctp/test/utils.c | 27 +++++++
net/mctp/test/utils.h | 1 +
5 files changed, 242 insertions(+), 59 deletions(-)
---
base-commit: 7fae6616704a17c64438ad4b73a6effa6c03ffda
change-id: 20260324-dev-mctp-null-eids-0515711235ee
Best regards,
--
Jeremy Kerr <jk@codeconstruct.com.au>
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH net-next 1/3] net: mctp: perform source address lookups when we populate our dst
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
2026-04-02 11:30 ` Paolo Abeni
2026-03-31 7:41 ` [PATCH net-next 2/3] net: mctp: allow local TX with no address assigned Jeremy Kerr
` (2 subsequent siblings)
3 siblings, 1 reply; 7+ messages in thread
From: Jeremy Kerr @ 2026-03-31 7:41 UTC (permalink / raw)
To: Matt Johnston, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman
Cc: netdev
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
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH net-next 2/3] net: mctp: allow local TX with no address assigned
2026-03-31 7:41 [PATCH net-next 0/3] net: mctp: improvements for NULL-EID addressing Jeremy Kerr
2026-03-31 7:41 ` [PATCH net-next 1/3] net: mctp: perform source address lookups when we populate our dst Jeremy Kerr
@ 2026-03-31 7:41 ` 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
3 siblings, 0 replies; 7+ messages in thread
From: Jeremy Kerr @ 2026-03-31 7:41 UTC (permalink / raw)
To: Matt Johnston, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman
Cc: netdev
If we're operating as a non-bus-owner endpoint, we may want to perform
MCTP communication to get an address assigned. In this case, we'll have
no local addresses, but can TX just fine either with extended routing,
or where a direct route exists.
Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
---
net/mctp/route.c | 18 ++-----
net/mctp/test/route-test.c | 114 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 118 insertions(+), 14 deletions(-)
diff --git a/net/mctp/route.c b/net/mctp/route.c
index f6a88e668e68a8431e58ccc46e7ebb7bf2303f71..8c484776e9e42e246d5e214f5c997281f820a43a 100644
--- a/net/mctp/route.c
+++ b/net/mctp/route.c
@@ -997,8 +997,8 @@ int mctp_route_lookup(struct net *net, unsigned int dnet,
if (rt->dst_type == MCTP_ROUTE_DIRECT) {
mctp_dst_from_route(&dst_tmp, daddr, mtu, rt);
- /* we need a source address */
- if (dst_tmp.saddr == MCTP_ADDR_NULL) {
+ /* cannot do gateway-ed routes without a src */
+ if (dst_tmp.saddr == MCTP_ADDR_NULL && depth != 0) {
mctp_dst_release(&dst_tmp);
} else {
if (dst)
@@ -1141,19 +1141,13 @@ int mctp_local_output(struct sock *sk, struct mctp_dst *dst,
struct mctp_sk_key *key;
struct mctp_hdr *hdr;
unsigned int netid;
- int rc = 0;
u8 tag;
KUNIT_STATIC_STUB_REDIRECT(mctp_local_output, sk, dst, skb, daddr,
req_tag);
- if (dst->saddr == MCTP_ADDR_NULL)
- rc = -EHOSTUNREACH;
netid = READ_ONCE(dst->dev->net);
- if (rc)
- goto err_free;
-
if (req_tag & MCTP_TAG_OWNER) {
if (req_tag & MCTP_TAG_PREALLOC)
key = mctp_lookup_prealloc_tag(msk, netid, daddr,
@@ -1163,8 +1157,8 @@ int mctp_local_output(struct sock *sk, struct mctp_dst *dst,
daddr, false, &tag);
if (IS_ERR(key)) {
- rc = PTR_ERR(key);
- goto err_free;
+ kfree_skb(skb);
+ return PTR_ERR(key);
}
mctp_skb_set_flow(skb, key);
/* done with the key in this scope */
@@ -1191,10 +1185,6 @@ int mctp_local_output(struct sock *sk, struct mctp_dst *dst,
/* route output functions consume the skb, even on error */
return mctp_do_fragment_route(dst, skb, dst->mtu, tag);
-
-err_free:
- kfree_skb(skb);
- return rc;
}
/* route management */
diff --git a/net/mctp/test/route-test.c b/net/mctp/test/route-test.c
index 639b7c41c2a233fa78f789d0ef25b87a15fb702b..fa28af9ac18e6605867c475ee7110fbbfd556edb 100644
--- a/net/mctp/test/route-test.c
+++ b/net/mctp/test/route-test.c
@@ -1570,6 +1570,117 @@ static void mctp_test_bind_lookup(struct kunit *test)
__mctp_route_test_fini(test, dev, &dst, sock_ty0);
}
+static void mctp_test_route_output_direct_no_eids(struct kunit *test)
+{
+ struct mctp_dst dst = { 0 };
+ struct sk_buff *skb, *skb2;
+ struct mctp_test_route *rt;
+ struct mctp_test_dev *dev;
+ struct socket *sock;
+ const int len = 2;
+ int rc;
+
+ dev = mctp_test_create_dev();
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+
+ rt = mctp_test_create_route_direct(&init_net, dev->mdev, 9, 68);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, rt);
+
+ rc = mctp_route_lookup(&init_net, dev->mdev->net, 9, &dst);
+ KUNIT_ASSERT_EQ(test, rc, 0);
+
+ rc = sock_create_kern(&init_net, AF_MCTP, SOCK_DGRAM, 0, &sock);
+ KUNIT_ASSERT_EQ(test, rc, 0);
+
+ skb = alloc_skb(sizeof(struct mctp_hdr) + 1 + len, GFP_KERNEL);
+ KUNIT_ASSERT_TRUE(test, skb);
+ __mctp_cb(skb);
+ skb_reserve(skb, sizeof(struct mctp_hdr) + 1 + len);
+ memset(skb_put(skb, len), 0, len);
+
+ rc = mctp_local_output(sock->sk, &dst, skb, 9, MCTP_TAG_OWNER);
+ KUNIT_ASSERT_EQ(test, rc, 0);
+
+ KUNIT_ASSERT_EQ(test, dev->pkts.qlen, 1);
+
+ skb2 = skb_dequeue(&dev->pkts);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, skb2);
+
+ kfree_skb(skb2);
+ sock_release(sock);
+ mctp_dst_release(&dst);
+ mctp_test_route_destroy(test, rt);
+ mctp_test_destroy_dev(dev);
+}
+
+static void mctp_test_route_output_gw_no_eids(struct kunit *test)
+{
+ struct mctp_test_route *rt1, *rt2;
+ struct mctp_test_dev *dev;
+ struct mctp_dst dst = { 0 };
+ int rc;
+
+ dev = mctp_test_create_dev();
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+
+ /* route: direct to bridge */
+ rt1 = mctp_test_create_route_direct(&init_net, dev->mdev, 9, 68);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, rt1);
+
+ /* route: bridge gw to final dest */
+ rt2 = mctp_test_create_route_gw(&init_net, dev->mdev->net, 10, 9, 0);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, rt2);
+
+ /* route lookup should fail, due to no source address on dev */
+ rc = mctp_route_lookup(&init_net, dev->mdev->net, 10, &dst);
+ KUNIT_ASSERT_NE(test, rc, 0);
+
+ mctp_test_route_destroy(test, rt1);
+ mctp_test_route_destroy(test, rt2);
+ mctp_test_destroy_dev(dev);
+}
+
+static void mctp_test_route_output_extaddr_no_eids(struct kunit *test)
+{
+ struct mctp_dst dst = { 0 };
+ struct sk_buff *skb, *skb2;
+ struct mctp_test_dev *dev;
+ struct socket *sock;
+ const int len = 1;
+ struct net *net;
+ int rc;
+
+ dev = mctp_test_create_dev();
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+
+ net = dev_net(dev->ndev);
+
+ rc = mctp_dst_from_extaddr(&dst, net, dev->ndev->ifindex, 0, NULL);
+ KUNIT_ASSERT_EQ(test, rc, 0);
+
+ rc = sock_create_kern(net, AF_MCTP, SOCK_DGRAM, 0, &sock);
+ KUNIT_ASSERT_EQ(test, rc, 0);
+
+ skb = alloc_skb(sizeof(struct mctp_hdr) + 1 + len, GFP_KERNEL);
+ KUNIT_ASSERT_TRUE(test, skb);
+ __mctp_cb(skb);
+ skb_reserve(skb, sizeof(struct mctp_hdr) + 1 + len);
+ memset(skb_put(skb, len), 0, len);
+
+ rc = mctp_local_output(sock->sk, &dst, skb, 9, MCTP_TAG_OWNER);
+ KUNIT_ASSERT_EQ(test, rc, 0);
+
+ KUNIT_ASSERT_EQ(test, dev->pkts.qlen, 1);
+
+ skb2 = skb_dequeue(&dev->pkts);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, skb2);
+
+ kfree_skb(skb2);
+ sock_release(sock);
+ mctp_dst_release(&dst);
+ mctp_test_destroy_dev(dev);
+}
+
static struct kunit_case mctp_test_cases[] = {
KUNIT_CASE_PARAM(mctp_test_fragment, mctp_frag_gen_params),
KUNIT_CASE_PARAM(mctp_test_rx_input, mctp_rx_input_gen_params),
@@ -1592,6 +1703,9 @@ static struct kunit_case mctp_test_cases[] = {
KUNIT_CASE_PARAM(mctp_test_route_gw_mtu, mctp_route_gw_mtu_gen_params),
KUNIT_CASE(mctp_test_route_gw_output),
KUNIT_CASE_PARAM(mctp_test_bind_lookup, mctp_bind_lookup_gen_params),
+ KUNIT_CASE(mctp_test_route_output_direct_no_eids),
+ KUNIT_CASE(mctp_test_route_output_gw_no_eids),
+ KUNIT_CASE(mctp_test_route_output_extaddr_no_eids),
{}
};
--
2.39.5
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH net-next 3/3] net: mctp: don't require a route for null-EID ingress
2026-03-31 7:41 [PATCH net-next 0/3] net: mctp: improvements for NULL-EID addressing Jeremy Kerr
2026-03-31 7:41 ` [PATCH net-next 1/3] net: mctp: perform source address lookups when we populate our dst 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 ` Jeremy Kerr
2026-04-02 11:40 ` [PATCH net-next 0/3] net: mctp: improvements for NULL-EID addressing patchwork-bot+netdevbpf
3 siblings, 0 replies; 7+ messages in thread
From: Jeremy Kerr @ 2026-03-31 7:41 UTC (permalink / raw)
To: Matt Johnston, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman
Cc: netdev
Currently, if we receive a physically-addressed packet for the local
stack, we perform a route_lookup_null to find a matching device-based
route. If a route is present, it will always have the ->output fn set to
mctp_dst_input, which provides our delivery mechanism.
However, if we don't yet have any local addresses assigned, we won't
have any local routes to lookup, so this will fail. One of the use-cases
for physical addressing is initial address assignment on endpoint nodes,
where we would have no addresses, and therefore no local routes.
Instead of iterating routes (looking for one matching the dev), just
create a suitable mctp_dst for the device directly.
Add a testcase for the no-route case too.
Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
---
net/mctp/route.c | 31 ++++++++++++-------------------
net/mctp/test/route-test.c | 43 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 55 insertions(+), 19 deletions(-)
diff --git a/net/mctp/route.c b/net/mctp/route.c
index 8c484776e9e42e246d5e214f5c997281f820a43a..78263e7ae423d5bd92b10920b5c42c5f51a15a75 100644
--- a/net/mctp/route.c
+++ b/net/mctp/route.c
@@ -1017,29 +1017,22 @@ int mctp_route_lookup(struct net *net, unsigned int dnet,
return rc;
}
-static int mctp_route_lookup_null(struct net *net, struct net_device *dev,
- struct mctp_dst *dst)
+static int mctp_dst_input_null(struct net *net, struct net_device *dev,
+ struct mctp_dst *dst)
{
- int rc = -EHOSTUNREACH;
- struct mctp_route *rt;
-
rcu_read_lock();
+ dst->dev = __mctp_dev_get(dev);
+ rcu_read_unlock();
- list_for_each_entry_rcu(rt, &net->mctp.routes, list) {
- if (rt->dst_type != MCTP_ROUTE_DIRECT || rt->type != RTN_LOCAL)
- continue;
-
- if (rt->dev->dev != dev)
- continue;
-
- mctp_dst_from_route(dst, 0, 0, rt);
- rc = 0;
- break;
- }
+ if (!dst->dev)
+ return -EHOSTUNREACH;
- rcu_read_unlock();
+ dst->mtu = READ_ONCE(dev->mtu);
+ dst->halen = 0;
+ dst->output = mctp_dst_input;
+ dst->nexthop = 0;
- return rc;
+ return 0;
}
static int mctp_do_fragment_route(struct mctp_dst *dst, struct sk_buff *skb,
@@ -1369,7 +1362,7 @@ static int mctp_pkttype_receive(struct sk_buff *skb, struct net_device *dev,
/* NULL EID, but addressed to our physical address */
if (rc && mh->dest == MCTP_ADDR_NULL && skb->pkt_type == PACKET_HOST)
- rc = mctp_route_lookup_null(net, dev, &dst);
+ rc = mctp_dst_input_null(net, dev, &dst);
if (rc)
goto err_drop;
diff --git a/net/mctp/test/route-test.c b/net/mctp/test/route-test.c
index fa28af9ac18e6605867c475ee7110fbbfd556edb..e1033643fab0e2045fef34b42cab87f746761545 100644
--- a/net/mctp/test/route-test.c
+++ b/net/mctp/test/route-test.c
@@ -914,6 +914,48 @@ static void mctp_test_route_input_cloned_frag(struct kunit *test)
__mctp_route_test_fini(test, dev, &dst, sock);
}
+/* check we can receive an incoming packet with the null EID as daddr, when
+ * no RTN_LOCAL routes are present.
+ */
+static void mctp_test_route_input_null_eid(struct kunit *test)
+{
+ struct mctp_hdr hdr = RX_HDR(1, 10, 0, FL_S | FL_E | FL_TO);
+ struct sk_buff *skb_pkt, *skb_sk;
+ struct mctp_test_dev *dev;
+ struct sockaddr_mctp addr;
+ struct socket *sock;
+ u8 type = 0;
+ int rc;
+
+ dev = mctp_test_create_dev();
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+
+ rc = sock_create_kern(&init_net, AF_MCTP, SOCK_DGRAM, 0, &sock);
+ KUNIT_ASSERT_EQ(test, rc, 0);
+
+ addr.smctp_family = AF_MCTP;
+ addr.smctp_network = MCTP_NET_ANY;
+ addr.smctp_addr.s_addr = MCTP_ADDR_ANY;
+ addr.smctp_type = type;
+ rc = kernel_bind(sock, (struct sockaddr_unsized *)&addr, sizeof(addr));
+ KUNIT_ASSERT_EQ(test, rc, 0);
+
+ skb_pkt = mctp_test_create_skb_data(&hdr, &type);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, skb_pkt);
+
+ skb_pkt->dev = dev->ndev;
+ skb_pkt->pkt_type = PACKET_HOST;
+
+ mctp_pkttype_receive(skb_pkt, dev->ndev, &mctp_packet_type, NULL);
+
+ skb_sk = skb_recv_datagram(sock->sk, MSG_DONTWAIT, &rc);
+ KUNIT_EXPECT_NOT_ERR_OR_NULL(test, skb_sk);
+
+ skb_free_datagram(sock->sk, skb_sk);
+ sock_release(sock);
+ mctp_test_destroy_dev(dev);
+}
+
#if IS_ENABLED(CONFIG_MCTP_FLOWS)
static void mctp_test_flow_init(struct kunit *test,
@@ -1693,6 +1735,7 @@ static struct kunit_case mctp_test_cases[] = {
KUNIT_CASE(mctp_test_route_input_sk_fail_frag),
KUNIT_CASE(mctp_test_route_input_multiple_nets_bind),
KUNIT_CASE(mctp_test_route_input_multiple_nets_key),
+ KUNIT_CASE(mctp_test_route_input_null_eid),
KUNIT_CASE(mctp_test_packet_flow),
KUNIT_CASE(mctp_test_fragment_flow),
KUNIT_CASE(mctp_test_route_output_key_create),
--
2.39.5
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH net-next 1/3] net: mctp: perform source address lookups when we populate our dst
2026-03-31 7:41 ` [PATCH net-next 1/3] net: mctp: perform source address lookups when we populate our dst Jeremy Kerr
@ 2026-04-02 11:30 ` Paolo Abeni
2026-04-02 11:48 ` Jeremy Kerr
0 siblings, 1 reply; 7+ messages in thread
From: Paolo Abeni @ 2026-04-02 11:30 UTC (permalink / raw)
To: Jeremy Kerr, Matt Johnston, David S. Miller, Eric Dumazet,
Jakub Kicinski, Simon Horman
Cc: netdev
On 3/31/26 9:41 AM, Jeremy Kerr wrote:
> 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>
Sashiko pointed to a possible pre-existent issue:
https://sashiko.dev/#/patchset/20260331-dev-mctp-null-eids-v1-0-b4d047372eaf%40codeconstruct.com.au
please have a look and follow-up if needed.
Thanks,
Paolo
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net-next 0/3] net: mctp: improvements for NULL-EID addressing
2026-03-31 7:41 [PATCH net-next 0/3] net: mctp: improvements for NULL-EID addressing Jeremy Kerr
` (2 preceding siblings ...)
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 ` patchwork-bot+netdevbpf
3 siblings, 0 replies; 7+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-04-02 11:40 UTC (permalink / raw)
To: Jeremy Kerr; +Cc: matt, davem, edumazet, kuba, pabeni, horms, netdev
Hello:
This series was applied to netdev/net-next.git (main)
by Paolo Abeni <pabeni@redhat.com>:
On Tue, 31 Mar 2026 15:41:05 +0800 you wrote:
> Currently, our focus for the MCTP routing implementation has been for
> MCTP bus-owner devices. In this case, we will generally have an EID
> assigned during local transmit, and have routes established before
> expecting to receive.
>
> We also want to handle non-bus-owner cases, where:
>
> [...]
Here is the summary with links:
- [net-next,1/3] net: mctp: perform source address lookups when we populate our dst
https://git.kernel.org/netdev/net-next/c/22cb45afd221
- [net-next,2/3] net: mctp: allow local TX with no address assigned
https://git.kernel.org/netdev/net-next/c/8af20defc4ed
- [net-next,3/3] net: mctp: don't require a route for null-EID ingress
https://git.kernel.org/netdev/net-next/c/0d8647bc74cb
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net-next 1/3] net: mctp: perform source address lookups when we populate our dst
2026-04-02 11:30 ` Paolo Abeni
@ 2026-04-02 11:48 ` Jeremy Kerr
0 siblings, 0 replies; 7+ messages in thread
From: Jeremy Kerr @ 2026-04-02 11:48 UTC (permalink / raw)
To: Paolo Abeni, Matt Johnston, David S. Miller, Eric Dumazet,
Jakub Kicinski, Simon Horman
Cc: netdev
Hi Pablo,
> > 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>
>
> Sashiko pointed to a possible pre-existent issue:
>
> https://sashiko.dev/#/patchset/20260331-dev-mctp-null-eids-v1-0-b4d047372eaf%40codeconstruct.com.au
>
> please have a look and follow-up if needed.
Yes, I've just been checking that out this afternoon. While there's
nothing pressing there (the findings are somewhat valid, but don't
affect any typical behaviour), I think it's worth a fix.
Given the merge to net-next, I assume a patch on top of the series is in
order, but let me know if you'd like something else.
Cheers,
Jeremy
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-04-02 11:48 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-31 7:41 [PATCH net-next 0/3] net: mctp: improvements for NULL-EID addressing Jeremy Kerr
2026-03-31 7:41 ` [PATCH net-next 1/3] net: mctp: perform source address lookups when we populate our dst Jeremy Kerr
2026-04-02 11:30 ` 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
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox