xref: /linux/net/core/dev_addr_lists_test.c (revision 0be3ff0c)
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");
237