1#!/bin/bash
2# Connects 6 network namespaces through veths.
3# Each NS may have different IPv6 global scope addresses :
4#   NS1 ---- NS2 ---- NS3 ---- NS4 ---- NS5 ---- NS6
5# fb00::1           fd00::1  fd00::2  fd00::3  fb00::6
6#                   fc42::1           fd00::4
7#
8# All IPv6 packets going to fb00::/16 through NS2 will be encapsulated in a
9# IPv6 header with a Segment Routing Header, with segments :
10# 	fd00::1 -> fd00::2 -> fd00::3 -> fd00::4
11#
12# 3 fd00::/16 IPv6 addresses are binded to seg6local End.BPF actions :
13# - fd00::1 : add a TLV, change the flags and apply a End.X action to fc42::1
14# - fd00::2 : remove the TLV, change the flags, add a tag
15# - fd00::3 : apply an End.T action to fd00::4, through routing table 117
16#
17# fd00::4 is a simple Segment Routing node decapsulating the inner IPv6 packet.
18# Each End.BPF action will validate the operations applied on the SRH by the
19# previous BPF program in the chain, otherwise the packet is dropped.
20#
21# An UDP datagram is sent from fb00::1 to fb00::6. The test succeeds if this
22# datagram can be read on NS6 when binding to fb00::6.
23
24# Kselftest framework requirement - SKIP code is 4.
25ksft_skip=4
26BPF_FILE="test_lwt_seg6local.bpf.o"
27readonly NS1="ns1-$(mktemp -u XXXXXX)"
28readonly NS2="ns2-$(mktemp -u XXXXXX)"
29readonly NS3="ns3-$(mktemp -u XXXXXX)"
30readonly NS4="ns4-$(mktemp -u XXXXXX)"
31readonly NS5="ns5-$(mktemp -u XXXXXX)"
32readonly NS6="ns6-$(mktemp -u XXXXXX)"
33
34msg="skip all tests:"
35if [ $UID != 0 ]; then
36	echo $msg please run this as root >&2
37	exit $ksft_skip
38fi
39
40TMP_FILE="/tmp/selftest_lwt_seg6local.txt"
41
42cleanup()
43{
44	if [ "$?" = "0" ]; then
45		echo "selftests: test_lwt_seg6local [PASS]";
46	else
47		echo "selftests: test_lwt_seg6local [FAILED]";
48	fi
49
50	set +e
51	ip netns del ${NS1} 2> /dev/null
52	ip netns del ${NS2} 2> /dev/null
53	ip netns del ${NS3} 2> /dev/null
54	ip netns del ${NS4} 2> /dev/null
55	ip netns del ${NS5} 2> /dev/null
56	ip netns del ${NS6} 2> /dev/null
57	rm -f $TMP_FILE
58}
59
60set -e
61
62ip netns add ${NS1}
63ip netns add ${NS2}
64ip netns add ${NS3}
65ip netns add ${NS4}
66ip netns add ${NS5}
67ip netns add ${NS6}
68
69trap cleanup 0 2 3 6 9
70
71ip link add veth1 type veth peer name veth2
72ip link add veth3 type veth peer name veth4
73ip link add veth5 type veth peer name veth6
74ip link add veth7 type veth peer name veth8
75ip link add veth9 type veth peer name veth10
76
77ip link set veth1 netns ${NS1}
78ip link set veth2 netns ${NS2}
79ip link set veth3 netns ${NS2}
80ip link set veth4 netns ${NS3}
81ip link set veth5 netns ${NS3}
82ip link set veth6 netns ${NS4}
83ip link set veth7 netns ${NS4}
84ip link set veth8 netns ${NS5}
85ip link set veth9 netns ${NS5}
86ip link set veth10 netns ${NS6}
87
88ip netns exec ${NS1} ip link set dev veth1 up
89ip netns exec ${NS2} ip link set dev veth2 up
90ip netns exec ${NS2} ip link set dev veth3 up
91ip netns exec ${NS3} ip link set dev veth4 up
92ip netns exec ${NS3} ip link set dev veth5 up
93ip netns exec ${NS4} ip link set dev veth6 up
94ip netns exec ${NS4} ip link set dev veth7 up
95ip netns exec ${NS5} ip link set dev veth8 up
96ip netns exec ${NS5} ip link set dev veth9 up
97ip netns exec ${NS6} ip link set dev veth10 up
98ip netns exec ${NS6} ip link set dev lo up
99
100# All link scope addresses and routes required between veths
101ip netns exec ${NS1} ip -6 addr add fb00::12/16 dev veth1 scope link
102ip netns exec ${NS1} ip -6 route add fb00::21 dev veth1 scope link
103ip netns exec ${NS2} ip -6 addr add fb00::21/16 dev veth2 scope link
104ip netns exec ${NS2} ip -6 addr add fb00::34/16 dev veth3 scope link
105ip netns exec ${NS2} ip -6 route add fb00::43 dev veth3 scope link
106ip netns exec ${NS3} ip -6 route add fb00::65 dev veth5 scope link
107ip netns exec ${NS3} ip -6 addr add fb00::43/16 dev veth4 scope link
108ip netns exec ${NS3} ip -6 addr add fb00::56/16 dev veth5 scope link
109ip netns exec ${NS4} ip -6 addr add fb00::65/16 dev veth6 scope link
110ip netns exec ${NS4} ip -6 addr add fb00::78/16 dev veth7 scope link
111ip netns exec ${NS4} ip -6 route add fb00::87 dev veth7 scope link
112ip netns exec ${NS5} ip -6 addr add fb00::87/16 dev veth8 scope link
113ip netns exec ${NS5} ip -6 addr add fb00::910/16 dev veth9 scope link
114ip netns exec ${NS5} ip -6 route add fb00::109 dev veth9 scope link
115ip netns exec ${NS5} ip -6 route add fb00::109 table 117 dev veth9 scope link
116ip netns exec ${NS6} ip -6 addr add fb00::109/16 dev veth10 scope link
117
118ip netns exec ${NS1} ip -6 addr add fb00::1/16 dev lo
119ip netns exec ${NS1} ip -6 route add fb00::6 dev veth1 via fb00::21
120
121ip netns exec ${NS2} ip -6 route add fb00::6 encap bpf in obj ${BPF_FILE} sec encap_srh dev veth2
122ip netns exec ${NS2} ip -6 route add fd00::1 dev veth3 via fb00::43 scope link
123
124ip netns exec ${NS3} ip -6 route add fc42::1 dev veth5 via fb00::65
125ip netns exec ${NS3} ip -6 route add fd00::1 encap seg6local action End.BPF endpoint obj ${BPF_FILE} sec add_egr_x dev veth4
126
127ip netns exec ${NS4} ip -6 route add fd00::2 encap seg6local action End.BPF endpoint obj ${BPF_FILE} sec pop_egr dev veth6
128ip netns exec ${NS4} ip -6 addr add fc42::1 dev lo
129ip netns exec ${NS4} ip -6 route add fd00::3 dev veth7 via fb00::87
130
131ip netns exec ${NS5} ip -6 route add fd00::4 table 117 dev veth9 via fb00::109
132ip netns exec ${NS5} ip -6 route add fd00::3 encap seg6local action End.BPF endpoint obj ${BPF_FILE} sec inspect_t dev veth8
133
134ip netns exec ${NS6} ip -6 addr add fb00::6/16 dev lo
135ip netns exec ${NS6} ip -6 addr add fd00::4/16 dev lo
136
137ip netns exec ${NS1} sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
138ip netns exec ${NS2} sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
139ip netns exec ${NS3} sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
140ip netns exec ${NS4} sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
141ip netns exec ${NS5} sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
142
143ip netns exec ${NS6} sysctl net.ipv6.conf.all.seg6_enabled=1 > /dev/null
144ip netns exec ${NS6} sysctl net.ipv6.conf.lo.seg6_enabled=1 > /dev/null
145ip netns exec ${NS6} sysctl net.ipv6.conf.veth10.seg6_enabled=1 > /dev/null
146
147ip netns exec ${NS6} nc -l -6 -u -d 7330 > $TMP_FILE &
148ip netns exec ${NS1} bash -c "echo 'foobar' | nc -w0 -6 -u -p 2121 -s fb00::1 fb00::6 7330"
149sleep 5 # wait enough time to ensure the UDP datagram arrived to the last segment
150kill -TERM $!
151
152if [[ $(< $TMP_FILE) != "foobar" ]]; then
153	exit 1
154fi
155
156exit 0
157