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