Merge tag 'drm-misc-next-2021-10-14' of git://anongit.freedesktop.org/drm/drm-misc...
[linux-2.6-microblaze.git] / tools / testing / selftests / bpf / test_lwt_ip_encap.sh
1 #!/bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3 #
4 # Setup/topology:
5 #
6 #    NS1             NS2             NS3
7 #   veth1 <---> veth2   veth3 <---> veth4 (the top route)
8 #   veth5 <---> veth6   veth7 <---> veth8 (the bottom route)
9 #
10 #   each vethN gets IPv[4|6]_N address
11 #
12 #   IPv*_SRC = IPv*_1
13 #   IPv*_DST = IPv*_4
14 #
15 #   all tests test pings from IPv*_SRC to IPv*_DST
16 #
17 #   by default, routes are configured to allow packets to go
18 #   IP*_1 <=> IP*_2 <=> IP*_3 <=> IP*_4 (the top route)
19 #
20 #   a GRE device is installed in NS3 with IPv*_GRE, and
21 #   NS1/NS2 are configured to route packets to IPv*_GRE via IP*_8
22 #   (the bottom route)
23 #
24 # Tests:
25 #
26 #   1. routes NS2->IPv*_DST are brought down, so the only way a ping
27 #      from IP*_SRC to IP*_DST can work is via IPv*_GRE
28 #
29 #   2a. in an egress test, a bpf LWT_XMIT program is installed on veth1
30 #       that encaps the packets with an IP/GRE header to route to IPv*_GRE
31 #
32 #       ping: SRC->[encap at veth1:egress]->GRE:decap->DST
33 #       ping replies go DST->SRC directly
34 #
35 #   2b. in an ingress test, a bpf LWT_IN program is installed on veth2
36 #       that encaps the packets with an IP/GRE header to route to IPv*_GRE
37 #
38 #       ping: SRC->[encap at veth2:ingress]->GRE:decap->DST
39 #       ping replies go DST->SRC directly
40
41 if [[ $EUID -ne 0 ]]; then
42         echo "This script must be run as root"
43         echo "FAIL"
44         exit 1
45 fi
46
47 readonly NS1="ns1-$(mktemp -u XXXXXX)"
48 readonly NS2="ns2-$(mktemp -u XXXXXX)"
49 readonly NS3="ns3-$(mktemp -u XXXXXX)"
50
51 readonly IPv4_1="172.16.1.100"
52 readonly IPv4_2="172.16.2.100"
53 readonly IPv4_3="172.16.3.100"
54 readonly IPv4_4="172.16.4.100"
55 readonly IPv4_5="172.16.5.100"
56 readonly IPv4_6="172.16.6.100"
57 readonly IPv4_7="172.16.7.100"
58 readonly IPv4_8="172.16.8.100"
59 readonly IPv4_GRE="172.16.16.100"
60
61 readonly IPv4_SRC=$IPv4_1
62 readonly IPv4_DST=$IPv4_4
63
64 readonly IPv6_1="fb01::1"
65 readonly IPv6_2="fb02::1"
66 readonly IPv6_3="fb03::1"
67 readonly IPv6_4="fb04::1"
68 readonly IPv6_5="fb05::1"
69 readonly IPv6_6="fb06::1"
70 readonly IPv6_7="fb07::1"
71 readonly IPv6_8="fb08::1"
72 readonly IPv6_GRE="fb10::1"
73
74 readonly IPv6_SRC=$IPv6_1
75 readonly IPv6_DST=$IPv6_4
76
77 TEST_STATUS=0
78 TESTS_SUCCEEDED=0
79 TESTS_FAILED=0
80
81 TMPFILE=""
82
83 process_test_results()
84 {
85         if [[ "${TEST_STATUS}" -eq 0 ]] ; then
86                 echo "PASS"
87                 TESTS_SUCCEEDED=$((TESTS_SUCCEEDED+1))
88         else
89                 echo "FAIL"
90                 TESTS_FAILED=$((TESTS_FAILED+1))
91         fi
92 }
93
94 print_test_summary_and_exit()
95 {
96         echo "passed tests: ${TESTS_SUCCEEDED}"
97         echo "failed tests: ${TESTS_FAILED}"
98         if [ "${TESTS_FAILED}" -eq "0" ] ; then
99                 exit 0
100         else
101                 exit 1
102         fi
103 }
104
105 setup()
106 {
107         set -e  # exit on error
108         TEST_STATUS=0
109
110         # create devices and namespaces
111         ip netns add "${NS1}"
112         ip netns add "${NS2}"
113         ip netns add "${NS3}"
114
115         # rp_filter gets confused by what these tests are doing, so disable it
116         ip netns exec ${NS1} sysctl -wq net.ipv4.conf.all.rp_filter=0
117         ip netns exec ${NS2} sysctl -wq net.ipv4.conf.all.rp_filter=0
118         ip netns exec ${NS3} sysctl -wq net.ipv4.conf.all.rp_filter=0
119         ip netns exec ${NS1} sysctl -wq net.ipv4.conf.default.rp_filter=0
120         ip netns exec ${NS2} sysctl -wq net.ipv4.conf.default.rp_filter=0
121         ip netns exec ${NS3} sysctl -wq net.ipv4.conf.default.rp_filter=0
122
123         ip link add veth1 type veth peer name veth2
124         ip link add veth3 type veth peer name veth4
125         ip link add veth5 type veth peer name veth6
126         ip link add veth7 type veth peer name veth8
127
128         ip netns exec ${NS2} sysctl -wq net.ipv4.ip_forward=1
129         ip netns exec ${NS2} sysctl -wq net.ipv6.conf.all.forwarding=1
130
131         ip link set veth1 netns ${NS1}
132         ip link set veth2 netns ${NS2}
133         ip link set veth3 netns ${NS2}
134         ip link set veth4 netns ${NS3}
135         ip link set veth5 netns ${NS1}
136         ip link set veth6 netns ${NS2}
137         ip link set veth7 netns ${NS2}
138         ip link set veth8 netns ${NS3}
139
140         if [ ! -z "${VRF}" ] ; then
141                 ip -netns ${NS1} link add red type vrf table 1001
142                 ip -netns ${NS1} link set red up
143                 ip -netns ${NS1} route add table 1001 unreachable default metric 8192
144                 ip -netns ${NS1} -6 route add table 1001 unreachable default metric 8192
145                 ip -netns ${NS1} link set veth1 vrf red
146                 ip -netns ${NS1} link set veth5 vrf red
147
148                 ip -netns ${NS2} link add red type vrf table 1001
149                 ip -netns ${NS2} link set red up
150                 ip -netns ${NS2} route add table 1001 unreachable default metric 8192
151                 ip -netns ${NS2} -6 route add table 1001 unreachable default metric 8192
152                 ip -netns ${NS2} link set veth2 vrf red
153                 ip -netns ${NS2} link set veth3 vrf red
154                 ip -netns ${NS2} link set veth6 vrf red
155                 ip -netns ${NS2} link set veth7 vrf red
156         fi
157
158         # configure addesses: the top route (1-2-3-4)
159         ip -netns ${NS1}    addr add ${IPv4_1}/24  dev veth1
160         ip -netns ${NS2}    addr add ${IPv4_2}/24  dev veth2
161         ip -netns ${NS2}    addr add ${IPv4_3}/24  dev veth3
162         ip -netns ${NS3}    addr add ${IPv4_4}/24  dev veth4
163         ip -netns ${NS1} -6 addr add ${IPv6_1}/128 nodad dev veth1
164         ip -netns ${NS2} -6 addr add ${IPv6_2}/128 nodad dev veth2
165         ip -netns ${NS2} -6 addr add ${IPv6_3}/128 nodad dev veth3
166         ip -netns ${NS3} -6 addr add ${IPv6_4}/128 nodad dev veth4
167
168         # configure addresses: the bottom route (5-6-7-8)
169         ip -netns ${NS1}    addr add ${IPv4_5}/24  dev veth5
170         ip -netns ${NS2}    addr add ${IPv4_6}/24  dev veth6
171         ip -netns ${NS2}    addr add ${IPv4_7}/24  dev veth7
172         ip -netns ${NS3}    addr add ${IPv4_8}/24  dev veth8
173         ip -netns ${NS1} -6 addr add ${IPv6_5}/128 nodad dev veth5
174         ip -netns ${NS2} -6 addr add ${IPv6_6}/128 nodad dev veth6
175         ip -netns ${NS2} -6 addr add ${IPv6_7}/128 nodad dev veth7
176         ip -netns ${NS3} -6 addr add ${IPv6_8}/128 nodad dev veth8
177
178         ip -netns ${NS1} link set dev veth1 up
179         ip -netns ${NS2} link set dev veth2 up
180         ip -netns ${NS2} link set dev veth3 up
181         ip -netns ${NS3} link set dev veth4 up
182         ip -netns ${NS1} link set dev veth5 up
183         ip -netns ${NS2} link set dev veth6 up
184         ip -netns ${NS2} link set dev veth7 up
185         ip -netns ${NS3} link set dev veth8 up
186
187         # configure routes: IP*_SRC -> veth1/IP*_2 (= top route) default;
188         # the bottom route to specific bottom addresses
189
190         # NS1
191         # top route
192         ip -netns ${NS1}    route add ${IPv4_2}/32  dev veth1 ${VRF}
193         ip -netns ${NS1}    route add default dev veth1 via ${IPv4_2} ${VRF}  # go top by default
194         ip -netns ${NS1} -6 route add ${IPv6_2}/128 dev veth1 ${VRF}
195         ip -netns ${NS1} -6 route add default dev veth1 via ${IPv6_2} ${VRF}  # go top by default
196         # bottom route
197         ip -netns ${NS1}    route add ${IPv4_6}/32  dev veth5 ${VRF}
198         ip -netns ${NS1}    route add ${IPv4_7}/32  dev veth5 via ${IPv4_6} ${VRF}
199         ip -netns ${NS1}    route add ${IPv4_8}/32  dev veth5 via ${IPv4_6} ${VRF}
200         ip -netns ${NS1} -6 route add ${IPv6_6}/128 dev veth5 ${VRF}
201         ip -netns ${NS1} -6 route add ${IPv6_7}/128 dev veth5 via ${IPv6_6} ${VRF}
202         ip -netns ${NS1} -6 route add ${IPv6_8}/128 dev veth5 via ${IPv6_6} ${VRF}
203
204         # NS2
205         # top route
206         ip -netns ${NS2}    route add ${IPv4_1}/32  dev veth2 ${VRF}
207         ip -netns ${NS2}    route add ${IPv4_4}/32  dev veth3 ${VRF}
208         ip -netns ${NS2} -6 route add ${IPv6_1}/128 dev veth2 ${VRF}
209         ip -netns ${NS2} -6 route add ${IPv6_4}/128 dev veth3 ${VRF}
210         # bottom route
211         ip -netns ${NS2}    route add ${IPv4_5}/32  dev veth6 ${VRF}
212         ip -netns ${NS2}    route add ${IPv4_8}/32  dev veth7 ${VRF}
213         ip -netns ${NS2} -6 route add ${IPv6_5}/128 dev veth6 ${VRF}
214         ip -netns ${NS2} -6 route add ${IPv6_8}/128 dev veth7 ${VRF}
215
216         # NS3
217         # top route
218         ip -netns ${NS3}    route add ${IPv4_3}/32  dev veth4
219         ip -netns ${NS3}    route add ${IPv4_1}/32  dev veth4 via ${IPv4_3}
220         ip -netns ${NS3}    route add ${IPv4_2}/32  dev veth4 via ${IPv4_3}
221         ip -netns ${NS3} -6 route add ${IPv6_3}/128 dev veth4
222         ip -netns ${NS3} -6 route add ${IPv6_1}/128 dev veth4 via ${IPv6_3}
223         ip -netns ${NS3} -6 route add ${IPv6_2}/128 dev veth4 via ${IPv6_3}
224         # bottom route
225         ip -netns ${NS3}    route add ${IPv4_7}/32  dev veth8
226         ip -netns ${NS3}    route add ${IPv4_5}/32  dev veth8 via ${IPv4_7}
227         ip -netns ${NS3}    route add ${IPv4_6}/32  dev veth8 via ${IPv4_7}
228         ip -netns ${NS3} -6 route add ${IPv6_7}/128 dev veth8
229         ip -netns ${NS3} -6 route add ${IPv6_5}/128 dev veth8 via ${IPv6_7}
230         ip -netns ${NS3} -6 route add ${IPv6_6}/128 dev veth8 via ${IPv6_7}
231
232         # configure IPv4 GRE device in NS3, and a route to it via the "bottom" route
233         ip -netns ${NS3} tunnel add gre_dev mode gre remote ${IPv4_1} local ${IPv4_GRE} ttl 255
234         ip -netns ${NS3} link set gre_dev up
235         ip -netns ${NS3} addr add ${IPv4_GRE} dev gre_dev
236         ip -netns ${NS1} route add ${IPv4_GRE}/32 dev veth5 via ${IPv4_6} ${VRF}
237         ip -netns ${NS2} route add ${IPv4_GRE}/32 dev veth7 via ${IPv4_8} ${VRF}
238
239
240         # configure IPv6 GRE device in NS3, and a route to it via the "bottom" route
241         ip -netns ${NS3} -6 tunnel add name gre6_dev mode ip6gre remote ${IPv6_1} local ${IPv6_GRE} ttl 255
242         ip -netns ${NS3} link set gre6_dev up
243         ip -netns ${NS3} -6 addr add ${IPv6_GRE} nodad dev gre6_dev
244         ip -netns ${NS1} -6 route add ${IPv6_GRE}/128 dev veth5 via ${IPv6_6} ${VRF}
245         ip -netns ${NS2} -6 route add ${IPv6_GRE}/128 dev veth7 via ${IPv6_8} ${VRF}
246
247         TMPFILE=$(mktemp /tmp/test_lwt_ip_encap.XXXXXX)
248
249         sleep 1  # reduce flakiness
250         set +e
251 }
252
253 cleanup()
254 {
255         if [ -f ${TMPFILE} ] ; then
256                 rm ${TMPFILE}
257         fi
258
259         ip netns del ${NS1} 2> /dev/null
260         ip netns del ${NS2} 2> /dev/null
261         ip netns del ${NS3} 2> /dev/null
262 }
263
264 trap cleanup EXIT
265
266 remove_routes_to_gredev()
267 {
268         ip -netns ${NS1} route del ${IPv4_GRE} dev veth5 ${VRF}
269         ip -netns ${NS2} route del ${IPv4_GRE} dev veth7 ${VRF}
270         ip -netns ${NS1} -6 route del ${IPv6_GRE}/128 dev veth5 ${VRF}
271         ip -netns ${NS2} -6 route del ${IPv6_GRE}/128 dev veth7 ${VRF}
272 }
273
274 add_unreachable_routes_to_gredev()
275 {
276         ip -netns ${NS1} route add unreachable ${IPv4_GRE}/32 ${VRF}
277         ip -netns ${NS2} route add unreachable ${IPv4_GRE}/32 ${VRF}
278         ip -netns ${NS1} -6 route add unreachable ${IPv6_GRE}/128 ${VRF}
279         ip -netns ${NS2} -6 route add unreachable ${IPv6_GRE}/128 ${VRF}
280 }
281
282 test_ping()
283 {
284         local readonly PROTO=$1
285         local readonly EXPECTED=$2
286         local RET=0
287
288         if [ "${PROTO}" == "IPv4" ] ; then
289                 ip netns exec ${NS1} ping  -c 1 -W 1 -I veth1 ${IPv4_DST} 2>&1 > /dev/null
290                 RET=$?
291         elif [ "${PROTO}" == "IPv6" ] ; then
292                 ip netns exec ${NS1} ping6 -c 1 -W 6 -I veth1 ${IPv6_DST} 2>&1 > /dev/null
293                 RET=$?
294         else
295                 echo "    test_ping: unknown PROTO: ${PROTO}"
296                 TEST_STATUS=1
297         fi
298
299         if [ "0" != "${RET}" ]; then
300                 RET=1
301         fi
302
303         if [ "${EXPECTED}" != "${RET}" ] ; then
304                 echo "    test_ping failed: expected: ${EXPECTED}; got ${RET}"
305                 TEST_STATUS=1
306         fi
307 }
308
309 test_gso()
310 {
311         local readonly PROTO=$1
312         local readonly PKT_SZ=5000
313         local IP_DST=""
314         : > ${TMPFILE}  # trim the capture file
315
316         # check that nc is present
317         command -v nc >/dev/null 2>&1 || \
318                 { echo >&2 "nc is not available: skipping TSO tests"; return; }
319
320         # listen on port 9000, capture TCP into $TMPFILE
321         if [ "${PROTO}" == "IPv4" ] ; then
322                 IP_DST=${IPv4_DST}
323                 ip netns exec ${NS3} bash -c \
324                         "nc -4 -l -p 9000 > ${TMPFILE} &"
325         elif [ "${PROTO}" == "IPv6" ] ; then
326                 IP_DST=${IPv6_DST}
327                 ip netns exec ${NS3} bash -c \
328                         "nc -6 -l -p 9000 > ${TMPFILE} &"
329                 RET=$?
330         else
331                 echo "    test_gso: unknown PROTO: ${PROTO}"
332                 TEST_STATUS=1
333         fi
334         sleep 1  # let nc start listening
335
336         # send a packet larger than MTU
337         ip netns exec ${NS1} bash -c \
338                 "dd if=/dev/zero bs=$PKT_SZ count=1 > /dev/tcp/${IP_DST}/9000 2>/dev/null"
339         sleep 2 # let the packet get delivered
340
341         # verify we received all expected bytes
342         SZ=$(stat -c %s ${TMPFILE})
343         if [ "$SZ" != "$PKT_SZ" ] ; then
344                 echo "    test_gso failed: ${PROTO}"
345                 TEST_STATUS=1
346         fi
347 }
348
349 test_egress()
350 {
351         local readonly ENCAP=$1
352         echo "starting egress ${ENCAP} encap test ${VRF}"
353         setup
354
355         # by default, pings work
356         test_ping IPv4 0
357         test_ping IPv6 0
358
359         # remove NS2->DST routes, ping fails
360         ip -netns ${NS2}    route del ${IPv4_DST}/32  dev veth3 ${VRF}
361         ip -netns ${NS2} -6 route del ${IPv6_DST}/128 dev veth3 ${VRF}
362         test_ping IPv4 1
363         test_ping IPv6 1
364
365         # install replacement routes (LWT/eBPF), pings succeed
366         if [ "${ENCAP}" == "IPv4" ] ; then
367                 ip -netns ${NS1} route add ${IPv4_DST} encap bpf xmit obj \
368                         test_lwt_ip_encap.o sec encap_gre dev veth1 ${VRF}
369                 ip -netns ${NS1} -6 route add ${IPv6_DST} encap bpf xmit obj \
370                         test_lwt_ip_encap.o sec encap_gre dev veth1 ${VRF}
371         elif [ "${ENCAP}" == "IPv6" ] ; then
372                 ip -netns ${NS1} route add ${IPv4_DST} encap bpf xmit obj \
373                         test_lwt_ip_encap.o sec encap_gre6 dev veth1 ${VRF}
374                 ip -netns ${NS1} -6 route add ${IPv6_DST} encap bpf xmit obj \
375                         test_lwt_ip_encap.o sec encap_gre6 dev veth1 ${VRF}
376         else
377                 echo "    unknown encap ${ENCAP}"
378                 TEST_STATUS=1
379         fi
380         test_ping IPv4 0
381         test_ping IPv6 0
382
383         # skip GSO tests with VRF: VRF routing needs properly assigned
384         # source IP/device, which is easy to do with ping and hard with dd/nc.
385         if [ -z "${VRF}" ] ; then
386                 test_gso IPv4
387                 test_gso IPv6
388         fi
389
390         # a negative test: remove routes to GRE devices: ping fails
391         remove_routes_to_gredev
392         test_ping IPv4 1
393         test_ping IPv6 1
394
395         # another negative test
396         add_unreachable_routes_to_gredev
397         test_ping IPv4 1
398         test_ping IPv6 1
399
400         cleanup
401         process_test_results
402 }
403
404 test_ingress()
405 {
406         local readonly ENCAP=$1
407         echo "starting ingress ${ENCAP} encap test ${VRF}"
408         setup
409
410         # need to wait a bit for IPv6 to autoconf, otherwise
411         # ping6 sometimes fails with "unable to bind to address"
412
413         # by default, pings work
414         test_ping IPv4 0
415         test_ping IPv6 0
416
417         # remove NS2->DST routes, pings fail
418         ip -netns ${NS2}    route del ${IPv4_DST}/32  dev veth3 ${VRF}
419         ip -netns ${NS2} -6 route del ${IPv6_DST}/128 dev veth3 ${VRF}
420         test_ping IPv4 1
421         test_ping IPv6 1
422
423         # install replacement routes (LWT/eBPF), pings succeed
424         if [ "${ENCAP}" == "IPv4" ] ; then
425                 ip -netns ${NS2} route add ${IPv4_DST} encap bpf in obj \
426                         test_lwt_ip_encap.o sec encap_gre dev veth2 ${VRF}
427                 ip -netns ${NS2} -6 route add ${IPv6_DST} encap bpf in obj \
428                         test_lwt_ip_encap.o sec encap_gre dev veth2 ${VRF}
429         elif [ "${ENCAP}" == "IPv6" ] ; then
430                 ip -netns ${NS2} route add ${IPv4_DST} encap bpf in obj \
431                         test_lwt_ip_encap.o sec encap_gre6 dev veth2 ${VRF}
432                 ip -netns ${NS2} -6 route add ${IPv6_DST} encap bpf in obj \
433                         test_lwt_ip_encap.o sec encap_gre6 dev veth2 ${VRF}
434         else
435                 echo "FAIL: unknown encap ${ENCAP}"
436                 TEST_STATUS=1
437         fi
438         test_ping IPv4 0
439         test_ping IPv6 0
440
441         # a negative test: remove routes to GRE devices: ping fails
442         remove_routes_to_gredev
443         test_ping IPv4 1
444         test_ping IPv6 1
445
446         # another negative test
447         add_unreachable_routes_to_gredev
448         test_ping IPv4 1
449         test_ping IPv6 1
450
451         cleanup
452         process_test_results
453 }
454
455 VRF=""
456 test_egress IPv4
457 test_egress IPv6
458 test_ingress IPv4
459 test_ingress IPv6
460
461 VRF="vrf red"
462 test_egress IPv4
463 test_egress IPv6
464 test_ingress IPv4
465 test_ingress IPv6
466
467 print_test_summary_and_exit