1 /*
2  * Copyright (c) 2019 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_REGISTER(net_test, CONFIG_NET_SOCKETS_LOG_LEVEL);
9 
10 #include <stdio.h>
11 #include <zephyr/ztest_assert.h>
12 #include <zephyr/sys_clock.h>
13 #include <zephyr/net/net_ip.h>
14 #include <zephyr/net/socket.h>
15 #include <zephyr/net/socket_net_mgmt.h>
16 #include <zephyr/net/net_event.h>
17 #include <zephyr/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 defined(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 = zsock_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 = zsock_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 = zsock_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 
ZTEST(net_socket_net_mgmt,test_net_mgmt_catch_kernel)450 ZTEST(net_socket_net_mgmt, test_net_mgmt_catch_kernel)
451 {
452 	test_net_mgmt_catch_events();
453 }
454 
ZTEST_USER(net_socket_net_mgmt,test_net_mgmt_catch_user)455 ZTEST_USER(net_socket_net_mgmt, test_net_mgmt_catch_user)
456 {
457 	test_net_mgmt_catch_events();
458 }
459 
test_net_mgmt_catch_events_failure(void)460 static void test_net_mgmt_catch_events_failure(void)
461 {
462 #define SMALL_BUF_LEN 16
463 	struct sockaddr_nm event_addr;
464 	socklen_t event_addr_len;
465 	uint8_t buf[SMALL_BUF_LEN];
466 	int ret;
467 
468 	memset(buf, 0, sizeof(buf));
469 	event_addr_len = sizeof(event_addr);
470 
471 	ret = zsock_recvfrom(fd, buf, sizeof(buf), 0,
472 			     (struct sockaddr *)&event_addr,
473 			     &event_addr_len);
474 	zassert_equal(ret, -1, "Msg check failed, %d", errno);
475 	zassert_equal(errno, EMSGSIZE, "Msg check failed, errno %d", errno);
476 }
477 
ZTEST(net_socket_net_mgmt,test_net_mgmt_catch_failure_kernel)478 ZTEST(net_socket_net_mgmt, test_net_mgmt_catch_failure_kernel)
479 {
480 	test_net_mgmt_catch_events_failure();
481 }
482 
ZTEST_USER(net_socket_net_mgmt,test_net_mgmt_catch_failure_user)483 ZTEST_USER(net_socket_net_mgmt, test_net_mgmt_catch_failure_user)
484 {
485 	test_net_mgmt_catch_events_failure();
486 }
487 
ZTEST(net_socket_net_mgmt,test_net_mgmt_cleanup)488 ZTEST(net_socket_net_mgmt, test_net_mgmt_cleanup)
489 {
490 	k_thread_abort(trigger_events_thread_id);
491 }
492 
test_ethernet_set_qav(void)493 static void test_ethernet_set_qav(void)
494 {
495 	struct ethernet_req_params 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 	params.qav_param.enabled = true;
503 
504 	ret = zsock_setsockopt(fd, SOL_NET_MGMT_RAW,
505 			       NET_REQUEST_ETHERNET_SET_QAV_PARAM,
506 			       &params, sizeof(params));
507 	zassert_equal(ret, 0, "Cannot set Qav parameters");
508 }
509 
ZTEST(net_socket_net_mgmt,test_ethernet_set_qav_kernel)510 ZTEST(net_socket_net_mgmt, test_ethernet_set_qav_kernel)
511 {
512 	test_ethernet_set_qav();
513 }
514 
ZTEST_USER(net_socket_net_mgmt,test_ethernet_set_qav_user)515 ZTEST_USER(net_socket_net_mgmt, test_ethernet_set_qav_user)
516 {
517 	test_ethernet_set_qav();
518 }
519 
test_ethernet_get_qav(void)520 static void test_ethernet_get_qav(void)
521 {
522 	struct ethernet_req_params params;
523 	socklen_t optlen = sizeof(params);
524 	int ret;
525 
526 	memset(&params, 0, sizeof(params));
527 
528 	params.qav_param.queue_id = 1;
529 	params.qav_param.type = ETHERNET_QAV_PARAM_TYPE_STATUS;
530 
531 	ret = zsock_getsockopt(fd, SOL_NET_MGMT_RAW,
532 			       NET_REQUEST_ETHERNET_GET_QAV_PARAM,
533 			       &params, &optlen);
534 	zassert_equal(ret, 0, "Cannot get Qav parameters (%d)", ret);
535 	zassert_equal(optlen, sizeof(params), "Invalid optlen (%d)", optlen);
536 
537 	zassert_true(params.qav_param.enabled, "Qav not enabled");
538 }
539 
ZTEST(net_socket_net_mgmt,test_ethernet_get_qav_kernel)540 ZTEST(net_socket_net_mgmt, test_ethernet_get_qav_kernel)
541 {
542 	test_ethernet_get_qav();
543 }
544 
ZTEST_USER(net_socket_net_mgmt,test_ethernet_get_qav_user)545 ZTEST_USER(net_socket_net_mgmt, test_ethernet_get_qav_user)
546 {
547 	test_ethernet_get_qav();
548 }
549 
test_ethernet_get_unknown_option(void)550 static void test_ethernet_get_unknown_option(void)
551 {
552 	struct ethernet_req_params params;
553 	socklen_t optlen = sizeof(params);
554 	int ret;
555 
556 	memset(&params, 0, sizeof(params));
557 
558 	ret = zsock_getsockopt(fd, SOL_NET_MGMT_RAW,
559 			       NET_REQUEST_ETHERNET_GET_PRIORITY_QUEUES_NUM,
560 			       &params, &optlen);
561 	zassert_equal(ret, -1, "Could get prio queue parameters (%d)", errno);
562 	zassert_equal(errno, EINVAL, "prio queue get parameters");
563 }
564 
ZTEST(net_socket_net_mgmt,test_ethernet_get_unknown_opt_kernel)565 ZTEST(net_socket_net_mgmt, test_ethernet_get_unknown_opt_kernel)
566 {
567 	test_ethernet_get_unknown_option();
568 }
569 
ZTEST_USER(net_socket_net_mgmt,test_ethernet_get_unknown_opt_user)570 ZTEST_USER(net_socket_net_mgmt, test_ethernet_get_unknown_opt_user)
571 {
572 	test_ethernet_get_unknown_option();
573 }
574 
test_ethernet_set_unknown_option(void)575 static void test_ethernet_set_unknown_option(void)
576 {
577 	struct ethernet_req_params params;
578 	socklen_t optlen = sizeof(params);
579 	int ret;
580 
581 	memset(&params, 0, sizeof(params));
582 
583 	ret = zsock_setsockopt(fd, SOL_NET_MGMT_RAW,
584 			       NET_REQUEST_ETHERNET_SET_MAC_ADDRESS,
585 			       &params, optlen);
586 	zassert_equal(ret, -1, "Could set promisc_mode parameters (%d)", errno);
587 	zassert_equal(errno, EINVAL, "promisc_mode set parameters");
588 }
589 
ZTEST(net_socket_net_mgmt,test_ethernet_set_unknown_opt_kernel)590 ZTEST(net_socket_net_mgmt, test_ethernet_set_unknown_opt_kernel)
591 {
592 	test_ethernet_set_unknown_option();
593 }
594 
ZTEST_USER(net_socket_net_mgmt,test_ethernet_set_unknown_opt_user)595 ZTEST_USER(net_socket_net_mgmt, test_ethernet_set_unknown_opt_user)
596 {
597 	test_ethernet_set_unknown_option();
598 }
599 
setup(void)600 static void *setup(void)
601 {
602 	k_thread_system_pool_assign(k_current_get());
603 	test_net_mgmt_setup();
604 	return NULL;
605 }
606 
607 ZTEST_SUITE(net_socket_net_mgmt, NULL, setup, NULL, NULL, NULL);
608