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 35 static 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 43 static 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; 108 fail: 109 return -1; 110 } 111 112 #define SERVER_PORT 7330 113 #define CLIENT_PORT 2121 114 void 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 167 close_client: 168 close(cfd); 169 close_server: 170 close(sfd); 171 close_netns: 172 close_netns(nstoken); 173 174 out: 175 cleanup(); 176 } 177