1 # Copyright (c) 2011, 2012 Nicira, Inc.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at:
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
16 ovsargs provide argument parsing for ovs-test utility
27 def ip_address(string):
28 """Verifies if string is a valid IP address"""
30 socket.inet_aton(string)
32 raise argparse.ArgumentTypeError("Not a valid IPv4 address")
36 def ip_optional_mask(string):
38 Verifies if string contains a valid IP address and an optional mask in
41 token = string.split("/")
43 raise argparse.ArgumentTypeError("IP address and netmask must be "
44 "separated by a single slash")
49 raise argparse.ArgumentTypeError("Netmask is not a valid integer")
50 if mask < 0 or mask > 31:
51 raise argparse.ArgumentTypeError("Netmask must be in range 0..31")
57 """Convert a string into a TCP/UDP Port (integer)"""
59 port_number = int(string)
60 if port_number < 1 or port_number > 65535:
61 raise argparse.ArgumentTypeError("Port is out of range")
63 raise argparse.ArgumentTypeError("Port is not an integer")
67 def ip_optional_port(string, default_port, ip_callback):
68 """Convert a string into IP and Port pair. If port was absent then use
69 default_port as the port. The third argument is a callback that verifies
70 whether IP address is given in correct format."""
71 value = string.split(':')
73 return (ip_callback(value[0]), default_port)
75 return (ip_callback(value[0]), port(value[1]))
77 raise argparse.ArgumentTypeError("IP address from the optional Port "
78 "must be colon-separated")
83 This function verifies whether given string is a correct VLAN tag.
88 raise argparse.ArgumentTypeError("VLAN tag is not a valid integer")
89 if value < 1 or value > 4094:
90 raise argparse.ArgumentTypeError("Not a valid VLAN tag. "
91 "VLAN tag should be in the "
96 def server_endpoint(string):
97 """Converts a string OuterIP[:OuterPort],InnerIP[/Mask][:InnerPort]
98 into a 4-tuple, where:
99 1. First element is OuterIP
100 2. Second element is OuterPort (if omitted will use default value 15531)
101 3 Third element is InnerIP with optional mask
102 4. Fourth element is InnerPort (if omitted will use default value 15532)
104 value = string.split(',')
106 ret1 = ip_optional_port(value[0], CONTROL_PORT, ip_address)
107 ret2 = ip_optional_port(value[1], DATA_PORT, ip_optional_mask)
108 return (ret1[0], ret1[1], ret2[0], ret2[1])
110 raise argparse.ArgumentTypeError("OuterIP:OuterPort and InnerIP/Mask:"
111 "InnerPort must be comma separated")
114 class UniqueServerAction(argparse.Action):
116 This custom action class will prevent user from entering multiple ovs-test
117 servers with the same OuterIP. If there is an server with 127.0.0.1 outer
118 IP address then it will be inserted in the front of the list.
120 def __call__(self, parser, namespace, values, option_string=None):
123 for server in values:
125 endpoint = server_endpoint(server)
126 except argparse.ArgumentTypeError:
127 raise argparse.ArgumentError(self, str(sys.exc_info()[1]))
128 if endpoint[0] in outer_ips:
129 raise argparse.ArgumentError(self, "Duplicate OuterIPs found")
131 outer_ips.add(endpoint[0])
132 if endpoint[0] == "127.0.0.1":
133 endpoints.insert(0, endpoint)
135 endpoints.append(endpoint)
136 setattr(namespace, self.dest, endpoints)
139 def bandwidth(string):
140 """Convert a string (given in bits/second with optional magnitude for
141 units) into a long (bytes/second)"""
142 if re.match("^[1-9][0-9]*[MK]?$", string) is None:
143 raise argparse.ArgumentTypeError("Not a valid target bandwidth")
144 bwidth = string.replace("M", "000000")
145 bwidth = bwidth.replace("K", "000")
146 return long(bwidth) / 8 # Convert from bits to bytes
149 def tunnel_types(string):
151 This function converts a string into a list that contains all tunnel types
152 that user intended to test.
154 return string.split(',')
157 def ovs_initialize_args():
159 Initialize argument parsing for ovs-test utility.
161 parser = argparse.ArgumentParser(description='Test connectivity '
162 'between two Open vSwitches.')
164 parser.add_argument('-v', '--version', action='version',
165 version='ovs-test (Open vSwitch) @VERSION@')
167 parser.add_argument("-b", "--bandwidth", action='store',
168 dest="targetBandwidth", default="1M", type=bandwidth,
169 help='Target bandwidth for UDP tests in bits/second. Use '
170 'postfix M or K to alter unit magnitude.')
171 parser.add_argument("-i", "--interval", action='store',
172 dest="testInterval", default=5, type=int,
173 help='Interval for how long to run each test in seconds.')
175 parser.add_argument("-t", "--tunnel-modes", action='store',
176 dest="tunnelModes", default=(), type=tunnel_types,
177 help='Do L3 tests with the given tunnel modes.')
178 parser.add_argument("-l", "--vlan-tag", action='store',
179 dest="vlanTag", default=None, type=vlan_tag,
180 help='Do VLAN tests and use the given VLAN tag.')
181 parser.add_argument("-d", "--direct", action='store_true',
182 dest="direct", default=None,
183 help='Do direct tests between both ovs-test servers.')
185 group = parser.add_mutually_exclusive_group(required=True)
186 group.add_argument("-s", "--server", action="store", dest="port",
188 help='Run in server mode and wait for the client to '
189 'connect to this port.')
190 group.add_argument('-c', "--client", nargs=2,
191 dest="servers", action=UniqueServerAction,
192 metavar=("SERVER1", "SERVER2"),
193 help='Run in client mode and do tests between these '
194 'two ovs-test servers. Each server must be specified in '
195 'following format - OuterIP:OuterPort,InnerIP[/mask] '
196 ':InnerPort. It is possible to start local instance of '
197 'ovs-test server in the client mode by using 127.0.0.1 as '
199 return parser.parse_args()