dev_addr_lists_test.c (6102B)
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 8static const struct net_device_ops dummy_netdev_ops = { 9}; 10 11struct dev_addr_test_priv { 12 u32 addr_seen; 13}; 14 15static 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 24static 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 34static 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 56static 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 65static 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 81static 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 108static 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 148static 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 166static 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 196static 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 218static 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 228static 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}; 234kunit_test_suite(dev_addr_test_suite); 235 236MODULE_LICENSE("GPL");