xref: /linux/tools/net/ynl/tests/rt-link.c (revision 91a4855d6c03e770e42f17c798a36a3c46e63de2)
1e0aa0c61SJakub Kicinski // SPDX-License-Identifier: GPL-2.0
2e0aa0c61SJakub Kicinski #include <stdio.h>
3e0aa0c61SJakub Kicinski #include <string.h>
4e0aa0c61SJakub Kicinski 
5e0aa0c61SJakub Kicinski #include <ynl.h>
6e0aa0c61SJakub Kicinski 
7e0aa0c61SJakub Kicinski #include <arpa/inet.h>
8e0aa0c61SJakub Kicinski #include <net/if.h>
9e0aa0c61SJakub Kicinski 
10*5c320678SJakub Kicinski #include <kselftest_harness.h>
11*5c320678SJakub Kicinski 
12e0aa0c61SJakub Kicinski #include "rt-link-user.h"
13e0aa0c61SJakub Kicinski 
14*5c320678SJakub Kicinski static void rt_link_print(struct __test_metadata *_metadata,
15*5c320678SJakub Kicinski 			  struct rt_link_getlink_rsp *r)
16e0aa0c61SJakub Kicinski {
17e0aa0c61SJakub Kicinski 	unsigned int i;
18e0aa0c61SJakub Kicinski 
19*5c320678SJakub Kicinski 	EXPECT_TRUE((bool)r->_hdr.ifi_index);
20*5c320678SJakub Kicinski 	ksft_print_msg("%3d: ", r->_hdr.ifi_index);
21e0aa0c61SJakub Kicinski 
22*5c320678SJakub Kicinski 	EXPECT_TRUE((bool)r->_len.ifname);
23e0aa0c61SJakub Kicinski 	if (r->_len.ifname)
24*5c320678SJakub Kicinski 		printf("%6s: ", r->ifname);
25e0aa0c61SJakub Kicinski 
26e0aa0c61SJakub Kicinski 	if (r->_present.mtu)
27e0aa0c61SJakub Kicinski 		printf("mtu %5d  ", r->mtu);
28e0aa0c61SJakub Kicinski 
29e0aa0c61SJakub Kicinski 	if (r->linkinfo._len.kind)
30e0aa0c61SJakub Kicinski 		printf("kind %-8s  ", r->linkinfo.kind);
31e0aa0c61SJakub Kicinski 	else
32e0aa0c61SJakub Kicinski 		printf("     %8s  ", "");
33e0aa0c61SJakub Kicinski 
34e0aa0c61SJakub Kicinski 	if (r->prop_list._count.alt_ifname) {
35e0aa0c61SJakub Kicinski 		printf("altname ");
36e0aa0c61SJakub Kicinski 		for (i = 0; i < r->prop_list._count.alt_ifname; i++)
37e0aa0c61SJakub Kicinski 			printf("%s ", r->prop_list.alt_ifname[i]->str);
38e0aa0c61SJakub Kicinski 		printf(" ");
39e0aa0c61SJakub Kicinski 	}
40e0aa0c61SJakub Kicinski 
41e0aa0c61SJakub Kicinski 	if (r->linkinfo._present.data && r->linkinfo.data._present.netkit) {
42e0aa0c61SJakub Kicinski 		struct rt_link_linkinfo_netkit_attrs *netkit;
43e0aa0c61SJakub Kicinski 		const char *name;
44e0aa0c61SJakub Kicinski 
45e0aa0c61SJakub Kicinski 		netkit = &r->linkinfo.data.netkit;
46e0aa0c61SJakub Kicinski 		printf("primary %d  ", netkit->primary);
47e0aa0c61SJakub Kicinski 
48e0aa0c61SJakub Kicinski 		name = NULL;
49e0aa0c61SJakub Kicinski 		if (netkit->_present.policy)
50e0aa0c61SJakub Kicinski 			name = rt_link_netkit_policy_str(netkit->policy);
51e0aa0c61SJakub Kicinski 		if (name)
52e0aa0c61SJakub Kicinski 			printf("policy %s  ", name);
53e0aa0c61SJakub Kicinski 	}
54e0aa0c61SJakub Kicinski 
55e0aa0c61SJakub Kicinski 	printf("\n");
56e0aa0c61SJakub Kicinski }
57e0aa0c61SJakub Kicinski 
58*5c320678SJakub Kicinski static int netkit_create(struct ynl_sock *ys)
59e0aa0c61SJakub Kicinski {
60e0aa0c61SJakub Kicinski 	struct rt_link_getlink_ntf *ntf_gl;
61e0aa0c61SJakub Kicinski 	struct rt_link_newlink_req *req;
62e0aa0c61SJakub Kicinski 	struct ynl_ntf_base_type *ntf;
63e0aa0c61SJakub Kicinski 	int ret;
64e0aa0c61SJakub Kicinski 
65e0aa0c61SJakub Kicinski 	req = rt_link_newlink_req_alloc();
66*5c320678SJakub Kicinski 	if (!req)
67e0aa0c61SJakub Kicinski 		return -1;
68e0aa0c61SJakub Kicinski 
69e0aa0c61SJakub Kicinski 	rt_link_newlink_req_set_nlflags(req, NLM_F_CREATE | NLM_F_ECHO);
70e0aa0c61SJakub Kicinski 	rt_link_newlink_req_set_linkinfo_kind(req, "netkit");
71e0aa0c61SJakub Kicinski 	rt_link_newlink_req_set_linkinfo_data_netkit_policy(req, NETKIT_DROP);
72e0aa0c61SJakub Kicinski 
73e0aa0c61SJakub Kicinski 	ret = rt_link_newlink(ys, req);
74e0aa0c61SJakub Kicinski 	rt_link_newlink_req_free(req);
75*5c320678SJakub Kicinski 	if (ret)
76e0aa0c61SJakub Kicinski 		return -1;
77e0aa0c61SJakub Kicinski 
78*5c320678SJakub Kicinski 	if (!ynl_has_ntf(ys))
79e0aa0c61SJakub Kicinski 		return 0;
80e0aa0c61SJakub Kicinski 
81e0aa0c61SJakub Kicinski 	ntf = ynl_ntf_dequeue(ys);
82*5c320678SJakub Kicinski 	if (!ntf || ntf->cmd != RTM_NEWLINK) {
83*5c320678SJakub Kicinski 		ynl_ntf_free(ntf);
84e0aa0c61SJakub Kicinski 		return 0;
85e0aa0c61SJakub Kicinski 	}
86e0aa0c61SJakub Kicinski 	ntf_gl = (void *)ntf;
87e0aa0c61SJakub Kicinski 	ret = ntf_gl->obj._hdr.ifi_index;
88e0aa0c61SJakub Kicinski 	ynl_ntf_free(ntf);
89e0aa0c61SJakub Kicinski 
90e0aa0c61SJakub Kicinski 	return ret;
91e0aa0c61SJakub Kicinski }
92e0aa0c61SJakub Kicinski 
93*5c320678SJakub Kicinski static void netkit_delete(struct __test_metadata *_metadata,
94*5c320678SJakub Kicinski 			  struct ynl_sock *ys, int ifindex)
95e0aa0c61SJakub Kicinski {
96e0aa0c61SJakub Kicinski 	struct rt_link_dellink_req *req;
97e0aa0c61SJakub Kicinski 
98e0aa0c61SJakub Kicinski 	req = rt_link_dellink_req_alloc();
99*5c320678SJakub Kicinski 	ASSERT_NE(NULL, req);
100e0aa0c61SJakub Kicinski 
101e0aa0c61SJakub Kicinski 	req->_hdr.ifi_index = ifindex;
102*5c320678SJakub Kicinski 	EXPECT_EQ(0, rt_link_dellink(ys, req));
103e0aa0c61SJakub Kicinski 	rt_link_dellink_req_free(req);
104e0aa0c61SJakub Kicinski }
105e0aa0c61SJakub Kicinski 
106*5c320678SJakub Kicinski FIXTURE(rt_link)
107*5c320678SJakub Kicinski {
108*5c320678SJakub Kicinski 	struct ynl_sock *ys;
109*5c320678SJakub Kicinski };
110*5c320678SJakub Kicinski 
111*5c320678SJakub Kicinski FIXTURE_SETUP(rt_link)
112*5c320678SJakub Kicinski {
113*5c320678SJakub Kicinski 	struct ynl_error yerr;
114*5c320678SJakub Kicinski 
115*5c320678SJakub Kicinski 	self->ys = ynl_sock_create(&ynl_rt_link_family, &yerr);
116*5c320678SJakub Kicinski 	ASSERT_NE(NULL, self->ys) {
117*5c320678SJakub Kicinski 		TH_LOG("failed to create rt-link socket: %s", yerr.msg);
118*5c320678SJakub Kicinski 	}
119*5c320678SJakub Kicinski }
120*5c320678SJakub Kicinski 
121*5c320678SJakub Kicinski FIXTURE_TEARDOWN(rt_link)
122*5c320678SJakub Kicinski {
123*5c320678SJakub Kicinski 	ynl_sock_destroy(self->ys);
124*5c320678SJakub Kicinski }
125*5c320678SJakub Kicinski 
126*5c320678SJakub Kicinski TEST_F(rt_link, dump)
127e0aa0c61SJakub Kicinski {
128e0aa0c61SJakub Kicinski 	struct rt_link_getlink_req_dump *req;
129e0aa0c61SJakub Kicinski 	struct rt_link_getlink_list *rsp;
130e0aa0c61SJakub Kicinski 
131e0aa0c61SJakub Kicinski 	req = rt_link_getlink_req_dump_alloc();
132*5c320678SJakub Kicinski 	ASSERT_NE(NULL, req);
133*5c320678SJakub Kicinski 	rsp = rt_link_getlink_dump(self->ys, req);
134e0aa0c61SJakub Kicinski 	rt_link_getlink_req_dump_free(req);
135*5c320678SJakub Kicinski 	ASSERT_NE(NULL, rsp) {
136*5c320678SJakub Kicinski 		TH_LOG("dump failed: %s", self->ys->err.msg);
137e0aa0c61SJakub Kicinski 	}
138*5c320678SJakub Kicinski 	ASSERT_FALSE(ynl_dump_empty(rsp));
139*5c320678SJakub Kicinski 
140*5c320678SJakub Kicinski 	ynl_dump_foreach(rsp, link)
141*5c320678SJakub Kicinski 		rt_link_print(_metadata, link);
142*5c320678SJakub Kicinski 
143*5c320678SJakub Kicinski 	rt_link_getlink_list_free(rsp);
144*5c320678SJakub Kicinski }
145*5c320678SJakub Kicinski 
146*5c320678SJakub Kicinski TEST_F(rt_link, netkit)
147*5c320678SJakub Kicinski {
148*5c320678SJakub Kicinski 	struct rt_link_getlink_req_dump *dreq;
149*5c320678SJakub Kicinski 	struct rt_link_getlink_list *rsp;
150*5c320678SJakub Kicinski 	bool found = false;
151*5c320678SJakub Kicinski 	int netkit_ifindex;
152*5c320678SJakub Kicinski 
153*5c320678SJakub Kicinski 	/* Create netkit with valid policy */
154*5c320678SJakub Kicinski 	netkit_ifindex = netkit_create(self->ys);
155*5c320678SJakub Kicinski 	ASSERT_GT(netkit_ifindex, 0)
156*5c320678SJakub Kicinski 		TH_LOG("failed to create netkit: %s", self->ys->err.msg);
157*5c320678SJakub Kicinski 
158*5c320678SJakub Kicinski 	/* Verify it appears in a dump */
159*5c320678SJakub Kicinski 	dreq = rt_link_getlink_req_dump_alloc();
160*5c320678SJakub Kicinski 	ASSERT_NE(NULL, dreq);
161*5c320678SJakub Kicinski 	rsp = rt_link_getlink_dump(self->ys, dreq);
162*5c320678SJakub Kicinski 	rt_link_getlink_req_dump_free(dreq);
163*5c320678SJakub Kicinski 	ASSERT_NE(NULL, rsp) {
164*5c320678SJakub Kicinski 		TH_LOG("dump failed: %s", self->ys->err.msg);
165*5c320678SJakub Kicinski 	}
166*5c320678SJakub Kicinski 
167*5c320678SJakub Kicinski 	ynl_dump_foreach(rsp, link) {
168*5c320678SJakub Kicinski 		if (link->_hdr.ifi_index == netkit_ifindex) {
169*5c320678SJakub Kicinski 			rt_link_print(_metadata, link);
170*5c320678SJakub Kicinski 			found = true;
171*5c320678SJakub Kicinski 		}
172*5c320678SJakub Kicinski 	}
173*5c320678SJakub Kicinski 	rt_link_getlink_list_free(rsp);
174*5c320678SJakub Kicinski 	EXPECT_TRUE(found);
175*5c320678SJakub Kicinski 
176*5c320678SJakub Kicinski 	netkit_delete(_metadata, self->ys, netkit_ifindex);
177*5c320678SJakub Kicinski }
178*5c320678SJakub Kicinski 
179*5c320678SJakub Kicinski TEST_F(rt_link, netkit_err_msg)
180*5c320678SJakub Kicinski {
181*5c320678SJakub Kicinski 	struct rt_link_newlink_req *req;
182*5c320678SJakub Kicinski 	int ret;
183*5c320678SJakub Kicinski 
184*5c320678SJakub Kicinski 	/* Test creating netkit with bad policy - should fail */
185*5c320678SJakub Kicinski 	req = rt_link_newlink_req_alloc();
186*5c320678SJakub Kicinski 	ASSERT_NE(NULL, req);
187*5c320678SJakub Kicinski 	rt_link_newlink_req_set_nlflags(req, NLM_F_CREATE);
188*5c320678SJakub Kicinski 	rt_link_newlink_req_set_linkinfo_kind(req, "netkit");
189*5c320678SJakub Kicinski 	rt_link_newlink_req_set_linkinfo_data_netkit_policy(req, 10);
190*5c320678SJakub Kicinski 
191*5c320678SJakub Kicinski 	ret = rt_link_newlink(self->ys, req);
192*5c320678SJakub Kicinski 	rt_link_newlink_req_free(req);
193*5c320678SJakub Kicinski 	EXPECT_NE(0, ret) {
194*5c320678SJakub Kicinski 		TH_LOG("creating netkit with bad policy should fail");
195*5c320678SJakub Kicinski 	}
196*5c320678SJakub Kicinski 
197*5c320678SJakub Kicinski 	/* Expect:
198*5c320678SJakub Kicinski 	 * Kernel error: 'Provided default xmit policy not supported' (bad attribute: .linkinfo.data(netkit).policy)
199*5c320678SJakub Kicinski 	 */
200*5c320678SJakub Kicinski 	EXPECT_NE(NULL, strstr(self->ys->err.msg, "bad attribute: .linkinfo.data(netkit).policy")) {
201*5c320678SJakub Kicinski 		TH_LOG("expected extack msg not found: %s",
202*5c320678SJakub Kicinski 		       self->ys->err.msg);
203*5c320678SJakub Kicinski 	}
204*5c320678SJakub Kicinski }
205*5c320678SJakub Kicinski 
206*5c320678SJakub Kicinski TEST_HARNESS_MAIN
207