234 lines · bash
1#!/bin/bash2# SPDX-License-Identifier: GPL-2.03# Author: Jesper Dangaard Brouer <hawk@kernel.org>4 5# Kselftest framework requirement - SKIP code is 4.6readonly KSFT_SKIP=47readonly NS1="ns1-$(mktemp -u XXXXXX)"8readonly NS2="ns2-$(mktemp -u XXXXXX)"9 10# Allow wrapper scripts to name test11if [ -z "$TESTNAME" ]; then12 TESTNAME=xdp_vlan13fi14 15# Default XDP mode16XDP_MODE=xdpgeneric17 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=$132 33 case "$mode" in34 xdpgeneric | xdpdrv | xdp)35 return 036 ;;37 *)38 return 139 esac40}41 42cleanup()43{44 local status=$?45 46 if [ "$status" = "0" ]; then47 echo "selftests: $TESTNAME [PASS]";48 else49 echo "selftests: $TESTNAME [FAILED]";50 fi51 52 if [ -n "$INTERACTIVE" ]; then53 echo "Namespace setup still active explore with:"54 echo " ip netns exec ${NS1} bash"55 echo " ip netns exec ${NS2} bash"56 exit $status57 fi58 59 set +e60 ip link del veth1 2> /dev/null61 ip netns del ${NS1} 2> /dev/null62 ip netns del ${NS2} 2> /dev/null63}64 65# Using external program "getopt" to get --long-options66OPTIONS=$(getopt -o hvfi: \67 --long verbose,flush,help,interactive,debug,mode: -- "$@")68if (( $? != 0 )); then69 usage70 echo "selftests: $TESTNAME [FAILED] Error calling getopt, unknown option?"71 exit 272fi73eval set -- "$OPTIONS"74 75## --- Parse command line arguments / parameters ---76while true; do77 case "$1" in78 -v | --verbose)79 export VERBOSE=yes80 shift81 ;;82 -i | --interactive | --debug )83 INTERACTIVE=yes84 shift85 ;;86 -f | --flush )87 cleanup88 shift89 ;;90 --mode )91 shift92 XDP_MODE=$193 shift94 ;;95 -- )96 shift97 break98 ;;99 -h | --help )100 usage;101 echo "selftests: $TESTNAME [SKIP] usage help info requested"102 exit $KSFT_SKIP103 ;;104 * )105 shift106 break107 ;;108 esac109done110 111if [ "$EUID" -ne 0 ]; then112 echo "selftests: $TESTNAME [FAILED] need root privileges"113 exit 1114fi115 116valid_xdp_mode $XDP_MODE117if [ $? -ne 0 ]; then118 echo "selftests: $TESTNAME [FAILED] unknown XDP mode ($XDP_MODE)"119 exit 1120fi121 122ip link set dev lo xdpgeneric off 2>/dev/null > /dev/null123if [ $? -ne 0 ]; then124 echo "selftests: $TESTNAME [SKIP] need ip xdp support"125 exit $KSFT_SKIP126fi127 128# Interactive mode likely require us to cleanup netns129if [ -n "$INTERACTIVE" ]; then130 ip link del veth1 2> /dev/null131 ip netns del ${NS1} 2> /dev/null132 ip netns del ${NS2} 2> /dev/null133fi134 135# Exit on failure136set -e137 138# Some shell-tools dependencies139which ip > /dev/null140which tc > /dev/null141which ethtool > /dev/null142 143# Make rest of shell verbose, showing comments as doc/info144if [ -n "$VERBOSE" ]; then145 set -v146fi147 148# Create two namespaces149ip netns add ${NS1}150ip netns add ${NS2}151 152# Run cleanup if failing or on kill153trap cleanup 0 2 3 6 9154 155# Create veth pair156ip link add veth1 type veth peer name veth2157 158# Move veth1 and veth2 into the respective namespaces159ip link set veth1 netns ${NS1}160ip link set veth2 netns ${NS2}161 162# NOTICE: XDP require VLAN header inside packet payload163# - Thus, disable VLAN offloading driver features164# - For veth REMEMBER TX side VLAN-offload165#166# Disable rx-vlan-offload (mostly needed on ns1)167ip netns exec ${NS1} ethtool -K veth1 rxvlan off168ip netns exec ${NS2} ethtool -K veth2 rxvlan off169#170# Disable tx-vlan-offload (mostly needed on ns2)171ip netns exec ${NS2} ethtool -K veth2 txvlan off172ip netns exec ${NS1} ethtool -K veth1 txvlan off173 174export IPADDR1=100.64.41.1175export IPADDR2=100.64.41.2176 177# In ns1/veth1 add IP-addr on plain net_device178ip netns exec ${NS1} ip addr add ${IPADDR1}/24 dev veth1179ip netns exec ${NS1} ip link set veth1 up180 181# In ns2/veth2 create VLAN device182export VLAN=4011183export DEVNS2=veth2184ip netns exec ${NS2} ip link add link $DEVNS2 name $DEVNS2.$VLAN type vlan id $VLAN185ip netns exec ${NS2} ip addr add ${IPADDR2}/24 dev $DEVNS2.$VLAN186ip netns exec ${NS2} ip link set $DEVNS2 up187ip netns exec ${NS2} ip link set $DEVNS2.$VLAN up188 189# Bringup lo in netns (to avoids confusing people using --interactive)190ip netns exec ${NS1} ip link set lo up191ip netns exec ${NS2} ip link set lo up192 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 tags200# ----------------------------------------------------------------------201# In ns1: ingress use XDP to remove VLAN tags202export DEVNS1=veth1203export BPF_FILE=test_xdp_vlan.bpf.o204 205# First test: Remove VLAN by setting VLAN ID 0, using "xdp_vlan_change"206export XDP_PROG=xdp_vlan_change207ip netns exec ${NS1} ip link set $DEVNS1 $XDP_MODE object $BPF_FILE section $XDP_PROG208 209# In ns1: egress use TC to add back VLAN tag 4011210# (del cmd)211# tc qdisc del dev $DEVNS1 clsact 2> /dev/null212#213ip netns exec ${NS1} tc qdisc add dev $DEVNS1 clsact214ip netns exec ${NS1} tc filter add dev $DEVNS1 egress \215 prio 1 handle 1 bpf da obj $BPF_FILE sec tc_vlan_push216 217# Now the namespaces can reach each-other, test with ping:218ip netns exec ${NS2} ping -i 0.2 -W 2 -c 2 $IPADDR1219ip netns exec ${NS1} ping -i 0.2 -W 2 -c 2 $IPADDR2220 221# Second test: Replace xdp prog, that fully remove vlan header222#223# Catch kernel bug for generic-XDP, that does didn't allow us to224# remove a VLAN header, because skb->protocol still contain VLAN225# ETH_P_8021Q indication, and this cause overwriting of our changes.226#227export XDP_PROG=xdp_vlan_remove_outer2228ip netns exec ${NS1} ip link set $DEVNS1 $XDP_MODE off229ip netns exec ${NS1} ip link set $DEVNS1 $XDP_MODE object $BPF_FILE section $XDP_PROG230 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 $IPADDR1233ip netns exec ${NS1} ping -i 0.2 -W 2 -c 2 $IPADDR2234