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")
81 def ip_optional_port_port(string, default_port1, default_port2, ip_callback):
82 """Convert a string into IP, Port1, Port2 tuple. If any of ports were
83 missing, then default ports will be used. The fourth argument is a
84 callback that verifies whether IP address is given in the expected
86 value = string.split(':')
88 return (ip_callback(value[0]), default_port1, default_port2)
90 return (ip_callback(value[0]), port(value[1]), default_port2)
92 return (ip_callback(value[0]), port(value[1]), port(value[2]))
94 raise argparse.ArgumentTypeError("Expected IP address and at most "
95 "two colon-separated ports")
100 This function verifies whether given string is a correct VLAN tag.
105 raise argparse.ArgumentTypeError("VLAN tag is not a valid integer")
106 if value < 1 or value > 4094:
107 raise argparse.ArgumentTypeError("Not a valid VLAN tag. "
108 "VLAN tag should be in the "
113 def server_endpoint(string):
114 """Converts a string OuterIP[:OuterPort],InnerIP[/Mask][:InnerPort]
115 into a 4-tuple, where:
116 1. First element is OuterIP
117 2. Second element is OuterPort (if omitted will use default value 15531)
118 3 Third element is InnerIP with optional mask
119 4. Fourth element is InnerPort (if omitted will use default value 15532)
121 value = string.split(',')
123 ret1 = ip_optional_port(value[0], CONTROL_PORT, ip_address)
124 ret2 = ip_optional_port(value[1], DATA_PORT, ip_optional_mask)
125 return (ret1[0], ret1[1], ret2[0], ret2[1])
127 raise argparse.ArgumentTypeError("OuterIP:OuterPort and InnerIP/Mask:"
128 "InnerPort must be comma separated")
131 class UniqueServerAction(argparse.Action):
133 This custom action class will prevent user from entering multiple ovs-test
134 servers with the same OuterIP. If there is an server with 127.0.0.1 outer
135 IP address then it will be inserted in the front of the list.
137 def __call__(self, parser, namespace, values, option_string=None):
140 for server in values:
142 endpoint = server_endpoint(server)
143 except argparse.ArgumentTypeError:
144 raise argparse.ArgumentError(self, str(sys.exc_info()[1]))
145 if endpoint[0] in outer_ips:
146 raise argparse.ArgumentError(self, "Duplicate OuterIPs found")
148 outer_ips.add(endpoint[0])
149 if endpoint[0] == "127.0.0.1":
150 endpoints.insert(0, endpoint)
152 endpoints.append(endpoint)
153 setattr(namespace, self.dest, endpoints)
156 def bandwidth(string):
157 """Convert a string (given in bits/second with optional magnitude for
158 units) into a long (bytes/second)"""
159 if re.match("^[1-9][0-9]*[MK]?$", string) is None:
160 raise argparse.ArgumentTypeError("Not a valid target bandwidth")
161 bwidth = string.replace("M", "000000")
162 bwidth = bwidth.replace("K", "000")
163 return long(bwidth) / 8 # Convert from bits to bytes
166 def tunnel_types(string):
168 This function converts a string into a list that contains all tunnel types
169 that user intended to test.
171 return string.split(',')
174 def l3_endpoint_client(string):
176 This function parses command line argument string in
177 remoteIP,localInnerIP[/mask][:ControlPort[:TestPort]],remoteInnerIP[:
178 ControlPort[:TestPort]] format.
181 remote_ip, me, he = string.split(',')
183 raise argparse.ArgumentTypeError("All 3 IP addresses must be comma "
185 r = (ip_address(remote_ip),
186 ip_optional_port_port(me, CONTROL_PORT, DATA_PORT, ip_optional_mask),
187 ip_optional_port_port(he, CONTROL_PORT, DATA_PORT, ip_address))
191 def l3_endpoint_server(string):
193 This function parses a command line argument string in
194 remoteIP,localInnerIP[/mask][:ControlPort] format.
197 remote_ip, me = string.split(',')
199 raise argparse.ArgumentTypeError("Both IP addresses must be comma "
201 return (ip_address(remote_ip),
202 ip_optional_port(me, CONTROL_PORT, ip_optional_mask))
205 def ovs_initialize_args():
207 Initialize argument parsing for ovs-test utility.
209 parser = argparse.ArgumentParser(description='Test connectivity '
210 'between two Open vSwitches.')
212 parser.add_argument('-v', '--version', action='version',
213 version='ovs-test (Open vSwitch) @VERSION@')
215 parser.add_argument("-b", "--bandwidth", action='store',
216 dest="targetBandwidth", default="1M", type=bandwidth,
217 help='Target bandwidth for UDP tests in bits/second. Use '
218 'postfix M or K to alter unit magnitude.')
219 parser.add_argument("-i", "--interval", action='store',
220 dest="testInterval", default=5, type=int,
221 help='Interval for how long to run each test in seconds.')
223 parser.add_argument("-t", "--tunnel-modes", action='store',
224 dest="tunnelModes", default=(), type=tunnel_types,
225 help='Do L3 tests with the given tunnel modes.')
226 parser.add_argument("-l", "--vlan-tag", action='store',
227 dest="vlanTag", default=None, type=vlan_tag,
228 help='Do VLAN tests and use the given VLAN tag.')
229 parser.add_argument("-d", "--direct", action='store_true',
230 dest="direct", default=None,
231 help='Do direct tests between both ovs-test servers.')
233 group = parser.add_mutually_exclusive_group(required=True)
234 group.add_argument("-s", "--server", action="store", dest="port",
236 help='Run in server mode and wait for the client to '
237 'connect to this port.')
238 group.add_argument('-c', "--client", nargs=2,
239 dest="servers", action=UniqueServerAction,
240 metavar=("SERVER1", "SERVER2"),
241 help='Run in client mode and do tests between these '
242 'two ovs-test servers. Each server must be specified in '
243 'following format - OuterIP:OuterPort,InnerIP[/mask] '
244 ':InnerPort. It is possible to start local instance of '
245 'ovs-test server in the client mode by using 127.0.0.1 as '
247 return parser.parse_args()
249 def l3_initialize_args():
251 Initialize argument parsing for ovs-l3ping utility.
253 parser = argparse.ArgumentParser(description='Test L3 tunnel '
254 'connectivity between two Open vSwitch instances.')
256 parser.add_argument('-v', '--version', action='version',
257 version='ovs-l3ping (Open vSwitch) @VERSION@')
259 parser.add_argument("-b", "--bandwidth", action='store',
260 dest="targetBandwidth", default="1M", type=bandwidth,
261 help='Target bandwidth for UDP tests in bits/second. Use '
262 'postfix M or K to alter unit magnitude.')
263 parser.add_argument("-i", "--interval", action='store',
264 dest="testInterval", default=5, type=int,
265 help='Interval for how long to run each test in seconds.')
267 parser.add_argument("-t", "--tunnel-mode", action='store',
268 dest="tunnelMode", required=True,
269 help='Do L3 tests with this tunnel type.')
271 group = parser.add_mutually_exclusive_group(required=True)
272 group.add_argument("-s", "--server", action="store", dest="server",
273 metavar="TUNNELIP,SERVER",
274 type=l3_endpoint_server,
275 help='Run in server mode and wait for the client to '
277 group.add_argument('-c', "--client", action="store", dest="client",
278 metavar="TUNNELIP,CLIENT,SERVER",
279 type=l3_endpoint_client,
280 help='Run in client mode and connect to the server.')
281 return parser.parse_args()