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