mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 09:20:13 -04:00
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 <jk@codeconstruct.com.au> Link: https://patch.msgid.link/20260331-dev-mctp-null-eids-v1-1-b4d047372eaf@codeconstruct.com.au Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
@@ -270,6 +270,7 @@ struct mctp_dst {
|
|||||||
struct mctp_dev *dev;
|
struct mctp_dev *dev;
|
||||||
unsigned int mtu;
|
unsigned int mtu;
|
||||||
mctp_eid_t nexthop;
|
mctp_eid_t nexthop;
|
||||||
|
mctp_eid_t saddr;
|
||||||
|
|
||||||
/* set for direct addressing */
|
/* set for direct addressing */
|
||||||
unsigned char halen;
|
unsigned char halen;
|
||||||
|
|||||||
@@ -880,6 +880,21 @@ static bool mctp_rt_compare_exact(struct mctp_route *rt1,
|
|||||||
rt1->max == rt2->max;
|
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 */
|
/* 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,
|
static void mctp_dst_from_route(struct mctp_dst *dst, mctp_eid_t eid,
|
||||||
unsigned int mtu, struct mctp_route *route)
|
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->mtu = min(dst->mtu, mtu);
|
||||||
dst->halen = 0;
|
dst->halen = 0;
|
||||||
dst->output = route->output;
|
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,
|
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->halen = halen;
|
||||||
dst->output = mctp_dst_output;
|
dst->output = mctp_dst_output;
|
||||||
dst->nexthop = 0;
|
dst->nexthop = 0;
|
||||||
|
dst->saddr = mctp_dev_saddr(dev);
|
||||||
memcpy(dst->haddr, haddr, halen);
|
memcpy(dst->haddr, haddr, halen);
|
||||||
|
|
||||||
rc = 0;
|
rc = 0;
|
||||||
@@ -958,6 +975,7 @@ int mctp_route_lookup(struct net *net, unsigned int dnet,
|
|||||||
{
|
{
|
||||||
const unsigned int max_depth = 32;
|
const unsigned int max_depth = 32;
|
||||||
unsigned int depth, mtu = 0;
|
unsigned int depth, mtu = 0;
|
||||||
|
struct mctp_dst dst_tmp;
|
||||||
int rc = -EHOSTUNREACH;
|
int rc = -EHOSTUNREACH;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
@@ -978,9 +996,15 @@ int mctp_route_lookup(struct net *net, unsigned int dnet,
|
|||||||
mtu = mtu ?: rt->mtu;
|
mtu = mtu ?: rt->mtu;
|
||||||
|
|
||||||
if (rt->dst_type == MCTP_ROUTE_DIRECT) {
|
if (rt->dst_type == MCTP_ROUTE_DIRECT) {
|
||||||
if (dst)
|
mctp_dst_from_route(&dst_tmp, daddr, mtu, rt);
|
||||||
mctp_dst_from_route(dst, daddr, mtu, rt);
|
/* we need a source address */
|
||||||
rc = 0;
|
if (dst_tmp.saddr == MCTP_ADDR_NULL) {
|
||||||
|
mctp_dst_release(&dst_tmp);
|
||||||
|
} else {
|
||||||
|
if (dst)
|
||||||
|
*dst = dst_tmp;
|
||||||
|
rc = 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
} else if (rt->dst_type == MCTP_ROUTE_GATEWAY) {
|
} 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_sock *msk = container_of(sk, struct mctp_sock, sk);
|
||||||
struct mctp_sk_key *key;
|
struct mctp_sk_key *key;
|
||||||
struct mctp_hdr *hdr;
|
struct mctp_hdr *hdr;
|
||||||
unsigned long flags;
|
|
||||||
unsigned int netid;
|
unsigned int netid;
|
||||||
mctp_eid_t saddr;
|
int rc = 0;
|
||||||
int rc;
|
|
||||||
u8 tag;
|
u8 tag;
|
||||||
|
|
||||||
KUNIT_STATIC_STUB_REDIRECT(mctp_local_output, sk, dst, skb, daddr,
|
KUNIT_STATIC_STUB_REDIRECT(mctp_local_output, sk, dst, skb, daddr,
|
||||||
req_tag);
|
req_tag);
|
||||||
|
|
||||||
rc = -ENODEV;
|
if (dst->saddr == MCTP_ADDR_NULL)
|
||||||
|
|
||||||
spin_lock_irqsave(&dst->dev->addrs_lock, flags);
|
|
||||||
if (dst->dev->num_addrs == 0) {
|
|
||||||
rc = -EHOSTUNREACH;
|
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);
|
netid = READ_ONCE(dst->dev->net);
|
||||||
|
|
||||||
if (rc)
|
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,
|
key = mctp_lookup_prealloc_tag(msk, netid, daddr,
|
||||||
req_tag, &tag);
|
req_tag, &tag);
|
||||||
else
|
else
|
||||||
key = mctp_alloc_local_tag(msk, netid, saddr, daddr,
|
key = mctp_alloc_local_tag(msk, netid, dst->saddr,
|
||||||
false, &tag);
|
daddr, false, &tag);
|
||||||
|
|
||||||
if (IS_ERR(key)) {
|
if (IS_ERR(key)) {
|
||||||
rc = PTR_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 = mctp_hdr(skb);
|
||||||
hdr->ver = 1;
|
hdr->ver = 1;
|
||||||
hdr->dest = daddr;
|
hdr->dest = daddr;
|
||||||
hdr->src = saddr;
|
hdr->src = dst->saddr;
|
||||||
|
|
||||||
/* route output functions consume the skb, even on error */
|
/* route output functions consume the skb, even on error */
|
||||||
return mctp_do_fragment_route(dst, skb, dst->mtu, tag);
|
return mctp_do_fragment_route(dst, skb, dst->mtu, tag);
|
||||||
|
|||||||
@@ -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,
|
KUNIT_ARRAY_PARAM(mctp_rx_input, mctp_rx_input_tests,
|
||||||
mctp_rx_input_test_to_desc);
|
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,
|
static void __mctp_route_test_init(struct kunit *test,
|
||||||
struct mctp_test_dev **devp,
|
struct mctp_test_dev **devp,
|
||||||
struct mctp_dst *dst,
|
struct mctp_dst *dst,
|
||||||
@@ -191,6 +193,10 @@ static void __mctp_route_test_init(struct kunit *test,
|
|||||||
if (netid != MCTP_NET_ANY)
|
if (netid != MCTP_NET_ANY)
|
||||||
WRITE_ONCE(dev->mdev->net, netid);
|
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);
|
mctp_test_dst_setup(test, dst, dev, 68);
|
||||||
|
|
||||||
rc = sock_create_kern(&init_net, AF_MCTP, SOCK_DGRAM, 0, &sock);
|
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);
|
__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);
|
skb = alloc_skb(len + sizeof(struct mctp_hdr) + 1, GFP_KERNEL);
|
||||||
KUNIT_ASSERT_TRUE(test, skb);
|
KUNIT_ASSERT_TRUE(test, skb);
|
||||||
__mctp_cb(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);
|
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
|
||||||
WRITE_ONCE(dev->mdev->net, netid);
|
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);
|
rc = sock_create_kern(&init_net, AF_MCTP, SOCK_DGRAM, 0, &sock);
|
||||||
KUNIT_ASSERT_EQ(test, rc, 0);
|
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->num_addrs = 1;
|
||||||
dev->mdev->addrs[0] = src_eid;
|
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);
|
skb = alloc_skb(sizeof(struct mctp_hdr) + 1 + len, GFP_KERNEL);
|
||||||
KUNIT_ASSERT_TRUE(test, skb);
|
KUNIT_ASSERT_TRUE(test, skb);
|
||||||
__mctp_cb(skb);
|
__mctp_cb(skb);
|
||||||
@@ -1165,7 +1166,7 @@ static void mctp_test_route_gw_lookup(struct kunit *test)
|
|||||||
struct mctp_test_dev *dev;
|
struct mctp_test_dev *dev;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
dev = mctp_test_create_dev();
|
dev = mctp_test_create_dev_with_addr(8);
|
||||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
|
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
|
||||||
|
|
||||||
/* 8 (local) -> 10 (gateway) via 9 (direct) */
|
/* 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;
|
struct mctp_test_dev *dev;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
dev = mctp_test_create_dev();
|
dev = mctp_test_create_dev_with_addr(8);
|
||||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
|
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
|
||||||
|
|
||||||
/* two routes using each other as the gw */
|
/* 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;
|
unsigned int netid;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
dev = mctp_test_create_dev();
|
dev = mctp_test_create_dev_with_addr(8);
|
||||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
|
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
|
||||||
dev->ndev->mtu = mtus->dev;
|
dev->ndev->mtu = mtus->dev;
|
||||||
mdev = dev->mdev;
|
mdev = dev->mdev;
|
||||||
|
|||||||
@@ -80,6 +80,26 @@ struct mctp_test_dev *mctp_test_create_dev(void)
|
|||||||
return __mctp_test_create_dev(0, NULL);
|
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,
|
struct mctp_test_dev *mctp_test_create_dev_lladdr(unsigned short lladdr_len,
|
||||||
const unsigned char *lladdr)
|
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,
|
void mctp_test_dst_setup(struct kunit *test, struct mctp_dst *dst,
|
||||||
struct mctp_test_dev *dev, unsigned int mtu)
|
struct mctp_test_dev *dev, unsigned int mtu)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
KUNIT_EXPECT_NOT_ERR_OR_NULL(test, dev);
|
KUNIT_EXPECT_NOT_ERR_OR_NULL(test, dev);
|
||||||
|
|
||||||
memset(dst, 0, sizeof(*dst));
|
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);
|
__mctp_dev_get(dst->dev->dev);
|
||||||
dst->mtu = mtu;
|
dst->mtu = mtu;
|
||||||
dst->output = mctp_test_dst_output;
|
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)
|
void mctp_test_route_destroy(struct kunit *test, struct mctp_test_route *rt)
|
||||||
|
|||||||
@@ -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(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,
|
struct mctp_test_dev *mctp_test_create_dev_lladdr(unsigned short lladdr_len,
|
||||||
const unsigned char *lladdr);
|
const unsigned char *lladdr);
|
||||||
void mctp_test_destroy_dev(struct mctp_test_dev *dev);
|
void mctp_test_destroy_dev(struct mctp_test_dev *dev);
|
||||||
|
|||||||
Reference in New Issue
Block a user