1 /* main.c - Application main entry point */
2
3 /*
4 * Copyright (c) 2018 Intel Corporation
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #define NET_LOG_LEVEL CONFIG_NET_L2_ETHERNET_LOG_LEVEL
10
11 #include <zephyr/logging/log.h>
12 LOG_MODULE_REGISTER(net_test, NET_LOG_LEVEL);
13
14 #include <zephyr/types.h>
15 #include <stdbool.h>
16 #include <stddef.h>
17 #include <string.h>
18 #include <errno.h>
19 #include <zephyr/sys/printk.h>
20 #include <zephyr/linker/sections.h>
21 #include <zephyr/random/random.h>
22
23 #include <zephyr/ztest.h>
24
25 #include <zephyr/net/ethernet.h>
26 #include <zephyr/net/buf.h>
27 #include <zephyr/net/net_ip.h>
28 #include <zephyr/net/net_l2.h>
29 #include <zephyr/net/udp.h>
30
31 #include "ipv6.h"
32 #include "udp_internal.h"
33
34 #define NET_LOG_ENABLED 1
35 #include "net_private.h"
36
37 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
38 #define DBG(fmt, ...) printk(fmt, ##__VA_ARGS__)
39 #else
40 #define DBG(fmt, ...)
41 #endif
42
43 #define TEST_PORT 9999
44
45 static char *test_data = "Test data to be sent";
46
47 /* Interface 1 addresses */
48 static struct in6_addr my_addr1 = { { { 0x20, 0x01, 0x0d, 0xb8, 1, 0, 0, 0,
49 0, 0, 0, 0, 0, 0, 0, 0x1 } } };
50
51 /* Interface 2 addresses */
52 static struct in6_addr my_addr2 = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
53 0, 0, 0, 0, 0, 0, 0, 0x1 } } };
54
55 /* Destination address for test packets */
56 static struct in6_addr dst_addr = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
57 0, 0, 0, 0, 0, 0, 0, 0x2 } } };
58
59 /* Extra address is assigned to ll_addr */
60 static struct in6_addr ll_addr = { { { 0xfe, 0x80, 0x43, 0xb8, 0, 0, 0, 0,
61 0, 0, 0, 0xf2, 0xaa, 0x29, 0x02,
62 0x04 } } };
63
64 static struct in_addr in4addr_my = { { { 192, 0, 2, 1 } } };
65 static struct in_addr in4addr_dst = { { { 192, 168, 1, 1 } } };
66 static struct in_addr in4addr_my2 = { { { 192, 0, 42, 1 } } };
67
68 /* Keep track of all ethernet interfaces. For native_posix board, we need
69 * to increase the count as it has one extra network interface defined in
70 * eth_native_posix driver.
71 */
72 static struct net_if *eth_interfaces[2 + IS_ENABLED(CONFIG_ETH_NATIVE_POSIX)];
73
74 static struct net_context *udp_v6_ctx_1;
75 static struct net_context *udp_v6_ctx_2;
76 static struct net_context *udp_v4_ctx_1;
77 static struct net_context *udp_v4_ctx_2;
78
79 static bool test_failed;
80 static bool test_started;
81 static bool start_receiving;
82
83 static K_SEM_DEFINE(wait_data, 0, UINT_MAX);
84
85 #define WAIT_TIME K_SECONDS(1)
86
87 struct eth_context {
88 struct net_if *iface;
89 uint8_t mac_addr[6];
90
91 uint16_t expecting_tag;
92 };
93
94 static struct eth_context eth_context_offloading_disabled;
95 static struct eth_context eth_context_offloading_enabled;
96
eth_iface_init(struct net_if * iface)97 static void eth_iface_init(struct net_if *iface)
98 {
99 const struct device *dev = net_if_get_device(iface);
100 struct eth_context *context = dev->data;
101
102 net_if_set_link_addr(iface, context->mac_addr,
103 sizeof(context->mac_addr),
104 NET_LINK_ETHERNET);
105
106 DBG("Iface %p addr %s\n", iface,
107 net_sprint_ll_addr(context->mac_addr, sizeof(context->mac_addr)));
108
109 ethernet_init(iface);
110 }
111
get_udp_chksum(struct net_pkt * pkt)112 static uint16_t get_udp_chksum(struct net_pkt *pkt)
113 {
114 NET_PKT_DATA_ACCESS_DEFINE(udp_access, struct net_udp_hdr);
115 struct net_udp_hdr *udp_hdr;
116 struct net_pkt_cursor backup;
117
118 net_pkt_set_overwrite(pkt, true);
119 net_pkt_cursor_backup(pkt, &backup);
120 net_pkt_cursor_init(pkt);
121
122 /* Let's move the cursor to UDP header */
123 if (net_pkt_skip(pkt, sizeof(struct net_eth_hdr) +
124 net_pkt_ip_hdr_len(pkt) +
125 net_pkt_ipv6_ext_len(pkt))) {
126 return 0;
127 }
128
129 udp_hdr = (struct net_udp_hdr *)net_pkt_get_data(pkt, &udp_access);
130 if (!udp_hdr) {
131 return 0;
132 }
133
134 net_pkt_cursor_restore(pkt, &backup);
135
136 return udp_hdr->chksum;
137 }
138
eth_tx_offloading_disabled(const struct device * dev,struct net_pkt * pkt)139 static int eth_tx_offloading_disabled(const struct device *dev,
140 struct net_pkt *pkt)
141 {
142 struct eth_context *context = dev->data;
143
144 zassert_equal_ptr(ð_context_offloading_disabled, context,
145 "Context pointers do not match (%p vs %p)",
146 eth_context_offloading_disabled, context);
147
148 if (!pkt->buffer) {
149 DBG("No data to send!\n");
150 return -ENODATA;
151 }
152
153 if (start_receiving) {
154 struct net_udp_hdr hdr, *udp_hdr;
155 uint16_t port;
156 uint8_t lladdr[6];
157
158 DBG("Packet %p received\n", pkt);
159
160 /* Swap IP src and destination address so that we can receive
161 * the packet and the stack will not reject it.
162 */
163 if (net_pkt_family(pkt) == AF_INET6) {
164 struct in6_addr addr;
165
166 net_ipv6_addr_copy_raw((uint8_t *)&addr, NET_IPV6_HDR(pkt)->src);
167 net_ipv6_addr_copy_raw(NET_IPV6_HDR(pkt)->src,
168 NET_IPV6_HDR(pkt)->dst);
169 net_ipv6_addr_copy_raw(NET_IPV6_HDR(pkt)->dst, (uint8_t *)&addr);
170 } else {
171 struct in_addr addr;
172
173 net_ipv4_addr_copy_raw((uint8_t *)&addr, NET_IPV4_HDR(pkt)->src);
174 net_ipv4_addr_copy_raw(NET_IPV4_HDR(pkt)->src,
175 NET_IPV4_HDR(pkt)->dst);
176 net_ipv4_addr_copy_raw(NET_IPV4_HDR(pkt)->dst, (uint8_t *)&addr);
177 }
178
179 udp_hdr = net_udp_get_hdr(pkt, &hdr);
180 zassert_not_null(udp_hdr, "UDP header missing");
181
182 port = udp_hdr->src_port;
183 udp_hdr->src_port = udp_hdr->dst_port;
184 udp_hdr->dst_port = port;
185
186 memcpy(lladdr,
187 ((struct net_eth_hdr *)net_pkt_data(pkt))->src.addr,
188 sizeof(lladdr));
189 memcpy(((struct net_eth_hdr *)net_pkt_data(pkt))->src.addr,
190 ((struct net_eth_hdr *)net_pkt_data(pkt))->dst.addr,
191 sizeof(lladdr));
192 memcpy(((struct net_eth_hdr *)net_pkt_data(pkt))->dst.addr,
193 lladdr, sizeof(lladdr));
194
195 if (net_recv_data(net_pkt_iface(pkt),
196 net_pkt_clone(pkt, K_NO_WAIT)) < 0) {
197 test_failed = true;
198 zassert_true(false, "Packet %p receive failed\n", pkt);
199 }
200
201 return 0;
202 }
203
204 if (test_started) {
205 uint16_t chksum;
206
207 chksum = get_udp_chksum(pkt);
208
209 DBG("Chksum 0x%x offloading disabled\n", chksum);
210
211 zassert_not_equal(chksum, 0, "Checksum calculated");
212
213 k_sem_give(&wait_data);
214 }
215
216 return 0;
217 }
218
eth_tx_offloading_enabled(const struct device * dev,struct net_pkt * pkt)219 static int eth_tx_offloading_enabled(const struct device *dev,
220 struct net_pkt *pkt)
221 {
222 struct eth_context *context = dev->data;
223
224 zassert_equal_ptr(ð_context_offloading_enabled, context,
225 "Context pointers do not match (%p vs %p)",
226 eth_context_offloading_enabled, context);
227
228 if (!pkt->buffer) {
229 DBG("No data to send!\n");
230 return -ENODATA;
231 }
232
233 if (test_started) {
234 uint16_t chksum;
235
236 chksum = get_udp_chksum(pkt);
237
238 DBG("Chksum 0x%x offloading enabled\n", chksum);
239
240 zassert_equal(chksum, 0, "Checksum calculated");
241
242 k_sem_give(&wait_data);
243 }
244
245 return 0;
246 }
247
eth_offloading_enabled(const struct device * dev)248 static enum ethernet_hw_caps eth_offloading_enabled(const struct device *dev)
249 {
250 return ETHERNET_HW_TX_CHKSUM_OFFLOAD |
251 ETHERNET_HW_RX_CHKSUM_OFFLOAD;
252 }
253
eth_offloading_disabled(const struct device * dev)254 static enum ethernet_hw_caps eth_offloading_disabled(const struct device *dev)
255 {
256 return 0;
257 }
258
259 static struct ethernet_api api_funcs_offloading_disabled = {
260 .iface_api.init = eth_iface_init,
261
262 .get_capabilities = eth_offloading_disabled,
263 .send = eth_tx_offloading_disabled,
264 };
265
266 static struct ethernet_api api_funcs_offloading_enabled = {
267 .iface_api.init = eth_iface_init,
268
269 .get_capabilities = eth_offloading_enabled,
270 .send = eth_tx_offloading_enabled,
271 };
272
generate_mac(uint8_t * mac_addr)273 static void generate_mac(uint8_t *mac_addr)
274 {
275 /* 00-00-5E-00-53-xx Documentation RFC 7042 */
276 mac_addr[0] = 0x00;
277 mac_addr[1] = 0x00;
278 mac_addr[2] = 0x5E;
279 mac_addr[3] = 0x00;
280 mac_addr[4] = 0x53;
281 mac_addr[5] = sys_rand32_get();
282 }
283
eth_init(const struct device * dev)284 static int eth_init(const struct device *dev)
285 {
286 struct eth_context *context = dev->data;
287
288 generate_mac(context->mac_addr);
289
290 return 0;
291 }
292
293 ETH_NET_DEVICE_INIT(eth1_offloading_disabled_test,
294 "eth1_offloading_disabled_test",
295 eth_init, NULL,
296 ð_context_offloading_disabled, NULL,
297 CONFIG_ETH_INIT_PRIORITY,
298 &api_funcs_offloading_disabled,
299 NET_ETH_MTU);
300
301 ETH_NET_DEVICE_INIT(eth0_offloading_enabled_test,
302 "eth0_offloading_enabled_test",
303 eth_init, NULL,
304 ð_context_offloading_enabled, NULL,
305 CONFIG_ETH_INIT_PRIORITY,
306 &api_funcs_offloading_enabled,
307 NET_ETH_MTU);
308
309 struct user_data {
310 int eth_if_count;
311 int total_if_count;
312 };
313
314 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
iface2str(struct net_if * iface)315 static const char *iface2str(struct net_if *iface)
316 {
317 #ifdef CONFIG_NET_L2_ETHERNET
318 if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
319 return "Ethernet";
320 }
321 #endif
322
323 #ifdef CONFIG_NET_L2_DUMMY
324 if (net_if_l2(iface) == &NET_L2_GET_NAME(DUMMY)) {
325 return "Dummy";
326 }
327 #endif
328
329 return "<unknown type>";
330 }
331 #endif
332
iface_cb(struct net_if * iface,void * user_data)333 static void iface_cb(struct net_if *iface, void *user_data)
334 {
335 struct user_data *ud = user_data;
336
337 DBG("Interface %p (%s) [%d]\n", iface, iface2str(iface),
338 net_if_get_by_iface(iface));
339
340 if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
341 struct eth_context *eth_ctx =
342 net_if_get_device(iface)->data;
343
344 if (eth_ctx == ð_context_offloading_disabled) {
345 DBG("Iface %p without offloading\n", iface);
346 eth_interfaces[0] = iface;
347 }
348
349 if (eth_ctx == ð_context_offloading_enabled) {
350 DBG("Iface %p with offloading\n", iface);
351 eth_interfaces[1] = iface;
352 }
353
354 ud->eth_if_count++;
355 }
356
357 /* By default all interfaces are down initially */
358 net_if_down(iface);
359
360 ud->total_if_count++;
361 }
362
test_eth_setup(void)363 static void test_eth_setup(void)
364 {
365 struct user_data ud = { 0 };
366
367 /* Make sure we have enough virtual interfaces */
368 net_if_foreach(iface_cb, &ud);
369
370 zassert_equal(ud.eth_if_count, sizeof(eth_interfaces) / sizeof(void *),
371 "Invalid number of interfaces (%d vs %d)\n",
372 ud.eth_if_count,
373 sizeof(eth_interfaces) / sizeof(void *));
374 }
375
test_address_setup(void)376 static void test_address_setup(void)
377 {
378 struct net_if_addr *ifaddr;
379 struct net_if *iface1, *iface2;
380
381 iface1 = eth_interfaces[0];
382 iface2 = eth_interfaces[1];
383
384 zassert_not_null(iface1, "Interface 1");
385 zassert_not_null(iface2, "Interface 2");
386
387 ifaddr = net_if_ipv6_addr_add(iface1, &my_addr1,
388 NET_ADDR_MANUAL, 0);
389 if (!ifaddr) {
390 DBG("Cannot add IPv6 address %s\n",
391 net_sprint_ipv6_addr(&my_addr1));
392 zassert_not_null(ifaddr, "addr1");
393 }
394
395 /* For testing purposes we need to set the addresses preferred */
396 ifaddr->addr_state = NET_ADDR_PREFERRED;
397
398 ifaddr = net_if_ipv6_addr_add(iface1, &ll_addr,
399 NET_ADDR_MANUAL, 0);
400 if (!ifaddr) {
401 DBG("Cannot add IPv6 address %s\n",
402 net_sprint_ipv6_addr(&ll_addr));
403 zassert_not_null(ifaddr, "ll_addr");
404 }
405
406 ifaddr->addr_state = NET_ADDR_PREFERRED;
407
408 ifaddr = net_if_ipv4_addr_add(iface1, &in4addr_my,
409 NET_ADDR_MANUAL, 0);
410 zassert_not_null(ifaddr, "Cannot add IPv4 address");
411
412 ifaddr = net_if_ipv6_addr_add(iface2, &my_addr2,
413 NET_ADDR_MANUAL, 0);
414 if (!ifaddr) {
415 DBG("Cannot add IPv6 address %s\n",
416 net_sprint_ipv6_addr(&my_addr2));
417 zassert_not_null(ifaddr, "addr2");
418 }
419
420 ifaddr->addr_state = NET_ADDR_PREFERRED;
421
422 ifaddr = net_if_ipv4_addr_add(iface2, &in4addr_my2,
423 NET_ADDR_MANUAL, 0);
424 zassert_not_null(ifaddr, "Cannot add IPv4 address");
425
426 net_if_up(iface1);
427 net_if_up(iface2);
428
429 /* The interface might receive data which might fail the checks
430 * in the iface sending function, so we need to reset the failure
431 * flag.
432 */
433 test_failed = false;
434 }
435
add_neighbor(struct net_if * iface,struct in6_addr * addr)436 static bool add_neighbor(struct net_if *iface, struct in6_addr *addr)
437 {
438 struct net_linkaddr_storage llstorage;
439 struct net_linkaddr lladdr;
440 struct net_nbr *nbr;
441
442 llstorage.addr[0] = 0x01;
443 llstorage.addr[1] = 0x02;
444 llstorage.addr[2] = 0x33;
445 llstorage.addr[3] = 0x44;
446 llstorage.addr[4] = 0x05;
447 llstorage.addr[5] = 0x06;
448
449 lladdr.len = 6U;
450 lladdr.addr = llstorage.addr;
451 lladdr.type = NET_LINK_ETHERNET;
452
453 nbr = net_ipv6_nbr_add(iface, addr, &lladdr, false,
454 NET_IPV6_NBR_STATE_REACHABLE);
455 if (!nbr) {
456 DBG("Cannot add dst %s to neighbor cache\n",
457 net_sprint_ipv6_addr(addr));
458 return false;
459 }
460
461 return true;
462 }
463
test_tx_chksum_offload_disabled_test_v6(void)464 static void test_tx_chksum_offload_disabled_test_v6(void)
465 {
466 struct eth_context *ctx; /* This is interface context */
467 struct net_if *iface;
468 int ret, len;
469 struct sockaddr_in6 dst_addr6 = {
470 .sin6_family = AF_INET6,
471 .sin6_port = htons(TEST_PORT),
472 };
473 struct sockaddr_in6 src_addr6 = {
474 .sin6_family = AF_INET6,
475 .sin6_port = 0,
476 };
477
478 ret = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP,
479 &udp_v6_ctx_1);
480 zassert_equal(ret, 0, "Create IPv6 UDP context failed");
481
482 memcpy(&src_addr6.sin6_addr, &my_addr1, sizeof(struct in6_addr));
483 memcpy(&dst_addr6.sin6_addr, &dst_addr, sizeof(struct in6_addr));
484
485 ret = net_context_bind(udp_v6_ctx_1, (struct sockaddr *)&src_addr6,
486 sizeof(struct sockaddr_in6));
487 zassert_equal(ret, 0, "Context bind failure test failed");
488
489 iface = eth_interfaces[0];
490 ctx = net_if_get_device(iface)->data;
491 zassert_equal_ptr(ð_context_offloading_disabled, ctx,
492 "eth context mismatch");
493
494 test_started = true;
495
496 ret = add_neighbor(iface, &dst_addr);
497 zassert_true(ret, "Cannot add neighbor");
498
499 len = strlen(test_data);
500
501 ret = net_context_sendto(udp_v6_ctx_1, test_data, len,
502 (struct sockaddr *)&dst_addr6,
503 sizeof(struct sockaddr_in6),
504 NULL, K_FOREVER, NULL);
505 zassert_equal(ret, len, "Send UDP pkt failed (%d)\n", ret);
506
507 if (k_sem_take(&wait_data, WAIT_TIME)) {
508 DBG("Timeout while waiting interface data\n");
509 zassert_false(true, "Timeout");
510 }
511
512 net_context_unref(udp_v6_ctx_1);
513 }
514
test_tx_chksum_offload_disabled_test_v4(void)515 static void test_tx_chksum_offload_disabled_test_v4(void)
516 {
517 struct eth_context *ctx; /* This is interface context */
518 struct net_if *iface;
519 int ret, len;
520 struct sockaddr_in dst_addr4 = {
521 .sin_family = AF_INET,
522 .sin_port = htons(TEST_PORT),
523 };
524 struct sockaddr_in src_addr4 = {
525 .sin_family = AF_INET,
526 .sin_port = 0,
527 };
528
529 ret = net_context_get(AF_INET, SOCK_DGRAM, IPPROTO_UDP,
530 &udp_v4_ctx_1);
531 zassert_equal(ret, 0, "Create IPv4 UDP context failed");
532
533 memcpy(&src_addr4.sin_addr, &in4addr_my, sizeof(struct in_addr));
534 memcpy(&dst_addr4.sin_addr, &in4addr_dst, sizeof(struct in_addr));
535
536 ret = net_context_bind(udp_v4_ctx_1, (struct sockaddr *)&src_addr4,
537 sizeof(struct sockaddr_in));
538 zassert_equal(ret, 0, "Context bind failure test failed");
539
540 iface = eth_interfaces[0];
541 ctx = net_if_get_device(iface)->data;
542 zassert_equal_ptr(ð_context_offloading_disabled, ctx,
543 "eth context mismatch");
544
545 len = strlen(test_data);
546
547 test_started = true;
548
549 ret = add_neighbor(iface, &dst_addr);
550 zassert_true(ret, "Cannot add neighbor");
551
552 ret = net_context_sendto(udp_v4_ctx_1, test_data, len,
553 (struct sockaddr *)&dst_addr4,
554 sizeof(struct sockaddr_in),
555 NULL, K_FOREVER, NULL);
556 zassert_equal(ret, len, "Send UDP pkt failed (%d)\n", ret);
557
558 if (k_sem_take(&wait_data, WAIT_TIME)) {
559 DBG("Timeout while waiting interface data\n");
560 zassert_false(true, "Timeout");
561 }
562
563 net_context_unref(udp_v4_ctx_1);
564 }
565
test_tx_chksum_offload_enabled_test_v6(void)566 static void test_tx_chksum_offload_enabled_test_v6(void)
567 {
568 struct eth_context *ctx; /* This is interface context */
569 struct net_if *iface;
570 int ret, len;
571 struct sockaddr_in6 dst_addr6 = {
572 .sin6_family = AF_INET6,
573 .sin6_port = htons(TEST_PORT),
574 };
575 struct sockaddr_in6 src_addr6 = {
576 .sin6_family = AF_INET6,
577 .sin6_port = 0,
578 };
579
580 ret = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP,
581 &udp_v6_ctx_2);
582 zassert_equal(ret, 0, "Create IPv6 UDP context failed");
583
584 memcpy(&src_addr6.sin6_addr, &my_addr2, sizeof(struct in6_addr));
585 memcpy(&dst_addr6.sin6_addr, &dst_addr, sizeof(struct in6_addr));
586
587 ret = net_context_bind(udp_v6_ctx_2, (struct sockaddr *)&src_addr6,
588 sizeof(struct sockaddr_in6));
589 zassert_equal(ret, 0, "Context bind failure test failed");
590
591 iface = eth_interfaces[1];
592 ctx = net_if_get_device(iface)->data;
593 zassert_equal_ptr(ð_context_offloading_enabled, ctx,
594 "eth context mismatch");
595
596 len = strlen(test_data);
597
598 test_started = true;
599
600 ret = add_neighbor(iface, &dst_addr);
601 zassert_true(ret, "Cannot add neighbor");
602
603 ret = net_context_sendto(udp_v6_ctx_2, test_data, len,
604 (struct sockaddr *)&dst_addr6,
605 sizeof(struct sockaddr_in6),
606 NULL, K_FOREVER, NULL);
607 zassert_equal(ret, len, "Send UDP pkt failed (%d)\n", ret);
608
609 if (k_sem_take(&wait_data, WAIT_TIME)) {
610 DBG("Timeout while waiting interface data\n");
611 zassert_false(true, "Timeout");
612 }
613
614 net_context_unref(udp_v6_ctx_2);
615 }
616
test_tx_chksum_offload_enabled_test_v4(void)617 static void test_tx_chksum_offload_enabled_test_v4(void)
618 {
619 struct eth_context *ctx; /* This is interface context */
620 struct net_if *iface;
621 int ret, len;
622 struct sockaddr_in dst_addr4 = {
623 .sin_family = AF_INET,
624 .sin_port = htons(TEST_PORT),
625 };
626 struct sockaddr_in src_addr4 = {
627 .sin_family = AF_INET,
628 .sin_port = 0,
629 };
630
631 ret = net_context_get(AF_INET, SOCK_DGRAM, IPPROTO_UDP,
632 &udp_v4_ctx_2);
633 zassert_equal(ret, 0, "Create IPv4 UDP context failed");
634
635 memcpy(&src_addr4.sin_addr, &in4addr_my2, sizeof(struct in_addr));
636 memcpy(&dst_addr4.sin_addr, &in4addr_dst, sizeof(struct in_addr));
637
638 ret = net_context_bind(udp_v4_ctx_2, (struct sockaddr *)&src_addr4,
639 sizeof(struct sockaddr_in));
640 zassert_equal(ret, 0, "Context bind failure test failed");
641
642 iface = eth_interfaces[1];
643 ctx = net_if_get_device(iface)->data;
644 zassert_equal_ptr(ð_context_offloading_enabled, ctx,
645 "eth context mismatch");
646
647 len = strlen(test_data);
648
649 test_started = true;
650
651 ret = add_neighbor(iface, &dst_addr);
652 zassert_true(ret, "Cannot add neighbor");
653
654 ret = net_context_sendto(udp_v4_ctx_2, test_data, len,
655 (struct sockaddr *)&dst_addr4,
656 sizeof(struct sockaddr_in),
657 NULL, K_FOREVER, NULL);
658 zassert_equal(ret, len, "Send UDP pkt failed (%d)\n", ret);
659
660 if (k_sem_take(&wait_data, WAIT_TIME)) {
661 DBG("Timeout while waiting interface data\n");
662 zassert_false(true, "Timeout");
663 }
664
665 net_context_unref(udp_v4_ctx_2);
666 }
667
recv_cb_offload_disabled(struct net_context * context,struct net_pkt * pkt,union net_ip_header * ip_hdr,union net_proto_header * proto_hdr,int status,void * user_data)668 static void recv_cb_offload_disabled(struct net_context *context,
669 struct net_pkt *pkt,
670 union net_ip_header *ip_hdr,
671 union net_proto_header *proto_hdr,
672 int status,
673 void *user_data)
674 {
675 zassert_not_null(proto_hdr->udp, "UDP header missing");
676 zassert_not_equal(proto_hdr->udp->chksum, 0, "Checksum is not set");
677
678 if (net_pkt_family(pkt) == AF_INET) {
679 struct net_ipv4_hdr *ipv4 = NET_IPV4_HDR(pkt);
680
681 zassert_not_equal(ipv4->chksum, 0,
682 "IPv4 checksum is not set");
683 }
684
685 k_sem_give(&wait_data);
686
687 net_pkt_unref(pkt);
688 }
689
recv_cb_offload_enabled(struct net_context * context,struct net_pkt * pkt,union net_ip_header * ip_hdr,union net_proto_header * proto_hdr,int status,void * user_data)690 static void recv_cb_offload_enabled(struct net_context *context,
691 struct net_pkt *pkt,
692 union net_ip_header *ip_hdr,
693 union net_proto_header *proto_hdr,
694 int status,
695 void *user_data)
696 {
697 zassert_not_null(proto_hdr->udp, "UDP header missing");
698 zassert_equal(proto_hdr->udp->chksum, 0, "Checksum is set");
699
700 if (net_pkt_family(pkt) == AF_INET) {
701 struct net_ipv4_hdr *ipv4 = NET_IPV4_HDR(pkt);
702
703 zassert_equal(ipv4->chksum, 0, "IPv4 checksum is set");
704 }
705
706 k_sem_give(&wait_data);
707
708 net_pkt_unref(pkt);
709 }
710
test_rx_chksum_offload_disabled_test_v6(void)711 static void test_rx_chksum_offload_disabled_test_v6(void)
712 {
713 struct eth_context *ctx; /* This is interface context */
714 struct net_if *iface;
715 int ret, len;
716 struct sockaddr_in6 dst_addr6 = {
717 .sin6_family = AF_INET6,
718 .sin6_port = htons(TEST_PORT),
719 };
720 struct sockaddr_in6 src_addr6 = {
721 .sin6_family = AF_INET6,
722 .sin6_port = 0,
723 };
724
725 ret = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP,
726 &udp_v6_ctx_1);
727 zassert_equal(ret, 0, "Create IPv6 UDP context failed");
728
729 memcpy(&src_addr6.sin6_addr, &my_addr1, sizeof(struct in6_addr));
730 memcpy(&dst_addr6.sin6_addr, &dst_addr, sizeof(struct in6_addr));
731
732 ret = net_context_bind(udp_v6_ctx_1, (struct sockaddr *)&src_addr6,
733 sizeof(struct sockaddr_in6));
734 zassert_equal(ret, 0, "Context bind failure test failed");
735
736 iface = eth_interfaces[0];
737 ctx = net_if_get_device(iface)->data;
738 zassert_equal_ptr(ð_context_offloading_disabled, ctx,
739 "eth context mismatch");
740
741 len = strlen(test_data);
742
743 test_started = true;
744 start_receiving = true;
745
746 ret = net_context_recv(udp_v6_ctx_1, recv_cb_offload_disabled,
747 K_NO_WAIT, NULL);
748 zassert_equal(ret, 0, "Recv UDP failed (%d)\n", ret);
749
750 start_receiving = false;
751
752 ret = net_context_sendto(udp_v6_ctx_1, test_data, len,
753 (struct sockaddr *)&dst_addr6,
754 sizeof(struct sockaddr_in6),
755 NULL, K_FOREVER, NULL);
756 zassert_equal(ret, len, "Send UDP pkt failed (%d)\n", ret);
757
758 if (k_sem_take(&wait_data, WAIT_TIME)) {
759 DBG("Timeout while waiting interface data\n");
760 zassert_false(true, "Timeout");
761 }
762
763 /* Let the receiver to receive the packets */
764 k_sleep(K_MSEC(10));
765 }
766
test_rx_chksum_offload_disabled_test_v4(void)767 static void test_rx_chksum_offload_disabled_test_v4(void)
768 {
769 struct eth_context *ctx; /* This is interface context */
770 struct net_if *iface;
771 int ret, len;
772 struct sockaddr_in dst_addr4 = {
773 .sin_family = AF_INET,
774 .sin_port = htons(TEST_PORT),
775 };
776 struct sockaddr_in src_addr4 = {
777 .sin_family = AF_INET,
778 .sin_port = 0,
779 };
780
781 ret = net_context_get(AF_INET, SOCK_DGRAM, IPPROTO_UDP,
782 &udp_v4_ctx_1);
783 zassert_equal(ret, 0, "Create IPv4 UDP context failed");
784
785 memcpy(&src_addr4.sin_addr, &in4addr_my, sizeof(struct in_addr));
786 memcpy(&dst_addr4.sin_addr, &in4addr_dst, sizeof(struct in_addr));
787
788 ret = net_context_bind(udp_v4_ctx_1, (struct sockaddr *)&src_addr4,
789 sizeof(struct sockaddr_in));
790 zassert_equal(ret, 0, "Context bind failure test failed");
791
792 iface = eth_interfaces[0];
793 ctx = net_if_get_device(iface)->data;
794 zassert_equal_ptr(ð_context_offloading_disabled, ctx,
795 "eth context mismatch");
796
797 len = strlen(test_data);
798
799 test_started = true;
800 start_receiving = true;
801
802 ret = net_context_recv(udp_v4_ctx_1, recv_cb_offload_disabled,
803 K_NO_WAIT, NULL);
804 zassert_equal(ret, 0, "Recv UDP failed (%d)\n", ret);
805
806 start_receiving = false;
807
808 ret = net_context_sendto(udp_v4_ctx_1, test_data, len,
809 (struct sockaddr *)&dst_addr4,
810 sizeof(struct sockaddr_in),
811 NULL, K_FOREVER, NULL);
812 zassert_equal(ret, len, "Send UDP pkt failed (%d)\n", ret);
813
814 if (k_sem_take(&wait_data, WAIT_TIME)) {
815 DBG("Timeout while waiting interface data\n");
816 zassert_false(true, "Timeout");
817 }
818
819 /* Let the receiver to receive the packets */
820 k_sleep(K_MSEC(10));
821 }
822
test_rx_chksum_offload_enabled_test_v6(void)823 static void test_rx_chksum_offload_enabled_test_v6(void)
824 {
825 struct eth_context *ctx; /* This is interface context */
826 struct net_if *iface;
827 int ret, len;
828 struct sockaddr_in6 dst_addr6 = {
829 .sin6_family = AF_INET6,
830 .sin6_port = htons(TEST_PORT),
831 };
832 struct sockaddr_in6 src_addr6 = {
833 .sin6_family = AF_INET6,
834 .sin6_port = 0,
835 };
836
837 ret = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP,
838 &udp_v6_ctx_2);
839 zassert_equal(ret, 0, "Create IPv6 UDP context failed");
840
841 memcpy(&src_addr6.sin6_addr, &my_addr2, sizeof(struct in6_addr));
842 memcpy(&dst_addr6.sin6_addr, &dst_addr, sizeof(struct in6_addr));
843
844 ret = net_context_bind(udp_v6_ctx_2, (struct sockaddr *)&src_addr6,
845 sizeof(struct sockaddr_in6));
846 zassert_equal(ret, 0, "Context bind failure test failed");
847
848 iface = net_if_ipv6_select_src_iface(&dst_addr6.sin6_addr);
849 ctx = net_if_get_device(iface)->data;
850 zassert_equal_ptr(ð_context_offloading_enabled, ctx,
851 "eth context mismatch");
852
853 len = strlen(test_data);
854
855 test_started = true;
856 start_receiving = true;
857
858 ret = net_context_recv(udp_v6_ctx_2, recv_cb_offload_enabled,
859 K_NO_WAIT, NULL);
860 zassert_equal(ret, 0, "Recv UDP failed (%d)\n", ret);
861
862 ret = net_context_sendto(udp_v6_ctx_2, test_data, len,
863 (struct sockaddr *)&dst_addr6,
864 sizeof(struct sockaddr_in6),
865 NULL, K_FOREVER, NULL);
866 zassert_equal(ret, len, "Send UDP pkt failed (%d)\n", ret);
867
868 if (k_sem_take(&wait_data, WAIT_TIME)) {
869 DBG("Timeout while waiting interface data\n");
870 zassert_false(true, "Timeout");
871 }
872
873 /* Let the receiver to receive the packets */
874 k_sleep(K_MSEC(10));
875 }
876
test_rx_chksum_offload_enabled_test_v4(void)877 static void test_rx_chksum_offload_enabled_test_v4(void)
878 {
879 struct eth_context *ctx; /* This is interface context */
880 struct net_if *iface;
881 int ret, len;
882 struct sockaddr_in dst_addr4 = {
883 .sin_family = AF_INET,
884 .sin_port = htons(TEST_PORT),
885 };
886 struct sockaddr_in src_addr4 = {
887 .sin_family = AF_INET,
888 .sin_port = 0,
889 };
890
891 ret = net_context_get(AF_INET, SOCK_DGRAM, IPPROTO_UDP,
892 &udp_v4_ctx_2);
893 zassert_equal(ret, 0, "Create IPv4 UDP context failed");
894
895 memcpy(&src_addr4.sin_addr, &in4addr_my2, sizeof(struct in_addr));
896 memcpy(&dst_addr4.sin_addr, &in4addr_dst, sizeof(struct in_addr));
897
898 ret = net_context_bind(udp_v4_ctx_2, (struct sockaddr *)&src_addr4,
899 sizeof(struct sockaddr_in));
900 zassert_equal(ret, 0, "Context bind failure test failed");
901
902 iface = eth_interfaces[1];
903 ctx = net_if_get_device(iface)->data;
904 zassert_equal_ptr(ð_context_offloading_enabled, ctx,
905 "eth context mismatch");
906
907 len = strlen(test_data);
908
909 test_started = true;
910 start_receiving = true;
911
912 ret = net_context_recv(udp_v4_ctx_2, recv_cb_offload_enabled,
913 K_NO_WAIT, NULL);
914 zassert_equal(ret, 0, "Recv UDP failed (%d)\n", ret);
915
916 ret = net_context_sendto(udp_v4_ctx_2, test_data, len,
917 (struct sockaddr *)&dst_addr4,
918 sizeof(struct sockaddr_in),
919 NULL, K_FOREVER, NULL);
920 zassert_equal(ret, len, "Send UDP pkt failed (%d)\n", ret);
921
922 if (k_sem_take(&wait_data, WAIT_TIME)) {
923 DBG("Timeout while waiting interface data\n");
924 zassert_false(true, "Timeout");
925 }
926
927 /* Let the receiver to receive the packets */
928 k_sleep(K_MSEC(10));
929 }
930
net_chksum_offload_tests_setup(void)931 static void *net_chksum_offload_tests_setup(void)
932 {
933 test_eth_setup();
934 test_address_setup();
935 return NULL;
936 }
937
ZTEST(net_chksum_offload,test_chksum_offload_disabled_v4)938 ZTEST(net_chksum_offload, test_chksum_offload_disabled_v4)
939 {
940 test_tx_chksum_offload_disabled_test_v4();
941 test_rx_chksum_offload_disabled_test_v4();
942 }
943
ZTEST(net_chksum_offload,test_chksum_offload_enabled_v4)944 ZTEST(net_chksum_offload, test_chksum_offload_enabled_v4)
945 {
946 test_tx_chksum_offload_enabled_test_v4();
947 test_rx_chksum_offload_enabled_test_v4();
948 }
949
ZTEST(net_chksum_offload,test_chksum_offload_disabled_v6)950 ZTEST(net_chksum_offload, test_chksum_offload_disabled_v6)
951 {
952 test_tx_chksum_offload_disabled_test_v6();
953 test_rx_chksum_offload_disabled_test_v6();
954 }
955
ZTEST(net_chksum_offload,test_chksum_offload_enabled_v6)956 ZTEST(net_chksum_offload, test_chksum_offload_enabled_v6)
957 {
958 test_tx_chksum_offload_enabled_test_v6();
959 test_rx_chksum_offload_enabled_test_v6();
960 }
961
962 ZTEST_SUITE(net_chksum_offload, NULL, net_chksum_offload_tests_setup, NULL, NULL, NULL);
963