Linux-libre 5.7.6-gnu
[librecmc/linux-libre.git] / tools / testing / selftests / bpf / test_tc_tunnel.sh
1 #!/bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3 #
4 # In-place tunneling
5
6 # must match the port that the bpf program filters on
7 readonly port=8000
8
9 readonly ns_prefix="ns-$$-"
10 readonly ns1="${ns_prefix}1"
11 readonly ns2="${ns_prefix}2"
12
13 readonly ns1_v4=192.168.1.1
14 readonly ns2_v4=192.168.1.2
15 readonly ns1_v6=fd::1
16 readonly ns2_v6=fd::2
17
18 # Must match port used by bpf program
19 readonly udpport=5555
20 # MPLSoverUDP
21 readonly mplsudpport=6635
22 readonly mplsproto=137
23
24 readonly infile="$(mktemp)"
25 readonly outfile="$(mktemp)"
26
27 setup() {
28         ip netns add "${ns1}"
29         ip netns add "${ns2}"
30
31         ip link add dev veth1 mtu 1500 netns "${ns1}" type veth \
32               peer name veth2 mtu 1500 netns "${ns2}"
33
34         ip netns exec "${ns1}" ethtool -K veth1 tso off
35
36         ip -netns "${ns1}" link set veth1 up
37         ip -netns "${ns2}" link set veth2 up
38
39         ip -netns "${ns1}" -4 addr add "${ns1_v4}/24" dev veth1
40         ip -netns "${ns2}" -4 addr add "${ns2_v4}/24" dev veth2
41         ip -netns "${ns1}" -6 addr add "${ns1_v6}/64" dev veth1 nodad
42         ip -netns "${ns2}" -6 addr add "${ns2_v6}/64" dev veth2 nodad
43
44         # clamp route to reserve room for tunnel headers
45         ip -netns "${ns1}" -4 route flush table main
46         ip -netns "${ns1}" -6 route flush table main
47         ip -netns "${ns1}" -4 route add "${ns2_v4}" mtu 1458 dev veth1
48         ip -netns "${ns1}" -6 route add "${ns2_v6}" mtu 1438 dev veth1
49
50         sleep 1
51
52         dd if=/dev/urandom of="${infile}" bs="${datalen}" count=1 status=none
53 }
54
55 cleanup() {
56         ip netns del "${ns2}"
57         ip netns del "${ns1}"
58
59         if [[ -f "${outfile}" ]]; then
60                 rm "${outfile}"
61         fi
62         if [[ -f "${infile}" ]]; then
63                 rm "${infile}"
64         fi
65
66         if [[ -n $server_pid ]]; then
67                 kill $server_pid 2> /dev/null
68         fi
69 }
70
71 server_listen() {
72         ip netns exec "${ns2}" nc "${netcat_opt}" -l -p "${port}" > "${outfile}" &
73         server_pid=$!
74         sleep 0.2
75 }
76
77 client_connect() {
78         ip netns exec "${ns1}" timeout 2 nc "${netcat_opt}" -w 1 "${addr2}" "${port}" < "${infile}"
79         echo $?
80 }
81
82 verify_data() {
83         wait "${server_pid}"
84         server_pid=
85         # sha1sum returns two fields [sha1] [filepath]
86         # convert to bash array and access first elem
87         insum=($(sha1sum ${infile}))
88         outsum=($(sha1sum ${outfile}))
89         if [[ "${insum[0]}" != "${outsum[0]}" ]]; then
90                 echo "data mismatch"
91                 exit 1
92         fi
93 }
94
95 set -e
96
97 # no arguments: automated test, run all
98 if [[ "$#" -eq "0" ]]; then
99         echo "ipip"
100         $0 ipv4 ipip none 100
101
102         echo "ip6ip6"
103         $0 ipv6 ip6tnl none 100
104
105         echo "sit"
106         $0 ipv6 sit none 100
107
108         for mac in none mpls eth ; do
109                 echo "ip gre $mac"
110                 $0 ipv4 gre $mac 100
111
112                 echo "ip6 gre $mac"
113                 $0 ipv6 ip6gre $mac 100
114
115                 echo "ip gre $mac gso"
116                 $0 ipv4 gre $mac 2000
117
118                 echo "ip6 gre $mac gso"
119                 $0 ipv6 ip6gre $mac 2000
120
121                 echo "ip udp $mac"
122                 $0 ipv4 udp $mac 100
123
124                 echo "ip6 udp $mac"
125                 $0 ipv6 ip6udp $mac 100
126
127                 echo "ip udp $mac gso"
128                 $0 ipv4 udp $mac 2000
129
130                 echo "ip6 udp $mac gso"
131                 $0 ipv6 ip6udp $mac 2000
132         done
133
134         echo "OK. All tests passed"
135         exit 0
136 fi
137
138 if [[ "$#" -ne "4" ]]; then
139         echo "Usage: $0"
140         echo "   or: $0 <ipv4|ipv6> <tuntype> <none|mpls|eth> <data_len>"
141         exit 1
142 fi
143
144 case "$1" in
145 "ipv4")
146         readonly addr1="${ns1_v4}"
147         readonly addr2="${ns2_v4}"
148         readonly ipproto=4
149         readonly netcat_opt=-${ipproto}
150         readonly foumod=fou
151         readonly foutype=ipip
152         readonly fouproto=4
153         readonly fouproto_mpls=${mplsproto}
154         readonly gretaptype=gretap
155         ;;
156 "ipv6")
157         readonly addr1="${ns1_v6}"
158         readonly addr2="${ns2_v6}"
159         readonly ipproto=6
160         readonly netcat_opt=-${ipproto}
161         readonly foumod=fou6
162         readonly foutype=ip6tnl
163         readonly fouproto="41 -6"
164         readonly fouproto_mpls="${mplsproto} -6"
165         readonly gretaptype=ip6gretap
166         ;;
167 *)
168         echo "unknown arg: $1"
169         exit 1
170         ;;
171 esac
172
173 readonly tuntype=$2
174 readonly mac=$3
175 readonly datalen=$4
176
177 echo "encap ${addr1} to ${addr2}, type ${tuntype}, mac ${mac} len ${datalen}"
178
179 trap cleanup EXIT
180
181 setup
182
183 # basic communication works
184 echo "test basic connectivity"
185 server_listen
186 client_connect
187 verify_data
188
189 # clientside, insert bpf program to encap all TCP to port ${port}
190 # client can no longer connect
191 ip netns exec "${ns1}" tc qdisc add dev veth1 clsact
192 ip netns exec "${ns1}" tc filter add dev veth1 egress \
193         bpf direct-action object-file ./test_tc_tunnel.o \
194         section "encap_${tuntype}_${mac}"
195 echo "test bpf encap without decap (expect failure)"
196 server_listen
197 ! client_connect
198
199 if [[ "$tuntype" =~ "udp" ]]; then
200         # Set up fou tunnel.
201         ttype="${foutype}"
202         targs="encap fou encap-sport auto encap-dport $udpport"
203         # fou may be a module; allow this to fail.
204         modprobe "${foumod}" ||true
205         if [[ "$mac" == "mpls" ]]; then
206                 dport=${mplsudpport}
207                 dproto=${fouproto_mpls}
208                 tmode="mode any ttl 255"
209         else
210                 dport=${udpport}
211                 dproto=${fouproto}
212         fi
213         ip netns exec "${ns2}" ip fou add port $dport ipproto ${dproto}
214         targs="encap fou encap-sport auto encap-dport $dport"
215 elif [[ "$tuntype" =~ "gre" && "$mac" == "eth" ]]; then
216         ttype=$gretaptype
217 else
218         ttype=$tuntype
219         targs=""
220 fi
221
222 # tunnel address family differs from inner for SIT
223 if [[ "${tuntype}" == "sit" ]]; then
224         link_addr1="${ns1_v4}"
225         link_addr2="${ns2_v4}"
226 else
227         link_addr1="${addr1}"
228         link_addr2="${addr2}"
229 fi
230
231 # serverside, insert decap module
232 # server is still running
233 # client can connect again
234 ip netns exec "${ns2}" ip link add name testtun0 type "${ttype}" \
235         ${tmode} remote "${link_addr1}" local "${link_addr2}" $targs
236
237 expect_tun_fail=0
238
239 if [[ "$tuntype" == "ip6udp" && "$mac" == "mpls" ]]; then
240         # No support for MPLS IPv6 fou tunnel; expect failure.
241         expect_tun_fail=1
242 elif [[ "$tuntype" =~ "udp" && "$mac" == "eth" ]]; then
243         # No support for TEB fou tunnel; expect failure.
244         expect_tun_fail=1
245 elif [[ "$tuntype" =~ "gre" && "$mac" == "eth" ]]; then
246         # Share ethernet address between tunnel/veth2 so L2 decap works.
247         ethaddr=$(ip netns exec "${ns2}" ip link show veth2 | \
248                   awk '/ether/ { print $2 }')
249         ip netns exec "${ns2}" ip link set testtun0 address $ethaddr
250 elif [[ "$mac" == "mpls" ]]; then
251         modprobe mpls_iptunnel ||true
252         modprobe mpls_gso ||true
253         ip netns exec "${ns2}" sysctl -qw net.mpls.platform_labels=65536
254         ip netns exec "${ns2}" ip -f mpls route add 1000 dev lo
255         ip netns exec "${ns2}" ip link set lo up
256         ip netns exec "${ns2}" sysctl -qw net.mpls.conf.testtun0.input=1
257         ip netns exec "${ns2}" sysctl -qw net.ipv4.conf.lo.rp_filter=0
258 fi
259
260 # Because packets are decapped by the tunnel they arrive on testtun0 from
261 # the IP stack perspective.  Ensure reverse path filtering is disabled
262 # otherwise we drop the TCP SYN as arriving on testtun0 instead of the
263 # expected veth2 (veth2 is where 192.168.1.2 is configured).
264 ip netns exec "${ns2}" sysctl -qw net.ipv4.conf.all.rp_filter=0
265 # rp needs to be disabled for both all and testtun0 as the rp value is
266 # selected as the max of the "all" and device-specific values.
267 ip netns exec "${ns2}" sysctl -qw net.ipv4.conf.testtun0.rp_filter=0
268 ip netns exec "${ns2}" ip link set dev testtun0 up
269 if [[ "$expect_tun_fail" == 1 ]]; then
270         # This tunnel mode is not supported, so we expect failure.
271         echo "test bpf encap with tunnel device decap (expect failure)"
272         ! client_connect
273 else
274         echo "test bpf encap with tunnel device decap"
275         client_connect
276         verify_data
277         server_listen
278 fi
279
280 # bpf_skb_net_shrink does not take tunnel flags yet, cannot update L3.
281 if [[ "${tuntype}" == "sit" ]]; then
282         echo OK
283         exit 0
284 fi
285
286 # serverside, use BPF for decap
287 ip netns exec "${ns2}" ip link del dev testtun0
288 ip netns exec "${ns2}" tc qdisc add dev veth2 clsact
289 ip netns exec "${ns2}" tc filter add dev veth2 ingress \
290         bpf direct-action object-file ./test_tc_tunnel.o section decap
291 echo "test bpf encap with bpf decap"
292 client_connect
293 verify_data
294
295 echo OK