Back to home page

OSCL-LXR

 
 

    


0001 #!/bin/bash
0002 # SPDX-License-Identifier: GPL-2.0
0003 #
0004 # In-place tunneling
0005 
0006 # must match the port that the bpf program filters on
0007 readonly port=8000
0008 
0009 readonly ns_prefix="ns-$$-"
0010 readonly ns1="${ns_prefix}1"
0011 readonly ns2="${ns_prefix}2"
0012 
0013 readonly ns1_v4=192.168.1.1
0014 readonly ns2_v4=192.168.1.2
0015 readonly ns1_v6=fd::1
0016 readonly ns2_v6=fd::2
0017 
0018 # Must match port used by bpf program
0019 readonly udpport=5555
0020 # MPLSoverUDP
0021 readonly mplsudpport=6635
0022 readonly mplsproto=137
0023 
0024 readonly infile="$(mktemp)"
0025 readonly outfile="$(mktemp)"
0026 
0027 setup() {
0028         ip netns add "${ns1}"
0029         ip netns add "${ns2}"
0030 
0031         ip link add dev veth1 mtu 1500 netns "${ns1}" type veth \
0032               peer name veth2 mtu 1500 netns "${ns2}"
0033 
0034         ip netns exec "${ns1}" ethtool -K veth1 tso off
0035 
0036         ip -netns "${ns1}" link set veth1 up
0037         ip -netns "${ns2}" link set veth2 up
0038 
0039         ip -netns "${ns1}" -4 addr add "${ns1_v4}/24" dev veth1
0040         ip -netns "${ns2}" -4 addr add "${ns2_v4}/24" dev veth2
0041         ip -netns "${ns1}" -6 addr add "${ns1_v6}/64" dev veth1 nodad
0042         ip -netns "${ns2}" -6 addr add "${ns2_v6}/64" dev veth2 nodad
0043 
0044         # clamp route to reserve room for tunnel headers
0045         ip -netns "${ns1}" -4 route flush table main
0046         ip -netns "${ns1}" -6 route flush table main
0047         ip -netns "${ns1}" -4 route add "${ns2_v4}" mtu 1450 dev veth1
0048         ip -netns "${ns1}" -6 route add "${ns2_v6}" mtu 1430 dev veth1
0049 
0050         sleep 1
0051 
0052         dd if=/dev/urandom of="${infile}" bs="${datalen}" count=1 status=none
0053 }
0054 
0055 cleanup() {
0056         ip netns del "${ns2}"
0057         ip netns del "${ns1}"
0058 
0059         if [[ -f "${outfile}" ]]; then
0060                 rm "${outfile}"
0061         fi
0062         if [[ -f "${infile}" ]]; then
0063                 rm "${infile}"
0064         fi
0065 
0066         if [[ -n $server_pid ]]; then
0067                 kill $server_pid 2> /dev/null
0068         fi
0069 }
0070 
0071 server_listen() {
0072         ip netns exec "${ns2}" nc "${netcat_opt}" -l "${port}" > "${outfile}" &
0073         server_pid=$!
0074         sleep 0.2
0075 }
0076 
0077 client_connect() {
0078         ip netns exec "${ns1}" timeout 2 nc "${netcat_opt}" -w 1 "${addr2}" "${port}" < "${infile}"
0079         echo $?
0080 }
0081 
0082 verify_data() {
0083         wait "${server_pid}"
0084         server_pid=
0085         # sha1sum returns two fields [sha1] [filepath]
0086         # convert to bash array and access first elem
0087         insum=($(sha1sum ${infile}))
0088         outsum=($(sha1sum ${outfile}))
0089         if [[ "${insum[0]}" != "${outsum[0]}" ]]; then
0090                 echo "data mismatch"
0091                 exit 1
0092         fi
0093 }
0094 
0095 set -e
0096 
0097 # no arguments: automated test, run all
0098 if [[ "$#" -eq "0" ]]; then
0099         echo "ipip"
0100         $0 ipv4 ipip none 100
0101 
0102         echo "ip6ip6"
0103         $0 ipv6 ip6tnl none 100
0104 
0105         echo "sit"
0106         $0 ipv6 sit none 100
0107 
0108         echo "ip4 vxlan"
0109         $0 ipv4 vxlan eth 2000
0110 
0111         echo "ip6 vxlan"
0112         $0 ipv6 ip6vxlan eth 2000
0113 
0114         for mac in none mpls eth ; do
0115                 echo "ip gre $mac"
0116                 $0 ipv4 gre $mac 100
0117 
0118                 echo "ip6 gre $mac"
0119                 $0 ipv6 ip6gre $mac 100
0120 
0121                 echo "ip gre $mac gso"
0122                 $0 ipv4 gre $mac 2000
0123 
0124                 echo "ip6 gre $mac gso"
0125                 $0 ipv6 ip6gre $mac 2000
0126 
0127                 echo "ip udp $mac"
0128                 $0 ipv4 udp $mac 100
0129 
0130                 echo "ip6 udp $mac"
0131                 $0 ipv6 ip6udp $mac 100
0132 
0133                 echo "ip udp $mac gso"
0134                 $0 ipv4 udp $mac 2000
0135 
0136                 echo "ip6 udp $mac gso"
0137                 $0 ipv6 ip6udp $mac 2000
0138         done
0139 
0140         echo "OK. All tests passed"
0141         exit 0
0142 fi
0143 
0144 if [[ "$#" -ne "4" ]]; then
0145         echo "Usage: $0"
0146         echo "   or: $0 <ipv4|ipv6> <tuntype> <none|mpls|eth> <data_len>"
0147         exit 1
0148 fi
0149 
0150 case "$1" in
0151 "ipv4")
0152         readonly addr1="${ns1_v4}"
0153         readonly addr2="${ns2_v4}"
0154         readonly ipproto=4
0155         readonly netcat_opt=-${ipproto}
0156         readonly foumod=fou
0157         readonly foutype=ipip
0158         readonly fouproto=4
0159         readonly fouproto_mpls=${mplsproto}
0160         readonly gretaptype=gretap
0161         ;;
0162 "ipv6")
0163         readonly addr1="${ns1_v6}"
0164         readonly addr2="${ns2_v6}"
0165         readonly ipproto=6
0166         readonly netcat_opt=-${ipproto}
0167         readonly foumod=fou6
0168         readonly foutype=ip6tnl
0169         readonly fouproto="41 -6"
0170         readonly fouproto_mpls="${mplsproto} -6"
0171         readonly gretaptype=ip6gretap
0172         ;;
0173 *)
0174         echo "unknown arg: $1"
0175         exit 1
0176         ;;
0177 esac
0178 
0179 readonly tuntype=$2
0180 readonly mac=$3
0181 readonly datalen=$4
0182 
0183 echo "encap ${addr1} to ${addr2}, type ${tuntype}, mac ${mac} len ${datalen}"
0184 
0185 trap cleanup EXIT
0186 
0187 setup
0188 
0189 # basic communication works
0190 echo "test basic connectivity"
0191 server_listen
0192 client_connect
0193 verify_data
0194 
0195 # clientside, insert bpf program to encap all TCP to port ${port}
0196 # client can no longer connect
0197 ip netns exec "${ns1}" tc qdisc add dev veth1 clsact
0198 ip netns exec "${ns1}" tc filter add dev veth1 egress \
0199         bpf direct-action object-file ./test_tc_tunnel.o \
0200         section "encap_${tuntype}_${mac}"
0201 echo "test bpf encap without decap (expect failure)"
0202 server_listen
0203 ! client_connect
0204 
0205 if [[ "$tuntype" =~ "udp" ]]; then
0206         # Set up fou tunnel.
0207         ttype="${foutype}"
0208         targs="encap fou encap-sport auto encap-dport $udpport"
0209         # fou may be a module; allow this to fail.
0210         modprobe "${foumod}" ||true
0211         if [[ "$mac" == "mpls" ]]; then
0212                 dport=${mplsudpport}
0213                 dproto=${fouproto_mpls}
0214                 tmode="mode any ttl 255"
0215         else
0216                 dport=${udpport}
0217                 dproto=${fouproto}
0218         fi
0219         ip netns exec "${ns2}" ip fou add port $dport ipproto ${dproto}
0220         targs="encap fou encap-sport auto encap-dport $dport"
0221 elif [[ "$tuntype" =~ "gre" && "$mac" == "eth" ]]; then
0222         ttype=$gretaptype
0223 elif [[ "$tuntype" =~ "vxlan" && "$mac" == "eth" ]]; then
0224         ttype="vxlan"
0225         targs="id 1 dstport 8472 udp6zerocsumrx"
0226 else
0227         ttype=$tuntype
0228         targs=""
0229 fi
0230 
0231 # tunnel address family differs from inner for SIT
0232 if [[ "${tuntype}" == "sit" ]]; then
0233         link_addr1="${ns1_v4}"
0234         link_addr2="${ns2_v4}"
0235 else
0236         link_addr1="${addr1}"
0237         link_addr2="${addr2}"
0238 fi
0239 
0240 # serverside, insert decap module
0241 # server is still running
0242 # client can connect again
0243 ip netns exec "${ns2}" ip link add name testtun0 type "${ttype}" \
0244         ${tmode} remote "${link_addr1}" local "${link_addr2}" $targs
0245 
0246 expect_tun_fail=0
0247 
0248 if [[ "$tuntype" == "ip6udp" && "$mac" == "mpls" ]]; then
0249         # No support for MPLS IPv6 fou tunnel; expect failure.
0250         expect_tun_fail=1
0251 elif [[ "$tuntype" =~ "udp" && "$mac" == "eth" ]]; then
0252         # No support for TEB fou tunnel; expect failure.
0253         expect_tun_fail=1
0254 elif [[ "$tuntype" =~ (gre|vxlan) && "$mac" == "eth" ]]; then
0255         # Share ethernet address between tunnel/veth2 so L2 decap works.
0256         ethaddr=$(ip netns exec "${ns2}" ip link show veth2 | \
0257                   awk '/ether/ { print $2 }')
0258         ip netns exec "${ns2}" ip link set testtun0 address $ethaddr
0259 elif [[ "$mac" == "mpls" ]]; then
0260         modprobe mpls_iptunnel ||true
0261         modprobe mpls_gso ||true
0262         ip netns exec "${ns2}" sysctl -qw net.mpls.platform_labels=65536
0263         ip netns exec "${ns2}" ip -f mpls route add 1000 dev lo
0264         ip netns exec "${ns2}" ip link set lo up
0265         ip netns exec "${ns2}" sysctl -qw net.mpls.conf.testtun0.input=1
0266         ip netns exec "${ns2}" sysctl -qw net.ipv4.conf.lo.rp_filter=0
0267 fi
0268 
0269 # Because packets are decapped by the tunnel they arrive on testtun0 from
0270 # the IP stack perspective.  Ensure reverse path filtering is disabled
0271 # otherwise we drop the TCP SYN as arriving on testtun0 instead of the
0272 # expected veth2 (veth2 is where 192.168.1.2 is configured).
0273 ip netns exec "${ns2}" sysctl -qw net.ipv4.conf.all.rp_filter=0
0274 # rp needs to be disabled for both all and testtun0 as the rp value is
0275 # selected as the max of the "all" and device-specific values.
0276 ip netns exec "${ns2}" sysctl -qw net.ipv4.conf.testtun0.rp_filter=0
0277 ip netns exec "${ns2}" ip link set dev testtun0 up
0278 if [[ "$expect_tun_fail" == 1 ]]; then
0279         # This tunnel mode is not supported, so we expect failure.
0280         echo "test bpf encap with tunnel device decap (expect failure)"
0281         ! client_connect
0282 else
0283         echo "test bpf encap with tunnel device decap"
0284         client_connect
0285         verify_data
0286         server_listen
0287 fi
0288 
0289 # bpf_skb_net_shrink does not take tunnel flags yet, cannot update L3.
0290 if [[ "${tuntype}" == "sit" ]]; then
0291         echo OK
0292         exit 0
0293 fi
0294 
0295 # serverside, use BPF for decap
0296 ip netns exec "${ns2}" ip link del dev testtun0
0297 ip netns exec "${ns2}" tc qdisc add dev veth2 clsact
0298 ip netns exec "${ns2}" tc filter add dev veth2 ingress \
0299         bpf direct-action object-file ./test_tc_tunnel.o section decap
0300 echo "test bpf encap with bpf decap"
0301 client_connect
0302 verify_data
0303 
0304 echo OK