From 46fc50f419bc241cddbbc842e2a609d21e964bf8 Mon Sep 17 00:00:00 2001 From: Caio Bruchert Date: Thu, 29 Feb 2024 13:41:00 -0300 Subject: [PATCH] Prevent configuring the Dell Minerva NIC VFs Since the Dell Operator will be responsible for VF configuration, the configuration of this NIC using sysinv is being blocked to prevent user mistakes. This is valid for the Dell Minerva NICs using Marvell CNF105xx family devices. The CNF105xx device IDs were found in the octeon_ep driver source code: https://github.com/MarvellEmbeddedProcessors/pcie_ep_octeon_host /drivers/octeon_ep/octep_main.h Test Plan: PASS: host-if-modify class from none to pci-passthrough: allowed PASS: host-if-modify class from pci-passthrough to none: allowed PASS: host-if-modify class from none to pci-sriov w/ VFs: blocked PASS: host-if-modify class from none to pci-sriov w/ VFs for other devices: allowed Story: 2010047 Task: 49650 Signed-off-by: Caio Bruchert Change-Id: Ib6a20952060331ac230b01813be28116fbceef36 --- .../sysinv/api/controllers/v1/interface.py | 14 +++++++- .../sysinv/sysinv/sysinv/common/constants.py | 8 +++++ .../sysinv/sysinv/tests/api/test_interface.py | 32 +++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/interface.py b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/interface.py index b94ef0b436..8e130335a5 100644 --- a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/interface.py +++ b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/interface.py @@ -1455,6 +1455,11 @@ def _check_interface_data(op, interface, ihost, existing_interface, return interface +def _is_port_sriov_restricted(port): + return port.pvendor in constants.SRIOV_RESTRICTED_NET_DEVICES and \ + port.pdevice in constants.SRIOV_RESTRICTED_NET_DEVICES[port.pvendor] + + def _check_ports(op, interface, ihost, ports): port_list = [] @@ -1474,10 +1479,17 @@ def _check_ports(op, interface, ihost, ports): raise wsme.exc.ClientSideError(_( "For Ethernet, select a single port.")) - # Make sure that no other interface is currently using these ports + # Make sure that the port is not in the SR-IOV restricted list and + # that no other interface is currently using these ports host_ports = pecan.request.dbapi.ethernet_port_get_all(hostid=ihost['id']) for p in host_ports: if p.name in port_list or p.uuid in port_list: + if (interface['ifclass'] == constants.INTERFACE_CLASS_PCI_SRIOV and + _is_port_sriov_restricted(p)): + pif = pecan.request.dbapi.iinterface_get(p.interface_id) + msg = _("Cannot use port. PCI vendor '%s' and device '%s' is not allowed." + % (p.pvendor, p.pdevice)) + raise wsme.exc.ClientSideError(msg) if p.interface_id and p.interface_id != this_interface_id: pif = pecan.request.dbapi.iinterface_get(p.interface_id) msg = _("Another interface %s is already using this port" diff --git a/sysinv/sysinv/sysinv/sysinv/common/constants.py b/sysinv/sysinv/sysinv/sysinv/common/constants.py index fa2c72a9e6..d58bdce4f8 100644 --- a/sysinv/sysinv/sysinv/sysinv/common/constants.py +++ b/sysinv/sysinv/sysinv/sysinv/common/constants.py @@ -2256,6 +2256,14 @@ DRIVERS_UP_BEFORE_SRIOV = [DRIVER_BNXT_EN] # become operational DRIVERS_NOT_IMMEDIATELY_OPERATIONAL = [DRIVER_BNXT_EN] +# SR-IOV restricted network devices (cannot be used to create VFs) +# Marvell (Cavium) CNF105xx family (CNF10KA and CNF10KB): +PVENDOR_CAVIUM = 'Cavium, Inc. [177d]' +PDEVICE_CAVIUM_BA00 = 'Device [ba00]' +PDEVICE_CAVIUM_BC00 = 'Device [bc00]' +SRIOV_RESTRICTED_NET_DEVICES = {PVENDOR_CAVIUM: (PDEVICE_CAVIUM_BA00, + PDEVICE_CAVIUM_BC00)} + # Traffic control TRAFFIC_CONTROL_SCRIPT = '/usr/local/bin/tc_setup.sh' diff --git a/sysinv/sysinv/sysinv/sysinv/tests/api/test_interface.py b/sysinv/sysinv/sysinv/sysinv/tests/api/test_interface.py index 5f526bf1d9..cbf677398e 100644 --- a/sysinv/sysinv/sysinv/sysinv/tests/api/test_interface.py +++ b/sysinv/sysinv/sysinv/sysinv/tests/api/test_interface.py @@ -1938,6 +1938,38 @@ class TestPostMixin(object): self.assertEqual(http_client.OK, patch_result.status_code) self.assertEqual(0, patch_result.json['max_tx_rate']) + def test_modify_sriov_restricted_port(self): + pvendor = constants.PVENDOR_CAVIUM + pdevice = constants.PDEVICE_CAVIUM_BA00 + interface = dbutils.create_test_interface(forihostid=self.worker.id, + datanetworks='group0-data0') + dbutils.create_test_ethernet_port( + id=1, name='enp81s0f0', host_id=self.worker.id, + interface_id=interface.id, + pciaddr='0000:51:00.0', dev_id=0, sriov_totalvfs=32, sriov_numvfs=0, + driver='octeon_ep', + pvendor=pvendor, + pdevice=pdevice) + # ifclass to pci-passthrough is allowed + patch_result = self.patch_dict_json( + '%s' % self._get_path(interface['uuid']), + ifname='sriov0', + ifclass=constants.INTERFACE_CLASS_PCI_PASSTHROUGH, + expect_errors=True) + self.assertEqual('application/json', patch_result.content_type) + self.assertEqual(http_client.OK, patch_result.status_code) + # ifclass to pci-sriov is not allowed + patch_result = self.patch_dict_json( + '%s' % self._get_path(interface['uuid']), + ifclass=constants.INTERFACE_CLASS_PCI_SRIOV, + sriov_numvfs=8, + expect_errors=True) + self.assertEqual(http_client.BAD_REQUEST, patch_result.status_int) + self.assertTrue(patch_result.json['error_message']) + self.assertIn(f"Cannot use port. PCI vendor '{pvendor}' and " + f"device '{pdevice}' is not allowed.", + patch_result.json['error_message']) + class TestAIOPost(InterfaceTestCase): def setUp(self):