You probably noticed this,  but choose-port.pl is sometimes being used to 
return a free TCP port.... which is promptly used for UDP.   Perhaps 
choose-port.pl should take an argument?

Neil

On Apr 3, 2013, at 12:02 PM, Ben Pfaff wrote:

> An occasionally occurring problem with "make check", especially when
> parallel tests are enabled, is that multiple tests try to bind the same
> TCP port and, of course, fail.  This happens because the code to select
> a TCP port to bind just generates random numbers until it finds a port that
> is not currently in use and uses the first one, which is of course prone
> to races.
> 
> This commit changes the tests to let the kernel directly choose an
> available port, which should avoid this type of failure.
> 
> Signed-off-by: Ben Pfaff <b...@nicira.com>
> ---
> tests/automake.mk       |    2 --
> tests/choose-port.pl    |   26 --------------------------
> tests/ofproto-dpif.at   |   33 ++++++++++++++++-----------------
> tests/ofproto-macros.at |   17 +++++++++++++++++
> tests/ovsdb-idl.at      |    7 ++++---
> tests/ovsdb-server.at   |   26 +++++++++++++-------------
> 6 files changed, 50 insertions(+), 61 deletions(-)
> delete mode 100644 tests/choose-port.pl
> 
> diff --git a/tests/automake.mk b/tests/automake.mk
> index 275ff53..aad8692 100644
> --- a/tests/automake.mk
> +++ b/tests/automake.mk
> @@ -300,8 +300,6 @@ noinst_PROGRAMS += tests/test-byte-order
> tests_test_byte_order_SOURCES = tests/test-byte-order.c
> tests_test_byte_order_LDADD = lib/libopenvswitch.a
> 
> -EXTRA_DIST += tests/choose-port.pl
> -
> # Python tests.
> CHECK_PYFILES = \
>       tests/appctl.py \
> diff --git a/tests/choose-port.pl b/tests/choose-port.pl
> deleted file mode 100644
> index 46c8db5..0000000
> --- a/tests/choose-port.pl
> +++ /dev/null
> @@ -1,26 +0,0 @@
> -# -*- perl -*-
> -
> -# Picks a random TCP port and attempts to bind it, retrying a few
> -# times if the chosen port is in use.  This is better than just
> -# picking a random number without checking whether it is in use (but
> -# of course a race window still exists).
> -#
> -# On success, prints a port number on stdout and exits with status 0.
> -# On failure, prints an error on stderr and exits with a nonzero status.
> -
> -use warnings;
> -use strict;
> -use Socket;
> -
> -socket(SOCK, PF_INET, SOCK_STREAM, 0) || die "socket: $!\n";
> -for (my ($i) = 0; ; $i++) {
> -    my ($port) = int(rand(16383)) + 49152;
> -    if (bind(SOCK, sockaddr_in($port, INADDR_ANY))) {
> -        print "$port\n";
> -        exit 0;
> -    } elsif ($i < 10 && $!{EADDRINUSE}) {
> -        # Address already in use.  Try again.
> -    } else {
> -        die "bind: $!\n";
> -    }
> -}
> diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
> index 06ebf23..857e6ab 100644
> --- a/tests/ofproto-dpif.at
> +++ b/tests/ofproto-dpif.at
> @@ -1208,10 +1208,12 @@ AT_CLEANUP
> 
> dnl Test that sFlow samples packets correctly.
> AT_SETUP([ofproto-dpif - sFlow packet sampling])
> -AT_CHECK([perl $srcdir/choose-port.pl], [0], [stdout])
> -SFLOW_PORT=`cat stdout`
> OVS_VSWITCHD_START([set Bridge br0 fail-mode=standalone])
> 
> +AT_CHECK([test-sflow --log-file --detach --no-chdir --pidfile 0:127.0.0.1 > 
> sflow.log], [0], [], [ignore])
> +AT_CAPTURE_FILE([sflow.log])
> +SFLOW_PORT=`parse_listening_port < test-sflow.log`
> +
> ovs-appctl time/stop
> 
> ADD_OF_PORTS([br0], 1, 2)
> @@ -1223,8 +1225,6 @@ ovs-vsctl \
>    --id=@sf create sflow targets=\"127.0.0.1:$SFLOW_PORT\" \
>      header=128 sampling=1 polling=1
> ON_EXIT([kill `cat test-sflow.pid`])
> -AT_CHECK([test-sflow --detach --no-chdir --pidfile $SFLOW_PORT:127.0.0.1 > 
> sflow.log])
> -AT_CAPTURE_FILE([sflow.log])
> 
> dnl open with ARP packets to seed the bridge-learning.  The output
> dnl ifIndex numbers should be reported predictably after that.
> @@ -1504,20 +1504,19 @@ dnl - Flow actions changing (in this case, due to MAC 
> learning)
> dnl   cause a record to be sent.
> AT_SETUP([ofproto-dpif - NetFlow flow expiration])
> 
> -AT_CHECK([perl $srcdir/choose-port.pl], [0], [stdout])
> -NETFLOW_PORT=`cat stdout`
> -
> OVS_VSWITCHD_START([set Bridge br0 fail-mode=standalone])
> ADD_OF_PORTS([br0], 1, 2)
> +
> +ON_EXIT([kill `cat test-netflow.pid`])
> +AT_CHECK([test-netflow --log-file --detach --no-chdir --pidfile 0:127.0.0.1 
> > netflow.log], [0], [], [ignore])
> +AT_CAPTURE_FILE([netflow.log])
> +NETFLOW_PORT=`parse_listening_port < test-netflow.log`
> +
> ovs-vsctl \
>    set Bridge br0 netflow=@nf -- \
>    --id=@nf create NetFlow targets=\"127.0.0.1:$NETFLOW_PORT\" \
>      engine_id=1 engine_type=2 active_timeout=30 add-id-to-interface=false
> 
> -ON_EXIT([kill `cat test-netflow.pid`])
> -AT_CHECK([test-netflow --detach --no-chdir --pidfile $NETFLOW_PORT:127.0.0.1 
> > netflow.log])
> -AT_CAPTURE_FILE([netflow.log])
> -
> for delay in 1000 30000; do
>     ovs-appctl netdev-dummy/receive p1 
> 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'
>     ovs-appctl netdev-dummy/receive p2 
> 'in_port(1),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=0,code=0)'
> @@ -1546,19 +1545,19 @@ AT_CLEANUP
> dnl Test that basic NetFlow reports active expirations correctly.
> AT_SETUP([ofproto-dpif - NetFlow active expiration])
> 
> -AT_CHECK([perl $srcdir/choose-port.pl], [0], [stdout])
> -NETFLOW_PORT=`cat stdout`
> -
> OVS_VSWITCHD_START([set Bridge br0 fail-mode=standalone])
> ADD_OF_PORTS([br0], 1, 2)
> +
> +ON_EXIT([kill `cat test-netflow.pid`])
> +AT_CHECK([test-netflow --log-file --detach --no-chdir --pidfile 0:127.0.0.1 
> > netflow.log], [0], [], [ignore])
> +AT_CAPTURE_FILE([netflow.log])
> +NETFLOW_PORT=`parse_listening_port < test-netflow.log`
> +
> ovs-vsctl \
>    set Bridge br0 netflow=@nf -- \
>    --id=@nf create NetFlow targets=\"127.0.0.1:$NETFLOW_PORT\" \
>      engine_id=1 engine_type=2 active_timeout=10 add-id-to-interface=false
> 
> -ON_EXIT([kill `cat test-netflow.pid`])
> -AT_CHECK([test-netflow --detach --no-chdir --pidfile $NETFLOW_PORT:127.0.0.1 
> > netflow.log])AT_CAPTURE_FILE([netflow.log])
> -
> AT_CHECK([ovs-appctl time/stop])
> n=1
> while test $n -le 60; do
> diff --git a/tests/ofproto-macros.at b/tests/ofproto-macros.at
> index 9a6d5ab..cad0080 100644
> --- a/tests/ofproto-macros.at
> +++ b/tests/ofproto-macros.at
> @@ -13,6 +13,23 @@ s/ n_bytes=0,//
> s/ idle_age=[0-9]*,//
> s/ hard_age=[0-9]*,//
> '
> +}
> +
> +# parse_listening_port [SERVER]
> +#
> +# Parses the TCP or SSL port on which a server is listening from the log,
> +# given that the server was told to listen on a kernel-chosen port,
> +# file provided on stdin, and prints the port number on stdout.
> +#
> +# Here's an example of how to use this with ovsdb-server:
> +#
> +#    OVS_LOGDIR=`pwd`; export OVS_LOGDIR
> +#    ovsdb-server --log-file --remote=ptcp:0:127.0.0.1 ...
> +#    TCP_PORT=`parse_listening_port < ovsdb-server.log`
> +#
> +# (Also works with pssl: in place of ptcp:.)
> +parse_listening_port () {
> +    sed -n 's/.*0:127\.0\.0\.1: listening on port \([0-9]*\)$/\1/p'
> }]
> m4_divert_pop([PREPARE_TESTS])
> 
> diff --git a/tests/ovsdb-idl.at b/tests/ovsdb-idl.at
> index 3c32e2f..21a22db 100644
> --- a/tests/ovsdb-idl.at
> +++ b/tests/ovsdb-idl.at
> @@ -57,11 +57,12 @@ m4_define([OVSDB_CHECK_IDL_TCP_PY],
>    AT_SKIP_IF([test $HAVE_PYTHON = no])
>    AT_KEYWORDS([ovsdb server idl positive Python with tcp socket $5])
>    OVS_RUNDIR=`pwd`; export OVS_RUNDIR
> +   OVS_LOGDIR=`pwd`; export OVS_LOGDIR
>    AT_CHECK([ovsdb-tool create db $abs_srcdir/idltest.ovsschema],
>                   [0], [stdout], [ignore])
> -   AT_CHECK([perl $srcdir/choose-port.pl], [0], [stdout])
> -   TCP_PORT=`cat stdout`
> -   AT_CHECK([ovsdb-server '-vPATTERN:console:ovsdb-server|%c|%m' --detach 
> --no-chdir --pidfile="`pwd`"/pid --remote=ptcp:$TCP_PORT:127.0.0.1 
> --unixctl="`pwd`"/unixctl db], [0], [ignore], [ignore])
> +   AT_CHECK([ovsdb-server --log-file '-vPATTERN:console:ovsdb-server|%c|%m' 
> --detach --no-chdir --pidfile="`pwd`"/pid --remote=punix:socket 
> --remote=ptcp:0:127.0.0.1 --unixctl="`pwd`"/unixctl db], [0], [ignore], 
> [ignore])
> +   TCP_PORT=`parse_listening_port < ovsdb-server.log`
> +
>    m4_if([$2], [], [],
>      [AT_CHECK([ovsdb-client transact tcp:127.0.0.1:$TCP_PORT $2], [0], 
> [ignore], [ignore], [kill `cat pid`])])
>    AT_CHECK([$PYTHON $srcdir/test-ovsdb.py  -t10 idl 
> $srcdir/idltest.ovsschema tcp:127.0.0.1:$TCP_PORT $3],
> diff --git a/tests/ovsdb-server.at b/tests/ovsdb-server.at
> index 62eae38..9cabab2 100644
> --- a/tests/ovsdb-server.at
> +++ b/tests/ovsdb-server.at
> @@ -254,15 +254,15 @@ AT_CHECK(
>                 "certificate": "'"$PKIDIR/testpki-cert2.pem"'",
>                 "ca_cert": "'"$PKIDIR/testpki-cacert.pem"'"}}]']],
>   [0], [ignore], [ignore])
> -AT_CHECK([perl $srcdir/choose-port.pl], [0], [stdout])
> -SSL_PORT=`cat stdout`
> +OVS_LOGDIR=`pwd`; export OVS_LOGDIR
> AT_CHECK(
> -  [ovsdb-server --detach --no-chdir --pidfile="`pwd`"/pid \
> +  [ovsdb-server --log-file --detach --no-chdir --pidfile="`pwd`"/pid \
>         --private-key=db:SSL,private_key \
>         --certificate=db:SSL,certificate \
>         --ca-cert=db:SSL,ca_cert \
> -         --remote=pssl:$SSL_PORT:127.0.0.1 --unixctl="`pwd`"/unixctl db],
> +        --remote=pssl:0:127.0.0.1 --unixctl="`pwd`"/unixctl db],
>   [0], [ignore], [ignore])
> +SSL_PORT=`parse_listening_port < ovsdb-server.log`
> AT_CHECK(
>   [[ovsdb-client \
>         --private-key=$PKIDIR/testpki-privkey.pem \
> @@ -437,12 +437,12 @@ m4_define([OVSDB_CHECK_EXECUTION],
>    AT_KEYWORDS([ovsdb server positive ssl $5])
>    AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
>    OVS_RUNDIR=`pwd`; export OVS_RUNDIR
> +   OVS_LOGDIR=`pwd`; export OVS_LOGDIR
>    $2 > schema
> -   AT_CHECK([perl $srcdir/choose-port.pl], [0], [stdout])
> -   SSL_PORT=`cat stdout`
>    PKIDIR=$abs_top_builddir/tests
>    AT_CHECK([ovsdb-tool create db schema], [0], [stdout], [ignore])
> -   AT_CHECK([ovsdb-server --detach --no-chdir --pidfile="`pwd`"/pid 
> --private-key=$PKIDIR/testpki-privkey2.pem 
> --certificate=$PKIDIR/testpki-cert2.pem --ca-cert=$PKIDIR/testpki-cacert.pem 
> --remote=pssl:$SSL_PORT:127.0.0.1 --unixctl="`pwd`"/unixctl db], [0], 
> [ignore], [ignore])
> +   AT_CHECK([ovsdb-server --log-file --detach --no-chdir 
> --pidfile="`pwd`"/pid --private-key=$PKIDIR/testpki-privkey2.pem 
> --certificate=$PKIDIR/testpki-cert2.pem --ca-cert=$PKIDIR/testpki-cacert.pem 
> --remote=pssl:0:127.0.0.1 --unixctl="`pwd`"/unixctl db], [0], [ignore], 
> [ignore])
> +   SSL_PORT=`parse_listening_port < ovsdb-server.log`
>    m4_foreach([txn], [$3], 
>      [AT_CHECK([ovsdb-client --private-key=$PKIDIR/testpki-privkey.pem 
> --certificate=$PKIDIR/testpki-cert.pem --ca-cert=$PKIDIR/testpki-cacert.pem 
> transact ssl:127.0.0.1:$SSL_PORT 'txn'], [0], [stdout], [ignore],
>      [test ! -e pid || kill `cat pid`])
> @@ -460,10 +460,10 @@ AT_BANNER([OVSDB -- ovsdb-server transactions (TCP 
> sockets)])
> AT_SETUP([ovsdb-client get-schema-version - tcp socket])
> AT_KEYWORDS([ovsdb server positive tcp])
> ordinal_schema > schema
> -AT_CHECK([perl $srcdir/choose-port.pl], [0], [stdout])
> -TCP_PORT=`cat stdout`
> AT_CHECK([ovsdb-tool create db schema], [0], [ignore], [ignore])
> -AT_CHECK([ovsdb-server --detach --no-chdir --pidfile="`pwd`"/pid 
> --unixctl="`pwd`"/unixctl --remote=ptcp:$TCP_PORT:127.0.0.1 db], [0], 
> [ignore], [ignore])
> +OVS_LOGDIR=`pwd`; export OVS_LOGDIR
> +AT_CHECK([ovsdb-server --log-file --detach --no-chdir --pidfile="`pwd`"/pid 
> --unixctl="`pwd`"/unixctl --remote=ptcp:0:127.0.0.1 db], [0], [ignore], 
> [ignore])
> +TCP_PORT=`parse_listening_port < ovsdb-server.log`
> AT_CHECK([ovsdb-client get-schema-version tcp:127.0.0.1:$TCP_PORT ordinals], 
> [0], [5.1.3
> ])
> OVSDB_SERVER_SHUTDOWN
> @@ -487,12 +487,12 @@ m4_define([OVSDB_CHECK_EXECUTION],
>   [AT_SETUP([$1])
>    AT_KEYWORDS([ovsdb server positive tcp $5])
>    OVS_RUNDIR=`pwd`; export OVS_RUNDIR
> +   OVS_LOGDIR=`pwd`; export OVS_LOGDIR
>    $2 > schema
> -   AT_CHECK([perl $srcdir/choose-port.pl], [0], [stdout])
> -   TCP_PORT=`cat stdout`
>    PKIDIR=$abs_top_builddir/tests
>    AT_CHECK([ovsdb-tool create db schema], [0], [stdout], [ignore])
> -   AT_CHECK([ovsdb-server --detach --no-chdir --pidfile="`pwd`"/pid 
> --remote=ptcp:$TCP_PORT:127.0.0.1 --unixctl="`pwd`"/unixctl db], [0], 
> [ignore], [ignore])
> +   AT_CHECK([ovsdb-server --log-file --detach --no-chdir 
> --pidfile="`pwd`"/pid --remote=ptcp:0:127.0.0.1 --unixctl="`pwd`"/unixctl 
> db], [0], [ignore], [ignore])
> +   TCP_PORT=`parse_listening_port < ovsdb-server.log`
>    m4_foreach([txn], [$3],
>      [AT_CHECK([ovsdb-client transact tcp:127.0.0.1:$TCP_PORT 'txn'], [0], 
> [stdout], [ignore],
>      [test ! -e pid || kill `cat pid`])
> -- 
> 1.7.10.4
> 
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to