testing: Wait for packets to be processed by tcpdump
authorTobias Brunner <tobias@strongswan.org>
Tue, 14 Jun 2016 18:41:43 +0000 (20:41 +0200)
committerTobias Brunner <tobias@strongswan.org>
Thu, 16 Jun 2016 12:36:15 +0000 (14:36 +0200)
Sometimes tcpdump fails to process all packets during the short running
time of a scenario:

0 packets captured
18 packets received by filter
0 packets dropped by kernel

So 18 packets were captured by libpcap but tcpdump did not yet process
and print them.

This tries to use --immediate-mode if supported by tcpdump (the one
currently in jessie or wheezy does not, but the one in jessie-backports
does), which disables the buffering in libpcap.

However, even with immediate mode there are cases where it takes a while
longer for all packets to get processed.  And without it we also need a
workaround (even though the version in wheezy actually works fine).
That's why there now is a loop checking for differences in captured vs.
received packets.  There are actually cases where these numbers are not
equal but we still captured all packets we're interested in, so we abort
after 1s of retrying.  But sometimes it could still happen that packets
we expected got lost somewhere ("packets dropped by kernel" is not
always 0 either).

testing/do-tests

index 992f3f5..d0d1ead 100755 (executable)
@@ -111,6 +111,13 @@ done
 [ -f $SHAREDDIR/.strongswan-version ] && SWANVERSION=`cat $SHAREDDIR/.strongswan-version`
 KERNELVERSION=`ssh $SSHCONF root@\$ipv4_winnetou uname -r 2>/dev/null`
 
+# check if tcpdump supports --immediate-mode
+ssh $SSHCONF root@$ipv4_winnetou tcpdump --immediate-mode -c 1 >/dev/null 2>&1
+if [ $? -eq 0 ]
+then
+       TCPDUMP_IM=--immediate-mode
+fi
+
 ##############################################################################
 # create header for the results html file
 #
@@ -359,7 +366,7 @@ do
            do
                host=`echo $host_iface | awk -F ":" '{print $1}'`
                iface=`echo $host_iface | awk -F ":" '{if ($2 != "") { print $2 } else { printf("eth0") }}'`
-               tcpdump_cmd="tcpdump -i $iface not port ssh and not port domain > /tmp/tcpdump.log 2>&1 &"
+               tcpdump_cmd="tcpdump -l $TCPDUMP_IM -i $iface not port ssh and not port domain >/tmp/tcpdump.log 2>/tmp/tcpdump.err.log &"
                echo "${host}# $tcpdump_cmd" >> $CONSOLE_LOG
                ssh $SSHCONF root@`eval echo \\\$ipv4_$host '$tcpdump_cmd'`
                eval TDUP_${host}="true"
@@ -417,6 +424,8 @@ do
        #
 
        function stop_tcpdump {
+           # wait for packets to get processed, but don't wait longer than 1s
+           eval ssh $SSHCONF root@\$ipv4_${1} "\"i=100; while [ \\\$i -gt 0 ]; do pkill -USR1 tcpdump; tail -1 /tmp/tcpdump.err.log | perl -n -e '/(\\d+).*?(\\d+)/; exit (\\\$1 == \\\$2)' || break; sleep 0.01; i=\\\$((\\\$i-1)); done;\""
            echo "${1}# killall tcpdump" >> $CONSOLE_LOG
            eval ssh $SSHCONF root@\$ipv4_${1} "\"killall tcpdump; while true; do killall -q -0 tcpdump || break; sleep 0.01; done;\""
            eval TDUP_${1}="false"