Thanks for writing this up.  I haven't read it closely yet.

I think using iperf to perform these tests is a great idea and the
right approach.  So far, the patch looks like it will be a great
improvement over the existing code.

I'm not quite sure we are getting a great deal of value out of the
twisted framework.  I may be misunderstanding it, but it looks to me
like all it does is start and stop iperf on the client and server
side, and help collect the output.  I think we can completely get rid
of the ovs-vlan-test server mode and just require the user to run
iperf in server mode at the destination, it already has a control
channel built in that can handle indicating test start and stops.  If
we do this, we can simply run iperf several times on the client side
and collect the results.  Doing this should be pretty trivial with the
standard python library.  Alternatively, we could keep the
ovs-vlan-test server mode and have it run iperf directly using the
python subprocess library without having to go through a framework.
Either way, we don't need to implement a control channel on top of the
one already built into iperf.

If we decided to go with twisted, we are going to have to update the
packaging for the non-debian platforms as well (notably rhel).

Ethan

On Tue, Oct 18, 2011 at 21:23, Ansis Atteka <aatt...@nicira.com> wrote:
> ovs-vlan-test runs through a number of tests to identify VLAN issues.  This
> is useful when trying to debug why a particular driver has issues, but it made
> the testing environment a bit harder to set up.  This commit adds an iperf
> test to check basic functionality.  It also useful in detecting performance
> issues.
>
> Issue #6976
> ---
>  utilities/ovs-vlan-test.8.in |   69 ++++---
>  utilities/ovs-vlan-test.in   |  545 
> +++++++++++-------------------------------
>  2 files changed, 184 insertions(+), 430 deletions(-)
>
> diff --git a/utilities/ovs-vlan-test.8.in b/utilities/ovs-vlan-test.8.in
> index 602d785..6e69f23 100644
> --- a/utilities/ovs-vlan-test.8.in
> +++ b/utilities/ovs-vlan-test.8.in
> @@ -1,45 +1,58 @@
> -.TH ovs\-vlan\-test 1 "December 2010" "Open vSwitch" "Open vSwitch Manual"
> +.TH ovs\-vlan\-test 1 "October 2011" "Open vSwitch" "Open vSwitch Manual"
>  .
>  .SH NAME
>  \fBovs\-vlan\-test\fR \- check Linux drivers for problems with vlan traffic
>  .
>  .SH SYNOPSIS
> -\fBovs\-vlan\-test\fR [\fB\-s\fR | \fB\-\-server\fR] \fIcontrol_ip\fR 
> \fIvlan_ip\fR
> +\fBovs\-vlan\-test\fR [\fB\-s\fR \fISERVERPORT\fR|\fB\-c\fR 
> \fISERVERIPPORT\fR]
> +[\fB\-b\fR \fITARGETBANDWIDTH\fR]
>  .so lib/common-syn.man
>  .
>  .SH DESCRIPTION
> -The \fBovs\-vlan\-test\fR program may be used to check for problems sending
> -802.1Q traffic which may occur when running Open vSwitch. These problems can
> -occur when Open vSwitch is used to send 802.1Q traffic through physical
> -interfaces running certain drivers of certain Linux kernel versions. To run a
> -test, configure Open vSwitch to tag traffic originating from \fIvlan_ip\fR 
> and
> -forward it out the target interface. Then run the \fBovs\-vlan\-test\fR in
> -client mode connecting to an \fBovs\-vlan\-test\fR server.
> -\fBovs\-vlan\-test\fR will display "OK" if it did not detect problems.
> +The \fBovs\-vlan\-test\fR program automates \fBiperf\fR utility and allows to
> +detect connectivity and performance problems. These problems can occur when
> +Open vSwitch is used to send 802.1Q traffic through physical interfaces 
> running
> +certain drivers of certain Linux kernel versions. To run a test, configure 
> Open
> +vSwitch to tag traffic originating from interface where \fBovs\-vlan\-test\fR
> +client will connect and forward it to the target interface where
> +\fBovs\-vlan\-test\fR server will be listening. Then run the
> +\fBovs\-vlan\-test\fR in client mode so that it connects to an
> +\fBovs\-vlan\-test\fR server. \fBovs\-vlan\-test\fR client will display "OK" 
> if
> +it did not detect any problems. Besides from that client will also display
> +count of lost and out-of-order packets for all UDP tests.
> +
> +.PP
> +UDP do not have effective flow control, so user is responsible to adjust 
> target
> +bandwidth (-b parameter). If target bandwidth is greater than the network
> +is able to handle then packet loss will occur.
> +
>  .PP
>  Some examples of the types of problems that may be encountered are:
>  .so utilities/ovs-vlan-bugs.man
>  .
>  .SS "Client Mode"
>  An \fBovs\-vlan\-test\fR client may be run on a host to check for VLAN
> -connectivity problems.  The client must be able to establish HTTP connections
> -with an \fBovs\-vlan\-test\fR server located at the specified 
> \fIcontrol_ip\fR
> -address.  UDP traffic sourced at \fIvlan_ip\fR should be tagged and directed 
> out
> -the interface whose connectivity is being tested.
> +connectivity and performance problems. Traffic originating from client should
> +be tagged and directed out to the interface whose connectivity is being 
> tested.
>  .
>  .SS "Server Mode"
> -To conduct tests, an \fBovs\-vlan\-test\fR server must be running on a host
> -known not to have VLAN connectivity problems.  The server must have a
> -\fIcontrol_ip\fR on a non\-VLAN network which clients can establish
> -connectivity with.  It must also have a \fIvlan_ip\fR address on a VLAN 
> network
> -which clients will use to test their VLAN connectivity.  Multiple clients may
> -test against a single \fBovs\-vlan\-test\fR server concurrently.
> +To conduct tests, an \fBovs\-vlan\-test\fR server must be running on another
> +host. Multiple clients may test against a single \fBovs\-vlan\-test\fR server
> +concurrently.
>  .
>  .SH OPTIONS
>  .
>  .TP
> -\fB\-s\fR, \fB\-\-server\fR
> -Run in server mode.
> +\fB\-s, \-\-server SERVERPORT\fR
> +Run in server mode and wait for client connections on SERVERPORT.
> +.TP
> +\fB\-c, \-\-client SERVERIPPORT\fR
> +Run in client mode and connect to the server that is listening at 
> SERVERIPPORT
> +(in IP:PORT format)
> +.TP
> +\fB\-b, \-\-bandwidth TARGETBANDWIDTH[KM]\fR
> +Set the target bandwidth to TARGETBANDWIDTH bits/sec (default 1 Mbps). Must 
> be
> +set at client-side.
>  .
>  .so lib/common.man
>  .SH EXAMPLES
> @@ -64,16 +77,16 @@ Set up a bridge which forwards traffic originating from 
> \fB1.2.3.4\fR out
>  .B ifconfig vlan\-br\-tag up 1.2.3.4
>  .
>  .PP
> -Run an \fBovs\-vlan\-test\fR server listening for client control traffic on
> -172.16.0.142 port 8080 and VLAN traffic on the default port of 1.2.3.3.
> +Run an \fBovs\-vlan\-test\fR server listening for client traffic on
> +port 10000.
>  .IP
> -.B ovs\-vlan\-test \-s 172.16.0.142:8080 1.2.3.3
> +.B ovs\-vlan\-test \-s 10000
>  .
>  .PP
> -Run an \fBovs\-vlan\-test\fR client with a control server located at
> -172.16.0.142 port 8080 and a local VLAN ip of 1.2.3.4.
> +Run an \fBovs\-vlan\-test\fR client that connects to a server located at
> +172.16.0.142 port 10000.
>  .IP
> -.B ovs\-vlan\-test 172.16.0.142:8080 1.2.3.4
> +.B ovs\-vlan\-test \-c 172.16.0.142:10000
>  .
>  .TP
>
> diff --git a/utilities/ovs-vlan-test.in b/utilities/ovs-vlan-test.in
> index f937845..ed35a7f 100755
> --- a/utilities/ovs-vlan-test.in
> +++ b/utilities/ovs-vlan-test.in
> @@ -1,6 +1,6 @@
>  #! @PYTHON@
>  #
> -# Copyright (c) 2010 Nicira Networks.
> +# Copyright (c) 2011 Nicira Networks.
>  #
>  # Licensed under the Apache License, Version 2.0 (the "License");
>  # you may not use this file except in compliance with the License.
> @@ -14,422 +14,163 @@
>  # See the License for the specific language governing permissions and
>  # limitations under the License.
>
> -import BaseHTTPServer
> -import getopt
> -import httplib
>  import os
> -import threading
> -import time
> -import signal #Causes keyboard interrupts to go to the main thread.
> +import re
>  import socket
> -import sys
> -
> -print_safe_lock = threading.Lock()
> -def print_safe(s):
> -    print_safe_lock.acquire()
> -    print(s)
> -    print_safe_lock.release()
> -
> -def start_thread(target, args):
> -    t = threading.Thread(target=target, args=args)
> -    t.setDaemon(True)
> -    t.start()
> -    return t
> -
> -#Caller is responsible for catching socket.error exceptions.
> -def send_packet(key, length, dest_ip, dest_port):
> -
> -    length -= 20 + 8  #IP and UDP headers.
> -
> -    packet = str(key)
> -    packet += chr(0) * (length - len(packet))
> -
> -    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
> -    sock.sendto(packet, (dest_ip, dest_port))
> -    sock.close()
> -
> -#UDP Receiver
> -class UDPReceiver:
> -    def __init__(self, vlan_ip, vlan_port):
> -        self.vlan_ip        = vlan_ip
> -        self.vlan_port      = vlan_port
> -        self.recv_callbacks = {}
> -        self.udp_run        = False
> -
> -    def recv_packet(self, key, success_callback, timeout_callback):
> -
> -        event = threading.Event()
> -
> -        def timeout_cb():
> -            timeout_callback()
> -            event.set()
> -
> -        timer = threading.Timer(30, timeout_cb)
> -        timer.daemon = True
> -
> -        def success_cb():
> -            timer.cancel()
> -            success_callback()
> -            event.set()
> -
> -        # Start the timer first to avoid a timer.cancel() race condition.
> -        timer.start()
> -        self.recv_callbacks[key] = success_cb
> -        return event
> -
> -    def udp_receiver(self):
> -
> -        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
> -        sock.settimeout(1)
> -
> -        try:
> -            sock.bind((self.vlan_ip, self.vlan_port))
> -        except socket.error, e:
> -            print_safe('Failed to bind to %s:%d with error: %s'
> -                    % (self.vlan_ip, self.vlan_port, e))
> -            os._exit(1) #sys.exit only exits the current thread.
> -
> -        while self.udp_run:
> -
> -            try:
> -                data, _ = sock.recvfrom(4096)
> -            except socket.timeout:
> -                continue
> -            except socket.error, e:
> -                print_safe('Failed to receive from %s:%d with error: %s'
> -                    % (self.vlan_ip, self.vlan_port, e))
> -                os._exit(1)
> -
> -            data_str = data.split(chr(0))[0]
> -
> -            if not data_str.isdigit():
> -                continue
> -
> -            key = int(data_str)
> -
> -            if key in self.recv_callbacks:
> -                self.recv_callbacks[key]()
> -                del self.recv_callbacks[key]
> -
> -    def start(self):
> -        self.udp_run = True
> -        start_thread(self.udp_receiver, ())
> -
> -    def stop(self):
> -        self.udp_run = False
> -
> -#Server
> -vlan_server = None
> -class VlanServer:
> -
> -    def __init__(self, server_ip, server_port, vlan_ip, vlan_port):
> -        global vlan_server
> -
> -        vlan_server = self
> -
> -        self.server_ip   = server_ip
> -        self.server_port = server_port
> -
> -        self.recv_response = '%s:%d:' % (vlan_ip, vlan_port)
> -
> -        self.result      = {}
> -        self.result_lock = threading.Lock()
> -
> -        self._test_id      = 0
> -        self._test_id_lock = threading.Lock()
> -
> -        self.udp_recv = UDPReceiver(vlan_ip, vlan_port)
> -
> -    def get_test_id(self):
> -        self._test_id_lock.acquire()
> -
> -        self._test_id += 1
> -        ret = self._test_id
> -
> -        self._test_id_lock.release()
> -        return ret
> -
> -    def set_result(self, key, value):
> -
> -        self.result_lock.acquire()
> -
> -        if key not in self.result:
> -            self.result[key] = value
> -
> -        self.result_lock.release()
> -
> -    def recv(self, test_id):
> -        self.udp_recv.recv_packet(test_id,
> -                lambda : self.set_result(test_id, 'Success'),
> -                lambda : self.set_result(test_id, 'Timeout'))
> -
> -        return self.recv_response + str(test_id)
> -
> -    def send(self, test_id, data):
> -        try:
> -            ip, port, size = data.split(':')
> -            port = int(port)
> -            size = int(size)
> -        except ValueError:
> -            self.set_result(test_id,
> -                    'Server failed to parse send request: %s' % data)
> -            return
> -
> -        def send_thread():
> -            send_time = 10
> -            for _ in range(send_time * 2):
> +import argparse
> +from twisted.internet import protocol
> +from twisted.internet import reactor
> +
> +
> +class IperfUDPClient(protocol.ProcessProtocol):
> +
> +    def __init__(self, scheduler, datagramSize):
> +        self.out_data = ""
> +        self.err_data = ""
> +        self.scheduler = scheduler
> +        self.datagramSize = datagramSize
> +        self.serverUnreachable = False
> +
> +    def outReceived(self, data):
> +        self.out_data = self.out_data + data #Concatenate STDOUT and parse 
> later
> +
> +    def errReceived(self, data):
> +        self.err_data = self.err_data + data
> +        if ("connect failed" in self.err_data) or \
> +        ("Connection refused" in self.err_data) or \
> +        ("did not receive ack" in self.err_data):
> +            self.serverUnreachable = True
> +            self.transport.signalProcess('KILL') #Server did not respond back
> +
> +    def processEnded(self, reason):
> +        if (reason.value.exitCode != 0) and (self.serverUnreachable == 
> False):
> +            print "Iperf returned with an error code"
> +        else:
> +            if self.serverUnreachable == True:
> +                print "Connectivity problems were detected with datagrams "\
> +                       "of size %u bytes. Test FAILED" % (self.datagramSize)
> +            else:
>                 try:
> -                    send_packet(test_id, size, ip, port)
> -                except socket.error, e:
> -                    self.set_result(test_id, 'Failure: ' + str(e))
> -                    return
> -                time.sleep(.5)
> -
> -            self.set_result(test_id, 'Success')
> -
> -        start_thread(send_thread, ())
> -
> -        return str(test_id)
> -
> -    def run(self):
> -        self.udp_recv.start()
> -        try:
> -            BaseHTTPServer.HTTPServer((self.server_ip, self.server_port),
> -                    VlanServerHandler).serve_forever()
> -        except socket.error, e:
> -            print_safe('Failed to start control server: %s' % e)
> -            self.udp_recv.stop()
> -
> -        return 1
> -
> -class VlanServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
> -    def do_GET(self):
> -
> -        #Guarantee three arguments.
> -        path = (self.path.lower().lstrip('/') + '//').split('/')
> -
> -        resp = 404
> -        body = None
> -
> -        if path[0] == 'start':
> -            test_id = vlan_server.get_test_id()
> -
> -            if path[1] == 'recv':
> -                resp = 200
> -                body = vlan_server.recv(test_id)
> -            elif path[1] == 'send':
> -                resp = 200
> -                body = vlan_server.send(test_id, path[2])
> -        elif (path[0] == 'result'
> -                and path[1].isdigit()
> -                and int(path[1]) in vlan_server.result):
> -            resp = 200
> -            body = vlan_server.result[int(path[1])]
> -        elif path[0] == 'ping':
> -            resp = 200
> -            body = 'pong'
> -
> -        self.send_response(resp)
> -        self.end_headers()
> -
> -        if body:
> -            self.wfile.write(body)
> -
> -#Client
> -class VlanClient:
> -
> -    def __init__(self, server_ip, server_port, vlan_ip, vlan_port):
> -        self.server_ip_port = '%s:%d' % (server_ip, server_port)
> -        self.vlan_ip_port   = "%s:%d" % (vlan_ip, vlan_port)
> -        self.udp_recv       = UDPReceiver(vlan_ip, vlan_port)
> -
> -    def request(self, resource):
> -        conn = httplib.HTTPConnection(self.server_ip_port)
> -        conn.request('GET', resource)
> -        return conn
> -
> -    def send(self, size):
> -
> -        def error_msg(e):
> -            print_safe('Send size %d unsuccessful: %s' % (size, e))
> -
> -        try:
> -            conn = self.request('/start/recv')
> -            data = conn.getresponse().read()
> -        except (socket.error, httplib.HTTPException), e:
> -            error_msg(e)
> -            return False
> -
> -        try:
> -            ip, port, test_id = data.split(':')
> -            port    = int(port)
> -            test_id = int(test_id)
> -        except ValueError:
> -            error_msg("Received invalid response from control server (%s)" %
> -                    data)
> -            return False
> -
> -        send_time = 5
> -
> -        for _ in range(send_time * 4):
> -
> -            try:
> -                send_packet(test_id, size, ip, port)
> -                resp = self.request('/result/%d' % test_id).getresponse()
> -                data = resp.read()
> -            except (socket.error, httplib.HTTPException), e:
> -                error_msg(e)
> -                return False
> -
> -            if resp.status == 200 and data == 'Success':
> -                print_safe('Send size %d successful' % size)
> -                return True
> -            elif resp.status == 200:
> -                error_msg(data)
> -                return False
> -
> -            time.sleep(.25)
> -
> -        error_msg('Timeout')
> -        return False
> -
> -    def recv(self, size):
> -
> -        def error_msg(e):
> -            print_safe('Receive size %d unsuccessful: %s' % (size, e))
> -
> -        resource = '/start/send/%s:%d' % (self.vlan_ip_port, size)
> -        try:
> -            conn    = self.request(resource)
> -            test_id = conn.getresponse().read()
> -        except (socket.error, httplib.HTTPException), e:
> -            error_msg(e)
> -            return False
> -
> -        if not test_id.isdigit():
> -            error_msg('Invalid response %s' % test_id)
> -            return False
> -
> -        success = [False] #Primitive datatypes can't be set from closures.
> -
> -        def success_cb():
> -            success[0] = True
> -
> -        def failure_cb():
> -            success[0] = False
> -
> -        self.udp_recv.recv_packet(int(test_id), success_cb, 
> failure_cb).wait()
> -
> -        if success[0]:
> -            print_safe('Receive size %d successful' % size)
> +                    lines = self.out_data.split('\n')
> +                    sl = lines[1].split(',')#Send Line
> +                    rl = lines[2].split(',')#Receive Line
> +
> +                    print "Sent %s UDP datagrams of size %u bytes; %s%% "\
> +                    "packetloss(%s) and %s out of order datagrams; OK"%\
> +                    (sl[11], self.datagramSize, sl[12], sl[10], sl[13])
> +
> +                    print "Received %s UDP datagrams of size %u bytes; %s%% 
> "\
> +                    "packetloss(%s) and %s out of order datagrams; OK"%\
> +                    (rl[11], self.datagramSize, rl[12], rl[10], rl[13])
> +                except IndexError:
> +                    print "Parsing failed. Please Report a bug against "\
> +                    "ovs-vlan-test and include this error message: %s"%\
> +                    (self.out_data)
> +        self.scheduler.scheduleNextTest()
> +
> +
> +class IperfServer(protocol.ProcessProtocol):
> +
> +    def __init__(self):
> +        pass
> +
> +    def processEnded(self, reason):
> +        if reason.value.exitCode != 0:
> +            print "Iperf did not start up properly."
> +
> +
> +class ClientTestScheduler:
> +
> +    def __init__(self, ip, port, targetBandwidth):
> +        self.serverIp = ip
> +        self.serverPort = port
> +        self.size = [1500, 1000, 500, 55]
> +        self.targetBandwidth = targetBandwidth
> +
> +    def scheduleNextTest(self):
> +        if len(self.size) > 0: #iterate over different datagram sizes
> +            s = self.size.pop()
> +            clientProcessProtocolHandler = IperfUDPClient(self, s)
> +            t = reactor.spawnProcess(clientProcessProtocolHandler, "iperf",
> +              ["iperf", "-c", self.serverIp, "-u", "-p", self.serverPort, 
> "-y",
> +              "C", "-l", str(s), "-r", "-b", self.targetBandwidth], {})
>         else:
> -            error_msg('Timeout')
> -
> -        return success[0]
> -
> -    def server_up(self):
> +            reactor.stop()#All tests are completed; Exit from the event-loop
>
> -        def error_msg(e):
> -            print_safe('Failed control server connectivity test: %s' % e)
>
> +def ipPort(string):
> +    value = string.split(':')
> +    if len(value) == 2:
>         try:
> -            resp = self.request('/ping').getresponse()
> -            data = resp.read()
> -        except (socket.error, httplib.HTTPException), e:
> -            error_msg(e)
> -            return False
> -
> -        if resp.status != 200:
> -            error_msg('Invalid status %d' % resp.status)
> -        elif data != 'pong':
> -            error_msg('Invalid response %s' % data)
> -
> -        return True
> -
> -    def run(self):
> -
> -        if not self.server_up():
> -            return 1
> -
> -        self.udp_recv.start()
> -
> -        success = True
> -        for size in [50, 500, 1000, 1500]:
> -            success = self.send(size) and success
> -            success = self.recv(size) and success
> -
> -        self.udp_recv.stop()
> -
> -        if success:
> -            print_safe('OK')
> -            return 0
> -        else:
> -            print_safe('FAILED')
> -            return 1
> -
> -def usage():
> -    print_safe("""\
> -%(argv0)s: Test vlan connectivity
> -usage: %(argv0)s server vlan
> -
> -The following options are also available:
> -  -s, --server                run in server mode
> -  -h, --help                  display this help message
> -  -V, --version               display version information\
> -""" % {'argv0': sys.argv[0]})
> +            socket.inet_aton(value[0])
> +        except socket.error:
> +            raise argparse.ArgumentTypeError("Not a valid IPv4 address")
> +        port(value[1]) #this function might throw an ArgumentTypeError 
> exception
> +    else:
> +        raise argparse.ArgumentTypeError("IP address and Port must be "\
> +                                          "comma-separated")
> +    return string
>
> -def main():
>
> +def port(string):
>     try:
> -        options, args = getopt.gnu_getopt(sys.argv[1:], 'hVs',
> -                                          ['help', 'version', 'server'])
> -    except getopt.GetoptError, geo:
> -        print_safe('%s: %s\n' % (sys.argv[0], geo.msg))
> -        return 1
> +        port_number = int(string)
> +        if port_number < 1 or port_number > 65535:
> +            raise argparse.ArgumentTypeError("Port is out of range")
> +    except ValueError:
> +        raise argparse.ArgumentTypeError("Port is not an integer")
> +    return string
>
> -    server = False
> -    for key, _ in options:
> -        if key in ['-h', '--help']:
> -            usage()
> -            return 0
> -        elif key in ['-V', '--version']:
> -            print_safe('ovs-vlan-test (Open vSwitch) @VERSION@')
> -            return 0
> -        elif key in ['-s', '--server']:
> -            server = True
> -        else:
> -            print_safe('Unexpected option %s. (use --help for help)' % key)
> -            return 1
> +
> +def bandwidth(string):
> +    if re.match("^[1-9][0-9]*[MK]?$",string) == None: #Number + K or M 
> character
> +        raise argparse.ArgumentTypeError("Not a valid target bandwidth")
> +    return string
>
> -    if len(args) != 2:
> -        print_safe('Expecting two arguments. (use --help for help)')
> -        return 1
>
> -    try:
> -        server_ip, server_port = args[0].split(':')
> -        server_port = int(server_port)
> -    except ValueError:
> -        server_ip = args[0]
> -        server_port = 80
> +def which(program):
> +    def is_exe(fpath):
> +        return os.path.exists(fpath) and os.access(fpath, os.X_OK)
>
> -    try:
> -        vlan_ip, vlan_port = args[1].split(':')
> -        vlan_port = int(vlan_port)
> -    except ValueError:
> -        vlan_ip   = args[1]
> -        vlan_port = 15213
> -
> -    if server:
> -        return VlanServer(server_ip, server_port, vlan_ip, vlan_port).run()
> +    fpath, fname = os.path.split(program)
> +    if fpath:
> +        if is_exe(program):
> +            return program
>     else:
> -        return VlanClient(server_ip, server_port, vlan_ip, vlan_port).run()
> +        for path in os.environ["PATH"].split(os.pathsep):
> +            exe_file = os.path.join(path, program)
> +            if is_exe(exe_file):
> +                return exe_file
> +    return None
>
> -if __name__ == '__main__':
> -    main_ret = main()
>
> -    # Python can throw exceptions if threads are running at exit.
> -    for th in threading.enumerate():
> -        if th != threading.currentThread():
> -            th.join()
> +if __name__ == '__main__':
>
> -    sys.exit(main_ret)
> +    parser = argparse.ArgumentParser(description='Test vlan connectivity')
> +    parser.add_argument('-v', '--version', action='version',
> +                    version='ovs-vlan-test (Open vSwitch) @VERSION@')
> +    parser.add_argument("-b", "--bandwidth", action='store',
> +                    dest="targetBandwidth", default="1M", type=bandwidth,
> +                    help='Specify target bandwidth for UDP tests (default 
> 1M)')
> +    group = parser.add_mutually_exclusive_group(required=True)
> +    group.add_argument("-s", "--server",action="store", dest="serverPort",
> +                    type=port, help='run in server mode and open listening '\
> +                    'UDP socket at SERVERPORT')
> +    group.add_argument('-c', "--client", action="store", dest="serverIpPort",
> +                    type=ipPort, help='run in client mode and connect '\
> +                    'to a server that is listening at SERVERIPPORT')
> +    args = parser.parse_args()
> +
> +    if which("iperf"):
> +        if args.serverPort:
> +            serverProcessProtocolHandler = IperfServer()
> +            reactor.spawnProcess(serverProcessProtocolHandler, "iperf",
> +                  ["iperf", "-s", "-u", "-p", args.serverPort , "-y", "C"], 
> {})
> +        else:
> +            [ServerIP, ServerPort] = args.serverIpPort.split(':')
> +            scheduler = ClientTestScheduler(ServerIP, ServerPort,
> +                                              args.targetBandwidth)
> +            scheduler.scheduleNextTest();
> +        reactor.run() #Enter the main event-loop
> +    else:
> +        print "iperf is not in the PATH (install it with yum or apt-get)"
> --
> 1.7.4.1
>
> _______________________________________________
> 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