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 ð_fake_data, NULL, CONFIG_ETH_INIT_PRIORITY,
269 ð_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(¶ms, 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 ¶ms, 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(¶ms, 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 ¶ms, &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(¶ms, 0, sizeof(params));
529
530 ret = getsockopt(fd, SOL_NET_MGMT_RAW,
531 NET_REQUEST_ETHERNET_GET_PRIORITY_QUEUES_NUM,
532 ¶ms, &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(¶ms, 0, sizeof(params));
554
555 ret = setsockopt(fd, SOL_NET_MGMT_RAW,
556 NET_REQUEST_ETHERNET_SET_MAC_ADDRESS,
557 ¶ms, 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