From: Jeremy Kerr Date: Tue, 31 Mar 2026 07:41:06 +0000 (+0800) Subject: net: mctp: perform source address lookups when we populate our dst X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=22cb45afd221b9e4f2a1dcc74a8ff645b7293aa1;p=thirdparty%2Flinux.git net: mctp: perform source address lookups when we populate our dst 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 Link: https://patch.msgid.link/20260331-dev-mctp-null-eids-v1-1-b4d047372eaf@codeconstruct.com.au Signed-off-by: Paolo Abeni --- diff --git a/include/net/mctp.h b/include/net/mctp.h index c3207ce98f07f..e1e0a69afdcef 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 021e04f1ea7c9..f6a88e668e68a 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 61c989c43ec09..639b7c41c2a23 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 97afe8cd2b05c..2f79f8c1a2b44 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 4cc90c9da4d1b..47603732e6a57 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);