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