-# 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.
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
: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)
: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)
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
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):
: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)
"""
# 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)
# 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:
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