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