summaryrefslogtreecommitdiffstats
path: root/tests/shell/testcases/transactions/30s-stress
diff options
context:
space:
mode:
Diffstat (limited to 'tests/shell/testcases/transactions/30s-stress')
-rwxr-xr-xtests/shell/testcases/transactions/30s-stress683
1 files changed, 683 insertions, 0 deletions
diff --git a/tests/shell/testcases/transactions/30s-stress b/tests/shell/testcases/transactions/30s-stress
new file mode 100755
index 00000000..e92b9226
--- /dev/null
+++ b/tests/shell/testcases/transactions/30s-stress
@@ -0,0 +1,683 @@
+#!/bin/bash
+
+# NFT_TEST_SKIP(NFT_TEST_SKIP_slow)
+
+runtime=30
+
+# allow stand-alone execution as well, e.g. '$0 3600'
+if [ x"$1" != "x" ] ;then
+ if [ -z "${NFT_TEST_HAVE_chain_binding+x}" ]; then
+ NFT_TEST_HAVE_chain_binding=y
+ fi
+ if [ -z "${NFT_TEST_HAVE_pipapo+x}" ]; then
+ NFT_TEST_HAVE_pipapo=y
+ fi
+ echo "running standalone with:"
+ echo "NFT_TEST_HAVE_chain_binding="$NFT_TEST_HAVE_chain_binding
+ echo "NFT_TEST_HAVE_pipapo="$NFT_TEST_HAVE_pipapo
+ if [ $1 -ge 0 ]; then
+ runtime="$1"
+ else
+ echo "Invalid runtime $1"
+ exit 1
+ fi
+fi
+
+if [ x = x"$NFT" ] ; then
+ NFT=nft
+fi
+
+if [ "$NFT_TEST_HAS_SOCKET_LIMITS" = y ] ; then
+ # The socket limit /proc/sys/net/core/wmem_max may be unsuitable for
+ # the test.
+ #
+ # Skip it. You may ensure that the limits are suitable and rerun
+ # with NFT_TEST_HAS_SOCKET_LIMITS=n.
+ exit 77
+fi
+
+if [ -z "${NFT_TEST_HAVE_chain_binding+x}" ] ; then
+ NFT_TEST_HAVE_chain_binding=n
+ mydir="$(dirname "$0")"
+ $NFT --check -f "$mydir/../../features/chain_binding.nft"
+ if [ $? -eq 0 ];then
+ NFT_TEST_HAVE_chain_binding=y
+ else
+ echo "Assuming anonymous chains are not supported"
+ fi
+fi
+
+if [ "$NFT_TEST_HAVE_pipapo" != y ] ;then
+ echo "Skipping pipapo set backend, kernel does not support it"
+fi
+
+testns=testns-$(mktemp -u "XXXXXXXX")
+tmp=""
+
+faultname="/proc/self/make-it-fail"
+tables="foo bar"
+
+failslab_defaults() {
+ test -w $faultname || return
+
+ # Disable fault injection unless process has 'make-it-fail' set
+ echo Y > /sys/kernel/debug/failslab/task-filter
+
+ # allow all slabs to fail (if process is tagged).
+ find /sys/kernel/slab/ -wholename '*/kmalloc-[0-9]*/failslab' -type f -exec sh -c 'echo 1 > {}' \;
+
+ # no limit on the number of failures, or clause works around old kernels that reject negative integer.
+ echo -1 > /sys/kernel/debug/failslab/times 2>/dev/null || printf '%#x -1' > /sys/kernel/debug/failslab/times
+
+ # Set to 2 for full dmesg traces for each injected error
+ echo 0 > /sys/kernel/debug/failslab/verbose
+}
+
+failslab_random()
+{
+ r=$((RANDOM%2))
+
+ if [ $r -eq 0 ]; then
+ echo Y > /sys/kernel/debug/failslab/ignore-gfp-wait
+ else
+ echo N > /sys/kernel/debug/failslab/ignore-gfp-wait
+ fi
+
+ r=$((RANDOM%5))
+ echo $r > /sys/kernel/debug/failslab/probability
+ r=$((RANDOM%100))
+ echo $r > /sys/kernel/debug/failslab/interval
+
+ # allow a small initial 'success budget'.
+ # failures only appear after this many allocated bytes.
+ r=$((RANDOM%16384))
+ echo $r > /sys/kernel/debug/$FAILTYPE/space
+}
+
+netns_del() {
+ ip netns pids "$testns" | xargs kill 2>/dev/null
+ ip netns del "$testns"
+}
+
+netns_add()
+{
+ ip netns add "$testns"
+ ip -netns "$testns" link set lo up
+}
+
+cleanup() {
+ [ "$tmp" = "" ] || rm -f "$tmp"
+ netns_del
+}
+
+nft_with_fault_inject()
+{
+ file="$1"
+
+ if [ -w "$faultname" ]; then
+ failslab_random
+
+ ip netns exec "$testns" bash -c "echo 1 > $faultname ; exec $NFT -f $file"
+ fi
+
+ ip netns exec "$testns" $NFT -f "$file"
+}
+
+trap cleanup EXIT
+tmp=$(mktemp)
+
+jump_or_goto()
+{
+ if [ $((RANDOM & 1)) -eq 0 ] ;then
+ echo -n "jump"
+ else
+ echo -n "goto"
+ fi
+}
+
+random_verdict()
+{
+ max="$1"
+
+ if [ $max -eq 0 ]; then
+ max=1
+ fi
+
+ rnd=$((RANDOM%max))
+
+ if [ $rnd -gt 0 ];then
+ jump_or_goto
+ printf " chain%03u" "$((rnd+1))"
+ return
+ fi
+
+ if [ $((RANDOM & 1)) -eq 0 ] ;then
+ echo "accept"
+ else
+ echo "drop"
+ fi
+}
+
+randsleep()
+{
+ local s=$((RANDOM%1))
+ local ms=$((RANDOM%1000))
+ sleep $s.$ms
+}
+
+randlist()
+{
+ while [ -r $tmp ]; do
+ randsleep
+ ip netns exec $testns $NFT list ruleset > /dev/null
+ done
+}
+
+randflush()
+{
+ while [ -r $tmp ]; do
+ randsleep
+ ip netns exec $testns $NFT flush ruleset > /dev/null
+ done
+}
+
+randdeltable()
+{
+ while [ -r $tmp ]; do
+ randsleep
+ for t in $tables; do
+ r=$((RANDOM%10))
+
+ if [ $r -eq 1 ] ;then
+ ip netns exec $testns $NFT delete table inet $t
+ randsleep
+ fi
+ done
+ done
+}
+
+randdelset()
+{
+ while [ -r $tmp ]; do
+ randsleep
+ for t in $tables; do
+ r=$((RANDOM%10))
+ s=$((RANDOM%10))
+
+ case $r in
+ 0)
+ setname=set_$s
+ ;;
+ 1)
+ setname=sett${s}
+ ;;
+ 2)
+ setname=dmap_${s}
+ ;;
+ 3)
+ setname=dmapt${s}
+ ;;
+ 4)
+ setname=vmap_${s}
+ ;;
+ 5)
+ setname=vmapt${s}
+ ;;
+ *)
+ continue
+ ;;
+ esac
+
+ if [ $r -eq 1 ] ;then
+ ip netns exec $testns $NFT delete set inet $t $setname
+ fi
+ done
+ done
+}
+
+randdelchain()
+{
+ while [ -r $tmp ]; do
+ for t in $tables; do
+ local c=$((RANDOM%100))
+ randsleep
+ chain=$(printf "chain%03u" "$c")
+
+ local r=$((RANDOM%10))
+ if [ $r -eq 1 ];then
+ # chain can be invalid/unknown.
+ ip netns exec $testns $NFT delete chain inet $t $chain
+ fi
+ done
+ done
+}
+
+randdisable()
+{
+ while [ -r $tmp ]; do
+ for t in $tables; do
+ randsleep
+ local r=$((RANDOM%10))
+ if [ $r -eq 1 ];then
+ ip netns exec $testns $NFT add table inet $t '{flags dormant; }'
+ randsleep
+ ip netns exec $testns $NFT add table inet $t '{ }'
+ fi
+ done
+ done
+}
+
+randdelns()
+{
+ while [ -r $tmp ]; do
+ randsleep
+ netns_del
+ netns_add
+ randsleep
+ done
+}
+
+available_flags()
+{
+ local -n available_flags=$1
+ selected_key=$2
+ if [ "$selected_key" == "single" ] ;then
+ available_flags+=("interval")
+ elif [ "$selected_key" == "concat" ] ;then
+ if [ "$NFT_TEST_HAVE_pipapo" = y ] ;then
+ available_flags+=("interval")
+ fi
+ fi
+}
+
+random_element_string=""
+
+# create a random element. Could cause any of the following:
+# 1. Invalid set/map
+# 2. Element already exists in set/map w. create
+# 3. Element is new but wants to jump to unknown chain
+# 4. Element already exsists in set/map w. add, but verdict (map data) differs
+# 5. Element is created/added/deleted from 'flags constant' set.
+random_elem()
+{
+ tr=$((RANDOM%2))
+ t=0
+
+ for table in $tables; do
+ if [ $t -ne $tr ]; then
+ t=$((t+1))
+ continue
+ fi
+
+ kr=$((RANDOM%2))
+ k=0
+ cnt=0
+ for key in "single" "concat"; do
+ if [ $k -ne $kr ] ;then
+ cnt=$((cnt+2))
+ k=$((k+1))
+ continue
+ fi
+
+ fr=$((RANDOM%2))
+ f=0
+
+ FLAGS=("")
+ available_flags FLAGS $key
+ for flags in "${FLAGS[@]}" ; do
+ cnt=$((cnt+1))
+ if [ $f -ne fkr ] ;then
+ f=$((f+1))
+ continue
+ fi
+
+ want="${key}${flags}"
+
+ e=$((RANDOM%256))
+ case "$want" in
+ "single") element="10.1.1.$e"
+ ;;
+ "concat") element="10.1.2.$e . $((RANDOM%65536))"
+ ;;
+ "singleinterval") element="10.1.$e.0-10.1.$e.$e"
+ ;;
+ "concatinterval") element="10.1.$e.0-10.1.$e.$e . $((RANDOM%65536))"
+ ;;
+ *) echo "bogus key $want"
+ exit 111
+ ;;
+ esac
+
+ # This may result in invalid jump, but thats what we want.
+ count=$(($RANDOM%100))
+
+ r=$((RANDOM%7))
+ case "$r" in
+ 0)
+ random_element_string=" inet $table set_${cnt} { $element }"
+ ;;
+ 1) random_element_string="inet $table sett${cnt} { $element timeout $((RANDOM%60))s }"
+ ;;
+ 2) random_element_string="inet $table dmap_${cnt} { $element : $RANDOM }"
+ ;;
+ 3) random_element_string="inet $table dmapt${cnt} { $element timeout $((RANDOM%60))s : $RANDOM }"
+ ;;
+ 4) random_element_string="inet $table vmap_${cnt} { $element : `random_verdict $count` }"
+ ;;
+ 5) random_element_string="inet $table vmapt${cnt} { $element timeout $((RANDOM%60))s : `random_verdict $count` }"
+ ;;
+ 6) random_element_string="inet $table setc${cnt} { $element }"
+ ;;
+ esac
+
+ return
+ done
+ done
+ done
+}
+
+randload()
+{
+ while [ -r $tmp ]; do
+ random_element_string=""
+ r=$((RANDOM%10))
+
+ what=""
+ case $r in
+ 1)
+ (echo "flush ruleset"; cat "$tmp"
+ echo "insert rule inet foo INPUT meta nftrace set 1"
+ echo "insert rule inet foo OUTPUT meta nftrace set 1"
+ ) | nft_with_fault_inject "/dev/stdin"
+ ;;
+ 2) what="add"
+ ;;
+ 3) what="create"
+ ;;
+ 4) what="delete"
+ ;;
+ 5) what="destroy"
+ ;;
+ 6) what="get"
+ ;;
+ *)
+ randsleep
+ ;;
+ esac
+
+ if [ x"$what" = "x" ]; then
+ nft_with_fault_inject "$tmp"
+ else
+ # This can trigger abort path, for various reasons:
+ # invalid set name
+ # key mismatches set specification (concat vs. single value)
+ # attempt to delete non-existent key
+ # attempt to create dupliacte key
+ # attempt to add duplicate key with non-matching value (data)
+ # attempt to add new uniqeue key with a jump to an unknown chain
+ random_elem
+ ( cat "$tmp"; echo "$what element $random_element_string") | nft_with_fault_inject "/dev/stdin"
+ fi
+ done
+}
+
+randmonitor()
+{
+ while [ -r $tmp ]; do
+ randsleep
+ timeout=$((RANDOM%16))
+ timeout $((timeout+1)) $NFT monitor > /dev/null
+ done
+}
+
+floodping() {
+ cpunum=$(grep -c processor /proc/cpuinfo)
+ cpunum=$((cpunum+1))
+
+ while [ -r $tmp ]; do
+ spawn=$((RANDOM%$cpunum))
+
+ # spawn at most $cpunum processes. Or maybe none at all.
+ i=0
+ while [ $i -lt $spawn ]; do
+ mask=$(printf 0x%x $((1<<$i)))
+ timeout 3 ip netns exec "$testns" taskset $mask ping -4 -fq 127.0.0.1 > /dev/null &
+ timeout 3 ip netns exec "$testns" taskset $mask ping -6 -fq ::1 > /dev/null &
+ i=$((i+1))
+ done
+
+ wait
+ randsleep
+ done
+}
+
+stress_all()
+{
+ # if fault injection is enabled, first a quick test to trigger
+ # abort paths without any parallel deletes/flushes.
+ if [ -w $faultname ] ;then
+ for i in $(seq 1 10);do
+ nft_with_fault_inject "$tmp"
+ done
+ fi
+
+ randlist &
+ randflush &
+ randdeltable &
+ randdisable &
+ randdelchain &
+ randdelset &
+ randdelns &
+ randload &
+ randmonitor &
+}
+
+gen_anon_chain_jump()
+{
+ echo -n "insert rule inet $@ "
+ jump_or_goto
+
+ if [ "$NFT_TEST_HAVE_chain_binding" = n ] ; then
+ echo " defaultchain"
+ return
+ fi
+
+ echo -n " { "
+ jump_or_goto
+ echo " defaultchain; counter; }"
+}
+
+gen_ruleset() {
+echo > "$tmp"
+for table in $tables; do
+ count=$((RANDOM % 100))
+ if [ $count -lt 1 ];then
+ count=1
+ fi
+
+ echo add table inet "$table" >> "$tmp"
+ echo flush table inet "$table" >> "$tmp"
+
+ echo "add chain inet $table INPUT { type filter hook input priority 0; }" >> "$tmp"
+ echo "add chain inet $table OUTPUT { type filter hook output priority 0; }" >> "$tmp"
+ for c in $(seq 1 $count); do
+ chain=$(printf "chain%03u" "$c")
+ echo "add chain inet $table $chain" >> "$tmp"
+ done
+
+ echo "add chain inet $table defaultchain" >> "$tmp"
+
+ for c in $(seq 1 $count); do
+ chain=$(printf "chain%03u" "$c")
+ for BASE in INPUT OUTPUT; do
+ echo "add rule inet $table $BASE counter jump $chain" >> "$tmp"
+ done
+ if [ $((RANDOM%10)) -eq 1 ];then
+ echo "add rule inet $table $chain counter jump defaultchain" >> "$tmp"
+ else
+ echo "add rule inet $table $chain counter return" >> "$tmp"
+ fi
+ done
+
+ cnt=0
+
+ # add a few anonymous sets. rhashtable is convered by named sets below.
+ c=$((RANDOM%$count))
+ chain=$(printf "chain%03u" "$((c+1))")
+ echo "insert rule inet $table $chain tcp dport 22-26 ip saddr { 1.2.3.4, 5.6.7.8 } counter comment hash_fast" >> "$tmp"
+ echo "insert rule inet $table $chain ip6 saddr { ::1, dead::beef } counter" comment hash >> "$tmp"
+ echo "insert rule inet $table $chain ip saddr { 1.2.3.4 - 5.6.7.8, 127.0.0.1 } comment rbtree" >> "$tmp"
+ # bitmap 1byte, with anon chain jump
+ gen_anon_chain_jump "$table $chain ip protocol { 6, 17 }" >> "$tmp"
+
+ # bitmap 2byte
+ echo "insert rule inet $table $chain tcp dport != { 22, 23, 80 } goto defaultchain" >> "$tmp"
+ echo "insert rule inet $table $chain tcp dport { 1-1024, 8000-8080 } jump defaultchain comment rbtree" >> "$tmp"
+ if [ "$NFT_TEST_HAVE_pipapo" = y ] ;then
+ # pipapo (concat + set), with goto anonymous chain.
+ gen_anon_chain_jump "$table $chain ip saddr . tcp dport { 1.2.3.4 . 1-1024, 1.2.3.6 - 1.2.3.10 . 8000-8080, 1.2.3.4 . 8080, 1.2.3.6 - 1.2.3.10 . 22 }" >> "$tmp"
+ fi
+
+ # add a few anonymous sets. rhashtable is convered by named sets below.
+ c=$((RANDOM%$count))
+ chain=$(printf "chain%03u" "$((c+1))")
+ echo "insert rule inet $table $chain tcp dport 22-26 ip saddr { 1.2.3.4, 5.6.7.8 } counter comment hash_fast" >> "$tmp"
+ echo "insert rule inet $table $chain ip6 saddr { ::1, dead::beef } counter" comment hash >> "$tmp"
+ echo "insert rule inet $table $chain ip saddr { 1.2.3.4 - 5.6.7.8, 127.0.0.1 } comment rbtree" >> "$tmp"
+ # bitmap 1byte, with anon chain jump
+ gen_anon_chain_jump "$table $chain ip protocol { 6, 17 }" >> "$tmp"
+ # bitmap 2byte
+ echo "insert rule inet $table $chain tcp dport != { 22, 23, 80 } goto defaultchain" >> "$tmp"
+ echo "insert rule inet $table $chain tcp dport { 1-1024, 8000-8080 } jump defaultchain comment rbtree" >> "$tmp"
+ if [ "$NFT_TEST_HAVE_pipapo" = y ] ;then
+ # pipapo (concat + set), with goto anonymous chain.
+ gen_anon_chain_jump "$table $chain ip saddr . tcp dport { 1.2.3.4 . 1-1024, 1.2.3.6 - 1.2.3.10 . 8000-8080, 1.2.3.4 . 8080, 1.2.3.6 - 1.2.3.10 . 22 }" >> "$tmp"
+ fi
+
+ # add constant/immutable sets
+ size=$((RANDOM%5120000))
+ size=$((size+2))
+ echo "add set inet $table setc1 { typeof tcp dport; size $size; flags constant; elements = { 22, 44 } }" >> "$tmp"
+ echo "add set inet $table setc2 { typeof ip saddr; size $size; flags constant; elements = { 1.2.3.4, 5.6.7.8 } }" >> "$tmp"
+ echo "add set inet $table setc3 { typeof ip6 daddr; size $size; flags constant; elements = { ::1, dead::1 } }" >> "$tmp"
+ echo "add set inet $table setc4 { typeof tcp dport; size $size; flags interval,constant; elements = { 22-44, 55-66 } }" >> "$tmp"
+ echo "add set inet $table setc5 { typeof ip saddr; size $size; flags interval,constant; elements = { 1.2.3.4-5.6.7.8, 10.1.1.1 } }" >> "$tmp"
+ echo "add set inet $table setc6 { typeof ip6 daddr; size $size; flags interval,constant; elements = { ::1, dead::1-dead::3 } }" >> "$tmp"
+
+ # add named sets with various combinations (plain value, range, concatenated values, concatenated ranges, with timeouts, with data ...)
+ for key in "ip saddr" "ip saddr . tcp dport"; do
+ FLAGS=("")
+ if [ "$key" == "ip saddr" ] ;then
+ FLAGS+=("flags interval;")
+ elif [ "$key" == "ip saddr . tcp dport" ] ;then
+ if [ "$NFT_TEST_HAVE_pipapo" = y ] ;then
+ FLAGS+=("flags interval;")
+ fi
+ fi
+ for ((i = 0; i < ${#FLAGS[@]}; i++)) ; do
+ timeout=$((RANDOM%10))
+ timeout=$((timeout+1))
+ timeout="timeout ${timeout}s"
+
+ cnt=$((cnt+1))
+ flags=${FLAGS[$i]}
+ echo "add set inet $table set_${cnt} { typeof ${key} ; ${flags} }" >> "$tmp"
+ echo "add set inet $table sett${cnt} { typeof ${key} ; $timeout; ${flags} }" >> "$tmp"
+ echo "add map inet $table dmap_${cnt} { typeof ${key} : meta mark ; ${flags} }" >> "$tmp"
+ echo "add map inet $table dmapt${cnt} { typeof ${key} : meta mark ; $timeout ; ${flags} }" >> "$tmp"
+ echo "add map inet $table vmap_${cnt} { typeof ${key} : verdict ; ${flags} }" >> "$tmp"
+ echo "add map inet $table vmapt${cnt} { typeof ${key} : verdict; $timeout ; ${flags} }" >> "$tmp"
+ done
+ done
+
+ cnt=0
+ for key in "single" "concat"; do
+ FLAGS=("")
+ available_flags FLAGS $key
+
+ for ((i = 0; i < ${#FLAGS[@]}; i++)) ; do
+ flags=${FLAGS[$i]}
+ want="${key}${flags}"
+ cnt=$((cnt+1))
+ maxip=$((RANDOM%256))
+
+ if [ $maxip -eq 0 ];then
+ maxip=1
+ fi
+
+ for e in $(seq 1 $maxip);do
+ case "$want" in
+ "single") element="10.1.1.$e"
+ ;;
+ "concat")
+ element="10.1.2.$e . $((RANDOM%65536))"
+ ;;
+ "singleinterval")
+ element="10.1.$e.0-10.1.$e.$e"
+ ;;
+ "concatinterval")
+ element="10.1.$e.0-10.1.$e.$e . $((RANDOM%65536))"
+ ;;
+ *)
+ echo "bogus key $want"
+ exit 111
+ ;;
+ esac
+
+ echo "add element inet $table set_${cnt} { $element }" >> "$tmp"
+ echo "add element inet $table sett${cnt} { $element timeout $((RANDOM%60))s }" >> "$tmp"
+ echo "add element inet $table dmap_${cnt} { $element : $RANDOM }" >> "$tmp"
+ echo "add element inet $table dmapt${cnt} { $element timeout $((RANDOM%60))s : $RANDOM }" >> "$tmp"
+ echo "add element inet $table vmap_${cnt} { $element : `random_verdict $count` }" >> "$tmp"
+ echo "add element inet $table vmapt${cnt} { $element timeout $((RANDOM%60))s : `random_verdict $count` }" >> "$tmp"
+ done
+ done
+ done
+done
+}
+
+run_test()
+{
+ local time_now=$(date +%s)
+ local time_stop=$((time_now + $runtime))
+ local regen=30
+
+ while [ $time_now -lt $time_stop ]; do
+ if [ $regen -gt 0 ];then
+ sleep 1
+ time_now=$(date +%s)
+ regen=$((regen-1))
+ continue
+ fi
+
+ # This clobbers the previously generated ruleset, this is intentional.
+ gen_ruleset
+ regen=$((RANDOM%60))
+ regen=$((regen+2))
+ time_now=$(date +%s)
+ done
+}
+
+netns_add
+
+gen_ruleset
+ip netns exec "$testns" $NFT -f "$tmp" || exit 1
+
+failslab_defaults
+
+stress_all 2>/dev/null &
+
+randsleep
+
+floodping 2> /dev/null &
+
+run_test
+
+# this stops stress_all
+rm -f "$tmp"
+tmp=""
+sleep 4
+
+if [ "$NFT_TEST_HAVE_chain_binding" = n ] ; then
+ echo "Ran a modified version of the test due to NFT_TEST_HAVE_chain_binding=n"
+fi