X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=python%2Fovstest%2Fargs.py;h=3f8d0d98b3f64f20d7f609b37f31bce9d9ea8ffc;hb=47284b1fc6fe84a9b5b43b49bef868e4eb230cd1;hp=d6b4756803b798211b4d58f89d27db7949ff92d2;hpb=0be6140a9a7de46f07e09d3ba200bd7f0cf73838;p=openvswitch diff --git a/python/ovstest/args.py b/python/ovstest/args.py index d6b47568..3f8d0d98 100644 --- a/python/ovstest/args.py +++ b/python/ovstest/args.py @@ -1,4 +1,4 @@ -# Copyright (c) 2011 Nicira Networks +# Copyright (c) 2011, 2012 Nicira Networks # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,11 +17,14 @@ ovsargs provide argument parsing for ovs-test utility """ import argparse -import socket import re +import socket +import sys +CONTROL_PORT = 15531 +DATA_PORT = 15532 -def ip(string): +def ip_address(string): """Verifies if string is a valid IP address""" try: socket.inet_aton(string) @@ -30,8 +33,28 @@ def ip(string): return string +def ip_optional_mask(string): + """ + Verifies if string contains a valid IP address and an optional mask in + CIDR notation. + """ + token = string.split("/") + if len(token) > 2: + raise argparse.ArgumentTypeError("IP address and netmask must be " + "separated by a single slash") + elif len(token) == 2: + try: + mask = int(token[1]) + except ValueError: + raise argparse.ArgumentTypeError("Netmask is not a valid integer") + if mask < 0 or mask > 31: + raise argparse.ArgumentTypeError("Netmask must be in range 0..31") + ip_address(token[0]) + return string + + def port(string): - """Convert a string into a Port (integer)""" + """Convert a string into a TCP/UDP Port (integer)""" try: port_number = int(string) if port_number < 1 or port_number > 65535: @@ -41,75 +64,136 @@ def port(string): return port_number -def ip_optional_port(string, default_port): +def ip_optional_port(string, default_port, ip_callback): """Convert a string into IP and Port pair. If port was absent then use - default_port as the port""" + default_port as the port. The third argument is a callback that verifies + whether IP address is given in correct format.""" value = string.split(':') if len(value) == 1: - return (ip(value[0]), default_port) + return (ip_callback(value[0]), default_port) elif len(value) == 2: - return (ip(value[0]), port(value[1])) + return (ip_callback(value[0]), port(value[1])) else: raise argparse.ArgumentTypeError("IP address from the optional Port " "must be colon-separated") +def vlan_tag(string): + """ + This function verifies whether given string is a correct VLAN tag. + """ + try: + value = int(string) + except ValueError: + raise argparse.ArgumentTypeError("VLAN tag is not a valid integer") + if value < 1 or value > 4094: + raise argparse.ArgumentTypeError("Not a valid VLAN tag. " + "VLAN tag should be in the " + "range 1..4094.") + return string + def server_endpoint(string): - """Converts a string in ControlIP[:ControlPort][,TestIP[:TestPort]] format + """Converts a string OuterIP[:OuterPort],InnerIP[/Mask][:InnerPort] into a 4-tuple, where: - 1. First element is ControlIP - 2. Second element is ControlPort (if omitted will use default value 15531) - 3 Third element is TestIP (if omitted will be the same as ControlIP) - 4. Fourth element is TestPort (if omitted will use default value 15532)""" + 1. First element is OuterIP + 2. Second element is OuterPort (if omitted will use default value 15531) + 3 Third element is InnerIP with optional mask + 4. Fourth element is InnerPort (if omitted will use default value 15532) + """ value = string.split(',') - if len(value) == 1: # TestIP and TestPort are not present - ret = ip_optional_port(value[0], 15531) - return (ret[0], ret[1], ret[0], 15532) - elif len(value) == 2: - ret1 = ip_optional_port(value[0], 15531) - ret2 = ip_optional_port(value[1], 15532) + if len(value) == 2: + ret1 = ip_optional_port(value[0], CONTROL_PORT, ip_address) + ret2 = ip_optional_port(value[1], DATA_PORT, ip_optional_mask) return (ret1[0], ret1[1], ret2[0], ret2[1]) else: - raise argparse.ArgumentTypeError("ControlIP:ControlPort and TestIP:" - "TestPort must be comma " - "separated") + raise argparse.ArgumentTypeError("OuterIP:OuterPort and InnerIP/Mask:" + "InnerPort must be comma separated") + + +class UniqueServerAction(argparse.Action): + """ + This custom action class will prevent user from entering multiple ovs-test + servers with the same OuterIP. If there is an server with 127.0.0.1 outer + IP address then it will be inserted in the front of the list. + """ + def __call__(self, parser, namespace, values, option_string=None): + outer_ips = set() + endpoints = [] + for server in values: + try: + endpoint = server_endpoint(server) + except argparse.ArgumentTypeError: + raise argparse.ArgumentError(self, str(sys.exc_info()[1])) + if endpoint[0] in outer_ips: + raise argparse.ArgumentError(self, "Duplicate OuterIPs found") + else: + outer_ips.add(endpoint[0]) + if endpoint[0] == "127.0.0.1": + endpoints.insert(0, endpoint) + else: + endpoints.append(endpoint) + setattr(namespace, self.dest, endpoints) def bandwidth(string): """Convert a string (given in bits/second with optional magnitude for units) into a long (bytes/second)""" - if re.match("^[1-9][0-9]*[MK]?$", string) == None: + if re.match("^[1-9][0-9]*[MK]?$", string) is None: raise argparse.ArgumentTypeError("Not a valid target bandwidth") bwidth = string.replace("M", "000000") bwidth = bwidth.replace("K", "000") - return long(bwidth) / 8 # Convert from bits to bytes + return long(bwidth) / 8 # Convert from bits to bytes + + +def tunnel_types(string): + """ + This function converts a string into a list that contains all tunnel types + that user intended to test. + """ + return string.split(',') def ovs_initialize_args(): - """Initialize args for ovstest utility""" - parser = argparse.ArgumentParser(description = 'Test ovs connectivity') - parser.add_argument('-v', '--version', action = 'version', - version = 'ovs-test (Open vSwitch) @VERSION@') - parser.add_argument("-b", "--bandwidth", action = 'store', - dest = "targetBandwidth", default = "1M", type = bandwidth, - help = 'target bandwidth for UDP tests in bits/second. Use ' + """ + Initialize argument parsing for ovs-test utility. + """ + parser = argparse.ArgumentParser(description='Test connectivity ' + 'between two Open vSwitches.') + + parser.add_argument('-v', '--version', action='version', + version='ovs-test (Open vSwitch) @VERSION@') + + parser.add_argument("-b", "--bandwidth", action='store', + dest="targetBandwidth", default="1M", type=bandwidth, + help='Target bandwidth for UDP tests in bits/second. Use ' 'postfix M or K to alter unit magnitude.') - group = parser.add_mutually_exclusive_group(required = True) - group.add_argument("-s", "--server", action = "store", dest = "port", - type = port, - help = 'run in server mode and wait client to connect to this ' - 'port') - group.add_argument('-c', "--client", action = "store", nargs = 2, - dest = "servers", type = server_endpoint, - metavar = ("SERVER1", "SERVER2"), - help = 'run in client mode and do tests between these ' - 'two servers. Each server must be specified in following ' - 'format - ControlIP[:ControlPort][,TestIP[:TestPort]]. If ' - 'TestIP is omitted then ovs-test server will also use the ' - 'ControlIP for testing purposes. ControlPort is TCP port ' - 'where server will listen for incoming XML/RPC control ' - 'connections to schedule tests (by default 15531). TestPort ' - 'is port which will be used by server to send test traffic ' - '(by default 15532)') + parser.add_argument("-i", "--interval", action='store', + dest="testInterval", default=5, type=int, + help='Interval for how long to run each test in seconds.') + + parser.add_argument("-t", "--tunnel-modes", action='store', + dest="tunnelModes", default=(), type=tunnel_types, + help='Do L3 tests with the given tunnel modes.') + parser.add_argument("-l", "--vlan-tag", action='store', + dest="vlanTag", default=None, type=vlan_tag, + help='Do VLAN tests and use the given VLAN tag.') + parser.add_argument("-d", "--direct", action='store_true', + dest="direct", default=None, + help='Do direct tests between both ovs-test servers.') + + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument("-s", "--server", action="store", dest="port", + type=port, + help='Run in server mode and wait for the client to ' + 'connect to this port.') + group.add_argument('-c', "--client", nargs=2, + dest="servers", action=UniqueServerAction, + metavar=("SERVER1", "SERVER2"), + help='Run in client mode and do tests between these ' + 'two ovs-test servers. Each server must be specified in ' + 'following format - OuterIP:OuterPort,InnerIP[/mask] ' + ':InnerPort. It is possible to start local instance of ' + 'ovs-test server in the client mode by using 127.0.0.1 as ' + 'OuterIP.') return parser.parse_args()