xref: /linux/tools/testing/selftests/bpf/prog_tests/test_tc_tunnel.c (revision 9e4e86a604dfd06402933467578c4b79f5412b2c)
1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 
3 /*
4  * End-to-end eBPF tunnel test suite
5  *   The file tests BPF network tunnels implementation. For each tunnel
6  *   type, the test validates that:
7  *   - basic communication can first be established between the two veths
8  *   - when adding a BPF-based encapsulation on client egress, it now fails
9  *   to communicate with the server
10  *   - when adding a kernel-based decapsulation on server ingress, client
11  *   can now connect
12  *   - when replacing the kernel-based decapsulation with a BPF-based one,
13  *   the client can still connect
14  */
15 
16 #include <stdio.h>
17 #include <unistd.h>
18 #include <fcntl.h>
19 #include <sys/socket.h>
20 #include <bpf/libbpf.h>
21 
22 #include "test_progs.h"
23 #include "network_helpers.h"
24 #include "test_tc_tunnel.skel.h"
25 
26 #define SERVER_NS	"tc-tunnel-server-ns"
27 #define CLIENT_NS	"tc-tunnel-client-ns"
28 #define MAC_ADDR_VETH1	"00:11:22:33:44:55"
29 #define IP4_ADDR_VETH1	"192.168.1.1"
30 #define IP6_ADDR_VETH1	"fd::1"
31 #define MAC_ADDR_VETH2	"66:77:88:99:AA:BB"
32 #define IP4_ADDR_VETH2	"192.168.1.2"
33 #define IP6_ADDR_VETH2	"fd::2"
34 
35 #define TEST_NAME_MAX_LEN	64
36 #define PROG_NAME_MAX_LEN	64
37 #define TUNNEL_ARGS_MAX_LEN	128
38 #define BUFFER_LEN		2000
39 #define DEFAULT_TEST_DATA_SIZE	100
40 #define GSO_TEST_DATA_SIZE	BUFFER_LEN
41 
42 #define TIMEOUT_MS			1000
43 #define TEST_PORT			8000
44 #define UDP_PORT			5555
45 #define MPLS_UDP_PORT			6635
46 #define FOU_MPLS_PROTO			137
47 #define VXLAN_ID			1
48 #define VXLAN_PORT			8472
49 #define MPLS_TABLE_ENTRIES_COUNT	65536
50 
51 static char tx_buffer[BUFFER_LEN], rx_buffer[BUFFER_LEN];
52 
53 struct subtest_cfg {
54 	char *ebpf_tun_type;
55 	char *iproute_tun_type;
56 	char *mac_tun_type;
57 	int ipproto;
58 	void (*extra_decap_mod_args_cb)(struct subtest_cfg *cfg, char *dst);
59 	bool tunnel_need_veth_mac;
60 	bool configure_fou_rx_port;
61 	char *tmode;
62 	bool expect_kern_decap_failure;
63 	bool configure_mpls;
64 	bool test_gso;
65 	char *tunnel_client_addr;
66 	char *tunnel_server_addr;
67 	char name[TEST_NAME_MAX_LEN];
68 	char *server_addr;
69 	int client_egress_prog_fd;
70 	int server_ingress_prog_fd;
71 	char extra_decap_mod_args[TUNNEL_ARGS_MAX_LEN];
72 	int server_fd;
73 };
74 
75 struct connection {
76 	int client_fd;
77 	int server_fd;
78 };
79 
build_subtest_name(struct subtest_cfg * cfg,char * dst,size_t size)80 static int build_subtest_name(struct subtest_cfg *cfg, char *dst, size_t size)
81 {
82 	int ret;
83 
84 	ret = snprintf(dst, size, "%s_%s", cfg->ebpf_tun_type,
85 		       cfg->mac_tun_type);
86 
87 	return ret < 0 ? ret : 0;
88 }
89 
set_subtest_progs(struct subtest_cfg * cfg,struct test_tc_tunnel * skel)90 static int set_subtest_progs(struct subtest_cfg *cfg, struct test_tc_tunnel *skel)
91 {
92 	char prog_name[PROG_NAME_MAX_LEN];
93 	struct bpf_program *prog;
94 	int ret;
95 
96 	ret = snprintf(prog_name, PROG_NAME_MAX_LEN, "__encap_");
97 	if (ret < 0)
98 		return ret;
99 	ret = build_subtest_name(cfg, prog_name + ret, PROG_NAME_MAX_LEN - ret);
100 	if (ret < 0)
101 		return ret;
102 	prog = bpf_object__find_program_by_name(skel->obj, prog_name);
103 	if (!prog)
104 		return -1;
105 
106 	cfg->client_egress_prog_fd = bpf_program__fd(prog);
107 	cfg->server_ingress_prog_fd = bpf_program__fd(skel->progs.decap_f);
108 	return 0;
109 }
110 
set_subtest_addresses(struct subtest_cfg * cfg)111 static void set_subtest_addresses(struct subtest_cfg *cfg)
112 {
113 	if (cfg->ipproto == 6)
114 		cfg->server_addr = IP6_ADDR_VETH2;
115 	else
116 		cfg->server_addr = IP4_ADDR_VETH2;
117 
118 	/* Some specific tunnel types need specific addressing, it then
119 	 * has been already set in the configuration table. Otherwise,
120 	 * deduce the relevant addressing from the ipproto
121 	 */
122 	if (cfg->tunnel_client_addr && cfg->tunnel_server_addr)
123 		return;
124 
125 	if (cfg->ipproto == 6) {
126 		cfg->tunnel_client_addr = IP6_ADDR_VETH1;
127 		cfg->tunnel_server_addr = IP6_ADDR_VETH2;
128 	} else {
129 		cfg->tunnel_client_addr = IP4_ADDR_VETH1;
130 		cfg->tunnel_server_addr = IP4_ADDR_VETH2;
131 	}
132 }
133 
run_server(struct subtest_cfg * cfg)134 static int run_server(struct subtest_cfg *cfg)
135 {
136 	int family = cfg->ipproto == 6 ? AF_INET6 : AF_INET;
137 	struct nstoken *nstoken;
138 	struct network_helper_opts opts = {
139 		.timeout_ms = TIMEOUT_MS
140 	};
141 
142 	nstoken = open_netns(SERVER_NS);
143 	if (!ASSERT_OK_PTR(nstoken, "open server ns"))
144 		return -1;
145 
146 	cfg->server_fd = start_server_str(family, SOCK_STREAM, cfg->server_addr,
147 					  TEST_PORT, &opts);
148 	close_netns(nstoken);
149 	if (!ASSERT_OK_FD(cfg->server_fd, "start server"))
150 		return -1;
151 
152 	return 0;
153 }
154 
check_server_rx_data(struct subtest_cfg * cfg,struct connection * conn,int len)155 static int check_server_rx_data(struct subtest_cfg *cfg,
156 				struct connection *conn, int len)
157 {
158 	int err;
159 
160 	memset(rx_buffer, 0, BUFFER_LEN);
161 	err = recv(conn->server_fd, rx_buffer, len, 0);
162 	if (!ASSERT_EQ(err, len, "check rx data len"))
163 		return 1;
164 	if (!ASSERT_MEMEQ(tx_buffer, rx_buffer, len, "check received data"))
165 		return 1;
166 	return 0;
167 }
168 
connect_client_to_server(struct subtest_cfg * cfg)169 static struct connection *connect_client_to_server(struct subtest_cfg *cfg)
170 {
171 	struct network_helper_opts opts = {.timeout_ms = 1000};
172 	int family = cfg->ipproto == 6 ? AF_INET6 : AF_INET;
173 	struct connection *conn = NULL;
174 	int client_fd, server_fd;
175 
176 	conn = malloc(sizeof(struct connection));
177 	if (!conn)
178 		return conn;
179 
180 	client_fd = connect_to_addr_str(family, SOCK_STREAM, cfg->server_addr,
181 					TEST_PORT, &opts);
182 
183 	if (client_fd < 0) {
184 		free(conn);
185 		return NULL;
186 	}
187 
188 	server_fd = accept(cfg->server_fd, NULL, NULL);
189 	if (server_fd < 0) {
190 		close(client_fd);
191 		free(conn);
192 		return NULL;
193 	}
194 
195 	conn->server_fd = server_fd;
196 	conn->client_fd = client_fd;
197 
198 	return conn;
199 }
200 
disconnect_client_from_server(struct subtest_cfg * cfg,struct connection * conn)201 static void disconnect_client_from_server(struct subtest_cfg *cfg,
202 					  struct connection *conn)
203 {
204 	close(conn->server_fd);
205 	close(conn->client_fd);
206 	free(conn);
207 }
208 
send_and_test_data(struct subtest_cfg * cfg)209 static int send_and_test_data(struct subtest_cfg *cfg)
210 {
211 	struct connection *conn;
212 	int err, res = -1;
213 
214 	conn = connect_client_to_server(cfg);
215 	if (!ASSERT_OK_PTR(conn, "connect to server"))
216 		return -1;
217 
218 	err = send(conn->client_fd, tx_buffer, DEFAULT_TEST_DATA_SIZE, 0);
219 	if (!ASSERT_EQ(err, DEFAULT_TEST_DATA_SIZE, "send data from client"))
220 		goto end;
221 	if (check_server_rx_data(cfg, conn, DEFAULT_TEST_DATA_SIZE))
222 		goto end;
223 
224 	if (!cfg->test_gso) {
225 		res = 0;
226 		goto end;
227 	}
228 
229 	err = send(conn->client_fd, tx_buffer, GSO_TEST_DATA_SIZE, 0);
230 	if (!ASSERT_EQ(err, GSO_TEST_DATA_SIZE, "send (large) data from client"))
231 		goto end;
232 	if (check_server_rx_data(cfg, conn, DEFAULT_TEST_DATA_SIZE))
233 		goto end;
234 
235 	res = 0;
236 end:
237 	disconnect_client_from_server(cfg, conn);
238 	return res;
239 }
240 
vxlan_decap_mod_args_cb(struct subtest_cfg * cfg,char * dst)241 static void vxlan_decap_mod_args_cb(struct subtest_cfg *cfg, char *dst)
242 {
243 	snprintf(dst, TUNNEL_ARGS_MAX_LEN, "id %d dstport %d udp6zerocsumrx",
244 		 VXLAN_ID, VXLAN_PORT);
245 }
246 
udp_decap_mod_args_cb(struct subtest_cfg * cfg,char * dst)247 static void udp_decap_mod_args_cb(struct subtest_cfg *cfg, char *dst)
248 {
249 	bool is_mpls = !strcmp(cfg->mac_tun_type, "mpls");
250 
251 	snprintf(dst, TUNNEL_ARGS_MAX_LEN,
252 		 "encap fou encap-sport auto encap-dport %d",
253 		 is_mpls ? MPLS_UDP_PORT : UDP_PORT);
254 }
255 
configure_fou_rx_port(struct subtest_cfg * cfg,bool add)256 static int configure_fou_rx_port(struct subtest_cfg *cfg, bool add)
257 {
258 	bool is_mpls = strcmp(cfg->mac_tun_type, "mpls") == 0;
259 	int fou_proto;
260 
261 	if (is_mpls)
262 		fou_proto = FOU_MPLS_PROTO;
263 	else
264 		fou_proto = cfg->ipproto == 6 ? 41 : 4;
265 
266 	SYS(fail, "ip fou %s port %d ipproto %d%s", add ? "add" : "del",
267 	    is_mpls ? MPLS_UDP_PORT : UDP_PORT, fou_proto,
268 	    cfg->ipproto == 6 ? " -6" : "");
269 
270 	return 0;
271 fail:
272 	return 1;
273 }
274 
add_fou_rx_port(struct subtest_cfg * cfg)275 static int add_fou_rx_port(struct subtest_cfg *cfg)
276 {
277 	return configure_fou_rx_port(cfg, true);
278 }
279 
del_fou_rx_port(struct subtest_cfg * cfg)280 static int del_fou_rx_port(struct subtest_cfg *cfg)
281 {
282 	return configure_fou_rx_port(cfg, false);
283 }
284 
update_tunnel_intf_addr(struct subtest_cfg * cfg)285 static int update_tunnel_intf_addr(struct subtest_cfg *cfg)
286 {
287 	SYS(fail, "ip link set dev testtun0 address " MAC_ADDR_VETH2);
288 	return 0;
289 fail:
290 	return -1;
291 }
292 
configure_kernel_for_mpls(struct subtest_cfg * cfg)293 static int configure_kernel_for_mpls(struct subtest_cfg *cfg)
294 {
295 	SYS(fail, "sysctl -qw net.mpls.platform_labels=%d",
296 	    MPLS_TABLE_ENTRIES_COUNT);
297 	SYS(fail, "ip -f mpls route add 1000 dev lo");
298 	SYS(fail, "ip link set lo up");
299 	SYS(fail, "sysctl -qw net.mpls.conf.testtun0.input=1");
300 	SYS(fail, "sysctl -qw net.ipv4.conf.lo.rp_filter=0");
301 	return 0;
302 fail:
303 	return -1;
304 }
305 
configure_encapsulation(struct subtest_cfg * cfg)306 static int configure_encapsulation(struct subtest_cfg *cfg)
307 {
308 	int ret;
309 
310 	ret = tc_prog_attach("veth1", -1, cfg->client_egress_prog_fd);
311 
312 	return ret;
313 }
314 
configure_kernel_decapsulation(struct subtest_cfg * cfg)315 static int configure_kernel_decapsulation(struct subtest_cfg *cfg)
316 {
317 	struct nstoken *nstoken = open_netns(SERVER_NS);
318 	int ret = -1;
319 
320 	if (!ASSERT_OK_PTR(nstoken, "open server ns"))
321 		return ret;
322 
323 	if (cfg->configure_fou_rx_port &&
324 	    !ASSERT_OK(add_fou_rx_port(cfg), "configure FOU RX port"))
325 		goto fail;
326 	SYS(fail, "ip link add name testtun0 type %s %s remote %s local %s %s",
327 	    cfg->iproute_tun_type, cfg->tmode ? cfg->tmode : "",
328 	    cfg->tunnel_client_addr, cfg->tunnel_server_addr,
329 	    cfg->extra_decap_mod_args);
330 	if (cfg->tunnel_need_veth_mac &&
331 	    !ASSERT_OK(update_tunnel_intf_addr(cfg), "update testtun0 mac"))
332 		goto fail;
333 	if (cfg->configure_mpls &&
334 	    (!ASSERT_OK(configure_kernel_for_mpls(cfg),
335 			"configure MPLS decap")))
336 		goto fail;
337 	SYS(fail, "sysctl -qw net.ipv4.conf.all.rp_filter=0");
338 	SYS(fail, "sysctl -qw net.ipv4.conf.testtun0.rp_filter=0");
339 	SYS(fail, "ip link set dev testtun0 up");
340 
341 	ret = 0;
342 fail:
343 	close_netns(nstoken);
344 	return ret;
345 }
346 
remove_kernel_decapsulation(struct subtest_cfg * cfg)347 static void remove_kernel_decapsulation(struct subtest_cfg *cfg)
348 {
349 	SYS_NOFAIL("ip link del testtun0");
350 	if (cfg->configure_mpls)
351 		SYS_NOFAIL("ip -f mpls route del 1000 dev lo");
352 	if (cfg->configure_fou_rx_port)
353 		del_fou_rx_port(cfg);
354 }
355 
configure_ebpf_decapsulation(struct subtest_cfg * cfg)356 static int configure_ebpf_decapsulation(struct subtest_cfg *cfg)
357 {
358 	struct nstoken *nstoken = open_netns(SERVER_NS);
359 	int ret = -1;
360 
361 	if (!ASSERT_OK_PTR(nstoken, "open server ns"))
362 		return ret;
363 
364 	if (!cfg->expect_kern_decap_failure)
365 		SYS(fail, "ip link del testtun0");
366 
367 	if (!ASSERT_OK(tc_prog_attach("veth2", cfg->server_ingress_prog_fd, -1),
368 		       "attach_program"))
369 		goto fail;
370 
371 	ret = 0;
372 fail:
373 	close_netns(nstoken);
374 	return ret;
375 }
376 
run_test(struct subtest_cfg * cfg)377 static void run_test(struct subtest_cfg *cfg)
378 {
379 	struct nstoken *nstoken;
380 
381 	if (!ASSERT_OK(run_server(cfg), "run server"))
382 		return;
383 
384 	nstoken = open_netns(CLIENT_NS);
385 	if (!ASSERT_OK_PTR(nstoken, "open client ns"))
386 		goto fail;
387 
388 	/* Basic communication must work */
389 	if (!ASSERT_OK(send_and_test_data(cfg), "connect without any encap"))
390 		goto fail;
391 
392 	/* Attach encapsulation program to client */
393 	if (!ASSERT_OK(configure_encapsulation(cfg), "configure encapsulation"))
394 		goto fail;
395 
396 	/* If supported, insert kernel decap module, connection must succeed */
397 	if (!cfg->expect_kern_decap_failure) {
398 		if (!ASSERT_OK(configure_kernel_decapsulation(cfg),
399 					"configure kernel decapsulation"))
400 			goto fail;
401 		if (!ASSERT_OK(send_and_test_data(cfg),
402 			       "connect with encap prog and kern decap"))
403 			goto fail;
404 	}
405 
406 	/* Replace kernel decapsulation with BPF decapsulation, test must pass */
407 	if (!ASSERT_OK(configure_ebpf_decapsulation(cfg), "configure ebpf decapsulation"))
408 		goto fail;
409 	ASSERT_OK(send_and_test_data(cfg), "connect with encap and decap progs");
410 
411 fail:
412 	close_netns(nstoken);
413 	close(cfg->server_fd);
414 }
415 
setup(void)416 static int setup(void)
417 {
418 	struct nstoken *nstoken_client, *nstoken_server;
419 	int fd, err;
420 
421 	fd = open("/dev/urandom", O_RDONLY);
422 	if (!ASSERT_OK_FD(fd, "open urandom"))
423 		goto fail;
424 	err = read(fd, tx_buffer, BUFFER_LEN);
425 	close(fd);
426 
427 	if (!ASSERT_EQ(err, BUFFER_LEN, "read random bytes"))
428 		goto fail;
429 
430 	/* Configure the testing network */
431 	if (!ASSERT_OK(make_netns(CLIENT_NS), "create client ns") ||
432 	    !ASSERT_OK(make_netns(SERVER_NS), "create server ns"))
433 		goto fail;
434 
435 	nstoken_client = open_netns(CLIENT_NS);
436 	if (!ASSERT_OK_PTR(nstoken_client, "open client ns"))
437 		goto fail_delete_ns;
438 	SYS(fail_close_ns_client, "ip link add %s type veth peer name %s",
439 	    "veth1 mtu 1500 netns " CLIENT_NS " address " MAC_ADDR_VETH1,
440 	    "veth2 mtu 1500 netns " SERVER_NS " address " MAC_ADDR_VETH2);
441 	SYS(fail_close_ns_client, "ethtool -K veth1 tso off");
442 	SYS(fail_close_ns_client, "ip link set veth1 up");
443 	nstoken_server = open_netns(SERVER_NS);
444 	if (!ASSERT_OK_PTR(nstoken_server, "open server ns"))
445 		goto fail_close_ns_client;
446 	SYS(fail_close_ns_server, "ip link set veth2 up");
447 
448 	close_netns(nstoken_server);
449 	close_netns(nstoken_client);
450 	return 0;
451 
452 fail_close_ns_server:
453 	close_netns(nstoken_server);
454 fail_close_ns_client:
455 	close_netns(nstoken_client);
456 fail_delete_ns:
457 	SYS_NOFAIL("ip netns del " CLIENT_NS);
458 	SYS_NOFAIL("ip netns del " SERVER_NS);
459 fail:
460 	return -1;
461 }
462 
subtest_setup(struct test_tc_tunnel * skel,struct subtest_cfg * cfg)463 static int subtest_setup(struct test_tc_tunnel *skel, struct subtest_cfg *cfg)
464 {
465 	struct nstoken *nstoken_client, *nstoken_server;
466 	int ret = -1;
467 
468 	set_subtest_addresses(cfg);
469 	if (!ASSERT_OK(set_subtest_progs(cfg, skel),
470 		       "find subtest progs"))
471 		goto fail;
472 	if (cfg->extra_decap_mod_args_cb)
473 		cfg->extra_decap_mod_args_cb(cfg, cfg->extra_decap_mod_args);
474 
475 	nstoken_client = open_netns(CLIENT_NS);
476 	if (!ASSERT_OK_PTR(nstoken_client, "open client ns"))
477 		goto fail;
478 	SYS(fail_close_client_ns,
479 	    "ip -4 addr add " IP4_ADDR_VETH1 "/24 dev veth1");
480 	SYS(fail_close_client_ns, "ip -4 route flush table main");
481 	SYS(fail_close_client_ns,
482 	    "ip -4 route add " IP4_ADDR_VETH2 " mtu 1450 dev veth1");
483 	SYS(fail_close_client_ns,
484 	    "ip -6 addr add " IP6_ADDR_VETH1 "/64 dev veth1 nodad");
485 	SYS(fail_close_client_ns, "ip -6 route flush table main");
486 	SYS(fail_close_client_ns,
487 	    "ip -6 route add " IP6_ADDR_VETH2 " mtu 1430 dev veth1");
488 	nstoken_server = open_netns(SERVER_NS);
489 	if (!ASSERT_OK_PTR(nstoken_server, "open server ns"))
490 		goto fail_close_client_ns;
491 	SYS(fail_close_server_ns,
492 	    "ip -4 addr add " IP4_ADDR_VETH2 "/24 dev veth2");
493 	SYS(fail_close_server_ns,
494 	    "ip -6 addr add " IP6_ADDR_VETH2 "/64 dev veth2 nodad");
495 
496 	ret = 0;
497 
498 fail_close_server_ns:
499 	close_netns(nstoken_server);
500 fail_close_client_ns:
501 	close_netns(nstoken_client);
502 fail:
503 	return ret;
504 }
505 
506 
subtest_cleanup(struct subtest_cfg * cfg)507 static void subtest_cleanup(struct subtest_cfg *cfg)
508 {
509 	struct nstoken *nstoken;
510 
511 	nstoken = open_netns(CLIENT_NS);
512 	if (ASSERT_OK_PTR(nstoken, "open clien ns")) {
513 		SYS_NOFAIL("tc qdisc delete dev veth1 parent ffff:fff1");
514 		SYS_NOFAIL("ip a flush veth1");
515 		close_netns(nstoken);
516 	}
517 	nstoken = open_netns(SERVER_NS);
518 	if (ASSERT_OK_PTR(nstoken, "open clien ns")) {
519 		SYS_NOFAIL("tc qdisc delete dev veth2 parent ffff:fff1");
520 		SYS_NOFAIL("ip a flush veth2");
521 		if (!cfg->expect_kern_decap_failure)
522 			remove_kernel_decapsulation(cfg);
523 		close_netns(nstoken);
524 	}
525 }
526 
cleanup(void)527 static void cleanup(void)
528 {
529 	remove_netns(CLIENT_NS);
530 	remove_netns(SERVER_NS);
531 }
532 
533 static struct subtest_cfg subtests_cfg[] = {
534 	{
535 		.ebpf_tun_type = "ipip",
536 		.mac_tun_type = "none",
537 		.iproute_tun_type = "ipip",
538 		.ipproto = 4,
539 	},
540 	{
541 		.ebpf_tun_type = "ipip6",
542 		.mac_tun_type = "none",
543 		.iproute_tun_type = "ip6tnl",
544 		.ipproto = 4,
545 		.tunnel_client_addr = IP6_ADDR_VETH1,
546 		.tunnel_server_addr = IP6_ADDR_VETH2,
547 	},
548 	{
549 		.ebpf_tun_type = "ip6tnl",
550 		.iproute_tun_type = "ip6tnl",
551 		.mac_tun_type = "none",
552 		.ipproto = 6,
553 	},
554 	{
555 		.mac_tun_type = "none",
556 		.ebpf_tun_type = "sit",
557 		.iproute_tun_type = "sit",
558 		.ipproto = 6,
559 		.tunnel_client_addr = IP4_ADDR_VETH1,
560 		.tunnel_server_addr = IP4_ADDR_VETH2,
561 	},
562 	{
563 		.ebpf_tun_type = "vxlan",
564 		.mac_tun_type = "eth",
565 		.iproute_tun_type = "vxlan",
566 		.ipproto = 4,
567 		.extra_decap_mod_args_cb = vxlan_decap_mod_args_cb,
568 		.tunnel_need_veth_mac = true
569 	},
570 	{
571 		.ebpf_tun_type = "ip6vxlan",
572 		.mac_tun_type = "eth",
573 		.iproute_tun_type = "vxlan",
574 		.ipproto = 6,
575 		.extra_decap_mod_args_cb = vxlan_decap_mod_args_cb,
576 		.tunnel_need_veth_mac = true
577 	},
578 	{
579 		.ebpf_tun_type = "gre",
580 		.mac_tun_type = "none",
581 		.iproute_tun_type = "gre",
582 		.ipproto = 4,
583 		.test_gso = true
584 	},
585 	{
586 		.ebpf_tun_type = "gre",
587 		.mac_tun_type = "eth",
588 		.iproute_tun_type = "gretap",
589 		.ipproto = 4,
590 		.tunnel_need_veth_mac = true,
591 		.test_gso = true
592 	},
593 	{
594 		.ebpf_tun_type = "gre",
595 		.mac_tun_type = "mpls",
596 		.iproute_tun_type = "gre",
597 		.ipproto = 4,
598 		.configure_mpls = true,
599 		.test_gso = true
600 	},
601 	{
602 		.ebpf_tun_type = "ip6gre",
603 		.mac_tun_type = "none",
604 		.iproute_tun_type = "ip6gre",
605 		.ipproto = 6,
606 		.test_gso = true,
607 	},
608 	{
609 		.ebpf_tun_type = "ip6gre",
610 		.mac_tun_type = "eth",
611 		.iproute_tun_type = "ip6gretap",
612 		.ipproto = 6,
613 		.tunnel_need_veth_mac = true,
614 		.test_gso = true
615 	},
616 	{
617 		.ebpf_tun_type = "ip6gre",
618 		.mac_tun_type = "mpls",
619 		.iproute_tun_type = "ip6gre",
620 		.ipproto = 6,
621 		.configure_mpls = true,
622 		.test_gso = true
623 	},
624 	{
625 		.ebpf_tun_type = "udp",
626 		.mac_tun_type = "none",
627 		.iproute_tun_type = "ipip",
628 		.ipproto = 4,
629 		.extra_decap_mod_args_cb = udp_decap_mod_args_cb,
630 		.configure_fou_rx_port = true,
631 		.test_gso = true
632 	},
633 	{
634 		.ebpf_tun_type = "udp",
635 		.mac_tun_type = "eth",
636 		.iproute_tun_type = "ipip",
637 		.ipproto = 4,
638 		.extra_decap_mod_args_cb = udp_decap_mod_args_cb,
639 		.configure_fou_rx_port = true,
640 		.expect_kern_decap_failure = true,
641 		.test_gso = true
642 	},
643 	{
644 		.ebpf_tun_type = "udp",
645 		.mac_tun_type = "mpls",
646 		.iproute_tun_type = "ipip",
647 		.ipproto = 4,
648 		.extra_decap_mod_args_cb = udp_decap_mod_args_cb,
649 		.configure_fou_rx_port = true,
650 		.tmode = "mode any ttl 255",
651 		.configure_mpls = true,
652 		.test_gso = true
653 	},
654 	{
655 		.ebpf_tun_type = "ip6udp",
656 		.mac_tun_type = "none",
657 		.iproute_tun_type = "ip6tnl",
658 		.ipproto = 6,
659 		.extra_decap_mod_args_cb = udp_decap_mod_args_cb,
660 		.configure_fou_rx_port = true,
661 		.test_gso = true
662 	},
663 	{
664 		.ebpf_tun_type = "ip6udp",
665 		.mac_tun_type = "eth",
666 		.iproute_tun_type = "ip6tnl",
667 		.ipproto = 6,
668 		.extra_decap_mod_args_cb = udp_decap_mod_args_cb,
669 		.configure_fou_rx_port = true,
670 		.expect_kern_decap_failure = true,
671 		.test_gso = true
672 	},
673 	{
674 		.ebpf_tun_type = "ip6udp",
675 		.mac_tun_type = "mpls",
676 		.iproute_tun_type = "ip6tnl",
677 		.ipproto = 6,
678 		.extra_decap_mod_args_cb = udp_decap_mod_args_cb,
679 		.configure_fou_rx_port = true,
680 		.tmode = "mode any ttl 255",
681 		.expect_kern_decap_failure = true,
682 		.test_gso = true
683 	},
684 };
685 
test_tc_tunnel(void)686 void test_tc_tunnel(void)
687 {
688 	struct test_tc_tunnel *skel;
689 	struct subtest_cfg *cfg;
690 	int i, ret;
691 
692 	skel = test_tc_tunnel__open_and_load();
693 	if (!ASSERT_OK_PTR(skel, "skel open and load"))
694 		return;
695 
696 	if (!ASSERT_OK(setup(), "global setup"))
697 		goto out;
698 
699 	for (i = 0; i < ARRAY_SIZE(subtests_cfg); i++) {
700 		cfg = &subtests_cfg[i];
701 		ret = build_subtest_name(cfg, cfg->name, TEST_NAME_MAX_LEN);
702 		if (ret < 0 || !test__start_subtest(cfg->name))
703 			continue;
704 		if (subtest_setup(skel, cfg) == 0)
705 			run_test(cfg);
706 		subtest_cleanup(cfg);
707 	}
708 	cleanup();
709 
710 out:
711 	test_tc_tunnel__destroy(skel);
712 }
713