The ovstest Python module was only used by the now removed ovs-test and ovs-l3ping utilities. Remove the module and all build system and packaging references.
Suggested-by: Ilya Maximets <[email protected]> Signed-off-by: Timothy Redaelli <[email protected]> --- NEWS | 2 + debian/control.in | 1 - debian/openvswitch-test.install | 1 - python/automake.mk | 14 +- python/ovstest/__init__.py | 1 - python/ovstest/args.py | 283 ------------------------ python/ovstest/rpcserver.py | 372 -------------------------------- python/ovstest/tcp.py | 120 ----------- python/ovstest/tests.py | 248 --------------------- python/ovstest/udp.py | 85 -------- python/ovstest/util.py | 249 --------------------- python/ovstest/vswitch.py | 107 --------- rhel/openvswitch-fedora.spec.in | 1 - 13 files changed, 4 insertions(+), 1480 deletions(-) delete mode 100644 python/ovstest/__init__.py delete mode 100644 python/ovstest/args.py delete mode 100644 python/ovstest/rpcserver.py delete mode 100644 python/ovstest/tcp.py delete mode 100644 python/ovstest/tests.py delete mode 100644 python/ovstest/udp.py delete mode 100644 python/ovstest/util.py delete mode 100644 python/ovstest/vswitch.py diff --git a/NEWS b/NEWS index a8810c08a..82042163c 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,8 @@ Post-v3.7.0 preferred for performance testing. - Removed ovs-test utility. Standard tools like iperf are preferred for performance testing. + - Removed ovstest Python module. It was only used by the now + removed ovs-test and ovs-l3ping utilities. - Userspace datapath: * ARP/ND lookups for native tunnel are now rate limited. The holdout timer can be configured with 'tnl/neigh/retrans_time'. diff --git a/debian/control.in b/debian/control.in index 836e2564a..19350c7bc 100644 --- a/debian/control.in +++ b/debian/control.in @@ -210,7 +210,6 @@ Description: Open vSwitch switch implementations Package: openvswitch-test Architecture: all Depends: - python3-twisted, ${misc:Depends}, ${python3:Depends}, Breaks: diff --git a/debian/openvswitch-test.install b/debian/openvswitch-test.install index 12b0d284a..3790b8f55 100644 --- a/debian/openvswitch-test.install +++ b/debian/openvswitch-test.install @@ -1,2 +1 @@ -usr/share/openvswitch/python/ovstest usr/lib/python3/dist-packages/ usr/share/openvswitch/scripts/usdt/* diff --git a/python/automake.mk b/python/automake.mk index 060d76cb7..3caf39140 100644 --- a/python/automake.mk +++ b/python/automake.mk @@ -1,13 +1,3 @@ -ovstest_pyfiles = \ - python/ovstest/__init__.py \ - python/ovstest/args.py \ - python/ovstest/rpcserver.py \ - python/ovstest/tcp.py \ - python/ovstest/tests.py \ - python/ovstest/udp.py \ - python/ovstest/util.py \ - python/ovstest/vswitch.py - ovs_pyfiles = \ python/ovs/__init__.py \ python/ovs/compat/__init__.py \ @@ -100,7 +90,7 @@ EXTRA_DIST += \ # C extension support. EXTRA_DIST += python/ovs/_json.c -PYFILES = $(ovs_pyfiles) python/ovs/dirs.py python/setup.py $(ovstest_pyfiles) $(ovs_pytests) \ +PYFILES = $(ovs_pyfiles) python/ovs/dirs.py python/setup.py $(ovs_pytests) \ $(ovs_flowviz) EXTRA_DIST += $(PYFILES) @@ -115,7 +105,7 @@ FLAKE8_PYFILES += \ python/ovs/dirs.py.template \ python/setup.py.template -nobase_pkgdata_DATA = $(ovs_pyfiles) $(ovstest_pyfiles) $(ovs_flowviz) +nobase_pkgdata_DATA = $(ovs_pyfiles) $(ovs_flowviz) nobase_pkgdata_DATA += python/ovs/flowviz/ovs-flowviz.conf ovs-install-data-local: diff --git a/python/ovstest/__init__.py b/python/ovstest/__init__.py deleted file mode 100644 index 218d8921e..000000000 --- a/python/ovstest/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# This file intentionally left blank. diff --git a/python/ovstest/args.py b/python/ovstest/args.py deleted file mode 100644 index 975d1880b..000000000 --- a/python/ovstest/args.py +++ /dev/null @@ -1,283 +0,0 @@ -# Copyright (c) 2011, 2012 Nicira, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -ovsargs provide argument parsing for ovs-test utility -""" - -import argparse -import re -import socket -import sys - -CONTROL_PORT = 15531 -DATA_PORT = 15532 - - -def ip_address(string): - """Verifies if string is a valid IP address""" - try: - socket.inet_aton(string) - except socket.error: - raise argparse.ArgumentTypeError("Not a valid IPv4 address") - 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 TCP/UDP Port (integer)""" - try: - 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 port_number - - -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. 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_callback(value[0]), default_port) - elif len(value) == 2: - return (ip_callback(value[0]), port(value[1])) - else: - raise argparse.ArgumentTypeError("IP address from the optional Port " - "must be colon-separated") - - -def ip_optional_port_port(string, default_port1, default_port2, ip_callback): - """Convert a string into IP, Port1, Port2 tuple. If any of ports were - missing, then default ports will be used. The fourth argument is a - callback that verifies whether IP address is given in the expected - format.""" - value = string.split(':') - if len(value) == 1: - return (ip_callback(value[0]), default_port1, default_port2) - elif len(value) == 2: - return (ip_callback(value[0]), port(value[1]), default_port2) - elif len(value) == 3: - return (ip_callback(value[0]), port(value[1]), port(value[2])) - else: - raise argparse.ArgumentTypeError("Expected IP address and at most " - "two colon-separated ports") - - -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 OuterIP[:OuterPort],InnerIP[/Mask][:InnerPort] - into a 4-tuple, where: - 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) == 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("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) is None: - raise argparse.ArgumentTypeError("Not a valid target bandwidth") - bwidth = string.replace("M", "000000") - bwidth = bwidth.replace("K", "000") - return int(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 l3_endpoint_client(string): - """ - This function parses command line argument string in - remoteIP,localInnerIP[/mask][:ControlPort[:TestPort]],remoteInnerIP[: - ControlPort[:TestPort]] format. - """ - try: - remote_ip, me, he = string.split(',') - except ValueError: - raise argparse.ArgumentTypeError("All 3 IP addresses must be comma " - "separated.") - r = (ip_address(remote_ip), - ip_optional_port_port(me, CONTROL_PORT, DATA_PORT, ip_optional_mask), - ip_optional_port_port(he, CONTROL_PORT, DATA_PORT, ip_address)) - return r - - -def l3_endpoint_server(string): - """ - This function parses a command line argument string in - remoteIP,localInnerIP[/mask][:ControlPort] format. - """ - try: - remote_ip, me = string.split(',') - except ValueError: - raise argparse.ArgumentTypeError("Both IP addresses must be comma " - "separated.") - return (ip_address(remote_ip), - ip_optional_port(me, CONTROL_PORT, ip_optional_mask)) - - -def ovs_initialize_args(): - """ - 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.') - 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() - - -def l3_initialize_args(): - """ - Initialize argument parsing for ovs-l3ping utility. - """ - parser = argparse.ArgumentParser(description='Test L3 tunnel ' - 'connectivity between two Open vSwitch instances.') - - parser.add_argument('-v', '--version', action='version', - version='ovs-l3ping (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.') - 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-mode", action='store', - dest="tunnelMode", required=True, - help='Do L3 tests with this tunnel type.') - - group = parser.add_mutually_exclusive_group(required=True) - group.add_argument("-s", "--server", action="store", dest="server", - metavar="TUNNELIP,SERVER", - type=l3_endpoint_server, - help='Run in server mode and wait for the client to ' - 'connect.') - group.add_argument('-c', "--client", action="store", dest="client", - metavar="TUNNELIP,CLIENT,SERVER", - type=l3_endpoint_client, - help='Run in client mode and connect to the server.') - return parser.parse_args() diff --git a/python/ovstest/rpcserver.py b/python/ovstest/rpcserver.py deleted file mode 100644 index 05b6b1be2..000000000 --- a/python/ovstest/rpcserver.py +++ /dev/null @@ -1,372 +0,0 @@ -# Copyright (c) 2011, 2012 Nicira, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -rpcserver is an XML RPC server that allows RPC client to initiate tests -""" - -import sys - -import xmlrpc.client - -from twisted.internet import reactor -from twisted.internet.error import CannotListenError -from twisted.web import server -from twisted.web import xmlrpc - -from . import tcp, udp, util, vswitch - - -class TestArena(xmlrpc.XMLRPC): - """ - This class contains all the functions that ovs-test client will call - remotely. The caller is responsible to use designated handleIds - for designated methods (e.g. do not mix UDP and TCP handles). - """ - - def __init__(self): - xmlrpc.XMLRPC.__init__(self, allowNone=True) - self.handle_id = 1 - self.handle_map = {} - self.bridges = set() - self.pbridges = set() - self.ports = set() - self.request = None - - def __acquire_handle(self, value): - """ - Allocates new handle and assigns value object to it - """ - handle = self.handle_id - self.handle_map[handle] = value - self.handle_id += 1 - return handle - - def __get_handle_resources(self, handle): - """ - Return resources that were assigned to handle - """ - return self.handle_map[handle] - - def __delete_handle(self, handle): - """ - Releases handle from handle_map - """ - del self.handle_map[handle] - - def cleanup(self): - """ - Delete all remaining bridges and ports if ovs-test client did not had - a chance to remove them. It is necessary to call this function if - ovs-test server is abruptly terminated when doing the tests. - """ - for port in self.ports: - # Remove ports that were added to existing bridges - vswitch.ovs_vsctl_del_port_from_bridge(port) - - for bridge in self.bridges: - # Remove bridges that were added for L3 tests - vswitch.ovs_vsctl_del_bridge(bridge) - - for pbridge in self.pbridges: - # Remove bridges that were added for VLAN tests - vswitch.ovs_vsctl_del_pbridge(pbridge[0], pbridge[1]) - - def render(self, request): - """ - This method overrides the original XMLRPC.render method so that it - would be possible to get the XML RPC client IP address from the - request object. - """ - self.request = request - return xmlrpc.XMLRPC.render(self, request) - - def xmlrpc_get_my_address(self): - """ - Returns the RPC client's IP address. - """ - return self.request.getClientIP() - - def xmlrpc_get_my_address_from(self, his_ip, his_port): - """ - Returns the ovs-test server IP address that the other ovs-test server - with the given ip will see. - """ - server1 = xmlrpc.client.Server("http://%s:%u/" % (his_ip, his_port)) - return server1.get_my_address() - - def xmlrpc_create_udp_listener(self, port): - """ - Creates a UDP listener that will receive packets from UDP sender - """ - try: - listener = udp.UdpListener() - reactor.listenUDP(port, listener) - handle_id = self.__acquire_handle(listener) - except CannotListenError: - return -1 - return handle_id - - def xmlrpc_create_udp_sender(self, host, count, size, duration): - """ - Send UDP datagrams to UDP listener - """ - sender = udp.UdpSender(tuple(host), count, size, duration) - reactor.listenUDP(0, sender) - handle_id = self.__acquire_handle(sender) - return handle_id - - def xmlrpc_get_udp_listener_results(self, handle): - """ - Returns number of datagrams that were received - """ - listener = self.__get_handle_resources(handle) - return listener.getResults() - - def xmlrpc_get_udp_sender_results(self, handle): - """ - Returns number of datagrams that were sent - """ - sender = self.__get_handle_resources(handle) - return sender.getResults() - - def xmlrpc_close_udp_listener(self, handle): - """ - Releases UdpListener and all its resources - """ - listener = self.__get_handle_resources(handle) - listener.transport.stopListening() - self.__delete_handle(handle) - return 0 - - def xmlrpc_close_udp_sender(self, handle): - """ - Releases UdpSender and all its resources - """ - sender = self.__get_handle_resources(handle) - sender.transport.stopListening() - self.__delete_handle(handle) - return 0 - - def xmlrpc_create_tcp_listener(self, port): - """ - Creates a TcpListener that will accept connection from TcpSender - """ - try: - listener = tcp.TcpListenerFactory() - port = reactor.listenTCP(port, listener) - handle_id = self.__acquire_handle((listener, port)) - return handle_id - except CannotListenError: - return -1 - - def xmlrpc_create_tcp_sender(self, his_ip, his_port, duration): - """ - Creates a TcpSender that will connect to TcpListener - """ - sender = tcp.TcpSenderFactory(duration) - connector = reactor.connectTCP(his_ip, his_port, sender) - handle_id = self.__acquire_handle((sender, connector)) - return handle_id - - def xmlrpc_get_tcp_listener_results(self, handle): - """ - Returns number of bytes received - """ - (listener, _) = self.__get_handle_resources(handle) - return listener.getResults() - - def xmlrpc_get_tcp_sender_results(self, handle): - """ - Returns number of bytes sent - """ - (sender, _) = self.__get_handle_resources(handle) - return sender.getResults() - - def xmlrpc_close_tcp_listener(self, handle): - """ - Releases TcpListener and all its resources - """ - try: - (_, port) = self.__get_handle_resources(handle) - port.loseConnection() - self.__delete_handle(handle) - except KeyError: - return -1 - return 0 - - def xmlrpc_close_tcp_sender(self, handle): - """ - Releases TcpSender and all its resources - """ - try: - (_, connector) = self.__get_handle_resources(handle) - connector.disconnect() - self.__delete_handle(handle) - except KeyError: - return -1 - return 0 - - def xmlrpc_create_test_bridge(self, bridge, iface): - """ - This function creates a physical bridge from iface. It moves the - IP configuration from the physical interface to the bridge. - """ - ret = vswitch.ovs_vsctl_add_bridge(bridge) - if ret == 0: - self.pbridges.add((bridge, iface)) - util.interface_up(bridge) - (ip_addr, mask) = util.interface_get_ip(iface) - util.interface_assign_ip(bridge, ip_addr, mask) - util.interface_up(bridge) - util.move_routes(iface, bridge) - util.interface_remove_ip(iface, ip_addr, mask) - ret = vswitch.ovs_vsctl_add_port_to_bridge(bridge, iface) - if ret == 0: - self.ports.add(iface) - else: - util.interface_assign_ip(iface, ip_addr, mask) - util.interface_up(iface) - util.move_routes(bridge, iface) - vswitch.ovs_vsctl_del_bridge(bridge) - - return ret - - def xmlrpc_del_test_bridge(self, bridge, iface): - """ - This function deletes the test bridge and moves its IP configuration - back to the physical interface. - """ - ret = vswitch.ovs_vsctl_del_pbridge(bridge, iface) - self.pbridges.discard((bridge, iface)) - return ret - - def xmlrpc_get_iface_from_bridge(self, brname): - """ - Tries to figure out physical interface from bridge. - """ - return vswitch.ovs_get_physical_interface(brname) - - def xmlrpc_create_bridge(self, brname): - """ - Creates an OVS bridge. - """ - ret = vswitch.ovs_vsctl_add_bridge(brname) - if ret == 0: - self.bridges.add(brname) - return ret - - def xmlrpc_del_bridge(self, brname): - """ - Deletes an OVS bridge. - """ - ret = vswitch.ovs_vsctl_del_bridge(brname) - if ret == 0: - self.bridges.discard(brname) - return ret - - def xmlrpc_is_ovs_bridge(self, bridge): - """ - This function verifies whether given interface is an ovs bridge. - """ - return vswitch.ovs_vsctl_is_ovs_bridge(bridge) - - def xmlrpc_add_port_to_bridge(self, bridge, port): - """ - Adds a port to the OVS bridge. - """ - ret = vswitch.ovs_vsctl_add_port_to_bridge(bridge, port) - if ret == 0: - self.ports.add(port) - return ret - - def xmlrpc_del_port_from_bridge(self, port): - """ - Removes a port from OVS bridge. - """ - ret = vswitch.ovs_vsctl_del_port_from_bridge(port) - if ret == 0: - self.ports.discard(port) - return ret - - def xmlrpc_ovs_vsctl_set(self, table, record, column, key, value): - """ - This function allows to alter OVS database. - """ - return vswitch.ovs_vsctl_set(table, record, column, key, value) - - def xmlrpc_interface_up(self, iface): - """ - This function brings up given interface. - """ - return util.interface_up(iface) - - def xmlrpc_interface_assign_ip(self, iface, ip_address, mask): - """ - This function allows to assing ip address to the given interface. - """ - return util.interface_assign_ip(iface, ip_address, mask) - - def xmlrpc_interface_remove_ip(self, iface, ip_address, mask): - """ - This function allows to assing ip address to the given interface. - """ - return util.interface_remove_ip(iface, ip_address, mask) - - def xmlrpc_get_interface(self, address): - """ - Finds first interface that has given address - """ - return util.get_interface(address) - - def xmlrpc_get_interface_mtu(self, iface): - """ - Returns MTU of the given interface - """ - return util.get_interface_mtu(iface) - - def xmlrpc_uname(self): - """ - Return information about running kernel - """ - return util.uname() - - def xmlrpc_get_driver(self, iface): - """ - Returns driver version - """ - return util.get_driver(iface) - - def xmlrpc_get_interface_from_routing_decision(self, ip): - """ - Returns driver version - """ - return util.get_interface_from_routing_decision(ip) - - -def start_rpc_server(port): - """ - This function creates a RPC server and adds it to the Twisted Reactor. - """ - rpc_server = TestArena() - reactor.listenTCP(port, server.Site(rpc_server)) - try: - print("Starting RPC server\n") - sys.stdout.flush() - # If this server was started from ovs-test client then we must flush - # STDOUT so that client would know that server is ready to accept - # XML RPC connections. - reactor.run() - finally: - rpc_server.cleanup() diff --git a/python/ovstest/tcp.py b/python/ovstest/tcp.py deleted file mode 100644 index 098c6cba3..000000000 --- a/python/ovstest/tcp.py +++ /dev/null @@ -1,120 +0,0 @@ -# Copyright (c) 2011, 2012 Nicira, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -tcp module contains listener and sender classes for TCP protocol -""" - -import time - -from twisted.internet import interfaces -from twisted.internet.protocol import ClientFactory, Factory, Protocol - -from zope.interface.declarations import implementer - - -class TcpListenerConnection(Protocol): - """ - This per-connection class is instantiated each time sender connects - """ - def __init__(self): - self.stats = 0 - - def dataReceived(self, data): - self.stats += len(data) - - def connectionLost(self, reason): - self.factory.stats += self.stats - - -class TcpListenerFactory(Factory): - """ - This per-listening socket class is used to - instantiate TcpListenerConnections - """ - protocol = TcpListenerConnection - - def __init__(self): - self.stats = 0 - - def getResults(self): - """ returns the number of bytes received as string""" - # XML RPC does not support 64bit int (http://bugs.python.org/issue2985) - # so we have to convert the amount of bytes into a string - return str(self.stats) - - -@implementer(interfaces.IPushProducer) -class Producer(object): - """ - This producer class generates infinite byte stream for a specified time - duration - """ - def __init__(self, proto, duration): - self.proto = proto - self.start = time.time() - self.produced = 0 - self.paused = False - self.data = "X" * 65535 - self.duration = duration - - def pauseProducing(self): - """This function is called whenever write() to socket would block""" - self.paused = True - - def resumeProducing(self): - """This function is called whenever socket becomes writable""" - self.paused = False - current = time.time() - while (not self.paused) and (current < self.start + self.duration): - self.proto.transport.write(self.data) - self.produced += len(self.data) - current = time.time() - if current >= self.start + self.duration: - self.proto.factory.stats += self.produced - self.proto.transport.unregisterProducer() - self.proto.transport.loseConnection() - - def stopProducing(self): - pass - - -class TcpSenderConnection(Protocol): - """ - TCP connection instance class that sends all traffic at full speed. - """ - - def connectionMade(self): - producer = Producer(self, self.factory.duration) - self.transport.registerProducer(producer, True) - producer.resumeProducing() - - def dataReceived(self, data): - self.transport.loseConnection() - - -class TcpSenderFactory(ClientFactory): - """ - This factory is responsible to instantiate TcpSenderConnection classes - each time sender initiates connection - """ - protocol = TcpSenderConnection - - def __init__(self, duration): - self.duration = duration - self.stats = 0 - - def getResults(self): - """Returns amount of bytes sent to the Listener (as a string)""" - return str(self.stats) diff --git a/python/ovstest/tests.py b/python/ovstest/tests.py deleted file mode 100644 index f959f945e..000000000 --- a/python/ovstest/tests.py +++ /dev/null @@ -1,248 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import math -import time - -import ovstest.util as util - -DEFAULT_TEST_BRIDGE = "ovstestbr0" -DEFAULT_TEST_PORT = "ovstestport0" -DEFAULT_TEST_TUN = "ovstestport1" -NO_HANDLE = -1 - - -def do_udp_tests(receiver, sender, tbwidth, duration, port_sizes): - """Schedule UDP tests between receiver and sender""" - server1 = util.rpc_client(receiver[0], receiver[1]) - server2 = util.rpc_client(sender[0], sender[1]) - - udpformat = '{0:>15} {1:>15} {2:>15} {3:>15} {4:>15}' - - print("UDP test from %s:%u to %s:%u with target bandwidth %s" % - (sender[0], sender[1], receiver[0], receiver[1], - util.bandwidth_to_string(tbwidth))) - print(udpformat.format("Datagram Size", "Snt Datagrams", "Rcv Datagrams", - "Datagram Loss", "Bandwidth")) - - for size in port_sizes: - listen_handle = NO_HANDLE - send_handle = NO_HANDLE - try: - packetcnt = (tbwidth * duration) / size - - listen_handle = server1.create_udp_listener(receiver[3]) - if listen_handle == NO_HANDLE: - print("Server could not open UDP listening socket on port" - " %u. Try to restart the server.\n" % receiver[3]) - return - send_handle = server2.create_udp_sender( - (util.ip_from_cidr(receiver[2]), - receiver[3]), packetcnt, size, - duration) - - # Using sleep here because there is no other synchronization - # source that would notify us when all sent packets were received - time.sleep(duration + 1) - - rcv_packets = server1.get_udp_listener_results(listen_handle) - snt_packets = server2.get_udp_sender_results(send_handle) - - loss = math.ceil(((snt_packets - rcv_packets) * 10000.0) / - snt_packets) / 100 - bwidth = (rcv_packets * size) / duration - - print(udpformat.format(size, snt_packets, rcv_packets, - '%.2f%%' % loss, util.bandwidth_to_string(bwidth))) - finally: - if listen_handle != NO_HANDLE: - server1.close_udp_listener(listen_handle) - if send_handle != NO_HANDLE: - server2.close_udp_sender(send_handle) - print("\n") - - -def do_tcp_tests(receiver, sender, duration): - """Schedule TCP tests between receiver and sender""" - server1 = util.rpc_client(receiver[0], receiver[1]) - server2 = util.rpc_client(sender[0], sender[1]) - - tcpformat = '{0:>15} {1:>15} {2:>15}' - print("TCP test from %s:%u to %s:%u (full speed)" % (sender[0], sender[1], - receiver[0], receiver[1])) - print(tcpformat.format("Snt Bytes", "Rcv Bytes", "Bandwidth")) - - listen_handle = NO_HANDLE - send_handle = NO_HANDLE - try: - listen_handle = server1.create_tcp_listener(receiver[3]) - if listen_handle == NO_HANDLE: - print("Server was unable to open TCP listening socket on port" - " %u. Try to restart the server.\n" % receiver[3]) - return - send_handle = server2.create_tcp_sender(util.ip_from_cidr(receiver[2]), - receiver[3], duration) - - time.sleep(duration + 1) - - rcv_bytes = int(server1.get_tcp_listener_results(listen_handle)) - snt_bytes = int(server2.get_tcp_sender_results(send_handle)) - - bwidth = rcv_bytes / duration - - print(tcpformat.format(snt_bytes, rcv_bytes, - util.bandwidth_to_string(bwidth))) - finally: - if listen_handle != NO_HANDLE: - server1.close_tcp_listener(listen_handle) - if send_handle != NO_HANDLE: - server2.close_tcp_sender(send_handle) - print("\n") - - -def do_l3_tests(node1, node2, bandwidth, duration, ps, type): - """ - Do L3 tunneling tests. Each node is given as 4 tuple - physical - interface IP, control port, test IP and test port. - """ - server1 = util.rpc_client(node1[0], node1[1]) - server2 = util.rpc_client(node2[0], node2[1]) - servers_with_bridges = [] - try: - server1.create_bridge(DEFAULT_TEST_BRIDGE) - servers_with_bridges.append(server1) - server2.create_bridge(DEFAULT_TEST_BRIDGE) - servers_with_bridges.append(server2) - - server1.interface_up(DEFAULT_TEST_BRIDGE) - server2.interface_up(DEFAULT_TEST_BRIDGE) - - server1.interface_assign_ip(DEFAULT_TEST_BRIDGE, node1[2], None) - server2.interface_assign_ip(DEFAULT_TEST_BRIDGE, node2[2], None) - - server1.add_port_to_bridge(DEFAULT_TEST_BRIDGE, DEFAULT_TEST_TUN) - server2.add_port_to_bridge(DEFAULT_TEST_BRIDGE, DEFAULT_TEST_TUN) - - server1.ovs_vsctl_set("Interface", DEFAULT_TEST_TUN, "type", - None, type) - server2.ovs_vsctl_set("Interface", DEFAULT_TEST_TUN, "type", - None, type) - server1.ovs_vsctl_set("Interface", DEFAULT_TEST_TUN, "options", - "remote_ip", node2[0]) - server2.ovs_vsctl_set("Interface", DEFAULT_TEST_TUN, "options", - "remote_ip", node1[0]) - - do_udp_tests(node1, node2, bandwidth, duration, ps) - do_udp_tests(node2, node1, bandwidth, duration, ps) - do_tcp_tests(node1, node2, duration) - do_tcp_tests(node2, node1, duration) - - finally: - for server in servers_with_bridges: - server.del_bridge(DEFAULT_TEST_BRIDGE) - - -def do_vlan_tests(node1, node2, bandwidth, duration, ps, tag): - """ - Do VLAN tests between node1 and node2. Each node is given - as 4 tuple - physical interface IP, control port, test IP and - test port. - """ - server1 = util.rpc_client(node1[0], node1[1]) - server2 = util.rpc_client(node2[0], node2[1]) - - br_name1 = None - br_name2 = None - - servers_with_test_ports = [] - - try: - interface_node1 = server1.get_interface(node1[0]) - interface_node2 = server2.get_interface(node2[0]) - - if server1.is_ovs_bridge(interface_node1): - br_name1 = interface_node1 - else: - br_name1 = DEFAULT_TEST_BRIDGE - server1.create_test_bridge(br_name1, interface_node1) - - if server2.is_ovs_bridge(interface_node2): - br_name2 = interface_node2 - else: - br_name2 = DEFAULT_TEST_BRIDGE - server2.create_test_bridge(br_name2, interface_node2) - - server1.add_port_to_bridge(br_name1, DEFAULT_TEST_PORT) - servers_with_test_ports.append(server1) - server2.add_port_to_bridge(br_name2, DEFAULT_TEST_PORT) - servers_with_test_ports.append(server2) - - server1.ovs_vsctl_set("Port", DEFAULT_TEST_PORT, "tag", None, tag) - server2.ovs_vsctl_set("Port", DEFAULT_TEST_PORT, "tag", None, tag) - - server1.ovs_vsctl_set("Interface", DEFAULT_TEST_PORT, "type", None, - "internal") - server2.ovs_vsctl_set("Interface", DEFAULT_TEST_PORT, "type", None, - "internal") - - server1.interface_assign_ip(DEFAULT_TEST_PORT, node1[2], None) - server2.interface_assign_ip(DEFAULT_TEST_PORT, node2[2], None) - - server1.interface_up(DEFAULT_TEST_PORT) - server2.interface_up(DEFAULT_TEST_PORT) - - do_udp_tests(node1, node2, bandwidth, duration, ps) - do_udp_tests(node2, node1, bandwidth, duration, ps) - do_tcp_tests(node1, node2, duration) - do_tcp_tests(node2, node1, duration) - - finally: - for server in servers_with_test_ports: - server.del_port_from_bridge(DEFAULT_TEST_PORT) - if br_name1 == DEFAULT_TEST_BRIDGE: - server1.del_test_bridge(br_name1, interface_node1) - if br_name2 == DEFAULT_TEST_BRIDGE: - server2.del_test_bridge(br_name2, interface_node2) - - -def do_direct_tests(node1, node2, bandwidth, duration, ps): - """ - Do tests between outer IPs without involving Open vSwitch. Each - node is given as 4 tuple - physical interface IP, control port, - test IP and test port. Direct tests will use physical interface - IP as the test IP address. - """ - n1 = (node1[0], node1[1], node1[0], node1[3]) - n2 = (node2[0], node2[1], node2[0], node2[3]) - - do_udp_tests(n1, n2, bandwidth, duration, ps) - do_udp_tests(n2, n1, bandwidth, duration, ps) - do_tcp_tests(n1, n2, duration) - do_tcp_tests(n2, n1, duration) - - -def configure_l3(conf, tunnel_mode): - """ - This function creates a temporary test bridge and adds an L3 tunnel. - """ - s = util.start_local_server(conf[1][1]) - server = util.rpc_client("127.0.0.1", conf[1][1]) - server.create_bridge(DEFAULT_TEST_BRIDGE) - server.add_port_to_bridge(DEFAULT_TEST_BRIDGE, DEFAULT_TEST_PORT) - server.interface_up(DEFAULT_TEST_BRIDGE) - server.interface_assign_ip(DEFAULT_TEST_BRIDGE, conf[1][0], - None) - server.ovs_vsctl_set("Interface", DEFAULT_TEST_PORT, "type", - None, tunnel_mode) - server.ovs_vsctl_set("Interface", DEFAULT_TEST_PORT, "options", - "remote_ip", conf[0]) - return s diff --git a/python/ovstest/udp.py b/python/ovstest/udp.py deleted file mode 100644 index acd28d575..000000000 --- a/python/ovstest/udp.py +++ /dev/null @@ -1,85 +0,0 @@ -# Copyright (c) 2011, 2012 Nicira, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -ovsudp contains listener and sender classes for UDP protocol -""" - -import array -import struct -import time - -from twisted.internet.protocol import DatagramProtocol -from twisted.internet.task import LoopingCall - - -class UdpListener(DatagramProtocol): - """ - Class that will listen for incoming UDP packets - """ - def __init__(self): - self.stats = [] - - def datagramReceived(self, data, _1_2): - """This function is called each time datagram is received""" - try: - self.stats.append(struct.unpack_from("Q", data, 0)) - except struct.error: - pass # ignore packets that are less than 8 bytes of size - - def getResults(self): - """Returns number of packets that were actually received""" - return len(self.stats) - - -class UdpSender(DatagramProtocol): - """ - Class that will send UDP packets to UDP Listener - """ - def __init__(self, host, count, size, duration): - # LoopingCall does not know whether UDP socket is actually writable - self.looper = None - self.host = host - self.count = count - self.duration = duration - self.start = time.time() - self.sent = 0 - self.data = array.array('c', 'X' * size) - - def startProtocol(self): - self.looper = LoopingCall(self.sendData) - period = self.duration / float(self.count) - self.looper.start(period, now=False) - - def stopProtocol(self): - if (self.looper is not None): - self.looper.stop() - self.looper = None - - def datagramReceived(self, data, host_port): - pass - - def sendData(self): - """This function is called from LoopingCall""" - if self.start + self.duration < time.time(): - self.looper.stop() - self.looper = None - - self.sent += 1 - struct.pack_into('Q', self.data, 0, self.sent) - self.transport.write(self.data, self.host) - - def getResults(self): - """Returns number of packets that were sent""" - return self.sent diff --git a/python/ovstest/util.py b/python/ovstest/util.py deleted file mode 100644 index 270d6a037..000000000 --- a/python/ovstest/util.py +++ /dev/null @@ -1,249 +0,0 @@ -# Copyright (c) 2011, 2012, 2017 Nicira, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -util module contains some helper function -""" -import array -import fcntl - -import os -import re -import select -import signal -import socket -import struct -import subprocess - -import xmlrpc.client - - -def str_ip(ip_address): - """ - Converts an IP address from binary format to a string. - """ - (x1, x2, x3, x4) = struct.unpack("BBBB", ip_address) - return ("%u.%u.%u.%u") % (x1, x2, x3, x4) - - -def get_interface_mtu(iface): - """ - Returns MTU of the given interface. - """ - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - indata = iface + ('\0' * (32 - len(iface))) - try: - outdata = fcntl.ioctl(s.fileno(), 0x8921, indata) # socket.SIOCGIFMTU - mtu = struct.unpack("16si12x", outdata)[1] - except: - return 0 - - return mtu - - -def get_interface(address): - """ - Finds first interface that has given address - """ - bytes = 256 * 32 - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - names = array.array('B', '\0' * bytes) - outbytes = struct.unpack('iL', fcntl.ioctl( - s.fileno(), - 0x8912, # SIOCGIFCONF - struct.pack('iL', bytes, names.buffer_info()[0]) - ))[0] - namestr = names.tostring() - - for i in range(0, outbytes, 40): - name = namestr[i:i + 16].split('\0', 1)[0] - if address == str_ip(namestr[i + 20:i + 24]): - return name - return None # did not find interface we were looking for - - -def uname(): - os_info = os.uname() - return os_info[2] # return only the kernel version number - - -def start_process(args): - try: - p = subprocess.Popen(args, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - out, err = p.communicate() - return (p.returncode, out, err) - except OSError: - return (-1, None, None) - - -def get_driver(iface): - ret, out, _err = start_process(["ethtool", "-i", iface]) - if ret == 0: - lines = out.splitlines() - driver = "%s(%s)" % (lines[0], lines[1]) # driver name + version - else: - driver = None - return driver - - -def interface_up(iface): - """ - This function brings given iface up. - """ - ret, _out, _err = start_process(["ip", "link", "set", iface, "up"]) - return ret - - -def interface_assign_ip(iface, ip_addr, mask): - """ - This function adds an IP address to an interface. If mask is None - then a mask will be selected automatically. In case of success - this function returns 0. - """ - interface_ip_op(iface, ip_addr, mask, "add") - - -def interface_remove_ip(iface, ip_addr, mask): - """ - This function removes an IP address from an interface. If mask is - None then a mask will be selected automatically. In case of - success this function returns 0. - """ - interface_ip_op(iface, ip_addr, mask, "del") - - -def interface_ip_op(iface, ip_addr, mask, op): - if mask is not None: - arg = "%s/%s" % (ip_addr, mask) - elif '/' in ip_addr: - arg = ip_addr - else: - (x1, x2, x3, x4) = struct.unpack("BBBB", socket.inet_aton(ip_addr)) - if x1 < 128: - arg = "%s/8" % ip_addr - elif x1 < 192: - arg = "%s/16" % ip_addr - else: - arg = "%s/24" % ip_addr - ret, _out, _err = start_process(["ip", "addr", op, arg, "dev", iface]) - return ret - - -def interface_get_ip(iface): - """ - This function returns tuple - ip and mask that was assigned to the - interface. - """ - args = ["ip", "addr", "show", iface] - ret, out, _err = start_process(args) - - if ret == 0: - ip = re.search(r'inet (\S+)/(\S+)', out) - if ip is not None: - return (ip.group(1), ip.group(2)) - else: - return ret - - -def move_routes(iface1, iface2): - """ - This function moves routes from iface1 to iface2. - """ - args = ["ip", "route", "show", "dev", iface1] - ret, out, _err = start_process(args) - if ret == 0: - for route in out.splitlines(): - args = ["ip", "route", "replace", "dev", iface2] + route.split() - start_process(args) - - -def get_interface_from_routing_decision(ip): - """ - This function returns the interface through which the given ip address - is reachable. - """ - args = ["ip", "route", "get", ip] - ret, out, _err = start_process(args) - if ret == 0: - iface = re.search(r'dev (\S+)', out) - if iface: - return iface.group(1) - return None - - -def rpc_client(ip, port): - return xmlrpc.client.Server("http://%s:%u/" % (ip, port), allow_none=True) - - -def sigint_intercept(): - """ - Intercept SIGINT from child (the local ovs-test server process). - """ - signal.signal(signal.SIGINT, signal.SIG_IGN) - - -def start_local_server(port): - """ - This function spawns an ovs-test server that listens on specified port - and blocks till the spawned ovs-test server is ready to accept XML RPC - connections. - """ - p = subprocess.Popen(["ovs-test", "-s", str(port)], - stdout=subprocess.PIPE, stderr=subprocess.PIPE, - preexec_fn=sigint_intercept) - fcntl.fcntl(p.stdout.fileno(), fcntl.F_SETFL, - fcntl.fcntl(p.stdout.fileno(), fcntl.F_GETFL) | os.O_NONBLOCK) - - while p.poll() is None: - fd = select.select([p.stdout.fileno()], [], [])[0] - if fd: - out = p.stdout.readline() - if out.startswith("Starting RPC server"): - break - if p.poll() is not None: - raise RuntimeError("Couldn't start local instance of ovs-test server") - return p - - -def get_datagram_sizes(mtu1, mtu2): - """ - This function calculates all the "interesting" datagram sizes so that - we test both - receive and send side with different packets sizes. - """ - s1 = set([8, mtu1 - 100, mtu1 - 28, mtu1]) - s2 = set([8, mtu2 - 100, mtu2 - 28, mtu2]) - return sorted(s1.union(s2)) - - -def ip_from_cidr(string): - """ - This function removes the netmask (if present) from the given string and - returns the IP address. - """ - token = string.split("/") - return token[0] - - -def bandwidth_to_string(bwidth): - """Convert bandwidth from long to string and add units.""" - bwidth = bwidth * 8 # Convert back to bits/second - if bwidth >= 10000000: - return str(int(bwidth / 1000000)) + "Mbps" - elif bwidth > 10000: - return str(int(bwidth / 1000)) + "Kbps" - else: - return str(int(bwidth)) + "bps" diff --git a/python/ovstest/vswitch.py b/python/ovstest/vswitch.py deleted file mode 100644 index 45c9587ee..000000000 --- a/python/ovstest/vswitch.py +++ /dev/null @@ -1,107 +0,0 @@ -# Copyright (c) 2012 Nicira, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -vswitch module allows its callers to interact with OVS DB. -""" -from . import util - - -def ovs_vsctl_add_bridge(bridge): - """ - This function creates an OVS bridge. - """ - ret, _out, _err = util.start_process(["ovs-vsctl", "add-br", bridge]) - return ret - - -def ovs_vsctl_del_bridge(bridge): - """ - This function deletes the OVS bridge. - """ - ret, _out, _err = util.start_process(["ovs-vsctl", "del-br", bridge]) - return ret - - -def ovs_vsctl_del_pbridge(bridge, iface): - """ - This function deletes the OVS bridge and assigns the bridge IP address - back to the iface. - """ - (ip_addr, mask) = util.interface_get_ip(bridge) - util.interface_assign_ip(iface, ip_addr, mask) - util.interface_up(iface) - util.move_routes(bridge, iface) - return ovs_vsctl_del_bridge(bridge) - - -def ovs_vsctl_is_ovs_bridge(bridge): - """ - This function verifies whether given port is an OVS bridge. If it is an - OVS bridge then it will return True. - """ - ret, _out, _err = util.start_process(["ovs-vsctl", "br-exists", bridge]) - return ret == 0 - - -def ovs_vsctl_add_port_to_bridge(bridge, iface): - """ - This function adds given interface to the bridge. - """ - ret, _out, _err = util.start_process(["ovs-vsctl", "add-port", bridge, - iface]) - return ret - - -def ovs_vsctl_del_port_from_bridge(port): - """ - This function removes given port from a OVS bridge. - """ - ret, _out, _err = util.start_process(["ovs-vsctl", "del-port", port]) - return ret - - -def ovs_vsctl_set(table, record, column, key, value): - """ - This function allows to alter the OVS database. If column is a map, then - caller should also set the key, otherwise the key should be left as an - empty string. - """ - if key is None: - index = column - else: - index = "%s:%s" % (column, key) - index_value = "%s=%s" % (index, value) - ret, _out, _err = util.start_process(["ovs-vsctl", "set", table, record, - index_value]) - return ret - - -def ovs_get_physical_interface(bridge): - """ - This function tries to figure out which is the physical interface that - belongs to the bridge. If there are multiple physical interfaces assigned - to this bridge then it will return the first match. - """ - ret, out, _err = util.start_process(["ovs-vsctl", "list-ifaces", bridge]) - - if ret == 0: - ifaces = out.splitlines() - for iface in ifaces: - ret, out, _err = util.start_process(["ovs-vsctl", "get", - "Interface", iface, "type"]) - if ret == 0: - if ('""' in out) or ('system' in out): - return iface # this should be the physical interface - return None diff --git a/rhel/openvswitch-fedora.spec.in b/rhel/openvswitch-fedora.spec.in index 359a6dd29..72bd676e8 100644 --- a/rhel/openvswitch-fedora.spec.in +++ b/rhel/openvswitch-fedora.spec.in @@ -427,7 +427,6 @@ fi %{_mandir}/man1/ovs-pcap.1* %{_mandir}/man8/ovs-tcpdump.8* %{_mandir}/man1/ovs-tcpundump.1* -%{python3_sitelib}/ovstest %files devel %{_libdir}/lib*.so -- 2.54.0 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
