From 74c02a95e8110f4bc8cc5e2d2852fcdaf023be26 Mon Sep 17 00:00:00 2001 From: John Date: Fri, 11 Sep 2026 12:30:33 +0100 Subject: [PATCH] Fix VLAN detection for named interfaces --- netbox_agent/network.py | 21 ++++++++++++++++++--- tests/network.py | 23 +++++++++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/netbox_agent/network.py b/netbox_agent/network.py index c2706108..6c14210c 100644 --- a/netbox_agent/network.py +++ b/netbox_agent/network.py @@ -17,6 +17,23 @@ VIRTUAL_NET_FOLDER = Path("/sys/devices/virtual/net") +def get_vlan_id(interface, vlan_root=Path("/proc/net/vlan")): + vlan_path = vlan_root / interface + try: + if vlan_path.is_file(): + match = re.search(r"\bVID:\s*(\d+)\b", vlan_path.read_text()) + if match: + return int(match.group(1)) + except OSError: + pass + + parts = interface.split(".") + if len(parts) > 1 and parts[1].isdigit(): + return int(parts[1]) + + return None + + class Network(object): def __init__(self, server, *args, **kwargs): self.nics = [] @@ -104,9 +121,7 @@ def scan(self): mac = mac.upper() mtu = int(open("/sys/class/net/{}/mtu".format(interface), "r").read().strip()) - vlan = None - if len(interface.split(".")) > 1: - vlan = int(interface.split(".")[1]) + vlan = get_vlan_id(interface) bonding = False bonding_slaves = [] diff --git a/tests/network.py b/tests/network.py index 99c42d4c..907f4100 100644 --- a/tests/network.py +++ b/tests/network.py @@ -1,4 +1,5 @@ from netbox_agent.lldp import LLDP +from netbox_agent.network import get_vlan_id from tests.conftest import parametrize_with_fixtures @@ -34,3 +35,25 @@ def test_lldp_parse_with_vlan(fixture): lldp = LLDP(fixture) assert lldp.get_switch_vlan("eth0") == {"300": {"pvid": True}} assert lldp.get_switch_vlan("eth1") == {"300": {}} + + +def test_get_vlan_id_from_kernel_vlan_info(tmp_path): + (tmp_path / "p6p3.vlan9").write_text("p6p3.vlan9 VID: 9 REORDER_HDR: 1\n") + assert get_vlan_id("p6p3.vlan9", tmp_path) == 9 + + +def test_get_vlan_id_from_numeric_suffix(tmp_path): + assert get_vlan_id("eth0.9", tmp_path) == 9 + assert get_vlan_id("eno1.50", tmp_path) == 50 + assert get_vlan_id("eth0.9.extra", tmp_path) == 9 + + +def test_get_vlan_id_from_non_numeric_dotted_name(tmp_path): + assert get_vlan_id("foo.bar", tmp_path) is None + + +def test_get_vlan_id_with_unusable_kernel_data(tmp_path): + (tmp_path / "eth0.9").write_text("unexpected content\n") + (tmp_path / "p6p3.vlan9").write_text("unexpected content\n") + assert get_vlan_id("eth0.9", tmp_path) == 9 + assert get_vlan_id("p6p3.vlan9", tmp_path) is None