1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3# Author: Jesper Dangaard Brouer <hawk@kernel.org> 4 5# Kselftest framework requirement - SKIP code is 4. 6readonly KSFT_SKIP=4 7 8# Allow wrapper scripts to name test 9if [ -z "$TESTNAME" ]; then 10 TESTNAME=xdp_vlan 11fi 12 13# Default XDP mode 14XDP_MODE=xdpgeneric 15 16usage() { 17 echo "Testing XDP + TC eBPF VLAN manipulations: $TESTNAME" 18 echo "" 19 echo "Usage: $0 [-vfh]" 20 echo " -v | --verbose : Verbose" 21 echo " --flush : Flush before starting (e.g. after --interactive)" 22 echo " --interactive : Keep netns setup running after test-run" 23 echo " --mode=XXX : Choose XDP mode (xdp | xdpgeneric | xdpdrv)" 24 echo "" 25} 26 27valid_xdp_mode() 28{ 29 local mode=$1 30 31 case "$mode" in 32 xdpgeneric | xdpdrv | xdp) 33 return 0 34 ;; 35 *) 36 return 1 37 esac 38} 39 40cleanup() 41{ 42 local status=$? 43 44 if [ "$status" = "0" ]; then 45 echo "selftests: $TESTNAME [PASS]"; 46 else 47 echo "selftests: $TESTNAME [FAILED]"; 48 fi 49 50 if [ -n "$INTERACTIVE" ]; then 51 echo "Namespace setup still active explore with:" 52 echo " ip netns exec ns1 bash" 53 echo " ip netns exec ns2 bash" 54 exit $status 55 fi 56 57 set +e 58 ip link del veth1 2> /dev/null 59 ip netns del ns1 2> /dev/null 60 ip netns del ns2 2> /dev/null 61} 62 63# Using external program "getopt" to get --long-options 64OPTIONS=$(getopt -o hvfi: \ 65 --long verbose,flush,help,interactive,debug,mode: -- "$@") 66if (( $? != 0 )); then 67 usage 68 echo "selftests: $TESTNAME [FAILED] Error calling getopt, unknown option?" 69 exit 2 70fi 71eval set -- "$OPTIONS" 72 73## --- Parse command line arguments / parameters --- 74while true; do 75 case "$1" in 76 -v | --verbose) 77 export VERBOSE=yes 78 shift 79 ;; 80 -i | --interactive | --debug ) 81 INTERACTIVE=yes 82 shift 83 ;; 84 -f | --flush ) 85 cleanup 86 shift 87 ;; 88 --mode ) 89 shift 90 XDP_MODE=$1 91 shift 92 ;; 93 -- ) 94 shift 95 break 96 ;; 97 -h | --help ) 98 usage; 99 echo "selftests: $TESTNAME [SKIP] usage help info requested" 100 exit $KSFT_SKIP 101 ;; 102 * ) 103 shift 104 break 105 ;; 106 esac 107done 108 109if [ "$EUID" -ne 0 ]; then 110 echo "selftests: $TESTNAME [FAILED] need root privileges" 111 exit 1 112fi 113 114valid_xdp_mode $XDP_MODE 115if [ $? -ne 0 ]; then 116 echo "selftests: $TESTNAME [FAILED] unknown XDP mode ($XDP_MODE)" 117 exit 1 118fi 119 120ip link set dev lo xdpgeneric off 2>/dev/null > /dev/null 121if [ $? -ne 0 ]; then 122 echo "selftests: $TESTNAME [SKIP] need ip xdp support" 123 exit $KSFT_SKIP 124fi 125 126# Interactive mode likely require us to cleanup netns 127if [ -n "$INTERACTIVE" ]; then 128 ip link del veth1 2> /dev/null 129 ip netns del ns1 2> /dev/null 130 ip netns del ns2 2> /dev/null 131fi 132 133# Exit on failure 134set -e 135 136# Some shell-tools dependencies 137which ip > /dev/null 138which tc > /dev/null 139which ethtool > /dev/null 140 141# Make rest of shell verbose, showing comments as doc/info 142if [ -n "$VERBOSE" ]; then 143 set -v 144fi 145 146# Create two namespaces 147ip netns add ns1 148ip netns add ns2 149 150# Run cleanup if failing or on kill 151trap cleanup 0 2 3 6 9 152 153# Create veth pair 154ip link add veth1 type veth peer name veth2 155 156# Move veth1 and veth2 into the respective namespaces 157ip link set veth1 netns ns1 158ip link set veth2 netns ns2 159 160# NOTICE: XDP require VLAN header inside packet payload 161# - Thus, disable VLAN offloading driver features 162# - For veth REMEMBER TX side VLAN-offload 163# 164# Disable rx-vlan-offload (mostly needed on ns1) 165ip netns exec ns1 ethtool -K veth1 rxvlan off 166ip netns exec ns2 ethtool -K veth2 rxvlan off 167# 168# Disable tx-vlan-offload (mostly needed on ns2) 169ip netns exec ns2 ethtool -K veth2 txvlan off 170ip netns exec ns1 ethtool -K veth1 txvlan off 171 172export IPADDR1=100.64.41.1 173export IPADDR2=100.64.41.2 174 175# In ns1/veth1 add IP-addr on plain net_device 176ip netns exec ns1 ip addr add ${IPADDR1}/24 dev veth1 177ip netns exec ns1 ip link set veth1 up 178 179# In ns2/veth2 create VLAN device 180export VLAN=4011 181export DEVNS2=veth2 182ip netns exec ns2 ip link add link $DEVNS2 name $DEVNS2.$VLAN type vlan id $VLAN 183ip netns exec ns2 ip addr add ${IPADDR2}/24 dev $DEVNS2.$VLAN 184ip netns exec ns2 ip link set $DEVNS2 up 185ip netns exec ns2 ip link set $DEVNS2.$VLAN up 186 187# Bringup lo in netns (to avoids confusing people using --interactive) 188ip netns exec ns1 ip link set lo up 189ip netns exec ns2 ip link set lo up 190 191# At this point, the hosts cannot reach each-other, 192# because ns2 are using VLAN tags on the packets. 193 194ip netns exec ns2 sh -c 'ping -W 1 -c 1 100.64.41.1 || echo "Success: First ping must fail"' 195 196 197# Now we can use the test_xdp_vlan.c program to pop/push these VLAN tags 198# ---------------------------------------------------------------------- 199# In ns1: ingress use XDP to remove VLAN tags 200export DEVNS1=veth1 201export FILE=test_xdp_vlan.o 202 203# First test: Remove VLAN by setting VLAN ID 0, using "xdp_vlan_change" 204export XDP_PROG=xdp_vlan_change 205ip netns exec ns1 ip link set $DEVNS1 $XDP_MODE object $FILE section $XDP_PROG 206 207# In ns1: egress use TC to add back VLAN tag 4011 208# (del cmd) 209# tc qdisc del dev $DEVNS1 clsact 2> /dev/null 210# 211ip netns exec ns1 tc qdisc add dev $DEVNS1 clsact 212ip netns exec ns1 tc filter add dev $DEVNS1 egress \ 213 prio 1 handle 1 bpf da obj $FILE sec tc_vlan_push 214 215# Now the namespaces can reach each-other, test with ping: 216ip netns exec ns2 ping -i 0.2 -W 2 -c 2 $IPADDR1 217ip netns exec ns1 ping -i 0.2 -W 2 -c 2 $IPADDR2 218 219# Second test: Replace xdp prog, that fully remove vlan header 220# 221# Catch kernel bug for generic-XDP, that does didn't allow us to 222# remove a VLAN header, because skb->protocol still contain VLAN 223# ETH_P_8021Q indication, and this cause overwriting of our changes. 224# 225export XDP_PROG=xdp_vlan_remove_outer2 226ip netns exec ns1 ip link set $DEVNS1 $XDP_MODE off 227ip netns exec ns1 ip link set $DEVNS1 $XDP_MODE object $FILE section $XDP_PROG 228 229# Now the namespaces should still be able reach each-other, test with ping: 230ip netns exec ns2 ping -i 0.2 -W 2 -c 2 $IPADDR1 231ip netns exec ns1 ping -i 0.2 -W 2 -c 2 $IPADDR2 232