Martin KaFai Lau | a3f7461 | 2016-06-30 10:28:45 -0700 | [diff] [blame] | 1 | #!/bin/bash |
| 2 | |
| 3 | MY_DIR=$(dirname $0) |
| 4 | # Details on the bpf prog |
| 5 | BPF_CGRP2_ARRAY_NAME='test_cgrp2_array_pin' |
| 6 | BPF_PROG="$MY_DIR/test_cgrp2_tc_kern.o" |
| 7 | BPF_SECTION='filter' |
| 8 | |
| 9 | [ -z "$TC" ] && TC='tc' |
| 10 | [ -z "$IP" ] && IP='ip' |
| 11 | |
| 12 | # Names of the veth interface, net namespace...etc. |
| 13 | HOST_IFC='ve' |
| 14 | NS_IFC='vens' |
| 15 | NS='ns' |
| 16 | |
| 17 | find_mnt() { |
| 18 | cat /proc/mounts | \ |
| 19 | awk '{ if ($3 == "'$1'" && mnt == "") { mnt = $2 }} END { print mnt }' |
| 20 | } |
| 21 | |
| 22 | # Init cgroup2 vars |
| 23 | init_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 |
| 35 | init_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 | |
| 41 | setup_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 | |
| 58 | setup_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 | |
| 70 | setup_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 | |
| 91 | run_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 | |
| 99 | do_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 | |
| 113 | do_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 | |
| 144 | init_cgrp2_vars |
| 145 | init_bpf_fs_vars |
| 146 | |
| 147 | while [[ $# -ge 1 ]] |
| 148 | do |
| 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 |
| 173 | done |
| 174 | |
| 175 | trap do_exit 0 |
| 176 | |
| 177 | [ "$MODE" == 'cleanuponly' ] && exit |
| 178 | |
| 179 | setup_cgrp2 start || exit $? |
| 180 | setup_net start || exit $? |
| 181 | init_bpf_fs_vars || exit $? |
| 182 | setup_bpf_cgrp2_array start || exit $? |
| 183 | do_test |
| 184 | echo |