Martin KaFai Lau | a3f7461 | 2016-06-30 10:28:45 -0700 | [diff] [blame] | 1 | #!/bin/bash |
Greg Kroah-Hartman | b244131 | 2017-11-01 15:07:57 +0100 | [diff] [blame] | 2 | # SPDX-License-Identifier: GPL-2.0 |
Martin KaFai Lau | a3f7461 | 2016-06-30 10:28:45 -0700 | [diff] [blame] | 3 | |
| 4 | MY_DIR=$(dirname $0) |
| 5 | # Details on the bpf prog |
| 6 | BPF_CGRP2_ARRAY_NAME='test_cgrp2_array_pin' |
| 7 | BPF_PROG="$MY_DIR/test_cgrp2_tc_kern.o" |
| 8 | BPF_SECTION='filter' |
| 9 | |
| 10 | [ -z "$TC" ] && TC='tc' |
| 11 | [ -z "$IP" ] && IP='ip' |
| 12 | |
| 13 | # Names of the veth interface, net namespace...etc. |
| 14 | HOST_IFC='ve' |
| 15 | NS_IFC='vens' |
| 16 | NS='ns' |
| 17 | |
| 18 | find_mnt() { |
| 19 | cat /proc/mounts | \ |
| 20 | awk '{ if ($3 == "'$1'" && mnt == "") { mnt = $2 }} END { print mnt }' |
| 21 | } |
| 22 | |
| 23 | # Init cgroup2 vars |
| 24 | init_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 |
| 36 | init_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 | |
| 42 | setup_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 | |
| 59 | setup_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 | |
| 71 | setup_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.accept_dad=0 |
| 77 | |
| 78 | $IP netns add ns || return $? |
| 79 | $IP link set dev $NS_IFC netns ns || return $? |
| 80 | $IP -n $NS link set dev $NS_IFC up || return $? |
| 81 | $IP netns exec $NS sysctl -q net.ipv6.conf.$NS_IFC.accept_dad=0 |
| 82 | $TC qdisc add dev $HOST_IFC clsact || return $? |
| 83 | $TC filter add dev $HOST_IFC egress bpf da obj $BPF_PROG sec $BPF_SECTION || return $? |
| 84 | ;; |
| 85 | *) |
| 86 | $IP netns del $NS |
| 87 | $IP link del $HOST_IFC |
| 88 | ;; |
| 89 | esac |
| 90 | } |
| 91 | |
| 92 | run_in_cgrp() { |
| 93 | # Fork another bash and move it under the specified cgroup. |
| 94 | # It makes the cgroup cleanup easier at the end of the test. |
| 95 | cmd='echo $$ > ' |
| 96 | cmd="$cmd $1/cgroup.procs; exec $2" |
| 97 | bash -c "$cmd" |
| 98 | } |
| 99 | |
| 100 | do_test() { |
| 101 | run_in_cgrp $CGRP2_TC_LEAF "ping -6 -c3 ff02::1%$HOST_IFC >& /dev/null" |
| 102 | local dropped=$($TC -s qdisc show dev $HOST_IFC | tail -3 | \ |
| 103 | awk '/drop/{print substr($7, 0, index($7, ",")-1)}') |
| 104 | if [[ $dropped -eq 0 ]] |
| 105 | then |
| 106 | echo "FAIL" |
| 107 | return 1 |
| 108 | else |
| 109 | echo "Successfully filtered $dropped packets" |
| 110 | return 0 |
| 111 | fi |
| 112 | } |
| 113 | |
| 114 | do_exit() { |
| 115 | if [ "$DEBUG" == "yes" ] && [ "$MODE" != 'cleanuponly' ] |
| 116 | then |
| 117 | echo "------ DEBUG ------" |
| 118 | echo "mount: "; mount | egrep '(cgroup2|bpf)'; echo |
| 119 | echo "$CGRP2_TC_LEAF: "; ls -l $CGRP2_TC_LEAF; echo |
| 120 | if [ -d "$BPF_FS_TC_SHARE" ] |
| 121 | then |
| 122 | echo "$BPF_FS_TC_SHARE: "; ls -l $BPF_FS_TC_SHARE; echo |
| 123 | fi |
| 124 | echo "Host net:" |
| 125 | $IP netns |
| 126 | $IP link show dev $HOST_IFC |
| 127 | $IP -6 a show dev $HOST_IFC |
| 128 | $TC -s qdisc show dev $HOST_IFC |
| 129 | echo |
| 130 | echo "$NS net:" |
| 131 | $IP -n $NS link show dev $NS_IFC |
| 132 | $IP -n $NS -6 link show dev $NS_IFC |
| 133 | echo "------ DEBUG ------" |
| 134 | echo |
| 135 | fi |
| 136 | |
| 137 | if [ "$MODE" != 'nocleanup' ] |
| 138 | then |
| 139 | setup_net stop |
| 140 | setup_bpf_cgrp2_array stop |
| 141 | setup_cgrp2 stop |
| 142 | fi |
| 143 | } |
| 144 | |
| 145 | init_cgrp2_vars |
| 146 | init_bpf_fs_vars |
| 147 | |
| 148 | while [[ $# -ge 1 ]] |
| 149 | do |
| 150 | a="$1" |
| 151 | case $a in |
| 152 | debug) |
| 153 | DEBUG='yes' |
| 154 | shift 1 |
| 155 | ;; |
| 156 | cleanup-only) |
| 157 | MODE='cleanuponly' |
| 158 | shift 1 |
| 159 | ;; |
| 160 | no-cleanup) |
| 161 | MODE='nocleanup' |
| 162 | shift 1 |
| 163 | ;; |
| 164 | *) |
| 165 | echo "test_cgrp2_tc [debug] [cleanup-only | no-cleanup]" |
| 166 | echo " debug: Print cgrp and network setup details at the end of the test" |
| 167 | echo " cleanup-only: Try to cleanup things from last test. No test will be run" |
| 168 | echo " no-cleanup: Run the test but don't do cleanup at the end" |
| 169 | echo "[Note: If no arg is given, it will run the test and do cleanup at the end]" |
| 170 | echo |
| 171 | exit -1 |
| 172 | ;; |
| 173 | esac |
| 174 | done |
| 175 | |
| 176 | trap do_exit 0 |
| 177 | |
| 178 | [ "$MODE" == 'cleanuponly' ] && exit |
| 179 | |
| 180 | setup_cgrp2 start || exit $? |
| 181 | setup_net start || exit $? |
| 182 | init_bpf_fs_vars || exit $? |
| 183 | setup_bpf_cgrp2_array start || exit $? |
| 184 | do_test |
| 185 | echo |