summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniil Baturin <daniil@vyos.io>2026-03-18 15:12:25 +0000
committerGitHub <noreply@github.com>2026-03-18 15:12:25 +0000
commitd5b4ac579a902408addf711276dfbf0d95b7a19b (patch)
tree86ffaa6aad1a1b3ac0e806f0c72aff843a540c46
parent0b3114e33a8dfbbde48e1231322b201938add330 (diff)
parent3722268b0859831ae96c9cb3f634382713139f6d (diff)
downloadvyos-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.in6
-rw-r--r--python/vyos/vpp/config_verify.py62
-rw-r--r--python/vyos/vpp/control_host.py36
-rwxr-xr-xsrc/conf_mode/vpp.py47
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']