diff options
| author | Daniil Baturin <daniil@vyos.io> | 2026-03-18 15:12:25 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-03-18 15:12:25 +0000 |
| commit | d5b4ac579a902408addf711276dfbf0d95b7a19b (patch) | |
| tree | 86ffaa6aad1a1b3ac0e806f0c72aff843a540c46 | |
| parent | 0b3114e33a8dfbbde48e1231322b201938add330 (diff) | |
| parent | 3722268b0859831ae96c9cb3f634382713139f6d (diff) | |
| download | vyos-1x-d5b4ac579a902408addf711276dfbf0d95b7a19b.tar.gz vyos-1x-d5b4ac579a902408addf711276dfbf0d95b7a19b.zip | |
Merge pull request #5041 from alexandr-san4ez/T8315-current
vpp: T8315: Add support for configuring unsupported NICs and update compatible list
| -rw-r--r-- | interface-definitions/vpp.xml.in | 6 | ||||
| -rw-r--r-- | python/vyos/vpp/config_verify.py | 62 | ||||
| -rw-r--r-- | python/vyos/vpp/control_host.py | 36 | ||||
| -rwxr-xr-x | src/conf_mode/vpp.py | 47 |
4 files changed, 86 insertions, 65 deletions
diff --git a/interface-definitions/vpp.xml.in b/interface-definitions/vpp.xml.in index 0da90ddd3..bf5e56db8 100644 --- a/interface-definitions/vpp.xml.in +++ b/interface-definitions/vpp.xml.in @@ -491,6 +491,12 @@ <defaultValue>0</defaultValue> </leafNode> #include <include/vpp/iface_rx_mode.xml.i> + <leafNode name="allow-unsupported-nics"> + <properties> + <help>Allow the attachment of unsupported NICs to VPP. This operation voids official support for the system</help> + <valueless/> + </properties> + </leafNode> </children> </node> <node name="sflow" owner="${vyos_conf_scripts_dir}/vpp_sflow.py"> diff --git a/python/vyos/vpp/config_verify.py b/python/vyos/vpp/config_verify.py index 7b90b37db..c93a647f9 100644 --- a/python/vyos/vpp/config_verify.py +++ b/python/vyos/vpp/config_verify.py @@ -62,68 +62,6 @@ def verify_vpp_tunnel_source_address(config: dict): ) -def verify_dev_driver(driver_type: str, driver: str) -> bool: - # Lists of drivers compatible with DPDK and XDP - drivers_dpdk: list[str] = [ - 'atlantic', - 'bnx2x', - 'e1000', - 'ena', - 'gve', - 'hv_netvsc', - 'i40e', - 'ice', - 'igc', - 'ixgbe', - 'ixgbevf', - 'liquidio', - 'mlx4_core', - 'mlx5_core', - 'qede', - 'sfc', - 'tap', - 'tun', - 'virtio_net', - 'vmxnet3', - ] - - drivers_xdp: list[str] = [ - 'atlantic', - 'ena', - 'gve', - 'hv_netvsc', - 'i40e', - 'ice', - 'igb', - 'igc', - 'ixgbe', - 'mlx4_core', - 'mlx5_core', - 'qede', - 'sfc', - 'tap', - 'tun', - 'virtio_net', - 'vmxnet3', - ] - - if driver_type == 'dpdk': - if driver in drivers_dpdk: - return True - # XDP support is intentionally disabled (T8202). - # XDP is no longer configurable via the CLI. - # This logic is kept commented out to make it easy - # to reintroduce XDP if there is a clear need in the future. - # - # elif driver_type == 'xdp': - # if driver in drivers_xdp: - # return True - else: - raise ConfigError(f'"Driver type {driver_type} is wrong') - - return False - - def create_cpu_error_message(cpus_required: int, cpus_available: int = None) -> str: cpu_info = get_cpus() logical_cores = sum( diff --git a/python/vyos/vpp/control_host.py b/python/vyos/vpp/control_host.py index 50ab4d97a..9808c9418 100644 --- a/python/vyos/vpp/control_host.py +++ b/python/vyos/vpp/control_host.py @@ -313,6 +313,42 @@ def get_eth_driver(iface: str) -> str: raise Exception(f'Could not determine driver for "{iface}": {error}') from error +def get_pci_id(iface: str) -> str | None: + """ + Retrieves the PCI ID for a specified network interface. + + Args: + iface (str): The name of the network interface (e.g., 'eth0'). + + Raises: + OSError: The interface cannot be resolved or PCI ID files cannot be read + + Returns: + str: The PCI ID in the format 'vendor:device'. + None: In case a NIC is not on a PCI bus. + """ + dev_id = get_dev_id(iface) + + # Check if this device is on a PCI bus, return `None` if this is not a PCI device + pci_dev_path = Path(f'/sys/bus/pci/devices/{dev_id}') + if not pci_dev_path.exists(): + return None + + # Read vendor and device IDs + def _read_bus(file: str) -> str: + path = Path(f'/sys/bus/pci/devices/{dev_id}/{file}') + return path.read_text().removeprefix('0x').strip() + + try: + device_id, vendor_id = _read_bus('device'), _read_bus('vendor') + except OSError as e: + # If we reached this exception, then something really weird happened, + # but it is still right to have it + raise OSError(f'PCI IDs for {iface} cannot be retrieved') from e + + return f'{vendor_id}:{device_id}'.lower() + + def unsafe_noiommu_mode(status: bool) -> None: """Control unsafe_noiommu_mode parameter of vfio module diff --git a/src/conf_mode/vpp.py b/src/conf_mode/vpp.py index a45d4dc65..bd8aad3f7 100755 --- a/src/conf_mode/vpp.py +++ b/src/conf_mode/vpp.py @@ -52,7 +52,6 @@ from vyos.vpp.config_deps import deps_bond_dict from vyos.vpp.config_deps import deps_bridge_dict from vyos.vpp.config_deps import deps_xconnect_dict from vyos.vpp.config_verify import ( - verify_dev_driver, verify_vpp_minimum_cpus, verify_vpp_minimum_memory, verify_vpp_cpu_cores, @@ -116,6 +115,21 @@ drivers_support_interrupt: dict[str, list] = { # drivers that require changing channels (half the maximum number of RX/TX queues) ethtool_channels_change_drv: list[str] = ['ena', 'gve'] +# List of NICs where VPP activation is supported +SUPPORTED_PCI_IDS = ( + '15b3:1019', # Mellanox Technologies MT28800 Family [ConnectX-5 Ex] + '15b3:101d', # Mellanox Technologies MT2892 Family [ConnectX-6 Dx] + '15b3:101e', # Mellanox Technologies ConnectX Family mlx5Gen Virtual Function + '8086:1592', # Intel Corporation Ethernet Controller E810-C for QSFP + '1ae0:0042', # Google, Inc. Compute Engine Virtual Ethernet [gVNIC] + '1af4:1000', # Red Hat, Inc. Virtio network device (legacy ID) + '1af4:1041', # Red Hat, Inc. Virtio network device (modern ID) + '1d0f:ec20', # Amazon.com, Inc. Elastic Network Adapter (ENA) +) +SUPPORTED_DRIVERS = ( + 'hv_netvsc', # Microsoft Hyper-V network interface card +) + def _load_module(module_name: str): """ @@ -229,6 +243,29 @@ def _check_removed_interfaces(config: dict, feature_name: str, interfaces_config ) +def _is_device_allowed(config: dict, iface: str): + """ + Determines if a network interface device is allowed to be used + with VPP based on its PCI ID or driver. + """ + if 'allow_unsupported_nics' in config['settings']: + return True + + persist_config = config['persist_config'][iface] + + pci_id = persist_config.get('pci_id') + # PCI ID is sufficient by itself, if presented + if pci_id is not None and pci_id in SUPPORTED_PCI_IDS: + return True + + # If the PCI ID did not match or does not exist, fall back to a driver + original_driver = persist_config.get('original_driver') + if original_driver is not None and original_driver in SUPPORTED_DRIVERS: + return True + + return False + + def get_config(config=None): # use persistent config to store interfaces data between executions # this is required because some interfaces after they are connected @@ -351,6 +388,7 @@ def get_config(config=None): } eth_ifaces_persist[iface]['bus_id'] = control_host.get_bus_name(iface) eth_ifaces_persist[iface]['dev_id'] = control_host.get_dev_id(iface) + eth_ifaces_persist[iface]['pci_id'] = control_host.get_pci_id(iface) eth_ifaces_persist[iface]['channels'] = control_host.get_eth_channels(iface) # Return to config dictionary @@ -572,10 +610,13 @@ def verify(config): not in config.get('effective', {}).get('settings', {}).get('interface', {}) or 'driver_changed' in iface_config ): - if not verify_dev_driver(iface_config['driver'], original_driver): + if not _is_device_allowed(config, iface): raise ConfigError( - f'Driver {iface_config["driver"]} is not compatible with interface {iface}!' + f'NIC used by "{iface}" is not validated for VPP on VyOS. ' + 'Using it is unsafe and unsupported and will void support for the entire system. ' + 'To proceed at your own risk, enable: "set vpp settings allow-unsupported-nics".' ) + if iface_config['driver'] == 'xdp' and 'xdp_options' in iface_config: if iface_config['xdp_options']['num_rx_queues'] != 'all': rx_queues = iface_config['xdp_api_params']['rxq_num'] |
