1 /* main.c - Application main entry point */
2
3 /*
4 * Copyright (c) 2024 Nordic Semiconductor
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #include <zephyr/logging/log.h>
10 LOG_MODULE_REGISTER(net_test, CONFIG_NET_PMTU_LOG_LEVEL);
11
12 #include <zephyr/types.h>
13 #include <stdbool.h>
14 #include <stddef.h>
15 #include <string.h>
16 #include <errno.h>
17 #include <zephyr/linker/sections.h>
18
19 #include <zephyr/ztest.h>
20
21 #include <zephyr/net/net_if.h>
22 #include <zephyr/net/net_pkt.h>
23 #include <zephyr/net/net_ip.h>
24 #include <zephyr/net/net_core.h>
25 #include <zephyr/net/ethernet.h>
26 #include <zephyr/net/dummy.h>
27 #include <zephyr/net/loopback.h>
28 #include <zephyr/net/net_mgmt.h>
29 #include <zephyr/net/net_event.h>
30 #include <zephyr/net/socket.h>
31
32 #include <zephyr/random/random.h>
33
34 #include "../../socket/socket_helpers.h"
35
36 #include "route.h"
37 #include "icmpv6.h"
38 #include "icmpv4.h"
39 #include "ipv6.h"
40 #include "ipv4.h"
41 #include "pmtu.h"
42
43 #define NET_LOG_ENABLED 1
44 #include "net_private.h"
45
46 #if defined(CONFIG_BOARD_NATIVE_SIM) || defined(CONFIG_BOARD_NATIVE_SIM_NATIVE_64)
47 #define WAIT_PROPERLY 0
48 #else
49 #define WAIT_PROPERLY 1
50 #endif
51
52 #if defined(CONFIG_NET_PMTU_LOG_LEVEL_DBG)
53 #define DBG(fmt, ...) printk(fmt, ##__VA_ARGS__)
54 #else
55 #define DBG(fmt, ...)
56 #endif
57
58 /* This is a helper function to get the MTU value for the given destination.
59 * It is implemented in tcp.c file.
60 */
61 extern uint16_t net_tcp_get_mtu(struct sockaddr *dst);
62
63 /* Small sleep between tests makes sure that the PMTU destination
64 * cache entries are separated from each other.
65 */
66 #define SMALL_SLEEP K_MSEC(5)
67
68 static struct in_addr dest_ipv4_addr1 = { { { 198, 51, 100, 1 } } };
69 static struct in_addr dest_ipv4_addr2 = { { { 198, 51, 100, 2 } } };
70 static struct in_addr dest_ipv4_addr3 = { { { 198, 51, 100, 3 } } };
71 static struct in_addr dest_ipv4_addr4 = { { { 198, 51, 100, 4 } } };
72 static struct in_addr dest_ipv4_addr_not_found = { { { 1, 2, 3, 4 } } };
73
74 static struct in6_addr dest_ipv6_addr1 = { { { 0x20, 0x01, 0x0d, 0xb8, 0x01, 0, 0, 0,
75 0, 0, 0, 0, 0, 0, 0, 0x1 } } };
76 static struct in6_addr dest_ipv6_addr2 = { { { 0x20, 0x01, 0x0d, 0xb8, 0x01, 0, 0, 0,
77 0, 0, 0, 0, 0, 0, 0, 0x2 } } };
78 static struct in6_addr dest_ipv6_addr3 = { { { 0x20, 0x01, 0x0d, 0xb8, 0x01, 0, 0, 0,
79 0, 0, 0, 0, 0, 0, 0, 0x3 } } };
80 static struct in6_addr dest_ipv6_addr4 = { { { 0x20, 0x01, 0x0d, 0xb8, 0x01, 0, 0, 0,
81 0, 0, 0, 0, 0, 0, 0, 0x4 } } };
82 static struct in6_addr dest_ipv6_addr_not_found = { { { 0x20, 0x01, 0x0d, 0xb8, 0xde,
83 0xad, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x4 } } };
84
85 static struct net_if *target_iface;
86 static char target_iface_name[CONFIG_NET_INTERFACE_NAME_LEN + 1];
87
88 K_SEM_DEFINE(wait_data, 0, UINT_MAX);
89
90 #define PKT_WAIT_TIME K_MSEC(500)
91 #define WAIT_TIME 500
92 #define WAIT_TIME_LONG MSEC_PER_SEC
93 #define MY_PORT 1969
94 #define PEER_PORT 2024
95 #define PEER_IPV6_ADDR "::1"
96 #define MY_IPV6_ADDR "::1"
97 #define MY_IPV4_ADDR "127.0.0.1"
98 #define PEER_IPV4_ADDR "127.0.0.1"
99
100 #define THREAD_SLEEP 50 /* ms */
101
102 static K_SEM_DEFINE(wait_pmtu_changed, 0, UINT_MAX);
103 static bool is_pmtu_changed;
104
ipv6_pmtu_changed(struct net_mgmt_event_callback * cb,uint32_t mgmt_event,struct net_if * iface)105 static void ipv6_pmtu_changed(struct net_mgmt_event_callback *cb,
106 uint32_t mgmt_event,
107 struct net_if *iface)
108 {
109 ARG_UNUSED(cb);
110 ARG_UNUSED(iface);
111
112 if (mgmt_event != NET_EVENT_IPV6_PMTU_CHANGED) {
113 return;
114 }
115
116 NET_DBG("IPv6 PMTU changed event received");
117
118 k_sem_give(&wait_pmtu_changed);
119 is_pmtu_changed = true;
120
121 /* Let the network stack to proceed */
122 k_msleep(THREAD_SLEEP);
123 }
124
ipv4_pmtu_changed(struct net_mgmt_event_callback * cb,uint32_t mgmt_event,struct net_if * iface)125 static void ipv4_pmtu_changed(struct net_mgmt_event_callback *cb,
126 uint32_t mgmt_event,
127 struct net_if *iface)
128 {
129 ARG_UNUSED(cb);
130 ARG_UNUSED(iface);
131
132 if (mgmt_event != NET_EVENT_IPV4_PMTU_CHANGED) {
133 return;
134 }
135
136 NET_DBG("IPv4 PMTU changed event received");
137
138 k_sem_give(&wait_pmtu_changed);
139 is_pmtu_changed = true;
140
141 /* Let the network stack to proceed */
142 k_msleep(THREAD_SLEEP);
143 }
144
145 static struct mgmt_events {
146 uint32_t event;
147 net_mgmt_event_handler_t handler;
148 struct net_mgmt_event_callback cb;
149 } mgmt_events[] = {
150 { .event = NET_EVENT_IPV6_PMTU_CHANGED, .handler = ipv6_pmtu_changed },
151 { .event = NET_EVENT_IPV4_PMTU_CHANGED, .handler = ipv4_pmtu_changed },
152 };
153
iface2str(struct net_if * iface)154 static const char *iface2str(struct net_if *iface)
155 {
156 if (net_if_l2(iface) == &NET_L2_GET_NAME(DUMMY)) {
157 return "No L2";
158 }
159
160 return "<unknown type>";
161 }
162
iface_cb(struct net_if * iface,void * user_data)163 static void iface_cb(struct net_if *iface, void *user_data)
164 {
165 static int if_count;
166
167 NET_DBG("Interface %p (%s) [%d]", iface, iface2str(iface),
168 net_if_get_by_iface(iface));
169
170 switch (if_count) {
171 case 0:
172 target_iface = iface;
173 (void)net_if_get_name(iface, target_iface_name,
174 CONFIG_NET_INTERFACE_NAME_LEN);
175 break;
176 }
177
178 if_count++;
179 }
180
setup_mgmt_events(void)181 static void setup_mgmt_events(void)
182 {
183 static bool setup_done;
184
185 if (setup_done) {
186 return;
187 }
188
189 setup_done = true;
190
191 ARRAY_FOR_EACH(mgmt_events, i) {
192 net_mgmt_init_event_callback(&mgmt_events[i].cb,
193 mgmt_events[i].handler,
194 mgmt_events[i].event);
195
196 net_mgmt_add_event_callback(&mgmt_events[i].cb);
197 }
198 }
199
test_setup(void)200 static void *test_setup(void)
201 {
202 net_if_foreach(iface_cb, NULL);
203
204 zassert_not_null(target_iface, "Interface is NULL");
205
206 return NULL;
207 }
208
ZTEST(net_pmtu_test_suite,test_pmtu_01_ipv4_get_entry)209 ZTEST(net_pmtu_test_suite, test_pmtu_01_ipv4_get_entry)
210 {
211 #if defined(CONFIG_NET_IPV4_PMTU)
212 struct net_pmtu_entry *entry;
213 struct sockaddr_in dest_ipv4;
214
215 net_ipaddr_copy(&dest_ipv4.sin_addr, &dest_ipv4_addr1);
216 dest_ipv4.sin_family = AF_INET;
217
218 entry = net_pmtu_get_entry((struct sockaddr *)&dest_ipv4);
219 zassert_is_null(entry, "PMTU IPv4 entry is not NULL");
220
221 k_sleep(SMALL_SLEEP);
222 #else
223 ztest_test_skip();
224 #endif
225 }
226
ZTEST(net_pmtu_test_suite,test_pmtu_01_ipv6_get_entry)227 ZTEST(net_pmtu_test_suite, test_pmtu_01_ipv6_get_entry)
228 {
229 #if defined(CONFIG_NET_IPV6_PMTU)
230 struct net_pmtu_entry *entry;
231 struct sockaddr_in6 dest_ipv6;
232
233 net_ipaddr_copy(&dest_ipv6.sin6_addr, &dest_ipv6_addr1);
234 dest_ipv6.sin6_family = AF_INET6;
235
236 entry = net_pmtu_get_entry((struct sockaddr *)&dest_ipv6);
237 zassert_is_null(entry, "PMTU IPv6 entry is not NULL");
238
239 k_sleep(SMALL_SLEEP);
240 #else
241 ztest_test_skip();
242 #endif
243 }
244
ZTEST(net_pmtu_test_suite,test_pmtu_02_ipv4_update_entry)245 ZTEST(net_pmtu_test_suite, test_pmtu_02_ipv4_update_entry)
246 {
247 #if defined(CONFIG_NET_IPV4_PMTU)
248 struct sockaddr_in dest_ipv4;
249 int ret;
250
251 net_ipaddr_copy(&dest_ipv4.sin_addr, &dest_ipv4_addr1);
252 dest_ipv4.sin_family = AF_INET;
253
254 ret = net_pmtu_update_mtu((struct sockaddr *)&dest_ipv4, 1300);
255 zassert_equal(ret, 0, "PMTU IPv4 MTU update failed (%d)", ret);
256
257 k_sleep(SMALL_SLEEP);
258 #else
259 ztest_test_skip();
260 #endif
261 }
262
ZTEST(net_pmtu_test_suite,test_pmtu_02_ipv6_update_entry)263 ZTEST(net_pmtu_test_suite, test_pmtu_02_ipv6_update_entry)
264 {
265 #if defined(CONFIG_NET_IPV6_PMTU)
266 struct sockaddr_in6 dest_ipv6;
267 int ret;
268
269 net_ipaddr_copy(&dest_ipv6.sin6_addr, &dest_ipv6_addr1);
270 dest_ipv6.sin6_family = AF_INET6;
271
272 ret = net_pmtu_update_mtu((struct sockaddr *)&dest_ipv6, 1600);
273 zassert_equal(ret, 0, "PMTU IPv6 MTU update failed (%d)", ret);
274
275 k_sleep(SMALL_SLEEP);
276 #else
277 ztest_test_skip();
278 #endif
279 }
280
ZTEST(net_pmtu_test_suite,test_pmtu_03_ipv4_create_more_entries)281 ZTEST(net_pmtu_test_suite, test_pmtu_03_ipv4_create_more_entries)
282 {
283 #if defined(CONFIG_NET_IPV4_PMTU)
284 struct sockaddr_in dest_ipv4;
285 struct net_pmtu_entry *entry;
286 uint16_t mtu;
287 int ret;
288
289 dest_ipv4.sin_family = AF_INET;
290
291 net_ipaddr_copy(&dest_ipv4.sin_addr, &dest_ipv4_addr1);
292 ret = net_pmtu_update_mtu((struct sockaddr *)&dest_ipv4, 1300);
293 zassert_equal(ret, 1300, "PMTU IPv4 MTU update failed (%d)", ret);
294 entry = net_pmtu_get_entry((struct sockaddr *)&dest_ipv4);
295 zassert_equal(entry->mtu, 1300, "PMTU IPv4 MTU is not correct (%d)",
296 entry->mtu);
297
298 k_sleep(SMALL_SLEEP);
299
300 net_ipaddr_copy(&dest_ipv4.sin_addr, &dest_ipv4_addr2);
301 ret = net_pmtu_update_mtu((struct sockaddr *)&dest_ipv4, 1400);
302 zassert_equal(ret, 0, "PMTU IPv4 MTU update failed (%d)", ret);
303 mtu = net_pmtu_get_mtu((struct sockaddr *)&dest_ipv4);
304 zassert_equal(mtu, 1400, "PMTU IPv4 MTU is not correct (%d)", mtu);
305
306 k_sleep(SMALL_SLEEP);
307
308 net_ipaddr_copy(&dest_ipv4.sin_addr, &dest_ipv4_addr3);
309 ret = net_pmtu_update_mtu((struct sockaddr *)&dest_ipv4, 1500);
310 zassert_equal(ret, 0, "PMTU IPv4 MTU update failed (%d)", ret);
311 entry = net_pmtu_get_entry((struct sockaddr *)&dest_ipv4);
312 zassert_equal(entry->mtu, 1500, "PMTU IPv4 MTU is not correct (%d)",
313 entry->mtu);
314
315 net_ipaddr_copy(&dest_ipv4.sin_addr, &dest_ipv4_addr_not_found);
316 ret = net_pmtu_get_mtu((struct sockaddr *)&dest_ipv4);
317 zassert_equal(ret, -ENOENT, "PMTU IPv4 MTU update succeed (%d)", ret);
318 entry = net_pmtu_get_entry((struct sockaddr *)&dest_ipv4);
319 zassert_equal(entry, NULL, "PMTU IPv4 MTU update succeed");
320 #else
321 ztest_test_skip();
322 #endif
323 }
324
ZTEST(net_pmtu_test_suite,test_pmtu_03_ipv6_create_more_entries)325 ZTEST(net_pmtu_test_suite, test_pmtu_03_ipv6_create_more_entries)
326 {
327 #if defined(CONFIG_NET_IPV6_PMTU)
328 struct sockaddr_in6 dest_ipv6;
329 struct net_pmtu_entry *entry;
330 uint16_t mtu;
331 int ret;
332
333 dest_ipv6.sin6_family = AF_INET6;
334
335 net_ipaddr_copy(&dest_ipv6.sin6_addr, &dest_ipv6_addr1);
336 ret = net_pmtu_update_mtu((struct sockaddr *)&dest_ipv6, 1600);
337 zassert_equal(ret, 1600, "PMTU IPv6 MTU update failed (%d)", ret);
338 entry = net_pmtu_get_entry((struct sockaddr *)&dest_ipv6);
339 zassert_equal(entry->mtu, 1600, "PMTU IPv6 MTU is not correct (%d)",
340 entry->mtu);
341
342 k_sleep(SMALL_SLEEP);
343
344 net_ipaddr_copy(&dest_ipv6.sin6_addr, &dest_ipv6_addr2);
345 ret = net_pmtu_update_mtu((struct sockaddr *)&dest_ipv6, 1700);
346 zassert_equal(ret, 0, "PMTU IPv6 MTU update failed (%d)", ret);
347 mtu = net_pmtu_get_mtu((struct sockaddr *)&dest_ipv6);
348 zassert_equal(mtu, 1700, "PMTU IPv6 MTU is not correct (%d)", mtu);
349
350 k_sleep(SMALL_SLEEP);
351
352 net_ipaddr_copy(&dest_ipv6.sin6_addr, &dest_ipv6_addr3);
353 ret = net_pmtu_update_mtu((struct sockaddr *)&dest_ipv6, 1800);
354 zassert_equal(ret, 0, "PMTU IPv6 MTU update failed (%d)", ret);
355 entry = net_pmtu_get_entry((struct sockaddr *)&dest_ipv6);
356 zassert_equal(entry->mtu, 1800, "PMTU IPv6 MTU is not correct (%d)",
357 entry->mtu);
358
359 net_ipaddr_copy(&dest_ipv6.sin6_addr, &dest_ipv6_addr_not_found);
360 ret = net_pmtu_get_mtu((struct sockaddr *)&dest_ipv6);
361 zassert_equal(ret, -ENOENT, "PMTU IPv6 MTU update succeed (%d)", ret);
362 entry = net_pmtu_get_entry((struct sockaddr *)&dest_ipv6);
363 zassert_equal(entry, NULL, "PMTU IPv6 MTU update succeed");
364 #else
365 ztest_test_skip();
366 #endif
367 }
368
ZTEST(net_pmtu_test_suite,test_pmtu_04_ipv4_overflow)369 ZTEST(net_pmtu_test_suite, test_pmtu_04_ipv4_overflow)
370 {
371 #if defined(CONFIG_NET_IPV4_PMTU)
372 struct sockaddr_in dest_ipv4;
373 struct net_pmtu_entry *entry;
374 int ret;
375
376 dest_ipv4.sin_family = AF_INET;
377
378 /* Create more entries than we have space */
379 net_ipaddr_copy(&dest_ipv4.sin_addr, &dest_ipv4_addr4);
380 ret = net_pmtu_update_mtu((struct sockaddr *)&dest_ipv4, 1450);
381 zassert_equal(ret, 0, "PMTU IPv4 MTU update failed (%d)", ret);
382
383 entry = net_pmtu_get_entry((struct sockaddr *)&dest_ipv4);
384 zassert_equal(entry->mtu, 1450, "PMTU IPv4 MTU is not correct (%d)",
385 entry->mtu);
386
387 k_sleep(SMALL_SLEEP);
388
389 net_ipaddr_copy(&dest_ipv4.sin_addr, &dest_ipv4_addr1);
390 entry = net_pmtu_get_entry((struct sockaddr *)&dest_ipv4);
391 zassert_is_null(entry, "PMTU IPv4 MTU found when it should not be");
392 #else
393 ztest_test_skip();
394 #endif
395 }
396
ZTEST(net_pmtu_test_suite,test_pmtu_04_ipv6_overflow)397 ZTEST(net_pmtu_test_suite, test_pmtu_04_ipv6_overflow)
398 {
399 #if defined(CONFIG_NET_IPV6_PMTU)
400 struct sockaddr_in6 dest_ipv6;
401 struct net_pmtu_entry *entry;
402 int ret;
403
404 dest_ipv6.sin6_family = AF_INET6;
405
406 /* Create more entries than we have space */
407 net_ipaddr_copy(&dest_ipv6.sin6_addr, &dest_ipv6_addr4);
408 ret = net_pmtu_update_mtu((struct sockaddr *)&dest_ipv6, 1650);
409 zassert_equal(ret, 0, "PMTU IPv6 MTU update failed (%d)", ret);
410
411 entry = net_pmtu_get_entry((struct sockaddr *)&dest_ipv6);
412 zassert_equal(entry->mtu, 1650, "PMTU IPv6 MTU is not correct (%d)",
413 entry->mtu);
414
415 k_sleep(SMALL_SLEEP);
416
417 /* If we have IPv4 PMTU enabled, then the oldest one is an IPv4 entry.
418 */
419 if (IS_ENABLED(CONFIG_NET_IPV4_PMTU)) {
420 struct sockaddr_in dest_ipv4;
421
422 dest_ipv4.sin_family = AF_INET;
423
424 net_ipaddr_copy(&dest_ipv4.sin_addr, &dest_ipv4_addr2);
425 entry = net_pmtu_get_entry((struct sockaddr *)&dest_ipv4);
426 } else {
427 net_ipaddr_copy(&dest_ipv6.sin6_addr, &dest_ipv6_addr1);
428 entry = net_pmtu_get_entry((struct sockaddr *)&dest_ipv6);
429 }
430
431 zassert_is_null(entry, "PMTU IPv6 MTU found when it should not be");
432 #else
433 ztest_test_skip();
434 #endif
435 }
436
test_bind(int sock,struct sockaddr * addr,socklen_t addrlen)437 static void test_bind(int sock, struct sockaddr *addr, socklen_t addrlen)
438 {
439 int ret;
440
441 ret = zsock_bind(sock, addr, addrlen);
442 zassert_equal(ret, 0, "bind failed with error %d", errno);
443 }
444
test_listen(int sock)445 static void test_listen(int sock)
446 {
447 zassert_equal(zsock_listen(sock, 1),
448 0,
449 "listen failed with error %d", errno);
450 }
451
test_connect(int sock,struct sockaddr * addr,socklen_t addrlen)452 static void test_connect(int sock, struct sockaddr *addr, socklen_t addrlen)
453 {
454 zassert_equal(zsock_connect(sock, addr, addrlen),
455 0,
456 "connect failed with error %d", errno);
457
458 if (IS_ENABLED(CONFIG_NET_TC_THREAD_PREEMPTIVE)) {
459 /* Let the connection proceed */
460 k_msleep(THREAD_SLEEP);
461 }
462 }
463
test_accept(int sock,int * new_sock,struct sockaddr * addr,socklen_t * addrlen)464 static void test_accept(int sock, int *new_sock, struct sockaddr *addr,
465 socklen_t *addrlen)
466 {
467 zassert_not_null(new_sock, "null newsock");
468
469 *new_sock = zsock_accept(sock, addr, addrlen);
470 zassert_true(*new_sock >= 0, "accept failed");
471 }
472
473 #if defined(CONFIG_NET_IPV6_PMTU)
get_v6_send_recv_sock(int * srv_sock,struct sockaddr_in6 * my_saddr,struct sockaddr_in6 * peer_saddr,uint16_t my_port,uint16_t peer_port)474 static int get_v6_send_recv_sock(int *srv_sock,
475 struct sockaddr_in6 *my_saddr,
476 struct sockaddr_in6 *peer_saddr,
477 uint16_t my_port,
478 uint16_t peer_port)
479 {
480 struct sockaddr addr;
481 socklen_t addrlen = sizeof(addr);
482 int new_sock;
483 int c_sock;
484 int s_sock;
485
486 prepare_sock_tcp_v6(PEER_IPV6_ADDR, peer_port, &s_sock, peer_saddr);
487 test_bind(s_sock, (struct sockaddr *)peer_saddr, sizeof(*peer_saddr));
488 test_listen(s_sock);
489
490 prepare_sock_tcp_v6(MY_IPV6_ADDR, my_port, &c_sock, my_saddr);
491 test_bind(c_sock, (struct sockaddr *)my_saddr, sizeof(*my_saddr));
492 test_connect(c_sock, (struct sockaddr *)peer_saddr, sizeof(*peer_saddr));
493
494 test_accept(s_sock, &new_sock, &addr, &addrlen);
495 zassert_equal(addrlen, sizeof(struct sockaddr_in6), "wrong addrlen");
496
497 *srv_sock = new_sock;
498
499 return c_sock;
500 }
501
create_icmpv6_ptb(struct net_if * iface,struct sockaddr_in6 * src,struct sockaddr_in6 * dst,uint32_t mtu,struct net_pkt ** pkt)502 static int create_icmpv6_ptb(struct net_if *iface,
503 struct sockaddr_in6 *src,
504 struct sockaddr_in6 *dst,
505 uint32_t mtu,
506 struct net_pkt **pkt)
507 {
508 struct net_icmpv6_ptb ptb_hdr;
509 struct net_pkt *ptb_pkt;
510 struct in6_addr *dest6;
511 struct in6_addr *src6;
512 int ret;
513
514 ptb_pkt = net_pkt_alloc_with_buffer(iface, sizeof(struct net_ipv6_hdr) +
515 sizeof(struct net_icmp_hdr) +
516 sizeof(struct net_icmpv6_ptb),
517 AF_INET6, IPPROTO_ICMPV6,
518 PKT_WAIT_TIME);
519 if (ptb_pkt == NULL) {
520 NET_DBG("No buffer");
521 return -ENOMEM;
522 }
523
524 dest6 = &dst->sin6_addr;
525 src6 = &src->sin6_addr;
526
527 ret = net_ipv6_create(ptb_pkt, src6, dest6);
528 if (ret < 0) {
529 LOG_ERR("Cannot create IPv6 pkt (%d)", ret);
530 return ret;
531 }
532
533 ret = net_icmpv6_create(ptb_pkt, NET_ICMPV6_PACKET_TOO_BIG, 0);
534 if (ret < 0) {
535 LOG_ERR("Cannot create ICMPv6 pkt (%d)", ret);
536 return ret;
537 }
538
539 ptb_hdr.mtu = htonl(mtu);
540
541 ret = net_pkt_write(ptb_pkt, &ptb_hdr, sizeof(ptb_hdr));
542 if (ret < 0) {
543 LOG_ERR("Cannot write payload (%d)", ret);
544 return ret;
545 }
546
547 net_pkt_cursor_init(ptb_pkt);
548 net_ipv6_finalize(ptb_pkt, IPPROTO_ICMPV6);
549
550 net_pkt_set_iface(ptb_pkt, iface);
551
552 *pkt = ptb_pkt;
553
554 return 0;
555 }
556 #endif
557
ZTEST(net_pmtu_test_suite,test_pmtu_05_ipv6_tcp)558 ZTEST(net_pmtu_test_suite, test_pmtu_05_ipv6_tcp)
559 {
560 #if defined(CONFIG_NET_IPV6_PMTU)
561 struct sockaddr_in6 dest_ipv6;
562 struct sockaddr_in6 s_saddr = { 0 }; /* peer */
563 struct sockaddr_in6 c_saddr = { 0 }; /* this host */
564 struct net_pkt *pkt = NULL;
565 int client_sock, server_sock;
566 uint16_t mtu;
567 int ret;
568
569 dest_ipv6.sin6_family = AF_INET6;
570
571 client_sock = get_v6_send_recv_sock(&server_sock, &c_saddr, &s_saddr,
572 MY_PORT, PEER_PORT);
573 zassert_true(client_sock >= 0, "Failed to create client socket");
574
575 /* Set initial MTU for the destination */
576 ret = net_pmtu_update_mtu((struct sockaddr *)&c_saddr, 4096);
577 zassert_true(ret >= 0, "PMTU IPv6 MTU update failed (%d)", ret);
578
579 /* Send an ICMPv6 "Packet too big" message from server to client which
580 * will update the PMTU entry.
581 */
582 ret = create_icmpv6_ptb(target_iface, &s_saddr, &c_saddr, 2048, &pkt);
583 zassert_equal(ret, 0, "Failed to create ICMPv6 PTB message");
584
585 ret = net_send_data(pkt);
586 zassert_equal(ret, 0, "Failed to send PTB message");
587
588 /* Check that the PMTU entry has been updated */
589 mtu = net_tcp_get_mtu((struct sockaddr *)&s_saddr);
590 zassert_equal(mtu, 2048, "PMTU IPv6 MTU is not correct (%d)", mtu);
591
592 (void)zsock_close(client_sock);
593 (void)zsock_close(server_sock);
594 #else
595 ztest_test_skip();
596 #endif /* CONFIG_NET_IPV6_PMTU */
597 }
598
599 #if defined(CONFIG_NET_IPV4_PMTU)
get_v4_send_recv_sock(int * srv_sock,struct sockaddr_in * my_saddr,struct sockaddr_in * peer_saddr,uint16_t my_port,uint16_t peer_port)600 static int get_v4_send_recv_sock(int *srv_sock,
601 struct sockaddr_in *my_saddr,
602 struct sockaddr_in *peer_saddr,
603 uint16_t my_port,
604 uint16_t peer_port)
605 {
606 struct sockaddr addr;
607 socklen_t addrlen = sizeof(addr);
608 int new_sock;
609 int c_sock;
610 int s_sock;
611
612 prepare_sock_tcp_v4(PEER_IPV4_ADDR, peer_port, &s_sock, peer_saddr);
613 test_bind(s_sock, (struct sockaddr *)peer_saddr, sizeof(*peer_saddr));
614 test_listen(s_sock);
615
616 prepare_sock_tcp_v4(MY_IPV4_ADDR, my_port, &c_sock, my_saddr);
617 test_bind(c_sock, (struct sockaddr *)my_saddr, sizeof(*my_saddr));
618 test_connect(c_sock, (struct sockaddr *)peer_saddr, sizeof(*peer_saddr));
619
620 test_accept(s_sock, &new_sock, &addr, &addrlen);
621 zassert_equal(addrlen, sizeof(struct sockaddr_in), "wrong addrlen");
622
623 *srv_sock = new_sock;
624
625 return c_sock;
626 }
627
create_icmpv4_dest_unreach(struct net_if * iface,struct sockaddr_in * src,struct sockaddr_in * dst,uint32_t mtu,struct net_pkt ** pkt)628 static int create_icmpv4_dest_unreach(struct net_if *iface,
629 struct sockaddr_in *src,
630 struct sockaddr_in *dst,
631 uint32_t mtu,
632 struct net_pkt **pkt)
633 {
634 struct net_icmpv4_dest_unreach du_hdr;
635 struct net_pkt *du_pkt;
636 struct in_addr *dest4;
637 struct in_addr *src4;
638 int ret;
639
640 du_pkt = net_pkt_alloc_with_buffer(iface, sizeof(struct net_ipv4_hdr) +
641 sizeof(struct net_icmp_hdr) +
642 sizeof(struct net_icmpv4_dest_unreach),
643 AF_INET, IPPROTO_ICMP,
644 PKT_WAIT_TIME);
645 if (du_pkt == NULL) {
646 NET_DBG("No buffer");
647 return -ENOMEM;
648 }
649
650 dest4 = &dst->sin_addr;
651 src4 = &src->sin_addr;
652
653 ret = net_ipv4_create(du_pkt, src4, dest4);
654 if (ret < 0) {
655 LOG_ERR("Cannot create IPv4 pkt (%d)", ret);
656 return ret;
657 }
658
659 ret = net_icmpv4_create(du_pkt, NET_ICMPV4_DST_UNREACH, 0);
660 if (ret < 0) {
661 LOG_ERR("Cannot create ICMPv4 pkt (%d)", ret);
662 return ret;
663 }
664
665 du_hdr.mtu = htons(mtu);
666
667 ret = net_pkt_write(du_pkt, &du_hdr, sizeof(du_hdr));
668 if (ret < 0) {
669 LOG_ERR("Cannot write payload (%d)", ret);
670 return ret;
671 }
672
673 net_pkt_cursor_init(du_pkt);
674 net_ipv4_finalize(du_pkt, IPPROTO_ICMP);
675
676 net_pkt_set_iface(du_pkt, iface);
677
678 *pkt = du_pkt;
679
680 return 0;
681 }
682 #endif
683
ZTEST(net_pmtu_test_suite,test_pmtu_05_ipv4_tcp)684 ZTEST(net_pmtu_test_suite, test_pmtu_05_ipv4_tcp)
685 {
686 #if defined(CONFIG_NET_IPV4_PMTU)
687 struct sockaddr_in dest_ipv4;
688 struct sockaddr_in s_saddr = { 0 }; /* peer */
689 struct sockaddr_in c_saddr = { 0 }; /* this host */
690 struct net_pkt *pkt = NULL;
691 int client_sock, server_sock;
692 uint16_t mtu;
693 int ret;
694
695 dest_ipv4.sin_family = AF_INET;
696
697 client_sock = get_v4_send_recv_sock(&server_sock, &c_saddr, &s_saddr,
698 MY_PORT, PEER_PORT);
699 zassert_true(client_sock >= 0, "Failed to create client socket");
700
701 /* Set initial MTU for the destination */
702 ret = net_pmtu_update_mtu((struct sockaddr *)&c_saddr, 4096);
703 zassert_true(ret >= 0, "PMTU IPv6 MTU update failed (%d)", ret);
704
705 /* Send an ICMPv4 "Destination Unreachable" message from server to client which
706 * will update the PMTU entry.
707 */
708 ret = create_icmpv4_dest_unreach(target_iface, &s_saddr, &c_saddr, 2048, &pkt);
709 zassert_equal(ret, 0, "Failed to create ICMPv4 Destination Unrechable message");
710
711 ret = net_send_data(pkt);
712 zassert_equal(ret, 0, "Failed to send Destination Unreachable message");
713
714 /* Check that the PMTU entry has been updated */
715 mtu = net_tcp_get_mtu((struct sockaddr *)&s_saddr);
716 zassert_equal(mtu, 2048, "PMTU IPv4 MTU is not correct (%d)", mtu);
717
718 (void)zsock_close(client_sock);
719 (void)zsock_close(server_sock);
720 #else
721 ztest_test_skip();
722 #endif /* CONFIG_NET_IPV4_PMTU */
723 }
724
ZTEST(net_pmtu_test_suite,test_pmtu_06_ipv4_event)725 ZTEST(net_pmtu_test_suite, test_pmtu_06_ipv4_event)
726 {
727 #if defined(CONFIG_NET_IPV4_PMTU) && WAIT_PROPERLY
728 struct sockaddr_in dest_ipv4;
729 int ret;
730
731 setup_mgmt_events();
732
733 is_pmtu_changed = false;
734
735 net_ipaddr_copy(&dest_ipv4.sin_addr, &dest_ipv4_addr1);
736 dest_ipv4.sin_family = AF_INET;
737
738 ret = net_pmtu_update_mtu((struct sockaddr *)&dest_ipv4, 1200);
739 zassert_equal(ret, 0, "PMTU IPv4 MTU update failed (%d)", ret);
740
741 if (k_sem_take(&wait_pmtu_changed, K_MSEC(WAIT_TIME))) {
742 zassert_true(0, "Timeout while waiting pmtu changed event");
743 }
744
745 zassert_true(is_pmtu_changed, "Did not catch pmtu changed event");
746
747 is_pmtu_changed = false;
748 #else
749 ztest_test_skip();
750 #endif /* CONFIG_NET_IPV4_PMTU */
751 }
752
ZTEST(net_pmtu_test_suite,test_pmtu_06_ipv6_event)753 ZTEST(net_pmtu_test_suite, test_pmtu_06_ipv6_event)
754 {
755 #if defined(CONFIG_NET_IPV6_PMTU) && WAIT_PROPERLY
756 struct sockaddr_in6 dest_ipv6;
757 int ret;
758
759 setup_mgmt_events();
760
761 is_pmtu_changed = false;
762
763 net_ipaddr_copy(&dest_ipv6.sin6_addr, &dest_ipv6_addr1);
764 dest_ipv6.sin6_family = AF_INET6;
765
766 ret = net_pmtu_update_mtu((struct sockaddr *)&dest_ipv6, 1500);
767 zassert_equal(ret, 0, "PMTU IPv6 MTU update failed (%d)", ret);
768
769 if (k_sem_take(&wait_pmtu_changed, K_MSEC(WAIT_TIME))) {
770 zassert_true(0, "Timeout while waiting pmtu changed event");
771 }
772
773 zassert_true(is_pmtu_changed, "Did not catch pmtu changed event");
774
775 is_pmtu_changed = false;
776 #else
777 ztest_test_skip();
778 #endif /* CONFIG_NET_IPV6_PMTU */
779 }
780
ZTEST(net_pmtu_test_suite,test_pmtu_07_socket_api_ipv4)781 ZTEST(net_pmtu_test_suite, test_pmtu_07_socket_api_ipv4)
782 {
783 #if defined(CONFIG_NET_IPV4_PMTU)
784 struct sockaddr_in s_saddr = { 0 }; /* peer */
785 struct sockaddr_in c_saddr = { 0 }; /* this host */
786 int ret, client_sock, server_sock;
787 size_t optlen;
788 int optval;
789 int err;
790
791 client_sock = get_v4_send_recv_sock(&server_sock, &c_saddr, &s_saddr,
792 MY_PORT + 1, PEER_PORT + 1);
793 zassert_true(client_sock >= 0, "Failed to create client socket");
794
795 /* Set initial MTU for the destination */
796 ret = net_pmtu_update_mtu((struct sockaddr *)&c_saddr, 4096);
797 zassert_true(ret >= 0, "PMTU IPv4 MTU update failed (%d)", ret);
798
799 optval = 0; optlen = sizeof(int);
800 ret = zsock_getsockopt(client_sock, IPPROTO_IP, IP_MTU, &optval, &optlen);
801 err = -errno;
802 zexpect_equal(ret, 0, "setsockopt failed (%d)", err);
803 zexpect_equal(optlen, sizeof(int), "setsockopt optlen (%d)", optlen);
804 zexpect_equal(optval, 4096, "setsockopt mtu (%d)", optval);
805
806 optval = 0; optlen = sizeof(int);
807 ret = zsock_setsockopt(client_sock, IPPROTO_IP, IP_MTU, &optval, optlen);
808 err = -errno;
809 zexpect_equal(ret, -1, "setsockopt failed (%d)", err);
810 zexpect_equal(optlen, sizeof(int), "setsockopt optlen (%d)", optlen);
811 zexpect_equal(optval, 0, "setsockopt mtu (%d)", optval);
812
813 (void)zsock_close(client_sock);
814 (void)zsock_close(server_sock);
815 #else
816 ztest_test_skip();
817 #endif /* CONFIG_NET_IPV4_PMTU */
818 }
819
ZTEST(net_pmtu_test_suite,test_pmtu_08_socket_api_ipv6)820 ZTEST(net_pmtu_test_suite, test_pmtu_08_socket_api_ipv6)
821 {
822 #if defined(CONFIG_NET_IPV6_PMTU)
823 struct sockaddr_in6 s_saddr = { 0 }; /* peer */
824 struct sockaddr_in6 c_saddr = { 0 }; /* this host */
825 int ret, client_sock, server_sock;
826 size_t optlen;
827 int optval;
828 int err;
829
830 client_sock = get_v6_send_recv_sock(&server_sock, &c_saddr, &s_saddr,
831 MY_PORT + 2, PEER_PORT + 2);
832 zassert_true(client_sock >= 0, "Failed to create client socket");
833
834 /* Set initial MTU for the destination */
835 ret = net_pmtu_update_mtu((struct sockaddr *)&c_saddr, 2048);
836 zassert_true(ret >= 0, "PMTU IPv6 MTU update failed (%d)", ret);
837
838 optval = 0; optlen = sizeof(int);
839 ret = zsock_getsockopt(client_sock, IPPROTO_IPV6, IPV6_MTU, &optval, &optlen);
840 err = -errno;
841 zexpect_equal(ret, 0, "getsockopt failed (%d)", err);
842 zexpect_equal(optlen, sizeof(int), "getsockopt optlen (%d)", optlen);
843 zexpect_equal(optval, 2048, "getsockopt mtu (%d)", optval);
844
845 optval = 1500; optlen = sizeof(int);
846 ret = zsock_setsockopt(client_sock, IPPROTO_IPV6, IPV6_MTU, &optval, optlen);
847 err = -errno;
848 zexpect_equal(ret, 0, "setsockopt failed (%d)", err);
849 zexpect_equal(optlen, sizeof(int), "setsockopt optlen (%d)", optlen);
850 zexpect_equal(optval, 1500, "setsockopt mtu (%d)", optval);
851
852 optval = 0; optlen = sizeof(int);
853 ret = zsock_getsockopt(client_sock, IPPROTO_IPV6, IPV6_MTU, &optval, &optlen);
854 err = -errno;
855 zexpect_equal(ret, 0, "getsockopt failed (%d)", err);
856 zexpect_equal(optlen, sizeof(int), "getsockopt optlen (%d)", optlen);
857 zexpect_equal(optval, 1500, "getsockopt mtu (%d)", optval);
858
859 (void)zsock_close(client_sock);
860 (void)zsock_close(server_sock);
861 #else
862 ztest_test_skip();
863 #endif /* CONFIG_NET_IPV6_PMTU */
864 }
865
866 ZTEST_SUITE(net_pmtu_test_suite, NULL, test_setup, NULL, NULL, NULL);
867