Merge tag 'drm-next-2023-11-07' of git://anongit.freedesktop.org/drm/drm
[linux-2.6-microblaze.git] / net / core / dev_addr_lists_test.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
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_MEMEQ(test, netdev->dev_addr, addr, sizeof(addr));
75
76         memset(addr, 3, sizeof(addr));
77         dev_addr_set(netdev, addr);
78         KUNIT_EXPECT_MEMEQ(test, 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_DESCRIPTION("KUnit tests for struct netdev_hw_addr_list");
237 MODULE_LICENSE("GPL");