Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/net/ynl/tests/netdev.c
170958 views
1
// SPDX-License-Identifier: GPL-2.0
2
#include <stdio.h>
3
#include <string.h>
4
5
#include <ynl.h>
6
7
#include <net/if.h>
8
9
#include <kselftest_harness.h>
10
11
#include "netdev-user.h"
12
#include "rt-link-user.h"
13
14
static void netdev_print_device(struct __test_metadata *_metadata,
15
struct netdev_dev_get_rsp *d, unsigned int op)
16
{
17
char ifname[IF_NAMESIZE];
18
const char *name;
19
20
EXPECT_TRUE((bool)d->_present.ifindex);
21
if (!d->_present.ifindex)
22
return;
23
24
name = if_indextoname(d->ifindex, ifname);
25
EXPECT_TRUE((bool)name);
26
if (name)
27
ksft_print_msg("%8s[%d]\t", name, d->ifindex);
28
else
29
ksft_print_msg("[%d]\t", d->ifindex);
30
31
EXPECT_TRUE((bool)d->_present.xdp_features);
32
if (!d->_present.xdp_features)
33
return;
34
35
printf("xdp-features (%llx):", d->xdp_features);
36
for (int i = 0; d->xdp_features >= 1U << i; i++) {
37
if (d->xdp_features & (1U << i))
38
printf(" %s", netdev_xdp_act_str(1 << i));
39
}
40
41
printf(" xdp-rx-metadata-features (%llx):",
42
d->xdp_rx_metadata_features);
43
for (int i = 0; d->xdp_rx_metadata_features >= 1U << i; i++) {
44
if (d->xdp_rx_metadata_features & (1U << i))
45
printf(" %s",
46
netdev_xdp_rx_metadata_str(1 << i));
47
}
48
49
printf(" xsk-features (%llx):", d->xsk_features);
50
for (int i = 0; d->xsk_features >= 1U << i; i++) {
51
if (d->xsk_features & (1U << i))
52
printf(" %s", netdev_xsk_flags_str(1 << i));
53
}
54
55
printf(" xdp-zc-max-segs=%u", d->xdp_zc_max_segs);
56
57
name = netdev_op_str(op);
58
if (name)
59
printf(" (ntf: %s)", name);
60
printf("\n");
61
}
62
63
static int veth_create(struct ynl_sock *ys_link)
64
{
65
struct rt_link_getlink_ntf *ntf_gl;
66
struct rt_link_newlink_req *req;
67
struct ynl_ntf_base_type *ntf;
68
int ret;
69
70
req = rt_link_newlink_req_alloc();
71
if (!req)
72
return -1;
73
74
rt_link_newlink_req_set_nlflags(req, NLM_F_CREATE | NLM_F_ECHO);
75
rt_link_newlink_req_set_linkinfo_kind(req, "veth");
76
77
ret = rt_link_newlink(ys_link, req);
78
rt_link_newlink_req_free(req);
79
if (ret)
80
return -1;
81
82
if (!ynl_has_ntf(ys_link))
83
return 0;
84
85
ntf = ynl_ntf_dequeue(ys_link);
86
if (!ntf || ntf->cmd != RTM_NEWLINK) {
87
ynl_ntf_free(ntf);
88
return 0;
89
}
90
ntf_gl = (void *)ntf;
91
ret = ntf_gl->obj._hdr.ifi_index;
92
ynl_ntf_free(ntf);
93
94
return ret;
95
}
96
97
static void veth_delete(struct __test_metadata *_metadata,
98
struct ynl_sock *ys_link, int ifindex)
99
{
100
struct rt_link_dellink_req *req;
101
102
req = rt_link_dellink_req_alloc();
103
ASSERT_NE(NULL, req);
104
105
req->_hdr.ifi_index = ifindex;
106
EXPECT_EQ(0, rt_link_dellink(ys_link, req));
107
rt_link_dellink_req_free(req);
108
}
109
110
FIXTURE(netdev)
111
{
112
struct ynl_sock *ys;
113
struct ynl_sock *ys_link;
114
};
115
116
FIXTURE_SETUP(netdev)
117
{
118
struct ynl_error yerr;
119
120
self->ys = ynl_sock_create(&ynl_netdev_family, &yerr);
121
ASSERT_NE(NULL, self->ys) {
122
TH_LOG("Failed to create YNL netdev socket: %s", yerr.msg);
123
}
124
}
125
126
FIXTURE_TEARDOWN(netdev)
127
{
128
if (self->ys_link)
129
ynl_sock_destroy(self->ys_link);
130
ynl_sock_destroy(self->ys);
131
}
132
133
TEST_F(netdev, dump)
134
{
135
struct netdev_dev_get_list *devs;
136
137
devs = netdev_dev_get_dump(self->ys);
138
ASSERT_NE(NULL, devs) {
139
TH_LOG("dump failed: %s", self->ys->err.msg);
140
}
141
142
if (ynl_dump_empty(devs)) {
143
netdev_dev_get_list_free(devs);
144
SKIP(return, "no entries in dump");
145
}
146
147
ynl_dump_foreach(devs, d)
148
netdev_print_device(_metadata, d, 0);
149
150
netdev_dev_get_list_free(devs);
151
}
152
153
TEST_F(netdev, get)
154
{
155
struct netdev_dev_get_list *devs;
156
struct netdev_dev_get_req *req;
157
struct netdev_dev_get_rsp *dev;
158
int ifindex = 0;
159
160
devs = netdev_dev_get_dump(self->ys);
161
ASSERT_NE(NULL, devs) {
162
TH_LOG("dump failed: %s", self->ys->err.msg);
163
}
164
165
ynl_dump_foreach(devs, d) {
166
if (d->_present.ifindex) {
167
ifindex = d->ifindex;
168
break;
169
}
170
}
171
netdev_dev_get_list_free(devs);
172
173
if (!ifindex)
174
SKIP(return, "no device to query");
175
176
req = netdev_dev_get_req_alloc();
177
ASSERT_NE(NULL, req);
178
netdev_dev_get_req_set_ifindex(req, ifindex);
179
180
dev = netdev_dev_get(self->ys, req);
181
netdev_dev_get_req_free(req);
182
ASSERT_NE(NULL, dev) {
183
TH_LOG("dev_get failed: %s", self->ys->err.msg);
184
}
185
186
netdev_print_device(_metadata, dev, 0);
187
netdev_dev_get_rsp_free(dev);
188
}
189
190
TEST_F(netdev, ntf_check)
191
{
192
struct ynl_ntf_base_type *ntf;
193
int veth_ifindex;
194
bool received;
195
int ret;
196
197
ret = ynl_subscribe(self->ys, "mgmt");
198
ASSERT_EQ(0, ret) {
199
TH_LOG("subscribe failed: %s", self->ys->err.msg);
200
}
201
202
self->ys_link = ynl_sock_create(&ynl_rt_link_family, NULL);
203
ASSERT_NE(NULL, self->ys_link)
204
TH_LOG("failed to create rt-link socket");
205
206
veth_ifindex = veth_create(self->ys_link);
207
ASSERT_GT(veth_ifindex, 0)
208
TH_LOG("failed to create veth");
209
210
ynl_ntf_check(self->ys);
211
212
ntf = ynl_ntf_dequeue(self->ys);
213
received = ntf;
214
if (ntf) {
215
netdev_print_device(_metadata,
216
(struct netdev_dev_get_rsp *)&ntf->data,
217
ntf->cmd);
218
ynl_ntf_free(ntf);
219
}
220
221
/* Drain any remaining notifications */
222
while ((ntf = ynl_ntf_dequeue(self->ys)))
223
ynl_ntf_free(ntf);
224
225
veth_delete(_metadata, self->ys_link, veth_ifindex);
226
227
ASSERT_TRUE(received)
228
TH_LOG("no notification received");
229
}
230
231
TEST_HARNESS_MAIN
232
233