From 961f0c633f0632bb2cb9d485218d7704008f996c Mon Sep 17 00:00:00 2001 From: Xichen96 Date: Sat, 25 Jul 2026 17:07:13 +0000 Subject: [PATCH 1/2] [dhcpmon] Classify nested VLAN members as downlinks Expand VLAN-backed PortChannels to their physical members when displaying dhcpmon counters so the new hierarchy is not mislabeled as uplink traffic. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 39f979be-d826-4d5c-949a-f20abb58bb83 Signed-off-by: Xichen96 --- .../test_show_dhcpmon_counters.py | 25 ++++++++++++++----- .../cli/show/plugins/show_dhcp_relay.py | 17 ++++++++++++- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/dockers/docker-dhcp-relay/cli-plugin-tests/test_show_dhcpmon_counters.py b/dockers/docker-dhcp-relay/cli-plugin-tests/test_show_dhcpmon_counters.py index e4d0f2513f1..cd3c9018539 100644 --- a/dockers/docker-dhcp-relay/cli-plugin-tests/test_show_dhcpmon_counters.py +++ b/dockers/docker-dhcp-relay/cli-plugin-tests/test_show_dhcpmon_counters.py @@ -35,16 +35,29 @@ def test_plugin_registration(): def test_get_vlan_members_from_config_db(): mock_db = MagicMock() - mock_db.keys.return_value = [ - "VLAN_MEMBER|Vlan1000|Ethernet1", - "VLAN_MEMBER|Vlan1000|Ethernet2", - "VLAN_MEMBER|Vlan2000|Ethernet3" - ] + def mock_keys(_, pattern): + if pattern.startswith("VLAN_MEMBER"): + return [ + "VLAN_MEMBER|Vlan1000|Ethernet1", + "VLAN_MEMBER|Vlan1000|PortChannel1001", + "VLAN_MEMBER|Vlan2000|Ethernet3" + ] + if pattern == "PORTCHANNEL_MEMBER|*": + return [ + "PORTCHANNEL_MEMBER|PortChannel1001|Ethernet2", + "PORTCHANNEL_MEMBER|PortChannel1001|Ethernet4", + "PORTCHANNEL_MEMBER|PortChannel2001|Ethernet5" + ] + return [] + + mock_db.keys.side_effect = mock_keys result = show_dhcp_relay.get_vlan_members_from_config_db( mock_db, "Vlan1000" ) assert result == { - "Vlan1000": set(["Ethernet1", "Ethernet2"]) + "Vlan1000": set([ + "Ethernet1", "PortChannel1001", "Ethernet2", "Ethernet4" + ]) } diff --git a/dockers/docker-dhcp-relay/cli/show/plugins/show_dhcp_relay.py b/dockers/docker-dhcp-relay/cli/show/plugins/show_dhcp_relay.py index 4123b64e0a1..8286ccce32c 100644 --- a/dockers/docker-dhcp-relay/cli/show/plugins/show_dhcp_relay.py +++ b/dockers/docker-dhcp-relay/cli/show/plugins/show_dhcp_relay.py @@ -77,6 +77,7 @@ # --- DB Key Separators --- VLAN_MEMBER_TABLE_PREFIX = "VLAN_MEMBER" +PORTCHANNEL_MEMBER_TABLE_PREFIX = "PORTCHANNEL_MEMBER" COUNTERS_DB_SEPRATOR = ":" CONFIG_DB_SEPRATOR = "|" MGMT_PORT_TABLE = "MGMT_PORT" @@ -496,6 +497,16 @@ def get_vlan_members_from_config_db(db, vlan_interface): Returns dict: {vlan_name: set(member_interfaces)} """ vlan_members = {} + portchannel_members = {} + member_pattern = ( + PORTCHANNEL_MEMBER_TABLE_PREFIX + CONFIG_DB_SEPRATOR + "*" + ) + for key in (db.keys(db.CONFIG_DB, member_pattern) or []): + splits = key.split(CONFIG_DB_SEPRATOR) + if len(splits) < 3: + continue + portchannel_members.setdefault(splits[1], set()).add(splits[2]) + pattern = ( VLAN_MEMBER_TABLE_PREFIX + CONFIG_DB_SEPRATOR + vlan_interface + "*" @@ -506,7 +517,11 @@ def get_vlan_members_from_config_db(db, vlan_interface): continue if splits[1] not in vlan_members: vlan_members[splits[1]] = set() - vlan_members[splits[1]].add(splits[2]) + member = splits[2] + vlan_members[splits[1]].add(member) + vlan_members[splits[1]].update( + portchannel_members.get(member, set()) + ) return vlan_members From be8fc60bc96ef224296a754c250d351359d7c96d Mon Sep 17 00:00:00 2001 From: Xichen96 Date: Sat, 25 Jul 2026 23:17:27 +0000 Subject: [PATCH 2/2] [dhcpmon] Validate VLAN membership keys Ignore malformed VLAN_MEMBER keys before classifying counter interfaces. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 39f979be-d826-4d5c-949a-f20abb58bb83 Signed-off-by: Xichen96 --- dockers/docker-dhcp-relay/cli/show/plugins/show_dhcp_relay.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dockers/docker-dhcp-relay/cli/show/plugins/show_dhcp_relay.py b/dockers/docker-dhcp-relay/cli/show/plugins/show_dhcp_relay.py index 8286ccce32c..a92fdabf8f4 100644 --- a/dockers/docker-dhcp-relay/cli/show/plugins/show_dhcp_relay.py +++ b/dockers/docker-dhcp-relay/cli/show/plugins/show_dhcp_relay.py @@ -513,6 +513,8 @@ def get_vlan_members_from_config_db(db, vlan_interface): ) for key in (db.keys(db.CONFIG_DB, pattern) or []): splits = key.split(CONFIG_DB_SEPRATOR) + if len(splits) < 3: + continue if not splits[1].endswith(vlan_interface): continue if splits[1] not in vlan_members: