xref: /linux/net/core/dev_addr_lists_test.c (revision 0fc8f6200d2313278fbf4539bbab74677c685531)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 #include <kunit/test.h>
4 #include <linux/etherdevice.h>
5 #include <linux/math64.h>
6 #include <linux/netdevice.h>
7 #include <linux/rtnetlink.h>
8 
9 static const struct net_device_ops dummy_netdev_ops = {
10 };
11 
12 #define ADDR_A	1
13 #define ADDR_B	2
14 #define ADDR_C	3
15 
16 struct dev_addr_test_priv {
17 	u32 addr_seen;
18 	u32 addr_synced;
19 	u32 addr_unsynced;
20 };
21 
22 static int dev_addr_test_sync(struct net_device *netdev, const unsigned char *a)
23 {
24 	struct dev_addr_test_priv *datp = netdev_priv(netdev);
25 
26 	if (a[0] < 31 && !memchr_inv(a, a[0], ETH_ALEN)) {
27 		datp->addr_seen |= 1 << a[0];
28 		datp->addr_synced |= 1 << a[0];
29 	}
30 	return 0;
31 }
32 
33 static int dev_addr_test_unsync(struct net_device *netdev,
34 				const unsigned char *a)
35 {
36 	struct dev_addr_test_priv *datp = netdev_priv(netdev);
37 
38 	if (a[0] < 31 && !memchr_inv(a, a[0], ETH_ALEN)) {
39 		datp->addr_seen &= ~(1 << a[0]);
40 		datp->addr_unsynced |= 1 << a[0];
41 	}
42 	return 0;
43 }
44 
45 static void dev_addr_test_reset(struct net_device *netdev)
46 {
47 	struct dev_addr_test_priv *datp = netdev_priv(netdev);
48 
49 	datp->addr_seen = 0;
50 	datp->addr_synced = 0;
51 	datp->addr_unsynced = 0;
52 }
53 
54 static int dev_addr_test_init(struct kunit *test)
55 {
56 	struct dev_addr_test_priv *datp;
57 	struct net_device *netdev;
58 	int err;
59 
60 	netdev = alloc_etherdev(sizeof(*datp));
61 	KUNIT_ASSERT_TRUE(test, !!netdev);
62 
63 	test->priv = netdev;
64 	netdev->netdev_ops = &dummy_netdev_ops;
65 
66 	err = register_netdev(netdev);
67 	if (err) {
68 		free_netdev(netdev);
69 		KUNIT_FAIL(test, "Can't register netdev %d", err);
70 	}
71 
72 	return 0;
73 }
74 
75 static void dev_addr_test_exit(struct kunit *test)
76 {
77 	struct net_device *netdev = test->priv;
78 
79 	unregister_netdev(netdev);
80 	free_netdev(netdev);
81 }
82 
83 static void dev_addr_test_basic(struct kunit *test)
84 {
85 	struct net_device *netdev = test->priv;
86 	u8 addr[ETH_ALEN];
87 
88 	rtnl_lock();
89 	KUNIT_EXPECT_TRUE(test, !!netdev->dev_addr);
90 
91 	memset(addr, 2, sizeof(addr));
92 	eth_hw_addr_set(netdev, addr);
93 	KUNIT_EXPECT_MEMEQ(test, netdev->dev_addr, addr, sizeof(addr));
94 
95 	memset(addr, 3, sizeof(addr));
96 	dev_addr_set(netdev, addr);
97 	KUNIT_EXPECT_MEMEQ(test, netdev->dev_addr, addr, sizeof(addr));
98 	rtnl_unlock();
99 }
100 
101 static void dev_addr_test_sync_one(struct kunit *test)
102 {
103 	struct net_device *netdev = test->priv;
104 	struct dev_addr_test_priv *datp;
105 	u8 addr[ETH_ALEN];
106 
107 	datp = netdev_priv(netdev);
108 
109 	rtnl_lock();
110 	memset(addr, 1, sizeof(addr));
111 	eth_hw_addr_set(netdev, addr);
112 
113 	__hw_addr_sync_dev(&netdev->dev_addrs, netdev, dev_addr_test_sync,
114 			   dev_addr_test_unsync);
115 	KUNIT_EXPECT_EQ(test, 2, datp->addr_seen);
116 
117 	memset(addr, 2, sizeof(addr));
118 	eth_hw_addr_set(netdev, addr);
119 
120 	datp->addr_seen = 0;
121 	__hw_addr_sync_dev(&netdev->dev_addrs, netdev, dev_addr_test_sync,
122 			   dev_addr_test_unsync);
123 	/* It's not going to sync anything because the main address is
124 	 * considered synced and we overwrite in place.
125 	 */
126 	KUNIT_EXPECT_EQ(test, 0, datp->addr_seen);
127 	rtnl_unlock();
128 }
129 
130 static void dev_addr_test_add_del(struct kunit *test)
131 {
132 	struct net_device *netdev = test->priv;
133 	struct dev_addr_test_priv *datp;
134 	u8 addr[ETH_ALEN];
135 	int i;
136 
137 	datp = netdev_priv(netdev);
138 
139 	rtnl_lock();
140 	for (i = 1; i < 4; i++) {
141 		memset(addr, i, sizeof(addr));
142 		KUNIT_EXPECT_EQ(test, 0, dev_addr_add(netdev, addr,
143 						      NETDEV_HW_ADDR_T_LAN));
144 	}
145 	/* Add 3 again */
146 	KUNIT_EXPECT_EQ(test, 0, dev_addr_add(netdev, addr,
147 					      NETDEV_HW_ADDR_T_LAN));
148 
149 	__hw_addr_sync_dev(&netdev->dev_addrs, netdev, dev_addr_test_sync,
150 			   dev_addr_test_unsync);
151 	KUNIT_EXPECT_EQ(test, 0xf, datp->addr_seen);
152 
153 	KUNIT_EXPECT_EQ(test, 0, dev_addr_del(netdev, addr,
154 					      NETDEV_HW_ADDR_T_LAN));
155 
156 	__hw_addr_sync_dev(&netdev->dev_addrs, netdev, dev_addr_test_sync,
157 			   dev_addr_test_unsync);
158 	KUNIT_EXPECT_EQ(test, 0xf, datp->addr_seen);
159 
160 	for (i = 1; i < 4; i++) {
161 		memset(addr, i, sizeof(addr));
162 		KUNIT_EXPECT_EQ(test, 0, dev_addr_del(netdev, addr,
163 						      NETDEV_HW_ADDR_T_LAN));
164 	}
165 
166 	__hw_addr_sync_dev(&netdev->dev_addrs, netdev, dev_addr_test_sync,
167 			   dev_addr_test_unsync);
168 	KUNIT_EXPECT_EQ(test, 1, datp->addr_seen);
169 	rtnl_unlock();
170 }
171 
172 static void dev_addr_test_del_main(struct kunit *test)
173 {
174 	struct net_device *netdev = test->priv;
175 	u8 addr[ETH_ALEN];
176 
177 	rtnl_lock();
178 	memset(addr, 1, sizeof(addr));
179 	eth_hw_addr_set(netdev, addr);
180 
181 	KUNIT_EXPECT_EQ(test, -ENOENT, dev_addr_del(netdev, addr,
182 						    NETDEV_HW_ADDR_T_LAN));
183 	KUNIT_EXPECT_EQ(test, 0, dev_addr_add(netdev, addr,
184 					      NETDEV_HW_ADDR_T_LAN));
185 	KUNIT_EXPECT_EQ(test, 0, dev_addr_del(netdev, addr,
186 					      NETDEV_HW_ADDR_T_LAN));
187 	KUNIT_EXPECT_EQ(test, -ENOENT, dev_addr_del(netdev, addr,
188 						    NETDEV_HW_ADDR_T_LAN));
189 	rtnl_unlock();
190 }
191 
192 static void dev_addr_test_add_set(struct kunit *test)
193 {
194 	struct net_device *netdev = test->priv;
195 	struct dev_addr_test_priv *datp;
196 	u8 addr[ETH_ALEN];
197 	int i;
198 
199 	datp = netdev_priv(netdev);
200 
201 	rtnl_lock();
202 	/* There is no external API like dev_addr_add_excl(),
203 	 * so shuffle the tree a little bit and exploit aliasing.
204 	 */
205 	for (i = 1; i < 16; i++) {
206 		memset(addr, i, sizeof(addr));
207 		KUNIT_EXPECT_EQ(test, 0, dev_addr_add(netdev, addr,
208 						      NETDEV_HW_ADDR_T_LAN));
209 	}
210 
211 	memset(addr, i, sizeof(addr));
212 	eth_hw_addr_set(netdev, addr);
213 	KUNIT_EXPECT_EQ(test, 0, dev_addr_add(netdev, addr,
214 					      NETDEV_HW_ADDR_T_LAN));
215 	memset(addr, 0, sizeof(addr));
216 	eth_hw_addr_set(netdev, addr);
217 
218 	__hw_addr_sync_dev(&netdev->dev_addrs, netdev, dev_addr_test_sync,
219 			   dev_addr_test_unsync);
220 	KUNIT_EXPECT_EQ(test, 0xffff, datp->addr_seen);
221 	rtnl_unlock();
222 }
223 
224 static void dev_addr_test_add_excl(struct kunit *test)
225 {
226 	struct net_device *netdev = test->priv;
227 	u8 addr[ETH_ALEN];
228 	int i;
229 
230 	rtnl_lock();
231 	for (i = 0; i < 10; i++) {
232 		memset(addr, i, sizeof(addr));
233 		KUNIT_EXPECT_EQ(test, 0, dev_uc_add_excl(netdev, addr));
234 	}
235 	KUNIT_EXPECT_EQ(test, -EEXIST, dev_uc_add_excl(netdev, addr));
236 
237 	for (i = 0; i < 10; i += 2) {
238 		memset(addr, i, sizeof(addr));
239 		KUNIT_EXPECT_EQ(test, 0, dev_uc_del(netdev, addr));
240 	}
241 	for (i = 1; i < 10; i += 2) {
242 		memset(addr, i, sizeof(addr));
243 		KUNIT_EXPECT_EQ(test, -EEXIST, dev_uc_add_excl(netdev, addr));
244 	}
245 	rtnl_unlock();
246 }
247 
248 /* Snapshot test: basic sync with no concurrent modifications.
249  * Add one address, snapshot, driver syncs it, reconcile propagates
250  * sync_cnt delta back to real list.
251  */
252 static void dev_addr_test_snapshot_sync(struct kunit *test)
253 {
254 	struct netdev_hw_addr_list snap, ref, cache;
255 	struct net_device *netdev = test->priv;
256 	struct dev_addr_test_priv *datp;
257 	struct netdev_hw_addr *ha;
258 	u8 addr[ETH_ALEN];
259 
260 	datp = netdev_priv(netdev);
261 
262 	rtnl_lock();
263 
264 	memset(addr, ADDR_A, sizeof(addr));
265 	KUNIT_EXPECT_EQ(test, 0, dev_uc_add(netdev, addr));
266 
267 	/* Snapshot: ADDR_A has sync_cnt=0, refcount=1 (new) */
268 	netif_addr_lock_bh(netdev);
269 	__hw_addr_init(&snap);
270 	__hw_addr_init(&ref);
271 	__hw_addr_init(&cache);
272 	KUNIT_EXPECT_EQ(test, 0,
273 			__hw_addr_list_snapshot(&snap, &netdev->uc, ETH_ALEN,
274 						&cache));
275 	KUNIT_EXPECT_EQ(test, 0,
276 			__hw_addr_list_snapshot(&ref, &netdev->uc, ETH_ALEN,
277 						&cache));
278 	netif_addr_unlock_bh(netdev);
279 
280 	/* Driver syncs ADDR_A to hardware */
281 	dev_addr_test_reset(netdev);
282 	__hw_addr_sync_dev(&snap, netdev, dev_addr_test_sync,
283 			   dev_addr_test_unsync);
284 	KUNIT_EXPECT_EQ(test, 1 << ADDR_A, datp->addr_synced);
285 	KUNIT_EXPECT_EQ(test, 0, datp->addr_unsynced);
286 
287 	/* Reconcile: delta=+1 applied to real entry */
288 	netif_addr_lock_bh(netdev);
289 	__hw_addr_list_reconcile(&netdev->uc, &snap, &ref, ETH_ALEN,
290 				 &cache);
291 	netif_addr_unlock_bh(netdev);
292 
293 	/* Real entry should now reflect the sync: sync_cnt=1, refcount=2 */
294 	KUNIT_EXPECT_EQ(test, 1, netdev->uc.count);
295 	ha = list_first_entry(&netdev->uc.list, struct netdev_hw_addr, list);
296 	KUNIT_EXPECT_MEMEQ(test, ha->addr, addr, ETH_ALEN);
297 	KUNIT_EXPECT_EQ(test, 1, ha->sync_cnt);
298 	KUNIT_EXPECT_EQ(test, 2, ha->refcount);
299 
300 	/* Second work run: already synced, nothing to do */
301 	dev_addr_test_reset(netdev);
302 	__hw_addr_sync_dev(&netdev->uc, netdev, dev_addr_test_sync,
303 			   dev_addr_test_unsync);
304 	KUNIT_EXPECT_EQ(test, 0, datp->addr_synced);
305 	KUNIT_EXPECT_EQ(test, 0, datp->addr_unsynced);
306 	KUNIT_EXPECT_EQ(test, 1, netdev->uc.count);
307 
308 	__hw_addr_flush(&cache);
309 	rtnl_unlock();
310 }
311 
312 /* Snapshot test: ADDR_A synced to hardware, then concurrently removed
313  * from the real list before reconcile runs. Reconcile re-inserts ADDR_A as
314  * a stale entry so the next work run unsyncs it from hardware.
315  */
316 static void dev_addr_test_snapshot_remove_during_sync(struct kunit *test)
317 {
318 	struct netdev_hw_addr_list snap, ref, cache;
319 	struct net_device *netdev = test->priv;
320 	struct dev_addr_test_priv *datp;
321 	struct netdev_hw_addr *ha;
322 	u8 addr[ETH_ALEN];
323 
324 	datp = netdev_priv(netdev);
325 
326 	rtnl_lock();
327 
328 	memset(addr, ADDR_A, sizeof(addr));
329 	KUNIT_EXPECT_EQ(test, 0, dev_uc_add(netdev, addr));
330 
331 	/* Snapshot: ADDR_A is new (sync_cnt=0, refcount=1) */
332 	netif_addr_lock_bh(netdev);
333 	__hw_addr_init(&snap);
334 	__hw_addr_init(&ref);
335 	__hw_addr_init(&cache);
336 	KUNIT_EXPECT_EQ(test, 0,
337 			__hw_addr_list_snapshot(&snap, &netdev->uc, ETH_ALEN,
338 						&cache));
339 	KUNIT_EXPECT_EQ(test, 0,
340 			__hw_addr_list_snapshot(&ref, &netdev->uc, ETH_ALEN,
341 						&cache));
342 	netif_addr_unlock_bh(netdev);
343 
344 	/* Driver syncs ADDR_A to hardware */
345 	dev_addr_test_reset(netdev);
346 	__hw_addr_sync_dev(&snap, netdev, dev_addr_test_sync,
347 			   dev_addr_test_unsync);
348 	KUNIT_EXPECT_EQ(test, 1 << ADDR_A, datp->addr_synced);
349 	KUNIT_EXPECT_EQ(test, 0, datp->addr_unsynced);
350 
351 	/* Concurrent removal: user deletes ADDR_A while driver was working */
352 	memset(addr, ADDR_A, sizeof(addr));
353 	KUNIT_EXPECT_EQ(test, 0, dev_uc_del(netdev, addr));
354 	KUNIT_EXPECT_EQ(test, 0, netdev->uc.count);
355 
356 	/* Reconcile: ADDR_A gone from real list but driver synced it,
357 	 * so it gets re-inserted as stale (sync_cnt=1, refcount=1).
358 	 */
359 	netif_addr_lock_bh(netdev);
360 	__hw_addr_list_reconcile(&netdev->uc, &snap, &ref, ETH_ALEN,
361 				 &cache);
362 	netif_addr_unlock_bh(netdev);
363 
364 	KUNIT_EXPECT_EQ(test, 1, netdev->uc.count);
365 	ha = list_first_entry(&netdev->uc.list, struct netdev_hw_addr, list);
366 	KUNIT_EXPECT_MEMEQ(test, ha->addr, addr, ETH_ALEN);
367 	KUNIT_EXPECT_EQ(test, 1, ha->sync_cnt);
368 	KUNIT_EXPECT_EQ(test, 1, ha->refcount);
369 
370 	/* Second work run: stale entry gets unsynced from HW and removed */
371 	dev_addr_test_reset(netdev);
372 	__hw_addr_sync_dev(&netdev->uc, netdev, dev_addr_test_sync,
373 			   dev_addr_test_unsync);
374 	KUNIT_EXPECT_EQ(test, 0, datp->addr_synced);
375 	KUNIT_EXPECT_EQ(test, 1 << ADDR_A, datp->addr_unsynced);
376 	KUNIT_EXPECT_EQ(test, 0, netdev->uc.count);
377 
378 	__hw_addr_flush(&cache);
379 	rtnl_unlock();
380 }
381 
382 /* Snapshot test: ADDR_A was stale (unsynced from hardware by driver),
383  * but concurrently re-added by the user. The re-add bumps refcount of
384  * the existing stale entry. Reconcile applies delta=-1, leaving ADDR_A
385  * as a fresh entry (sync_cnt=0, refcount=1) for the next work run.
386  */
387 static void dev_addr_test_snapshot_readd_during_unsync(struct kunit *test)
388 {
389 	struct netdev_hw_addr_list snap, ref, cache;
390 	struct net_device *netdev = test->priv;
391 	struct dev_addr_test_priv *datp;
392 	struct netdev_hw_addr *ha;
393 	u8 addr[ETH_ALEN];
394 
395 	datp = netdev_priv(netdev);
396 
397 	rtnl_lock();
398 
399 	memset(addr, ADDR_A, sizeof(addr));
400 	KUNIT_EXPECT_EQ(test, 0, dev_uc_add(netdev, addr));
401 
402 	/* Sync ADDR_A to hardware: sync_cnt=1, refcount=2 */
403 	dev_addr_test_reset(netdev);
404 	__hw_addr_sync_dev(&netdev->uc, netdev, dev_addr_test_sync,
405 			   dev_addr_test_unsync);
406 	KUNIT_EXPECT_EQ(test, 1 << ADDR_A, datp->addr_synced);
407 	KUNIT_EXPECT_EQ(test, 0, datp->addr_unsynced);
408 
409 	/* User removes ADDR_A: refcount=1, sync_cnt=1 -> stale */
410 	KUNIT_EXPECT_EQ(test, 0, dev_uc_del(netdev, addr));
411 
412 	/* Snapshot: ADDR_A is stale (sync_cnt=1, refcount=1) */
413 	netif_addr_lock_bh(netdev);
414 	__hw_addr_init(&snap);
415 	__hw_addr_init(&ref);
416 	__hw_addr_init(&cache);
417 	KUNIT_EXPECT_EQ(test, 0,
418 			__hw_addr_list_snapshot(&snap, &netdev->uc, ETH_ALEN,
419 						&cache));
420 	KUNIT_EXPECT_EQ(test, 0,
421 			__hw_addr_list_snapshot(&ref, &netdev->uc, ETH_ALEN,
422 						&cache));
423 	netif_addr_unlock_bh(netdev);
424 
425 	/* Driver unsyncs stale ADDR_A from hardware */
426 	dev_addr_test_reset(netdev);
427 	__hw_addr_sync_dev(&snap, netdev, dev_addr_test_sync,
428 			   dev_addr_test_unsync);
429 	KUNIT_EXPECT_EQ(test, 0, datp->addr_synced);
430 	KUNIT_EXPECT_EQ(test, 1 << ADDR_A, datp->addr_unsynced);
431 
432 	/* Concurrent: user re-adds ADDR_A.  dev_uc_add finds the existing
433 	 * stale entry and bumps refcount from 1 -> 2.  sync_cnt stays 1.
434 	 */
435 	KUNIT_EXPECT_EQ(test, 0, dev_uc_add(netdev, addr));
436 	KUNIT_EXPECT_EQ(test, 1, netdev->uc.count);
437 
438 	/* Reconcile: ref sync_cnt=1 matches real sync_cnt=1, delta=-1
439 	 * applied. Result: sync_cnt=0, refcount=1 (fresh).
440 	 */
441 	netif_addr_lock_bh(netdev);
442 	__hw_addr_list_reconcile(&netdev->uc, &snap, &ref, ETH_ALEN,
443 				 &cache);
444 	netif_addr_unlock_bh(netdev);
445 
446 	/* Entry survives as fresh: needs re-sync to HW */
447 	KUNIT_EXPECT_EQ(test, 1, netdev->uc.count);
448 	ha = list_first_entry(&netdev->uc.list, struct netdev_hw_addr, list);
449 	KUNIT_EXPECT_MEMEQ(test, ha->addr, addr, ETH_ALEN);
450 	KUNIT_EXPECT_EQ(test, 0, ha->sync_cnt);
451 	KUNIT_EXPECT_EQ(test, 1, ha->refcount);
452 
453 	/* Second work run: fresh entry gets synced to HW */
454 	dev_addr_test_reset(netdev);
455 	__hw_addr_sync_dev(&netdev->uc, netdev, dev_addr_test_sync,
456 			   dev_addr_test_unsync);
457 	KUNIT_EXPECT_EQ(test, 1 << ADDR_A, datp->addr_synced);
458 	KUNIT_EXPECT_EQ(test, 0, datp->addr_unsynced);
459 
460 	__hw_addr_flush(&cache);
461 	rtnl_unlock();
462 }
463 
464 /* Snapshot test: ADDR_A is new (synced by driver), and independent ADDR_B
465  * is concurrently removed from the real list. A's sync delta propagates
466  * normally; B's absence doesn't interfere.
467  */
468 static void dev_addr_test_snapshot_add_and_remove(struct kunit *test)
469 {
470 	struct netdev_hw_addr_list snap, ref, cache;
471 	struct net_device *netdev = test->priv;
472 	struct dev_addr_test_priv *datp;
473 	struct netdev_hw_addr *ha;
474 	u8 addr[ETH_ALEN];
475 
476 	datp = netdev_priv(netdev);
477 
478 	rtnl_lock();
479 
480 	/* Add ADDR_A and ADDR_B (will be synced then removed) */
481 	memset(addr, ADDR_A, sizeof(addr));
482 	KUNIT_EXPECT_EQ(test, 0, dev_uc_add(netdev, addr));
483 	memset(addr, ADDR_B, sizeof(addr));
484 	KUNIT_EXPECT_EQ(test, 0, dev_uc_add(netdev, addr));
485 
486 	/* Sync both to hardware: sync_cnt=1, refcount=2 */
487 	__hw_addr_sync_dev(&netdev->uc, netdev, dev_addr_test_sync,
488 			   dev_addr_test_unsync);
489 
490 	/* Add ADDR_C (new, will be synced by snapshot) */
491 	memset(addr, ADDR_C, sizeof(addr));
492 	KUNIT_EXPECT_EQ(test, 0, dev_uc_add(netdev, addr));
493 
494 	/* Snapshot: A,B synced (sync_cnt=1,refcount=2); C new (0,1) */
495 	netif_addr_lock_bh(netdev);
496 	__hw_addr_init(&snap);
497 	__hw_addr_init(&ref);
498 	__hw_addr_init(&cache);
499 	KUNIT_EXPECT_EQ(test, 0,
500 			__hw_addr_list_snapshot(&snap, &netdev->uc, ETH_ALEN,
501 						&cache));
502 	KUNIT_EXPECT_EQ(test, 0,
503 			__hw_addr_list_snapshot(&ref, &netdev->uc, ETH_ALEN,
504 						&cache));
505 	netif_addr_unlock_bh(netdev);
506 
507 	/* Driver syncs snapshot: ADDR_C is new -> synced; A,B already synced */
508 	dev_addr_test_reset(netdev);
509 	__hw_addr_sync_dev(&snap, netdev, dev_addr_test_sync,
510 			   dev_addr_test_unsync);
511 	KUNIT_EXPECT_EQ(test, 1 << ADDR_C, datp->addr_synced);
512 	KUNIT_EXPECT_EQ(test, 0, datp->addr_unsynced);
513 
514 	/* Concurrent: user removes addr B while driver was working */
515 	memset(addr, ADDR_B, sizeof(addr));
516 	KUNIT_EXPECT_EQ(test, 0, dev_uc_del(netdev, addr));
517 
518 	/* Reconcile: ADDR_C's delta=+1 applied to real list.
519 	 * ADDR_B's delta=0 (unchanged in snapshot),
520 	 * so nothing to apply to ADDR_B.
521 	 */
522 	netif_addr_lock_bh(netdev);
523 	__hw_addr_list_reconcile(&netdev->uc, &snap, &ref, ETH_ALEN,
524 				 &cache);
525 	netif_addr_unlock_bh(netdev);
526 
527 	/* ADDR_A: unchanged (sync_cnt=1, refcount=2)
528 	 * ADDR_B: refcount went from 2->1 via dev_uc_del (still present, stale)
529 	 * ADDR_C: sync propagated (sync_cnt=1, refcount=2)
530 	 */
531 	KUNIT_EXPECT_EQ(test, 3, netdev->uc.count);
532 	netdev_hw_addr_list_for_each(ha, &netdev->uc) {
533 		u8 id = ha->addr[0];
534 
535 		if (!memchr_inv(ha->addr, id, ETH_ALEN)) {
536 			if (id == ADDR_A) {
537 				KUNIT_EXPECT_EQ(test, 1, ha->sync_cnt);
538 				KUNIT_EXPECT_EQ(test, 2, ha->refcount);
539 			} else if (id == ADDR_B) {
540 				/* B: still present but now stale */
541 				KUNIT_EXPECT_EQ(test, 1, ha->sync_cnt);
542 				KUNIT_EXPECT_EQ(test, 1, ha->refcount);
543 			} else if (id == ADDR_C) {
544 				KUNIT_EXPECT_EQ(test, 1, ha->sync_cnt);
545 				KUNIT_EXPECT_EQ(test, 2, ha->refcount);
546 			}
547 		}
548 	}
549 
550 	/* Second work run: ADDR_B is stale, gets unsynced and removed */
551 	dev_addr_test_reset(netdev);
552 	__hw_addr_sync_dev(&netdev->uc, netdev, dev_addr_test_sync,
553 			   dev_addr_test_unsync);
554 	KUNIT_EXPECT_EQ(test, 0, datp->addr_synced);
555 	KUNIT_EXPECT_EQ(test, 1 << ADDR_B, datp->addr_unsynced);
556 	KUNIT_EXPECT_EQ(test, 2, netdev->uc.count);
557 
558 	__hw_addr_flush(&cache);
559 	rtnl_unlock();
560 }
561 
562 static void dev_addr_test_snapshot_benchmark(struct kunit *test)
563 {
564 	struct net_device *netdev = test->priv;
565 	struct netdev_hw_addr_list snap, cache;
566 	u8 addr[ETH_ALEN];
567 	s64 duration = 0;
568 	ktime_t start;
569 	int i, iter;
570 
571 	rtnl_lock();
572 
573 	for (i = 0; i < 1024; i++) {
574 		memset(addr, 0, sizeof(addr));
575 		addr[0] = (i >> 8) & 0xff;
576 		addr[1] = i & 0xff;
577 		KUNIT_EXPECT_EQ(test, 0, dev_uc_add(netdev, addr));
578 	}
579 
580 	__hw_addr_init(&cache);
581 
582 	for (iter = 0; iter < 1000; iter++) {
583 		netif_addr_lock_bh(netdev);
584 		__hw_addr_init(&snap);
585 
586 		start = ktime_get();
587 		KUNIT_EXPECT_EQ(test, 0,
588 				__hw_addr_list_snapshot(&snap, &netdev->uc,
589 							ETH_ALEN, &cache));
590 		duration += ktime_to_ns(ktime_sub(ktime_get(), start));
591 
592 		netif_addr_unlock_bh(netdev);
593 		__hw_addr_flush(&snap);
594 	}
595 
596 	__hw_addr_flush(&cache);
597 
598 	kunit_info(test,
599 		   "1024 addrs x 1000 snapshots: %lld ns total, %lld ns/iter",
600 		   duration, div_s64(duration, 1000));
601 
602 	rtnl_unlock();
603 }
604 
605 static struct kunit_case dev_addr_test_cases[] = {
606 	KUNIT_CASE(dev_addr_test_basic),
607 	KUNIT_CASE(dev_addr_test_sync_one),
608 	KUNIT_CASE(dev_addr_test_add_del),
609 	KUNIT_CASE(dev_addr_test_del_main),
610 	KUNIT_CASE(dev_addr_test_add_set),
611 	KUNIT_CASE(dev_addr_test_add_excl),
612 	KUNIT_CASE(dev_addr_test_snapshot_sync),
613 	KUNIT_CASE(dev_addr_test_snapshot_remove_during_sync),
614 	KUNIT_CASE(dev_addr_test_snapshot_readd_during_unsync),
615 	KUNIT_CASE(dev_addr_test_snapshot_add_and_remove),
616 	KUNIT_CASE_SLOW(dev_addr_test_snapshot_benchmark),
617 	{}
618 };
619 
620 static struct kunit_suite dev_addr_test_suite = {
621 	.name = "dev-addr-list-test",
622 	.test_cases = dev_addr_test_cases,
623 	.init = dev_addr_test_init,
624 	.exit = dev_addr_test_exit,
625 };
626 kunit_test_suite(dev_addr_test_suite);
627 
628 MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
629 MODULE_DESCRIPTION("KUnit tests for struct netdev_hw_addr_list");
630 MODULE_LICENSE("GPL");
631