]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
tests: add test script for race-free restore
authorFlorian Westphal <fw@strlen.de>
Tue, 23 Apr 2019 13:16:25 +0000 (15:16 +0200)
committerFlorian Westphal <fw@strlen.de>
Fri, 26 Apr 2019 23:08:54 +0000 (01:08 +0200)
xtables-nft-restore ignores -w, check that we don't add
duplicate rules when parallel restores happen.

With a slightly older iptables-nft version this ususally fails with:
I: [EXECUTING] iptables/tests/shell/testcases/ipt-restore/0004-restore-race_0
iptables-restore v1.8.2 (nf_tables):
line 5: CHAIN_USER_ADD failed (File exists): chain UC-0
line 6: CHAIN_USER_ADD failed (File exists): chain UC-1
W: [FAILED] ipt-restore/0004-restore-race_0: expected 0 but got 4

or
I: [EXECUTING]   iptables/tests/shell/testcases/ipt-restore/0004-restore-race_0
iptables-restore v1.8.2 (nf_tables):
line 1: TABLE_FLUSH failed (No such file or directory): table filter

or
/tmp/tmp.SItN4URxxF /tmp/tmp.P1y4LIxhTl differ: byte 7159, line 137

As the legacy version should not have such race (due to nature
of full-table-replace), only do one iteration for legacy case.

Signed-off-by: Florian Westphal <fw@strlen.de>
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
iptables/tests/shell/testcases/ipt-restore/0004-restore-race_0 [new file with mode: 0755]

diff --git a/iptables/tests/shell/testcases/ipt-restore/0004-restore-race_0 b/iptables/tests/shell/testcases/ipt-restore/0004-restore-race_0
new file mode 100755 (executable)
index 0000000..14b910e
--- /dev/null
@@ -0,0 +1,119 @@
+#!/bin/bash
+
+export XTABLES_LIBDIR=$(pwd)/extensions
+have_nft=false
+nft -v > /dev/null && have_nft=true
+
+dumpfile=""
+tmpfile=""
+
+set -e
+
+clean()
+{
+       $XT_MULTI iptables -t filter -F
+       $XT_MULTI iptables -t filter -X
+       $have_nft && nft flush ruleset
+}
+
+clean_tempfile()
+{
+       [ -n "${tmpfile}" ] && rm -f "${tmpfile}"
+       [ -n "${dumpfile}" ] && rm -f "${dumpfile}"
+       clean
+}
+
+trap clean_tempfile EXIT
+
+ENTRY_NUM=$((RANDOM%100))
+UCHAIN_NUM=$((RANDOM%10))
+
+get_target()
+{
+       if [ $UCHAIN_NUM -eq 0 ]; then
+               echo -n "ACCEPT"
+               return
+       fi
+
+
+       x=$((RANDOM%2))
+       if [ $x -eq 0 ];then
+               echo -n "ACCEPT"
+       else
+               printf -- "UC-%x" $((RANDOM%UCHAIN_NUM))
+       fi
+}
+
+make_dummy_rules()
+{
+
+       echo "*filter"
+       echo ":INPUT ACCEPT [0:0]"
+       echo ":FORWARD ACCEPT [0:0]"
+       echo ":OUTPUT ACCEPT [0:0]"
+
+       if [ $UCHAIN_NUM -gt 0 ]; then
+               for i in $(seq 0 $UCHAIN_NUM); do
+                       printf -- ":UC-%x - [0:0]\n" $i
+               done
+       fi
+
+       for proto in tcp udp sctp; do
+               for i in $(seq 0 $ENTRY_NUM); do
+                       t=$(get_target)
+                       printf -- "-A INPUT -i lo -p $proto --dport %d -j %s\n" $((61000-i)) $t
+                       t=$(get_target)
+                       printf -- "-A FORWARD -i lo -o lo -p $proto --dport %d -j %s\n" $((61000-i)) $t
+                       t=$(get_target)
+                       printf -- "-A OUTPUT -o lo -p $proto --dport %d -j %s\n" $((61000-i)) $t
+                       [ $UCHAIN_NUM -gt 0 ] && printf -- "-A UC-%x -j ACCEPT\n" $((RANDOM%UCHAIN_NUM))
+               done
+       done
+       echo COMMIT
+}
+
+tmpfile=$(mktemp) || exit 1
+dumpfile=$(mktemp) || exit 1
+
+make_dummy_rules > $dumpfile
+$XT_MULTI iptables-restore -w < $dumpfile
+LINES=$(wc -l < $dumpfile)
+$XT_MULTI iptables-save | grep -v '^#' > $dumpfile
+LINES2=$(wc -l < $dumpfile)
+
+if [ $LINES -ne $LINES2 ]; then
+       echo "Original dump has $LINES, not $LINES2" 1>&2
+       exit 111
+fi
+
+case "$XT_MULTI" in
+*/xtables-nft-multi)
+       attempts=$((RANDOM%200))
+       attempts=$((attempts+1))
+       ;;
+*)
+       attempts=1
+       ;;
+esac
+
+while [ $attempts -gt 0 ]; do
+       attempts=$((attempts-1))
+
+       clean
+
+       for i in $(seq 1 10); do
+               $XT_MULTI iptables-restore -w 15 < $dumpfile &
+       done
+
+       for i in $(seq 1 10); do
+               # causes exit in case ipt-restore failed (runs with set -e)
+               wait %$i
+       done
+
+       $XT_MULTI iptables-save | grep -v '^#' > $tmpfile
+
+       clean
+       cmp $tmpfile $dumpfile
+done
+
+exit 0