File Index
Files and directories
Sign in
FILE

lwt_seg6local.c

File preview with syntax highlighting.

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