xref: /linux/net/core/dev_addr_lists_test.c (revision 621cde16e49b3ecf7d59a8106a20aaebfb4a59a9)
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 
dev_addr_test_sync(struct net_device * netdev,const unsigned char * a)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 
dev_addr_test_unsync(struct net_device * netdev,const unsigned char * a)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 
dev_addr_test_init(struct kunit * test)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 	return 0;
53 }
54 
dev_addr_test_exit(struct kunit * test)55 static void dev_addr_test_exit(struct kunit *test)
56 {
57 	struct net_device *netdev = test->priv;
58 
59 	unregister_netdev(netdev);
60 	free_netdev(netdev);
61 }
62 
dev_addr_test_basic(struct kunit * test)63 static void dev_addr_test_basic(struct kunit *test)
64 {
65 	struct net_device *netdev = test->priv;
66 	u8 addr[ETH_ALEN];
67 
68 	rtnl_lock();
69 	KUNIT_EXPECT_TRUE(test, !!netdev->dev_addr);
70 
71 	memset(addr, 2, sizeof(addr));
72 	eth_hw_addr_set(netdev, addr);
73 	KUNIT_EXPECT_MEMEQ(test, netdev->dev_addr, addr, sizeof(addr));
74 
75 	memset(addr, 3, sizeof(addr));
76 	dev_addr_set(netdev, addr);
77 	KUNIT_EXPECT_MEMEQ(test, netdev->dev_addr, addr, sizeof(addr));
78 	rtnl_unlock();
79 }
80 
dev_addr_test_sync_one(struct kunit * test)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 	rtnl_lock();
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);
107 	rtnl_unlock();
108 }
109 
dev_addr_test_add_del(struct kunit * test)110 static 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 
119 	rtnl_lock();
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);
149 	rtnl_unlock();
150 }
151 
dev_addr_test_del_main(struct kunit * test)152 static void dev_addr_test_del_main(struct kunit *test)
153 {
154 	struct net_device *netdev = test->priv;
155 	u8 addr[ETH_ALEN];
156 
157 	rtnl_lock();
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));
169 	rtnl_unlock();
170 }
171 
dev_addr_test_add_set(struct kunit * test)172 static 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 
181 	rtnl_lock();
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);
201 	rtnl_unlock();
202 }
203 
dev_addr_test_add_excl(struct kunit * test)204 static 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 
210 	rtnl_lock();
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 	}
225 	rtnl_unlock();
226 }
227 
228 static 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 
238 static 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 };
244 kunit_test_suite(dev_addr_test_suite);
245 
246 MODULE_DESCRIPTION("KUnit tests for struct netdev_hw_addr_list");
247 MODULE_LICENSE("GPL");
248