dpdk: misc fixes for EAL initialization

For OpenStack Queens and later instances are setup with vhostuser
ports in server mode, with the OVS side of the port connecting
as a client to the vhostuser socket on disk; as a result we no
longer need to pass permissions information via dpdk-extra (the
two passed options are not valid in later OVS versions).

In addition, we should also whitelist the devices we're going to
use; this ensures that EAL initialization does not take an extended
period of time reducing the amount of time taken to restart OVS.

Change-Id: I224e778de0ed6e279b2de7f4f46781df33121165
Closes-Bug: 1833734
Closes-Bug: 1793729
(cherry picked from commit 3c66c48bbd)
This commit is contained in:
James Page 2019-06-24 10:11:04 +01:00
parent adf5e756a2
commit bd354841d5
4 changed files with 136 additions and 18 deletions

View File

@ -420,14 +420,42 @@ class OVSDPDKDeviceContext(OSContextGenerator):
else:
return str(sm_size)
def device_whitelist(self):
'''Formatted list of devices to whitelist for dpdk'''
_flag = '-w {device}'
def devices(self):
'''List of PCI devices for use by DPDK'''
pci_devices = resolve_dpdk_bridges()
pci_devices.update(resolve_dpdk_bonds())
return pci_devices
def _formatted_whitelist(self, flag):
'''Flag formatted list of devices to whitelist
:param flag: flag format to use
:type flag: str
:rtype: str
'''
whitelist = []
for device in resolve_dpdk_bridges():
whitelist.append(_flag.format(device=device))
for device in self.devices():
whitelist.append(flag.format(device=device))
return ' '.join(whitelist)
def device_whitelist(self):
'''
Formatted list of devices to whitelist for dpdk
using the old style '-w' flag
:rtype: str
'''
return self._formatted_whitelist('-w {device}')
def pci_whitelist(self):
'''
Formatted list of devices to whitelist for dpdk
using the new style '--pci-whitelist' flag
:rtype: str
'''
return self._formatted_whitelist('--pci-whitelist {device}')
def __call__(self):
ctxt = {}
whitelist = self.device_whitelist()

View File

@ -473,12 +473,20 @@ def enable_ovs_dpdk():
if ovs_has_late_dpdk_init():
dpdk_context = neutron_ovs_context.OVSDPDKDeviceContext()
other_config = OrderedDict([
('pmd-cpu-mask', dpdk_context.cpu_mask()),
('dpdk-lcore-mask', dpdk_context.cpu_mask()),
('dpdk-socket-mem', dpdk_context.socket_memory()),
('dpdk-extra',
'--vhost-owner libvirt-qemu:kvm --vhost-perm 0660'),
('dpdk-init', 'true'),
])
if not ovs_vhostuser_client():
other_config['dpdk-extra'] = (
'--vhost-owner libvirt-qemu:kvm --vhost-perm 0660 ' +
dpdk_context.pci_whitelist()
)
else:
other_config['dpdk-extra'] = (
dpdk_context.pci_whitelist()
)
other_config['dpdk-init'] = 'true'
for column, value in other_config.items():
values_changed.append(
set_Open_vSwitch_column_value(
@ -715,6 +723,17 @@ def ovs_has_late_dpdk_init():
return apt_pkg.version_compare(ovs_version, '2.6.0') >= 0
def ovs_vhostuser_client():
'''
Determine whether OVS will act as a client on the vhostuser socket
@returns boolean indicating whether OVS will act as a client
'''
import apt_pkg
ovs_version = get_upstream_version("openvswitch-switch")
return apt_pkg.version_compare(ovs_version, '2.9.0') >= 0
def enable_sriov():
'''Determine whether SR-IOV is enabled and supported'''
cmp_release = CompareOpenStackReleases(

View File

@ -623,10 +623,10 @@ class TestOVSDPDKDeviceContext(CharmTestCase):
def test_device_whitelist(self):
'''Test device whitelist generation'''
self.resolve_dpdk_bridges.return_value = [
'0000:00:1c.0',
'0000:00:1d.0'
]
self.resolve_dpdk_bridges.return_value = {
'0000:00:1c.0': 'br-data',
'0000:00:1d.0': 'br-data',
}
self.assertEqual(self.test_context.device_whitelist(),
'-w 0000:00:1c.0 -w 0000:00:1d.0')
@ -657,15 +657,16 @@ class TestOVSDPDKDeviceContext(CharmTestCase):
def test_context_no_devices(self):
'''Ensure that DPDK is disable when no devices detected'''
self.resolve_dpdk_bridges.return_value = []
self.resolve_dpdk_bridges.return_value = {}
self.assertEqual(self.test_context(), {})
def test_context_devices(self):
'''Ensure DPDK is enabled when devices are detected'''
self.resolve_dpdk_bridges.return_value = [
'0000:00:1c.0',
'0000:00:1d.0'
]
self.resolve_dpdk_bridges.return_value = {
'0000:00:1c.0': 'br-data',
'0000:00:1d.0': 'br-data',
}
self.resolve_dpdk_bonds.return_value = {}
self.numa_node_cores.return_value = NUMA_CORES_SINGLE
self.glob.glob.return_value = ['a']
self.assertEqual(self.test_context(), {

View File

@ -61,6 +61,7 @@ TO_PATCH = [
'enable_ipfix',
'disable_ipfix',
'ovs_has_late_dpdk_init',
'ovs_vhostuser_client',
'parse_data_port_mappings',
'user_exists',
'group_exists',
@ -103,6 +104,7 @@ class TestNeutronOVSUtils(CharmTestCase):
self.config.side_effect = self.test_config.get
self.use_dpdk.return_value = False
self.ovs_has_late_dpdk_init.return_value = False
self.ovs_vhostuser_client.return_value = False
def tearDown(self):
# Reset cached cache
@ -596,7 +598,8 @@ class TestNeutronOVSUtils(CharmTestCase):
def _run_configure_ovs_dpdk(self, mock_config, _use_dvr,
_resolve_dpdk_bridges, _resolve_dpdk_bonds,
_late_init, _test_bonds):
_late_init, _test_bonds,
_ovs_vhostuser_client=False):
def _resolve_port_name(pci_address, device_index, late_init):
if late_init:
return 'dpdk-{}'.format(
@ -626,6 +629,7 @@ class TestNeutronOVSUtils(CharmTestCase):
_use_dvr.return_value = True
self.use_dpdk.return_value = True
self.ovs_has_late_dpdk_init.return_value = _late_init
self.ovs_vhostuser_client.return_value = _ovs_vhostuser_client
mock_config.side_effect = self.test_config.get
self.config.side_effect = self.test_config.get
self.test_config.set('enable-dpdk', True)
@ -925,6 +929,72 @@ class TestNeutronOVSUtils(CharmTestCase):
['systemd-tmpfiles', '--create']
)
@patch.object(nutils, 'is_unit_paused_set')
@patch.object(nutils.subprocess, 'check_call')
@patch.object(neutron_ovs_context, 'OVSDPDKDeviceContext')
@patch.object(nutils, 'set_Open_vSwitch_column_value')
def test_enable_ovs_dpdk(self,
_set_Open_vSwitch_column_value,
_OVSDPDKDeviceContext,
_check_call,
_is_unit_paused_set):
mock_context = MagicMock()
mock_context.cpu_mask.return_value = '0x03'
mock_context.socket_memory.return_value = '4096,4096'
mock_context.pci_whitelist.return_value = \
'--pci-whitelist 00:0300:01'
_OVSDPDKDeviceContext.return_value = mock_context
_set_Open_vSwitch_column_value.return_value = True
self.ovs_has_late_dpdk_init.return_value = True
self.ovs_vhostuser_client.return_value = False
_is_unit_paused_set.return_value = False
nutils.enable_ovs_dpdk()
_set_Open_vSwitch_column_value.assert_has_calls([
call('other_config:dpdk-lcore-mask', '0x03'),
call('other_config:dpdk-socket-mem', '4096,4096'),
call('other_config:dpdk-init', 'true'),
call('other_config:dpdk-extra',
'--vhost-owner libvirt-qemu:kvm --vhost-perm 0660 '
'--pci-whitelist 00:0300:01')
])
_check_call.assert_called_once_with(
nutils.UPDATE_ALTERNATIVES + [nutils.OVS_DPDK_BIN]
)
self.service_restart.assert_called_with('openvswitch-switch')
@patch.object(nutils, 'is_unit_paused_set')
@patch.object(nutils.subprocess, 'check_call')
@patch.object(neutron_ovs_context, 'OVSDPDKDeviceContext')
@patch.object(nutils, 'set_Open_vSwitch_column_value')
def test_enable_ovs_dpdk_vhostuser_client(
self,
_set_Open_vSwitch_column_value,
_OVSDPDKDeviceContext,
_check_call,
_is_unit_paused_set):
mock_context = MagicMock()
mock_context.cpu_mask.return_value = '0x03'
mock_context.socket_memory.return_value = '4096,4096'
mock_context.pci_whitelist.return_value = \
'--pci-whitelist 00:0300:01'
_OVSDPDKDeviceContext.return_value = mock_context
_set_Open_vSwitch_column_value.return_value = True
self.ovs_has_late_dpdk_init.return_value = True
self.ovs_vhostuser_client.return_value = True
_is_unit_paused_set.return_value = False
nutils.enable_ovs_dpdk()
_set_Open_vSwitch_column_value.assert_has_calls([
call('other_config:dpdk-lcore-mask', '0x03'),
call('other_config:dpdk-socket-mem', '4096,4096'),
call('other_config:dpdk-init', 'true'),
call('other_config:dpdk-extra',
'--pci-whitelist 00:0300:01')
])
_check_call.assert_called_once_with(
nutils.UPDATE_ALTERNATIVES + [nutils.OVS_DPDK_BIN]
)
self.service_restart.assert_called_with('openvswitch-switch')
class TestDPDKBridgeBondMap(CharmTestCase):