diff options
author | Yiting.Li <liyiting@huawei.com> | 2015-12-22 17:11:12 -0800 |
---|---|---|
committer | Yiting.Li <liyiting@huawei.com> | 2015-12-22 17:11:12 -0800 |
commit | 8f1101df131a4d3e03b377738507d88b745831c0 (patch) | |
tree | 73f140474fcec2a77c85a453f6946957ca0742d1 /vstf/vstf/agent/env/vswitch_plugins | |
parent | 1a24ebbda3f95600c0e7d5ed8661317a8ff7e265 (diff) |
Upload the contribution of vstf as bottleneck network framework.
End to End Performance test
JIRA:BOTTLENECK-29
Change-Id: Ib2c553c8b60d6cda9e7a7b52b737c9139f706ebd
Signed-off-by: Yiting.Li <liyiting@huawei.com>
Diffstat (limited to 'vstf/vstf/agent/env/vswitch_plugins')
-rwxr-xr-x | vstf/vstf/agent/env/vswitch_plugins/__init__.py | 0 | ||||
-rwxr-xr-x | vstf/vstf/agent/env/vswitch_plugins/bridge_plugin.py | 67 | ||||
-rwxr-xr-x | vstf/vstf/agent/env/vswitch_plugins/manager.py | 31 | ||||
-rwxr-xr-x | vstf/vstf/agent/env/vswitch_plugins/model.py | 63 | ||||
-rwxr-xr-x | vstf/vstf/agent/env/vswitch_plugins/ovs_plugin.py | 183 |
5 files changed, 344 insertions, 0 deletions
diff --git a/vstf/vstf/agent/env/vswitch_plugins/__init__.py b/vstf/vstf/agent/env/vswitch_plugins/__init__.py new file mode 100755 index 00000000..e69de29b --- /dev/null +++ b/vstf/vstf/agent/env/vswitch_plugins/__init__.py diff --git a/vstf/vstf/agent/env/vswitch_plugins/bridge_plugin.py b/vstf/vstf/agent/env/vswitch_plugins/bridge_plugin.py new file mode 100755 index 00000000..252f190d --- /dev/null +++ b/vstf/vstf/agent/env/vswitch_plugins/bridge_plugin.py @@ -0,0 +1,67 @@ +""" +Created on 2015-10-12 + +@author: y00228926 +""" +from vstf.agent.env.vswitch_plugins import model +from vstf.common.utils import check_call, get_eth_by_bdf, check_output + + +class BridgePlugin(model.VswitchPlugin): + def __init__(self): + pass + + def clean(self): + """clean brs created before. + + """ + out = check_output(r"brctl show | grep -v '^\s' | awk '{print $1}'|sed '1,1d'", shell=True) + print out + for br in out.split(): + if br != 'br0': + self._del_br(br) + + return True + + def init(self): + pass + + def _del_br(self, name): + check_call('ip link set dev %s down' % name, shell=True) + check_call('brctl delbr %s' % name, shell=True) + + def create_br(self, br_cfg): + """Create a bridge(virtual switch). Return True for success, return False for failure. + + :param dict br_cfg: configuration for bridge creation like + { + "name": "br1", + "uplinks": [ + { + "bdf": "04:00.0", + }, + { + "bdf": "04:00.1", + } + ] + } + + """ + name, uplinks = br_cfg['name'], br_cfg['uplinks'] + check_call("brctl addbr %s" % name, shell=True) + for uplink in uplinks: + device = get_eth_by_bdf(uplink['bdf']) + check_call("ip link set dev %s up" % device, shell=True) + check_call("brctl addif %s %s" % (name, device), shell=True) + check_call("ip link set dev %s up" % name, shell=True) + return True + + def set_tap_vid(self, tap_cfg): + """linux bridge doesn't support vlan id setting. + """ + return True + + def set_fastlink(self, br_cfg): + """linux bridge doesn't support openflow protocol. + """ + return True diff --git a/vstf/vstf/agent/env/vswitch_plugins/manager.py b/vstf/vstf/agent/env/vswitch_plugins/manager.py new file mode 100755 index 00000000..00115dfd --- /dev/null +++ b/vstf/vstf/agent/env/vswitch_plugins/manager.py @@ -0,0 +1,31 @@ +""" +Created on 2015-9-15 + +@author: y00228926 +""" +import stevedore + + +class VswitchPluginManager(object): + def __init__(self): + self.plugin = None + self.mgr = stevedore.extension.ExtensionManager(namespace="vswitch.plugins", invoke_on_load=True) + + def clean(self): + if self.plugin: + self.plugin.clean() + self.plugin = None + for plugin in self.mgr.names(): + self.mgr[plugin].obj.clean() + return True + + def get_vs_plugin(self, plugin): + if plugin in self.mgr.names(): + ext = self.mgr[plugin] + self.plugin = ext.obj + return self.plugin + else: + raise Exception("unsupported vswitch plugin: %s" % plugin) + + def get_supported_plugins(self): + return self.mgr.names() diff --git a/vstf/vstf/agent/env/vswitch_plugins/model.py b/vstf/vstf/agent/env/vswitch_plugins/model.py new file mode 100755 index 00000000..a4d8b3b5 --- /dev/null +++ b/vstf/vstf/agent/env/vswitch_plugins/model.py @@ -0,0 +1,63 @@ +""" +Created on 2015-9-15 + +@author: y00228926 +""" +from abc import ABCMeta +from abc import abstractmethod + + +class VswitchPlugin: + __metaclass__ = ABCMeta + + @abstractmethod + def clean(self): + """implement this clean function to clean environment before and after calling any other functions. + + """ + pass + + @abstractmethod + def init(self): + """implements this init function to setup necessary Preconditions. + + """ + pass + + @abstractmethod + def create_br(self, br_cfg): + """Create a bridge(virtual switch). Return True for success, return False for failure. + + :param dict br_cfg: configuration for bridge creation like + { + "type": "ovs", + "name": "ovs1", + "uplinks": [ + { + "bdf": "04:00.0", + "vlan_mode": "access", + "vlan_id": "1" + } + ], + "vtep": {}, + } + + """ + pass + + @abstractmethod + def set_tap_vid(self, tap_cfg): + """set vlan id or vxlan id for tap device(virtual nic for vm). + + :param dict tap_cfg: dictionary config for tap device like + { + "tap_name": "tap_in", + "vlan_mode": "access", + "vlan_id": "1" + } + + """ + pass + + def set_fastlink(self, br_cfg): + return True
\ No newline at end of file diff --git a/vstf/vstf/agent/env/vswitch_plugins/ovs_plugin.py b/vstf/vstf/agent/env/vswitch_plugins/ovs_plugin.py new file mode 100755 index 00000000..46045950 --- /dev/null +++ b/vstf/vstf/agent/env/vswitch_plugins/ovs_plugin.py @@ -0,0 +1,183 @@ +""" +Created on 2015-10-10 + +@author: y00228926 +""" +import os +import shutil +import logging +import time +import re + +from vstf.agent.env.vswitch_plugins import model +from vstf.common.utils import check_and_kill, check_and_rmmod, check_call, check_output, \ + get_eth_by_bdf, my_mkdir, call + +LOG = logging.getLogger(__name__) + + +class OvsPlugin(model.VswitchPlugin): + + def __init__(self): + self.daemons = ['ovs-vswitchd', 'ovsdb-server'] + self.mods = ['openvswitch'] + self.dirs = {'db': "/usr/local/etc/openvswitch"} + self.cmds = [] + self.cmds.append("mkdir -p /usr/local/etc/openvswitch") + self.cmds.append("ovsdb-tool create /usr/local/etc/openvswitch/conf.db") + self.cmds.append("ovsdb-server --remote=punix:/usr/local/var/run/openvswitch/db.sock \ + --remote=db:Open_vSwitch,Open_vSwitch,manager_options \ + --private-key=db:Open_vSwitch,SSL,private_key \ + --certificate=db:Open_vSwitch,SSL,certificate \ + --bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert \ + --pidfile --detach") + self.cmds.append("ovs-vsctl --no-wait init") + self.cmds.append("ovs-vswitchd --pidfile --detach") + self.initialized = False + + def init(self): + if not self.initialized: + self._start_servers() + self.initialized = True + + def clean(self): + """clean for ovs. Rmmod openvswitch.ko, kill openvswitch daemon process. + + """ + for process in self.daemons: + check_and_kill(process) + for mod in self.mods: + check_and_rmmod(mod) + for _, directory in self.dirs.items(): + if os.path.isdir(directory): + LOG.info('rm -rf %s', directory) + shutil.rmtree(directory, ignore_errors=True) + self.initialized = False + return True + + def create_br(self, br_cfg): + """Create a bridge(virtual switch). Return True for success, return False for failure. + + :param dict br_cfg: configuration for bridge creation like + { + "type": "ovs", + "name": "ovs1", + "uplinks": [ + { + "bdf": "04:00.0", + "vlan_mode": "access", + "vlan_id": "1" + } + ], + "vtep": {}, + } + + """ + self.init() + name, uplinks = br_cfg['name'], br_cfg['uplinks'] + + check_call("ovs-vsctl add-br %s" % (name), shell=True) + if br_cfg['vtep']: # vxlan supports + local_ip, remote_ip = br_cfg['vtep']['local_ip'], br_cfg['vtep']['remote_ip'] + assert len(uplinks) == 1 + uplink = uplinks[0] + device = get_eth_by_bdf(uplink['bdf']) + time.sleep(0.5) + vtep = 'vx1' + check_call("ifconfig %s %s up" % (device, local_ip), shell=True) + check_call("ovs-vsctl add-port %s %s" % (name, vtep), shell=True) + check_call("ovs-vsctl set interface %s type=vxlan options:remote_ip=%s" % (vtep, remote_ip), shell=True) + for uplink in uplinks: + device = get_eth_by_bdf(uplink['bdf']) + vlan_mode = uplink['vlan_mode'] + vlan_id = uplink['vlan_id'] + check_call("ip link set dev %s up" % device, shell=True) + call("ethtool -A %s rx off tx off " % device, shell=True) + check_call("ovs-vsctl add-port %s %s" % (name, device), shell=True) + if vlan_mode == 'trunk': + check_call("ovs-vsctl set port %s trunks=%s" % (device, vlan_id), shell=True) + elif vlan_mode == 'access': + check_call("ovs-vsctl set port %s tag=%s" % (device, vlan_id), shell=True) + else: + raise Exception("unreconized vlan_mode:%s" % vlan_mode) + return True + + def set_tap_vid(self, tap_cfg): + """set vlan id or vxlan id for tap device(virtual nic for vm). + return True for success, return False for failure. + + :param dict tap_cfg: dictionary config for tap device like + { + "tap_name": "tap_in", + "vlan_mode": "access", + "vlan_id": "1" + } + + """ + port, vlan_mode, vlan = tap_cfg['tap_name'], tap_cfg['vlan_mode'], tap_cfg['vlan_id'] + assert vlan_mode in ('access', 'vxlan') + if int(vlan) > '4095': + # vxlan setting + self.__set_tap_vid(port, "vxlan", vlan) + else: + # vlan setting + self.__set_tap_vid(port, vlan_mode, vlan) + return True + + def set_fastlink(self, br_cfg): + """connect two ports directly, so that packets comes from any one port be forwarded to the other. + return True for success, return False for failure. + + :param dict br_cfg: dictionary configuration for linking ports. + { + "name": "ovs1", + "fastlink": [ + { + "inport": "04:00.0", + "outport": "tap_in" + } + ] + } + """ + br_name = br_cfg['name'] + for fast_cfg in br_cfg['fastlink']: + p1, p2 = fast_cfg['inport'], fast_cfg['outport'] + self.__fastlink(br_name, p1, p2) + return True + + def _start_servers(self): + for _, directory in self.dirs.items(): + my_mkdir(directory) + for mod in self.mods: + check_call("modprobe %s" % mod, shell=True) + for cmd in self.cmds: + check_call(cmd, shell=True) + return True + + def __set_tap_vid(self, port, vlan_mode, vlan_id): + if vlan_mode == 'vxlan': + raise Exception("don't support vxlan setting right now.") + elif vlan_mode == 'trunk': + check_call("ovs-vsctl set port %s trunks=%s" % (port, vlan_id), shell=True) + else: + check_call("ovs-vsctl set port %s tag=%s" % (port, vlan_id), shell=True) + + def __fastlink(self, br, p1, p2): + LOG.info("_fastlink(%s,%s,%s)", br, p1, p2) + p1 = p1.replace(' ', '') + p2 = p2.replace(' ', '') + bdfs = check_output("lspci |grep Eth | awk '{print $1}'", shell=True).splitlines() + if p1 in bdfs: + p1 = get_eth_by_bdf(p1) + if p2 in bdfs: + p2 = get_eth_by_bdf(p2) + ovs_port = {} + buf = check_output("ovs-ofctl show %s" % br, shell=True) + port_info = re.compile(r"[0-9]+\(.*\)", re.IGNORECASE | re.MULTILINE) + for s in port_info.findall(buf): + port_num, interface = s.replace('(', ' ').replace(')', ' ').split() + ovs_port[interface] = port_num + pn1, pn2 = ovs_port[p1], ovs_port[p2] + check_call("ovs-ofctl add-flow %s in_port=%s,priority=100,action=output:%s" % (br, pn1, pn2), shell=True) + check_call("ovs-ofctl add-flow %s in_port=%s,priority=100,action=output:%s" % (br, pn2, pn1), shell=True) + return True |