From 48baae41f41f43288388c8adf29a26d2ce284447 Mon Sep 17 00:00:00 2001 From: Mikhail Chusavitin Date: Mon, 17 Aug 2026 09:42:34 +0300 Subject: [PATCH] fix(exporter): key PCIe canonical dedup by BDF before serial canonicalKey used serial_number as the primary merge key for pcie-class devices (PCIe/GPU/Network), falling back to BDF only when serial was empty. Multi-port NICs commonly report one serial for the whole physical card across all of its ports/BDFs (e.g. a dual-port ConnectX-5: same serial, distinct BDFs 0000:65:00.0/.1, distinct MACs). Keying on serial first collapsed every port sharing that serial into a single canonical device, silently dropping all but one port from the export. BDF now takes priority for pcie-class devices, since it uniquely identifies one physical PCI function; other device kinds (storage, memory, PSU, etc.) keep the existing serial-first behavior, which is correct there since a serial genuinely maps 1:1 to a physical unit for those. Co-Authored-By: Claude Sonnet 5 --- internal/exporter/reanimator_converter.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/internal/exporter/reanimator_converter.go b/internal/exporter/reanimator_converter.go index b0fe113..36031b2 100644 --- a/internal/exporter/reanimator_converter.go +++ b/internal/exporter/reanimator_converter.go @@ -718,10 +718,19 @@ func mergeDetailMaps(primary, secondary map[string]any) map[string]any { func canonicalKey(item models.HardwareDevice) string { kind := canonicalMergeKind(item.Kind) + bdf := strings.ToLower(strings.TrimSpace(item.BDF)) + if kind == "pcie-class" && bdf != "" { + // BDF identifies one physical PCI function; prefer it over serial for + // pcie-class devices. Multi-port NICs commonly report the same serial + // (the physical card's serial) across several BDFs/ports — keying on + // serial first would collapse distinct ports into a single record and + // silently drop the others. + return kind + "|bdf:" + bdf + } if sn := normalizedSerial(item.SerialNumber); sn != "" { return kind + "|sn:" + strings.ToLower(sn) } - if bdf := strings.ToLower(strings.TrimSpace(item.BDF)); bdf != "" { + if bdf != "" { return kind + "|bdf:" + bdf } return ""