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