Skip to content

Commit 2c193f2

Browse files
kuba-moodavem330
authored andcommitted
net: kunit: add a test for dev_addr_lists
Add a KUnit test for the dev_addr API. Signed-off-by: Jakub Kicinski <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent a387ff8 commit 2c193f2

File tree

3 files changed

+243
-0
lines changed

3 files changed

+243
-0
lines changed

net/Kconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,4 +455,9 @@ config ETHTOOL_NETLINK
455455
netlink. It provides better extensibility and some new features,
456456
e.g. notification messages.
457457

458+
config NETDEV_ADDR_LIST_TEST
459+
tristate "Unit tests for device address list"
460+
default KUNIT_ALL_TESTS
461+
depends on KUNIT
462+
458463
endif # if NET

net/core/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ obj-y += dev.o dev_addr_lists.o dst.o netevent.o \
1313
sock_diag.o dev_ioctl.o tso.o sock_reuseport.o \
1414
fib_notifier.o xdp.o flow_offload.o gro.o
1515

16+
obj-$(CONFIG_NETDEV_ADDR_LIST_TEST) += dev_addr_lists_test.o
17+
1618
obj-y += net-sysfs.o
1719
obj-$(CONFIG_PAGE_POOL) += page_pool.o
1820
obj-$(CONFIG_PROC_FS) += net-procfs.o

net/core/dev_addr_lists_test.c

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
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");

0 commit comments

Comments
 (0)