1 /*
2  * Copyright (c) 2023 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/types.h>
8 #include <stdbool.h>
9 #include <stddef.h>
10 #include <string.h>
11 #include <errno.h>
12 #include <zephyr/linker/sections.h>
13 
14 #include <zephyr/ztest.h>
15 
16 #include <zephyr/net/net_if.h>
17 #include <zephyr/net/dummy.h>
18 #include <zephyr/net/conn_mgr_monitor.h>
19 #include <zephyr/net/conn_mgr_connectivity.h>
20 #include "conn_mgr_private.h"
21 #include "test_ifaces.h"
22 #include <zephyr/net/net_ip.h>
23 
24 #include <zephyr/logging/log.h>
25 
26 /* Time to wait for NET_MGMT events to finish firing */
27 #define EVENT_WAIT_TIME_SHORT  K_MSEC(10)
28 #define EVENT_WAIT_TIME_MEDIUM K_MSEC(100)
29 #define EVENT_WAIT_TIME        K_MSEC(200)
30 
31 
32 /* Time to wait for IPv6 DAD-gated events to finish.
33  * Equivalent to EVENT_WAIT_TIME if DAD is dissabled.
34  */
35 #if defined(CONFIG_NET_IPV6_DAD)
36 #define DAD_WAIT_TIME K_MSEC(110)
37 #else
38 #define DAD_WAIT_TIME EVENT_WAIT_TIME
39 #endif
40 
41 #define TEST_EXPECT_L4_CONNECTED         BIT(NET_EVENT_L4_CMD_CONNECTED)
42 #define TEST_EXPECT_L4_DISCONNECTED      BIT(NET_EVENT_L4_CMD_DISCONNECTED)
43 #define TEST_EXPECT_L4_IPV6_CONNECTED    BIT(NET_EVENT_L4_CMD_IPV6_CONNECTED)
44 #define TEST_EXPECT_L4_IPV6_DISCONNECTED BIT(NET_EVENT_L4_CMD_IPV6_DISCONNECTED)
45 #define TEST_EXPECT_L4_IPV4_CONNECTED    BIT(NET_EVENT_L4_CMD_IPV4_CONNECTED)
46 #define TEST_EXPECT_L4_IPV4_DISCONNECTED BIT(NET_EVENT_L4_CMD_IPV4_DISCONNECTED)
47 
48 #define TEST_EXPECT_CLEAR(event) (global_stats.expected_events &= ~event)
49 
50 /* IP addresses -- Two of each are needed because address sharing will cause address removal to
51  * fail silently (Address is only removed from one iface).
52  */
53 static struct in_addr test_ipv4_a = { { { 10, 0, 0, 1 } } };
54 static struct in_addr test_ipv4_b = { { { 10, 0, 0, 2 } } };
55 static struct in6_addr test_ipv6_a = { { {
56 	0x20, 0x01, 0x0d, 0xb8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1
57 } } };
58 static struct in6_addr test_ipv6_b = { { {
59 	0x20, 0x01, 0x0d, 0xb8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2
60 } } };
61 
62 
63 /* Helpers */
reset_test_iface(struct net_if * iface)64 static void reset_test_iface(struct net_if *iface)
65 {
66 	struct in6_addr *ll_ipv6;
67 
68 	if (net_if_is_admin_up(iface)) {
69 		(void)net_if_down(iface);
70 	}
71 
72 	net_if_ipv4_addr_rm(iface, &test_ipv4_a);
73 	net_if_ipv4_addr_rm(iface, &test_ipv4_b);
74 	net_if_ipv6_addr_rm(iface, &test_ipv6_a);
75 	net_if_ipv6_addr_rm(iface, &test_ipv6_b);
76 
77 	/* DAD adds the link-local address automatically. Check for it, and remove it if present. */
78 	ll_ipv6 = net_if_ipv6_get_ll(iface, NET_ADDR_ANY_STATE);
79 	if (ll_ipv6) {
80 		net_if_ipv6_addr_rm(iface, ll_ipv6);
81 	}
82 
83 	conn_mgr_watch_iface(iface);
84 }
85 
86 /* Thread-safe test statistics */
87 static K_MUTEX_DEFINE(stats_mutex);
88 static K_SEM_DEFINE(event_sem, 0, 1);
89 
90 static struct test_stats {
91 	/** IPv4 connectivity event counters */
92 	int event_count_ipv4; /* any */
93 	int conn_count_ipv4;  /* connect */
94 	int dconn_count_ipv4; /* disconnect */
95 
96 	/** IPv6 connectivity event counters */
97 	int event_count_ipv6; /* any */
98 	int conn_count_ipv6;  /* connect */
99 	int dconn_count_ipv6; /* disconnect */
100 
101 	/** General connectivity event counters */
102 	int event_count_gen; /* any */
103 	int conn_count_gen;  /* connect */
104 	int dconn_count_gen; /* disconnect */
105 
106 	/** The iface blamed for the last disconnect event */
107 	struct net_if *dconn_iface_gen;
108 	struct net_if *dconn_iface_ipv4;
109 	struct net_if *dconn_iface_ipv6;
110 
111 	/** The iface blamed for the last connect event */
112 	struct net_if *conn_iface_gen;
113 	struct net_if *conn_iface_ipv4;
114 	struct net_if *conn_iface_ipv6;
115 
116 	uint32_t expected_events;
117 } global_stats;
118 
reset_stats(void)119 static void reset_stats(void)
120 {
121 	k_mutex_lock(&stats_mutex, K_FOREVER);
122 
123 	global_stats.conn_count_gen = 0;
124 	global_stats.dconn_count_gen = 0;
125 	global_stats.event_count_gen = 0;
126 	global_stats.dconn_iface_gen = NULL;
127 	global_stats.conn_iface_gen = NULL;
128 
129 	global_stats.conn_count_ipv4 = 0;
130 	global_stats.dconn_count_ipv4 = 0;
131 	global_stats.event_count_ipv4 = 0;
132 	global_stats.dconn_iface_ipv4 = NULL;
133 	global_stats.conn_iface_ipv4 = NULL;
134 
135 	global_stats.conn_count_ipv6 = 0;
136 	global_stats.dconn_count_ipv6 = 0;
137 	global_stats.event_count_ipv6 = 0;
138 	global_stats.dconn_iface_ipv6 = NULL;
139 	global_stats.conn_iface_ipv6 = NULL;
140 
141 	global_stats.expected_events = 0;
142 
143 	k_mutex_unlock(&stats_mutex);
144 }
145 
146 /**
147  * @brief Copy and then reset global test stats.
148  *
149  * @return struct test_stats -- The copy of the global test stats struct before it was reset
150  */
get_reset_stats(void)151 static struct test_stats get_reset_stats(void)
152 {
153 	struct test_stats copy;
154 
155 	k_mutex_lock(&stats_mutex, K_FOREVER);
156 	copy = global_stats;
157 	reset_stats();
158 	k_mutex_unlock(&stats_mutex);
159 	return copy;
160 }
161 
162 /* Callback hooks */
163 struct net_mgmt_event_callback l4_callback;
164 
l4_handler(struct net_mgmt_event_callback * cb,uint32_t event,struct net_if * iface)165 void l4_handler(struct net_mgmt_event_callback *cb, uint32_t event, struct net_if *iface)
166 {
167 	if (event == NET_EVENT_L4_CONNECTED) {
168 		k_mutex_lock(&stats_mutex, K_FOREVER);
169 		global_stats.conn_count_gen += 1;
170 		global_stats.event_count_gen += 1;
171 		global_stats.conn_iface_gen = iface;
172 		TEST_EXPECT_CLEAR(TEST_EXPECT_L4_CONNECTED);
173 		k_mutex_unlock(&stats_mutex);
174 	} else if (event == NET_EVENT_L4_DISCONNECTED) {
175 		k_mutex_lock(&stats_mutex, K_FOREVER);
176 		global_stats.dconn_count_gen += 1;
177 		global_stats.event_count_gen += 1;
178 		global_stats.dconn_iface_gen = iface;
179 		TEST_EXPECT_CLEAR(TEST_EXPECT_L4_DISCONNECTED);
180 		k_mutex_unlock(&stats_mutex);
181 	}
182 
183 	if (global_stats.expected_events == 0) {
184 		k_sem_give(&event_sem);
185 	}
186 }
187 
188 struct net_mgmt_event_callback conn_callback;
189 
conn_handler(struct net_mgmt_event_callback * cb,uint32_t event,struct net_if * iface)190 void conn_handler(struct net_mgmt_event_callback *cb, uint32_t event, struct net_if *iface)
191 {
192 	if (event == NET_EVENT_L4_IPV6_CONNECTED) {
193 		k_mutex_lock(&stats_mutex, K_FOREVER);
194 		global_stats.conn_count_ipv6 += 1;
195 		global_stats.event_count_ipv6 += 1;
196 		global_stats.conn_iface_ipv6 = iface;
197 		TEST_EXPECT_CLEAR(TEST_EXPECT_L4_IPV6_CONNECTED);
198 		k_mutex_unlock(&stats_mutex);
199 	} else if (event == NET_EVENT_L4_IPV6_DISCONNECTED) {
200 		k_mutex_lock(&stats_mutex, K_FOREVER);
201 		global_stats.dconn_count_ipv6 += 1;
202 		global_stats.event_count_ipv6 += 1;
203 		global_stats.dconn_iface_ipv6 = iface;
204 		TEST_EXPECT_CLEAR(TEST_EXPECT_L4_IPV6_DISCONNECTED);
205 		k_mutex_unlock(&stats_mutex);
206 	} else if (event == NET_EVENT_L4_IPV4_CONNECTED) {
207 		k_mutex_lock(&stats_mutex, K_FOREVER);
208 		global_stats.conn_count_ipv4 += 1;
209 		global_stats.event_count_ipv4 += 1;
210 		global_stats.conn_iface_ipv4 = iface;
211 		TEST_EXPECT_CLEAR(TEST_EXPECT_L4_IPV4_CONNECTED);
212 		k_mutex_unlock(&stats_mutex);
213 	} else if (event == NET_EVENT_L4_IPV4_DISCONNECTED) {
214 		k_mutex_lock(&stats_mutex, K_FOREVER);
215 		global_stats.dconn_count_ipv4 += 1;
216 		global_stats.event_count_ipv4 += 1;
217 		global_stats.dconn_iface_ipv4 = iface;
218 		TEST_EXPECT_CLEAR(TEST_EXPECT_L4_IPV4_DISCONNECTED);
219 		k_mutex_unlock(&stats_mutex);
220 	}
221 
222 	if (global_stats.expected_events == 0) {
223 		k_sem_give(&event_sem);
224 	}
225 }
226 
wait_for_events(uint32_t event_mask,k_timeout_t timeout)227 static void wait_for_events(uint32_t event_mask, k_timeout_t timeout)
228 {
229 	k_mutex_lock(&stats_mutex, K_FOREVER);
230 	k_sem_reset(&event_sem);
231 	global_stats.expected_events = event_mask;
232 	k_mutex_unlock(&stats_mutex);
233 
234 	(void)k_sem_take(&event_sem, timeout);
235 
236 	/* Add small extra sleep to give any unexpected events to show up. */
237 	k_sleep(EVENT_WAIT_TIME_SHORT);
238 }
239 
240 /* Test suite shared functions & routines */
241 
conn_mgr_setup(void)242 static void *conn_mgr_setup(void)
243 {
244 	net_mgmt_init_event_callback(
245 		&l4_callback, l4_handler, NET_EVENT_L4_CONNECTED | NET_EVENT_L4_DISCONNECTED
246 	);
247 	net_mgmt_add_event_callback(&l4_callback);
248 
249 	net_mgmt_init_event_callback(
250 		&conn_callback, conn_handler,
251 		NET_EVENT_L4_IPV6_CONNECTED | NET_EVENT_L4_IPV6_DISCONNECTED |
252 		NET_EVENT_L4_IPV4_CONNECTED | NET_EVENT_L4_IPV4_DISCONNECTED
253 	);
254 	net_mgmt_add_event_callback(&conn_callback);
255 	return NULL;
256 }
257 
258 
conn_mgr_before(void * data)259 static void conn_mgr_before(void *data)
260 {
261 	ARG_UNUSED(data);
262 
263 	reset_test_iface(if_simp_a);
264 	reset_test_iface(if_simp_b);
265 	reset_test_iface(if_conn_a);
266 	reset_test_iface(if_conn_b);
267 
268 	/* Allow any triggered events to shake out */
269 	k_sleep(K_MSEC(50));
270 
271 	reset_stats();
272 }
273 
274 /**
275  * @brief Cycles two ifaces through several transitions from readiness to unreadiness.
276  *
277  * Ifaces are assigned a single IPv4 address at the start, and cycled through oper-states, since
278  * the other manners in which an iface can become L4-ready are covered by cycle_iface_pre_ready
279  *
280  * It is not necessary to cover all possible state transitions, only half of them, since
281  * this will be called twice by the test suites for each combination of iface type (except
282  * combinations where both ifaces are of the same type).
283  */
284 
cycle_ready_ifaces(struct net_if * ifa,struct net_if * ifb)285 static void cycle_ready_ifaces(struct net_if *ifa, struct net_if *ifb)
286 {
287 	struct test_stats stats;
288 
289 	/* Add IPv4 addresses */
290 	net_if_ipv4_addr_add(ifa, &test_ipv4_a, NET_ADDR_MANUAL, 0);
291 	net_if_ipv4_addr_add(ifb, &test_ipv4_b, NET_ADDR_MANUAL, 0);
292 
293 	/* Expect no events */
294 	k_sleep(EVENT_WAIT_TIME_SHORT);
295 	stats = get_reset_stats();
296 	zassert_equal(stats.event_count_gen, 0,
297 		"No events should be fired if connectivity availability did not change.");
298 
299 	/* Take A up */
300 	zassert_equal(net_if_up(ifa), 0, "net_if_up should succeed for ifa.");
301 
302 	/* Expect connectivity gained */
303 	wait_for_events(TEST_EXPECT_L4_CONNECTED, EVENT_WAIT_TIME);
304 	stats = get_reset_stats();
305 	zassert_equal(stats.conn_count_gen, 1,
306 		"NET_EVENT_L4_CONNECTED should be fired when connectivity is gained.");
307 	zassert_equal(stats.event_count_gen, 1,
308 		"Only NET_EVENT_L4_CONNECTED should be fired when connectivity is gained.");
309 	zassert_equal(stats.conn_iface_gen, ifa, "ifa should be blamed.");
310 
311 	/* Take B up */
312 	zassert_equal(net_if_up(ifb), 0, "net_if_up should succeed for ifb.");
313 
314 	/* Expect no events */
315 	k_sleep(EVENT_WAIT_TIME_SHORT);
316 	stats = get_reset_stats();
317 	zassert_equal(stats.event_count_gen, 0,
318 		"No events should be fired if connectivity availability did not change.");
319 
320 	/* Take A down */
321 	zassert_equal(net_if_down(ifa), 0, "net_if_down should succeed for ifa.");
322 
323 	/* Expect no events */
324 	k_sleep(EVENT_WAIT_TIME_SHORT);
325 	stats = get_reset_stats();
326 	zassert_equal(stats.event_count_gen, 0,
327 		"No events should be fired if connectivity availability did not change.");
328 
329 	/* Take B down */
330 	zassert_equal(net_if_down(ifb), 0, "net_if_down should succeed for ifb.");
331 
332 	/* Expect connectivity loss */
333 	wait_for_events(TEST_EXPECT_L4_DISCONNECTED, EVENT_WAIT_TIME);
334 	stats = get_reset_stats();
335 	zassert_equal(stats.dconn_count_gen, 1,
336 		"NET_EVENT_L4_DISCONNECTED should be fired when connectivity is lost.");
337 	zassert_equal(stats.event_count_gen, 1,
338 		"Only NET_EVENT_L4_DISCONNECTED should be fired when connectivity is lost.");
339 	zassert_equal(stats.dconn_iface_gen, ifb, "ifb should be blamed.");
340 }
341 
342 /**
343  * @brief Ignores and then toggles ifb's readiness several times, ensuring no events are fired.
344  *
345  * At several points, change the readiness state of ifa and ensure events are fired.
346  *
347  * Steps which bring ifa or ifb online wait for the DAD delay to allow IPv6 events to finish.
348  * For test builds that have DAD disabled, this is equivalent to the usual event wait time.
349  *
350  * @param ifa
351  * @param ifb
352  */
cycle_ignored_iface(struct net_if * ifa,struct net_if * ifb)353 static void cycle_ignored_iface(struct net_if *ifa, struct net_if *ifb)
354 {
355 	struct test_stats stats;
356 	printk("cycle_ignored_iface\n");
357 
358 	/* Ignore B */
359 	conn_mgr_ignore_iface(ifb);
360 
361 	/* Add IPv4 and IPv6 addresses so that all possible event types are fired. */
362 	net_if_ipv4_addr_add(ifa, &test_ipv4_a, NET_ADDR_MANUAL, 0);
363 	net_if_ipv4_addr_add(ifb, &test_ipv4_b, NET_ADDR_MANUAL, 0);
364 	net_if_ipv6_addr_add(ifa, &test_ipv6_a, NET_ADDR_MANUAL, 0);
365 	net_if_ipv6_addr_add(ifb, &test_ipv6_b, NET_ADDR_MANUAL, 0);
366 
367 	/* Set one: Change A state between B state toggles */
368 
369 	/* Take B up */
370 	zassert_equal(net_if_up(ifb), 0, "net_if_up should succeed for ifb.");
371 
372 	/* Expect no events.
373 	 * Wait for the DAD delay since IPv6 connected events might be delayed by this amount.
374 	 */
375 	printk("Expect no events.\n");
376 	k_sleep(DAD_WAIT_TIME);
377 	stats = get_reset_stats();
378 	zassert_equal(stats.event_count_gen, 0,
379 		"No events should be fired if connectivity availability did not change.");
380 	zassert_equal(stats.event_count_ipv4, 0,
381 		"No events should be fired if connectivity availability did not change.");
382 	zassert_equal(stats.event_count_ipv6, 0,
383 		"No events should be fired if connectivity availability did not change.");
384 
385 	/* Take B down */
386 	zassert_equal(net_if_down(ifb), 0, "net_if_down should succeed for ifb.");
387 
388 	/* Expect no events */
389 	k_sleep(EVENT_WAIT_TIME_SHORT);
390 	stats = get_reset_stats();
391 	zassert_equal(stats.event_count_gen, 0,
392 		"No events should be fired if connectivity availability did not change.");
393 	zassert_equal(stats.event_count_ipv4, 0,
394 		"No events should be fired if connectivity availability did not change.");
395 	zassert_equal(stats.event_count_ipv6, 0,
396 		"No events should be fired if connectivity availability did not change.");
397 
398 	/* Take A up */
399 	zassert_equal(net_if_up(ifa), 0, "net_if_up should succeed for ifa.");
400 
401 	/* Expect connectivity gained */
402 	wait_for_events(TEST_EXPECT_L4_CONNECTED |
403 			TEST_EXPECT_L4_IPV4_CONNECTED |
404 			TEST_EXPECT_L4_IPV6_CONNECTED,
405 			EVENT_WAIT_TIME);
406 	stats = get_reset_stats();
407 	zassert_equal(stats.conn_count_gen, 1,
408 		"NET_EVENT_L4_CONNECTED should be fired when connectivity is gained.");
409 	zassert_equal(stats.event_count_gen, 1,
410 		"Only NET_EVENT_L4_CONNECTED should be fired when connectivity is gained.");
411 	zassert_equal(stats.conn_count_ipv6, 1,
412 		"NET_EVENT_L4_IPV6_CONNECTED should be fired when connectivity is gained.");
413 	zassert_equal(stats.event_count_ipv6, 1,
414 		"Only NET_EVENT_L4_IPV6_CONNECTED should be fired when connectivity is gained.");
415 	zassert_equal(stats.conn_count_ipv4, 1,
416 		"NET_EVENT_L4_IPV4_CONNECTED should be fired when connectivity is gained.");
417 	zassert_equal(stats.event_count_ipv4, 1,
418 		"Only NET_EVENT_L4_IPV4_CONNECTED should be fired when connectivity is gained.");
419 	zassert_equal(stats.conn_iface_gen, ifa, "ifa should be blamed.");
420 	zassert_equal(stats.conn_iface_ipv4, ifa, "ifa should be blamed.");
421 	zassert_equal(stats.conn_iface_ipv6, ifa, "ifa should be blamed.");
422 
423 	/* Take B up */
424 	zassert_equal(net_if_up(ifb), 0, "net_if_up should succeed for ifb.");
425 
426 	/* Expect no events */
427 	k_sleep(DAD_WAIT_TIME);
428 	stats = get_reset_stats();
429 	zassert_equal(stats.event_count_gen, 0,
430 		"No events should be fired if connectivity availability did not change.");
431 	zassert_equal(stats.event_count_ipv4, 0,
432 		"No events should be fired if connectivity availability did not change.");
433 	zassert_equal(stats.event_count_ipv6, 0,
434 		"No events should be fired if connectivity availability did not change.");
435 
436 	/* Take B down */
437 	zassert_equal(net_if_down(ifb), 0, "net_if_down should succeed for ifb.");
438 
439 	/* Expect no events */
440 	k_sleep(EVENT_WAIT_TIME_SHORT);
441 	stats = get_reset_stats();
442 	zassert_equal(stats.event_count_gen, 0,
443 		"No events should be fired if connectivity availability did not change.");
444 	zassert_equal(stats.event_count_ipv4, 0,
445 		"No events should be fired if connectivity availability did not change.");
446 	zassert_equal(stats.event_count_ipv6, 0,
447 		"No events should be fired if connectivity availability did not change.");
448 
449 	/* Take A down */
450 	zassert_equal(net_if_down(ifa), 0, "net_if_down should succeed for ifa.");
451 
452 	/* Expect connectivity lost */
453 	wait_for_events(TEST_EXPECT_L4_DISCONNECTED |
454 			TEST_EXPECT_L4_IPV4_DISCONNECTED |
455 			TEST_EXPECT_L4_IPV6_DISCONNECTED,
456 			EVENT_WAIT_TIME);
457 	stats = get_reset_stats();
458 	zassert_equal(stats.dconn_count_gen, 1,
459 		"NET_EVENT_L4_DISCONNECTED should be fired when connectivity is lost.");
460 	zassert_equal(stats.event_count_gen, 1,
461 		"Only NET_EVENT_L4_DISCONNECTED should be fired when connectivity is lost.");
462 	zassert_equal(stats.dconn_count_ipv6, 1,
463 		"NET_EVENT_L4_IPV6_DISCONNECTED should be fired when connectivity is lost.");
464 	zassert_equal(stats.event_count_ipv6, 1,
465 		"Only NET_EVENT_L4_IPV6_DISCONNECTED should be fired when connectivity is lost.");
466 	zassert_equal(stats.dconn_count_ipv4, 1,
467 		"NET_EVENT_L4_IPV4_DISCONNECTED should be fired when connectivity is lost.");
468 	zassert_equal(stats.event_count_ipv4, 1,
469 		"Only NET_EVENT_L4_IPV4_DISCONNECTED should be fired when connectivity is lost.");
470 	zassert_equal(stats.dconn_iface_gen, ifa, "ifa should be blamed.");
471 	zassert_equal(stats.dconn_iface_ipv4, ifa, "ifa should be blamed.");
472 	zassert_equal(stats.dconn_iface_ipv6, ifa, "ifa should be blamed.");
473 
474 
475 	/* Set two: Change A state during B state toggles */
476 
477 	/* Take B up */
478 	zassert_equal(net_if_up(ifb), 0, "net_if_up should succeed for ifb.");
479 
480 	/* Expect no events */
481 	k_sleep(DAD_WAIT_TIME);
482 	stats = get_reset_stats();
483 	zassert_equal(stats.event_count_gen, 0,
484 		"No events should be fired if connectivity availability did not change.");
485 	zassert_equal(stats.event_count_ipv4, 0,
486 		"No events should be fired if connectivity availability did not change.");
487 	zassert_equal(stats.event_count_ipv6, 0,
488 		"No events should be fired if connectivity availability did not change.");
489 
490 	/* Take A up */
491 	zassert_equal(net_if_up(ifa), 0, "net_if_up should succeed for ifa.");
492 
493 	/* Expect connectivity gained */
494 	wait_for_events(TEST_EXPECT_L4_CONNECTED |
495 			TEST_EXPECT_L4_IPV4_CONNECTED |
496 			TEST_EXPECT_L4_IPV6_CONNECTED,
497 			EVENT_WAIT_TIME);
498 	stats = get_reset_stats();
499 	zassert_equal(stats.conn_count_gen, 1,
500 		"NET_EVENT_L4_CONNECTED should be fired when connectivity is gained.");
501 	zassert_equal(stats.event_count_gen, 1,
502 		"Only NET_EVENT_L4_CONNECTED should be fired when connectivity is gained.");
503 	zassert_equal(stats.conn_count_ipv6, 1,
504 		"NET_EVENT_L4_IPV6_CONNECTED should be fired when connectivity is gained.");
505 	zassert_equal(stats.event_count_ipv6, 1,
506 		"Only NET_EVENT_L4_IPV6_CONNECTED should be fired when connectivity is gained.");
507 	zassert_equal(stats.conn_count_ipv4, 1,
508 		"NET_EVENT_L4_IPV4_CONNECTED should be fired when connectivity is gained.");
509 	zassert_equal(stats.event_count_ipv4, 1,
510 		"Only NET_EVENT_L4_IPV4_CONNECTED should be fired when connectivity is gained.");
511 	zassert_equal(stats.conn_iface_gen, ifa, "ifa should be blamed.");
512 	zassert_equal(stats.conn_iface_ipv4, ifa, "ifa should be blamed.");
513 	zassert_equal(stats.conn_iface_ipv6, ifa, "ifa should be blamed.");
514 
515 	/* Take B down */
516 	zassert_equal(net_if_down(ifb), 0, "net_if_down should succeed for ifb.");
517 
518 	/* Expect no events */
519 	k_sleep(EVENT_WAIT_TIME_SHORT);
520 	stats = get_reset_stats();
521 	zassert_equal(stats.event_count_gen, 0,
522 		"No events should be fired if connectivity availability did not change.");
523 	zassert_equal(stats.event_count_ipv4, 0,
524 		"No events should be fired if connectivity availability did not change.");
525 	zassert_equal(stats.event_count_ipv6, 0,
526 		"No events should be fired if connectivity availability did not change.");
527 
528 
529 	/* Take B up */
530 	zassert_equal(net_if_up(ifb), 0, "net_if_up should succeed for ifb.");
531 
532 	/* Expect no events */
533 	k_sleep(DAD_WAIT_TIME);
534 	stats = get_reset_stats();
535 	zassert_equal(stats.event_count_gen, 0,
536 		"No events should be fired if connectivity availability did not change.");
537 	zassert_equal(stats.event_count_ipv4, 0,
538 		"No events should be fired if connectivity availability did not change.");
539 	zassert_equal(stats.event_count_ipv6, 0,
540 		"No events should be fired if connectivity availability did not change.");
541 
542 	/* Take A down */
543 	zassert_equal(net_if_down(ifa), 0, "net_if_down should succeed for ifa.");
544 
545 	/* Expect connectivity lost */
546 	wait_for_events(TEST_EXPECT_L4_DISCONNECTED |
547 			TEST_EXPECT_L4_IPV4_DISCONNECTED |
548 			TEST_EXPECT_L4_IPV6_DISCONNECTED,
549 			EVENT_WAIT_TIME);
550 	stats = get_reset_stats();
551 	zassert_equal(stats.dconn_count_gen, 1,
552 		"NET_EVENT_L4_DISCONNECTED should be fired when connectivity is lost.");
553 	zassert_equal(stats.event_count_gen, 1,
554 		"Only NET_EVENT_L4_DISCONNECTED should be fired when connectivity is lost.");
555 	zassert_equal(stats.dconn_count_ipv6, 1,
556 		"NET_EVENT_L4_IPV6_DISCONNECTED should be fired when connectivity is lost.");
557 	zassert_equal(stats.event_count_ipv6, 1,
558 		"Only NET_EVENT_L4_IPV6_DISCONNECTED should be fired when connectivity is lost.");
559 	zassert_equal(stats.dconn_count_ipv4, 1,
560 		"NET_EVENT_L4_IPV4_DISCONNECTED should be fired when connectivity is lost.");
561 	zassert_equal(stats.event_count_ipv4, 1,
562 		"Only NET_EVENT_L4_IPV4_DISCONNECTED should be fired when connectivity is lost.");
563 	zassert_equal(stats.dconn_iface_gen, ifa, "ifa should be blamed.");
564 	zassert_equal(stats.dconn_iface_ipv4, ifa, "ifa should be blamed.");
565 	zassert_equal(stats.dconn_iface_ipv6, ifa, "ifa should be blamed.");
566 
567 	/* Take B down */
568 	zassert_equal(net_if_down(ifb), 0, "net_if_down should succeed for ifb.");
569 
570 	/* Expect no events */
571 	k_sleep(EVENT_WAIT_TIME_SHORT);
572 	stats = get_reset_stats();
573 	zassert_equal(stats.event_count_gen, 0,
574 		"No events should be fired if connectivity availability did not change.");
575 	zassert_equal(stats.event_count_ipv4, 0,
576 		"No events should be fired if connectivity availability did not change.");
577 	zassert_equal(stats.event_count_ipv6, 0,
578 		"No events should be fired if connectivity availability did not change.");
579 }
580 
581 enum ip_order {
582 	IPV4_FIRST,
583 	IPV6_FIRST
584 };
585 
586 /**
587  * @brief Cycles a single iface through all possible ready and pre-ready states,
588  * ensuring the correct events are observed and generated by conn_mgr_monitor.
589  *
590  * Ifaces can be in one of four states that are relevant to L4 readiness:
591  * 00: oper-down, no IPs associated (unready state)
592  * 01: Has IP, is oper-down (semi-ready state)
593  * 10: Is oper-up, has no IP (semi-ready state)
594  * 11: Has IP and is oper-up (ready state)
595  *
596  * In total there are eight possible state transitions:
597  *
598  * (00 -> 10): Gain oper-up from unready state
599  * (10 -> 11): Gain IP from semi-ready state
600  * (11 -> 10): Lose IP from ready state
601  * (10 -> 00): Lose oper-up from semi-ready state
602  * (00 -> 01): Gain IP from unready state
603  * (01 -> 11): Gain Oper-up from semi-ready state
604  * (11 -> 01): Lose oper-up from ready state
605  * (01 -> 00): Lose IP from semi-ready state
606  *
607  * We test these state transitions in that order.
608  *
609  * This is slightly complicated by the fact that ifaces can be assigned multiple IPs, and multiple
610  * types of IPs. Whenever IPs are assigned or removed, two of them, an IPv6 and IPv4 address is
611  * added or removed.
612  *
613  * @param iface
614  * @param ifa_ipm
615  */
cycle_iface_states(struct net_if * iface,enum ip_order ifa_ipm)616 static void cycle_iface_states(struct net_if *iface, enum ip_order ifa_ipm)
617 {
618 	struct test_stats stats;
619 
620 	/* (00 -> 10): Gain oper-up from unready state */
621 
622 	/* Take iface up */
623 	zassert_equal(net_if_up(iface), 0, "net_if_up should succeed.");
624 
625 	/* Verify that no events have been fired yet */
626 	k_sleep(EVENT_WAIT_TIME_MEDIUM);
627 	stats = get_reset_stats();
628 	zassert_equal(stats.event_count_gen, 0,
629 		"No events should be fired if connectivity availability did not change.");
630 
631 	/* (10 -> 11): Gain IP from semi-ready state */
632 	switch (ifa_ipm) {
633 	case IPV4_FIRST:
634 		/* Add IPv4 */
635 		net_if_ipv4_addr_add(iface, &test_ipv4_a, NET_ADDR_MANUAL, 0);
636 
637 		/* Verify correct events */
638 		wait_for_events(TEST_EXPECT_L4_CONNECTED |
639 				TEST_EXPECT_L4_IPV4_CONNECTED,
640 				EVENT_WAIT_TIME);
641 		stats = get_reset_stats();
642 		zassert_equal(stats.conn_count_gen, 1,
643 			"NET_EVENT_L4_CONNECTED should be fired when connectivity is gained.");
644 		zassert_equal(stats.event_count_gen, 1,
645 			"Only NET_EVENT_L4_CONNECTED should be fired when connectivity is gained.");
646 		zassert_equal(stats.conn_count_ipv4, 1,
647 			"NET_EVENT_L4_IPV4_CONNECTED should be fired when IPv4 "
648 			"connectivity is gained.");
649 		zassert_equal(stats.event_count_ipv4, 1,
650 			"Only NET_EVENT_L4_IPV4_CONNECTED should be fired when IPv4 "
651 			"connectivity is gained.");
652 		zassert_equal(stats.event_count_ipv6, 0,
653 			"No IPv6 events should be fired when IPv4 connectivity is gained.");
654 		zassert_equal(stats.conn_iface_gen, iface, "The test iface should be blamed.");
655 		zassert_equal(stats.conn_iface_ipv4, iface, "The test iface should be blamed.");
656 
657 		/* Add IPv6 */
658 		net_if_ipv6_addr_add(iface, &test_ipv6_a, NET_ADDR_MANUAL, 0);
659 
660 		/* Verify only IPv6 events */
661 		wait_for_events(TEST_EXPECT_L4_IPV6_CONNECTED, EVENT_WAIT_TIME);
662 		stats = get_reset_stats();
663 		zassert_equal(stats.event_count_gen, 0,
664 			"No events should be fired if connectivity availability did not change.");
665 		zassert_equal(stats.conn_count_ipv6, 1,
666 			"NET_EVENT_L4_IPV6_CONNECTED should be fired when IPv6 "
667 			"connectivity is gained.");
668 		zassert_equal(stats.event_count_ipv6, 1,
669 			"Only NET_EVENT_L4_IPV6_CONNECTED should be fired when IPv6 "
670 			"connectivity is gained.");
671 		zassert_equal(stats.event_count_ipv4, 0,
672 			"No IPv4 events should be fired when IPv6 connectivity is gained.");
673 		zassert_equal(stats.conn_iface_ipv6, iface, "The test iface should be blamed.");
674 
675 		break;
676 	case IPV6_FIRST:
677 		/* Add IPv6 */
678 		net_if_ipv6_addr_add(iface, &test_ipv6_a, NET_ADDR_MANUAL, 0);
679 
680 		/* Verify correct events */
681 		wait_for_events(TEST_EXPECT_L4_CONNECTED |
682 				TEST_EXPECT_L4_IPV6_CONNECTED,
683 				EVENT_WAIT_TIME);
684 		stats = get_reset_stats();
685 		zassert_equal(stats.conn_count_gen, 1,
686 			"NET_EVENT_L4_CONNECTED should be fired when connectivity is gained.");
687 		zassert_equal(stats.event_count_gen, 1,
688 			"Only NET_EVENT_L4_CONNECTED should be fired when connectivity is gained.");
689 		zassert_equal(stats.conn_count_ipv6, 1,
690 			"NET_EVENT_L4_IPV6_CONNECTED should be fired when IPv6 "
691 			"connectivity is gained.");
692 		zassert_equal(stats.event_count_ipv6, 1,
693 			"Only NET_EVENT_L4_IPV6_CONNECTED should be fired when IPv6 "
694 			"connectivity is gained.");
695 		zassert_equal(stats.event_count_ipv4, 0,
696 			"No IPv4 events should be fired when IPv6 connectivity is gained.");
697 		zassert_equal(stats.conn_iface_gen, iface, "The test iface should be blamed.");
698 		zassert_equal(stats.conn_iface_ipv6, iface, "The test iface should be blamed.");
699 
700 		/* Add IPv4 */
701 		net_if_ipv4_addr_add(iface, &test_ipv4_a, NET_ADDR_MANUAL, 0);
702 
703 		/* Verify only IPv4 events */
704 		wait_for_events(TEST_EXPECT_L4_IPV4_CONNECTED, EVENT_WAIT_TIME);
705 		stats = get_reset_stats();
706 		zassert_equal(stats.event_count_gen, 0,
707 			"No events should be fired if connectivity availability did not change.");
708 		zassert_equal(stats.conn_count_ipv4, 1,
709 			"NET_EVENT_L4_IPV4_CONNECTED should be fired when IPv4 "
710 			"connectivity is gained.");
711 		zassert_equal(stats.event_count_ipv4, 1,
712 			"Only NET_EVENT_L4_IPV4_CONNECTED should be fired when IPv4 "
713 			"connectivity is gained.");
714 		zassert_equal(stats.event_count_ipv6, 0,
715 			"No IPv6 events should be fired when IPv4 connectivity is gained.");
716 		zassert_equal(stats.conn_iface_ipv4, iface, "The test iface should be blamed.");
717 		break;
718 	}
719 
720 	/* (11 -> 10): Lose IP from ready state */
721 	switch (ifa_ipm) {
722 	case IPV4_FIRST:
723 		/* Remove IPv4 */
724 		zassert_true(net_if_ipv4_addr_rm(iface, &test_ipv4_a),
725 							"IPv4 removal should succeed.");
726 
727 		/* Verify only IPv4 events */
728 		wait_for_events(TEST_EXPECT_L4_IPV4_DISCONNECTED, EVENT_WAIT_TIME);
729 		stats = get_reset_stats();
730 		zassert_equal(stats.event_count_gen, 0,
731 			"No events should be fired if connectivity availability did not change.");
732 		zassert_equal(stats.dconn_count_ipv4, 1,
733 			"NET_EVENT_L4_IPV4_DISCONNECTED should be fired when IPv4 "
734 			"connectivity is lost.");
735 		zassert_equal(stats.event_count_ipv4, 1,
736 			"Only NET_EVENT_L4_IPV4_DISCONNECTED should be fired when IPv4 "
737 			"connectivity is lost.");
738 		zassert_equal(stats.event_count_ipv6, 0,
739 			"No IPv6 events should be fired when IPv4 connectivity is gained.");
740 		zassert_equal(stats.dconn_iface_ipv4, iface, "The test iface should be blamed.");
741 
742 		/* Remove IPv6 */
743 		zassert_true(net_if_ipv6_addr_rm(iface, &test_ipv6_a),
744 							"IPv6 removal should succeed.");
745 
746 		/* Verify correct events */
747 		wait_for_events(TEST_EXPECT_L4_DISCONNECTED |
748 				TEST_EXPECT_L4_IPV6_DISCONNECTED,
749 				EVENT_WAIT_TIME);
750 		stats = get_reset_stats();
751 		zassert_equal(stats.dconn_count_gen, 1,
752 			"NET_EVENT_L4_DISCONNECTED should be fired when connectivity is lost.");
753 		zassert_equal(stats.event_count_gen, 1,
754 			"Only NET_EVENT_L4_DISCONNECTED should be fired when connectivity "
755 			"is lost.");
756 		zassert_equal(stats.dconn_count_ipv6, 1,
757 			"NET_EVENT_L4_IPV6_DISCONNECTED should be fired when IPv6 "
758 			"connectivity is lost.");
759 		zassert_equal(stats.event_count_ipv6, 1,
760 			"Only NET_EVENT_L4_IPV6_DISCONNECTED should be fired when IPv6 "
761 			"connectivity is lost.");
762 		zassert_equal(stats.event_count_ipv4, 0,
763 			"No IPv4 events should be fired when IPv6 connectivity is gained.");
764 
765 		zassert_equal(stats.dconn_iface_gen, iface, "The test iface should be blamed.");
766 		zassert_equal(stats.dconn_iface_ipv6, iface, "The test iface should be blamed.");
767 
768 		break;
769 	case IPV6_FIRST:
770 		/* Remove IPv6 */
771 		zassert_true(net_if_ipv6_addr_rm(iface, &test_ipv6_a),
772 							"IPv6 removal should succeed.");
773 
774 		/* Verify only IPv6 events */
775 		wait_for_events(TEST_EXPECT_L4_IPV6_DISCONNECTED, EVENT_WAIT_TIME);
776 		stats = get_reset_stats();
777 		zassert_equal(stats.event_count_gen, 0,
778 			"No events should be fired if connectivity availability did not change.");
779 		zassert_equal(stats.dconn_count_ipv6, 1,
780 			"NET_EVENT_L4_IPV6_DISCONNECTED should be fired when IPv6 "
781 			"connectivity is lost.");
782 		zassert_equal(stats.event_count_ipv6, 1,
783 			"Only NET_EVENT_L4_IPV6_DISCONNECTED should be fired when IPv6 "
784 			"connectivity is lost.");
785 		zassert_equal(stats.event_count_ipv4, 0,
786 			"No IPv4 events should be fired when IPv6 connectivity is gained.");
787 		zassert_equal(stats.dconn_iface_ipv6, iface, "The test iface should be blamed.");
788 
789 		/* Remove IPv4 */
790 		zassert_true(net_if_ipv4_addr_rm(iface, &test_ipv4_a),
791 							"IPv4 removal should succeed.");
792 
793 		/* Verify correct events */
794 		wait_for_events(TEST_EXPECT_L4_DISCONNECTED |
795 				TEST_EXPECT_L4_IPV4_DISCONNECTED,
796 				EVENT_WAIT_TIME);
797 		stats = get_reset_stats();
798 		zassert_equal(stats.dconn_count_gen, 1,
799 			"NET_EVENT_L4_DISCONNECTED should be fired when connectivity is lost.");
800 		zassert_equal(stats.event_count_gen, 1,
801 			"Only NET_EVENT_L4_DISCONNECTED should be fired when connectivity "
802 			"is lost.");
803 		zassert_equal(stats.dconn_count_ipv4, 1,
804 			"NET_EVENT_L4_IPV4_DISCONNECTED should be fired when IPv4 "
805 			"connectivity is lost.");
806 		zassert_equal(stats.event_count_ipv4, 1,
807 			"Only NET_EVENT_L4_IPV4_DISCONNECTED should be fired when IPv4 "
808 			"connectivity is lost.");
809 		zassert_equal(stats.event_count_ipv6, 0,
810 			"No IPv6 events should be fired when IPv4 connectivity is gained.");
811 		zassert_equal(stats.dconn_iface_gen, iface, "The test iface should be blamed.");
812 		zassert_equal(stats.dconn_iface_ipv4, iface, "The test iface should be blamed.");
813 
814 		break;
815 	}
816 
817 	/* (10 -> 00): Lose oper-up from semi-ready state */
818 
819 	/* Take iface down */
820 	zassert_equal(net_if_down(iface), 0, "net_if_down should succeed.");
821 
822 	/* Verify there are no events fired */
823 	k_sleep(EVENT_WAIT_TIME_SHORT);
824 	stats = get_reset_stats();
825 	zassert_equal(stats.event_count_gen, 0,
826 		"No events should be fired if connectivity availability did not change.");
827 	zassert_equal(stats.event_count_ipv4, 0,
828 		"No events should be fired if connectivity availability did not change.");
829 	zassert_equal(stats.event_count_ipv6, 0,
830 		"No events should be fired if connectivity availability did not change.");
831 
832 	/* (00 -> 01): Gain IP from unready state */
833 
834 	/* Add IP addresses to iface */
835 	switch (ifa_ipm) {
836 	case IPV4_FIRST:
837 		/* Add IPv4 and IPv6 */
838 		net_if_ipv4_addr_add(iface, &test_ipv4_a, NET_ADDR_MANUAL, 0);
839 		net_if_ipv6_addr_add(iface, &test_ipv6_a, NET_ADDR_MANUAL, 0);
840 		k_sleep(DAD_WAIT_TIME);
841 		break;
842 	case IPV6_FIRST:
843 		/* Add IPv6 then IPv4 */
844 		net_if_ipv6_addr_add(iface, &test_ipv6_a, NET_ADDR_MANUAL, 0);
845 		k_sleep(DAD_WAIT_TIME);
846 		net_if_ipv4_addr_add(iface, &test_ipv4_a, NET_ADDR_MANUAL, 0);
847 		break;
848 	}
849 
850 	/* Verify that no events are fired */
851 	k_sleep(EVENT_WAIT_TIME_SHORT);
852 	stats = get_reset_stats();
853 	zassert_equal(stats.event_count_gen, 0,
854 		"No events should be fired if connectivity availability did not change.");
855 	zassert_equal(stats.event_count_ipv4, 0,
856 		"No events should be fired if connectivity availability did not change.");
857 	zassert_equal(stats.event_count_ipv6, 0,
858 		"No events should be fired if connectivity availability did not change.");
859 
860 	/* (01 -> 11): Gain Oper-up from semi-ready state */
861 
862 	/* Take iface up */
863 	zassert_equal(net_if_up(iface), 0, "net_if_up should succeed.");
864 
865 	/* Verify events are fired */
866 	wait_for_events(TEST_EXPECT_L4_CONNECTED |
867 			TEST_EXPECT_L4_IPV4_CONNECTED |
868 			TEST_EXPECT_L4_IPV6_CONNECTED,
869 			EVENT_WAIT_TIME);
870 	stats = get_reset_stats();
871 	zassert_equal(stats.conn_count_gen, 1,
872 		"NET_EVENT_L4_CONNECTED should be fired when connectivity is gained.");
873 	zassert_equal(stats.event_count_gen, 1,
874 		"Only NET_EVENT_L4_CONNECTED should be fired when connectivity is gained.");
875 	zassert_equal(stats.conn_count_ipv4, 1,
876 		"NET_EVENT_L4_IPV4_CONNECTED should be fired when IPv4 "
877 		"connectivity is gained.");
878 	zassert_equal(stats.event_count_ipv4, 1,
879 		"Only NET_EVENT_L4_IPV4_CONNECTED should be fired when IPv4 "
880 		"connectivity is gained.");
881 	zassert_equal(stats.conn_count_ipv6, 1,
882 		"NET_EVENT_L4_IPV6_CONNECTED should be fired when IPv6 "
883 		"connectivity is gained.");
884 	zassert_equal(stats.event_count_ipv6, 1,
885 		"Only NET_EVENT_L4_IPV6_CONNECTED should be fired when IPv6 "
886 		"connectivity is gained.");
887 	zassert_equal(stats.conn_iface_gen, iface, "The test iface should be blamed.");
888 	zassert_equal(stats.conn_iface_ipv4, iface, "The test iface should be blamed.");
889 	zassert_equal(stats.conn_iface_ipv6, iface, "The test iface should be blamed.");
890 
891 	/* (11 -> 01): Lose oper-up from ready state */
892 
893 	/* Take iface down */
894 	zassert_equal(net_if_down(iface), 0, "net_if_down should succeed.");
895 
896 	/* Verify events are fired */
897 	wait_for_events(TEST_EXPECT_L4_DISCONNECTED |
898 			TEST_EXPECT_L4_IPV4_DISCONNECTED |
899 			TEST_EXPECT_L4_IPV6_DISCONNECTED,
900 			EVENT_WAIT_TIME);
901 	stats = get_reset_stats();
902 	zassert_equal(stats.dconn_count_gen, 1,
903 		"NET_EVENT_L4_DISCONNECTED should be fired when connectivity is lost.");
904 	zassert_equal(stats.event_count_gen, 1,
905 		"Only NET_EVENT_L4_DISCONNECTED should be fired when connectivity is lost.");
906 	zassert_equal(stats.dconn_count_ipv4, 1,
907 		"NET_EVENT_L4_IPV4_DISCONNECTED should be fired when IPv4 "
908 		"connectivity is lost.");
909 	zassert_equal(stats.event_count_ipv4, 1,
910 		"Only NET_EVENT_L4_IPV4_DISCONNECTED should be fired when IPv4 "
911 		"connectivity is lost.");
912 	zassert_equal(stats.dconn_count_ipv6, 1,
913 		"NET_EVENT_L4_IPV6_DISCONNECTED should be fired when IPv6 "
914 		"connectivity is lost.");
915 	zassert_equal(stats.event_count_ipv6, 1,
916 		"Only NET_EVENT_L4_IPV6_DISCONNECTED should be fired when IPv6 "
917 		"connectivity is lost.");
918 	zassert_equal(stats.dconn_iface_gen, iface, "The test iface should be blamed.");
919 	zassert_equal(stats.dconn_iface_ipv4, iface, "The test iface should be blamed.");
920 	zassert_equal(stats.dconn_iface_ipv6, iface, "The test iface should be blamed.");
921 
922 	/* (01 -> 00): Lose IP from semi-ready state */
923 
924 	/* Remove IPs */
925 	switch (ifa_ipm) {
926 	case IPV4_FIRST:
927 		/* Remove IPv4 then IPv6 */
928 		zassert_true(net_if_ipv4_addr_rm(iface, &test_ipv4_a),
929 							"IPv4 removal should succeed.");
930 		zassert_true(net_if_ipv6_addr_rm(iface, &test_ipv6_a),
931 							"IPv6 removal should succeed.");
932 		break;
933 	case IPV6_FIRST:
934 		/* Remove IPv6 then IPv4 */
935 		zassert_true(net_if_ipv6_addr_rm(iface, &test_ipv6_a),
936 							"IPv6 removal should succeed.");
937 		zassert_true(net_if_ipv4_addr_rm(iface, &test_ipv4_a),
938 							"IPv4 removal should succeed.");
939 		break;
940 	}
941 
942 	/* Verify no events fired */
943 	k_sleep(EVENT_WAIT_TIME_SHORT);
944 	stats = get_reset_stats();
945 	zassert_equal(stats.event_count_gen, 0,
946 		"No events should be fired if connectivity availability did not change.");
947 	zassert_equal(stats.event_count_ipv4, 0,
948 		"No events should be fired if connectivity availability did not change.");
949 	zassert_equal(stats.event_count_ipv6, 0,
950 		"No events should be fired if connectivity availability did not change.");
951 }
952 
953 /* Cases */
954 
955 /* Make sure all readiness transitions of a pair of connectivity-enabled ifaces results in all
956  * expected events.
957  */
ZTEST(conn_mgr_monitor,test_cycle_ready_CC)958 ZTEST(conn_mgr_monitor, test_cycle_ready_CC)
959 {
960 	cycle_ready_ifaces(if_conn_a, if_conn_b);
961 }
962 
963 /* Make sure half of all readiness transitions of a connectivity-enabled iface and a simple
964  * iface results in all expected events.
965  */
ZTEST(conn_mgr_monitor,test_cycle_ready_CNC)966 ZTEST(conn_mgr_monitor, test_cycle_ready_CNC)
967 {
968 	cycle_ready_ifaces(if_conn_a, if_simp_a);
969 }
970 
971 /* Make sure the other half of all readiness transitions of a connectivity-enabled iface and a
972  * simple iface results in all expected events.
973  */
ZTEST(conn_mgr_monitor,test_cycle_ready_NCC)974 ZTEST(conn_mgr_monitor, test_cycle_ready_NCC)
975 {
976 	cycle_ready_ifaces(if_simp_a, if_conn_a);
977 }
978 
979 /* Make sure all readiness transitions of a pair of simple ifaces results in all expected events.
980  */
ZTEST(conn_mgr_monitor,test_cycle_ready_NCNC)981 ZTEST(conn_mgr_monitor, test_cycle_ready_NCNC)
982 {
983 	cycle_ready_ifaces(if_simp_a, if_simp_b);
984 }
985 
986 /* Make sure that a simple iface can be successfully ignored without interfering with the events
987  * fired by another simple iface
988  */
ZTEST(conn_mgr_monitor,test_cycle_ready_NCINC)989 ZTEST(conn_mgr_monitor, test_cycle_ready_NCINC)
990 {
991 	cycle_ignored_iface(if_simp_a, if_simp_b);
992 }
993 
994 /* Make sure that a connectivity-enabled iface can be successfully ignored without interfering
995  * with the events fired by another connectivity-enabled iface
996  */
ZTEST(conn_mgr_monitor,test_cycle_ready_CIC)997 ZTEST(conn_mgr_monitor, test_cycle_ready_CIC)
998 {
999 	cycle_ignored_iface(if_conn_a, if_conn_b);
1000 }
1001 
1002 /* Make sure that a connectivity-enabled iface can be successfully ignored without interfering
1003  * with the events fired by a simple iface
1004  */
ZTEST(conn_mgr_monitor,test_cycle_ready_CINC)1005 ZTEST(conn_mgr_monitor, test_cycle_ready_CINC)
1006 {
1007 	cycle_ignored_iface(if_conn_a, if_simp_a);
1008 }
1009 
1010 /* Make sure that a simple iface can be successfully ignored without interfering
1011  * with the events fired by a connectivity-enabled iface
1012  */
ZTEST(conn_mgr_monitor,test_cycle_ready_NCIC)1013 ZTEST(conn_mgr_monitor, test_cycle_ready_NCIC)
1014 {
1015 	cycle_ignored_iface(if_simp_a, if_conn_a);
1016 }
1017 
1018 /* Make sure that DAD readiness is actually verified by conn_mgr_monitor */
ZTEST(conn_mgr_monitor,test_DAD)1019 ZTEST(conn_mgr_monitor, test_DAD)
1020 {
1021 	struct test_stats stats;
1022 
1023 	/* This test specifically requires DAD to function */
1024 	Z_TEST_SKIP_IFNDEF(CONFIG_NET_IPV6_DAD);
1025 
1026 	/* Take iface up */
1027 	zassert_equal(net_if_up(if_simp_a), 0, "net_if_up should succeed.");
1028 
1029 	/* Add IPv6 */
1030 	net_if_ipv6_addr_add(if_simp_a, &test_ipv6_a, NET_ADDR_MANUAL, 0);
1031 
1032 	/* After a delay too short for DAD, ensure no events */
1033 	k_sleep(EVENT_WAIT_TIME_SHORT);
1034 	stats = get_reset_stats();
1035 	zassert_equal(stats.event_count_gen, 0,
1036 		"No events should be fired before DAD success.");
1037 
1038 	/* After a delay long enough for DAD, ensure connectivity acquired */
1039 	wait_for_events(TEST_EXPECT_L4_CONNECTED, EVENT_WAIT_TIME);
1040 	stats = get_reset_stats();
1041 	zassert_equal(stats.conn_count_gen, 1,
1042 			"NET_EVENT_L4_CONNECTED should be fired after DAD success.");
1043 }
1044 
1045 /* Test whether ignoring and un-ignoring a ready iface fires the appropriate events */
ZTEST(conn_mgr_monitor,test_ignore_while_ready)1046 ZTEST(conn_mgr_monitor, test_ignore_while_ready)
1047 {
1048 	struct test_stats stats;
1049 
1050 	/* Ignore iface */
1051 	conn_mgr_ignore_iface(if_simp_a);
1052 
1053 	/* Add IP and take iface up */
1054 	net_if_ipv4_addr_add(if_simp_a, &test_ipv4_a, NET_ADDR_MANUAL, 0);
1055 	net_if_ipv6_addr_add(if_simp_a, &test_ipv6_a, NET_ADDR_MANUAL, 0);
1056 	zassert_equal(net_if_up(if_simp_a), 0, "net_if_up should succeed for if_simp_a.");
1057 
1058 	/* Ensure no events */
1059 	k_sleep(DAD_WAIT_TIME);
1060 	stats = get_reset_stats();
1061 	zassert_equal(stats.event_count_gen, 0,
1062 		"No events should be fired if connecting iface is ignored.");
1063 	zassert_equal(stats.event_count_ipv4, 0,
1064 		"No events should be fired if connecting iface is ignored.");
1065 	zassert_equal(stats.event_count_ipv6, 0,
1066 		"No events should be fired if connecting iface is ignored.");
1067 
1068 	/* Watch iface */
1069 	conn_mgr_watch_iface(if_simp_a);
1070 
1071 	/* Ensure connectivity gained */
1072 	wait_for_events(TEST_EXPECT_L4_CONNECTED |
1073 			TEST_EXPECT_L4_IPV4_CONNECTED |
1074 			TEST_EXPECT_L4_IPV6_CONNECTED,
1075 			EVENT_WAIT_TIME);
1076 	stats = get_reset_stats();
1077 	zassert_equal(stats.conn_count_gen, 1,
1078 		"NET_EVENT_L4_CONNECTED should be fired when online iface is watched.");
1079 	zassert_equal(stats.event_count_gen, 1,
1080 		"Only NET_EVENT_L4_CONNECTED should be fired.");
1081 	zassert_equal(stats.conn_count_ipv4, 1,
1082 		"NET_EVENT_L4_IPV4_CONNECTED should be fired when online iface is watched.");
1083 	zassert_equal(stats.event_count_ipv4, 1,
1084 		"Only NET_EVENT_L4_IPV4_CONNECTED should be fired.");
1085 	zassert_equal(stats.conn_count_ipv6, 1,
1086 		"NET_EVENT_L4_IPV6_CONNECTED should be fired when online iface is watched.");
1087 	zassert_equal(stats.event_count_ipv6, 1,
1088 		"Only NET_EVENT_L4_IPV6_CONNECTED should be fired.");
1089 	zassert_equal(stats.conn_iface_gen, if_simp_a, "if_simp_a should be blamed");
1090 	zassert_equal(stats.conn_iface_ipv4, if_simp_a, "if_simp_a should be blamed");
1091 	zassert_equal(stats.conn_iface_ipv6, if_simp_a, "if_simp_a should be blamed");
1092 
1093 
1094 	/* Ignore iface */
1095 	conn_mgr_ignore_iface(if_simp_a);
1096 
1097 	/* Ensure connectivity lost */
1098 	wait_for_events(TEST_EXPECT_L4_DISCONNECTED |
1099 			TEST_EXPECT_L4_IPV4_DISCONNECTED |
1100 			TEST_EXPECT_L4_IPV6_DISCONNECTED,
1101 			EVENT_WAIT_TIME);
1102 	stats = get_reset_stats();
1103 	zassert_equal(stats.dconn_count_gen, 1,
1104 		"NET_EVENT_L4_DISCONNECTED should be fired when online iface is ignored.");
1105 	zassert_equal(stats.event_count_gen, 1,
1106 		"Only NET_EVENT_L4_DISCONNECTED should be fired.");
1107 	zassert_equal(stats.dconn_count_ipv4, 1,
1108 		"NET_EVENT_L4_IPV4_DISCONNECTED should be fired when online iface is ignored.");
1109 	zassert_equal(stats.event_count_ipv4, 1,
1110 		"Only NET_EVENT_L4_IPV4_DISCONNECTED should be fired.");
1111 	zassert_equal(stats.dconn_count_ipv6, 1,
1112 		"NET_EVENT_L4_IPV6_DISCONNECTED should be fired when online iface is ignored.");
1113 	zassert_equal(stats.event_count_ipv6, 1,
1114 		"Only NET_EVENT_L4_IPV6_DISCONNECTED should be fired.");
1115 	zassert_equal(stats.dconn_iface_gen, if_simp_a, "if_simp_a should be blamed");
1116 	zassert_equal(stats.dconn_iface_ipv4, if_simp_a, "if_simp_a should be blamed");
1117 	zassert_equal(stats.dconn_iface_ipv6, if_simp_a, "if_simp_a should be blamed");
1118 
1119 	/* Take iface down*/
1120 	zassert_equal(net_if_down(if_simp_a), 0, "net_if_down should succeed for if_simp_a.");
1121 
1122 	/* Ensure no events */
1123 	k_sleep(EVENT_WAIT_TIME_SHORT);
1124 	stats = get_reset_stats();
1125 	zassert_equal(stats.event_count_gen, 0,
1126 		"No events should be fired if disconnecting iface is ignored.");
1127 	zassert_equal(stats.event_count_ipv4, 0,
1128 		"No events should be fired if disconnecting iface is ignored.");
1129 	zassert_equal(stats.event_count_ipv6, 0,
1130 		"No events should be fired if disconnecting iface is ignored.");
1131 }
1132 
1133 /* Test L2 and iface ignore API */
ZTEST(conn_mgr_monitor,test_ignores)1134 ZTEST(conn_mgr_monitor, test_ignores)
1135 {
1136 	/* Ignore if_simp_a, ensuring if_simp_b is unaffected */
1137 	conn_mgr_ignore_iface(if_simp_a);
1138 	zassert_true(conn_mgr_is_iface_ignored(if_simp_a),
1139 			"if_simp_a should be ignored.");
1140 	zassert_false(conn_mgr_is_iface_ignored(if_simp_b),
1141 			"if_simp_b should not be affected.");
1142 
1143 	/* Ignore if_simp_b, ensuring if_simp_a is unaffected */
1144 	conn_mgr_ignore_iface(if_simp_b);
1145 	zassert_true(conn_mgr_is_iface_ignored(if_simp_b),
1146 			"if_simp_b should be ignored.");
1147 	zassert_true(conn_mgr_is_iface_ignored(if_simp_a),
1148 			"if_simp_a should not be affected.");
1149 
1150 	/* Watch if_simp_a, ensuring if_simp_b is unaffected */
1151 	conn_mgr_watch_iface(if_simp_a);
1152 	zassert_false(conn_mgr_is_iface_ignored(if_simp_a),
1153 			"if_simp_a should be watched.");
1154 	zassert_true(conn_mgr_is_iface_ignored(if_simp_b),
1155 			"if_simp_b should not be affected.");
1156 
1157 	/* Watch if_simp_b, ensuring if_simp_a is unaffected */
1158 	conn_mgr_watch_iface(if_simp_b);
1159 	zassert_false(conn_mgr_is_iface_ignored(if_simp_b),
1160 			"if_simp_b should be watched.");
1161 	zassert_false(conn_mgr_is_iface_ignored(if_simp_a),
1162 			"if_simp_a should not be affected.");
1163 
1164 	/* Ignore the entire DUMMY_L2, ensuring all ifaces except if_dummy_eth are affected */
1165 	conn_mgr_ignore_l2(&NET_L2_GET_NAME(DUMMY));
1166 	zassert_true(conn_mgr_is_iface_ignored(if_simp_a),
1167 		"All DUMMY_L2 ifaces should be ignored.");
1168 	zassert_true(conn_mgr_is_iface_ignored(if_simp_b),
1169 		"All DUMMY_L2 ifaces should be ignored.");
1170 	zassert_true(conn_mgr_is_iface_ignored(if_conn_a),
1171 		"All DUMMY_L2 ifaces should be ignored.");
1172 	zassert_true(conn_mgr_is_iface_ignored(if_conn_b),
1173 		"All DUMMY_L2 ifaces should be ignored.");
1174 	zassert_false(conn_mgr_is_iface_ignored(if_dummy_eth),
1175 		"if_dummy_eth should not be affected.");
1176 
1177 	/* Watch the entire DUMMY_L2, ensuring all ifaces except if_dummy_eth are affected */
1178 	conn_mgr_watch_l2(&NET_L2_GET_NAME(DUMMY));
1179 	zassert_false(conn_mgr_is_iface_ignored(if_simp_a),
1180 		"All DUMMY_L2 ifaces should be watched.");
1181 	zassert_false(conn_mgr_is_iface_ignored(if_simp_b),
1182 		"All DUMMY_L2 ifaces should be watched.");
1183 	zassert_false(conn_mgr_is_iface_ignored(if_conn_a),
1184 		"All DUMMY_L2 ifaces should be watched.");
1185 	zassert_false(conn_mgr_is_iface_ignored(if_conn_b),
1186 		"All DUMMY_L2 ifaces should be watched.");
1187 	zassert_false(conn_mgr_is_iface_ignored(if_dummy_eth),
1188 		"if_dummy_eth should not be affected.");
1189 }
1190 
1191 /* Make sure all state transitions of a single connectivity-enabled iface result in all expected
1192  * events. Perform IPv4 changes before IPv6 changes.
1193  */
ZTEST(conn_mgr_monitor,test_cycle_states_connected_ipv46)1194 ZTEST(conn_mgr_monitor, test_cycle_states_connected_ipv46)
1195 {
1196 	cycle_iface_states(if_conn_a, IPV4_FIRST);
1197 }
1198 
1199 /* Make sure all state transitions of a single connectivity-enabled iface result in all expected
1200  * events. Perform IPv6 changes before IPv4 changes.
1201  */
ZTEST(conn_mgr_monitor,test_cycle_states_connected_ipv64)1202 ZTEST(conn_mgr_monitor, test_cycle_states_connected_ipv64)
1203 {
1204 	cycle_iface_states(if_conn_a, IPV6_FIRST);
1205 }
1206 
1207 /* Make sure all state transitions of a single simple iface result in all expected events.
1208  * Perform IPv4 changes before IPv6 changes.
1209  */
ZTEST(conn_mgr_monitor,test_cycle_states_simple_ipv46)1210 ZTEST(conn_mgr_monitor, test_cycle_states_simple_ipv46)
1211 {
1212 	cycle_iface_states(if_simp_a, IPV4_FIRST);
1213 }
1214 
1215 /* Make sure all state transitions of a single simple iface result in all expected events.
1216  * Perform IPv6 changes before IPv4 changes.
1217  */
ZTEST(conn_mgr_monitor,test_cycle_states_simple_ipv64)1218 ZTEST(conn_mgr_monitor, test_cycle_states_simple_ipv64)
1219 {
1220 	cycle_iface_states(if_simp_a, IPV6_FIRST);
1221 }
1222 
1223 ZTEST_SUITE(conn_mgr_monitor, NULL, conn_mgr_setup, conn_mgr_before, NULL, NULL);
1224