struct mctp_dev *dev;
unsigned int mtu;
mctp_eid_t nexthop;
+ mctp_eid_t saddr;
/* set for direct addressing */
unsigned char halen;
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)
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,
dst->halen = halen;
dst->output = mctp_dst_output;
dst->nexthop = 0;
+ dst->saddr = mctp_dev_saddr(dev);
memcpy(dst->haddr, haddr, halen);
rc = 0;
{
const unsigned int max_depth = 32;
unsigned int depth, mtu = 0;
+ struct mctp_dst dst_tmp;
int rc = -EHOSTUNREACH;
rcu_read_lock();
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) {
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)
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);
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);
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,
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);
*/
__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);
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);
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);
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) */
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 */
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;
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)
{
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));
__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)
};
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);