X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=vswitches%2Fovs_dpdk_vhost.py;h=8da043c68506a7f7fec3427645f047fbcaab398e;hb=63b56ed1d74657129006f066a3f118c4c369d23c;hp=7b5034c5a10059961ac3f7ce697116549ca76851;hpb=0eff3e49f89c98f7332cae91cdac296ac5e0ac4b;p=vswitchperf.git diff --git a/vswitches/ovs_dpdk_vhost.py b/vswitches/ovs_dpdk_vhost.py index 7b5034c5..8da043c6 100644 --- a/vswitches/ovs_dpdk_vhost.py +++ b/vswitches/ovs_dpdk_vhost.py @@ -1,4 +1,4 @@ -# Copyright 2015 Intel Corporation. +# Copyright 2015-2018 Intel Corporation., Tieto # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,15 +15,15 @@ """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 subprocess -VSWITCHD_CONST_ARGS = ['--', '--log-file'] +from src.ovs import OFBridge +from src.dpdk import dpdk +from conf import settings as S +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 @@ -33,14 +33,38 @@ class OvsDpdkVhost(IVSwitch): 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 - self._vswitchd = VSwitchd(vswitchd_args=vswitchd_args, - expected_cmd=r'EAL: Master l*core \d+ is ready') - self._bridges = {} + def __init__(self): + super().__init__() + vswitchd_args = [] + + # legacy DPDK configuration through --dpdk option of vswitchd + if self.old_dpdk_config(): + # override socket-mem settings + tmp_dpdk_args = S.getValue('VSWITCHD_DPDK_ARGS') + for tmp_arg in tmp_dpdk_args: + if tmp_arg.startswith('--socket-mem'): + tmp_dpdk_args.remove(tmp_arg) + tmp_dpdk_args += ['--socket-mem ' + ','.join(S.getValue('DPDK_SOCKET_MEM'))] + vswitchd_args = ['--dpdk'] + tmp_dpdk_args + # add dpdk args to generic ovs-vswitchd settings + 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 = S.getValue('VSWITCHD_DPDK_CONFIG') + if dpdk_config and not self.old_dpdk_config(): + # override socket-mem settings + dpdk_config['dpdk-socket-mem'] = ','.join(S.getValue('DPDK_SOCKET_MEM')) + # 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 @@ -48,33 +72,38 @@ class OvsDpdkVhost(IVSwitch): 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 S.getValue('OVS_OLD_STYLE_MQ') and \ + int(S.getValue('VSWITCH_DPDK_MULTI_QUEUES')): + tmp_br = OFBridge(timeout=-1) + tmp_br.set_db_attribute( + 'Open_vSwitch', '.', 'other_config:' + + 'n-dpdk-rxqs', S.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', '60000') - 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() + 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 S.getValue('VSWITCH_AFFINITIZATION_ON') == 1: + # Sets the PMD core mask to VSWITCH_PMD_CPU_MASK + # for CPU core affinitization + self._switches[switch_name].set_db_attribute('Open_vSwitch', '.', + 'other_config:pmd-cpu-mask', + S.getValue('VSWITCH_PMD_CPU_MASK')) def add_phy_port(self, switch_name): """See IVswitch for general description @@ -82,12 +111,27 @@ class OvsDpdkVhost(IVSwitch): Creates a port of type dpdk. The new port is named dpdk where n is an integer starting from 0. """ - bridge = self._bridges[switch_name] - dpdk_count = self._get_port_count(bridge, 'type=dpdk') + _nics = S.getValue('NICS') + bridge = self._switches[switch_name] + dpdk_count = self._get_port_count('type=dpdk') + if dpdk_count == len(_nics): + raise RuntimeError("Can't add phy port! There are only {} ports defined " + "by WHITELIST_NICS parameter!".format(len(_nics))) 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' + nic_pci = 'options:dpdk-devargs=' + _nics[dpdk_count]['pci'] + params = ['--', 'set', 'Interface', port_name, 'type=dpdk', nic_pci] + # multi-queue enable + + if int(S.getValue('VSWITCH_DPDK_MULTI_QUEUES')) and \ + not S.getValue('OVS_OLD_STYLE_MQ'): + params += ['options:n_rxq={}'.format( + S.getValue('VSWITCH_DPDK_MULTI_QUEUES'))] + if S.getValue('VSWITCH_JUMBO_FRAMES_ENABLED'): + params += ['mtu_request={}'.format( + S.getValue('VSWITCH_JUMBO_FRAMES_SIZE'))] of_port = bridge.add_port(port_name, params) - return (port_name, of_port) def add_vport(self, switch_name): @@ -97,48 +141,36 @@ class OvsDpdkVhost(IVSwitch): The new port is named dpdkvhost where n is an integer starting from 0 """ - bridge = self._bridges[switch_name] - vhost_count = self._get_port_count(bridge, 'type=dpdkvhost') - port_name = 'dpdkvhost' + str(vhost_count) - params = ['--', 'set', 'Interface', port_name, 'type=dpdkvhost'] + bridge = self._switches[switch_name] + + if S.getValue('VSWITCH_VHOSTUSER_SERVER_MODE'): + nic_type = 'dpdkvhostuser' + else: + nic_type = 'dpdkvhostuserclient' + + vhost_count = self._get_port_count('type={}'.format(nic_type)) + port_name = nic_type + str(vhost_count) + params = ['--', 'set', 'Interface', port_name, 'type={}'.format(nic_type)] + if not S.getValue('VSWITCH_VHOSTUSER_SERVER_MODE'): + params += ['--', 'set', 'Interface', port_name, 'options:vhost-server-path=' + '{}{}'.format(S.getValue('TOOLS')['ovs_var_tmp'], port_name)] + if S.getValue('VSWITCH_JUMBO_FRAMES_ENABLED'): + params += ['mtu_request={}'.format( + S.getValue('VSWITCH_JUMBO_FRAMES_SIZE'))] 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 = S.getValue('TOOLS')['ovs-vswitchd'] + try: + subprocess.check_output(ovs_vswitchd_bin + r' --help | grep "\-\-dpdk"', shell=True) + return True + except subprocess.CalledProcessError: + return False