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(&eth_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(&eth_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 		    &eth_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 		    &eth_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 == &eth_context_offloading_disabled) {
345 			DBG("Iface %p without offloading\n", iface);
346 			eth_interfaces[0] = iface;
347 		}
348 
349 		if (eth_ctx == &eth_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(&eth_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(&eth_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(&eth_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(&eth_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(&eth_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(&eth_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(&eth_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(&eth_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