Back to home page

OSCL-LXR

 
 

    


0001 #!/bin/bash
0002 # SPDX-License-Identifier: GPL-2.0
0003 
0004 MY_DIR=$(dirname $0)
0005 # Details on the bpf prog
0006 BPF_CGRP2_ARRAY_NAME='test_cgrp2_array_pin'
0007 BPF_PROG="$MY_DIR/test_cgrp2_tc_kern.o"
0008 BPF_SECTION='filter'
0009 
0010 [ -z "$TC" ] && TC='tc'
0011 [ -z "$IP" ] && IP='ip'
0012 
0013 # Names of the veth interface, net namespace...etc.
0014 HOST_IFC='ve'
0015 NS_IFC='vens'
0016 NS='ns'
0017 
0018 find_mnt() {
0019     cat /proc/mounts | \
0020         awk '{ if ($3 == "'$1'" && mnt == "") { mnt = $2 }} END { print mnt }'
0021 }
0022 
0023 # Init cgroup2 vars
0024 init_cgrp2_vars() {
0025     CGRP2_ROOT=$(find_mnt cgroup2)
0026     if [ -z "$CGRP2_ROOT" ]
0027     then
0028         CGRP2_ROOT='/mnt/cgroup2'
0029         MOUNT_CGRP2="yes"
0030     fi
0031     CGRP2_TC="$CGRP2_ROOT/tc"
0032     CGRP2_TC_LEAF="$CGRP2_TC/leaf"
0033 }
0034 
0035 # Init bpf fs vars
0036 init_bpf_fs_vars() {
0037     local bpf_fs_root=$(find_mnt bpf)
0038     [ -n "$bpf_fs_root" ] || return -1
0039     BPF_FS_TC_SHARE="$bpf_fs_root/tc/globals"
0040 }
0041 
0042 setup_cgrp2() {
0043     case $1 in
0044         start)
0045             if [ "$MOUNT_CGRP2" == 'yes' ]
0046             then
0047                 [ -d $CGRP2_ROOT ] || mkdir -p $CGRP2_ROOT
0048                 mount -t cgroup2 none $CGRP2_ROOT || return $?
0049             fi
0050             mkdir -p $CGRP2_TC_LEAF
0051             ;;
0052         *)
0053             rmdir $CGRP2_TC_LEAF && rmdir $CGRP2_TC
0054             [ "$MOUNT_CGRP2" == 'yes' ] && umount $CGRP2_ROOT
0055             ;;
0056     esac
0057 }
0058 
0059 setup_bpf_cgrp2_array() {
0060     local bpf_cgrp2_array="$BPF_FS_TC_SHARE/$BPF_CGRP2_ARRAY_NAME"
0061     case $1 in
0062         start)
0063             $MY_DIR/test_cgrp2_array_pin -U $bpf_cgrp2_array -v $CGRP2_TC
0064             ;;
0065         *)
0066             [ -d "$BPF_FS_TC_SHARE" ] && rm -f $bpf_cgrp2_array
0067             ;;
0068     esac
0069 }
0070 
0071 setup_net() {
0072     case $1 in
0073         start)
0074             $IP link add $HOST_IFC type veth peer name $NS_IFC || return $?
0075             $IP link set dev $HOST_IFC up || return $?
0076             sysctl -q net.ipv6.conf.$HOST_IFC.accept_dad=0
0077 
0078             $IP netns add ns || return $?
0079             $IP link set dev $NS_IFC netns ns || return $?
0080             $IP -n $NS link set dev $NS_IFC up || return $?
0081             $IP netns exec $NS sysctl -q net.ipv6.conf.$NS_IFC.accept_dad=0
0082             $TC qdisc add dev $HOST_IFC clsact || return $?
0083             $TC filter add dev $HOST_IFC egress bpf da obj $BPF_PROG sec $BPF_SECTION || return $?
0084             ;;
0085         *)
0086             $IP netns del $NS
0087             $IP link del $HOST_IFC
0088             ;;
0089     esac
0090 }
0091 
0092 run_in_cgrp() {
0093     # Fork another bash and move it under the specified cgroup.
0094     # It makes the cgroup cleanup easier at the end of the test.
0095     cmd='echo $$ > '
0096     cmd="$cmd $1/cgroup.procs; exec $2"
0097     bash -c "$cmd"
0098 }
0099 
0100 do_test() {
0101     run_in_cgrp $CGRP2_TC_LEAF "ping -6 -c3 ff02::1%$HOST_IFC >& /dev/null"
0102     local dropped=$($TC -s qdisc show dev $HOST_IFC | tail -3 | \
0103                            awk '/drop/{print substr($7, 0, index($7, ",")-1)}')
0104     if [[ $dropped -eq 0 ]]
0105     then
0106         echo "FAIL"
0107         return 1
0108     else
0109         echo "Successfully filtered $dropped packets"
0110         return 0
0111     fi
0112 }
0113 
0114 do_exit() {
0115     if [ "$DEBUG" == "yes" ] && [ "$MODE" != 'cleanuponly' ]
0116     then
0117         echo "------ DEBUG ------"
0118         echo "mount: "; mount | egrep '(cgroup2|bpf)'; echo
0119         echo "$CGRP2_TC_LEAF: "; ls -l $CGRP2_TC_LEAF; echo
0120         if [ -d "$BPF_FS_TC_SHARE" ]
0121         then
0122             echo "$BPF_FS_TC_SHARE: "; ls -l $BPF_FS_TC_SHARE; echo
0123         fi
0124         echo "Host net:"
0125         $IP netns
0126         $IP link show dev $HOST_IFC
0127         $IP -6 a show dev $HOST_IFC
0128         $TC -s qdisc show dev $HOST_IFC
0129         echo
0130         echo "$NS net:"
0131         $IP -n $NS link show dev $NS_IFC
0132         $IP -n $NS -6 link show dev $NS_IFC
0133         echo "------ DEBUG ------"
0134         echo
0135     fi
0136 
0137     if [ "$MODE" != 'nocleanup' ]
0138     then
0139         setup_net stop
0140         setup_bpf_cgrp2_array stop
0141         setup_cgrp2 stop
0142     fi
0143 }
0144 
0145 init_cgrp2_vars
0146 init_bpf_fs_vars
0147 
0148 while [[ $# -ge 1 ]]
0149 do
0150     a="$1"
0151     case $a in
0152         debug)
0153             DEBUG='yes'
0154             shift 1
0155             ;;
0156         cleanup-only)
0157             MODE='cleanuponly'
0158             shift 1
0159             ;;
0160         no-cleanup)
0161             MODE='nocleanup'
0162             shift 1
0163             ;;
0164         *)
0165             echo "test_cgrp2_tc [debug] [cleanup-only | no-cleanup]"
0166             echo "  debug: Print cgrp and network setup details at the end of the test"
0167             echo "  cleanup-only: Try to cleanup things from last test.  No test will be run"
0168             echo "  no-cleanup: Run the test but don't do cleanup at the end"
0169             echo "[Note: If no arg is given, it will run the test and do cleanup at the end]"
0170             echo
0171             exit -1
0172             ;;
0173     esac
0174 done
0175 
0176 trap do_exit 0
0177 
0178 [ "$MODE" == 'cleanuponly' ] && exit
0179 
0180 setup_cgrp2 start || exit $?
0181 setup_net start || exit $?
0182 init_bpf_fs_vars || exit $?
0183 setup_bpf_cgrp2_array start || exit $?
0184 do_test
0185 echo