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