1 /*
2  * Copyright (c) 2019 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <logging/log.h>
8 LOG_MODULE_REGISTER(net_test, CONFIG_NET_SOCKETS_LOG_LEVEL);
9 
10 #include <stdio.h>
11 #include <ztest_assert.h>
12 #include <sys_clock.h>
13 #include <net/net_ip.h>
14 #include <net/socket.h>
15 #include <net/socket_net_mgmt.h>
16 #include <net/net_event.h>
17 #include <net/ethernet_mgmt.h>
18 
19 #define MAX_BUF_LEN 64
20 #define STACK_SIZE 1024
21 #define THREAD_PRIORITY K_PRIO_COOP(8)
22 
23 static struct net_if *default_iface;
24 
25 static ZTEST_BMEM int fd;
26 static ZTEST_BMEM struct in6_addr addr_v6;
27 static ZTEST_DMEM struct in_addr addr_v4 = { { { 192, 0, 2, 3 } } };
28 
29 #if IS_ENABLED(CONFIG_NET_SOCKETS_LOG_LEVEL_DBG)
30 #define DBG(fmt, ...) printk(fmt, ##__VA_ARGS__)
31 #else
32 #define DBG(fmt, ...)
33 #endif
34 
35 static const uint8_t mac_addr_init[6] = { 0x01, 0x02, 0x03,
36 				       0x04,  0x05,  0x06 };
37 
38 struct eth_fake_context {
39 	struct net_if *iface;
40 	uint8_t mac_address[6];
41 
42 	bool auto_negotiation;
43 	bool full_duplex;
44 	bool link_10bt;
45 	bool link_100bt;
46 	bool promisc_mode;
47 	struct {
48 		bool qav_enabled;
49 		int idle_slope;
50 		int delta_bandwidth;
51 	} priority_queues[2];
52 };
53 
54 static struct eth_fake_context eth_fake_data;
55 
eth_fake_iface_init(struct net_if * iface)56 static void eth_fake_iface_init(struct net_if *iface)
57 {
58 	const struct device *dev = net_if_get_device(iface);
59 	struct eth_fake_context *ctx = dev->data;
60 
61 	ctx->iface = iface;
62 
63 	net_if_set_link_addr(iface, ctx->mac_address,
64 			     sizeof(ctx->mac_address),
65 			     NET_LINK_ETHERNET);
66 
67 	ethernet_init(iface);
68 }
69 
eth_fake_send(const struct device * dev,struct net_pkt * pkt)70 static int eth_fake_send(const struct device *dev,
71 			 struct net_pkt *pkt)
72 {
73 	ARG_UNUSED(dev);
74 	ARG_UNUSED(pkt);
75 
76 	return 0;
77 }
78 
eth_fake_get_total_bandwidth(struct eth_fake_context * ctx)79 static int eth_fake_get_total_bandwidth(struct eth_fake_context *ctx)
80 {
81 	if (ctx->link_100bt) {
82 		return 100 * 1000 * 1000 / 8;
83 	}
84 
85 	if (ctx->link_10bt) {
86 		return 10 * 1000 * 1000 / 8;
87 	}
88 
89 	/* No link */
90 	return 0;
91 }
92 
eth_fake_recalc_qav_delta_bandwidth(struct eth_fake_context * ctx)93 static void eth_fake_recalc_qav_delta_bandwidth(struct eth_fake_context *ctx)
94 {
95 	int bw;
96 	int i;
97 
98 	bw = eth_fake_get_total_bandwidth(ctx);
99 
100 	for (i = 0; i < ARRAY_SIZE(ctx->priority_queues); ++i) {
101 		if (bw == 0) {
102 			ctx->priority_queues[i].delta_bandwidth = 0;
103 		} else {
104 			ctx->priority_queues[i].delta_bandwidth =
105 				(ctx->priority_queues[i].idle_slope * 100);
106 
107 			ctx->priority_queues[i].delta_bandwidth /= bw;
108 		}
109 	}
110 }
111 
eth_fake_recalc_qav_idle_slopes(struct eth_fake_context * ctx)112 static void eth_fake_recalc_qav_idle_slopes(struct eth_fake_context *ctx)
113 {
114 	int bw;
115 	int i;
116 
117 	bw = eth_fake_get_total_bandwidth(ctx);
118 
119 	for (i = 0; i < ARRAY_SIZE(ctx->priority_queues); ++i) {
120 		ctx->priority_queues[i].idle_slope =
121 			(ctx->priority_queues[i].delta_bandwidth * bw) / 100;
122 	}
123 }
124 
eth_fake_set_config(const struct device * dev,enum ethernet_config_type type,const struct ethernet_config * config)125 static int eth_fake_set_config(const struct device *dev,
126 			       enum ethernet_config_type type,
127 			       const struct ethernet_config *config)
128 {
129 	struct eth_fake_context *ctx = dev->data;
130 	int priority_queues_num = ARRAY_SIZE(ctx->priority_queues);
131 	enum ethernet_qav_param_type qav_param_type;
132 	int queue_id;
133 
134 	switch (type) {
135 	case ETHERNET_CONFIG_TYPE_QAV_PARAM:
136 		queue_id = config->qav_param.queue_id;
137 		qav_param_type = config->qav_param.type;
138 
139 		if (queue_id < 0 || queue_id >= priority_queues_num) {
140 			return -EINVAL;
141 		}
142 
143 		switch (qav_param_type) {
144 		case ETHERNET_QAV_PARAM_TYPE_STATUS:
145 			ctx->priority_queues[queue_id].qav_enabled =
146 				config->qav_param.enabled;
147 			break;
148 		case ETHERNET_QAV_PARAM_TYPE_IDLE_SLOPE:
149 			ctx->priority_queues[queue_id].idle_slope =
150 				config->qav_param.idle_slope;
151 
152 			eth_fake_recalc_qav_delta_bandwidth(ctx);
153 			break;
154 		case ETHERNET_QAV_PARAM_TYPE_DELTA_BANDWIDTH:
155 			ctx->priority_queues[queue_id].delta_bandwidth =
156 				config->qav_param.delta_bandwidth;
157 
158 			eth_fake_recalc_qav_idle_slopes(ctx);
159 			break;
160 		default:
161 			return -ENOTSUP;
162 		}
163 
164 		break;
165 	default:
166 		return -ENOTSUP;
167 	}
168 
169 	return 0;
170 }
171 
eth_fake_get_config(const struct device * dev,enum ethernet_config_type type,struct ethernet_config * config)172 static int eth_fake_get_config(const struct device *dev,
173 			       enum ethernet_config_type type,
174 			       struct ethernet_config *config)
175 {
176 	struct eth_fake_context *ctx = dev->data;
177 	int priority_queues_num = ARRAY_SIZE(ctx->priority_queues);
178 	enum ethernet_qav_param_type qav_param_type;
179 	int queue_id;
180 
181 	switch (type) {
182 	case ETHERNET_CONFIG_TYPE_QAV_PARAM:
183 		queue_id = config->qav_param.queue_id;
184 		qav_param_type = config->qav_param.type;
185 
186 		if (queue_id < 0 || queue_id >= priority_queues_num) {
187 			return -EINVAL;
188 		}
189 
190 		switch (qav_param_type) {
191 		case ETHERNET_QAV_PARAM_TYPE_STATUS:
192 			config->qav_param.enabled =
193 				ctx->priority_queues[queue_id].qav_enabled;
194 			break;
195 		case ETHERNET_QAV_PARAM_TYPE_IDLE_SLOPE:
196 		case ETHERNET_QAV_PARAM_TYPE_OPER_IDLE_SLOPE:
197 			/* No distinction between idle slopes for fake eth */
198 			config->qav_param.idle_slope =
199 				ctx->priority_queues[queue_id].idle_slope;
200 			break;
201 		case ETHERNET_QAV_PARAM_TYPE_DELTA_BANDWIDTH:
202 			config->qav_param.delta_bandwidth =
203 				ctx->priority_queues[queue_id].delta_bandwidth;
204 			break;
205 		case ETHERNET_QAV_PARAM_TYPE_TRAFFIC_CLASS:
206 			/* Default TC for BE - it doesn't really matter here */
207 			config->qav_param.traffic_class =
208 				net_tx_priority2tc(NET_PRIORITY_BE);
209 			break;
210 		default:
211 			return -ENOTSUP;
212 		}
213 
214 		break;
215 	default:
216 		return -ENOTSUP;
217 	}
218 
219 	return 0;
220 }
221 
eth_fake_get_capabilities(const struct device * dev)222 static enum ethernet_hw_caps eth_fake_get_capabilities(const struct device *dev)
223 {
224 	return ETHERNET_AUTO_NEGOTIATION_SET | ETHERNET_LINK_10BASE_T |
225 		ETHERNET_LINK_100BASE_T | ETHERNET_DUPLEX_SET | ETHERNET_QAV |
226 		ETHERNET_PROMISC_MODE | ETHERNET_PRIORITY_QUEUES;
227 }
228 
229 static struct ethernet_api eth_fake_api_funcs = {
230 	.iface_api.init = eth_fake_iface_init,
231 
232 	.get_capabilities = eth_fake_get_capabilities,
233 	.set_config = eth_fake_set_config,
234 	.get_config = eth_fake_get_config,
235 	.send = eth_fake_send,
236 };
237 
eth_fake_init(const struct device * dev)238 static int eth_fake_init(const struct device *dev)
239 {
240 	struct eth_fake_context *ctx = dev->data;
241 	int i;
242 
243 	ctx->auto_negotiation = true;
244 	ctx->full_duplex = true;
245 	ctx->link_10bt = true;
246 	ctx->link_100bt = false;
247 
248 	memcpy(ctx->mac_address, mac_addr_init, 6);
249 
250 	/* Initialize priority queues */
251 	for (i = 0; i < ARRAY_SIZE(ctx->priority_queues); ++i) {
252 		ctx->priority_queues[i].qav_enabled = true;
253 		if (i + 1 == ARRAY_SIZE(ctx->priority_queues)) {
254 			/* 75% for the last priority queue */
255 			ctx->priority_queues[i].delta_bandwidth = 75;
256 		} else {
257 			/* 0% for the rest */
258 			ctx->priority_queues[i].delta_bandwidth = 0;
259 		}
260 	}
261 
262 	eth_fake_recalc_qav_idle_slopes(ctx);
263 
264 	return 0;
265 }
266 
267 ETH_NET_DEVICE_INIT(eth_fake, "eth_fake", eth_fake_init, NULL,
268 		    &eth_fake_data, NULL, CONFIG_ETH_INIT_PRIORITY,
269 		    &eth_fake_api_funcs, NET_ETH_MTU);
270 
271 /* A test thread that spits out events that we can catch and show to user */
trigger_events(void)272 static void trigger_events(void)
273 {
274 	int operation = 0;
275 	struct net_if_addr *ifaddr_v6, *ifaddr_v4;
276 	struct net_if *iface;
277 	int ret;
278 
279 	iface = default_iface;
280 
281 	net_ipv6_addr_create(&addr_v6, 0x2001, 0x0db8, 0, 0, 0, 0, 0, 0x0003);
282 
283 	while (1) {
284 		switch (operation) {
285 		case 0:
286 			ifaddr_v6 = net_if_ipv6_addr_add(iface, &addr_v6,
287 							 NET_ADDR_MANUAL, 0);
288 			if (!ifaddr_v6) {
289 				LOG_ERR("Cannot add IPv%c address", '6');
290 				break;
291 			}
292 
293 			break;
294 		case 1:
295 			ifaddr_v4 = net_if_ipv4_addr_add(iface, &addr_v4,
296 							 NET_ADDR_MANUAL, 0);
297 			if (!ifaddr_v4) {
298 				LOG_ERR("Cannot add IPv%c address", '4');
299 				break;
300 			}
301 
302 			break;
303 		case 2:
304 			ret = net_if_ipv6_addr_rm(iface, &addr_v6);
305 			if (!ret) {
306 				LOG_ERR("Cannot del IPv%c address", '6');
307 				break;
308 			}
309 
310 			break;
311 		case 3:
312 			ret = net_if_ipv4_addr_rm(iface, &addr_v4);
313 			if (!ret) {
314 				LOG_ERR("Cannot del IPv%c address", '4');
315 				break;
316 			}
317 
318 			break;
319 		default:
320 			operation = -1;
321 			break;
322 		}
323 
324 		operation++;
325 
326 		k_sleep(K_MSEC(100));
327 	}
328 }
329 
330 K_THREAD_DEFINE(trigger_events_thread_id, STACK_SIZE,
331 		trigger_events, NULL, NULL, NULL,
332 		THREAD_PRIORITY, 0, -1);
333 
get_ip_addr(char * ipaddr,size_t len,sa_family_t family,struct net_mgmt_msghdr * hdr)334 static char *get_ip_addr(char *ipaddr, size_t len, sa_family_t family,
335 			 struct net_mgmt_msghdr *hdr)
336 {
337 	char *buf;
338 
339 	buf = net_addr_ntop(family, hdr->nm_msg, ipaddr, len);
340 	if (!buf) {
341 		return "?";
342 	}
343 
344 	return buf;
345 }
346 
iface_cb(struct net_if * iface,void * user_data)347 static void iface_cb(struct net_if *iface, void *user_data)
348 {
349 	struct net_if **my_iface = user_data;
350 
351 	if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
352 		if (PART_OF_ARRAY(NET_IF_GET_NAME(eth_fake, 0), iface)) {
353 			*my_iface = iface;
354 		}
355 	}
356 }
357 
test_net_mgmt_setup(void)358 static void test_net_mgmt_setup(void)
359 {
360 	struct sockaddr_nm sockaddr;
361 	int ret;
362 
363 	net_if_foreach(iface_cb, &default_iface);
364 	zassert_not_null(default_iface, "Cannot find test interface");
365 
366 	fd = socket(AF_NET_MGMT, SOCK_DGRAM, NET_MGMT_EVENT_PROTO);
367 	zassert_false(fd < 0, "Cannot create net_mgmt socket (%d)", errno);
368 
369 #ifdef CONFIG_USERSPACE
370 	/* Set the underlying net_context to global access scope so that
371 	 * other scenario threads may use it
372 	 */
373 	void *ctx = zsock_get_context_object(fd);
374 
375 	zassert_not_null(ctx, "null net_context");
376 	k_object_access_all_grant(ctx);
377 #endif /* CONFIG_USERSPACE */
378 
379 	memset(&sockaddr, 0, sizeof(sockaddr));
380 
381 	sockaddr.nm_family = AF_NET_MGMT;
382 	sockaddr.nm_ifindex = net_if_get_by_iface(default_iface);
383 	sockaddr.nm_pid = (uintptr_t)k_current_get();
384 	sockaddr.nm_mask = NET_EVENT_IPV6_DAD_SUCCEED |
385 			   NET_EVENT_IPV6_ADDR_ADD |
386 			   NET_EVENT_IPV6_ADDR_DEL;
387 
388 	ret = bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
389 	zassert_false(ret < 0, "Cannot bind net_mgmt socket (%d)", errno);
390 
391 	k_thread_start(trigger_events_thread_id);
392 }
393 
test_net_mgmt_catch_events(void)394 static void test_net_mgmt_catch_events(void)
395 {
396 	struct sockaddr_nm event_addr;
397 	socklen_t event_addr_len;
398 	char ipaddr[INET6_ADDRSTRLEN];
399 	uint8_t buf[MAX_BUF_LEN];
400 	int event_count = 2;
401 	int ret;
402 
403 	while (event_count > 0) {
404 		struct net_mgmt_msghdr *hdr;
405 
406 		memset(buf, 0, sizeof(buf));
407 		event_addr_len = sizeof(event_addr);
408 
409 		ret = recvfrom(fd, buf, sizeof(buf), 0,
410 			       (struct sockaddr *)&event_addr,
411 			       &event_addr_len);
412 		if (ret < 0) {
413 			continue;
414 		}
415 
416 		hdr = (struct net_mgmt_msghdr *)buf;
417 
418 		if (hdr->nm_msg_version != NET_MGMT_SOCKET_VERSION_1) {
419 			/* Do not know how to parse the message */
420 			continue;
421 		}
422 
423 		switch (event_addr.nm_mask) {
424 		case NET_EVENT_IPV6_ADDR_ADD:
425 			DBG("IPv6 address added to interface %d (%s)\n",
426 			    event_addr.nm_ifindex,
427 			    get_ip_addr(ipaddr, sizeof(ipaddr),
428 					AF_INET6, hdr));
429 			zassert_equal(strncmp(ipaddr, "2001:db8::3",
430 					      sizeof(ipaddr) - 1), 0,
431 				      "Invalid IPv6 address %s added",
432 				      ipaddr);
433 			event_count--;
434 			break;
435 		case NET_EVENT_IPV6_ADDR_DEL:
436 			DBG("IPv6 address removed from interface %d (%s)\n",
437 			    event_addr.nm_ifindex,
438 			    get_ip_addr(ipaddr, sizeof(ipaddr),
439 					AF_INET6, hdr));
440 			zassert_equal(strncmp(ipaddr, "2001:db8::3",
441 					      sizeof(ipaddr) - 1), 0,
442 				      "Invalid IPv6 address %s removed",
443 				      ipaddr);
444 			event_count--;
445 			break;
446 		}
447 	}
448 }
449 
test_net_mgmt_catch_kernel(void)450 static void test_net_mgmt_catch_kernel(void)
451 {
452 	test_net_mgmt_catch_events();
453 }
454 
test_net_mgmt_catch_user(void)455 static void test_net_mgmt_catch_user(void)
456 {
457 	test_net_mgmt_catch_events();
458 }
459 
test_net_mgmt_cleanup(void)460 static void test_net_mgmt_cleanup(void)
461 {
462 	k_thread_abort(trigger_events_thread_id);
463 }
464 
test_ethernet_set_qav(void)465 static void test_ethernet_set_qav(void)
466 {
467 	struct ethernet_req_params params;
468 	int ret;
469 
470 	memset(&params, 0, sizeof(params));
471 
472 	params.qav_param.queue_id = 1;
473 	params.qav_param.type = ETHERNET_QAV_PARAM_TYPE_STATUS;
474 	params.qav_param.enabled = true;
475 
476 	ret = setsockopt(fd, SOL_NET_MGMT_RAW,
477 			 NET_REQUEST_ETHERNET_SET_QAV_PARAM,
478 			 &params, sizeof(params));
479 	zassert_equal(ret, 0, "Cannot set Qav parameters");
480 }
481 
test_ethernet_set_qav_kernel(void)482 static void test_ethernet_set_qav_kernel(void)
483 {
484 	test_ethernet_set_qav();
485 }
486 
test_ethernet_set_qav_user(void)487 static void test_ethernet_set_qav_user(void)
488 {
489 	test_ethernet_set_qav();
490 }
491 
test_ethernet_get_qav(void)492 static void test_ethernet_get_qav(void)
493 {
494 	struct ethernet_req_params params;
495 	socklen_t optlen = sizeof(params);
496 	int ret;
497 
498 	memset(&params, 0, sizeof(params));
499 
500 	params.qav_param.queue_id = 1;
501 	params.qav_param.type = ETHERNET_QAV_PARAM_TYPE_STATUS;
502 
503 	ret = getsockopt(fd, SOL_NET_MGMT_RAW,
504 			 NET_REQUEST_ETHERNET_GET_QAV_PARAM,
505 			 &params, &optlen);
506 	zassert_equal(ret, 0, "Cannot get Qav parameters (%d)", ret);
507 	zassert_equal(optlen, sizeof(params), "Invalid optlen (%d)", optlen);
508 
509 	zassert_true(params.qav_param.enabled, "Qav not enabled");
510 }
511 
test_ethernet_get_qav_kernel(void)512 static void test_ethernet_get_qav_kernel(void)
513 {
514 	test_ethernet_get_qav();
515 }
516 
test_ethernet_get_qav_user(void)517 static void test_ethernet_get_qav_user(void)
518 {
519 	test_ethernet_get_qav();
520 }
521 
test_ethernet_get_unknown_option(void)522 static void test_ethernet_get_unknown_option(void)
523 {
524 	struct ethernet_req_params params;
525 	socklen_t optlen = sizeof(params);
526 	int ret;
527 
528 	memset(&params, 0, sizeof(params));
529 
530 	ret = getsockopt(fd, SOL_NET_MGMT_RAW,
531 			 NET_REQUEST_ETHERNET_GET_PRIORITY_QUEUES_NUM,
532 			 &params, &optlen);
533 	zassert_equal(ret, -1, "Could get prio queue parameters (%d)", errno);
534 	zassert_equal(errno, EINVAL, "prio queue get parameters");
535 }
536 
test_ethernet_get_unknown_opt_kernel(void)537 static void test_ethernet_get_unknown_opt_kernel(void)
538 {
539 	test_ethernet_get_unknown_option();
540 }
541 
test_ethernet_get_unknown_opt_user(void)542 static void test_ethernet_get_unknown_opt_user(void)
543 {
544 	test_ethernet_get_unknown_option();
545 }
546 
test_ethernet_set_unknown_option(void)547 static void test_ethernet_set_unknown_option(void)
548 {
549 	struct ethernet_req_params params;
550 	socklen_t optlen = sizeof(params);
551 	int ret;
552 
553 	memset(&params, 0, sizeof(params));
554 
555 	ret = setsockopt(fd, SOL_NET_MGMT_RAW,
556 			 NET_REQUEST_ETHERNET_SET_MAC_ADDRESS,
557 			 &params, optlen);
558 	zassert_equal(ret, -1, "Could set promisc_mode parameters (%d)", errno);
559 	zassert_equal(errno, EINVAL, "promisc_mode set parameters");
560 }
561 
test_ethernet_set_unknown_opt_kernel(void)562 static void test_ethernet_set_unknown_opt_kernel(void)
563 {
564 	test_ethernet_set_unknown_option();
565 }
566 
test_ethernet_set_unknown_opt_user(void)567 static void test_ethernet_set_unknown_opt_user(void)
568 {
569 	test_ethernet_set_unknown_option();
570 }
571 
test_main(void)572 void test_main(void)
573 {
574 	k_thread_system_pool_assign(k_current_get());
575 
576 	ztest_test_suite(socket_net_mgmt,
577 			 ztest_unit_test(test_net_mgmt_setup),
578 			 ztest_unit_test(test_net_mgmt_catch_kernel),
579 			 ztest_user_unit_test(test_net_mgmt_catch_user),
580 			 ztest_unit_test(test_net_mgmt_cleanup),
581 			 ztest_unit_test(test_ethernet_set_qav_kernel),
582 			 ztest_user_unit_test(test_ethernet_set_qav_user),
583 			 ztest_unit_test(test_ethernet_get_qav_kernel),
584 			 ztest_user_unit_test(test_ethernet_get_qav_user),
585 			 ztest_unit_test(test_ethernet_get_unknown_opt_kernel),
586 			 ztest_user_unit_test(
587 				 test_ethernet_get_unknown_opt_user),
588 			 ztest_unit_test(test_ethernet_set_unknown_opt_kernel),
589 			 ztest_user_unit_test(
590 				 test_ethernet_set_unknown_opt_user));
591 
592 	ztest_run_test_suite(socket_net_mgmt);
593 }
594