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