ovs-dpdk: support late initialization since ovs 2.6.0

OVS 2.6.0 introduces new mechanisms to configure the DPDK netdev
provider. It now relies on the database and allows dynamic runtime
configuration. Network interface binding is more fine grained by
specifying the NIC PCI address and not relying on special port naming
and indexing.

Here we introduce the support of post 2.6.0 OVS-DPDK and change the
relevant tests.

Change-Id: Ic0185097d65df04a2b566e16cb22bcbd088eed3e
This commit is contained in:
Nikolay Nikolaev 2018-06-12 14:21:48 +03:00
parent 7d5126e1c3
commit 862c362296
2 changed files with 60 additions and 16 deletions

View File

@ -40,6 +40,7 @@ from charmhelpers.contrib.network.ovs import (
full_restart,
enable_ipfix,
disable_ipfix,
set_Open_vSwitch_column_value
)
from charmhelpers.core.hookenv import (
config,
@ -69,6 +70,7 @@ from charmhelpers.fetch import (
apt_purge,
apt_update,
filter_installed_packages,
get_upstream_version
)
from pci import PCINetDevices
@ -307,6 +309,8 @@ def resource_map():
)
if not use_dpdk():
drop_config.append(DPDK_INTERFACES)
if ovs_has_late_dpdk_init():
drop_config.append(OVS_DEFAULT)
else:
drop_config.extend([OVS_CONF, DPDK_INTERFACES])
@ -376,6 +380,17 @@ OVS_DEFAULT_BIN = '/usr/lib/openvswitch-switch/ovs-vswitchd'
def enable_ovs_dpdk():
'''Enables the DPDK variant of ovs-vswitchd and restarts it'''
subprocess.check_call(UPDATE_ALTERNATIVES + [OVS_DPDK_BIN])
if ovs_has_late_dpdk_init():
ctxt = neutron_ovs_context.OVSDPDKDeviceContext()
set_Open_vSwitch_column_value(
'other_config:dpdk-init=true')
set_Open_vSwitch_column_value(
'other_config:dpdk-lcore-mask={}'.format(ctxt['cpu_mask']))
set_Open_vSwitch_column_value(
'other_config:dpdk-socket-mem={}'.format(ctxt['socket_memory']))
set_Open_vSwitch_column_value(
'other_config:dpdk-extra=--vhost-owner'
' libvirt-qemu:kvm --vhost-perm 0660')
if not is_unit_paused_set():
service_restart('openvswitch-switch')
@ -411,12 +426,12 @@ def configure_ovs():
else:
# NOTE: when in dpdk mode, add based on pci bus order
# with type 'dpdk'
dpdk_bridgemaps = neutron_ovs_context.resolve_dpdk_ports()
bridgemaps = neutron_ovs_context.resolve_dpdk_ports()
device_index = 0
for br in dpdk_bridgemaps.values():
for pci_address, br in bridgemaps.items():
add_bridge(br, datapath_type)
dpdk_add_bridge_port(br, 'dpdk{}'.format(device_index),
port_type='dpdk')
pci_address)
device_index += 1
target = config('ipfix-target')
@ -560,6 +575,13 @@ def use_dpdk():
return (cmp_release >= 'mitaka' and config('enable-dpdk'))
def ovs_has_late_dpdk_init():
''' OVS 2.6.0 introduces late initialization '''
import apt_pkg
ovs_version = get_upstream_version("openvswitch-switch")
return apt_pkg.version_compare(ovs_version, '2.6.0') >= 0
def enable_sriov():
'''Determine whether SR-IOV is enabled and supported'''
cmp_release = CompareOpenStackReleases(
@ -568,13 +590,19 @@ def enable_sriov():
# TODO: update into charm-helpers to add port_type parameter
def dpdk_add_bridge_port(name, port, promisc=False, port_type=None):
def dpdk_add_bridge_port(name, port, pci_address=None):
''' Add a port to the named openvswitch bridge '''
# log('Adding port {} to bridge {}'.format(port, name))
cmd = ["ovs-vsctl", "--", "--may-exist", "add-port", name, port]
if port_type:
cmd += ['--', 'set', 'Interface', port,
'type={}'.format(port_type)]
if ovs_has_late_dpdk_init():
cmd = ["ovs-vsctl",
"add-port", name, port, "--",
"set", "Interface", port,
"type=dpdk",
"options:dpdk-devargs={}".format(pci_address)]
else:
cmd = ["ovs-vsctl", "--",
"--may-exist", "add-port", name, port,
"--", "set", "Interface", port, "type=dpdk"]
subprocess.check_call(cmd)

View File

@ -55,6 +55,7 @@ TO_PATCH = [
'PCINetDevices',
'enable_ipfix',
'disable_ipfix',
'ovs_has_late_dpdk_init',
]
head_pkg = 'linux-headers-3.15.0-5-generic'
@ -92,6 +93,7 @@ class TestNeutronOVSUtils(CharmTestCase):
self.neutron_plugin_attribute.side_effect = _mock_npa
self.config.side_effect = self.test_config.get
self.use_dpdk.return_value = False
self.ovs_has_late_dpdk_init.return_value = False
def tearDown(self):
# Reset cached cache
@ -470,11 +472,8 @@ class TestNeutronOVSUtils(CharmTestCase):
])
self.add_bridge_port.assert_called_with('br-ex', 'eth0')
@patch.object(neutron_ovs_context, 'resolve_dpdk_ports')
@patch.object(nutils, 'use_dvr')
@patch('charmhelpers.contrib.openstack.context.config')
def test_configure_ovs_dpdk(self, mock_config, _use_dvr,
_resolve_dpdk_ports):
def _run_configure_ovs_dpdk(self, mock_config, _use_dvr,
_resolve_dpdk_ports, _late_init):
_resolve_dpdk_ports.return_value = OrderedDict([
('0000:001c.01', 'br-phynet1'),
('0000:001c.02', 'br-phynet2'),
@ -482,6 +481,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
mock_config.side_effect = self.test_config.get
self.config.side_effect = self.test_config.get
self.test_config.set('enable-dpdk', True)
@ -495,12 +495,28 @@ class TestNeutronOVSUtils(CharmTestCase):
any_order=True
)
self.dpdk_add_bridge_port.assert_has_calls([
call('br-phynet1', 'dpdk0', port_type='dpdk'),
call('br-phynet2', 'dpdk1', port_type='dpdk'),
call('br-phynet3', 'dpdk2', port_type='dpdk')],
call('br-phynet1', 'dpdk0', '0000:001c.01'),
call('br-phynet2', 'dpdk1', '0000:001c.02'),
call('br-phynet3', 'dpdk2', '0000:001c.03')],
any_order=True
)
@patch.object(neutron_ovs_context, 'resolve_dpdk_ports')
@patch.object(nutils, 'use_dvr')
@patch('charmhelpers.contrib.openstack.context.config')
def test_configure_ovs_dpdk(self, mock_config, _use_dvr,
_resolve_dpdk_ports):
return self._run_configure_ovs_dpdk(mock_config, _use_dvr,
_resolve_dpdk_ports, False)
@patch.object(neutron_ovs_context, 'resolve_dpdk_ports')
@patch.object(nutils, 'use_dvr')
@patch('charmhelpers.contrib.openstack.context.config')
def test_configure_ovs_dpdk_late_init(self, mock_config, _use_dvr,
_resolve_dpdk_ports):
return self._run_configure_ovs_dpdk(mock_config, _use_dvr,
_resolve_dpdk_ports, True)
@patch.object(nutils, 'use_dvr')
@patch('charmhelpers.contrib.openstack.context.config')
def test_configure_ovs_enable_ipfix(self, mock_config, mock_use_dvr):