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