-# Copyright 2015 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.
"""VSPERF VSwitch implementation using DPDK and vhost ports
"""
-from conf import settings
-from vswitches.vswitch import IVSwitch
-from src.ovs import VSwitchd, OFBridge
-from src.dpdk import dpdk
+import logging
+import subprocess
-_VSWITCHD_CONST_ARGS = ['--', '--log-file']
+from src.ovs import OFBridge
+from src.dpdk import dpdk
+from conf import settings
+from vswitches.ovs import IVSwitchOvs
-class OvsDpdkVhost(IVSwitch):
- """VSwitch implementation using DPDK and vhost ports
+class OvsDpdkVhost(IVSwitchOvs):
+ """ Open vSwitch with DPDK support
Generic OVS wrapper functionality in src.ovs is maximally used. This
class wraps DPDK system configuration along with DPDK specific OVS
implementation. For generic information of the nature of the methods,
see the interface.
"""
+
def __init__(self):
- vswitchd_args = ['--dpdk']
- vswitchd_args += settings.getValue('VSWITCHD_DPDK_ARGS')
- vswitchd_args += _VSWITCHD_CONST_ARGS
+ super(OvsDpdkVhost, self).__init__()
+ self._logger = logging.getLogger(__name__)
+
+ vswitchd_args = []
- self._vswitchd = VSwitchd(vswitchd_args=vswitchd_args,
- expected_cmd=
- r'EAL: Master l*core \d+ is ready')
- self._bridges = {}
+ # legacy DPDK configuration through --dpdk option of vswitchd
+ if self.old_dpdk_config():
+ vswitchd_args = ['--dpdk'] + settings.getValue('VSWITCHD_DPDK_ARGS')
+ if self._vswitchd_args:
+ self._vswitchd_args = vswitchd_args + ['--'] + self._vswitchd_args
+ else:
+ self._vswitchd_args = vswitchd_args
+
+ def configure(self):
+ """ Configure vswitchd DPDK options through ovsdb if needed
+ """
+ dpdk_config = settings.getValue('VSWITCHD_DPDK_CONFIG')
+ if dpdk_config and not self.old_dpdk_config():
+ # enforce calls to ovs-vsctl with --no-wait
+ tmp_br = OFBridge(timeout=-1)
+ for option in dpdk_config:
+ tmp_br.set_db_attribute('Open_vSwitch', '.',
+ 'other_config:' + option, dpdk_config[option])
def start(self):
"""See IVswitch for general description
Activates DPDK kernel modules, ovsdb and vswitchd.
"""
dpdk.init()
- self._vswitchd.start()
+ super(OvsDpdkVhost, self).start()
+ # old style OVS <= 2.5.0 multi-queue enable
+ if settings.getValue('OVS_OLD_STYLE_MQ') and \
+ int(settings.getValue('VSWITCH_DPDK_MULTI_QUEUES')):
+ tmp_br = OFBridge(timeout=-1)
+ tmp_br.set_db_attribute(
+ 'Open_vSwitch', '.', 'other_config:' +
+ 'n-dpdk-rxqs', settings.getValue('VSWITCH_DPDK_MULTI_QUEUES'))
def stop(self):
"""See IVswitch for general description
Kills ovsdb and vswitchd and removes DPDK kernel modules.
"""
- self._vswitchd.kill()
+
+ super(OvsDpdkVhost, self).stop()
dpdk.cleanup()
- def add_switch(self, switch_name):
+ def add_switch(self, switch_name, params=None):
"""See IVswitch for general description
"""
- bridge = OFBridge(switch_name)
- bridge.create()
- bridge.set_db_attribute('Open_vSwitch', '.',
- 'other_config:max-idle',
- settings.getValue('VSWITCH_FLOW_TIMEOUT'))
+ switch_params = ['--', 'set', 'bridge', switch_name, 'datapath_type=netdev']
+ if params:
+ switch_params = switch_params + params
+ super(OvsDpdkVhost, self).add_switch(switch_name, switch_params)
if settings.getValue('VSWITCH_AFFINITIZATION_ON') == 1:
# Sets the PMD core mask to VSWITCH_PMD_CPU_MASK
# for CPU core affinitization
- bridge.set_db_attribute('Open_vSwitch', '.',
- 'other_config:pmd-cpu-mask',
- settings.getValue('VSWITCH_PMD_CPU_MASK'))
-
- bridge.set_db_attribute('Bridge', bridge.br_name,
- 'datapath_type', 'netdev')
- self._bridges[switch_name] = bridge
-
- def del_switch(self, switch_name):
- """See IVswitch for general description
- """
- bridge = self._bridges[switch_name]
- self._bridges.pop(switch_name)
- bridge.destroy()
+ self._bridges[switch_name].set_db_attribute('Open_vSwitch', '.',
+ 'other_config:pmd-cpu-mask',
+ settings.getValue('VSWITCH_PMD_CPU_MASK'))
def add_phy_port(self, switch_name):
"""See IVswitch for general description
The new port is named dpdk<n> where n is an integer starting from 0.
"""
bridge = self._bridges[switch_name]
- dpdk_count = self._get_port_count(bridge, 'type=dpdk')
+ dpdk_count = self._get_port_count('type=dpdk')
port_name = 'dpdk' + str(dpdk_count)
- params = ['--', 'set', 'Interface', port_name, 'type=dpdk']
+ # PCI info. Please note there must be no blank space, eg must be
+ # like 'options:dpdk-devargs=0000:06:00.0'
+ _nics = settings.getValue('NICS')
+ nic_pci = 'options:dpdk-devargs=' + _nics[dpdk_count]['pci']
+ params = ['--', 'set', 'Interface', port_name, 'type=dpdk', nic_pci]
+ # multi-queue enable
+
+ if int(settings.getValue('VSWITCH_DPDK_MULTI_QUEUES')) and \
+ not settings.getValue('OVS_OLD_STYLE_MQ'):
+ params += ['options:n_rxq={}'.format(
+ settings.getValue('VSWITCH_DPDK_MULTI_QUEUES'))]
of_port = bridge.add_port(port_name, params)
-
return (port_name, of_port)
def add_vport(self, switch_name):
from 0
"""
bridge = self._bridges[switch_name]
- # Changed dpdkvhost to dpdkvhostuser to be able to run in Qemu 2.2
- vhost_count = self._get_port_count(bridge, 'type=dpdkvhostuser')
+ vhost_count = self._get_port_count('type=dpdkvhostuser')
port_name = 'dpdkvhostuser' + str(vhost_count)
params = ['--', 'set', 'Interface', port_name, 'type=dpdkvhostuser']
of_port = bridge.add_port(port_name, params)
return (port_name, of_port)
- def get_ports(self, switch_name):
- """See IVswitch for general description
- """
- bridge = self._bridges[switch_name]
- ports = list(bridge.get_ports().items())
- return [(name, of_port) for (name, (of_port, _)) in ports]
-
- def del_port(self, switch_name, port_name):
- """See IVswitch for general description
- """
- bridge = self._bridges[switch_name]
- bridge.del_port(port_name)
-
- def add_flow(self, switch_name, flow):
- """See IVswitch for general description
- """
- bridge = self._bridges[switch_name]
- bridge.add_flow(flow)
-
- def del_flow(self, switch_name, flow=None):
- """See IVswitch for general description
- """
- flow = flow or {}
- bridge = self._bridges[switch_name]
- bridge.del_flow(flow)
-
@staticmethod
- def _get_port_count(bridge, param):
- """Returns the number of ports having a certain parameter
+ def old_dpdk_config():
+ """Checks if ovs-vswitchd uses legacy dpdk configuration via --dpdk option
- :param bridge: The src.ovs.ofctl.OFBridge on which to operate
- :param param: The parameter to search for
- :returns: Count of matches
+ :returns: True if legacy --dpdk option is supported, otherwise it returns False
"""
- port_params = [c for (_, (_, c)) in list(bridge.get_ports().items())]
- param_hits = [i for i in port_params if param in i]
- return len(param_hits)
+
+ ovs_vswitchd_bin = settings.getValue('TOOLS')['ovs-vswitchd']
+ try:
+ subprocess.check_output(ovs_vswitchd_bin + r' --help | grep "\-\-dpdk"', shell=True)
+ return True
+ except subprocess.CalledProcessError:
+ return False