File Index
Files and directories
Sign in
FILE

dev_addr_lists_test.c

File preview with syntax highlighting.

linux-6.19.14/net/core/dev_addr_lists_test.c 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
  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	return 0;
 53}
 54
 55static 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
 63static 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
 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	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
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
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
152static 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
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
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
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
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
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
246MODULE_DESCRIPTION("KUnit tests for struct netdev_hw_addr_list");
247MODULE_LICENSE("GPL");
~/ Read-only file preview.