vswitches/ovs: delete bridges on stop
[vswitchperf.git] / src / ovs / ofctl.py
index a75d0be..21da850 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 2015-2016 Intel Corporation.
+# Copyright 2015-2017 Intel Corporation.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -19,30 +19,26 @@ Much of this code is based on ``ovs-lib.py`` from Open Stack:
 
 https://github.com/openstack/neutron/blob/6eac1dc99124ca024d6a69b3abfa3bc69c735667/neutron/agent/linux/ovs_lib.py
 """
-
-import os
 import logging
 import string
 import re
+import netaddr
 
 from tools import tasks
-from conf import settings
-
-_OVS_VSCTL_BIN = os.path.join(settings.getValue('OVS_DIR'), 'utilities',
-                              'ovs-vsctl')
-_OVS_OFCTL_BIN = os.path.join(settings.getValue('OVS_DIR'), 'utilities',
-                              'ovs-ofctl')
-_OVS_APPCTL_BIN = os.path.join(settings.getValue('OVS_DIR'), 'utilities',
-                               'ovs-appctl')
+from conf import settings as S
 
-_OVS_BRIDGE_NAME = settings.getValue('VSWITCH_BRIDGE_NAME')
+_OVS_BRIDGE_NAME = S.getValue('VSWITCH_BRIDGE_NAME')
+_OVS_CMD_TIMEOUT = S.getValue('OVS_CMD_TIMEOUT')
 
 _CACHE_FILE_NAME = '/tmp/vsperf_flows_cache'
 
+# only simple regex is used; validity of IPv4 is not checked by regex
+_IPV4_REGEX = r"([0-9]{1,3}(\.[0-9]{1,3}){3}(\/[0-9]{1,2})?)"
+
 class OFBase(object):
     """Add/remove/show datapaths using ``ovs-ofctl``.
     """
-    def __init__(self, timeout=10):
+    def __init__(self, timeout=_OVS_CMD_TIMEOUT):
         """Initialise logger.
 
         :param timeout: Timeout to be used for each command
@@ -66,9 +62,11 @@ class OFBase(object):
         :return: None
         """
         if self.timeout == -1:
-            cmd = ['sudo', _OVS_VSCTL_BIN, '--no-wait'] + args
+            cmd = ['sudo', S.getValue('TOOLS')['ovs-vsctl'], '--no-wait'] + \
+                  S.getValue('OVS_VSCTL_ARGS') + args
         else:
-            cmd = ['sudo', _OVS_VSCTL_BIN, '--timeout', str(self.timeout)] + args
+            cmd = ['sudo', S.getValue('TOOLS')['ovs-vsctl'], '--timeout',
+                   str(self.timeout)] + S.getValue('OVS_VSCTL_ARGS') + args
         return tasks.run_task(
             cmd, self.logger, 'Running ovs-vsctl...', check_error)
 
@@ -81,9 +79,9 @@ class OFBase(object):
 
         :return: None
         """
-        cmd = ['sudo', _OVS_APPCTL_BIN,
+        cmd = ['sudo', S.getValue('TOOLS')['ovs-appctl'],
                '--timeout',
-               str(self.timeout)] + args
+               str(self.timeout)] + S.getValue('OVS_APPCTL_ARGS') + args
         return tasks.run_task(
             cmd, self.logger, 'Running ovs-appctl...', check_error)
 
@@ -145,7 +143,7 @@ class OFBase(object):
 class OFBridge(OFBase):
     """Control a bridge instance using ``ovs-vsctl`` and ``ovs-ofctl``.
     """
-    def __init__(self, br_name=_OVS_BRIDGE_NAME, timeout=10):
+    def __init__(self, br_name=_OVS_BRIDGE_NAME, timeout=_OVS_CMD_TIMEOUT):
         """Initialise bridge.
 
         :param br_name: Bridge name
@@ -158,21 +156,6 @@ class OFBridge(OFBase):
         self._ports = {}
         self._cache_file = None
 
-    # context manager
-
-    def __enter__(self):
-        """Create datapath
-
-        :returns: self
-        """
-        return self
-
-    def __exit__(self, type_, value, traceback):
-        """Remove datapath.
-        """
-        if not traceback:
-            self.destroy()
-
     # helpers
 
     def run_ofctl(self, args, check_error=False, timeout=None):
@@ -183,9 +166,9 @@ class OFBridge(OFBase):
 
         :return: None
         """
-        tmp_timeout = self.timeout if timeout == None else timeout
-        cmd = ['sudo', _OVS_OFCTL_BIN, '-O', 'OpenFlow13', '--timeout',
-               str(tmp_timeout)] + args
+        tmp_timeout = self.timeout if timeout is None else timeout
+        cmd = ['sudo', S.getValue('TOOLS')['ovs-ofctl'], '--timeout',
+               str(tmp_timeout)] + S.getValue('OVS_OFCTL_ARGS') + args
         return tasks.run_task(
             cmd, self.logger, 'Running ovs-ofctl...', check_error)
 
@@ -298,7 +281,7 @@ class OFBridge(OFBase):
         """
         # insert flows from cache into OVS if needed
         if cache == 'flush':
-            if self._cache_file == None:
+            if self._cache_file is None:
                 self.logger.error('flow cache flush called, but nothing is cached')
                 return
             self.logger.debug('flows cached in %s will be added to the bridge', _CACHE_FILE_NAME)
@@ -317,7 +300,7 @@ class OFBridge(OFBase):
         # insert flow to the cache or OVS
         if cache == 'on':
             # create and open cache file if needed
-            if self._cache_file == None:
+            if self._cache_file is None:
                 self._cache_file = open(_CACHE_FILE_NAME, 'w')
             self._cache_file.write(_flow_key + '\n')
         else:
@@ -454,14 +437,21 @@ def flow_match(flow_dump, flow_src):
     flow_src = flow_src.replace('udp_dst', 'tp_dst')
     flow_src = flow_src.replace('tcp_src', 'tp_src')
     flow_src = flow_src.replace('tcp_dst', 'tp_dst')
+    flow_src = flow_src.replace('0x800', '0x0800')
+
+    # modify IPv4 CIDR to real network addresses
+    for ipv4_cidr in re.findall(_IPV4_REGEX, flow_src):
+        if ipv4_cidr[2]:
+            tmp_cidr = str(netaddr.IPNetwork(ipv4_cidr[0]).cidr)
+            flow_src = flow_src.replace(ipv4_cidr[0], tmp_cidr)
 
     # split flow strings into lists of comparable elements
-    flow_dump_list = re.findall(r"[\w.:=()]+", flow_dump)
-    flow_src_list = re.findall(r"[\w.:=()]+", flow_src)
+    flow_dump_list = re.findall(r"[\w.:=()/]+", flow_dump)
+    flow_src_list = re.findall(r"[\w.:=()/]+", flow_src)
 
     # check if all items from source flow are present in dump flow
     flow_src_ctrl = list(flow_src_list)
     for rule in flow_src_list:
         if rule in flow_dump_list:
             flow_src_ctrl.remove(rule)
-    return True if not len(flow_src_ctrl) else False
+    return True if not flow_src_ctrl else False