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