// SPDX-License-Identifier: GPL-2.0-only
/* Connects 6 network namespaces through veths.
* Each NS may have different IPv6 global scope addresses :
*
* NS1 NS2 NS3 NS4 NS5 NS6
* lo veth1 < - > veth2 veth3 < - > veth4 veth5 < - > veth6 lo veth7 < - > veth8 veth9 < - > veth10 lo
* fb00 : : 1 : : 12 : : 21 : : 34 : : 43 : : 56 : : 65 : : 78 : : 87 : : 910 : : 109 : : 6
* fd00 : : 4
* fc42 : : 1
*
* All IPv6 packets going to fb00 : : / 16 through NS2 will be encapsulated in a
* IPv6 header with a Segment Routing Header , with segments :
* fd00 : : 1 - > fd00 : : 2 - > fd00 : : 3 - > fd00 : : 4
*
* 3 fd00 : : / 16 IPv6 addresses are binded to seg6local End . BPF actions :
* - fd00 : : 1 : add a TLV , change the flags and apply a End . X action to fc42 : : 1
* - fd00 : : 2 : remove the TLV , change the flags , add a tag
* - fd00 : : 3 : apply an End . T action to fd00 : : 4 , through routing table 117
*
* fd00 : : 4 is a simple Segment Routing node decapsulating the inner IPv6 packet .
* Each End . BPF action will validate the operations applied on the SRH by the
* previous BPF program in the chain , otherwise the packet is dropped .
*
* An UDP datagram is sent from fb00 : : 1 to fb00 : : 6 . The test succeeds if this
* datagram can be read on NS6 when binding to fb00 : : 6 .
*/
#include "network_helpers.h"
#include "test_progs.h"
#define NETNS_BASE "lwt-seg6local-"
#define BPF_FILE "test_lwt_seg6local.bpf.o"
static void cleanup(void )
{
int ns;
for (ns = 1 ; ns < 7 ; ns++)
SYS_NOFAIL("ip netns del %s%d" , NETNS_BASE, ns);
}
static int setup(void )
{
int ns;
for (ns = 1 ; ns < 7 ; ns++)
SYS(fail, "ip netns add %s%d" , NETNS_BASE, ns);
SYS(fail, "ip -n %s6 link set dev lo up" , NETNS_BASE);
for (ns = 1 ; ns < 6 ; ns++) {
int local_id = ns * 2 - 1 ;
int peer_id = ns * 2 ;
int next_ns = ns + 1 ;
SYS(fail, "ip -n %s%d link add veth%d type veth peer name veth%d netns %s%d" ,
NETNS_BASE, ns, local_id, peer_id, NETNS_BASE, next_ns);
SYS(fail, "ip -n %s%d link set dev veth%d up" , NETNS_BASE, ns, local_id);
SYS(fail, "ip -n %s%d link set dev veth%d up" , NETNS_BASE, next_ns, peer_id);
/* All link scope addresses to veths */
SYS(fail, "ip -n %s%d -6 addr add fb00::%d%d/16 dev veth%d scope link" ,
NETNS_BASE, ns, local_id, peer_id, local_id);
SYS(fail, "ip -n %s%d -6 addr add fb00::%d%d/16 dev veth%d scope link" ,
NETNS_BASE, next_ns, peer_id, local_id, peer_id);
}
SYS(fail, "ip -n %s5 -6 route add fb00::109 table 117 dev veth9 scope link" , NETNS_BASE);
SYS(fail, "ip -n %s1 -6 addr add fb00::1/16 dev lo" , NETNS_BASE);
SYS(fail, "ip -n %s1 -6 route add fb00::6 dev veth1 via fb00::21" , NETNS_BASE);
SYS(fail, "ip -n %s2 -6 route add fb00::6 encap bpf in obj %s sec encap_srh dev veth2" ,
NETNS_BASE, BPF_FILE);
SYS(fail, "ip -n %s2 -6 route add fd00::1 dev veth3 via fb00::43 scope link" , NETNS_BASE);
SYS(fail, "ip -n %s3 -6 route add fc42::1 dev veth5 via fb00::65" , NETNS_BASE);
SYS(fail,
"ip -n %s3 -6 route add fd00::1 encap seg6local action End.BPF endpoint obj %s sec add_egr_x dev veth4" ,
NETNS_BASE, BPF_FILE);
SYS(fail,
"ip -n %s4 -6 route add fd00::2 encap seg6local action End.BPF endpoint obj %s sec pop_egr dev veth6" ,
NETNS_BASE, BPF_FILE);
SYS(fail, "ip -n %s4 -6 addr add fc42::1 dev lo" , NETNS_BASE);
SYS(fail, "ip -n %s4 -6 route add fd00::3 dev veth7 via fb00::87" , NETNS_BASE);
SYS(fail, "ip -n %s5 -6 route add fd00::4 table 117 dev veth9 via fb00::109" , NETNS_BASE);
SYS(fail,
"ip -n %s5 -6 route add fd00::3 encap seg6local action End.BPF endpoint obj %s sec inspect_t dev veth8" ,
NETNS_BASE, BPF_FILE);
SYS(fail, "ip -n %s6 -6 addr add fb00::6/16 dev lo" , NETNS_BASE);
SYS(fail, "ip -n %s6 -6 addr add fd00::4/16 dev lo" , NETNS_BASE);
for (ns = 1 ; ns < 6 ; ns++)
SYS(fail, "ip netns exec %s%d sysctl -wq net.ipv6.conf.all.forwarding=1" ,
NETNS_BASE, ns);
SYS(fail, "ip netns exec %s6 sysctl -wq net.ipv6.conf.all.seg6_enabled=1" , NETNS_BASE);
SYS(fail, "ip netns exec %s6 sysctl -wq net.ipv6.conf.lo.seg6_enabled=1" , NETNS_BASE);
SYS(fail, "ip netns exec %s6 sysctl -wq net.ipv6.conf.veth10.seg6_enabled=1" , NETNS_BASE);
return 0 ;
fail:
return -1 ;
}
#define SERVER_PORT 7330
#define CLIENT_PORT 2121
void test_lwt_seg6local(void )
{
struct sockaddr_in6 server_addr = {};
const char *ns1 = NETNS_BASE "1" ;
const char *ns6 = NETNS_BASE "6" ;
struct nstoken *nstoken = NULL;
const char *foobar = "foobar" ;
ssize_t bytes;
int sfd, cfd;
char buf[7 ];
if (!ASSERT_OK(setup(), "setup" ))
goto out;
nstoken = open_netns(ns6);
if (!ASSERT_OK_PTR(nstoken, "open ns6" ))
goto out;
sfd = start_server_str(AF_INET6, SOCK_DGRAM, "fb00::6" , SERVER_PORT, NULL);
if (!ASSERT_OK_FD(sfd, "start server" ))
goto close_netns;
close_netns(nstoken);
nstoken = open_netns(ns1);
if (!ASSERT_OK_PTR(nstoken, "open ns1" ))
goto close_server;
cfd = start_server_str(AF_INET6, SOCK_DGRAM, "fb00::1" , CLIENT_PORT, NULL);
if (!ASSERT_OK_FD(cfd, "start client" ))
goto close_server;
close_netns(nstoken);
nstoken = NULL;
/* Send a packet larger than MTU */
server_addr.sin6_family = AF_INET6;
server_addr.sin6_port = htons(SERVER_PORT);
if (!ASSERT_EQ(inet_pton(AF_INET6, "fb00::6" , &server_addr.sin6_addr), 1 ,
"build target addr" ))
goto close_client;
bytes = sendto(cfd, foobar, sizeof (foobar), 0 ,
(struct sockaddr *)&server_addr, sizeof (server_addr));
if (!ASSERT_EQ(bytes, sizeof (foobar), "send packet" ))
goto close_client;
/* Verify we received all expected bytes */
bytes = read(sfd, buf, sizeof (buf));
if (!ASSERT_EQ(bytes, sizeof (buf), "receive packet" ))
goto close_client;
ASSERT_STREQ(buf, foobar, "check udp packet" );
close_client:
close(cfd);
close_server:
close(sfd);
close_netns:
close_netns(nstoken);
out:
cleanup();
}
Messung V0.5 in Prozent C=98 H=53 G=78
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-10-12)
¤
*© Formatika GbR, Deutschland