OvS 2.7 support - dpdk-devargs needs to provided for DPDK devices
The pci address of the DPDK NIC needs to be specified as dpdk-devargs
when adding the DPDK port. This is required for using DPDK with
OvS 2.7
Change-Id: I4975130961199ee04dd002ec987081299e3ddd4a
Closes-Bug: #1702457
Signed-off-by: Karthik S <ksundara@redhat.com>
(cherry picked from commit 312a77a1ac
)
This commit is contained in:
parent
8ecbb1a755
commit
694f06c69b
|
@ -294,6 +294,14 @@ class IfcfgNetConfig(os_net_config.NetConfig):
|
||||||
data += "DEVICETYPE=ovs\n"
|
data += "DEVICETYPE=ovs\n"
|
||||||
data += "TYPE=OVSDPDKPort\n"
|
data += "TYPE=OVSDPDKPort\n"
|
||||||
data += "OVS_BRIDGE=%s\n" % base_opt.bridge_name
|
data += "OVS_BRIDGE=%s\n" % base_opt.bridge_name
|
||||||
|
# Validation of DPDK port having only one interface is done prior
|
||||||
|
# to this. So accesing the interface name statically.
|
||||||
|
# Also pci_address would be valid here, since
|
||||||
|
# bind_dpdk_interfaces() is invoked before this.
|
||||||
|
pci_address = utils.get_stored_pci_address(
|
||||||
|
base_opt.members[0].name, self.noop)
|
||||||
|
ovs_extra.append("set Interface $DEVICE options:dpdk-devargs="
|
||||||
|
"%s" % pci_address)
|
||||||
elif isinstance(base_opt, objects.OvsDpdkBond):
|
elif isinstance(base_opt, objects.OvsDpdkBond):
|
||||||
ovs_extra.extend(base_opt.ovs_extra)
|
ovs_extra.extend(base_opt.ovs_extra)
|
||||||
# Referring to bug:1643026, the below commenting of the interfaces,
|
# Referring to bug:1643026, the below commenting of the interfaces,
|
||||||
|
@ -307,6 +315,16 @@ class IfcfgNetConfig(os_net_config.NetConfig):
|
||||||
data += "TYPE=OVSDPDKBond\n"
|
data += "TYPE=OVSDPDKBond\n"
|
||||||
data += "OVS_BRIDGE=%s\n" % base_opt.bridge_name
|
data += "OVS_BRIDGE=%s\n" % base_opt.bridge_name
|
||||||
if base_opt.members:
|
if base_opt.members:
|
||||||
|
for bond_member in base_opt.members:
|
||||||
|
# Validation of DPDK port having only one interface is done
|
||||||
|
# prior to this. So accesing the interface name statically.
|
||||||
|
# Also pci_address would be valid here, since
|
||||||
|
# bind_dpdk_interfaces () is invoked before this.
|
||||||
|
pci_address = utils.get_stored_pci_address(
|
||||||
|
bond_member.members[0].name, self.noop)
|
||||||
|
ovs_extra.append("set Interface %s options:"
|
||||||
|
"dpdk-devargs=%s"
|
||||||
|
% (bond_member.name, pci_address))
|
||||||
members = [member.name for member in base_opt.members]
|
members = [member.name for member in base_opt.members]
|
||||||
data += ("BOND_IFACES=\"%s\"\n" % " ".join(members))
|
data += ("BOND_IFACES=\"%s\"\n" % " ".join(members))
|
||||||
if base_opt.ovs_options:
|
if base_opt.ovs_options:
|
||||||
|
|
|
@ -412,6 +412,14 @@ class TestIfcfgNetConfig(base.TestCase):
|
||||||
def get_route6_config(self, name='em1'):
|
def get_route6_config(self, name='em1'):
|
||||||
return self.provider.route6_data.get(name, '')
|
return self.provider.route6_data.get(name, '')
|
||||||
|
|
||||||
|
def stub_get_stored_pci_address(self, ifname, noop):
|
||||||
|
if 'eth0' in ifname:
|
||||||
|
return "0000:00:07.0"
|
||||||
|
if 'eth1' in ifname:
|
||||||
|
return "0000:00:08.0"
|
||||||
|
if 'eth2' in ifname:
|
||||||
|
return "0000:00:09.0"
|
||||||
|
|
||||||
def test_add_base_interface(self):
|
def test_add_base_interface(self):
|
||||||
interface = objects.Interface('em1')
|
interface = objects.Interface('em1')
|
||||||
self.provider.add_interface(interface)
|
self.provider.add_interface(interface)
|
||||||
|
@ -893,6 +901,8 @@ DNS2=5.6.7.8
|
||||||
self.assertEqual(driver, 'vfio-pci')
|
self.assertEqual(driver, 'vfio-pci')
|
||||||
self.stubs.Set(utils, 'bind_dpdk_interfaces',
|
self.stubs.Set(utils, 'bind_dpdk_interfaces',
|
||||||
test_bind_dpdk_interfaces)
|
test_bind_dpdk_interfaces)
|
||||||
|
self.stubs.Set(utils, 'get_stored_pci_address',
|
||||||
|
self.stub_get_stored_pci_address)
|
||||||
|
|
||||||
self.provider.add_ovs_dpdk_port(dpdk_port)
|
self.provider.add_ovs_dpdk_port(dpdk_port)
|
||||||
self.provider.add_ovs_user_bridge(bridge)
|
self.provider.add_ovs_user_bridge(bridge)
|
||||||
|
@ -914,6 +924,7 @@ PEERDNS=no
|
||||||
DEVICETYPE=ovs
|
DEVICETYPE=ovs
|
||||||
TYPE=OVSDPDKPort
|
TYPE=OVSDPDKPort
|
||||||
OVS_BRIDGE=br-link
|
OVS_BRIDGE=br-link
|
||||||
|
OVS_EXTRA="set Interface $DEVICE options:dpdk-devargs=0000:00:09.0"
|
||||||
"""
|
"""
|
||||||
self.assertEqual(br_link_config,
|
self.assertEqual(br_link_config,
|
||||||
self.provider.bridge_data['br-link'])
|
self.provider.bridge_data['br-link'])
|
||||||
|
@ -935,6 +946,8 @@ OVS_BRIDGE=br-link
|
||||||
self.assertEqual(driver, 'vfio-pci')
|
self.assertEqual(driver, 'vfio-pci')
|
||||||
self.stubs.Set(utils, 'bind_dpdk_interfaces',
|
self.stubs.Set(utils, 'bind_dpdk_interfaces',
|
||||||
test_bind_dpdk_interfaces)
|
test_bind_dpdk_interfaces)
|
||||||
|
self.stubs.Set(utils, 'get_stored_pci_address',
|
||||||
|
self.stub_get_stored_pci_address)
|
||||||
|
|
||||||
self.provider.add_ovs_dpdk_bond(bond)
|
self.provider.add_ovs_dpdk_bond(bond)
|
||||||
self.provider.add_ovs_user_bridge(bridge)
|
self.provider.add_ovs_user_bridge(bridge)
|
||||||
|
@ -949,6 +962,8 @@ DEVICETYPE=ovs
|
||||||
TYPE=OVSDPDKBond
|
TYPE=OVSDPDKBond
|
||||||
OVS_BRIDGE=br-link
|
OVS_BRIDGE=br-link
|
||||||
BOND_IFACES="dpdk0 dpdk1"
|
BOND_IFACES="dpdk0 dpdk1"
|
||||||
|
OVS_EXTRA="set Interface dpdk0 options:dpdk-devargs=0000:00:08.0 \
|
||||||
|
-- set Interface dpdk1 options:dpdk-devargs=0000:00:09.0"
|
||||||
"""
|
"""
|
||||||
self.assertEqual(dpdk_bond_config,
|
self.assertEqual(dpdk_bond_config,
|
||||||
self.get_interface_config('dpdkbond0'))
|
self.get_interface_config('dpdkbond0'))
|
||||||
|
|
|
@ -102,6 +102,24 @@ class TestUtils(base.TestCase):
|
||||||
pci = utils._get_pci_address('nic2', False)
|
pci = utils._get_pci_address('nic2', False)
|
||||||
self.assertEqual(None, pci)
|
self.assertEqual(None, pci)
|
||||||
|
|
||||||
|
def test_get_stored_pci_address_success(self):
|
||||||
|
def test_get_dpdk_map():
|
||||||
|
return [{'name': 'eth1', 'pci_address': '0000:00:09.0',
|
||||||
|
'mac_address': '01:02:03:04:05:06',
|
||||||
|
'driver': 'vfio-pci'}]
|
||||||
|
|
||||||
|
self.stubs.Set(utils, '_get_dpdk_map', test_get_dpdk_map)
|
||||||
|
pci = utils.get_stored_pci_address('eth1', False)
|
||||||
|
self.assertEqual('0000:00:09.0', pci)
|
||||||
|
|
||||||
|
def test_get_stored_pci_address_empty(self):
|
||||||
|
def test_get_dpdk_map():
|
||||||
|
return []
|
||||||
|
|
||||||
|
self.stubs.Set(utils, '_get_dpdk_map', test_get_dpdk_map)
|
||||||
|
pci = utils.get_stored_pci_address('eth1', False)
|
||||||
|
self.assertEqual(None, pci)
|
||||||
|
|
||||||
def test_bind_dpdk_interfaces(self):
|
def test_bind_dpdk_interfaces(self):
|
||||||
def test_execute(name, dummy1, dummy2=None, dummy3=None):
|
def test_execute(name, dummy1, dummy2=None, dummy3=None):
|
||||||
if 'ethtool' in name:
|
if 'ethtool' in name:
|
||||||
|
@ -115,8 +133,10 @@ class TestUtils(base.TestCase):
|
||||||
self.stubs.Set(processutils, 'execute', test_execute)
|
self.stubs.Set(processutils, 'execute', test_execute)
|
||||||
self.stubs.Set(utils, '_get_dpdk_mac_address',
|
self.stubs.Set(utils, '_get_dpdk_mac_address',
|
||||||
test_get_dpdk_mac_address)
|
test_get_dpdk_mac_address)
|
||||||
|
try:
|
||||||
utils.bind_dpdk_interfaces('nic2', 'vfio-pci', False)
|
utils.bind_dpdk_interfaces('nic2', 'vfio-pci', False)
|
||||||
|
except utils.OvsDpdkBindException:
|
||||||
|
self.fail("Received OvsDpdkBindException unexpectedly")
|
||||||
|
|
||||||
def test_bind_dpdk_interfaces_fail(self):
|
def test_bind_dpdk_interfaces_fail(self):
|
||||||
def test_execute(name, dummy1, dummy2=None, dummy3=None):
|
def test_execute(name, dummy1, dummy2=None, dummy3=None):
|
||||||
|
@ -136,6 +156,54 @@ class TestUtils(base.TestCase):
|
||||||
utils.bind_dpdk_interfaces, 'eth1', 'vfio-pci',
|
utils.bind_dpdk_interfaces, 'eth1', 'vfio-pci',
|
||||||
False)
|
False)
|
||||||
|
|
||||||
|
def test_bind_dpdk_interfaces_skip_valid_device(self):
|
||||||
|
def test_execute(name, dummy1, dummy2=None, dummy3=None):
|
||||||
|
if 'ethtool' in name:
|
||||||
|
return None, 'Error'
|
||||||
|
if 'driverctl' in name:
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
def test_get_dpdk_mac_address(name):
|
||||||
|
return '01:02:03:04:05:06'
|
||||||
|
|
||||||
|
def test_get_dpdk_map():
|
||||||
|
return [{'name': 'eth1', 'pci_address': '0000:00:09.0',
|
||||||
|
'mac_address': '01:02:03:04:05:06',
|
||||||
|
'driver': 'vfio-pci'}]
|
||||||
|
|
||||||
|
self.stubs.Set(utils, '_get_dpdk_map', test_get_dpdk_map)
|
||||||
|
self.stubs.Set(processutils, 'execute', test_execute)
|
||||||
|
self.stubs.Set(utils, '_get_dpdk_mac_address',
|
||||||
|
test_get_dpdk_mac_address)
|
||||||
|
try:
|
||||||
|
utils.bind_dpdk_interfaces('eth1', 'vfio-pci', False)
|
||||||
|
except utils.OvsDpdkBindException:
|
||||||
|
self.fail("Received OvsDpdkBindException unexpectedly")
|
||||||
|
|
||||||
|
def test_bind_dpdk_interfaces_fail_invalid_device(self):
|
||||||
|
def test_execute(name, dummy1, dummy2=None, dummy3=None):
|
||||||
|
if 'ethtool' in name:
|
||||||
|
return None, 'Error'
|
||||||
|
if 'driverctl' in name:
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
def test_get_dpdk_mac_address(name):
|
||||||
|
return '01:02:03:04:05:06'
|
||||||
|
|
||||||
|
def test_get_dpdk_map():
|
||||||
|
return [{'name': 'eth1', 'pci_address': '0000:00:09.0',
|
||||||
|
'mac_address': '01:02:03:04:05:06',
|
||||||
|
'driver': 'vfio-pci'}]
|
||||||
|
|
||||||
|
self.stubs.Set(utils, '_get_dpdk_map', test_get_dpdk_map)
|
||||||
|
self.stubs.Set(processutils, 'execute', test_execute)
|
||||||
|
self.stubs.Set(utils, '_get_dpdk_mac_address',
|
||||||
|
test_get_dpdk_mac_address)
|
||||||
|
|
||||||
|
self.assertRaises(utils.OvsDpdkBindException,
|
||||||
|
utils.bind_dpdk_interfaces, 'eth2', 'vfio-pci',
|
||||||
|
False)
|
||||||
|
|
||||||
def test__update_dpdk_map_new(self):
|
def test__update_dpdk_map_new(self):
|
||||||
utils._update_dpdk_map('eth1', '0000:03:00.0', '01:02:03:04:05:06',
|
utils._update_dpdk_map('eth1', '0000:03:00.0', '01:02:03:04:05:06',
|
||||||
'vfio-pci')
|
'vfio-pci')
|
||||||
|
|
|
@ -230,6 +230,14 @@ def bind_dpdk_interfaces(ifname, driver, noop):
|
||||||
except processutils.ProcessExecutionError:
|
except processutils.ProcessExecutionError:
|
||||||
msg = "Failed to bind interface %s with dpdk" % ifname
|
msg = "Failed to bind interface %s with dpdk" % ifname
|
||||||
raise OvsDpdkBindException(msg)
|
raise OvsDpdkBindException(msg)
|
||||||
|
else:
|
||||||
|
# Check if the pci address is already fetched and stored.
|
||||||
|
# If the pci address could not be fetched from dpdk_mapping.yaml
|
||||||
|
# raise OvsDpdkBindException, since the interface is neither
|
||||||
|
# available nor bound with dpdk.
|
||||||
|
if not get_stored_pci_address(ifname, noop):
|
||||||
|
msg = "Interface %s cannot be found" % ifname
|
||||||
|
raise OvsDpdkBindException(msg)
|
||||||
else:
|
else:
|
||||||
logger.info('Interface %(name)s bound to DPDK driver %(driver)s '
|
logger.info('Interface %(name)s bound to DPDK driver %(driver)s '
|
||||||
'using driverctl command' %
|
'using driverctl command' %
|
||||||
|
@ -256,14 +264,24 @@ def _get_pci_address(ifname, noop):
|
||||||
'ethtool' % ifname)
|
'ethtool' % ifname)
|
||||||
|
|
||||||
|
|
||||||
|
def get_stored_pci_address(ifname, noop):
|
||||||
|
if not noop:
|
||||||
|
dpdk_map = _get_dpdk_map()
|
||||||
|
for dpdk_nic in dpdk_map:
|
||||||
|
if dpdk_nic['name'] == ifname:
|
||||||
|
return dpdk_nic['pci_address']
|
||||||
|
else:
|
||||||
|
logger.info('Fetch the PCI address of the interface %s using '
|
||||||
|
'ethtool' % ifname)
|
||||||
|
|
||||||
|
|
||||||
# Once the interface is bound to a DPDK driver, all the references to the
|
# Once the interface is bound to a DPDK driver, all the references to the
|
||||||
# interface including '/sys' and '/proc', will be removed. And there is no
|
# interface including '/sys' and '/proc', will be removed. And there is no
|
||||||
# way to identify the nic name after it is bound. So, the DPDK bound nic info
|
# way to identify the nic name after it is bound. So, the DPDK bound nic info
|
||||||
# is stored persistently in a file and is used to for nic numbering on
|
# is stored persistently in a file and is used to for nic numbering on
|
||||||
# subsequent runs of os-net-config.
|
# subsequent runs of os-net-config.
|
||||||
def _update_dpdk_map(ifname, pci_address, mac_address, driver):
|
def _update_dpdk_map(ifname, pci_address, mac_address, driver):
|
||||||
contents = get_file_data(_DPDK_MAPPING_FILE)
|
dpdk_map = _get_dpdk_map()
|
||||||
dpdk_map = yaml.load(contents) if contents else []
|
|
||||||
for item in dpdk_map:
|
for item in dpdk_map:
|
||||||
if item['pci_address'] == pci_address:
|
if item['pci_address'] == pci_address:
|
||||||
item['name'] = ifname
|
item['name'] = ifname
|
||||||
|
@ -281,6 +299,12 @@ def _update_dpdk_map(ifname, pci_address, mac_address, driver):
|
||||||
write_yaml_config(_DPDK_MAPPING_FILE, dpdk_map)
|
write_yaml_config(_DPDK_MAPPING_FILE, dpdk_map)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_dpdk_map():
|
||||||
|
contents = get_file_data(_DPDK_MAPPING_FILE)
|
||||||
|
dpdk_map = yaml.load(contents) if contents else []
|
||||||
|
return dpdk_map
|
||||||
|
|
||||||
|
|
||||||
def _get_dpdk_mac_address(name):
|
def _get_dpdk_mac_address(name):
|
||||||
contents = get_file_data(_DPDK_MAPPING_FILE)
|
contents = get_file_data(_DPDK_MAPPING_FILE)
|
||||||
dpdk_map = yaml.load(contents) if contents else []
|
dpdk_map = yaml.load(contents) if contents else []
|
||||||
|
|
Loading…
Reference in New Issue