#!/bin/bash global MY_DIR := $[dirname $0] # Details on the bpf prog global BPF_CGRP2_ARRAY_NAME := ''test_cgrp2_array_pin'' global BPF_PROG := ""$MY_DIR/test_cgrp2_tc_kern.o"" global BPF_SECTION := ''filter'' test -z $TC && global TC := ''tc'' test -z $IP && global IP := ''ip'' # Names of the veth interface, net namespace...etc. global HOST_IFC := ''ve'' global NS_IFC := ''vens'' global NS := ''ns'' proc find_mnt { cat /proc/mounts | \ awk '{ if ($3 == "'$1'" && mnt == "") { mnt = $2 }} END { print mnt }' } # Init cgroup2 vars proc init_cgrp2_vars { global CGRP2_ROOT := $[find_mnt cgroup2] if test -z $CGRP2_ROOT { global CGRP2_ROOT := ''/mnt/cgroup2'' global MOUNT_CGRP2 := '"yes'" } global CGRP2_TC := ""$CGRP2_ROOT/tc"" global CGRP2_TC_LEAF := ""$CGRP2_TC/leaf"" } # Init bpf fs vars proc init_bpf_fs_vars { var bpf_fs_root = $[find_mnt bpf] test -n $bpf_fs_root || return -1 global BPF_FS_TC_SHARE := ""$bpf_fs_root/tc/globals"" } proc setup_cgrp2 { matchstr $1 { start { if test $MOUNT_CGRP2 == 'yes' { test -d $CGRP2_ROOT || mkdir -p $CGRP2_ROOT mount -t cgroup2 none $CGRP2_ROOT || return $? } mkdir -p $CGRP2_TC_LEAF } * { rmdir $CGRP2_TC_LEAF && rmdir $CGRP2_TC test $MOUNT_CGRP2 == 'yes' && umount $CGRP2_ROOT } } } proc setup_bpf_cgrp2_array { var bpf_cgrp2_array = ""$BPF_FS_TC_SHARE/$BPF_CGRP2_ARRAY_NAME"" matchstr $1 { start { $MY_DIR/test_cgrp2_array_pin -U $bpf_cgrp2_array -v $CGRP2_TC } * { test -d $BPF_FS_TC_SHARE && rm -f $bpf_cgrp2_array } } } proc setup_net { matchstr $1 { 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 } } } proc 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. global cmd := ''echo $$ > '' global cmd := ""$cmd $1/cgroup.procs; exec $2"" bash -c $cmd } proc do_test { run_in_cgrp $CGRP2_TC_LEAF "ping -6 -c3 ff02::1%$HOST_IFC >& /dev/null" var dropped = $[$TC -s qdisc show dev $HOST_IFC | tail -3 | \ awk '/drop/{print substr($7, 0, index($7, ",")-1)}] if [[ $dropped -eq 0 ]] { echo "FAIL" return 1 } else { echo "Successfully filtered $dropped packets" return 0 } } proc do_exit { if test $DEBUG == "yes" && test $MODE != 'cleanuponly' { echo "------ DEBUG ------" echo "mount: "; mount | egrep '(cgroup2|bpf)'; echo echo "$CGRP2_TC_LEAF: "; ls -l $CGRP2_TC_LEAF; echo if test -d $BPF_FS_TC_SHARE { echo "$BPF_FS_TC_SHARE: "; ls -l $BPF_FS_TC_SHARE; echo } 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 } if test $MODE != 'nocleanup' { setup_net stop setup_bpf_cgrp2_array stop setup_cgrp2 stop } } init_cgrp2_vars init_bpf_fs_vars while [[ $# -ge 1 ]] { global a := $1 matchstr $a { debug { global DEBUG := ''yes'' shift 1 } cleanup-only { global MODE := ''cleanuponly'' shift 1 } no-cleanup { global 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 } } } trap do_exit 0 test $MODE == 'cleanuponly' && exit setup_cgrp2 start || exit $Status setup_net start || exit $Status init_bpf_fs_vars || exit $Status setup_bpf_cgrp2_array start || exit $Status do_test echo (CommandList children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:MY_DIR) op: Equal rhs: { (CommandSubPart command_list: (CommandList children:[(C {(dirname)} {($ VSub_Number "$0")})]) left_token: spids: [5 9] ) } spids: [4] ) ] spids: [4] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:BPF_CGRP2_ARRAY_NAME) op: Equal rhs: {(SQ )} spids: [14] ) ] spids: [14] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:BPF_PROG) op: Equal rhs: {(DQ ($ VSub_Name "$MY_DIR") (/test_cgrp2_tc_kern.o))} spids: [19] ) ] spids: [19] ) (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:BPF_SECTION) op:Equal rhs:{(SQ )} spids:[25])] spids: [25] ) (AndOr children: [ (C {(Lit_Other "[")} {(-z)} {(DQ ($ VSub_Name "$TC"))} {(Lit_Other "]")}) (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:TC) op:Equal rhs:{(SQ )} spids:[43])] spids: [43] ) ] op_id: Op_DAmp ) (AndOr children: [ (C {(Lit_Other "[")} {(-z)} {(DQ ($ VSub_Name "$IP"))} {(Lit_Other "]")}) (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:IP) op:Equal rhs:{(SQ )} spids:[60])] spids: [60] ) ] op_id: Op_DAmp ) (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:HOST_IFC) op:Equal rhs:{(SQ )} spids:[69])] spids: [69] ) (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:NS_IFC) op:Equal rhs:{(SQ )} spids:[74])] spids: [74] ) (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:NS) op:Equal rhs:{(SQ )} spids:[79])] spids: [79] ) (FuncDef name: find_mnt body: (BraceGroup children: [ (Pipeline children: [ (C {(cat)} {(/proc/mounts)}) (C {(awk)} {(SQ <"{ if ($3 == \"">) ($ VSub_Number "$1") (SQ <"\" && mnt == \"\") { mnt = $2 }} END { print mnt }">) } ) ] negated: False ) ] spids: [89] ) spids: [85 88] ) (FuncDef name: init_cgrp2_vars body: (BraceGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:CGRP2_ROOT) op: Equal rhs: { (CommandSubPart command_list: (CommandList children:[(C {(find_mnt)} {(cgroup2)})]) left_token: spids: [124 128] ) } spids: [123] ) ] spids: [123] ) (If arms: [ (if_arm cond: [ (C {(Lit_Other "[")} {(-z)} {(DQ ($ VSub_Name "$CGRP2_ROOT"))} {(Lit_Other "]")}) ] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:CGRP2_ROOT) op: Equal rhs: {(SQ )} spids: [147] ) ] spids: [147] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:MOUNT_CGRP2) op: Equal rhs: {(DQ (yes))} spids: [153] ) ] spids: [153] ) ] spids: [-1 144] ) ] spids: [-1 159] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:CGRP2_TC) op: Equal rhs: {(DQ ($ VSub_Name "$CGRP2_ROOT") (/tc))} spids: [162] ) ] spids: [162] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:CGRP2_TC_LEAF) op: Equal rhs: {(DQ ($ VSub_Name "$CGRP2_TC") (/leaf))} spids: [169] ) ] spids: [169] ) ] spids: [120] ) spids: [116 119] ) (FuncDef name: init_bpf_fs_vars body: (BraceGroup children: [ (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:bpf_fs_root) op: Equal rhs: { (CommandSubPart command_list: (CommandList children:[(C {(find_mnt)} {(bpf)})]) left_token: spids: [191 195] ) } spids: [190] ) ] spids: [188] ) (AndOr children: [ (C {(Lit_Other "[")} {(-n)} {(DQ ($ VSub_Name "$bpf_fs_root"))} {(Lit_Other "]")}) (ControlFlow token: arg_word:{(-1)}) ] op_id: Op_DPipe ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:BPF_FS_TC_SHARE) op: Equal rhs: {(DQ ($ VSub_Name "$bpf_fs_root") (/tc/globals))} spids: [215] ) ] spids: [215] ) ] spids: [185] ) spids: [181 184] ) (FuncDef name: setup_cgrp2 body: (BraceGroup children: [ (Case to_match: {($ VSub_Number "$1")} arms: [ (case_arm pat_list: [{(start)}] action: [ (If arms: [ (if_arm cond: [ (C {(Lit_Other "[")} {(DQ ($ VSub_Name "$MOUNT_CGRP2"))} {(Lit_Other "=") (Lit_Other "=")} {(SQ )} {(Lit_Other "]")} ) ] action: [ (AndOr children: [ (C {(Lit_Other "[")} {(-d)} {($ VSub_Name "$CGRP2_ROOT")} {(Lit_Other "]")} ) (C {(mkdir)} {(-p)} {($ VSub_Name "$CGRP2_ROOT")}) ] op_id: Op_DPipe ) (AndOr children: [ (C {(mount)} {(-t)} {(cgroup2)} {(none)} {($ VSub_Name "$CGRP2_ROOT")}) (ControlFlow token: arg_word: {($ VSub_QMark "$?")} ) ] op_id: Op_DPipe ) ] spids: [-1 260] ) ] spids: [-1 297] ) (C {(mkdir)} {(-p)} {($ VSub_Name "$CGRP2_TC_LEAF")}) ] spids: [238 239 307 -1] ) (case_arm pat_list: [{(Lit_Other "*")}] action: [ (AndOr children: [ (C {(rmdir)} {($ VSub_Name "$CGRP2_TC_LEAF")}) (C {(rmdir)} {($ VSub_Name "$CGRP2_TC")}) ] op_id: Op_DAmp ) (AndOr children: [ (C {(Lit_Other "[")} {(DQ ($ VSub_Name "$MOUNT_CGRP2"))} {(Lit_Other "=") (Lit_Other "=")} {(SQ )} {(Lit_Other "]")} ) (C {(umount)} {($ VSub_Name "$CGRP2_ROOT")}) ] op_id: Op_DAmp ) ] spids: [310 311 347 -1] ) ] spids: [231 235 350] ) ] spids: [228] ) spids: [224 227] ) (FuncDef name: setup_bpf_cgrp2_array body: (BraceGroup children: [ (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:bpf_cgrp2_array) op: Equal rhs: {(DQ ($ VSub_Name "$BPF_FS_TC_SHARE") (/) ($ VSub_Name "$BPF_CGRP2_ARRAY_NAME"))} spids: [364] ) ] spids: [362] ) (Case to_match: {($ VSub_Number "$1")} arms: [ (case_arm pat_list: [{(start)}] action: [ (C {($ VSub_Name "$MY_DIR") (/test_cgrp2_array_pin)} {(-U)} {($ VSub_Name "$bpf_cgrp2_array")} {(-v)} {($ VSub_Name "$CGRP2_TC")} ) ] spids: [379 380 395 -1] ) (case_arm pat_list: [{(Lit_Other "*")}] action: [ (AndOr children: [ (C {(Lit_Other "[")} {(-d)} {(DQ ($ VSub_Name "$BPF_FS_TC_SHARE"))} {(Lit_Other "]")} ) (C {(rm)} {(-f)} {($ VSub_Name "$bpf_cgrp2_array")}) ] op_id: Op_DAmp ) ] spids: [398 399 421 -1] ) ] spids: [372 376 424] ) ] spids: [359] ) spids: [355 358] ) (FuncDef name: setup_net body: (BraceGroup children: [ (Case to_match: {($ VSub_Number "$1")} arms: [ (case_arm pat_list: [{(start)}] action: [ (AndOr children: [ (C {($ VSub_Name "$IP")} {(link)} {(add)} {($ VSub_Name "$HOST_IFC")} {(type)} {(veth)} {(peer)} {(name)} {($ VSub_Name "$NS_IFC")} ) (ControlFlow token: arg_word: {($ VSub_QMark "$?")} ) ] op_id: Op_DPipe ) (AndOr children: [ (C {($ VSub_Name "$IP")} {(link)} {(set)} {(dev)} {($ VSub_Name "$HOST_IFC")} {(up)} ) (ControlFlow token: arg_word: {($ VSub_QMark "$?")} ) ] op_id: Op_DPipe ) (C {(sysctl)} {(-q)} {(net.ipv6.conf.) ($ VSub_Name "$HOST_IFC") (.accept_dad) (Lit_Other "=") (0)} ) (AndOr children: [ (C {($ VSub_Name "$IP")} {(netns)} {(add)} {(ns)}) (ControlFlow token: arg_word: {($ VSub_QMark "$?")} ) ] op_id: Op_DPipe ) (AndOr children: [ (C {($ VSub_Name "$IP")} {(link)} {(set)} {(dev)} {($ VSub_Name "$NS_IFC")} {(netns)} {(ns)} ) (ControlFlow token: arg_word: {($ VSub_QMark "$?")} ) ] op_id: Op_DPipe ) (AndOr children: [ (C {($ VSub_Name "$IP")} {(-n)} {($ VSub_Name "$NS")} {(link)} {(set)} {(dev)} {($ VSub_Name "$NS_IFC")} {(up)} ) (ControlFlow token: arg_word: {($ VSub_QMark "$?")} ) ] op_id: Op_DPipe ) (C {($ VSub_Name "$IP")} {(netns)} {(exec)} {($ VSub_Name "$NS")} {(sysctl)} {(-q)} {(net.ipv6.conf.) ($ VSub_Name "$NS_IFC") (.accept_dad) (Lit_Other "=") (0)} ) (AndOr children: [ (C {($ VSub_Name "$TC")} {(qdisc)} {(add)} {(dev)} {($ VSub_Name "$HOST_IFC")} {(clsact)} ) (ControlFlow token: arg_word: {($ VSub_QMark "$?")} ) ] op_id: Op_DPipe ) (AndOr children: [ (C {($ VSub_Name "$TC")} {(filter)} {(add)} {(dev)} {($ VSub_Name "$HOST_IFC")} {(egress)} {(bpf)} {(da)} {(obj)} {($ VSub_Name "$BPF_PROG")} {(sec)} {($ VSub_Name "$BPF_SECTION")} ) (ControlFlow token: arg_word: {($ VSub_QMark "$?")} ) ] op_id: Op_DPipe ) ] spids: [443 444 631 -1] ) (case_arm pat_list: [{(Lit_Other "*")}] action: [ (C {($ VSub_Name "$IP")} {(netns)} {(del)} {($ VSub_Name "$NS")}) (C {($ VSub_Name "$IP")} {(link)} {(del)} {($ VSub_Name "$HOST_IFC")}) ] spids: [634 635 656 -1] ) ] spids: [436 440 659] ) ] spids: [433] ) spids: [429 432] ) (FuncDef name: run_in_cgrp body: (BraceGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:cmd) op: Equal rhs: {(SQ <"echo $$ > ">)} spids: [679] ) ] spids: [679] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:cmd) op: Equal rhs: { (DQ ($ VSub_Name "$cmd") (" ") ($ VSub_Number "$1") ("/cgroup.procs; exec ") ($ VSub_Number "$2") ) } spids: [685] ) ] spids: [685] ) (C {(bash)} {(-c)} {(DQ ($ VSub_Name "$cmd"))}) ] spids: [668] ) spids: [664 667] ) (FuncDef name: do_test body: (BraceGroup children: [ (C {(run_in_cgrp)} {($ VSub_Name "$CGRP2_TC_LEAF")} {(DQ ("ping -6 -c3 ff02::1%") ($ VSub_Name "$HOST_IFC") (" >& /dev/null"))} ) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:dropped) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [ (Pipeline children: [ (C {($ VSub_Name "$TC")} {(-s)} {(qdisc)} {(show)} {(dev)} {($ VSub_Name "$HOST_IFC")} ) (C {(tail)} {(-3)}) (C {(awk)} {(SQ <"/drop/{print substr($7, 0, index($7, \",\")-1)}">)}) ] negated: False ) ] ) left_token: spids: [727 755] ) } spids: [726] ) ] spids: [724] ) (If arms: [ (if_arm cond: [ (DBracket expr: (BoolBinary op_id: BoolBinary_eq left: {($ VSub_Name "$dropped")} right: {(0)} ) ) ] action: [ (C {(echo)} {(DQ (FAIL))}) (ControlFlow token: arg_word:{(1)}) ] spids: [-1 771] ) ] else_action: [ (C {(echo)} {(DQ ("Successfully filtered ") ($ VSub_Name "$dropped") (" packets"))}) (ControlFlow token: arg_word:{(0)}) ] spids: [786 803] ) ] spids: [710] ) spids: [706 709] ) (FuncDef name: do_exit body: (BraceGroup children: [ (If arms: [ (if_arm cond: [ (AndOr children: [ (C {(Lit_Other "[")} {(DQ ($ VSub_Name "$DEBUG"))} {(Lit_Other "=") (Lit_Other "=")} {(DQ (yes))} {(Lit_Other "]")} ) (C {(Lit_Other "[")} {(DQ ($ VSub_Name "$MODE"))} {(KW_Bang "!") (Lit_Other "=")} {(SQ )} {(Lit_Other "]")} ) ] op_id: Op_DAmp ) ] action: [ (C {(echo)} {(DQ ("------ DEBUG ------"))}) (Sentence child: (C {(echo)} {(DQ ("mount: "))}) terminator: ) (Sentence child: (Pipeline children: [(C {(mount)}) (C {(egrep)} {(SQ <"(cgroup2|bpf)">)})] negated: False ) terminator: ) (C {(echo)}) (Sentence child: (C {(echo)} {(DQ ($ VSub_Name "$CGRP2_TC_LEAF") (": "))}) terminator: ) (Sentence child: (C {(ls)} {(-l)} {($ VSub_Name "$CGRP2_TC_LEAF")}) terminator: ) (C {(echo)}) (If arms: [ (if_arm cond: [ (C {(Lit_Other "[")} {(-d)} {(DQ ($ VSub_Name "$BPF_FS_TC_SHARE"))} {(Lit_Other "]")} ) ] action: [ (Sentence child: (C {(echo)} {(DQ ($ VSub_Name "$BPF_FS_TC_SHARE") (": "))}) terminator: ) (Sentence child: (C {(ls)} {(-l)} {($ VSub_Name "$BPF_FS_TC_SHARE")}) terminator: ) (C {(echo)}) ] spids: [-1 912] ) ] spids: [-1 933] ) (C {(echo)} {(DQ ("Host net:"))}) (C {($ VSub_Name "$IP")} {(netns)}) (C {($ VSub_Name "$IP")} {(link)} {(show)} {(dev)} {($ VSub_Name "$HOST_IFC")}) (C {($ VSub_Name "$IP")} {(-6)} {(a)} {(show)} {(dev)} {($ VSub_Name "$HOST_IFC")}) (C {($ VSub_Name "$TC")} {(-s)} {(qdisc)} {(show)} {(dev)} {($ VSub_Name "$HOST_IFC")}) (C {(echo)}) (C {(echo)} {(DQ ($ VSub_Name "$NS") (" net:"))}) (C {($ VSub_Name "$IP")} {(-n)} {($ VSub_Name "$NS")} {(link)} {(show)} {(dev)} {($ VSub_Name "$NS_IFC")} ) (C {($ VSub_Name "$IP")} {(-n)} {($ VSub_Name "$NS")} {(-6)} {(link)} {(show)} {(dev)} {($ VSub_Name "$NS_IFC")} ) (C {(echo)} {(DQ ("------ DEBUG ------"))}) (C {(echo)}) ] spids: [-1 850] ) ] spids: [-1 1038] ) (If arms: [ (if_arm cond: [ (C {(Lit_Other "[")} {(DQ ($ VSub_Name "$MODE"))} {(KW_Bang "!") (Lit_Other "=")} {(SQ )} {(Lit_Other "]")} ) ] action: [ (C {(setup_net)} {(stop)}) (C {(setup_bpf_cgrp2_array)} {(stop)}) (C {(setup_cgrp2)} {(stop)}) ] spids: [-1 1060] ) ] spids: [-1 1078] ) ] spids: [812] ) spids: [808 811] ) (C {(init_cgrp2_vars)}) (C {(init_bpf_fs_vars)}) (While cond: [(DBracket expr:(BoolBinary op_id:BoolBinary_ge left:{($ VSub_Pound "$#")} right:{(1)}))] body: (DoGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:a) op: Equal rhs: {(DQ ($ VSub_Number "$1"))} spids: [1103] ) ] spids: [1103] ) (Case to_match: {($ VSub_Name "$a")} arms: [ (case_arm pat_list: [{(debug)}] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:DEBUG) op: Equal rhs: {(SQ )} spids: [1120] ) ] spids: [1120] ) (C {(shift)} {(1)}) ] spids: [1116 1117 1131 -1] ) (case_arm pat_list: [{(cleanup-only)}] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:MODE) op: Equal rhs: {(SQ )} spids: [1138] ) ] spids: [1138] ) (C {(shift)} {(1)}) ] spids: [1134 1135 1149 -1] ) (case_arm pat_list: [{(no-cleanup)}] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:MODE) op: Equal rhs: {(SQ )} spids: [1156] ) ] spids: [1156] ) (C {(shift)} {(1)}) ] spids: [1152 1153 1167 -1] ) (case_arm pat_list: [{(Lit_Other "*")}] action: [ (C {(echo)} {(DQ ("test_cgrp2_tc [debug] [cleanup-only | no-cleanup]"))}) (C {(echo)} {(DQ (" debug: Print cgrp and network setup details at the end of the test"))} ) (C {(echo)} { (DQ ( " cleanup-only: Try to cleanup things from last test. No test will be run" ) ) } ) (C {(echo)} {(DQ (" no-cleanup: Run the test but don't do cleanup at the end"))}) (C {(echo)} { (DQ ( "[Note: If no arg is given, it will run the test and do cleanup at the end]" ) ) } ) (C {(echo)}) (C {(exit)} {(-1)}) ] spids: [1170 1171 1217 -1] ) ] spids: [1109 1113 1220] ) ] spids: [1100 1222] ) ) (C {(trap)} {(do_exit)} {(0)}) (AndOr children: [ (C {(Lit_Other "[")} {(DQ ($ VSub_Name "$MODE"))} {(Lit_Other "=") (Lit_Other "=")} {(SQ )} {(Lit_Other "]")} ) (C {(exit)}) ] op_id: Op_DAmp ) (AndOr children: [(C {(setup_cgrp2)} {(start)}) (C {(exit)} {($ VSub_QMark "$?")})] op_id: Op_DPipe ) (AndOr children: [(C {(setup_net)} {(start)}) (C {(exit)} {($ VSub_QMark "$?")})] op_id: Op_DPipe ) (AndOr children:[(C {(init_bpf_fs_vars)})(C {(exit)} {($ VSub_QMark "$?")})] op_id:Op_DPipe) (AndOr children: [(C {(setup_bpf_cgrp2_array)} {(start)}) (C {(exit)} {($ VSub_QMark "$?")})] op_id: Op_DPipe ) (C {(do_test)}) (C {(echo)}) ] )