Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: kunit: add a test for dev_addr_lists

Add a KUnit test for the dev_addr API.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Jakub Kicinski and committed by
David S. Miller
2c193f2c a387ff8e

+243
+5
net/Kconfig
··· 455 455 netlink. It provides better extensibility and some new features, 456 456 e.g. notification messages. 457 457 458 + config NETDEV_ADDR_LIST_TEST 459 + tristate "Unit tests for device address list" 460 + default KUNIT_ALL_TESTS 461 + depends on KUNIT 462 + 458 463 endif # if NET
+2
net/core/Makefile
··· 13 13 sock_diag.o dev_ioctl.o tso.o sock_reuseport.o \ 14 14 fib_notifier.o xdp.o flow_offload.o gro.o 15 15 16 + obj-$(CONFIG_NETDEV_ADDR_LIST_TEST) += dev_addr_lists_test.o 17 + 16 18 obj-y += net-sysfs.o 17 19 obj-$(CONFIG_PAGE_POOL) += page_pool.o 18 20 obj-$(CONFIG_PROC_FS) += net-procfs.o
+236
net/core/dev_addr_lists_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + 3 + #include <kunit/test.h> 4 + #include <linux/etherdevice.h> 5 + #include <linux/netdevice.h> 6 + #include <linux/rtnetlink.h> 7 + 8 + static const struct net_device_ops dummy_netdev_ops = { 9 + }; 10 + 11 + struct dev_addr_test_priv { 12 + u32 addr_seen; 13 + }; 14 + 15 + static int dev_addr_test_sync(struct net_device *netdev, const unsigned char *a) 16 + { 17 + struct dev_addr_test_priv *datp = netdev_priv(netdev); 18 + 19 + if (a[0] < 31 && !memchr_inv(a, a[0], ETH_ALEN)) 20 + datp->addr_seen |= 1 << a[0]; 21 + return 0; 22 + } 23 + 24 + static int dev_addr_test_unsync(struct net_device *netdev, 25 + const unsigned char *a) 26 + { 27 + struct dev_addr_test_priv *datp = netdev_priv(netdev); 28 + 29 + if (a[0] < 31 && !memchr_inv(a, a[0], ETH_ALEN)) 30 + datp->addr_seen &= ~(1 << a[0]); 31 + return 0; 32 + } 33 + 34 + static int dev_addr_test_init(struct kunit *test) 35 + { 36 + struct dev_addr_test_priv *datp; 37 + struct net_device *netdev; 38 + int err; 39 + 40 + netdev = alloc_etherdev(sizeof(*datp)); 41 + KUNIT_ASSERT_TRUE(test, !!netdev); 42 + 43 + test->priv = netdev; 44 + netdev->netdev_ops = &dummy_netdev_ops; 45 + 46 + err = register_netdev(netdev); 47 + if (err) { 48 + free_netdev(netdev); 49 + KUNIT_FAIL(test, "Can't register netdev %d", err); 50 + } 51 + 52 + rtnl_lock(); 53 + return 0; 54 + } 55 + 56 + static void dev_addr_test_exit(struct kunit *test) 57 + { 58 + struct net_device *netdev = test->priv; 59 + 60 + rtnl_unlock(); 61 + unregister_netdev(netdev); 62 + free_netdev(netdev); 63 + } 64 + 65 + static void dev_addr_test_basic(struct kunit *test) 66 + { 67 + struct net_device *netdev = test->priv; 68 + u8 addr[ETH_ALEN]; 69 + 70 + KUNIT_EXPECT_TRUE(test, !!netdev->dev_addr); 71 + 72 + memset(addr, 2, sizeof(addr)); 73 + eth_hw_addr_set(netdev, addr); 74 + KUNIT_EXPECT_EQ(test, 0, memcmp(netdev->dev_addr, addr, sizeof(addr))); 75 + 76 + memset(addr, 3, sizeof(addr)); 77 + dev_addr_set(netdev, addr); 78 + KUNIT_EXPECT_EQ(test, 0, memcmp(netdev->dev_addr, addr, sizeof(addr))); 79 + } 80 + 81 + static void dev_addr_test_sync_one(struct kunit *test) 82 + { 83 + struct net_device *netdev = test->priv; 84 + struct dev_addr_test_priv *datp; 85 + u8 addr[ETH_ALEN]; 86 + 87 + datp = netdev_priv(netdev); 88 + 89 + memset(addr, 1, sizeof(addr)); 90 + eth_hw_addr_set(netdev, addr); 91 + 92 + __hw_addr_sync_dev(&netdev->dev_addrs, netdev, dev_addr_test_sync, 93 + dev_addr_test_unsync); 94 + KUNIT_EXPECT_EQ(test, 2, datp->addr_seen); 95 + 96 + memset(addr, 2, sizeof(addr)); 97 + eth_hw_addr_set(netdev, addr); 98 + 99 + datp->addr_seen = 0; 100 + __hw_addr_sync_dev(&netdev->dev_addrs, netdev, dev_addr_test_sync, 101 + dev_addr_test_unsync); 102 + /* It's not going to sync anything because the main address is 103 + * considered synced and we overwrite in place. 104 + */ 105 + KUNIT_EXPECT_EQ(test, 0, datp->addr_seen); 106 + } 107 + 108 + static void dev_addr_test_add_del(struct kunit *test) 109 + { 110 + struct net_device *netdev = test->priv; 111 + struct dev_addr_test_priv *datp; 112 + u8 addr[ETH_ALEN]; 113 + int i; 114 + 115 + datp = netdev_priv(netdev); 116 + 117 + for (i = 1; i < 4; i++) { 118 + memset(addr, i, sizeof(addr)); 119 + KUNIT_EXPECT_EQ(test, 0, dev_addr_add(netdev, addr, 120 + NETDEV_HW_ADDR_T_LAN)); 121 + } 122 + /* Add 3 again */ 123 + KUNIT_EXPECT_EQ(test, 0, dev_addr_add(netdev, addr, 124 + NETDEV_HW_ADDR_T_LAN)); 125 + 126 + __hw_addr_sync_dev(&netdev->dev_addrs, netdev, dev_addr_test_sync, 127 + dev_addr_test_unsync); 128 + KUNIT_EXPECT_EQ(test, 0xf, datp->addr_seen); 129 + 130 + KUNIT_EXPECT_EQ(test, 0, dev_addr_del(netdev, addr, 131 + NETDEV_HW_ADDR_T_LAN)); 132 + 133 + __hw_addr_sync_dev(&netdev->dev_addrs, netdev, dev_addr_test_sync, 134 + dev_addr_test_unsync); 135 + KUNIT_EXPECT_EQ(test, 0xf, datp->addr_seen); 136 + 137 + for (i = 1; i < 4; i++) { 138 + memset(addr, i, sizeof(addr)); 139 + KUNIT_EXPECT_EQ(test, 0, dev_addr_del(netdev, addr, 140 + NETDEV_HW_ADDR_T_LAN)); 141 + } 142 + 143 + __hw_addr_sync_dev(&netdev->dev_addrs, netdev, dev_addr_test_sync, 144 + dev_addr_test_unsync); 145 + KUNIT_EXPECT_EQ(test, 1, datp->addr_seen); 146 + } 147 + 148 + static void dev_addr_test_del_main(struct kunit *test) 149 + { 150 + struct net_device *netdev = test->priv; 151 + u8 addr[ETH_ALEN]; 152 + 153 + memset(addr, 1, sizeof(addr)); 154 + eth_hw_addr_set(netdev, addr); 155 + 156 + KUNIT_EXPECT_EQ(test, -ENOENT, dev_addr_del(netdev, addr, 157 + NETDEV_HW_ADDR_T_LAN)); 158 + KUNIT_EXPECT_EQ(test, 0, dev_addr_add(netdev, addr, 159 + NETDEV_HW_ADDR_T_LAN)); 160 + KUNIT_EXPECT_EQ(test, 0, dev_addr_del(netdev, addr, 161 + NETDEV_HW_ADDR_T_LAN)); 162 + KUNIT_EXPECT_EQ(test, -ENOENT, dev_addr_del(netdev, addr, 163 + NETDEV_HW_ADDR_T_LAN)); 164 + } 165 + 166 + static void dev_addr_test_add_set(struct kunit *test) 167 + { 168 + struct net_device *netdev = test->priv; 169 + struct dev_addr_test_priv *datp; 170 + u8 addr[ETH_ALEN]; 171 + int i; 172 + 173 + datp = netdev_priv(netdev); 174 + 175 + /* There is no external API like dev_addr_add_excl(), 176 + * so shuffle the tree a little bit and exploit aliasing. 177 + */ 178 + for (i = 1; i < 16; i++) { 179 + memset(addr, i, sizeof(addr)); 180 + KUNIT_EXPECT_EQ(test, 0, dev_addr_add(netdev, addr, 181 + NETDEV_HW_ADDR_T_LAN)); 182 + } 183 + 184 + memset(addr, i, sizeof(addr)); 185 + eth_hw_addr_set(netdev, addr); 186 + KUNIT_EXPECT_EQ(test, 0, dev_addr_add(netdev, addr, 187 + NETDEV_HW_ADDR_T_LAN)); 188 + memset(addr, 0, sizeof(addr)); 189 + eth_hw_addr_set(netdev, addr); 190 + 191 + __hw_addr_sync_dev(&netdev->dev_addrs, netdev, dev_addr_test_sync, 192 + dev_addr_test_unsync); 193 + KUNIT_EXPECT_EQ(test, 0xffff, datp->addr_seen); 194 + } 195 + 196 + static void dev_addr_test_add_excl(struct kunit *test) 197 + { 198 + struct net_device *netdev = test->priv; 199 + u8 addr[ETH_ALEN]; 200 + int i; 201 + 202 + for (i = 0; i < 10; i++) { 203 + memset(addr, i, sizeof(addr)); 204 + KUNIT_EXPECT_EQ(test, 0, dev_uc_add_excl(netdev, addr)); 205 + } 206 + KUNIT_EXPECT_EQ(test, -EEXIST, dev_uc_add_excl(netdev, addr)); 207 + 208 + for (i = 0; i < 10; i += 2) { 209 + memset(addr, i, sizeof(addr)); 210 + KUNIT_EXPECT_EQ(test, 0, dev_uc_del(netdev, addr)); 211 + } 212 + for (i = 1; i < 10; i += 2) { 213 + memset(addr, i, sizeof(addr)); 214 + KUNIT_EXPECT_EQ(test, -EEXIST, dev_uc_add_excl(netdev, addr)); 215 + } 216 + } 217 + 218 + static struct kunit_case dev_addr_test_cases[] = { 219 + KUNIT_CASE(dev_addr_test_basic), 220 + KUNIT_CASE(dev_addr_test_sync_one), 221 + KUNIT_CASE(dev_addr_test_add_del), 222 + KUNIT_CASE(dev_addr_test_del_main), 223 + KUNIT_CASE(dev_addr_test_add_set), 224 + KUNIT_CASE(dev_addr_test_add_excl), 225 + {} 226 + }; 227 + 228 + static struct kunit_suite dev_addr_test_suite = { 229 + .name = "dev-addr-list-test", 230 + .test_cases = dev_addr_test_cases, 231 + .init = dev_addr_test_init, 232 + .exit = dev_addr_test_exit, 233 + }; 234 + kunit_test_suite(dev_addr_test_suite); 235 + 236 + MODULE_LICENSE("GPL");