Linux 6.10-rc3
[linux-block.git] / net / core / dev_addr_lists_test.c
CommitLineData
2c193f2c
JK
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
2c193f2c
JK
52 return 0;
53}
54
55static void dev_addr_test_exit(struct kunit *test)
56{
57 struct net_device *netdev = test->priv;
58
2c193f2c
JK
59 unregister_netdev(netdev);
60 free_netdev(netdev);
61}
62
63static void dev_addr_test_basic(struct kunit *test)
64{
65 struct net_device *netdev = test->priv;
66 u8 addr[ETH_ALEN];
67
3db3b629 68 rtnl_lock();
2c193f2c
JK
69 KUNIT_EXPECT_TRUE(test, !!netdev->dev_addr);
70
71 memset(addr, 2, sizeof(addr));
72 eth_hw_addr_set(netdev, addr);
a52a5451 73 KUNIT_EXPECT_MEMEQ(test, netdev->dev_addr, addr, sizeof(addr));
2c193f2c
JK
74
75 memset(addr, 3, sizeof(addr));
76 dev_addr_set(netdev, addr);
a52a5451 77 KUNIT_EXPECT_MEMEQ(test, netdev->dev_addr, addr, sizeof(addr));
3db3b629 78 rtnl_unlock();
2c193f2c
JK
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
3db3b629 89 rtnl_lock();
2c193f2c
JK
90 memset(addr, 1, sizeof(addr));
91 eth_hw_addr_set(netdev, addr);
92
93 __hw_addr_sync_dev(&netdev->dev_addrs, netdev, dev_addr_test_sync,
94 dev_addr_test_unsync);
95 KUNIT_EXPECT_EQ(test, 2, datp->addr_seen);
96
97 memset(addr, 2, sizeof(addr));
98 eth_hw_addr_set(netdev, addr);
99
100 datp->addr_seen = 0;
101 __hw_addr_sync_dev(&netdev->dev_addrs, netdev, dev_addr_test_sync,
102 dev_addr_test_unsync);
103 /* It's not going to sync anything because the main address is
104 * considered synced and we overwrite in place.
105 */
106 KUNIT_EXPECT_EQ(test, 0, datp->addr_seen);
3db3b629 107 rtnl_unlock();
2c193f2c
JK
108}
109
110static void dev_addr_test_add_del(struct kunit *test)
111{
112 struct net_device *netdev = test->priv;
113 struct dev_addr_test_priv *datp;
114 u8 addr[ETH_ALEN];
115 int i;
116
117 datp = netdev_priv(netdev);
118
3db3b629 119 rtnl_lock();
2c193f2c
JK
120 for (i = 1; i < 4; i++) {
121 memset(addr, i, sizeof(addr));
122 KUNIT_EXPECT_EQ(test, 0, dev_addr_add(netdev, addr,
123 NETDEV_HW_ADDR_T_LAN));
124 }
125 /* Add 3 again */
126 KUNIT_EXPECT_EQ(test, 0, dev_addr_add(netdev, addr,
127 NETDEV_HW_ADDR_T_LAN));
128
129 __hw_addr_sync_dev(&netdev->dev_addrs, netdev, dev_addr_test_sync,
130 dev_addr_test_unsync);
131 KUNIT_EXPECT_EQ(test, 0xf, datp->addr_seen);
132
133 KUNIT_EXPECT_EQ(test, 0, dev_addr_del(netdev, addr,
134 NETDEV_HW_ADDR_T_LAN));
135
136 __hw_addr_sync_dev(&netdev->dev_addrs, netdev, dev_addr_test_sync,
137 dev_addr_test_unsync);
138 KUNIT_EXPECT_EQ(test, 0xf, datp->addr_seen);
139
140 for (i = 1; i < 4; i++) {
141 memset(addr, i, sizeof(addr));
142 KUNIT_EXPECT_EQ(test, 0, dev_addr_del(netdev, addr,
143 NETDEV_HW_ADDR_T_LAN));
144 }
145
146 __hw_addr_sync_dev(&netdev->dev_addrs, netdev, dev_addr_test_sync,
147 dev_addr_test_unsync);
148 KUNIT_EXPECT_EQ(test, 1, datp->addr_seen);
3db3b629 149 rtnl_unlock();
2c193f2c
JK
150}
151
152static void dev_addr_test_del_main(struct kunit *test)
153{
154 struct net_device *netdev = test->priv;
155 u8 addr[ETH_ALEN];
156
3db3b629 157 rtnl_lock();
2c193f2c
JK
158 memset(addr, 1, sizeof(addr));
159 eth_hw_addr_set(netdev, addr);
160
161 KUNIT_EXPECT_EQ(test, -ENOENT, dev_addr_del(netdev, addr,
162 NETDEV_HW_ADDR_T_LAN));
163 KUNIT_EXPECT_EQ(test, 0, dev_addr_add(netdev, addr,
164 NETDEV_HW_ADDR_T_LAN));
165 KUNIT_EXPECT_EQ(test, 0, dev_addr_del(netdev, addr,
166 NETDEV_HW_ADDR_T_LAN));
167 KUNIT_EXPECT_EQ(test, -ENOENT, dev_addr_del(netdev, addr,
168 NETDEV_HW_ADDR_T_LAN));
3db3b629 169 rtnl_unlock();
2c193f2c
JK
170}
171
172static void dev_addr_test_add_set(struct kunit *test)
173{
174 struct net_device *netdev = test->priv;
175 struct dev_addr_test_priv *datp;
176 u8 addr[ETH_ALEN];
177 int i;
178
179 datp = netdev_priv(netdev);
180
3db3b629 181 rtnl_lock();
2c193f2c
JK
182 /* There is no external API like dev_addr_add_excl(),
183 * so shuffle the tree a little bit and exploit aliasing.
184 */
185 for (i = 1; i < 16; i++) {
186 memset(addr, i, sizeof(addr));
187 KUNIT_EXPECT_EQ(test, 0, dev_addr_add(netdev, addr,
188 NETDEV_HW_ADDR_T_LAN));
189 }
190
191 memset(addr, i, sizeof(addr));
192 eth_hw_addr_set(netdev, addr);
193 KUNIT_EXPECT_EQ(test, 0, dev_addr_add(netdev, addr,
194 NETDEV_HW_ADDR_T_LAN));
195 memset(addr, 0, sizeof(addr));
196 eth_hw_addr_set(netdev, addr);
197
198 __hw_addr_sync_dev(&netdev->dev_addrs, netdev, dev_addr_test_sync,
199 dev_addr_test_unsync);
200 KUNIT_EXPECT_EQ(test, 0xffff, datp->addr_seen);
3db3b629 201 rtnl_unlock();
2c193f2c
JK
202}
203
204static void dev_addr_test_add_excl(struct kunit *test)
205{
206 struct net_device *netdev = test->priv;
207 u8 addr[ETH_ALEN];
208 int i;
209
3db3b629 210 rtnl_lock();
2c193f2c
JK
211 for (i = 0; i < 10; i++) {
212 memset(addr, i, sizeof(addr));
213 KUNIT_EXPECT_EQ(test, 0, dev_uc_add_excl(netdev, addr));
214 }
215 KUNIT_EXPECT_EQ(test, -EEXIST, dev_uc_add_excl(netdev, addr));
216
217 for (i = 0; i < 10; i += 2) {
218 memset(addr, i, sizeof(addr));
219 KUNIT_EXPECT_EQ(test, 0, dev_uc_del(netdev, addr));
220 }
221 for (i = 1; i < 10; i += 2) {
222 memset(addr, i, sizeof(addr));
223 KUNIT_EXPECT_EQ(test, -EEXIST, dev_uc_add_excl(netdev, addr));
224 }
3db3b629 225 rtnl_unlock();
2c193f2c
JK
226}
227
228static struct kunit_case dev_addr_test_cases[] = {
229 KUNIT_CASE(dev_addr_test_basic),
230 KUNIT_CASE(dev_addr_test_sync_one),
231 KUNIT_CASE(dev_addr_test_add_del),
232 KUNIT_CASE(dev_addr_test_del_main),
233 KUNIT_CASE(dev_addr_test_add_set),
234 KUNIT_CASE(dev_addr_test_add_excl),
235 {}
236};
237
238static struct kunit_suite dev_addr_test_suite = {
239 .name = "dev-addr-list-test",
240 .test_cases = dev_addr_test_cases,
241 .init = dev_addr_test_init,
242 .exit = dev_addr_test_exit,
243};
244kunit_test_suite(dev_addr_test_suite);
245
beb5eed3 246MODULE_DESCRIPTION("KUnit tests for struct netdev_hw_addr_list");
2c193f2c 247MODULE_LICENSE("GPL");