xref: /linux/tools/testing/selftests/bpf/prog_tests/lwt_seg6local.c (revision 4f9786035f9e519db41375818e1d0b5f20da2f10)
1*1041b8bcSBastien Curutchet (eBPF Foundation) // SPDX-License-Identifier: GPL-2.0-only
2*1041b8bcSBastien Curutchet (eBPF Foundation) 
3*1041b8bcSBastien Curutchet (eBPF Foundation) /* Connects 6 network namespaces through veths.
4*1041b8bcSBastien Curutchet (eBPF Foundation)  * Each NS may have different IPv6 global scope addresses :
5*1041b8bcSBastien Curutchet (eBPF Foundation)  *
6*1041b8bcSBastien Curutchet (eBPF Foundation)  *          NS1            NS2             NS3              NS4               NS5             NS6
7*1041b8bcSBastien Curutchet (eBPF Foundation)  *      lo  veth1 <-> veth2 veth3 <-> veth4 veth5 <-> veth6 lo veth7 <-> veth8 veth9 <-> veth10 lo
8*1041b8bcSBastien Curutchet (eBPF Foundation)  * fb00 ::1  ::12      ::21  ::34      ::43  ::56      ::65     ::78      ::87  ::910     ::109  ::6
9*1041b8bcSBastien Curutchet (eBPF Foundation)  * fd00                                                                                          ::4
10*1041b8bcSBastien Curutchet (eBPF Foundation)  * fc42                                                     ::1
11*1041b8bcSBastien Curutchet (eBPF Foundation)  *
12*1041b8bcSBastien Curutchet (eBPF Foundation)  * All IPv6 packets going to fb00::/16 through NS2 will be encapsulated in a
13*1041b8bcSBastien Curutchet (eBPF Foundation)  * IPv6 header with a Segment Routing Header, with segments :
14*1041b8bcSBastien Curutchet (eBPF Foundation)  *	fd00::1 -> fd00::2 -> fd00::3 -> fd00::4
15*1041b8bcSBastien Curutchet (eBPF Foundation)  *
16*1041b8bcSBastien Curutchet (eBPF Foundation)  * 3 fd00::/16 IPv6 addresses are binded to seg6local End.BPF actions :
17*1041b8bcSBastien Curutchet (eBPF Foundation)  * - fd00::1 : add a TLV, change the flags and apply a End.X action to fc42::1
18*1041b8bcSBastien Curutchet (eBPF Foundation)  * - fd00::2 : remove the TLV, change the flags, add a tag
19*1041b8bcSBastien Curutchet (eBPF Foundation)  * - fd00::3 : apply an End.T action to fd00::4, through routing table 117
20*1041b8bcSBastien Curutchet (eBPF Foundation)  *
21*1041b8bcSBastien Curutchet (eBPF Foundation)  * fd00::4 is a simple Segment Routing node decapsulating the inner IPv6 packet.
22*1041b8bcSBastien Curutchet (eBPF Foundation)  * Each End.BPF action will validate the operations applied on the SRH by the
23*1041b8bcSBastien Curutchet (eBPF Foundation)  * previous BPF program in the chain, otherwise the packet is dropped.
24*1041b8bcSBastien Curutchet (eBPF Foundation)  *
25*1041b8bcSBastien Curutchet (eBPF Foundation)  * An UDP datagram is sent from fb00::1 to fb00::6. The test succeeds if this
26*1041b8bcSBastien Curutchet (eBPF Foundation)  * datagram can be read on NS6 when binding to fb00::6.
27*1041b8bcSBastien Curutchet (eBPF Foundation)  */
28*1041b8bcSBastien Curutchet (eBPF Foundation) 
29*1041b8bcSBastien Curutchet (eBPF Foundation) #include "network_helpers.h"
30*1041b8bcSBastien Curutchet (eBPF Foundation) #include "test_progs.h"
31*1041b8bcSBastien Curutchet (eBPF Foundation) 
32*1041b8bcSBastien Curutchet (eBPF Foundation) #define NETNS_BASE "lwt-seg6local-"
33*1041b8bcSBastien Curutchet (eBPF Foundation) #define BPF_FILE "test_lwt_seg6local.bpf.o"
34*1041b8bcSBastien Curutchet (eBPF Foundation) 
35*1041b8bcSBastien Curutchet (eBPF Foundation) static void cleanup(void)
36*1041b8bcSBastien Curutchet (eBPF Foundation) {
37*1041b8bcSBastien Curutchet (eBPF Foundation) 	int ns;
38*1041b8bcSBastien Curutchet (eBPF Foundation) 
39*1041b8bcSBastien Curutchet (eBPF Foundation) 	for (ns = 1; ns < 7; ns++)
40*1041b8bcSBastien Curutchet (eBPF Foundation) 		SYS_NOFAIL("ip netns del %s%d", NETNS_BASE, ns);
41*1041b8bcSBastien Curutchet (eBPF Foundation) }
42*1041b8bcSBastien Curutchet (eBPF Foundation) 
43*1041b8bcSBastien Curutchet (eBPF Foundation) static int setup(void)
44*1041b8bcSBastien Curutchet (eBPF Foundation) {
45*1041b8bcSBastien Curutchet (eBPF Foundation) 	int ns;
46*1041b8bcSBastien Curutchet (eBPF Foundation) 
47*1041b8bcSBastien Curutchet (eBPF Foundation) 	for (ns = 1; ns < 7; ns++)
48*1041b8bcSBastien Curutchet (eBPF Foundation) 		SYS(fail, "ip netns add %s%d", NETNS_BASE, ns);
49*1041b8bcSBastien Curutchet (eBPF Foundation) 
50*1041b8bcSBastien Curutchet (eBPF Foundation) 	SYS(fail, "ip -n %s6 link set dev lo up", NETNS_BASE);
51*1041b8bcSBastien Curutchet (eBPF Foundation) 
52*1041b8bcSBastien Curutchet (eBPF Foundation) 	for (ns = 1; ns < 6; ns++) {
53*1041b8bcSBastien Curutchet (eBPF Foundation) 		int local_id = ns * 2 - 1;
54*1041b8bcSBastien Curutchet (eBPF Foundation) 		int peer_id = ns * 2;
55*1041b8bcSBastien Curutchet (eBPF Foundation) 		int next_ns = ns + 1;
56*1041b8bcSBastien Curutchet (eBPF Foundation) 
57*1041b8bcSBastien Curutchet (eBPF Foundation) 		SYS(fail, "ip -n %s%d link add veth%d type veth peer name veth%d netns %s%d",
58*1041b8bcSBastien Curutchet (eBPF Foundation) 		    NETNS_BASE, ns, local_id, peer_id, NETNS_BASE, next_ns);
59*1041b8bcSBastien Curutchet (eBPF Foundation) 
60*1041b8bcSBastien Curutchet (eBPF Foundation) 		SYS(fail, "ip -n %s%d link set dev veth%d up", NETNS_BASE, ns, local_id);
61*1041b8bcSBastien Curutchet (eBPF Foundation) 		SYS(fail, "ip -n %s%d link set dev veth%d up", NETNS_BASE, next_ns, peer_id);
62*1041b8bcSBastien Curutchet (eBPF Foundation) 
63*1041b8bcSBastien Curutchet (eBPF Foundation) 		/* All link scope addresses to veths */
64*1041b8bcSBastien Curutchet (eBPF Foundation) 		SYS(fail, "ip -n %s%d -6 addr add fb00::%d%d/16 dev veth%d scope link",
65*1041b8bcSBastien Curutchet (eBPF Foundation) 		    NETNS_BASE, ns, local_id, peer_id, local_id);
66*1041b8bcSBastien Curutchet (eBPF Foundation) 		SYS(fail, "ip -n %s%d -6 addr add fb00::%d%d/16 dev veth%d scope link",
67*1041b8bcSBastien Curutchet (eBPF Foundation) 		    NETNS_BASE, next_ns, peer_id, local_id, peer_id);
68*1041b8bcSBastien Curutchet (eBPF Foundation) 	}
69*1041b8bcSBastien Curutchet (eBPF Foundation) 
70*1041b8bcSBastien Curutchet (eBPF Foundation) 
71*1041b8bcSBastien Curutchet (eBPF Foundation) 	SYS(fail, "ip -n %s5 -6 route add fb00::109 table 117 dev veth9 scope link", NETNS_BASE);
72*1041b8bcSBastien Curutchet (eBPF Foundation) 
73*1041b8bcSBastien Curutchet (eBPF Foundation) 	SYS(fail, "ip -n %s1 -6 addr add fb00::1/16 dev lo", NETNS_BASE);
74*1041b8bcSBastien Curutchet (eBPF Foundation) 	SYS(fail, "ip -n %s1 -6 route add fb00::6 dev veth1 via fb00::21", NETNS_BASE);
75*1041b8bcSBastien Curutchet (eBPF Foundation) 
76*1041b8bcSBastien Curutchet (eBPF Foundation) 	SYS(fail, "ip -n %s2 -6 route add fb00::6 encap bpf in obj %s sec encap_srh dev veth2",
77*1041b8bcSBastien Curutchet (eBPF Foundation) 	    NETNS_BASE, BPF_FILE);
78*1041b8bcSBastien Curutchet (eBPF Foundation) 	SYS(fail, "ip -n %s2 -6 route add fd00::1 dev veth3 via fb00::43 scope link", NETNS_BASE);
79*1041b8bcSBastien Curutchet (eBPF Foundation) 
80*1041b8bcSBastien Curutchet (eBPF Foundation) 	SYS(fail, "ip -n %s3 -6 route add fc42::1 dev veth5 via fb00::65", NETNS_BASE);
81*1041b8bcSBastien Curutchet (eBPF Foundation) 	SYS(fail,
82*1041b8bcSBastien Curutchet (eBPF Foundation) 	    "ip -n %s3 -6 route add fd00::1 encap seg6local action End.BPF endpoint obj %s sec add_egr_x dev veth4",
83*1041b8bcSBastien Curutchet (eBPF Foundation) 	    NETNS_BASE, BPF_FILE);
84*1041b8bcSBastien Curutchet (eBPF Foundation) 
85*1041b8bcSBastien Curutchet (eBPF Foundation) 	SYS(fail,
86*1041b8bcSBastien Curutchet (eBPF Foundation) 	    "ip -n %s4 -6 route add fd00::2 encap seg6local action End.BPF endpoint obj %s sec pop_egr dev veth6",
87*1041b8bcSBastien Curutchet (eBPF Foundation) 	    NETNS_BASE, BPF_FILE);
88*1041b8bcSBastien Curutchet (eBPF Foundation) 	SYS(fail, "ip -n %s4 -6 addr add fc42::1 dev lo", NETNS_BASE);
89*1041b8bcSBastien Curutchet (eBPF Foundation) 	SYS(fail, "ip -n %s4 -6 route add fd00::3 dev veth7 via fb00::87", NETNS_BASE);
90*1041b8bcSBastien Curutchet (eBPF Foundation) 
91*1041b8bcSBastien Curutchet (eBPF Foundation) 	SYS(fail, "ip -n %s5 -6 route add fd00::4 table 117 dev veth9 via fb00::109", NETNS_BASE);
92*1041b8bcSBastien Curutchet (eBPF Foundation) 	SYS(fail,
93*1041b8bcSBastien Curutchet (eBPF Foundation) 	    "ip -n %s5 -6 route add fd00::3 encap seg6local action End.BPF endpoint obj %s sec inspect_t dev veth8",
94*1041b8bcSBastien Curutchet (eBPF Foundation) 	    NETNS_BASE, BPF_FILE);
95*1041b8bcSBastien Curutchet (eBPF Foundation) 
96*1041b8bcSBastien Curutchet (eBPF Foundation) 	SYS(fail, "ip -n %s6 -6 addr add fb00::6/16 dev lo", NETNS_BASE);
97*1041b8bcSBastien Curutchet (eBPF Foundation) 	SYS(fail, "ip -n %s6 -6 addr add fd00::4/16 dev lo", NETNS_BASE);
98*1041b8bcSBastien Curutchet (eBPF Foundation) 
99*1041b8bcSBastien Curutchet (eBPF Foundation) 	for (ns = 1; ns < 6; ns++)
100*1041b8bcSBastien Curutchet (eBPF Foundation) 		SYS(fail, "ip netns exec %s%d sysctl -wq net.ipv6.conf.all.forwarding=1",
101*1041b8bcSBastien Curutchet (eBPF Foundation) 		    NETNS_BASE, ns);
102*1041b8bcSBastien Curutchet (eBPF Foundation) 
103*1041b8bcSBastien Curutchet (eBPF Foundation) 	SYS(fail, "ip netns exec %s6 sysctl -wq net.ipv6.conf.all.seg6_enabled=1", NETNS_BASE);
104*1041b8bcSBastien Curutchet (eBPF Foundation) 	SYS(fail, "ip netns exec %s6 sysctl -wq net.ipv6.conf.lo.seg6_enabled=1", NETNS_BASE);
105*1041b8bcSBastien Curutchet (eBPF Foundation) 	SYS(fail, "ip netns exec %s6 sysctl -wq net.ipv6.conf.veth10.seg6_enabled=1", NETNS_BASE);
106*1041b8bcSBastien Curutchet (eBPF Foundation) 
107*1041b8bcSBastien Curutchet (eBPF Foundation) 	return 0;
108*1041b8bcSBastien Curutchet (eBPF Foundation) fail:
109*1041b8bcSBastien Curutchet (eBPF Foundation) 	return -1;
110*1041b8bcSBastien Curutchet (eBPF Foundation) }
111*1041b8bcSBastien Curutchet (eBPF Foundation) 
112*1041b8bcSBastien Curutchet (eBPF Foundation) #define SERVER_PORT 7330
113*1041b8bcSBastien Curutchet (eBPF Foundation) #define CLIENT_PORT 2121
114*1041b8bcSBastien Curutchet (eBPF Foundation) void test_lwt_seg6local(void)
115*1041b8bcSBastien Curutchet (eBPF Foundation) {
116*1041b8bcSBastien Curutchet (eBPF Foundation) 	struct sockaddr_in6 server_addr = {};
117*1041b8bcSBastien Curutchet (eBPF Foundation) 	const char *ns1 = NETNS_BASE "1";
118*1041b8bcSBastien Curutchet (eBPF Foundation) 	const char *ns6 = NETNS_BASE "6";
119*1041b8bcSBastien Curutchet (eBPF Foundation) 	struct nstoken *nstoken = NULL;
120*1041b8bcSBastien Curutchet (eBPF Foundation) 	const char *foobar = "foobar";
121*1041b8bcSBastien Curutchet (eBPF Foundation) 	ssize_t bytes;
122*1041b8bcSBastien Curutchet (eBPF Foundation) 	int sfd, cfd;
123*1041b8bcSBastien Curutchet (eBPF Foundation) 	char buf[7];
124*1041b8bcSBastien Curutchet (eBPF Foundation) 
125*1041b8bcSBastien Curutchet (eBPF Foundation) 	if (!ASSERT_OK(setup(), "setup"))
126*1041b8bcSBastien Curutchet (eBPF Foundation) 		goto out;
127*1041b8bcSBastien Curutchet (eBPF Foundation) 
128*1041b8bcSBastien Curutchet (eBPF Foundation) 	nstoken = open_netns(ns6);
129*1041b8bcSBastien Curutchet (eBPF Foundation) 	if (!ASSERT_OK_PTR(nstoken, "open ns6"))
130*1041b8bcSBastien Curutchet (eBPF Foundation) 		goto out;
131*1041b8bcSBastien Curutchet (eBPF Foundation) 
132*1041b8bcSBastien Curutchet (eBPF Foundation) 	sfd = start_server_str(AF_INET6, SOCK_DGRAM, "fb00::6", SERVER_PORT, NULL);
133*1041b8bcSBastien Curutchet (eBPF Foundation) 	if (!ASSERT_OK_FD(sfd, "start server"))
134*1041b8bcSBastien Curutchet (eBPF Foundation) 		goto close_netns;
135*1041b8bcSBastien Curutchet (eBPF Foundation) 
136*1041b8bcSBastien Curutchet (eBPF Foundation) 	close_netns(nstoken);
137*1041b8bcSBastien Curutchet (eBPF Foundation) 
138*1041b8bcSBastien Curutchet (eBPF Foundation) 	nstoken = open_netns(ns1);
139*1041b8bcSBastien Curutchet (eBPF Foundation) 	if (!ASSERT_OK_PTR(nstoken, "open ns1"))
140*1041b8bcSBastien Curutchet (eBPF Foundation) 		goto close_server;
141*1041b8bcSBastien Curutchet (eBPF Foundation) 
142*1041b8bcSBastien Curutchet (eBPF Foundation) 	cfd = start_server_str(AF_INET6, SOCK_DGRAM, "fb00::1", CLIENT_PORT, NULL);
143*1041b8bcSBastien Curutchet (eBPF Foundation) 	if (!ASSERT_OK_FD(cfd, "start client"))
144*1041b8bcSBastien Curutchet (eBPF Foundation) 		goto close_server;
145*1041b8bcSBastien Curutchet (eBPF Foundation) 
146*1041b8bcSBastien Curutchet (eBPF Foundation) 	close_netns(nstoken);
147*1041b8bcSBastien Curutchet (eBPF Foundation) 	nstoken = NULL;
148*1041b8bcSBastien Curutchet (eBPF Foundation) 
149*1041b8bcSBastien Curutchet (eBPF Foundation) 	/* Send a packet larger than MTU */
150*1041b8bcSBastien Curutchet (eBPF Foundation) 	server_addr.sin6_family = AF_INET6;
151*1041b8bcSBastien Curutchet (eBPF Foundation) 	server_addr.sin6_port = htons(SERVER_PORT);
152*1041b8bcSBastien Curutchet (eBPF Foundation) 	if (!ASSERT_EQ(inet_pton(AF_INET6, "fb00::6", &server_addr.sin6_addr), 1,
153*1041b8bcSBastien Curutchet (eBPF Foundation) 		       "build target addr"))
154*1041b8bcSBastien Curutchet (eBPF Foundation) 		goto close_client;
155*1041b8bcSBastien Curutchet (eBPF Foundation) 
156*1041b8bcSBastien Curutchet (eBPF Foundation) 	bytes = sendto(cfd, foobar, sizeof(foobar), 0,
157*1041b8bcSBastien Curutchet (eBPF Foundation) 		       (struct sockaddr *)&server_addr, sizeof(server_addr));
158*1041b8bcSBastien Curutchet (eBPF Foundation) 	if (!ASSERT_EQ(bytes, sizeof(foobar), "send packet"))
159*1041b8bcSBastien Curutchet (eBPF Foundation) 		goto close_client;
160*1041b8bcSBastien Curutchet (eBPF Foundation) 
161*1041b8bcSBastien Curutchet (eBPF Foundation) 	/* Verify we received all expected bytes */
162*1041b8bcSBastien Curutchet (eBPF Foundation) 	bytes = read(sfd, buf, sizeof(buf));
163*1041b8bcSBastien Curutchet (eBPF Foundation) 	if (!ASSERT_EQ(bytes, sizeof(buf), "receive packet"))
164*1041b8bcSBastien Curutchet (eBPF Foundation) 		goto close_client;
165*1041b8bcSBastien Curutchet (eBPF Foundation) 	ASSERT_STREQ(buf, foobar, "check udp packet");
166*1041b8bcSBastien Curutchet (eBPF Foundation) 
167*1041b8bcSBastien Curutchet (eBPF Foundation) close_client:
168*1041b8bcSBastien Curutchet (eBPF Foundation) 	close(cfd);
169*1041b8bcSBastien Curutchet (eBPF Foundation) close_server:
170*1041b8bcSBastien Curutchet (eBPF Foundation) 	close(sfd);
171*1041b8bcSBastien Curutchet (eBPF Foundation) close_netns:
172*1041b8bcSBastien Curutchet (eBPF Foundation) 	close_netns(nstoken);
173*1041b8bcSBastien Curutchet (eBPF Foundation) 
174*1041b8bcSBastien Curutchet (eBPF Foundation) out:
175*1041b8bcSBastien Curutchet (eBPF Foundation) 	cleanup();
176*1041b8bcSBastien Curutchet (eBPF Foundation) }
177