Blame view

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