test_cgrp2_tc.sh 4.3 KB

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