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 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
8665f79fd6
commit
48baae41f4
@@ -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 ""
|
||||
|
||||
Reference in New Issue
Block a user