Back to home page

OSCL-LXR

 
 

    


0001 #!/bin/bash
0002 # SPDX-License-Identifier: GPL-2.0
0003 # Author: Jesper Dangaard Brouer <hawk@kernel.org>
0004 
0005 # Kselftest framework requirement - SKIP code is 4.
0006 readonly KSFT_SKIP=4
0007 readonly NS1="ns1-$(mktemp -u XXXXXX)"
0008 readonly NS2="ns2-$(mktemp -u XXXXXX)"
0009 
0010 # Allow wrapper scripts to name test
0011 if [ -z "$TESTNAME" ]; then
0012     TESTNAME=xdp_vlan
0013 fi
0014 
0015 # Default XDP mode
0016 XDP_MODE=xdpgeneric
0017 
0018 usage() {
0019   echo "Testing XDP + TC eBPF VLAN manipulations: $TESTNAME"
0020   echo ""
0021   echo "Usage: $0 [-vfh]"
0022   echo "  -v | --verbose : Verbose"
0023   echo "  --flush        : Flush before starting (e.g. after --interactive)"
0024   echo "  --interactive  : Keep netns setup running after test-run"
0025   echo "  --mode=XXX     : Choose XDP mode (xdp | xdpgeneric | xdpdrv)"
0026   echo ""
0027 }
0028 
0029 valid_xdp_mode()
0030 {
0031         local mode=$1
0032 
0033         case "$mode" in
0034                 xdpgeneric | xdpdrv | xdp)
0035                         return 0
0036                         ;;
0037                 *)
0038                         return 1
0039         esac
0040 }
0041 
0042 cleanup()
0043 {
0044         local status=$?
0045 
0046         if [ "$status" = "0" ]; then
0047                 echo "selftests: $TESTNAME [PASS]";
0048         else
0049                 echo "selftests: $TESTNAME [FAILED]";
0050         fi
0051 
0052         if [ -n "$INTERACTIVE" ]; then
0053                 echo "Namespace setup still active explore with:"
0054                 echo " ip netns exec ${NS1} bash"
0055                 echo " ip netns exec ${NS2} bash"
0056                 exit $status
0057         fi
0058 
0059         set +e
0060         ip link del veth1 2> /dev/null
0061         ip netns del ${NS1} 2> /dev/null
0062         ip netns del ${NS2} 2> /dev/null
0063 }
0064 
0065 # Using external program "getopt" to get --long-options
0066 OPTIONS=$(getopt -o hvfi: \
0067     --long verbose,flush,help,interactive,debug,mode: -- "$@")
0068 if (( $? != 0 )); then
0069     usage
0070     echo "selftests: $TESTNAME [FAILED] Error calling getopt, unknown option?"
0071     exit 2
0072 fi
0073 eval set -- "$OPTIONS"
0074 
0075 ##  --- Parse command line arguments / parameters ---
0076 while true; do
0077         case "$1" in
0078             -v | --verbose)
0079                 export VERBOSE=yes
0080                 shift
0081                 ;;
0082             -i | --interactive | --debug )
0083                 INTERACTIVE=yes
0084                 shift
0085                 ;;
0086             -f | --flush )
0087                 cleanup
0088                 shift
0089                 ;;
0090             --mode )
0091                 shift
0092                 XDP_MODE=$1
0093                 shift
0094                 ;;
0095             -- )
0096                 shift
0097                 break
0098                 ;;
0099             -h | --help )
0100                 usage;
0101                 echo "selftests: $TESTNAME [SKIP] usage help info requested"
0102                 exit $KSFT_SKIP
0103                 ;;
0104             * )
0105                 shift
0106                 break
0107                 ;;
0108         esac
0109 done
0110 
0111 if [ "$EUID" -ne 0 ]; then
0112         echo "selftests: $TESTNAME [FAILED] need root privileges"
0113         exit 1
0114 fi
0115 
0116 valid_xdp_mode $XDP_MODE
0117 if [ $? -ne 0 ]; then
0118         echo "selftests: $TESTNAME [FAILED] unknown XDP mode ($XDP_MODE)"
0119         exit 1
0120 fi
0121 
0122 ip link set dev lo xdpgeneric off 2>/dev/null > /dev/null
0123 if [ $? -ne 0 ]; then
0124         echo "selftests: $TESTNAME [SKIP] need ip xdp support"
0125         exit $KSFT_SKIP
0126 fi
0127 
0128 # Interactive mode likely require us to cleanup netns
0129 if [ -n "$INTERACTIVE" ]; then
0130         ip link del veth1 2> /dev/null
0131         ip netns del ${NS1} 2> /dev/null
0132         ip netns del ${NS2} 2> /dev/null
0133 fi
0134 
0135 # Exit on failure
0136 set -e
0137 
0138 # Some shell-tools dependencies
0139 which ip > /dev/null
0140 which tc > /dev/null
0141 which ethtool > /dev/null
0142 
0143 # Make rest of shell verbose, showing comments as doc/info
0144 if [ -n "$VERBOSE" ]; then
0145     set -v
0146 fi
0147 
0148 # Create two namespaces
0149 ip netns add ${NS1}
0150 ip netns add ${NS2}
0151 
0152 # Run cleanup if failing or on kill
0153 trap cleanup 0 2 3 6 9
0154 
0155 # Create veth pair
0156 ip link add veth1 type veth peer name veth2
0157 
0158 # Move veth1 and veth2 into the respective namespaces
0159 ip link set veth1 netns ${NS1}
0160 ip link set veth2 netns ${NS2}
0161 
0162 # NOTICE: XDP require VLAN header inside packet payload
0163 #  - Thus, disable VLAN offloading driver features
0164 #  - For veth REMEMBER TX side VLAN-offload
0165 #
0166 # Disable rx-vlan-offload (mostly needed on ns1)
0167 ip netns exec ${NS1} ethtool -K veth1 rxvlan off
0168 ip netns exec ${NS2} ethtool -K veth2 rxvlan off
0169 #
0170 # Disable tx-vlan-offload (mostly needed on ns2)
0171 ip netns exec ${NS2} ethtool -K veth2 txvlan off
0172 ip netns exec ${NS1} ethtool -K veth1 txvlan off
0173 
0174 export IPADDR1=100.64.41.1
0175 export IPADDR2=100.64.41.2
0176 
0177 # In ns1/veth1 add IP-addr on plain net_device
0178 ip netns exec ${NS1} ip addr add ${IPADDR1}/24 dev veth1
0179 ip netns exec ${NS1} ip link set veth1 up
0180 
0181 # In ns2/veth2 create VLAN device
0182 export VLAN=4011
0183 export DEVNS2=veth2
0184 ip netns exec ${NS2} ip link add link $DEVNS2 name $DEVNS2.$VLAN type vlan id $VLAN
0185 ip netns exec ${NS2} ip addr add ${IPADDR2}/24 dev $DEVNS2.$VLAN
0186 ip netns exec ${NS2} ip link set $DEVNS2 up
0187 ip netns exec ${NS2} ip link set $DEVNS2.$VLAN up
0188 
0189 # Bringup lo in netns (to avoids confusing people using --interactive)
0190 ip netns exec ${NS1} ip link set lo up
0191 ip netns exec ${NS2} ip link set lo up
0192 
0193 # At this point, the hosts cannot reach each-other,
0194 # because ns2 are using VLAN tags on the packets.
0195 
0196 ip netns exec ${NS2} sh -c 'ping -W 1 -c 1 100.64.41.1 || echo "Success: First ping must fail"'
0197 
0198 
0199 # Now we can use the test_xdp_vlan.c program to pop/push these VLAN tags
0200 # ----------------------------------------------------------------------
0201 # In ns1: ingress use XDP to remove VLAN tags
0202 export DEVNS1=veth1
0203 export FILE=test_xdp_vlan.o
0204 
0205 # First test: Remove VLAN by setting VLAN ID 0, using "xdp_vlan_change"
0206 export XDP_PROG=xdp_vlan_change
0207 ip netns exec ${NS1} ip link set $DEVNS1 $XDP_MODE object $FILE section $XDP_PROG
0208 
0209 # In ns1: egress use TC to add back VLAN tag 4011
0210 #  (del cmd)
0211 #  tc qdisc del dev $DEVNS1 clsact 2> /dev/null
0212 #
0213 ip netns exec ${NS1} tc qdisc add dev $DEVNS1 clsact
0214 ip netns exec ${NS1} tc filter add dev $DEVNS1 egress \
0215   prio 1 handle 1 bpf da obj $FILE sec tc_vlan_push
0216 
0217 # Now the namespaces can reach each-other, test with ping:
0218 ip netns exec ${NS2} ping -i 0.2 -W 2 -c 2 $IPADDR1
0219 ip netns exec ${NS1} ping -i 0.2 -W 2 -c 2 $IPADDR2
0220 
0221 # Second test: Replace xdp prog, that fully remove vlan header
0222 #
0223 # Catch kernel bug for generic-XDP, that does didn't allow us to
0224 # remove a VLAN header, because skb->protocol still contain VLAN
0225 # ETH_P_8021Q indication, and this cause overwriting of our changes.
0226 #
0227 export XDP_PROG=xdp_vlan_remove_outer2
0228 ip netns exec ${NS1} ip link set $DEVNS1 $XDP_MODE off
0229 ip netns exec ${NS1} ip link set $DEVNS1 $XDP_MODE object $FILE section $XDP_PROG
0230 
0231 # Now the namespaces should still be able reach each-other, test with ping:
0232 ip netns exec ${NS2} ping -i 0.2 -W 2 -c 2 $IPADDR1
0233 ip netns exec ${NS1} ping -i 0.2 -W 2 -c 2 $IPADDR2