1 /* main.c - Application main entry point */
2
3 /*
4 * Copyright (c) 2023 Nordic Semiconductor ASA
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 /* Use highest log level if both IPv4 and IPv6 are defined */
10 #if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_IPV6)
11
12 #if CONFIG_NET_ICMPV4_LOG_LEVEL > CONFIG_NET_ICMPV6_LOG_LEVEL
13 #define ICMP_LOG_LEVEL CONFIG_NET_ICMPV4_LOG_LEVEL
14 #else
15 #define ICMP_LOG_LEVEL CONFIG_NET_ICMPV6_LOG_LEVEL
16 #endif
17
18 #elif defined(CONFIG_NET_IPV4)
19 #define ICMP_LOG_LEVEL CONFIG_NET_ICMPV4_LOG_LEVEL
20 #elif defined(CONFIG_NET_IPV6)
21 #define ICMP_LOG_LEVEL CONFIG_NET_ICMPV6_LOG_LEVEL
22 #else
23 #define ICMP_LOG_LEVEL LOG_LEVEL_INF
24 #endif
25
26 #include <zephyr/logging/log.h>
27 LOG_MODULE_REGISTER(net_test, ICMP_LOG_LEVEL);
28
29 #include <errno.h>
30 #include <zephyr/types.h>
31 #include <stddef.h>
32 #include <string.h>
33 #include <zephyr/net_buf.h>
34 #include <zephyr/ztest.h>
35 #include <zephyr/net/dummy.h>
36 #include <zephyr/net/ethernet.h>
37 #include <zephyr/net/icmp.h>
38 #include <zephyr/net/net_stats.h>
39 #include <zephyr/net/net_pkt.h>
40 #include <zephyr/net/net_offload.h>
41 #include <zephyr/net/offloaded_netdev.h>
42 #include <zephyr/net/wifi_mgmt.h>
43
44 #include "net_private.h"
45 #include "icmpv4.h"
46 #include "icmpv6.h"
47 #include "ipv4.h"
48 #include "ipv6.h"
49
50 #define PKT_WAIT_TIME K_SECONDS(1)
51 #define SEM_WAIT_TIME K_SECONDS(1)
52 #define TEST_DATA "dummy test data"
53
54 static struct in6_addr send_addr_6 = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
55 0, 0, 0, 0, 0, 0, 0, 0x1 } } };
56 static struct in6_addr recv_addr_6 = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
57 0, 0, 0, 0, 0, 0, 0, 0x2 } } };
58 static struct in_addr send_addr_4 = { { { 192, 0, 2, 1 } } };
59 static struct in_addr recv_addr_4 = { { { 192, 0, 2, 2 } } };
60
61 static struct net_if *sender, *receiver;
62
63 static struct test_icmp_context {
64 uint8_t mac[sizeof(struct net_eth_addr)];
65 struct net_if *iface;
66 uint8_t test_data[sizeof(TEST_DATA)];
67 struct k_sem tx_sem;
68 bool req_received;
69 } send_ctx, recv_ctx;
70
71 #if defined(CONFIG_NET_OFFLOADING_SUPPORT)
72 static struct test_icmp_context offload_ctx;
73 static struct net_if *offload_sender;
74
75 static struct in6_addr offload_send_addr_6 = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
76 0, 0, 0, 0, 0, 0, 0, 0x3 } } };
77 static struct in6_addr offload_recv_addr_6 = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
78 0, 0, 0, 0, 0, 0, 0, 0x4 } } };
79 static struct in_addr offload_send_addr_4 = { { { 192, 0, 2, 3 } } };
80 static struct in_addr offload_recv_addr_4 = { { { 192, 0, 2, 4 } } };
81 #endif
82
test_iface_init(struct net_if * iface)83 static void test_iface_init(struct net_if *iface)
84 {
85 struct test_icmp_context *ctx = net_if_get_device(iface)->data;
86 static int counter;
87
88 /* Generate and assign MAC. */
89 /* 00-00-5E-00-53-xx Documentation RFC 7042 */
90 ctx->mac[0] = 0x00;
91 ctx->mac[1] = 0x00;
92 ctx->mac[2] = 0x5E;
93 ctx->mac[3] = 0x00;
94 ctx->mac[4] = 0x53;
95 ctx->mac[5] = ++counter;
96
97 net_if_set_link_addr(iface, ctx->mac, sizeof(ctx->mac), NET_LINK_ETHERNET);
98
99 ctx->iface = iface;
100 }
101
test_sender(const struct device * dev,struct net_pkt * pkt)102 static int test_sender(const struct device *dev, struct net_pkt *pkt)
103 {
104 struct net_pkt *send_pkt;
105
106 send_pkt = net_pkt_clone(pkt, PKT_WAIT_TIME);
107
108 net_pkt_set_iface(send_pkt, recv_ctx.iface);
109
110 (void)net_recv_data(recv_ctx.iface, send_pkt);
111
112 net_pkt_unref(pkt);
113
114 return 0;
115 }
116
test_receiver(const struct device * dev,struct net_pkt * pkt)117 static int test_receiver(const struct device *dev, struct net_pkt *pkt)
118 {
119 struct net_pkt *send_pkt;
120
121 send_pkt = net_pkt_clone(pkt, PKT_WAIT_TIME);
122
123 net_pkt_set_iface(send_pkt, send_ctx.iface);
124
125 (void)net_recv_data(send_ctx.iface, send_pkt);
126
127 net_pkt_unref(pkt);
128
129 return 0;
130 }
131
132 static struct dummy_api send_if_api = {
133 .iface_api.init = test_iface_init,
134 .send = test_sender,
135 };
136
137 static struct dummy_api recv_if_api = {
138 .iface_api.init = test_iface_init,
139 .send = test_receiver,
140 };
141
142 NET_DEVICE_INIT(test_sender_icmp, "test_sender_icmp", NULL, NULL, &send_ctx, NULL,
143 CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &send_if_api,
144 DUMMY_L2, NET_L2_GET_CTX_TYPE(DUMMY_L2), NET_IPV6_MTU);
145
146 NET_DEVICE_INIT(test_receiver_icmp, "test_receiver_icmp", NULL, NULL, &recv_ctx, NULL,
147 CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &recv_if_api,
148 DUMMY_L2, NET_L2_GET_CTX_TYPE(DUMMY_L2), NET_IPV6_MTU);
149
150 #if defined(CONFIG_NET_OFFLOADING_SUPPORT)
offload_dummy_get(sa_family_t family,enum net_sock_type type,enum net_ip_protocol ip_proto,struct net_context ** context)151 static int offload_dummy_get(sa_family_t family,
152 enum net_sock_type type,
153 enum net_ip_protocol ip_proto,
154 struct net_context **context)
155 {
156 return -1;
157 }
158
159 /* Placeholders, until Zephyr IP stack updated to handle a NULL net_offload */
160 static struct net_offload offload_dummy = {
161 .get = offload_dummy_get,
162 .bind = NULL,
163 .listen = NULL,
164 .connect = NULL,
165 .accept = NULL,
166 .send = NULL,
167 .sendto = NULL,
168 .recv = NULL,
169 .put = NULL,
170 };
171
172 static struct net_icmp_offload offload_data;
173
174 #if defined(CONFIG_NET_IPV4)
get_ipv4_reply(struct net_if * iface,struct sockaddr * dst,struct net_icmp_ping_params * params,struct net_pkt ** reply_pkt,struct net_ipv4_hdr ** hdr_ipv4,struct net_icmp_hdr ** hdr_icmp)175 static int get_ipv4_reply(struct net_if *iface,
176 struct sockaddr *dst,
177 struct net_icmp_ping_params *params,
178 struct net_pkt **reply_pkt,
179 struct net_ipv4_hdr **hdr_ipv4,
180 struct net_icmp_hdr **hdr_icmp)
181 {
182 struct net_ipv4_hdr *ipv4_hdr = NULL;
183 struct net_icmp_hdr *icmp_hdr;
184 const struct in_addr *dest4;
185 struct net_pkt *reply;
186 struct in_addr *src4;
187 int ret;
188
189 /* The code below should not be used in real life scenarios
190 * as it is missing filling the ICMP params etc. We just create
191 * a basic IPv4 header here in order to pass sanity checks
192 * in IP packet parsing.
193 */
194 reply = net_pkt_alloc_with_buffer(iface, sizeof(struct net_ipv4_hdr) +
195 sizeof(struct net_icmp_hdr) +
196 params->data_size,
197 AF_INET, IPPROTO_ICMP,
198 PKT_WAIT_TIME);
199 if (!reply) {
200 NET_DBG("No buffer");
201 return -ENOMEM;
202 }
203
204 dest4 = &offload_send_addr_4;
205 src4 = &net_sin(dst)->sin_addr;
206
207 ipv4_hdr = net_pkt_cursor_get_pos(reply);
208 *hdr_ipv4 = ipv4_hdr;
209
210 net_pkt_set_ipv4_ttl(reply, 1U);
211
212 ret = net_ipv4_create_full(reply, src4, dest4, params->tc_tos,
213 params->identifier, 0, 0);
214 if (ret < 0) {
215 LOG_ERR("Cannot create IPv4 pkt (%d)", ret);
216 return ret;
217 }
218
219 icmp_hdr = net_pkt_cursor_get_pos(reply);
220 *hdr_icmp = icmp_hdr;
221
222 ret = net_icmpv4_create(reply, NET_ICMPV4_ECHO_REPLY, 0);
223 if (ret < 0) {
224 LOG_ERR("Cannot create ICMPv4 pkt (%d)", ret);
225 return ret;
226 }
227
228 ret = net_pkt_write(reply, params->data, params->data_size);
229 if (ret < 0) {
230 LOG_ERR("Cannot write payload (%d)", ret);
231 return ret;
232 }
233
234 net_pkt_cursor_init(reply);
235 net_ipv4_finalize(reply, IPPROTO_ICMP);
236
237 *reply_pkt = reply;
238
239 return 0;
240 }
241 #else
get_ipv4_reply(struct net_if * iface,struct sockaddr * dst,struct net_icmp_ping_params * params,struct net_pkt ** reply_pkt,struct net_ipv4_hdr ** hdr_ipv4,struct net_icmp_hdr ** hdr_icmp)242 static int get_ipv4_reply(struct net_if *iface,
243 struct sockaddr *dst,
244 struct net_icmp_ping_params *params,
245 struct net_pkt **reply_pkt,
246 struct net_ipv4_hdr **hdr_ipv4,
247 struct net_icmp_hdr **hdr_icmp)
248 {
249 return -ENOTSUP;
250 }
251 #endif
252
253 #if defined(CONFIG_NET_IPV6)
get_ipv6_reply(struct net_if * iface,struct sockaddr * dst,struct net_icmp_ping_params * params,struct net_pkt ** reply_pkt,struct net_ipv6_hdr ** hdr_ipv6,struct net_icmp_hdr ** hdr_icmp)254 static int get_ipv6_reply(struct net_if *iface,
255 struct sockaddr *dst,
256 struct net_icmp_ping_params *params,
257 struct net_pkt **reply_pkt,
258 struct net_ipv6_hdr **hdr_ipv6,
259 struct net_icmp_hdr **hdr_icmp)
260 {
261 struct net_ipv6_hdr *ipv6_hdr = NULL;
262 struct net_icmp_hdr *icmp_hdr;
263 const struct in6_addr *dest6;
264 struct net_pkt *reply;
265 struct in6_addr *src6;
266 int ret;
267
268 reply = net_pkt_alloc_with_buffer(iface, sizeof(struct net_ipv6_hdr) +
269 sizeof(struct net_icmp_hdr) +
270 params->data_size,
271 AF_INET6, IPPROTO_ICMP,
272 PKT_WAIT_TIME);
273 if (!reply) {
274 NET_DBG("No buffer");
275 return -ENOMEM;
276 }
277
278 dest6 = &offload_send_addr_6;
279 src6 = &net_sin6(dst)->sin6_addr;
280
281 ipv6_hdr = net_pkt_cursor_get_pos(reply);
282 *hdr_ipv6 = ipv6_hdr;
283
284 ret = net_ipv6_create(reply, src6, dest6);
285 if (ret < 0) {
286 LOG_ERR("Cannot create IPv6 pkt (%d)", ret);
287 return ret;
288 }
289
290 icmp_hdr = net_pkt_cursor_get_pos(reply);
291 *hdr_icmp = icmp_hdr;
292
293 ret = net_icmpv6_create(reply, NET_ICMPV6_ECHO_REPLY, 0);
294 if (ret < 0) {
295 LOG_ERR("Cannot create ICMPv6 pkt (%d)", ret);
296 return ret;
297 }
298
299 ret = net_pkt_write(reply, params->data, params->data_size);
300 if (ret < 0) {
301 LOG_ERR("Cannot write payload (%d)", ret);
302 return ret;
303 }
304
305 net_pkt_cursor_init(reply);
306 net_ipv6_finalize(reply, IPPROTO_ICMP);
307
308 *reply_pkt = reply;
309
310 return 0;
311 }
312 #else
get_ipv6_reply(struct net_if * iface,struct sockaddr * dst,struct net_icmp_ping_params * params,struct net_pkt ** reply_pkt,struct net_ipv6_hdr ** hdr_ipv6,struct net_icmp_hdr ** hdr_icmp)313 static int get_ipv6_reply(struct net_if *iface,
314 struct sockaddr *dst,
315 struct net_icmp_ping_params *params,
316 struct net_pkt **reply_pkt,
317 struct net_ipv6_hdr **hdr_ipv6,
318 struct net_icmp_hdr **hdr_icmp)
319 {
320 return -ENOTSUP;
321 }
322 #endif
323
offload_ping_handler(struct net_icmp_ctx * ctx,struct net_if * iface,struct sockaddr * dst,struct net_icmp_ping_params * params,void * user_data)324 static int offload_ping_handler(struct net_icmp_ctx *ctx,
325 struct net_if *iface,
326 struct sockaddr *dst,
327 struct net_icmp_ping_params *params,
328 void *user_data)
329 {
330 struct net_icmp_offload *icmp_offload_ctx = &offload_data;
331 struct net_icmp_hdr *icmp_hdr = NULL;
332 struct net_pkt *reply = NULL;
333 struct net_icmp_ip_hdr ip_hdr;
334 struct net_ipv4_hdr *ipv4_hdr;
335 struct net_ipv6_hdr *ipv6_hdr;
336 net_icmp_handler_t resp_handler;
337 int ret;
338
339 ret = net_icmp_get_offload_rsp_handler(icmp_offload_ctx, &resp_handler);
340 if (ret < 0) {
341 LOG_ERR("Cannot get offload response handler.");
342 return -ENOENT;
343 }
344
345 /* So in real life scenario, we should here send a Echo-Request via
346 * some offloaded way to peer. When the response is received, we
347 * should then return that information to the ping caller by
348 * calling the response handler function.
349 * Here we just simulate a reply as there is no need to actually
350 * send anything anywhere.
351 */
352 if (IS_ENABLED(CONFIG_NET_IPV4) && dst->sa_family == AF_INET) {
353 ret = get_ipv4_reply(iface, dst, params, &reply,
354 &ipv4_hdr, &icmp_hdr);
355 if (ret < 0) {
356 LOG_ERR("Cannot create reply pkt (%d)", ret);
357 return ret;
358 }
359
360 ip_hdr.family = AF_INET;
361 ip_hdr.ipv4 = ipv4_hdr;
362 }
363
364 if (IS_ENABLED(CONFIG_NET_IPV6) && dst->sa_family == AF_INET6) {
365 ret = get_ipv6_reply(iface, dst, params, &reply,
366 &ipv6_hdr, &icmp_hdr);
367 if (ret < 0) {
368 LOG_ERR("Cannot create reply pkt (%d)", ret);
369 return ret;
370 }
371
372 ip_hdr.family = AF_INET6;
373 ip_hdr.ipv6 = ipv6_hdr;
374 }
375
376 ret = resp_handler(ctx, reply, &ip_hdr, icmp_hdr, user_data);
377 if (ret < 0) {
378 LOG_ERR("Cannot send response (%d)", ret);
379 }
380
381 return ret;
382 }
383
offload_iface_init(struct net_if * iface)384 static void offload_iface_init(struct net_if *iface)
385 {
386 struct test_icmp_context *ctx = net_if_get_device(iface)->data;
387 int ret;
388
389 /* Generate and assign MAC. */
390 /* 00-00-5E-00-53-xx Documentation RFC 7042 */
391 ctx->mac[0] = 0x00;
392 ctx->mac[1] = 0x00;
393 ctx->mac[2] = 0x5E;
394 ctx->mac[3] = 0x00;
395 ctx->mac[4] = 0x53;
396 ctx->mac[5] = 0xF0;
397
398 net_if_set_link_addr(iface, ctx->mac, sizeof(ctx->mac), NET_LINK_ETHERNET);
399
400 /* A dummy placeholder to allow network stack to pass offloaded data to our interface */
401 iface->if_dev->offload = &offload_dummy;
402
403 /* This will cause ping requests to be re-directed to our offload handler */
404 ret = net_icmp_register_offload_ping(&offload_data, iface, offload_ping_handler);
405 if (ret < 0) {
406 LOG_ERR("Cannot register offload ping handler (%d)", ret);
407 }
408
409 ctx->iface = iface;
410 }
411
offload_get_type(void)412 static enum offloaded_net_if_types offload_get_type(void)
413 {
414 return L2_OFFLOADED_NET_IF_TYPE_WIFI;
415 }
416
417 static const struct net_wifi_mgmt_offload offload_api = {
418 .wifi_iface.iface_api.init = offload_iface_init,
419 .wifi_iface.get_type = offload_get_type,
420 };
421
422 NET_DEVICE_OFFLOAD_INIT(test_offload, "test_offload", NULL, NULL, &offload_ctx, NULL,
423 CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &offload_api, 1500);
424 #endif /* CONFIG_NET_OFFLOADING_SUPPORT */
425
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)426 static int icmp_handler(struct net_icmp_ctx *ctx,
427 struct net_pkt *pkt,
428 struct net_icmp_ip_hdr *hdr,
429 struct net_icmp_hdr *icmp_hdr,
430 void *user_data)
431 {
432 struct test_icmp_context *test = user_data;
433
434 if (hdr->family == AF_INET) {
435 struct net_ipv4_hdr *ip_hdr = hdr->ipv4;
436
437 NET_DBG("Received Echo reply from %s to %s",
438 net_sprint_ipv4_addr(&ip_hdr->src),
439 net_sprint_ipv4_addr(&ip_hdr->dst));
440
441 } else if (hdr->family == AF_INET6) {
442 struct net_ipv6_hdr *ip_hdr = hdr->ipv6;
443
444 NET_DBG("Received Echo Reply from %s to %s",
445 net_sprint_ipv6_addr(&ip_hdr->src),
446 net_sprint_ipv6_addr(&ip_hdr->dst));
447 } else {
448 return -ENOENT;
449 }
450
451 test->req_received = true;
452 k_sem_give(&test->tx_sem);
453
454 return 0;
455 }
456
ZTEST(icmp_tests,test_icmpv6_echo_request)457 ZTEST(icmp_tests, test_icmpv6_echo_request)
458 {
459 struct sockaddr_in6 dst6 = { 0 };
460 struct net_icmp_ping_params params;
461 struct net_icmp_ctx ctx;
462 int ret;
463
464 if (!IS_ENABLED(CONFIG_NET_IPV6)) {
465 return;
466 }
467
468 ret = net_icmp_init_ctx(&ctx, NET_ICMPV6_ECHO_REPLY, 0, icmp_handler);
469 zassert_equal(ret, 0, "Cannot init ICMP (%d)", ret);
470
471 dst6.sin6_family = AF_INET6;
472
473 #if defined(CONFIG_NET_IPV6)
474 memcpy(&dst6.sin6_addr, &recv_addr_6, sizeof(recv_addr_6));
475 #endif
476
477 params.identifier = 1234;
478 params.sequence = 5678;
479 params.tc_tos = 1;
480 params.priority = 2;
481 params.data = send_ctx.test_data;
482 params.data_size = sizeof(send_ctx.test_data);
483
484 ret = net_icmp_send_echo_request(&ctx, sender,
485 (struct sockaddr *)&dst6,
486 ¶ms,
487 &send_ctx);
488 zassert_equal(ret, 0, "Cannot send ICMP Echo-Request (%d)", ret);
489
490 k_sem_take(&send_ctx.tx_sem, SEM_WAIT_TIME);
491
492 zassert_true(send_ctx.req_received, "Did not receive Echo-Request");
493
494 ret = net_icmp_cleanup_ctx(&ctx);
495 zassert_equal(ret, 0, "Cannot cleanup ICMP (%d)", ret);
496
497 send_ctx.req_received = false;
498 }
499
ZTEST(icmp_tests,test_icmpv4_echo_request)500 ZTEST(icmp_tests, test_icmpv4_echo_request)
501 {
502 struct sockaddr_in dst4 = { 0 };
503 struct net_icmp_ping_params params;
504 struct net_icmp_ctx ctx;
505 int ret;
506
507 if (!IS_ENABLED(CONFIG_NET_IPV4)) {
508 return;
509 }
510
511 ret = net_icmp_init_ctx(&ctx, NET_ICMPV4_ECHO_REPLY, 0, icmp_handler);
512 zassert_equal(ret, 0, "Cannot init ICMP (%d)", ret);
513
514 dst4.sin_family = AF_INET;
515
516 #if defined(CONFIG_NET_IPV4)
517 memcpy(&dst4.sin_addr, &recv_addr_4, sizeof(recv_addr_4));
518 #endif
519
520 params.identifier = 1234;
521 params.sequence = 5678;
522 params.tc_tos = 1;
523 params.priority = 2;
524 params.data = send_ctx.test_data;
525 params.data_size = sizeof(send_ctx.test_data);
526
527 ret = net_icmp_send_echo_request(&ctx, sender,
528 (struct sockaddr *)&dst4,
529 ¶ms,
530 &send_ctx);
531 zassert_equal(ret, 0, "Cannot send ICMP Echo-Request (%d)", ret);
532
533 k_sem_take(&send_ctx.tx_sem, SEM_WAIT_TIME);
534
535 zassert_true(send_ctx.req_received, "Did not receive Echo-Request");
536
537 ret = net_icmp_cleanup_ctx(&ctx);
538 zassert_equal(ret, 0, "Cannot cleanup ICMP (%d)", ret);
539
540 send_ctx.req_received = false;
541 }
542
543 #if defined(CONFIG_NET_OFFLOADING_SUPPORT)
544 #if defined(CONFIG_NET_IPV4)
ZTEST(icmp_tests,test_offload_icmpv4_echo_request)545 ZTEST(icmp_tests, test_offload_icmpv4_echo_request)
546 {
547 struct sockaddr_in dst4 = { 0 };
548 struct net_icmp_ping_params params;
549 struct net_icmp_ctx ctx;
550 int ret;
551
552 ret = net_icmp_init_ctx(&ctx, NET_ICMPV4_ECHO_REPLY, 0, icmp_handler);
553 zassert_equal(ret, 0, "Cannot init ICMP (%d)", ret);
554
555 dst4.sin_family = AF_INET;
556
557 memcpy(&dst4.sin_addr, &offload_recv_addr_4, sizeof(offload_recv_addr_4));
558
559 params.identifier = 1234;
560 params.sequence = 5678;
561 params.tc_tos = 1;
562 params.priority = 2;
563 params.data = offload_ctx.test_data;
564 params.data_size = sizeof(offload_ctx.test_data);
565
566 ret = net_icmp_send_echo_request(&ctx, offload_sender,
567 (struct sockaddr *)&dst4,
568 ¶ms,
569 &offload_ctx);
570 zassert_equal(ret, 0, "Cannot send ICMP Echo-Request (%d)", ret);
571
572 k_sem_take(&offload_ctx.tx_sem, SEM_WAIT_TIME);
573
574 zassert_true(offload_ctx.req_received, "Did not receive Echo-Request");
575
576 ret = net_icmp_cleanup_ctx(&ctx);
577 zassert_equal(ret, 0, "Cannot cleanup ICMP (%d)", ret);
578
579 offload_ctx.req_received = false;
580 }
581 #endif
582
583 #if defined(CONFIG_NET_IPV6)
ZTEST(icmp_tests,test_offload_icmpv6_echo_request)584 ZTEST(icmp_tests, test_offload_icmpv6_echo_request)
585 {
586 struct sockaddr_in6 dst6 = { 0 };
587 struct net_icmp_ping_params params;
588 struct net_icmp_ctx ctx;
589 int ret;
590
591 ret = net_icmp_init_ctx(&ctx, NET_ICMPV6_ECHO_REPLY, 0, icmp_handler);
592 zassert_equal(ret, 0, "Cannot init ICMP (%d)", ret);
593
594 dst6.sin6_family = AF_INET6;
595
596 memcpy(&dst6.sin6_addr, &offload_recv_addr_6, sizeof(offload_recv_addr_6));
597
598 params.identifier = 1234;
599 params.sequence = 5678;
600 params.tc_tos = 1;
601 params.priority = 2;
602 params.data = offload_ctx.test_data;
603 params.data_size = sizeof(offload_ctx.test_data);
604
605 ret = net_icmp_send_echo_request(&ctx, offload_sender,
606 (struct sockaddr *)&dst6,
607 ¶ms,
608 &offload_ctx);
609 zassert_equal(ret, 0, "Cannot send ICMP Echo-Request (%d)", ret);
610
611 k_sem_take(&offload_ctx.tx_sem, SEM_WAIT_TIME);
612
613 zassert_true(offload_ctx.req_received, "Did not receive Echo-Request");
614
615 ret = net_icmp_cleanup_ctx(&ctx);
616 zassert_equal(ret, 0, "Cannot cleanup ICMP (%d)", ret);
617
618 offload_ctx.req_received = false;
619 }
620 #endif
621 #endif /* CONFIG_NET_OFFLOADING_SUPPORT */
622
setup(void)623 static void *setup(void)
624 {
625 if (IS_ENABLED(CONFIG_NET_TC_THREAD_COOPERATIVE)) {
626 k_thread_priority_set(k_current_get(),
627 K_PRIO_COOP(CONFIG_NUM_COOP_PRIORITIES - 1));
628 } else {
629 k_thread_priority_set(k_current_get(), K_PRIO_PREEMPT(9));
630 }
631
632 #if defined(CONFIG_NET_IPV6)
633 (void)net_if_ipv6_addr_add(send_ctx.iface, &send_addr_6, NET_ADDR_MANUAL, 0);
634 (void)net_if_ipv6_addr_add(recv_ctx.iface, &recv_addr_6, NET_ADDR_MANUAL, 0);
635 #else
636 ARG_UNUSED(send_addr_6);
637 ARG_UNUSED(recv_addr_6);
638 #endif
639
640 #if defined(CONFIG_NET_IPV4)
641 (void)net_if_ipv4_addr_add(send_ctx.iface, &send_addr_4, NET_ADDR_MANUAL, 0);
642 (void)net_if_ipv4_addr_add(recv_ctx.iface, &recv_addr_4, NET_ADDR_MANUAL, 0);
643 #else
644 ARG_UNUSED(send_addr_4);
645 ARG_UNUSED(recv_addr_4);
646 #endif
647
648 memcpy(send_ctx.test_data, &(TEST_DATA), sizeof(TEST_DATA));
649 memcpy(recv_ctx.test_data, &(TEST_DATA), sizeof(TEST_DATA));
650
651 k_sem_init(&send_ctx.tx_sem, 0, 1);
652 k_sem_init(&recv_ctx.tx_sem, 0, 1);
653
654 sender = net_if_lookup_by_dev(DEVICE_GET(test_sender_icmp));
655 zassert_equal(sender, send_ctx.iface, "Invalid interface (%p vs %p)",
656 sender, send_ctx.iface);
657
658 receiver = net_if_lookup_by_dev(DEVICE_GET(test_receiver_icmp));
659 zassert_equal(receiver, recv_ctx.iface, "Invalid interface (%p vs %p)",
660 receiver, recv_ctx.iface);
661
662 #if defined(CONFIG_NET_OFFLOADING_SUPPORT)
663
664 #if defined(CONFIG_NET_IPV6)
665 (void)net_if_ipv6_addr_add(offload_ctx.iface, &offload_send_addr_6, NET_ADDR_MANUAL, 0);
666 #else
667 ARG_UNUSED(offload_send_addr_6);
668 ARG_UNUSED(offload_recv_addr_6);
669 #endif
670
671 #if defined(CONFIG_NET_IPV4)
672 (void)net_if_ipv4_addr_add(offload_ctx.iface, &offload_send_addr_4, NET_ADDR_MANUAL, 0);
673 #else
674 ARG_UNUSED(offload_send_addr_4);
675 ARG_UNUSED(offload_recv_addr_4);
676 #endif
677
678 memcpy(offload_ctx.test_data, &(TEST_DATA), sizeof(TEST_DATA));
679 k_sem_init(&offload_ctx.tx_sem, 0, 1);
680
681 offload_sender = net_if_lookup_by_dev(DEVICE_GET(test_offload));
682 zassert_equal(offload_sender, offload_ctx.iface, "Invalid interface (%p vs %p)",
683 offload_sender, offload_ctx.iface);
684 #endif
685
686 return NULL;
687 }
688
689 ZTEST_SUITE(icmp_tests, NULL, setup, NULL, NULL, NULL);
690