xref: /linux/tools/testing/selftests/bpf/prog_tests/test_bpf_smc.c (revision 24f171c7e145f43b9f187578e89b0982ce87e54c)
1*beb3c672SD. Wythe // SPDX-License-Identifier: GPL-2.0
2*beb3c672SD. Wythe #include <test_progs.h>
3*beb3c672SD. Wythe #include <linux/genetlink.h>
4*beb3c672SD. Wythe #include "network_helpers.h"
5*beb3c672SD. Wythe #include "bpf_smc.skel.h"
6*beb3c672SD. Wythe 
7*beb3c672SD. Wythe #ifndef IPPROTO_SMC
8*beb3c672SD. Wythe #define IPPROTO_SMC 256
9*beb3c672SD. Wythe #endif
10*beb3c672SD. Wythe 
11*beb3c672SD. Wythe #define CLIENT_IP			"127.0.0.1"
12*beb3c672SD. Wythe #define SERVER_IP			"127.0.1.0"
13*beb3c672SD. Wythe #define SERVER_IP_VIA_RISK_PATH	"127.0.2.0"
14*beb3c672SD. Wythe 
15*beb3c672SD. Wythe #define SERVICE_1	80
16*beb3c672SD. Wythe #define SERVICE_2	443
17*beb3c672SD. Wythe #define SERVICE_3	8443
18*beb3c672SD. Wythe 
19*beb3c672SD. Wythe #define TEST_NS	"bpf_smc_netns"
20*beb3c672SD. Wythe 
21*beb3c672SD. Wythe static struct netns_obj *test_netns;
22*beb3c672SD. Wythe 
23*beb3c672SD. Wythe struct smc_policy_ip_key {
24*beb3c672SD. Wythe 	__u32  sip;
25*beb3c672SD. Wythe 	__u32  dip;
26*beb3c672SD. Wythe };
27*beb3c672SD. Wythe 
28*beb3c672SD. Wythe struct smc_policy_ip_value {
29*beb3c672SD. Wythe 	__u8	mode;
30*beb3c672SD. Wythe };
31*beb3c672SD. Wythe 
32*beb3c672SD. Wythe #if defined(__s390x__)
33*beb3c672SD. Wythe /* s390x has default seid  */
34*beb3c672SD. Wythe static bool setup_ueid(void) { return true; }
35*beb3c672SD. Wythe static void cleanup_ueid(void) {}
36*beb3c672SD. Wythe #else
37*beb3c672SD. Wythe enum {
38*beb3c672SD. Wythe 	SMC_NETLINK_ADD_UEID = 10,
39*beb3c672SD. Wythe 	SMC_NETLINK_REMOVE_UEID
40*beb3c672SD. Wythe };
41*beb3c672SD. Wythe 
42*beb3c672SD. Wythe enum {
43*beb3c672SD. Wythe 	SMC_NLA_EID_TABLE_UNSPEC,
44*beb3c672SD. Wythe 	SMC_NLA_EID_TABLE_ENTRY,    /* string */
45*beb3c672SD. Wythe };
46*beb3c672SD. Wythe 
47*beb3c672SD. Wythe struct msgtemplate {
48*beb3c672SD. Wythe 	struct nlmsghdr n;
49*beb3c672SD. Wythe 	struct genlmsghdr g;
50*beb3c672SD. Wythe 	char buf[1024];
51*beb3c672SD. Wythe };
52*beb3c672SD. Wythe 
53*beb3c672SD. Wythe #define GENLMSG_DATA(glh)	((void *)(NLMSG_DATA(glh) + GENL_HDRLEN))
54*beb3c672SD. Wythe #define GENLMSG_PAYLOAD(glh)	(NLMSG_PAYLOAD(glh, 0) - GENL_HDRLEN)
55*beb3c672SD. Wythe #define NLA_DATA(na)		((void *)((char *)(na) + NLA_HDRLEN))
56*beb3c672SD. Wythe #define NLA_PAYLOAD(len)	((len) - NLA_HDRLEN)
57*beb3c672SD. Wythe 
58*beb3c672SD. Wythe #define SMC_GENL_FAMILY_NAME	"SMC_GEN_NETLINK"
59*beb3c672SD. Wythe #define SMC_BPFTEST_UEID	"SMC-BPFTEST-UEID"
60*beb3c672SD. Wythe 
61*beb3c672SD. Wythe static uint16_t smc_nl_family_id = -1;
62*beb3c672SD. Wythe 
63*beb3c672SD. Wythe static int send_cmd(int fd, __u16 nlmsg_type, __u32 nlmsg_pid,
64*beb3c672SD. Wythe 		    __u16 nlmsg_flags, __u8 genl_cmd, __u16 nla_type,
65*beb3c672SD. Wythe 		    void *nla_data, int nla_len)
66*beb3c672SD. Wythe {
67*beb3c672SD. Wythe 	struct nlattr *na;
68*beb3c672SD. Wythe 	struct sockaddr_nl nladdr;
69*beb3c672SD. Wythe 	int r, buflen;
70*beb3c672SD. Wythe 	char *buf;
71*beb3c672SD. Wythe 
72*beb3c672SD. Wythe 	struct msgtemplate msg = {0};
73*beb3c672SD. Wythe 
74*beb3c672SD. Wythe 	msg.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
75*beb3c672SD. Wythe 	msg.n.nlmsg_type = nlmsg_type;
76*beb3c672SD. Wythe 	msg.n.nlmsg_flags = nlmsg_flags;
77*beb3c672SD. Wythe 	msg.n.nlmsg_seq = 0;
78*beb3c672SD. Wythe 	msg.n.nlmsg_pid = nlmsg_pid;
79*beb3c672SD. Wythe 	msg.g.cmd = genl_cmd;
80*beb3c672SD. Wythe 	msg.g.version = 1;
81*beb3c672SD. Wythe 	na = (struct nlattr *)GENLMSG_DATA(&msg);
82*beb3c672SD. Wythe 	na->nla_type = nla_type;
83*beb3c672SD. Wythe 	na->nla_len = nla_len + 1 + NLA_HDRLEN;
84*beb3c672SD. Wythe 	memcpy(NLA_DATA(na), nla_data, nla_len);
85*beb3c672SD. Wythe 	msg.n.nlmsg_len += NLMSG_ALIGN(na->nla_len);
86*beb3c672SD. Wythe 
87*beb3c672SD. Wythe 	buf = (char *)&msg;
88*beb3c672SD. Wythe 	buflen = msg.n.nlmsg_len;
89*beb3c672SD. Wythe 	memset(&nladdr, 0, sizeof(nladdr));
90*beb3c672SD. Wythe 	nladdr.nl_family = AF_NETLINK;
91*beb3c672SD. Wythe 
92*beb3c672SD. Wythe 	while ((r = sendto(fd, buf, buflen, 0, (struct sockaddr *)&nladdr,
93*beb3c672SD. Wythe 			   sizeof(nladdr))) < buflen) {
94*beb3c672SD. Wythe 		if (r > 0) {
95*beb3c672SD. Wythe 			buf += r;
96*beb3c672SD. Wythe 			buflen -= r;
97*beb3c672SD. Wythe 		} else if (errno != EAGAIN) {
98*beb3c672SD. Wythe 			return -1;
99*beb3c672SD. Wythe 		}
100*beb3c672SD. Wythe 	}
101*beb3c672SD. Wythe 	return 0;
102*beb3c672SD. Wythe }
103*beb3c672SD. Wythe 
104*beb3c672SD. Wythe static bool get_smc_nl_family_id(void)
105*beb3c672SD. Wythe {
106*beb3c672SD. Wythe 	struct sockaddr_nl nl_src;
107*beb3c672SD. Wythe 	struct msgtemplate msg;
108*beb3c672SD. Wythe 	struct nlattr *nl;
109*beb3c672SD. Wythe 	int fd, ret;
110*beb3c672SD. Wythe 	pid_t pid;
111*beb3c672SD. Wythe 
112*beb3c672SD. Wythe 	fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
113*beb3c672SD. Wythe 	if (!ASSERT_OK_FD(fd, "nl_family socket"))
114*beb3c672SD. Wythe 		return false;
115*beb3c672SD. Wythe 
116*beb3c672SD. Wythe 	pid = getpid();
117*beb3c672SD. Wythe 
118*beb3c672SD. Wythe 	memset(&nl_src, 0, sizeof(nl_src));
119*beb3c672SD. Wythe 	nl_src.nl_family = AF_NETLINK;
120*beb3c672SD. Wythe 	nl_src.nl_pid = pid;
121*beb3c672SD. Wythe 
122*beb3c672SD. Wythe 	ret = bind(fd, (struct sockaddr *)&nl_src, sizeof(nl_src));
123*beb3c672SD. Wythe 	if (!ASSERT_OK(ret, "nl_family bind"))
124*beb3c672SD. Wythe 		goto fail;
125*beb3c672SD. Wythe 
126*beb3c672SD. Wythe 	ret = send_cmd(fd, GENL_ID_CTRL, pid,
127*beb3c672SD. Wythe 		       NLM_F_REQUEST, CTRL_CMD_GETFAMILY,
128*beb3c672SD. Wythe 		       CTRL_ATTR_FAMILY_NAME, (void *)SMC_GENL_FAMILY_NAME,
129*beb3c672SD. Wythe 		       strlen(SMC_GENL_FAMILY_NAME));
130*beb3c672SD. Wythe 	if (!ASSERT_OK(ret, "nl_family query"))
131*beb3c672SD. Wythe 		goto fail;
132*beb3c672SD. Wythe 
133*beb3c672SD. Wythe 	ret = recv(fd, &msg, sizeof(msg), 0);
134*beb3c672SD. Wythe 	if (!ASSERT_FALSE(msg.n.nlmsg_type == NLMSG_ERROR || ret < 0 ||
135*beb3c672SD. Wythe 			  !NLMSG_OK(&msg.n, ret), "nl_family response"))
136*beb3c672SD. Wythe 		goto fail;
137*beb3c672SD. Wythe 
138*beb3c672SD. Wythe 	nl = (struct nlattr *)GENLMSG_DATA(&msg);
139*beb3c672SD. Wythe 	nl = (struct nlattr *)((char *)nl + NLA_ALIGN(nl->nla_len));
140*beb3c672SD. Wythe 	if (!ASSERT_EQ(nl->nla_type, CTRL_ATTR_FAMILY_ID, "nl_family nla type"))
141*beb3c672SD. Wythe 		goto fail;
142*beb3c672SD. Wythe 
143*beb3c672SD. Wythe 	smc_nl_family_id = *(uint16_t *)NLA_DATA(nl);
144*beb3c672SD. Wythe 	close(fd);
145*beb3c672SD. Wythe 	return true;
146*beb3c672SD. Wythe fail:
147*beb3c672SD. Wythe 	close(fd);
148*beb3c672SD. Wythe 	return false;
149*beb3c672SD. Wythe }
150*beb3c672SD. Wythe 
151*beb3c672SD. Wythe static bool smc_ueid(int op)
152*beb3c672SD. Wythe {
153*beb3c672SD. Wythe 	struct sockaddr_nl nl_src;
154*beb3c672SD. Wythe 	struct msgtemplate msg;
155*beb3c672SD. Wythe 	struct nlmsgerr *err;
156*beb3c672SD. Wythe 	char test_ueid[32];
157*beb3c672SD. Wythe 	int fd, ret;
158*beb3c672SD. Wythe 	pid_t pid;
159*beb3c672SD. Wythe 
160*beb3c672SD. Wythe 	/* UEID required */
161*beb3c672SD. Wythe 	memset(test_ueid, '\x20', sizeof(test_ueid));
162*beb3c672SD. Wythe 	memcpy(test_ueid, SMC_BPFTEST_UEID, strlen(SMC_BPFTEST_UEID));
163*beb3c672SD. Wythe 	fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
164*beb3c672SD. Wythe 	if (!ASSERT_OK_FD(fd, "ueid socket"))
165*beb3c672SD. Wythe 		return false;
166*beb3c672SD. Wythe 
167*beb3c672SD. Wythe 	pid = getpid();
168*beb3c672SD. Wythe 	memset(&nl_src, 0, sizeof(nl_src));
169*beb3c672SD. Wythe 	nl_src.nl_family = AF_NETLINK;
170*beb3c672SD. Wythe 	nl_src.nl_pid = pid;
171*beb3c672SD. Wythe 
172*beb3c672SD. Wythe 	ret = bind(fd, (struct sockaddr *)&nl_src, sizeof(nl_src));
173*beb3c672SD. Wythe 	if (!ASSERT_OK(ret, "ueid bind"))
174*beb3c672SD. Wythe 		goto fail;
175*beb3c672SD. Wythe 
176*beb3c672SD. Wythe 	ret = send_cmd(fd, smc_nl_family_id, pid,
177*beb3c672SD. Wythe 		       NLM_F_REQUEST | NLM_F_ACK, op, SMC_NLA_EID_TABLE_ENTRY,
178*beb3c672SD. Wythe 		       (void *)test_ueid, sizeof(test_ueid));
179*beb3c672SD. Wythe 	if (!ASSERT_OK(ret, "ueid cmd"))
180*beb3c672SD. Wythe 		goto fail;
181*beb3c672SD. Wythe 
182*beb3c672SD. Wythe 	ret = recv(fd, &msg, sizeof(msg), 0);
183*beb3c672SD. Wythe 	if (!ASSERT_FALSE(ret < 0 ||
184*beb3c672SD. Wythe 			  !NLMSG_OK(&msg.n, ret), "ueid response"))
185*beb3c672SD. Wythe 		goto fail;
186*beb3c672SD. Wythe 
187*beb3c672SD. Wythe 	if (msg.n.nlmsg_type == NLMSG_ERROR) {
188*beb3c672SD. Wythe 		err = NLMSG_DATA(&msg);
189*beb3c672SD. Wythe 		switch (op) {
190*beb3c672SD. Wythe 		case SMC_NETLINK_REMOVE_UEID:
191*beb3c672SD. Wythe 			if (!ASSERT_FALSE((err->error && err->error != -ENOENT),
192*beb3c672SD. Wythe 					  "ueid remove"))
193*beb3c672SD. Wythe 				goto fail;
194*beb3c672SD. Wythe 			break;
195*beb3c672SD. Wythe 		case SMC_NETLINK_ADD_UEID:
196*beb3c672SD. Wythe 			if (!ASSERT_OK(err->error, "ueid add"))
197*beb3c672SD. Wythe 				goto fail;
198*beb3c672SD. Wythe 			break;
199*beb3c672SD. Wythe 		default:
200*beb3c672SD. Wythe 			break;
201*beb3c672SD. Wythe 		}
202*beb3c672SD. Wythe 	}
203*beb3c672SD. Wythe 	close(fd);
204*beb3c672SD. Wythe 	return true;
205*beb3c672SD. Wythe fail:
206*beb3c672SD. Wythe 	close(fd);
207*beb3c672SD. Wythe 	return false;
208*beb3c672SD. Wythe }
209*beb3c672SD. Wythe 
210*beb3c672SD. Wythe static bool setup_ueid(void)
211*beb3c672SD. Wythe {
212*beb3c672SD. Wythe 	/* get smc nl id */
213*beb3c672SD. Wythe 	if (!get_smc_nl_family_id())
214*beb3c672SD. Wythe 		return false;
215*beb3c672SD. Wythe 	/* clear old ueid for bpftest */
216*beb3c672SD. Wythe 	smc_ueid(SMC_NETLINK_REMOVE_UEID);
217*beb3c672SD. Wythe 	/* smc-loopback required ueid */
218*beb3c672SD. Wythe 	return smc_ueid(SMC_NETLINK_ADD_UEID);
219*beb3c672SD. Wythe }
220*beb3c672SD. Wythe 
221*beb3c672SD. Wythe static void cleanup_ueid(void)
222*beb3c672SD. Wythe {
223*beb3c672SD. Wythe 	smc_ueid(SMC_NETLINK_REMOVE_UEID);
224*beb3c672SD. Wythe }
225*beb3c672SD. Wythe #endif /* __s390x__ */
226*beb3c672SD. Wythe 
227*beb3c672SD. Wythe static bool setup_netns(void)
228*beb3c672SD. Wythe {
229*beb3c672SD. Wythe 	test_netns = netns_new(TEST_NS, true);
230*beb3c672SD. Wythe 	if (!ASSERT_OK_PTR(test_netns, "open net namespace"))
231*beb3c672SD. Wythe 		goto fail_netns;
232*beb3c672SD. Wythe 
233*beb3c672SD. Wythe 	SYS(fail_ip, "ip addr add 127.0.1.0/8 dev lo");
234*beb3c672SD. Wythe 	SYS(fail_ip, "ip addr add 127.0.2.0/8 dev lo");
235*beb3c672SD. Wythe 
236*beb3c672SD. Wythe 	return true;
237*beb3c672SD. Wythe fail_ip:
238*beb3c672SD. Wythe 	netns_free(test_netns);
239*beb3c672SD. Wythe fail_netns:
240*beb3c672SD. Wythe 	return false;
241*beb3c672SD. Wythe }
242*beb3c672SD. Wythe 
243*beb3c672SD. Wythe static void cleanup_netns(void)
244*beb3c672SD. Wythe {
245*beb3c672SD. Wythe 	netns_free(test_netns);
246*beb3c672SD. Wythe }
247*beb3c672SD. Wythe 
248*beb3c672SD. Wythe static bool setup_smc(void)
249*beb3c672SD. Wythe {
250*beb3c672SD. Wythe 	if (!setup_ueid())
251*beb3c672SD. Wythe 		return false;
252*beb3c672SD. Wythe 
253*beb3c672SD. Wythe 	if (!setup_netns())
254*beb3c672SD. Wythe 		goto fail_netns;
255*beb3c672SD. Wythe 
256*beb3c672SD. Wythe 	return true;
257*beb3c672SD. Wythe fail_netns:
258*beb3c672SD. Wythe 	cleanup_ueid();
259*beb3c672SD. Wythe 	return false;
260*beb3c672SD. Wythe }
261*beb3c672SD. Wythe 
262*beb3c672SD. Wythe static int set_client_addr_cb(int fd, void *opts)
263*beb3c672SD. Wythe {
264*beb3c672SD. Wythe 	const char *src = (const char *)opts;
265*beb3c672SD. Wythe 	struct sockaddr_in localaddr;
266*beb3c672SD. Wythe 
267*beb3c672SD. Wythe 	localaddr.sin_family = AF_INET;
268*beb3c672SD. Wythe 	localaddr.sin_port = htons(0);
269*beb3c672SD. Wythe 	localaddr.sin_addr.s_addr = inet_addr(src);
270*beb3c672SD. Wythe 	return !ASSERT_OK(bind(fd, &localaddr, sizeof(localaddr)), "client bind");
271*beb3c672SD. Wythe }
272*beb3c672SD. Wythe 
273*beb3c672SD. Wythe static void run_link(const char *src, const char *dst, int port)
274*beb3c672SD. Wythe {
275*beb3c672SD. Wythe 	struct network_helper_opts opts = {0};
276*beb3c672SD. Wythe 	int server, client;
277*beb3c672SD. Wythe 
278*beb3c672SD. Wythe 	server = start_server_str(AF_INET, SOCK_STREAM, dst, port, NULL);
279*beb3c672SD. Wythe 	if (!ASSERT_OK_FD(server, "start service_1"))
280*beb3c672SD. Wythe 		return;
281*beb3c672SD. Wythe 
282*beb3c672SD. Wythe 	opts.proto = IPPROTO_TCP;
283*beb3c672SD. Wythe 	opts.post_socket_cb = set_client_addr_cb;
284*beb3c672SD. Wythe 	opts.cb_opts = (void *)src;
285*beb3c672SD. Wythe 
286*beb3c672SD. Wythe 	client = connect_to_fd_opts(server, &opts);
287*beb3c672SD. Wythe 	if (!ASSERT_OK_FD(client, "start connect"))
288*beb3c672SD. Wythe 		goto fail_client;
289*beb3c672SD. Wythe 
290*beb3c672SD. Wythe 	close(client);
291*beb3c672SD. Wythe fail_client:
292*beb3c672SD. Wythe 	close(server);
293*beb3c672SD. Wythe }
294*beb3c672SD. Wythe 
295*beb3c672SD. Wythe static void block_link(int map_fd, const char *src, const char *dst)
296*beb3c672SD. Wythe {
297*beb3c672SD. Wythe 	struct smc_policy_ip_value val = { .mode = /* block */ 0 };
298*beb3c672SD. Wythe 	struct smc_policy_ip_key key = {
299*beb3c672SD. Wythe 		.sip = inet_addr(src),
300*beb3c672SD. Wythe 		.dip = inet_addr(dst),
301*beb3c672SD. Wythe 	};
302*beb3c672SD. Wythe 
303*beb3c672SD. Wythe 	bpf_map_update_elem(map_fd, &key, &val, BPF_ANY);
304*beb3c672SD. Wythe }
305*beb3c672SD. Wythe 
306*beb3c672SD. Wythe /*
307*beb3c672SD. Wythe  * This test describes a real-life service topology as follows:
308*beb3c672SD. Wythe  *
309*beb3c672SD. Wythe  *                             +-------------> service_1
310*beb3c672SD. Wythe  *            link 1           |                     |
311*beb3c672SD. Wythe  *   +--------------------> server                   |  link 2
312*beb3c672SD. Wythe  *   |                         |                     V
313*beb3c672SD. Wythe  *   |                         +-------------> service_2
314*beb3c672SD. Wythe  *   |        link 3
315*beb3c672SD. Wythe  *  client -------------------> server_via_unsafe_path -> service_3
316*beb3c672SD. Wythe  *
317*beb3c672SD. Wythe  * Among them,
318*beb3c672SD. Wythe  * 1. link-1 is very suitable for using SMC.
319*beb3c672SD. Wythe  * 2. link-2 is not suitable for using SMC, because the mode of this link is
320*beb3c672SD. Wythe  *    kind of short-link services.
321*beb3c672SD. Wythe  * 3. link-3 is also not suitable for using SMC, because the RDMA link is
322*beb3c672SD. Wythe  *    unavailable and needs to go through a long timeout before it can fallback
323*beb3c672SD. Wythe  *    to TCP.
324*beb3c672SD. Wythe  * To achieve this goal, we use a customized SMC ip strategy via smc_hs_ctrl.
325*beb3c672SD. Wythe  */
326*beb3c672SD. Wythe static void test_topo(void)
327*beb3c672SD. Wythe {
328*beb3c672SD. Wythe 	struct bpf_smc *skel;
329*beb3c672SD. Wythe 	int rc, map_fd;
330*beb3c672SD. Wythe 
331*beb3c672SD. Wythe 	skel = bpf_smc__open_and_load();
332*beb3c672SD. Wythe 	if (!ASSERT_OK_PTR(skel, "bpf_smc__open_and_load"))
333*beb3c672SD. Wythe 		return;
334*beb3c672SD. Wythe 
335*beb3c672SD. Wythe 	rc = bpf_smc__attach(skel);
336*beb3c672SD. Wythe 	if (!ASSERT_OK(rc, "bpf_smc__attach"))
337*beb3c672SD. Wythe 		goto fail;
338*beb3c672SD. Wythe 
339*beb3c672SD. Wythe 	map_fd = bpf_map__fd(skel->maps.smc_policy_ip);
340*beb3c672SD. Wythe 	if (!ASSERT_OK_FD(map_fd, "bpf_map__fd"))
341*beb3c672SD. Wythe 		goto fail;
342*beb3c672SD. Wythe 
343*beb3c672SD. Wythe 	/* Mock the process of transparent replacement, since we will modify
344*beb3c672SD. Wythe 	 * protocol to ipproto_smc accropding to it via
345*beb3c672SD. Wythe 	 * fmod_ret/update_socket_protocol.
346*beb3c672SD. Wythe 	 */
347*beb3c672SD. Wythe 	write_sysctl("/proc/sys/net/smc/hs_ctrl", "linkcheck");
348*beb3c672SD. Wythe 
349*beb3c672SD. Wythe 	/* Configure ip strat */
350*beb3c672SD. Wythe 	block_link(map_fd, CLIENT_IP, SERVER_IP_VIA_RISK_PATH);
351*beb3c672SD. Wythe 	block_link(map_fd, SERVER_IP, SERVER_IP);
352*beb3c672SD. Wythe 
353*beb3c672SD. Wythe 	/* should go with smc */
354*beb3c672SD. Wythe 	run_link(CLIENT_IP, SERVER_IP, SERVICE_1);
355*beb3c672SD. Wythe 	/* should go with smc fallback */
356*beb3c672SD. Wythe 	run_link(SERVER_IP, SERVER_IP, SERVICE_2);
357*beb3c672SD. Wythe 
358*beb3c672SD. Wythe 	ASSERT_EQ(skel->bss->smc_cnt, 2, "smc count");
359*beb3c672SD. Wythe 	ASSERT_EQ(skel->bss->fallback_cnt, 1, "fallback count");
360*beb3c672SD. Wythe 
361*beb3c672SD. Wythe 	/* should go with smc */
362*beb3c672SD. Wythe 	run_link(CLIENT_IP, SERVER_IP, SERVICE_2);
363*beb3c672SD. Wythe 
364*beb3c672SD. Wythe 	ASSERT_EQ(skel->bss->smc_cnt, 3, "smc count");
365*beb3c672SD. Wythe 	ASSERT_EQ(skel->bss->fallback_cnt, 1, "fallback count");
366*beb3c672SD. Wythe 
367*beb3c672SD. Wythe 	/* should go with smc fallback */
368*beb3c672SD. Wythe 	run_link(CLIENT_IP, SERVER_IP_VIA_RISK_PATH, SERVICE_3);
369*beb3c672SD. Wythe 
370*beb3c672SD. Wythe 	ASSERT_EQ(skel->bss->smc_cnt, 4, "smc count");
371*beb3c672SD. Wythe 	ASSERT_EQ(skel->bss->fallback_cnt, 2, "fallback count");
372*beb3c672SD. Wythe 
373*beb3c672SD. Wythe fail:
374*beb3c672SD. Wythe 	bpf_smc__destroy(skel);
375*beb3c672SD. Wythe }
376*beb3c672SD. Wythe 
377*beb3c672SD. Wythe void test_bpf_smc(void)
378*beb3c672SD. Wythe {
379*beb3c672SD. Wythe 	if (!setup_smc()) {
380*beb3c672SD. Wythe 		printf("setup for smc test failed, test SKIP:\n");
381*beb3c672SD. Wythe 		test__skip();
382*beb3c672SD. Wythe 		return;
383*beb3c672SD. Wythe 	}
384*beb3c672SD. Wythe 
385*beb3c672SD. Wythe 	if (test__start_subtest("topo"))
386*beb3c672SD. Wythe 		test_topo();
387*beb3c672SD. Wythe 
388*beb3c672SD. Wythe 	cleanup_ueid();
389*beb3c672SD. Wythe 	cleanup_netns();
390*beb3c672SD. Wythe }
391