dpdk: Support of DPDK v16.04
[vswitchperf.git] / src / ovs / ofctl.py
index 9d16ef7..1ee4813 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 2015 Intel Corporation.
+# Copyright 2015-2016 Intel Corporation.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@ https://github.com/openstack/neutron/blob/6eac1dc99124ca024d6a69b3abfa3bc69c7356
 import os
 import logging
 import string
+import re
 
 from tools import tasks
 from conf import settings
@@ -31,6 +32,8 @@ _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')
 
 _OVS_BRIDGE_NAME = settings.getValue('VSWITCH_BRIDGE_NAME')
 
@@ -54,15 +57,37 @@ class OFBase(object):
     def run_vsctl(self, args, check_error=False):
         """Run ``ovs-vsctl`` with supplied arguments.
 
+        In case that timeout is set to -1, then ovs-vsctl
+        will be called with --no-wait option.
+
         :param args: Arguments to pass to ``ovs-vsctl``
         :param check_error: Throw exception on error
 
         :return: None
         """
-        cmd = ['sudo', _OVS_VSCTL_BIN, '--timeout', str(self.timeout)] + args
+        if self.timeout == -1:
+            cmd = ['sudo', _OVS_VSCTL_BIN, '--no-wait'] + args
+        else:
+            cmd = ['sudo', _OVS_VSCTL_BIN, '--timeout', str(self.timeout)] + args
         return tasks.run_task(
             cmd, self.logger, 'Running ovs-vsctl...', check_error)
 
+
+    def run_appctl(self, args, check_error=False):
+        """Run ``ovs-appctl`` with supplied arguments.
+
+        :param args: Arguments to pass to ``ovs-appctl``
+        :param check_error: Throw exception on error
+
+        :return: None
+        """
+        cmd = ['sudo', _OVS_APPCTL_BIN,
+               '--timeout',
+               str(self.timeout)] + args
+        return tasks.run_task(
+            cmd, self.logger, 'Running ovs-appctl...', check_error)
+
+
     # datapath management
 
     def add_br(self, br_name=_OVS_BRIDGE_NAME, params=None):
@@ -90,6 +115,32 @@ class OFBase(object):
         self.logger.debug('delete bridge')
         self.run_vsctl(['del-br', br_name])
 
+    # Route and ARP functions
+
+    def add_route(self, network, destination):
+        """Add route to tunneling routing table.
+
+        :param network: Network
+        :param destination: Gateway
+
+        :return: None
+        """
+        self.logger.debug('add ovs/route')
+        self.run_appctl(['ovs/route/add', network, destination])
+
+
+    def set_tunnel_arp(self, ip_addr, mac_addr, br_name=_OVS_BRIDGE_NAME):
+        """Add OVS arp entry for tunneling
+
+        :param ip: IP of bridge
+        :param mac_addr: MAC address of the bridge
+        :param br_name: Name of the bridge
+
+        :return: None
+        """
+        self.logger.debug('tnl/arp/set')
+        self.run_appctl(['tnl/arp/set', br_name, ip_addr, mac_addr])
+
 
 class OFBridge(OFBase):
     """Control a bridge instance using ``ovs-vsctl`` and ``ovs-ofctl``.
@@ -330,10 +381,10 @@ def flow_key(flow):
         field_params.append('%(field)s=%(value)s' %
                             {'field': key, 'value': default})
 
-    field_params = ','.join(field_params)
+    field_params_str = ','.join(field_params)
 
     _flow_key_param = {
-        'fields': field_params,
+        'fields': field_params_str,
     }
 
     # no actions == delete key
@@ -345,3 +396,26 @@ def flow_key(flow):
         flow_str = _flow_del_key.substitute(_flow_key_param)
 
     return flow_str
+
+def flow_match(flow_dump, flow_src):
+    """ Compares two flows
+
+    :param flow_dump: string - a string with flow obtained by ovs-ofctl dump-flows
+    :param flow_src: string - a string with flow obtained by call of flow_key()
+
+    :return: boolean
+    """
+    # perform unifications on both source and destination flows
+    flow_dump = flow_dump.replace('actions=', 'action=')
+    flow_src = flow_src.replace('actions=', 'action=')
+
+    # 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)
+
+    # 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