From aeaa6fe62b39a00f3b075a94c076f267f0c70af0 Mon Sep 17 00:00:00 2001 From: waleed mousa Date: Tue, 30 Jan 2018 04:00:39 -0500 Subject: [PATCH] Adding the class and mac approach as dpdk-devargs in mellanox ConnectX-3 Some NICs (i.e. Mellanox ConnectX-3) have only one PCI address associated with multiple ports. Using a PCI address as dpdk-devargs in OvsDpdkPort won't work. Instead, class and mac approach is used dpdk-devargs="class=eth,mac=" see this http://docs.openvswitch.org/en/latest/howto/dpdk/ Change-Id: I29de6e82a0897ee46953a1e6a966e9c5790068c9 --- os_net_config/impl_ifcfg.py | 13 +++---- os_net_config/tests/test_utils.py | 26 ++++++++++++++ os_net_config/utils.py | 34 +++++++++++++++++++ ...pdk-on-mellanox-nics-1d8fdb843a4e2b60.yaml | 5 +++ 4 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 releasenotes/notes/dpdk-on-mellanox-nics-1d8fdb843a4e2b60.yaml diff --git a/os_net_config/impl_ifcfg.py b/os_net_config/impl_ifcfg.py index 39a55876..ad111fc0 100644 --- a/os_net_config/impl_ifcfg.py +++ b/os_net_config/impl_ifcfg.py @@ -304,12 +304,13 @@ class IfcfgNetConfig(os_net_config.NetConfig): 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 + # Also dpdk_devargs would be valid here, since # bind_dpdk_interfaces() is invoked before this. - pci_address = utils.get_stored_pci_address( + dpdk_devargs = utils.get_dpdk_devargs( base_opt.members[0].name, self.noop) + ovs_extra.append("set Interface $DEVICE options:dpdk-devargs=" - "%s" % pci_address) + "%s" % dpdk_devargs) if base_opt.mtu: ovs_extra.append("set Interface $DEVICE mtu_request=$MTU") if base_opt.rx_queue: @@ -332,13 +333,13 @@ class IfcfgNetConfig(os_net_config.NetConfig): 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 + # Also dpdk_devargs would be valid here, since # bind_dpdk_interfaces () is invoked before this. - pci_address = utils.get_stored_pci_address( + dpdk_devargs = utils.get_dpdk_devargs( bond_member.members[0].name, self.noop) ovs_extra.append("set Interface %s options:" "dpdk-devargs=%s" - % (bond_member.name, pci_address)) + % (bond_member.name, dpdk_devargs)) members = [member.name for member in base_opt.members] data += ("BOND_IFACES=\"%s\"\n" % " ".join(members)) # MTU configuration given for the OvsDpdkbond shall be applied diff --git a/os_net_config/tests/test_utils.py b/os_net_config/tests/test_utils.py index 23c9c6ce..7b47b814 100644 --- a/os_net_config/tests/test_utils.py +++ b/os_net_config/tests/test_utils.py @@ -209,6 +209,32 @@ class TestUtils(base.TestCase): pci = utils.get_stored_pci_address('eth1', False) self.assertEqual(None, pci) + def test_get_vendor_id_success(self): + mocked_open = mock.mock_open(read_data='0x15b3\n') + with mock.patch('os_net_config.utils.open', mocked_open, create=True): + vendor = utils.get_vendor_id('nic2') + self.assertEqual('0x15b3', vendor) + + def test_get_vendor_id_exception(self): + mocked_open = mock.mock_open() + mocked_open.side_effect = IOError + with mock.patch('os_net_config.utils.open', mocked_open, create=True): + vendor = utils.get_vendor_id('nic2') + self.assertEqual(None, vendor) + + def test_get_device_id_success(self): + mocked_open = mock.mock_open(read_data='0x1003\n') + with mock.patch('os_net_config.utils.open', mocked_open, create=True): + device = utils.get_device_id('nic2') + self.assertEqual('0x1003', device) + + def test_get_device_id_exception(self): + mocked_open = mock.mock_open() + mocked_open.side_effect = IOError + with mock.patch('os_net_config.utils.open', mocked_open, create=True): + device = utils.get_device_id('nic2') + self.assertEqual(None, device) + def test_bind_dpdk_interfaces(self): def test_execute(name, dummy1, dummy2=None, dummy3=None): if 'ethtool' in name: diff --git a/os_net_config/utils.py b/os_net_config/utils.py index c8dff2dd..b16e7483 100644 --- a/os_net_config/utils.py +++ b/os_net_config/utils.py @@ -336,6 +336,40 @@ def translate_ifname_to_pci_address(ifname, noop): return pci_address +def get_vendor_id(ifname): + try: + with open('%s/%s/device/vendor' % (_SYS_CLASS_NET, ifname), + 'r') as f: + out = f.read().strip() + return out + except IOError: + return + + +def get_device_id(ifname): + try: + with open('%s/%s/device/device' % (_SYS_CLASS_NET, ifname), + 'r') as f: + out = f.read().strip() + return out + except IOError: + return + + +def get_dpdk_devargs(ifname, noop): + if not noop: + vendor_id = get_vendor_id(ifname) + device_id = get_device_id(ifname) + if vendor_id == "0x15b3" and device_id == "0x1007": + # Some NICs (i.e. Mellanox ConnectX-3) have only one PCI address + # associated with multiple ports. Using a PCI device won’t work. + # Instead, we should use "class=eth,mac=" + dpdk_devargs = "class=eth,mac=%s" % interface_mac(ifname) + else: + dpdk_devargs = get_stored_pci_address(ifname, noop) + return dpdk_devargs + + # 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 # way to identify the nic name after it is bound. So, the DPDK bound nic info diff --git a/releasenotes/notes/dpdk-on-mellanox-nics-1d8fdb843a4e2b60.yaml b/releasenotes/notes/dpdk-on-mellanox-nics-1d8fdb843a4e2b60.yaml new file mode 100644 index 00000000..6728a343 --- /dev/null +++ b/releasenotes/notes/dpdk-on-mellanox-nics-1d8fdb843a4e2b60.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + Adding dpdk support in meallnox nics. + Dpdk now fully suuported in mellanox nics.