1*4882a593Smuzhiyun#!/bin/bash 2*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0 3*4882a593Smuzhiyun 4*4882a593SmuzhiyunMY_DIR=$(dirname $0) 5*4882a593Smuzhiyun# Details on the bpf prog 6*4882a593SmuzhiyunBPF_CGRP2_ARRAY_NAME='test_cgrp2_array_pin' 7*4882a593SmuzhiyunBPF_PROG="$MY_DIR/test_cgrp2_tc_kern.o" 8*4882a593SmuzhiyunBPF_SECTION='filter' 9*4882a593Smuzhiyun 10*4882a593Smuzhiyun[ -z "$TC" ] && TC='tc' 11*4882a593Smuzhiyun[ -z "$IP" ] && IP='ip' 12*4882a593Smuzhiyun 13*4882a593Smuzhiyun# Names of the veth interface, net namespace...etc. 14*4882a593SmuzhiyunHOST_IFC='ve' 15*4882a593SmuzhiyunNS_IFC='vens' 16*4882a593SmuzhiyunNS='ns' 17*4882a593Smuzhiyun 18*4882a593Smuzhiyunfind_mnt() { 19*4882a593Smuzhiyun cat /proc/mounts | \ 20*4882a593Smuzhiyun awk '{ if ($3 == "'$1'" && mnt == "") { mnt = $2 }} END { print mnt }' 21*4882a593Smuzhiyun} 22*4882a593Smuzhiyun 23*4882a593Smuzhiyun# Init cgroup2 vars 24*4882a593Smuzhiyuninit_cgrp2_vars() { 25*4882a593Smuzhiyun CGRP2_ROOT=$(find_mnt cgroup2) 26*4882a593Smuzhiyun if [ -z "$CGRP2_ROOT" ] 27*4882a593Smuzhiyun then 28*4882a593Smuzhiyun CGRP2_ROOT='/mnt/cgroup2' 29*4882a593Smuzhiyun MOUNT_CGRP2="yes" 30*4882a593Smuzhiyun fi 31*4882a593Smuzhiyun CGRP2_TC="$CGRP2_ROOT/tc" 32*4882a593Smuzhiyun CGRP2_TC_LEAF="$CGRP2_TC/leaf" 33*4882a593Smuzhiyun} 34*4882a593Smuzhiyun 35*4882a593Smuzhiyun# Init bpf fs vars 36*4882a593Smuzhiyuninit_bpf_fs_vars() { 37*4882a593Smuzhiyun local bpf_fs_root=$(find_mnt bpf) 38*4882a593Smuzhiyun [ -n "$bpf_fs_root" ] || return -1 39*4882a593Smuzhiyun BPF_FS_TC_SHARE="$bpf_fs_root/tc/globals" 40*4882a593Smuzhiyun} 41*4882a593Smuzhiyun 42*4882a593Smuzhiyunsetup_cgrp2() { 43*4882a593Smuzhiyun case $1 in 44*4882a593Smuzhiyun start) 45*4882a593Smuzhiyun if [ "$MOUNT_CGRP2" == 'yes' ] 46*4882a593Smuzhiyun then 47*4882a593Smuzhiyun [ -d $CGRP2_ROOT ] || mkdir -p $CGRP2_ROOT 48*4882a593Smuzhiyun mount -t cgroup2 none $CGRP2_ROOT || return $? 49*4882a593Smuzhiyun fi 50*4882a593Smuzhiyun mkdir -p $CGRP2_TC_LEAF 51*4882a593Smuzhiyun ;; 52*4882a593Smuzhiyun *) 53*4882a593Smuzhiyun rmdir $CGRP2_TC_LEAF && rmdir $CGRP2_TC 54*4882a593Smuzhiyun [ "$MOUNT_CGRP2" == 'yes' ] && umount $CGRP2_ROOT 55*4882a593Smuzhiyun ;; 56*4882a593Smuzhiyun esac 57*4882a593Smuzhiyun} 58*4882a593Smuzhiyun 59*4882a593Smuzhiyunsetup_bpf_cgrp2_array() { 60*4882a593Smuzhiyun local bpf_cgrp2_array="$BPF_FS_TC_SHARE/$BPF_CGRP2_ARRAY_NAME" 61*4882a593Smuzhiyun case $1 in 62*4882a593Smuzhiyun start) 63*4882a593Smuzhiyun $MY_DIR/test_cgrp2_array_pin -U $bpf_cgrp2_array -v $CGRP2_TC 64*4882a593Smuzhiyun ;; 65*4882a593Smuzhiyun *) 66*4882a593Smuzhiyun [ -d "$BPF_FS_TC_SHARE" ] && rm -f $bpf_cgrp2_array 67*4882a593Smuzhiyun ;; 68*4882a593Smuzhiyun esac 69*4882a593Smuzhiyun} 70*4882a593Smuzhiyun 71*4882a593Smuzhiyunsetup_net() { 72*4882a593Smuzhiyun case $1 in 73*4882a593Smuzhiyun start) 74*4882a593Smuzhiyun $IP link add $HOST_IFC type veth peer name $NS_IFC || return $? 75*4882a593Smuzhiyun $IP link set dev $HOST_IFC up || return $? 76*4882a593Smuzhiyun sysctl -q net.ipv6.conf.$HOST_IFC.accept_dad=0 77*4882a593Smuzhiyun 78*4882a593Smuzhiyun $IP netns add ns || return $? 79*4882a593Smuzhiyun $IP link set dev $NS_IFC netns ns || return $? 80*4882a593Smuzhiyun $IP -n $NS link set dev $NS_IFC up || return $? 81*4882a593Smuzhiyun $IP netns exec $NS sysctl -q net.ipv6.conf.$NS_IFC.accept_dad=0 82*4882a593Smuzhiyun $TC qdisc add dev $HOST_IFC clsact || return $? 83*4882a593Smuzhiyun $TC filter add dev $HOST_IFC egress bpf da obj $BPF_PROG sec $BPF_SECTION || return $? 84*4882a593Smuzhiyun ;; 85*4882a593Smuzhiyun *) 86*4882a593Smuzhiyun $IP netns del $NS 87*4882a593Smuzhiyun $IP link del $HOST_IFC 88*4882a593Smuzhiyun ;; 89*4882a593Smuzhiyun esac 90*4882a593Smuzhiyun} 91*4882a593Smuzhiyun 92*4882a593Smuzhiyunrun_in_cgrp() { 93*4882a593Smuzhiyun # Fork another bash and move it under the specified cgroup. 94*4882a593Smuzhiyun # It makes the cgroup cleanup easier at the end of the test. 95*4882a593Smuzhiyun cmd='echo $$ > ' 96*4882a593Smuzhiyun cmd="$cmd $1/cgroup.procs; exec $2" 97*4882a593Smuzhiyun bash -c "$cmd" 98*4882a593Smuzhiyun} 99*4882a593Smuzhiyun 100*4882a593Smuzhiyundo_test() { 101*4882a593Smuzhiyun run_in_cgrp $CGRP2_TC_LEAF "ping -6 -c3 ff02::1%$HOST_IFC >& /dev/null" 102*4882a593Smuzhiyun local dropped=$($TC -s qdisc show dev $HOST_IFC | tail -3 | \ 103*4882a593Smuzhiyun awk '/drop/{print substr($7, 0, index($7, ",")-1)}') 104*4882a593Smuzhiyun if [[ $dropped -eq 0 ]] 105*4882a593Smuzhiyun then 106*4882a593Smuzhiyun echo "FAIL" 107*4882a593Smuzhiyun return 1 108*4882a593Smuzhiyun else 109*4882a593Smuzhiyun echo "Successfully filtered $dropped packets" 110*4882a593Smuzhiyun return 0 111*4882a593Smuzhiyun fi 112*4882a593Smuzhiyun} 113*4882a593Smuzhiyun 114*4882a593Smuzhiyundo_exit() { 115*4882a593Smuzhiyun if [ "$DEBUG" == "yes" ] && [ "$MODE" != 'cleanuponly' ] 116*4882a593Smuzhiyun then 117*4882a593Smuzhiyun echo "------ DEBUG ------" 118*4882a593Smuzhiyun echo "mount: "; mount | egrep '(cgroup2|bpf)'; echo 119*4882a593Smuzhiyun echo "$CGRP2_TC_LEAF: "; ls -l $CGRP2_TC_LEAF; echo 120*4882a593Smuzhiyun if [ -d "$BPF_FS_TC_SHARE" ] 121*4882a593Smuzhiyun then 122*4882a593Smuzhiyun echo "$BPF_FS_TC_SHARE: "; ls -l $BPF_FS_TC_SHARE; echo 123*4882a593Smuzhiyun fi 124*4882a593Smuzhiyun echo "Host net:" 125*4882a593Smuzhiyun $IP netns 126*4882a593Smuzhiyun $IP link show dev $HOST_IFC 127*4882a593Smuzhiyun $IP -6 a show dev $HOST_IFC 128*4882a593Smuzhiyun $TC -s qdisc show dev $HOST_IFC 129*4882a593Smuzhiyun echo 130*4882a593Smuzhiyun echo "$NS net:" 131*4882a593Smuzhiyun $IP -n $NS link show dev $NS_IFC 132*4882a593Smuzhiyun $IP -n $NS -6 link show dev $NS_IFC 133*4882a593Smuzhiyun echo "------ DEBUG ------" 134*4882a593Smuzhiyun echo 135*4882a593Smuzhiyun fi 136*4882a593Smuzhiyun 137*4882a593Smuzhiyun if [ "$MODE" != 'nocleanup' ] 138*4882a593Smuzhiyun then 139*4882a593Smuzhiyun setup_net stop 140*4882a593Smuzhiyun setup_bpf_cgrp2_array stop 141*4882a593Smuzhiyun setup_cgrp2 stop 142*4882a593Smuzhiyun fi 143*4882a593Smuzhiyun} 144*4882a593Smuzhiyun 145*4882a593Smuzhiyuninit_cgrp2_vars 146*4882a593Smuzhiyuninit_bpf_fs_vars 147*4882a593Smuzhiyun 148*4882a593Smuzhiyunwhile [[ $# -ge 1 ]] 149*4882a593Smuzhiyundo 150*4882a593Smuzhiyun a="$1" 151*4882a593Smuzhiyun case $a in 152*4882a593Smuzhiyun debug) 153*4882a593Smuzhiyun DEBUG='yes' 154*4882a593Smuzhiyun shift 1 155*4882a593Smuzhiyun ;; 156*4882a593Smuzhiyun cleanup-only) 157*4882a593Smuzhiyun MODE='cleanuponly' 158*4882a593Smuzhiyun shift 1 159*4882a593Smuzhiyun ;; 160*4882a593Smuzhiyun no-cleanup) 161*4882a593Smuzhiyun MODE='nocleanup' 162*4882a593Smuzhiyun shift 1 163*4882a593Smuzhiyun ;; 164*4882a593Smuzhiyun *) 165*4882a593Smuzhiyun echo "test_cgrp2_tc [debug] [cleanup-only | no-cleanup]" 166*4882a593Smuzhiyun echo " debug: Print cgrp and network setup details at the end of the test" 167*4882a593Smuzhiyun echo " cleanup-only: Try to cleanup things from last test. No test will be run" 168*4882a593Smuzhiyun echo " no-cleanup: Run the test but don't do cleanup at the end" 169*4882a593Smuzhiyun echo "[Note: If no arg is given, it will run the test and do cleanup at the end]" 170*4882a593Smuzhiyun echo 171*4882a593Smuzhiyun exit -1 172*4882a593Smuzhiyun ;; 173*4882a593Smuzhiyun esac 174*4882a593Smuzhiyundone 175*4882a593Smuzhiyun 176*4882a593Smuzhiyuntrap do_exit 0 177*4882a593Smuzhiyun 178*4882a593Smuzhiyun[ "$MODE" == 'cleanuponly' ] && exit 179*4882a593Smuzhiyun 180*4882a593Smuzhiyunsetup_cgrp2 start || exit $? 181*4882a593Smuzhiyunsetup_net start || exit $? 182*4882a593Smuzhiyuninit_bpf_fs_vars || exit $? 183*4882a593Smuzhiyunsetup_bpf_cgrp2_array start || exit $? 184*4882a593Smuzhiyundo_test 185*4882a593Smuzhiyunecho 186