xref: /linux/net/mctp/test/utils.c (revision 30f831b44a98a660ccaf608f88d8bb945318dc59)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 #include <linux/netdevice.h>
4 #include <linux/mctp.h>
5 #include <linux/if_arp.h>
6 
7 #include <net/mctp.h>
8 #include <net/mctpdevice.h>
9 #include <net/pkt_sched.h>
10 
11 #include "utils.h"
12 
13 static netdev_tx_t mctp_test_dev_tx(struct sk_buff *skb,
14 				    struct net_device *ndev)
15 {
16 	struct mctp_test_dev *dev = netdev_priv(ndev);
17 
18 	skb_queue_tail(&dev->pkts, skb);
19 
20 	return NETDEV_TX_OK;
21 }
22 
23 static const struct net_device_ops mctp_test_netdev_ops = {
24 	.ndo_start_xmit = mctp_test_dev_tx,
25 };
26 
27 static void mctp_test_dev_setup(struct net_device *ndev)
28 {
29 	ndev->type = ARPHRD_MCTP;
30 	ndev->mtu = MCTP_DEV_TEST_MTU;
31 	ndev->hard_header_len = 0;
32 	ndev->tx_queue_len = 0;
33 	ndev->flags = IFF_NOARP;
34 	ndev->netdev_ops = &mctp_test_netdev_ops;
35 	ndev->needs_free_netdev = true;
36 }
37 
38 static struct mctp_test_dev *__mctp_test_create_dev(unsigned short lladdr_len,
39 						    const unsigned char *lladdr)
40 {
41 	struct mctp_test_dev *dev;
42 	struct net_device *ndev;
43 	int rc;
44 
45 	if (WARN_ON(lladdr_len > MAX_ADDR_LEN))
46 		return NULL;
47 
48 	ndev = alloc_netdev(sizeof(*dev), "mctptest%d", NET_NAME_ENUM,
49 			    mctp_test_dev_setup);
50 	if (!ndev)
51 		return NULL;
52 
53 	dev = netdev_priv(ndev);
54 	dev->ndev = ndev;
55 	ndev->addr_len = lladdr_len;
56 	dev_addr_set(ndev, lladdr);
57 	skb_queue_head_init(&dev->pkts);
58 
59 	rc = register_netdev(ndev);
60 	if (rc) {
61 		free_netdev(ndev);
62 		return NULL;
63 	}
64 
65 	rcu_read_lock();
66 	dev->mdev = __mctp_dev_get(ndev);
67 	dev->mdev->net = mctp_default_net(dev_net(ndev));
68 	rcu_read_unlock();
69 
70 	/* bring the device up; we want to be able to TX immediately */
71 	rtnl_lock();
72 	dev_open(ndev, NULL);
73 	rtnl_unlock();
74 
75 	return dev;
76 }
77 
78 struct mctp_test_dev *mctp_test_create_dev(void)
79 {
80 	return __mctp_test_create_dev(0, NULL);
81 }
82 
83 struct mctp_test_dev *mctp_test_create_dev_with_addr(mctp_eid_t addr)
84 {
85 	struct mctp_test_dev *dev;
86 
87 	dev = __mctp_test_create_dev(0, NULL);
88 	if (!dev)
89 		return NULL;
90 
91 	dev->mdev->addrs = kmalloc_objs(u8, 1, GFP_KERNEL);
92 	if (!dev->mdev->addrs) {
93 		mctp_test_destroy_dev(dev);
94 		return NULL;
95 	}
96 
97 	dev->mdev->num_addrs = 1;
98 	dev->mdev->addrs[0] = 8;
99 
100 	return dev;
101 }
102 
103 struct mctp_test_dev *mctp_test_create_dev_lladdr(unsigned short lladdr_len,
104 						  const unsigned char *lladdr)
105 {
106 	return __mctp_test_create_dev(lladdr_len, lladdr);
107 }
108 
109 void mctp_test_destroy_dev(struct mctp_test_dev *dev)
110 {
111 	skb_queue_purge(&dev->pkts);
112 	mctp_dev_put(dev->mdev);
113 	unregister_netdev(dev->ndev);
114 }
115 
116 static int mctp_test_dst_output(struct mctp_dst *dst, struct sk_buff *skb)
117 {
118 	skb->dev = dst->dev->dev;
119 	dev_queue_xmit(skb);
120 
121 	return 0;
122 }
123 
124 /* local version of mctp_route_alloc() */
125 static struct mctp_test_route *mctp_route_test_alloc(void)
126 {
127 	struct mctp_test_route *rt;
128 
129 	rt = kzalloc_obj(*rt);
130 	if (!rt)
131 		return NULL;
132 
133 	INIT_LIST_HEAD(&rt->rt.list);
134 	refcount_set(&rt->rt.refs, 1);
135 	rt->rt.output = mctp_test_dst_output;
136 
137 	return rt;
138 }
139 
140 struct mctp_test_route *mctp_test_create_route_direct(struct net *net,
141 						      struct mctp_dev *dev,
142 						      mctp_eid_t eid,
143 						      unsigned int mtu)
144 {
145 	struct mctp_test_route *rt;
146 
147 	rt = mctp_route_test_alloc();
148 	if (!rt)
149 		return NULL;
150 
151 	rt->rt.min = eid;
152 	rt->rt.max = eid;
153 	rt->rt.mtu = mtu;
154 	rt->rt.type = RTN_UNSPEC;
155 	rt->rt.dst_type = MCTP_ROUTE_DIRECT;
156 	if (dev)
157 		mctp_dev_hold(dev);
158 	rt->rt.dev = dev;
159 
160 	list_add_rcu(&rt->rt.list, &net->mctp.routes);
161 
162 	return rt;
163 }
164 
165 struct mctp_test_route *mctp_test_create_route_gw(struct net *net,
166 						  unsigned int netid,
167 						  mctp_eid_t eid,
168 						  mctp_eid_t gw,
169 						  unsigned int mtu)
170 {
171 	struct mctp_test_route *rt;
172 
173 	rt = mctp_route_test_alloc();
174 	if (!rt)
175 		return NULL;
176 
177 	rt->rt.min = eid;
178 	rt->rt.max = eid;
179 	rt->rt.mtu = mtu;
180 	rt->rt.type = RTN_UNSPEC;
181 	rt->rt.dst_type = MCTP_ROUTE_GATEWAY;
182 	rt->rt.gateway.eid = gw;
183 	rt->rt.gateway.net = netid;
184 
185 	list_add_rcu(&rt->rt.list, &net->mctp.routes);
186 
187 	return rt;
188 }
189 
190 /* Convenience function for our test dst; release with mctp_dst_release() */
191 void mctp_test_dst_setup(struct kunit *test, struct mctp_dst *dst,
192 			 struct mctp_test_dev *dev, unsigned int mtu)
193 {
194 	unsigned long flags;
195 
196 	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, dev);
197 
198 	memset(dst, 0, sizeof(*dst));
199 
200 	dst->dev = dev->mdev;
201 	__mctp_dev_get(dst->dev->dev);
202 	dst->mtu = mtu;
203 	dst->output = mctp_test_dst_output;
204 	dst->saddr = MCTP_ADDR_NULL;
205 	spin_lock_irqsave(&dev->mdev->addrs_lock, flags);
206 	if (dev->mdev->num_addrs)
207 		dst->saddr = dev->mdev->addrs[0];
208 	spin_unlock_irqrestore(&dev->mdev->addrs_lock, flags);
209 }
210 
211 void mctp_test_route_destroy(struct kunit *test, struct mctp_test_route *rt)
212 {
213 	unsigned int refs;
214 
215 	rtnl_lock();
216 	list_del_rcu(&rt->rt.list);
217 	rtnl_unlock();
218 
219 	if (rt->rt.dst_type == MCTP_ROUTE_DIRECT && rt->rt.dev)
220 		mctp_dev_put(rt->rt.dev);
221 
222 	refs = refcount_read(&rt->rt.refs);
223 	KUNIT_ASSERT_EQ_MSG(test, refs, 1, "route ref imbalance");
224 
225 	kfree_rcu(&rt->rt, rcu);
226 }
227 
228 void mctp_test_skb_set_dev(struct sk_buff *skb, struct mctp_test_dev *dev)
229 {
230 	struct mctp_skb_cb *cb;
231 
232 	cb = mctp_cb(skb);
233 	cb->net = READ_ONCE(dev->mdev->net);
234 	skb->dev = dev->ndev;
235 }
236 
237 struct sk_buff *mctp_test_create_skb(const struct mctp_hdr *hdr,
238 				     unsigned int data_len)
239 {
240 	size_t hdr_len = sizeof(*hdr);
241 	struct sk_buff *skb;
242 	unsigned int i;
243 	u8 *buf;
244 
245 	skb = alloc_skb(hdr_len + data_len, GFP_KERNEL);
246 	if (!skb)
247 		return NULL;
248 
249 	__mctp_cb(skb);
250 	memcpy(skb_put(skb, hdr_len), hdr, hdr_len);
251 
252 	buf = skb_put(skb, data_len);
253 	for (i = 0; i < data_len; i++)
254 		buf[i] = i & 0xff;
255 
256 	return skb;
257 }
258 
259 struct sk_buff *__mctp_test_create_skb_data(const struct mctp_hdr *hdr,
260 					    const void *data, size_t data_len)
261 {
262 	size_t hdr_len = sizeof(*hdr);
263 	struct sk_buff *skb;
264 
265 	skb = alloc_skb(hdr_len + data_len, GFP_KERNEL);
266 	if (!skb)
267 		return NULL;
268 
269 	__mctp_cb(skb);
270 	memcpy(skb_put(skb, hdr_len), hdr, hdr_len);
271 	memcpy(skb_put(skb, data_len), data, data_len);
272 
273 	return skb;
274 }
275 
276 void mctp_test_bind_run(struct kunit *test,
277 			const struct mctp_test_bind_setup *setup,
278 			int *ret_bind_errno, struct socket **sock)
279 {
280 	struct sockaddr_mctp addr;
281 	int rc;
282 
283 	*ret_bind_errno = -EIO;
284 
285 	rc = sock_create_kern(&init_net, AF_MCTP, SOCK_DGRAM, 0, sock);
286 	KUNIT_ASSERT_EQ(test, rc, 0);
287 
288 	/* connect() if requested */
289 	if (setup->have_peer) {
290 		memset(&addr, 0x0, sizeof(addr));
291 		addr.smctp_family = AF_MCTP;
292 		addr.smctp_network = setup->peer_net;
293 		addr.smctp_addr.s_addr = setup->peer_addr;
294 		/* connect() type must match bind() type */
295 		addr.smctp_type = setup->bind_type;
296 		rc = kernel_connect(*sock, (struct sockaddr_unsized *)&addr,
297 				    sizeof(addr), 0);
298 		KUNIT_EXPECT_EQ(test, rc, 0);
299 	}
300 
301 	/* bind() */
302 	memset(&addr, 0x0, sizeof(addr));
303 	addr.smctp_family = AF_MCTP;
304 	addr.smctp_network = setup->bind_net;
305 	addr.smctp_addr.s_addr = setup->bind_addr;
306 	addr.smctp_type = setup->bind_type;
307 
308 	*ret_bind_errno =
309 		kernel_bind(*sock, (struct sockaddr_unsized *)&addr,
310 			    sizeof(addr));
311 }
312