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 static uint8_t test_data_large[2000];
47 static uint8_t verify_buf[2000];
48 
49 /* Interface 1 addresses */
50 static struct in6_addr my_addr1 = { { { 0x20, 0x01, 0x0d, 0xb8, 1, 0, 0, 0,
51 					0, 0, 0, 0, 0, 0, 0, 0x1 } } };
52 
53 /* Interface 2 addresses */
54 static struct in6_addr my_addr2 = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
55 					0, 0, 0, 0, 0, 0, 0, 0x1 } } };
56 
57 /* Destination address for test packets (interface 1) */
58 static struct in6_addr dst_addr1 = { { { 0x20, 0x01, 0x0d, 0xb8, 1, 0, 0, 0,
59 					 0, 0, 0, 0, 0, 0, 0, 0x2 } } };
60 
61 /* Destination address for test packets (interface 2) */
62 static struct in6_addr dst_addr2 = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
63 					 0, 0, 0, 0, 0, 0, 0, 0x2 } } };
64 
65 /* Extra address is assigned to ll_addr */
66 static struct in6_addr ll_addr = { { { 0xfe, 0x80, 0x43, 0xb8, 0, 0, 0, 0,
67 				       0, 0, 0, 0xf2, 0xaa, 0x29, 0x02,
68 				       0x04 } } };
69 
70 static struct in_addr in4addr_my = { { { 192, 0, 2, 1 } } };
71 static struct in_addr in4addr_dst = { { { 192, 0, 2, 2 } } };
72 static struct in_addr in4addr_my2 = { { { 192, 0, 42, 1 } } };
73 static struct in_addr in4addr_dst2 = { { { 192, 0, 42, 2 } } };
74 
75 /* Keep track of all ethernet interfaces. For native_sim board, we need
76  * to increase the count as it has one extra network interface defined in
77  * eth_native_posix driver.
78  */
79 static struct net_if *eth_interfaces[2 + IS_ENABLED(CONFIG_ETH_NATIVE_POSIX)];
80 
81 static bool test_failed;
82 static bool test_started;
83 static int test_proto;
84 static bool verify_fragment;
85 static bool start_receiving;
86 static bool change_chksum;
87 static int fragment_count;
88 static int fragment_offset;
89 
90 static K_SEM_DEFINE(wait_data_off, 0, UINT_MAX);
91 static K_SEM_DEFINE(wait_data_nonoff, 0, UINT_MAX);
92 
93 #define WAIT_TIME K_MSEC(100)
94 
95 struct eth_context {
96 	struct net_if *iface;
97 	uint8_t mac_addr[6];
98 
99 	uint16_t expecting_tag;
100 };
101 
102 static struct eth_context eth_context_offloading_disabled;
103 static struct eth_context eth_context_offloading_enabled;
104 
verify_test_data_large(uint8_t * buf,size_t offset,size_t len)105 static void verify_test_data_large(uint8_t *buf, size_t offset, size_t len)
106 {
107 	zassert(offset + len <= sizeof(test_data_large), "Out of bound data");
108 
109 	for (size_t i = 0; i < len; i++) {
110 		zassert_equal(buf[i], test_data_large[offset + i], "Invalid data");
111 	}
112 }
113 
eth_iface_init(struct net_if * iface)114 static void eth_iface_init(struct net_if *iface)
115 {
116 	const struct device *dev = net_if_get_device(iface);
117 	struct eth_context *context = dev->data;
118 
119 	net_if_set_link_addr(iface, context->mac_addr,
120 			     sizeof(context->mac_addr),
121 			     NET_LINK_ETHERNET);
122 
123 	DBG("Iface %p addr %s\n", iface,
124 	    net_sprint_ll_addr(context->mac_addr, sizeof(context->mac_addr)));
125 
126 	ethernet_init(iface);
127 }
128 
get_udp_chksum(struct net_pkt * pkt)129 static uint16_t get_udp_chksum(struct net_pkt *pkt)
130 {
131 	NET_PKT_DATA_ACCESS_DEFINE(udp_access, struct net_udp_hdr);
132 	struct net_udp_hdr *udp_hdr;
133 	struct net_pkt_cursor backup;
134 
135 	net_pkt_set_overwrite(pkt, true);
136 	net_pkt_cursor_backup(pkt, &backup);
137 	net_pkt_cursor_init(pkt);
138 
139 	/* Let's move the cursor to UDP header */
140 	if (net_pkt_skip(pkt, sizeof(struct net_eth_hdr) +
141 			 net_pkt_ip_hdr_len(pkt) +
142 			 net_pkt_ipv6_ext_len(pkt))) {
143 		return 0;
144 	}
145 
146 	udp_hdr = (struct net_udp_hdr *)net_pkt_get_data(pkt, &udp_access);
147 	if (!udp_hdr) {
148 		return 0;
149 	}
150 
151 	net_pkt_cursor_restore(pkt, &backup);
152 
153 	return udp_hdr->chksum;
154 }
155 
get_icmp_chksum(struct net_pkt * pkt)156 static uint16_t get_icmp_chksum(struct net_pkt *pkt)
157 {
158 	NET_PKT_DATA_ACCESS_DEFINE(icmp_access, struct net_icmp_hdr);
159 	struct net_icmp_hdr *icmp_hdr;
160 	struct net_pkt_cursor backup;
161 
162 	net_pkt_set_overwrite(pkt, true);
163 	net_pkt_cursor_backup(pkt, &backup);
164 	net_pkt_cursor_init(pkt);
165 
166 	/* Move the cursor to the ICMP header */
167 	if (net_pkt_skip(pkt, sizeof(struct net_eth_hdr) +
168 			 net_pkt_ip_hdr_len(pkt) +
169 			 net_pkt_ipv6_ext_len(pkt))) {
170 		return 0;
171 	}
172 
173 	icmp_hdr = (struct net_icmp_hdr *)net_pkt_get_data(pkt, &icmp_access);
174 	if (!icmp_hdr) {
175 		return 0;
176 	}
177 
178 	net_pkt_cursor_restore(pkt, &backup);
179 
180 	return icmp_hdr->chksum;
181 }
182 
test_receiving(struct net_pkt * pkt)183 static void test_receiving(struct net_pkt *pkt)
184 {
185 	uint16_t port;
186 	uint8_t lladdr[6];
187 
188 	DBG("Packet %p received\n", pkt);
189 
190 	memcpy(lladdr, ((struct net_eth_hdr *)net_pkt_data(pkt))->src.addr,
191 	       sizeof(lladdr));
192 	memcpy(((struct net_eth_hdr *)net_pkt_data(pkt))->src.addr,
193 	       ((struct net_eth_hdr *)net_pkt_data(pkt))->dst.addr,
194 	       sizeof(lladdr));
195 	memcpy(((struct net_eth_hdr *)net_pkt_data(pkt))->dst.addr,
196 	       lladdr, sizeof(lladdr));
197 
198 	net_pkt_skip(pkt, sizeof(struct net_eth_hdr));
199 
200 	/* Swap IP src and destination address so that we can receive
201 	 * the packet and the stack will not reject it.
202 	 */
203 	if (net_pkt_family(pkt) == AF_INET6) {
204 		NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv6_access,
205 						      struct net_ipv6_hdr);
206 		struct net_ipv6_hdr *ipv6_hdr;
207 		struct in6_addr addr;
208 
209 		ipv6_hdr = (struct net_ipv6_hdr *)
210 					net_pkt_get_data(pkt, &ipv6_access);
211 		zassert_not_null(ipv6_hdr, "Can't access IPv6 header");
212 
213 		net_ipv6_addr_copy_raw((uint8_t *)&addr, ipv6_hdr->src);
214 		net_ipv6_addr_copy_raw(ipv6_hdr->src, ipv6_hdr->dst);
215 		net_ipv6_addr_copy_raw(ipv6_hdr->dst, (uint8_t *)&addr);
216 	} else {
217 		NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv4_access,
218 						      struct net_ipv4_hdr);
219 		struct net_ipv4_hdr *ipv4_hdr;
220 		struct in_addr addr;
221 
222 		ipv4_hdr = (struct net_ipv4_hdr *)
223 					net_pkt_get_data(pkt, &ipv4_access);
224 		zassert_not_null(ipv4_hdr, "Can't access IPv4 header");
225 
226 		net_ipv4_addr_copy_raw((uint8_t *)&addr, ipv4_hdr->src);
227 		net_ipv4_addr_copy_raw(ipv4_hdr->src, ipv4_hdr->dst);
228 		net_ipv4_addr_copy_raw(ipv4_hdr->dst, (uint8_t *)&addr);
229 	}
230 
231 	if (!verify_fragment || fragment_count == 1) {
232 		net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt) + net_pkt_ip_opts_len(pkt));
233 		if (test_proto == IPPROTO_UDP) {
234 			NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(
235 					udp_access, struct net_udp_hdr);
236 			struct net_udp_hdr *udp_hdr;
237 
238 			udp_hdr = (struct net_udp_hdr *)
239 					net_pkt_get_data(pkt, &udp_access);
240 			zassert_not_null(udp_hdr, "Can't access UDP header");
241 
242 			port = udp_hdr->src_port;
243 			udp_hdr->src_port = udp_hdr->dst_port;
244 			udp_hdr->dst_port = port;
245 
246 			if (change_chksum) {
247 				udp_hdr->chksum++;
248 			}
249 		} else if (test_proto == IPPROTO_ICMP ||
250 			   test_proto == IPPROTO_ICMPV6) {
251 			NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(
252 					icmp_access, struct net_icmp_hdr);
253 			struct net_icmp_hdr *icmp_hdr;
254 
255 			icmp_hdr = (struct net_icmp_hdr *)
256 					net_pkt_get_data(pkt, &icmp_access);
257 			zassert_not_null(icmp_hdr, "Can't access ICMP header");
258 
259 			if (change_chksum) {
260 				icmp_hdr->chksum++;
261 			}
262 		}
263 	}
264 
265 	net_pkt_cursor_init(pkt);
266 
267 	if (net_recv_data(net_pkt_iface(pkt),
268 			  net_pkt_rx_clone(pkt, K_NO_WAIT)) < 0) {
269 		test_failed = true;
270 		zassert_true(false, "Packet %p receive failed\n", pkt);
271 	}
272 }
273 
test_fragment(struct net_pkt * pkt,bool offloaded)274 static void test_fragment(struct net_pkt *pkt, bool offloaded)
275 {
276 	uint16_t chksum = 0;
277 	size_t data_len;
278 	size_t hdr_offset = sizeof(struct net_eth_hdr) +
279 			    net_pkt_ip_hdr_len(pkt) +
280 			    net_pkt_ip_opts_len(pkt);
281 
282 	fragment_count++;
283 
284 	net_pkt_set_overwrite(pkt, true);
285 	net_pkt_cursor_init(pkt);
286 
287 	if (start_receiving) {
288 		test_receiving(pkt);
289 		return;
290 	}
291 
292 	if (fragment_count == 1) {
293 		if (test_proto == IPPROTO_UDP) {
294 			chksum = get_udp_chksum(pkt);
295 			hdr_offset += sizeof(struct net_udp_hdr);
296 		} else if (test_proto == IPPROTO_ICMP ||
297 			   test_proto == IPPROTO_ICMPV6) {
298 			chksum = get_icmp_chksum(pkt);
299 			hdr_offset += sizeof(struct net_icmp_hdr) +
300 				      sizeof(struct net_icmpv6_echo_req);
301 		}
302 
303 		/* Fragmented packet should have checksum set regardless of
304 		 * checksum offloading
305 		 */
306 		zassert_not_equal(chksum, 0, "Checksum missing");
307 	}
308 
309 	zassert_true(net_pkt_is_chksum_done(pkt),
310 		     "Checksum should me marked as ready on net_pkt");
311 
312 	/* Verify that payload has not been altered. */
313 	data_len = net_pkt_get_len(pkt) - hdr_offset;
314 	net_pkt_skip(pkt, hdr_offset);
315 	net_pkt_read(pkt, verify_buf, data_len);
316 
317 	verify_test_data_large(verify_buf, fragment_offset, data_len);
318 	fragment_offset += data_len;
319 
320 	if (fragment_count > 1) {
321 		if (offloaded) {
322 			k_sem_give(&wait_data_off);
323 		} else {
324 			k_sem_give(&wait_data_nonoff);
325 		}
326 	}
327 }
328 
eth_tx_offloading_disabled(const struct device * dev,struct net_pkt * pkt)329 static int eth_tx_offloading_disabled(const struct device *dev,
330 				      struct net_pkt *pkt)
331 {
332 	struct eth_context *context = dev->data;
333 
334 	zassert_equal_ptr(&eth_context_offloading_disabled, context,
335 			  "Context pointers do not match (%p vs %p)",
336 			  eth_context_offloading_disabled, context);
337 
338 	if (!pkt->buffer) {
339 		DBG("No data to send!\n");
340 		return -ENODATA;
341 	}
342 
343 	if (verify_fragment) {
344 		test_fragment(pkt, false);
345 		return 0;
346 	}
347 
348 	if (start_receiving) {
349 		test_receiving(pkt);
350 		return 0;
351 	}
352 
353 	if (test_started) {
354 		uint16_t chksum = 0;
355 
356 		if (test_proto == IPPROTO_UDP) {
357 			chksum = get_udp_chksum(pkt);
358 		} else if (test_proto == IPPROTO_ICMP ||
359 			   test_proto == IPPROTO_ICMPV6) {
360 			chksum = get_icmp_chksum(pkt);
361 		}
362 
363 		DBG("Chksum 0x%x offloading disabled\n", chksum);
364 
365 		zassert_not_equal(chksum, 0, "Checksum not calculated");
366 
367 		k_sem_give(&wait_data_nonoff);
368 	}
369 
370 	return 0;
371 }
372 
eth_tx_offloading_enabled(const struct device * dev,struct net_pkt * pkt)373 static int eth_tx_offloading_enabled(const struct device *dev,
374 				     struct net_pkt *pkt)
375 {
376 	struct eth_context *context = dev->data;
377 
378 	zassert_equal_ptr(&eth_context_offloading_enabled, context,
379 			  "Context pointers do not match (%p vs %p)",
380 			  eth_context_offloading_enabled, context);
381 
382 	if (!pkt->buffer) {
383 		DBG("No data to send!\n");
384 		return -ENODATA;
385 	}
386 
387 	if (verify_fragment) {
388 		test_fragment(pkt, true);
389 		return 0;
390 	}
391 
392 	if (start_receiving) {
393 		test_receiving(pkt);
394 	}
395 
396 	if (test_started) {
397 		uint16_t chksum = 0;
398 
399 		if (test_proto == IPPROTO_UDP) {
400 			chksum = get_udp_chksum(pkt);
401 		} else if (test_proto == IPPROTO_ICMP ||
402 			   test_proto == IPPROTO_ICMPV6) {
403 			chksum = get_icmp_chksum(pkt);
404 		}
405 
406 		DBG("Chksum 0x%x offloading enabled\n", chksum);
407 
408 		zassert_equal(chksum, 0, "Checksum calculated");
409 
410 		k_sem_give(&wait_data_off);
411 	}
412 
413 	return 0;
414 }
415 
eth_offloading_enabled(const struct device * dev)416 static enum ethernet_hw_caps eth_offloading_enabled(const struct device *dev)
417 {
418 	return ETHERNET_HW_TX_CHKSUM_OFFLOAD |
419 		ETHERNET_HW_RX_CHKSUM_OFFLOAD;
420 }
421 
eth_offloading_disabled(const struct device * dev)422 static enum ethernet_hw_caps eth_offloading_disabled(const struct device *dev)
423 {
424 	return 0;
425 }
426 
427 static struct ethernet_api api_funcs_offloading_disabled = {
428 	.iface_api.init = eth_iface_init,
429 
430 	.get_capabilities = eth_offloading_disabled,
431 	.send = eth_tx_offloading_disabled,
432 };
433 
434 static struct ethernet_api api_funcs_offloading_enabled = {
435 	.iface_api.init = eth_iface_init,
436 
437 	.get_capabilities = eth_offloading_enabled,
438 	.send = eth_tx_offloading_enabled,
439 };
440 
generate_mac(uint8_t * mac_addr)441 static void generate_mac(uint8_t *mac_addr)
442 {
443 	/* 00-00-5E-00-53-xx Documentation RFC 7042 */
444 	mac_addr[0] = 0x00;
445 	mac_addr[1] = 0x00;
446 	mac_addr[2] = 0x5E;
447 	mac_addr[3] = 0x00;
448 	mac_addr[4] = 0x53;
449 	mac_addr[5] = sys_rand8_get();
450 }
451 
eth_init(const struct device * dev)452 static int eth_init(const struct device *dev)
453 {
454 	struct eth_context *context = dev->data;
455 
456 	generate_mac(context->mac_addr);
457 
458 	return 0;
459 }
460 
461 ETH_NET_DEVICE_INIT(eth1_offloading_disabled_test,
462 		    "eth1_offloading_disabled_test",
463 		    eth_init, NULL,
464 		    &eth_context_offloading_disabled, NULL,
465 		    CONFIG_ETH_INIT_PRIORITY,
466 		    &api_funcs_offloading_disabled,
467 		    NET_ETH_MTU);
468 
469 ETH_NET_DEVICE_INIT(eth0_offloading_enabled_test,
470 		    "eth0_offloading_enabled_test",
471 		    eth_init, NULL,
472 		    &eth_context_offloading_enabled, NULL,
473 		    CONFIG_ETH_INIT_PRIORITY,
474 		    &api_funcs_offloading_enabled,
475 		    NET_ETH_MTU);
476 
477 struct user_data {
478 	int eth_if_count;
479 	int total_if_count;
480 };
481 
482 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
iface2str(struct net_if * iface)483 static const char *iface2str(struct net_if *iface)
484 {
485 #ifdef CONFIG_NET_L2_ETHERNET
486 	if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
487 		return "Ethernet";
488 	}
489 #endif
490 
491 #ifdef CONFIG_NET_L2_DUMMY
492 	if (net_if_l2(iface) == &NET_L2_GET_NAME(DUMMY)) {
493 		return "Dummy";
494 	}
495 #endif
496 
497 	return "<unknown type>";
498 }
499 #endif
500 
iface_cb(struct net_if * iface,void * user_data)501 static void iface_cb(struct net_if *iface, void *user_data)
502 {
503 	struct user_data *ud = user_data;
504 
505 	DBG("Interface %p (%s) [%d]\n", iface, iface2str(iface),
506 	    net_if_get_by_iface(iface));
507 
508 	if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
509 		struct eth_context *eth_ctx =
510 			net_if_get_device(iface)->data;
511 
512 		if (eth_ctx == &eth_context_offloading_disabled) {
513 			DBG("Iface %p without offloading\n", iface);
514 			eth_interfaces[0] = iface;
515 		}
516 
517 		if (eth_ctx == &eth_context_offloading_enabled) {
518 			DBG("Iface %p with offloading\n", iface);
519 			eth_interfaces[1] = iface;
520 		}
521 
522 		ud->eth_if_count++;
523 	}
524 
525 	/* By default all interfaces are down initially */
526 	net_if_down(iface);
527 
528 	ud->total_if_count++;
529 }
530 
test_eth_setup(void)531 static void test_eth_setup(void)
532 {
533 	struct user_data ud = { 0 };
534 
535 	/* Make sure we have enough virtual interfaces */
536 	net_if_foreach(iface_cb, &ud);
537 
538 	zassert_equal(ud.eth_if_count, sizeof(eth_interfaces) / sizeof(void *),
539 		      "Invalid number of interfaces (%d vs %d)\n",
540 		      ud.eth_if_count,
541 		      sizeof(eth_interfaces) / sizeof(void *));
542 }
543 
test_address_setup(void)544 static void test_address_setup(void)
545 {
546 	struct in_addr netmask = { { { 255, 255, 255, 0 } } };
547 	struct net_if_addr *ifaddr;
548 	struct net_if *iface1, *iface2;
549 
550 	iface1 = eth_interfaces[0];
551 	iface2 = eth_interfaces[1];
552 
553 	zassert_not_null(iface1, "Interface 1");
554 	zassert_not_null(iface2, "Interface 2");
555 
556 	ifaddr = net_if_ipv6_addr_add(iface1, &my_addr1,
557 				      NET_ADDR_MANUAL, 0);
558 	if (!ifaddr) {
559 		DBG("Cannot add IPv6 address %s\n",
560 		       net_sprint_ipv6_addr(&my_addr1));
561 		zassert_not_null(ifaddr, "addr1");
562 	}
563 
564 	/* For testing purposes we need to set the addresses preferred */
565 	ifaddr->addr_state = NET_ADDR_PREFERRED;
566 
567 	ifaddr = net_if_ipv6_addr_add(iface1, &ll_addr,
568 				      NET_ADDR_MANUAL, 0);
569 	if (!ifaddr) {
570 		DBG("Cannot add IPv6 address %s\n",
571 		       net_sprint_ipv6_addr(&ll_addr));
572 		zassert_not_null(ifaddr, "ll_addr");
573 	}
574 
575 	ifaddr->addr_state = NET_ADDR_PREFERRED;
576 
577 	ifaddr = net_if_ipv4_addr_add(iface1, &in4addr_my,
578 				      NET_ADDR_MANUAL, 0);
579 	zassert_not_null(ifaddr, "Cannot add IPv4 address");
580 
581 	net_if_ipv4_set_netmask_by_addr(iface1, &in4addr_my, &netmask);
582 
583 	ifaddr = net_if_ipv6_addr_add(iface2, &my_addr2,
584 				      NET_ADDR_MANUAL, 0);
585 	if (!ifaddr) {
586 		DBG("Cannot add IPv6 address %s\n",
587 		       net_sprint_ipv6_addr(&my_addr2));
588 		zassert_not_null(ifaddr, "addr2");
589 	}
590 
591 	ifaddr->addr_state = NET_ADDR_PREFERRED;
592 
593 	ifaddr = net_if_ipv4_addr_add(iface2, &in4addr_my2,
594 				      NET_ADDR_MANUAL, 0);
595 	zassert_not_null(ifaddr, "Cannot add IPv4 address");
596 
597 	net_if_ipv4_set_netmask_by_addr(iface2, &in4addr_my2, &netmask);
598 
599 	net_if_up(iface1);
600 	net_if_up(iface2);
601 
602 	/* The interface might receive data which might fail the checks
603 	 * in the iface sending function, so we need to reset the failure
604 	 * flag.
605 	 */
606 	test_failed = false;
607 }
608 
add_neighbor(struct net_if * iface,struct in6_addr * addr)609 static void add_neighbor(struct net_if *iface, struct in6_addr *addr)
610 {
611 	struct net_linkaddr_storage llstorage;
612 	struct net_linkaddr lladdr;
613 	struct net_nbr *nbr;
614 
615 	llstorage.addr[0] = 0x01;
616 	llstorage.addr[1] = 0x02;
617 	llstorage.addr[2] = 0x33;
618 	llstorage.addr[3] = 0x44;
619 	llstorage.addr[4] = 0x05;
620 	llstorage.addr[5] = 0x06;
621 
622 	lladdr.len = 6U;
623 	lladdr.addr = llstorage.addr;
624 	lladdr.type = NET_LINK_ETHERNET;
625 
626 	nbr = net_ipv6_nbr_add(iface, addr, &lladdr, false,
627 			       NET_IPV6_NBR_STATE_REACHABLE);
628 	if (!nbr) {
629 		DBG("Cannot add dst %s to neighbor cache\n",
630 		    net_sprint_ipv6_addr(addr));
631 	}
632 }
633 
test_udp_context_prepare(sa_family_t family,bool offloaded,struct sockaddr * dst_addr)634 static struct net_context *test_udp_context_prepare(sa_family_t family,
635 						    bool offloaded,
636 						    struct sockaddr *dst_addr)
637 {
638 	struct net_context *net_ctx;
639 	struct eth_context *ctx; /* This is interface context */
640 	struct sockaddr src_addr;
641 	socklen_t addrlen;
642 	struct net_if *iface;
643 	int ret;
644 
645 	if (family == AF_INET6) {
646 		struct sockaddr_in6 *dst_addr6 =
647 					(struct sockaddr_in6 *)dst_addr;
648 		struct sockaddr_in6 *src_addr6 =
649 					(struct sockaddr_in6 *)&src_addr;
650 
651 		dst_addr6->sin6_family = AF_INET6;
652 		dst_addr6->sin6_port = htons(TEST_PORT);
653 		src_addr6->sin6_family = AF_INET6;
654 		src_addr6->sin6_port = 0;
655 
656 		if (offloaded) {
657 			memcpy(&src_addr6->sin6_addr, &my_addr2,
658 			       sizeof(struct in6_addr));
659 			memcpy(&dst_addr6->sin6_addr, &dst_addr2,
660 			       sizeof(struct in6_addr));
661 		} else {
662 			memcpy(&src_addr6->sin6_addr, &my_addr1,
663 			       sizeof(struct in6_addr));
664 			memcpy(&dst_addr6->sin6_addr, &dst_addr1,
665 			       sizeof(struct in6_addr));
666 		}
667 
668 		addrlen = sizeof(struct sockaddr_in6);
669 	} else {
670 		struct sockaddr_in *dst_addr4 =
671 					(struct sockaddr_in *)dst_addr;
672 		struct sockaddr_in *src_addr4 =
673 					(struct sockaddr_in *)&src_addr;
674 
675 		dst_addr4->sin_family = AF_INET;
676 		dst_addr4->sin_port = htons(TEST_PORT);
677 		src_addr4->sin_family = AF_INET;
678 		src_addr4->sin_port = 0;
679 
680 		if (offloaded) {
681 			memcpy(&src_addr4->sin_addr, &in4addr_my2,
682 			       sizeof(struct in_addr));
683 			memcpy(&dst_addr4->sin_addr, &in4addr_dst2,
684 			       sizeof(struct in_addr));
685 		} else {
686 			memcpy(&src_addr4->sin_addr, &in4addr_my,
687 			       sizeof(struct in_addr));
688 			memcpy(&dst_addr4->sin_addr, &in4addr_dst,
689 			       sizeof(struct in_addr));
690 		}
691 
692 		addrlen = sizeof(struct sockaddr_in6);
693 	}
694 
695 	ret = net_context_get(family, SOCK_DGRAM, IPPROTO_UDP, &net_ctx);
696 	zassert_equal(ret, 0, "Create %s UDP context failed",
697 		      family == AF_INET6 ? "IPv6" : "IPv4");
698 
699 	ret = net_context_bind(net_ctx, &src_addr, addrlen);
700 	zassert_equal(ret, 0, "Context bind failure test failed");
701 
702 	/* Verify iface data */
703 	if (offloaded) {
704 		iface = eth_interfaces[1];
705 		ctx = net_if_get_device(iface)->data;
706 		zassert_equal_ptr(&eth_context_offloading_enabled, ctx,
707 				  "eth context mismatch");
708 	} else {
709 		iface = eth_interfaces[0];
710 		ctx = net_if_get_device(iface)->data;
711 		zassert_equal_ptr(&eth_context_offloading_disabled, ctx,
712 				  "eth context mismatch");
713 	}
714 
715 	return net_ctx;
716 }
717 
test_tx_chksum(sa_family_t family,bool offloaded)718 static void test_tx_chksum(sa_family_t family, bool offloaded)
719 {
720 	struct k_sem *wait_data = offloaded ? &wait_data_off : &wait_data_nonoff;
721 	socklen_t addrlen = (family == AF_INET6) ? sizeof(struct sockaddr_in6) :
722 						   sizeof(struct sockaddr_in);
723 	struct net_context *net_ctx;
724 	struct sockaddr dst_addr;
725 	int ret, len;
726 
727 	net_ctx = test_udp_context_prepare(family, offloaded, &dst_addr);
728 	zassert_not_null(net_ctx, "Failed to obtain net_ctx");
729 
730 	test_started = true;
731 	test_proto = IPPROTO_UDP;
732 
733 	len = strlen(test_data);
734 	ret = net_context_sendto(net_ctx, test_data, len, &dst_addr,
735 				 addrlen, NULL, K_FOREVER, NULL);
736 	zassert_equal(ret, len, "Send UDP pkt failed (%d)\n", ret);
737 
738 	if (k_sem_take(wait_data, WAIT_TIME)) {
739 		DBG("Timeout while waiting interface data\n");
740 		zassert_false(true, "Timeout");
741 	}
742 
743 	net_context_unref(net_ctx);
744 }
745 
ZTEST(net_chksum_offload,test_tx_chksum_offload_disabled_test_v6)746 ZTEST(net_chksum_offload, test_tx_chksum_offload_disabled_test_v6)
747 {
748 	test_tx_chksum(AF_INET6, false);
749 }
750 
ZTEST(net_chksum_offload,test_tx_chksum_offload_disabled_test_v4)751 ZTEST(net_chksum_offload, test_tx_chksum_offload_disabled_test_v4)
752 {
753 	test_tx_chksum(AF_INET, false);
754 }
755 
ZTEST(net_chksum_offload,test_tx_chksum_offload_enabled_test_v6)756 ZTEST(net_chksum_offload, test_tx_chksum_offload_enabled_test_v6)
757 {
758 	test_tx_chksum(AF_INET6, true);
759 }
760 
ZTEST(net_chksum_offload,test_tx_chksum_offload_enabled_test_v4)761 ZTEST(net_chksum_offload, test_tx_chksum_offload_enabled_test_v4)
762 {
763 	test_tx_chksum(AF_INET, true);
764 }
765 
test_tx_chksum_udp_frag(sa_family_t family,bool offloaded)766 static void test_tx_chksum_udp_frag(sa_family_t family, bool offloaded)
767 {
768 	struct k_sem *wait_data = offloaded ? &wait_data_off : &wait_data_nonoff;
769 	socklen_t addrlen = (family == AF_INET6) ? sizeof(struct sockaddr_in6) :
770 						   sizeof(struct sockaddr_in);
771 	struct net_context *net_ctx;
772 	struct sockaddr dst_addr;
773 	int ret, len;
774 
775 	net_ctx = test_udp_context_prepare(family, offloaded, &dst_addr);
776 	zassert_not_null(net_ctx, "Failed to obtain net_ctx");
777 
778 	test_started = true;
779 	test_proto = IPPROTO_UDP;
780 	verify_fragment = true;
781 
782 	len = sizeof(test_data_large);
783 	ret = net_context_sendto(net_ctx, test_data_large, len, &dst_addr,
784 				 addrlen, NULL, K_FOREVER, NULL);
785 	zassert_equal(ret, len, "Send UDP pkt failed (%d)\n", ret);
786 
787 	if (k_sem_take(wait_data, WAIT_TIME)) {
788 		DBG("Timeout while waiting interface data\n");
789 		zassert_false(true, "Timeout");
790 	}
791 
792 	net_context_unref(net_ctx);
793 }
794 
ZTEST(net_chksum_offload,test_tx_chksum_offload_disabled_test_v6_udp_frag)795 ZTEST(net_chksum_offload, test_tx_chksum_offload_disabled_test_v6_udp_frag)
796 {
797 	test_tx_chksum_udp_frag(AF_INET6, false);
798 }
799 
ZTEST(net_chksum_offload,test_tx_chksum_offload_disabled_test_v4_udp_frag)800 ZTEST(net_chksum_offload, test_tx_chksum_offload_disabled_test_v4_udp_frag)
801 {
802 	test_tx_chksum_udp_frag(AF_INET, false);
803 }
804 
ZTEST(net_chksum_offload,test_tx_chksum_offload_enabled_test_v6_udp_frag)805 ZTEST(net_chksum_offload, test_tx_chksum_offload_enabled_test_v6_udp_frag)
806 {
807 	test_tx_chksum_udp_frag(AF_INET6, true);
808 }
809 
ZTEST(net_chksum_offload,test_tx_chksum_offload_enabled_test_v4_udp_frag)810 ZTEST(net_chksum_offload, test_tx_chksum_offload_enabled_test_v4_udp_frag)
811 {
812 	test_tx_chksum_udp_frag(AF_INET, true);
813 }
814 
dummy_icmp_handler(struct net_icmp_ctx * ctx,struct net_pkt * pkt,struct net_icmp_ip_hdr * hdr,struct net_icmp_hdr * icmp_hdr,void * user_data)815 static int dummy_icmp_handler(struct net_icmp_ctx *ctx,
816 			      struct net_pkt *pkt,
817 			      struct net_icmp_ip_hdr *hdr,
818 			      struct net_icmp_hdr *icmp_hdr,
819 			      void *user_data)
820 {
821 	ARG_UNUSED(ctx);
822 	ARG_UNUSED(pkt);
823 	ARG_UNUSED(hdr);
824 	ARG_UNUSED(icmp_hdr);
825 	ARG_UNUSED(user_data);
826 
827 	return 0;
828 }
829 
test_icmp_init(sa_family_t family,bool offloaded,struct sockaddr * dst_addr,struct net_if ** iface)830 static void test_icmp_init(sa_family_t family, bool offloaded,
831 			   struct sockaddr *dst_addr, struct net_if **iface)
832 {
833 	if (family == AF_INET6) {
834 		struct sockaddr_in6 *dst_addr6 =
835 					(struct sockaddr_in6 *)dst_addr;
836 
837 		dst_addr6->sin6_family = AF_INET6;
838 
839 		if (offloaded) {
840 			memcpy(&dst_addr6->sin6_addr, &dst_addr2,
841 			       sizeof(struct in6_addr));
842 		} else {
843 			memcpy(&dst_addr6->sin6_addr, &dst_addr1,
844 			       sizeof(struct in6_addr));
845 		}
846 	} else {
847 		struct sockaddr_in *dst_addr4 =
848 					(struct sockaddr_in *)dst_addr;
849 
850 		dst_addr4->sin_family = AF_INET;
851 
852 		if (offloaded) {
853 			memcpy(&dst_addr4->sin_addr, &in4addr_dst2,
854 			       sizeof(struct in_addr));
855 		} else {
856 			memcpy(&dst_addr4->sin_addr, &in4addr_dst,
857 			       sizeof(struct in_addr));
858 		}
859 	}
860 
861 	if (offloaded) {
862 		*iface = eth_interfaces[1];
863 	} else {
864 		*iface = eth_interfaces[0];
865 	}
866 }
867 
test_tx_chksum_icmp_frag(sa_family_t family,bool offloaded)868 static void test_tx_chksum_icmp_frag(sa_family_t family, bool offloaded)
869 {
870 	struct k_sem *wait_data = offloaded ? &wait_data_off : &wait_data_nonoff;
871 	struct net_icmp_ping_params params = { 0 };
872 	struct net_icmp_ctx ctx;
873 	struct sockaddr dst_addr;
874 	struct net_if *iface;
875 	int ret;
876 
877 	test_icmp_init(family, offloaded, &dst_addr, &iface);
878 
879 	ret = net_icmp_init_ctx(&ctx, 0, 0, dummy_icmp_handler);
880 	zassert_equal(ret, 0, "Cannot init ICMP (%d)", ret);
881 
882 	test_started = true;
883 	test_proto = (family == AF_INET6) ? IPPROTO_ICMPV6 : IPPROTO_ICMP;
884 	verify_fragment = true;
885 
886 	params.data = test_data_large;
887 	params.data_size = sizeof(test_data_large);
888 	ret = net_icmp_send_echo_request(&ctx, iface, &dst_addr, &params, NULL);
889 	zassert_equal(ret, 0, "Cannot send ICMP Echo-Request (%d)", ret);
890 
891 	if (k_sem_take(wait_data, WAIT_TIME)) {
892 		DBG("Timeout while waiting interface data\n");
893 		zassert_false(true, "Timeout");
894 	}
895 
896 	ret = net_icmp_cleanup_ctx(&ctx);
897 	zassert_equal(ret, 0, "Cannot cleanup ICMP (%d)", ret);
898 }
899 
ZTEST(net_chksum_offload,test_tx_chksum_offload_disabled_test_v6_icmp_frag)900 ZTEST(net_chksum_offload, test_tx_chksum_offload_disabled_test_v6_icmp_frag)
901 {
902 	test_tx_chksum_icmp_frag(AF_INET6, false);
903 }
904 
ZTEST(net_chksum_offload,test_tx_chksum_offload_disabled_test_v4_icmp_frag)905 ZTEST(net_chksum_offload, test_tx_chksum_offload_disabled_test_v4_icmp_frag)
906 {
907 	test_tx_chksum_icmp_frag(AF_INET, false);
908 }
909 
ZTEST(net_chksum_offload,test_tx_chksum_offload_enabled_test_v6_icmp_frag)910 ZTEST(net_chksum_offload, test_tx_chksum_offload_enabled_test_v6_icmp_frag)
911 {
912 	test_tx_chksum_icmp_frag(AF_INET6, true);
913 }
914 
ZTEST(net_chksum_offload,test_tx_chksum_offload_enabled_test_v4_icmp_frag)915 ZTEST(net_chksum_offload, test_tx_chksum_offload_enabled_test_v4_icmp_frag)
916 {
917 	test_tx_chksum_icmp_frag(AF_INET, true);
918 }
919 
test_fragment_rx_udp(struct net_pkt * pkt,union net_proto_header * proto_hdr)920 static void test_fragment_rx_udp(struct net_pkt *pkt,
921 				 union net_proto_header *proto_hdr)
922 {
923 	size_t hdr_offset = net_pkt_ip_hdr_len(pkt) +
924 			    net_pkt_ip_opts_len(pkt) +
925 			    sizeof(struct net_udp_hdr);
926 	size_t data_len = net_pkt_get_len(pkt) - hdr_offset;
927 
928 	/* In case of fragmented packets, checksum shall be present/verified
929 	 * regardless.
930 	 */
931 	zassert_not_equal(proto_hdr->udp->chksum, 0, "Checksum is not set");
932 	zassert_equal(net_calc_verify_chksum_udp(pkt), 0, "Incorrect checksum");
933 
934 	/* Verify that packet content has not been altered */
935 	net_pkt_read(pkt, verify_buf, data_len);
936 	verify_test_data_large(verify_buf, 0, data_len);
937 }
938 
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)939 static void recv_cb_offload_disabled(struct net_context *context,
940 				     struct net_pkt *pkt,
941 				     union net_ip_header *ip_hdr,
942 				     union net_proto_header *proto_hdr,
943 				     int status,
944 				     void *user_data)
945 {
946 	zassert_not_null(proto_hdr->udp, "UDP header missing");
947 
948 	if (verify_fragment) {
949 		test_fragment_rx_udp(pkt, proto_hdr);
950 	} else {
951 		zassert_not_equal(proto_hdr->udp->chksum, 0, "Checksum is not set");
952 		zassert_equal(net_calc_verify_chksum_udp(pkt), 0, "Incorrect checksum");
953 	}
954 
955 	if (net_pkt_family(pkt) == AF_INET) {
956 		struct net_ipv4_hdr *ipv4 = NET_IPV4_HDR(pkt);
957 
958 		zassert_not_equal(ipv4->chksum, 0,
959 				  "IPv4 checksum is not set");
960 	}
961 
962 	k_sem_give(&wait_data_nonoff);
963 
964 	net_pkt_unref(pkt);
965 }
966 
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)967 static void recv_cb_offload_enabled(struct net_context *context,
968 				    struct net_pkt *pkt,
969 				    union net_ip_header *ip_hdr,
970 				    union net_proto_header *proto_hdr,
971 				    int status,
972 				    void *user_data)
973 {
974 	zassert_not_null(proto_hdr->udp, "UDP header missing");
975 
976 	if (verify_fragment) {
977 		test_fragment_rx_udp(pkt, proto_hdr);
978 	} else {
979 		zassert_equal(proto_hdr->udp->chksum, 0, "Checksum is set");
980 
981 		if (net_pkt_family(pkt) == AF_INET) {
982 			struct net_ipv4_hdr *ipv4 = NET_IPV4_HDR(pkt);
983 
984 			zassert_equal(ipv4->chksum, 0, "IPv4 checksum is set");
985 		}
986 	}
987 
988 	k_sem_give(&wait_data_off);
989 
990 	net_pkt_unref(pkt);
991 }
992 
test_rx_chksum(sa_family_t family,bool offloaded)993 static void test_rx_chksum(sa_family_t family, bool offloaded)
994 {
995 	struct k_sem *wait_data = offloaded ? &wait_data_off : &wait_data_nonoff;
996 	net_context_recv_cb_t cb = offloaded ? recv_cb_offload_enabled :
997 					       recv_cb_offload_disabled;
998 	socklen_t addrlen = (family == AF_INET6) ? sizeof(struct sockaddr_in6) :
999 						   sizeof(struct sockaddr_in);
1000 	struct net_context *net_ctx;
1001 	struct sockaddr dst_addr;
1002 	int ret, len;
1003 
1004 	net_ctx = test_udp_context_prepare(family, offloaded, &dst_addr);
1005 	zassert_not_null(net_ctx, "Failed to obtain net_ctx");
1006 
1007 	test_started = true;
1008 	test_proto = IPPROTO_UDP;
1009 	start_receiving = true;
1010 
1011 	ret = net_context_recv(net_ctx, cb, K_NO_WAIT, NULL);
1012 	zassert_equal(ret, 0, "Recv UDP failed (%d)\n", ret);
1013 
1014 	len = strlen(test_data);
1015 	ret = net_context_sendto(net_ctx, test_data, len, &dst_addr,
1016 				 addrlen, NULL, K_FOREVER, NULL);
1017 	zassert_equal(ret, len, "Send UDP pkt failed (%d)\n", ret);
1018 
1019 	if (k_sem_take(wait_data, WAIT_TIME)) {
1020 		DBG("Timeout while waiting interface data\n");
1021 		zassert_false(true, "Timeout");
1022 	}
1023 
1024 	/* Let the receiver to receive the packets */
1025 	k_sleep(K_MSEC(10));
1026 
1027 	net_context_unref(net_ctx);
1028 }
1029 
ZTEST(net_chksum_offload,test_rx_chksum_offload_disabled_test_v6)1030 ZTEST(net_chksum_offload, test_rx_chksum_offload_disabled_test_v6)
1031 {
1032 	test_rx_chksum(AF_INET6, false);
1033 }
1034 
ZTEST(net_chksum_offload,test_rx_chksum_offload_disabled_test_v4)1035 ZTEST(net_chksum_offload, test_rx_chksum_offload_disabled_test_v4)
1036 {
1037 	test_rx_chksum(AF_INET, false);
1038 }
1039 
ZTEST(net_chksum_offload,test_rx_chksum_offload_enabled_test_v6)1040 ZTEST(net_chksum_offload, test_rx_chksum_offload_enabled_test_v6)
1041 {
1042 	test_rx_chksum(AF_INET6, true);
1043 }
1044 
ZTEST(net_chksum_offload,test_rx_chksum_offload_enabled_test_v4)1045 ZTEST(net_chksum_offload, test_rx_chksum_offload_enabled_test_v4)
1046 {
1047 	test_rx_chksum(AF_INET, true);
1048 }
1049 
test_rx_chksum_udp_frag(sa_family_t family,bool offloaded)1050 static void test_rx_chksum_udp_frag(sa_family_t family, bool offloaded)
1051 {
1052 	struct k_sem *wait_data = offloaded ? &wait_data_off : &wait_data_nonoff;
1053 	net_context_recv_cb_t cb = offloaded ? recv_cb_offload_enabled :
1054 					       recv_cb_offload_disabled;
1055 	socklen_t addrlen = (family == AF_INET6) ? sizeof(struct sockaddr_in6) :
1056 						   sizeof(struct sockaddr_in);
1057 	struct net_context *net_ctx;
1058 	struct sockaddr dst_addr;
1059 	int ret, len;
1060 
1061 	net_ctx = test_udp_context_prepare(family, offloaded, &dst_addr);
1062 	zassert_not_null(net_ctx, "Failed to obtain net_ctx");
1063 
1064 	test_started = true;
1065 	test_proto = IPPROTO_UDP;
1066 	start_receiving = true;
1067 	verify_fragment = true;
1068 
1069 	ret = net_context_recv(net_ctx, cb, K_NO_WAIT, NULL);
1070 	zassert_equal(ret, 0, "Recv UDP failed (%d)\n", ret);
1071 
1072 	len = sizeof(test_data_large);
1073 	ret = net_context_sendto(net_ctx, test_data_large, len, &dst_addr,
1074 				 addrlen, NULL, K_FOREVER, NULL);
1075 	zassert_equal(ret, len, "Send UDP pkt failed (%d)\n", ret);
1076 
1077 	if (k_sem_take(wait_data, WAIT_TIME)) {
1078 		DBG("Timeout while waiting interface data\n");
1079 		zassert_false(true, "Timeout");
1080 	}
1081 
1082 	/* Let the receiver to receive the packets */
1083 	k_sleep(K_MSEC(10));
1084 
1085 	net_context_unref(net_ctx);
1086 }
1087 
ZTEST(net_chksum_offload,test_rx_chksum_offload_disabled_test_v6_udp_frag)1088 ZTEST(net_chksum_offload, test_rx_chksum_offload_disabled_test_v6_udp_frag)
1089 {
1090 	test_rx_chksum_udp_frag(AF_INET6, false);
1091 }
1092 
ZTEST(net_chksum_offload,test_rx_chksum_offload_disabled_test_v4_udp_frag)1093 ZTEST(net_chksum_offload, test_rx_chksum_offload_disabled_test_v4_udp_frag)
1094 {
1095 	test_rx_chksum_udp_frag(AF_INET, false);
1096 }
1097 
ZTEST(net_chksum_offload,test_rx_chksum_offload_enabled_test_v6_udp_frag)1098 ZTEST(net_chksum_offload, test_rx_chksum_offload_enabled_test_v6_udp_frag)
1099 {
1100 	test_rx_chksum_udp_frag(AF_INET6, true);
1101 }
1102 
ZTEST(net_chksum_offload,test_rx_chksum_offload_enabled_test_v4_udp_frag)1103 ZTEST(net_chksum_offload, test_rx_chksum_offload_enabled_test_v4_udp_frag)
1104 {
1105 	test_rx_chksum_udp_frag(AF_INET, true);
1106 }
1107 
test_rx_chksum_udp_frag_bad(sa_family_t family,bool offloaded)1108 static void test_rx_chksum_udp_frag_bad(sa_family_t family, bool offloaded)
1109 {
1110 	struct k_sem *wait_data = offloaded ? &wait_data_off : &wait_data_nonoff;
1111 	net_context_recv_cb_t cb = offloaded ? recv_cb_offload_enabled :
1112 					       recv_cb_offload_disabled;
1113 	socklen_t addrlen = (family == AF_INET6) ? sizeof(struct sockaddr_in6) :
1114 						   sizeof(struct sockaddr_in);
1115 	struct net_context *net_ctx;
1116 	struct sockaddr dst_addr;
1117 	int ret, len;
1118 
1119 	net_ctx = test_udp_context_prepare(family, offloaded, &dst_addr);
1120 	zassert_not_null(net_ctx, "Failed to obtain net_ctx");
1121 
1122 	test_started = true;
1123 	test_proto = IPPROTO_UDP;
1124 	start_receiving = true;
1125 	verify_fragment = true;
1126 	change_chksum = true;
1127 
1128 	ret = net_context_recv(net_ctx, cb, K_NO_WAIT, NULL);
1129 	zassert_equal(ret, 0, "Recv UDP failed (%d)\n", ret);
1130 
1131 	len = sizeof(test_data_large);
1132 	ret = net_context_sendto(net_ctx, test_data_large, len, &dst_addr,
1133 				 addrlen, NULL, K_FOREVER, NULL);
1134 	zassert_equal(ret, len, "Send UDP pkt failed (%d)\n", ret);
1135 
1136 	if (k_sem_take(wait_data, WAIT_TIME) == 0) {
1137 		DBG("Packet with bad chksum should be dropped\n");
1138 		zassert_false(true, "Packet received");
1139 	}
1140 
1141 	/* Let the receiver to receive the packets */
1142 	k_sleep(K_MSEC(10));
1143 
1144 	net_context_unref(net_ctx);
1145 }
1146 
ZTEST(net_chksum_offload,test_tx_chksum_offload_disabled_test_v6_udp_frag_bad)1147 ZTEST(net_chksum_offload, test_tx_chksum_offload_disabled_test_v6_udp_frag_bad)
1148 {
1149 	test_rx_chksum_udp_frag_bad(AF_INET6, false);
1150 }
1151 
ZTEST(net_chksum_offload,test_tx_chksum_offload_disabled_test_v4_udp_frag_bad)1152 ZTEST(net_chksum_offload, test_tx_chksum_offload_disabled_test_v4_udp_frag_bad)
1153 {
1154 	test_rx_chksum_udp_frag_bad(AF_INET, false);
1155 }
1156 
ZTEST(net_chksum_offload,test_tx_chksum_offload_enabled_test_v6_udp_frag_bad)1157 ZTEST(net_chksum_offload, test_tx_chksum_offload_enabled_test_v6_udp_frag_bad)
1158 {
1159 	test_rx_chksum_udp_frag_bad(AF_INET6, true);
1160 }
1161 
ZTEST(net_chksum_offload,test_tx_chksum_offload_enabled_test_v4_udp_frag_bad)1162 ZTEST(net_chksum_offload, test_tx_chksum_offload_enabled_test_v4_udp_frag_bad)
1163 {
1164 	test_rx_chksum_udp_frag_bad(AF_INET, true);
1165 }
1166 
icmp_handler(struct net_icmp_ctx * ctx,struct net_pkt * pkt,struct net_icmp_ip_hdr * hdr,struct net_icmp_hdr * icmp_hdr,void * user_data)1167 static int icmp_handler(struct net_icmp_ctx *ctx,
1168 			struct net_pkt *pkt,
1169 			struct net_icmp_ip_hdr *hdr,
1170 			struct net_icmp_hdr *icmp_hdr,
1171 			void *user_data)
1172 {
1173 	struct k_sem *wait_data = user_data;
1174 
1175 	size_t hdr_offset = net_pkt_ip_hdr_len(pkt) +
1176 			    net_pkt_ip_opts_len(pkt) +
1177 			    sizeof(struct net_icmp_hdr) +
1178 			    sizeof(struct net_icmpv6_echo_req);
1179 	size_t data_len = net_pkt_get_len(pkt) - hdr_offset;
1180 
1181 	/* In case of fragmented packets, checksum shall be present/verified
1182 	 * regardless.
1183 	 */
1184 	zassert_not_equal(icmp_hdr->chksum, 0, "Checksum is not set");
1185 
1186 	if (test_proto == IPPROTO_ICMPV6) {
1187 		zassert_equal(net_calc_chksum_icmpv6(pkt), 0, "Incorrect checksum");
1188 	} else {
1189 		zassert_equal(net_calc_chksum_icmpv4(pkt), 0, "Incorrect checksum");
1190 	}
1191 
1192 	/* Verify that packet content has not been altered */
1193 	net_pkt_set_overwrite(pkt, true);
1194 	net_pkt_cursor_init(pkt);
1195 	net_pkt_skip(pkt, hdr_offset);
1196 	net_pkt_read(pkt, verify_buf, data_len);
1197 	verify_test_data_large(verify_buf, 0, data_len);
1198 
1199 	k_sem_give(wait_data);
1200 
1201 	return 0;
1202 }
1203 
test_rx_chksum_icmp_frag(sa_family_t family,bool offloaded)1204 static void test_rx_chksum_icmp_frag(sa_family_t family, bool offloaded)
1205 {
1206 	struct k_sem *wait_data = offloaded ? &wait_data_off : &wait_data_nonoff;
1207 	struct net_icmp_ping_params params = { 0 };
1208 	struct net_icmp_ctx ctx;
1209 	struct sockaddr dst_addr;
1210 	struct net_if *iface;
1211 	int ret;
1212 
1213 	test_icmp_init(family, offloaded, &dst_addr, &iface);
1214 
1215 	ret = net_icmp_init_ctx(&ctx,
1216 				family == AF_INET6 ? NET_ICMPV6_ECHO_REPLY :
1217 						     NET_ICMPV4_ECHO_REPLY,
1218 				0, icmp_handler);
1219 	zassert_equal(ret, 0, "Cannot init ICMP (%d)", ret);
1220 
1221 	test_started = true;
1222 	test_proto = (family == AF_INET6) ? IPPROTO_ICMPV6 : IPPROTO_ICMP;
1223 	start_receiving = true;
1224 	verify_fragment = true;
1225 
1226 	params.data = test_data_large;
1227 	params.data_size = sizeof(test_data_large);
1228 	ret = net_icmp_send_echo_request(&ctx, iface, &dst_addr, &params,
1229 					 wait_data);
1230 	zassert_equal(ret, 0, "Cannot send ICMP Echo-Request (%d)", ret);
1231 
1232 	if (k_sem_take(wait_data, WAIT_TIME)) {
1233 		DBG("Timeout while waiting interface data\n");
1234 		zassert_false(true, "Timeout");
1235 	}
1236 
1237 	ret = net_icmp_cleanup_ctx(&ctx);
1238 	zassert_equal(ret, 0, "Cannot cleanup ICMP (%d)", ret);
1239 }
1240 
ZTEST(net_chksum_offload,test_rx_chksum_offload_disabled_test_v6_icmp_frag)1241 ZTEST(net_chksum_offload, test_rx_chksum_offload_disabled_test_v6_icmp_frag)
1242 {
1243 	test_rx_chksum_icmp_frag(AF_INET6, false);
1244 }
1245 
ZTEST(net_chksum_offload,test_rx_chksum_offload_disabled_test_v4_icmp_frag)1246 ZTEST(net_chksum_offload, test_rx_chksum_offload_disabled_test_v4_icmp_frag)
1247 {
1248 	test_rx_chksum_icmp_frag(AF_INET, false);
1249 }
1250 
ZTEST(net_chksum_offload,test_rx_chksum_offload_enabled_test_v6_icmp_frag)1251 ZTEST(net_chksum_offload, test_rx_chksum_offload_enabled_test_v6_icmp_frag)
1252 {
1253 	test_rx_chksum_icmp_frag(AF_INET6, true);
1254 }
1255 
ZTEST(net_chksum_offload,test_rx_chksum_offload_enabled_test_v4_icmp_frag)1256 ZTEST(net_chksum_offload, test_rx_chksum_offload_enabled_test_v4_icmp_frag)
1257 {
1258 	test_rx_chksum_icmp_frag(AF_INET, true);
1259 }
1260 
test_rx_chksum_icmp_frag_bad(sa_family_t family,bool offloaded)1261 static void test_rx_chksum_icmp_frag_bad(sa_family_t family, bool offloaded)
1262 {
1263 	struct k_sem *wait_data = offloaded ? &wait_data_off : &wait_data_nonoff;
1264 	struct net_icmp_ping_params params = { 0 };
1265 	struct net_icmp_ctx ctx;
1266 	struct sockaddr dst_addr;
1267 	struct net_if *iface;
1268 	int ret;
1269 
1270 	test_icmp_init(family, offloaded, &dst_addr, &iface);
1271 
1272 	ret = net_icmp_init_ctx(&ctx,
1273 				family == AF_INET6 ? NET_ICMPV6_ECHO_REPLY :
1274 						     NET_ICMPV4_ECHO_REPLY,
1275 				0, icmp_handler);
1276 	zassert_equal(ret, 0, "Cannot init ICMP (%d)", ret);
1277 
1278 	test_started = true;
1279 	test_proto = (family == AF_INET6) ? IPPROTO_ICMPV6 : IPPROTO_ICMP;
1280 	start_receiving = true;
1281 	verify_fragment = true;
1282 	change_chksum = true;
1283 
1284 	params.data = test_data_large;
1285 	params.data_size = sizeof(test_data_large);
1286 	ret = net_icmp_send_echo_request(&ctx, iface, &dst_addr, &params,
1287 					 wait_data);
1288 	zassert_equal(ret, 0, "Cannot send ICMP Echo-Request (%d)", ret);
1289 
1290 	if (k_sem_take(wait_data, WAIT_TIME) == 0) {
1291 		DBG("Packet with bad chksum should be dropped\n");
1292 		zassert_false(true, "Packet received");
1293 	}
1294 
1295 	ret = net_icmp_cleanup_ctx(&ctx);
1296 	zassert_equal(ret, 0, "Cannot cleanup ICMP (%d)", ret);
1297 }
1298 
ZTEST(net_chksum_offload,test_rx_chksum_offload_disabled_test_v6_icmp_frag_bad)1299 ZTEST(net_chksum_offload, test_rx_chksum_offload_disabled_test_v6_icmp_frag_bad)
1300 {
1301 	test_rx_chksum_icmp_frag_bad(AF_INET6, false);
1302 }
1303 
ZTEST(net_chksum_offload,test_rx_chksum_offload_disabled_test_v4_icmp_frag_bad)1304 ZTEST(net_chksum_offload, test_rx_chksum_offload_disabled_test_v4_icmp_frag_bad)
1305 {
1306 	test_rx_chksum_icmp_frag_bad(AF_INET, false);
1307 }
1308 
ZTEST(net_chksum_offload,test_rx_chksum_offload_enabled_test_v6_icmp_frag_bad)1309 ZTEST(net_chksum_offload, test_rx_chksum_offload_enabled_test_v6_icmp_frag_bad)
1310 {
1311 	test_rx_chksum_icmp_frag_bad(AF_INET6, true);
1312 }
1313 
ZTEST(net_chksum_offload,test_rx_chksum_offload_enabled_test_v4_icmp_frag_bad)1314 ZTEST(net_chksum_offload, test_rx_chksum_offload_enabled_test_v4_icmp_frag_bad)
1315 {
1316 	test_rx_chksum_icmp_frag_bad(AF_INET, true);
1317 }
1318 
net_chksum_offload_tests_setup(void)1319 static void *net_chksum_offload_tests_setup(void)
1320 {
1321 	test_eth_setup();
1322 	test_address_setup();
1323 
1324 	add_neighbor(eth_interfaces[0], &dst_addr1);
1325 	add_neighbor(eth_interfaces[1], &dst_addr2);
1326 
1327 	for (size_t i = 0; i < sizeof(test_data_large); i++) {
1328 		test_data_large[i] = (uint8_t)i;
1329 	}
1330 
1331 	return NULL;
1332 }
1333 
net_chksum_offload_tests_before(void * fixture)1334 static void net_chksum_offload_tests_before(void *fixture)
1335 {
1336 	ARG_UNUSED(fixture);
1337 
1338 	k_sem_reset(&wait_data_off);
1339 	k_sem_reset(&wait_data_nonoff);
1340 
1341 	test_failed = false;
1342 	test_started = false;
1343 	start_receiving = false;
1344 	verify_fragment = false;
1345 	change_chksum = false;
1346 	fragment_count = 0;
1347 	fragment_offset = 0;
1348 	test_proto = 0;
1349 
1350 	memset(verify_buf, 0, sizeof(verify_buf));
1351 }
1352 
1353 ZTEST_SUITE(net_chksum_offload, NULL, net_chksum_offload_tests_setup,
1354 	    net_chksum_offload_tests_before, NULL, NULL);
1355