redfish: filter PCIe topology noise, deduplicate GPU/NIC cross-sources
- isUnidentifiablePCIeDevice: skip PCIe entries with generic class (SingleFunction/MultiFunction) and no model/serial/VendorID — eliminates PCH bridges, root ports and other bus infrastructure that MSI BMC enumerates exhaustively (59→9 entries on CG480-S5063) - collectPCIeDevices: skip entries where looksLikeGPU — prevents GPU devices from appearing in both hw.GPUs and hw.PCIeDevices (fixed Inspur H100 duplicate) - dedupeCanonicalDevices: secondary model+manufacturer match for noKey items (no serial, no BDF) — merges NetworkAdapter entries into matching PCIe device entries; isGenericDeviceClass helper for DeviceClass identity check (fixed Inspur ENFI1100-T4 duplicate) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -720,7 +720,13 @@ func (c *RedfishConnector) collectPCIeDevices(ctx context.Context, client *http.
|
||||
|
||||
for _, doc := range memberDocs {
|
||||
functionDocs := c.getLinkedPCIeFunctions(ctx, client, req, baseURL, doc)
|
||||
if looksLikeGPU(doc, functionDocs) {
|
||||
continue
|
||||
}
|
||||
dev := parsePCIeDevice(doc, functionDocs)
|
||||
if isUnidentifiablePCIeDevice(dev) {
|
||||
continue
|
||||
}
|
||||
out = append(out, dev)
|
||||
}
|
||||
}
|
||||
@@ -2975,6 +2981,27 @@ func isMissingOrRawPCIModel(model string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// isUnidentifiablePCIeDevice returns true for PCIe topology entries that carry no
|
||||
// useful inventory information: generic class (SingleFunction/MultiFunction), no
|
||||
// resolved model or serial, and no PCI vendor/device IDs for future resolution.
|
||||
// These are typically PCH bridges, root ports, or other bus infrastructure that
|
||||
// some BMCs (e.g. MSI) enumerate exhaustively in their PCIeDevices collection.
|
||||
func isUnidentifiablePCIeDevice(dev models.PCIeDevice) bool {
|
||||
if !isGenericPCIeClassLabel(dev.DeviceClass) {
|
||||
return false
|
||||
}
|
||||
if normalizeRedfishIdentityField(dev.PartNumber) != "" {
|
||||
return false
|
||||
}
|
||||
if normalizeRedfishIdentityField(dev.SerialNumber) != "" {
|
||||
return false
|
||||
}
|
||||
if dev.VendorID > 0 || dev.DeviceID > 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func isGenericPCIeClassLabel(v string) bool {
|
||||
switch strings.ToLower(strings.TrimSpace(v)) {
|
||||
case "", "pcie device", "display", "display controller", "vga", "3d controller", "network", "network controller", "storage", "storage controller", "other", "unknown", "singlefunction", "multifunction", "simulated":
|
||||
|
||||
@@ -1261,7 +1261,13 @@ func (r redfishSnapshotReader) collectPCIeDevices(systemPaths, chassisPaths []st
|
||||
}
|
||||
for _, doc := range memberDocs {
|
||||
functionDocs := r.getLinkedPCIeFunctions(doc)
|
||||
if looksLikeGPU(doc, functionDocs) {
|
||||
continue
|
||||
}
|
||||
dev := parsePCIeDevice(doc, functionDocs)
|
||||
if isUnidentifiablePCIeDevice(dev) {
|
||||
continue
|
||||
}
|
||||
out = append(out, dev)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user