fix(redfish): recover MSI NIC serials from PCIe functions

This commit is contained in:
Mikhail Chusavitin
2026-04-01 15:48:47 +03:00
parent c47c34fd11
commit 93ce676f04
2 changed files with 113 additions and 15 deletions

View File

@@ -2810,13 +2810,6 @@ func shouldCrawlPath(path string) bool {
if isAllowedNVSwitchFabricPath(normalized) {
return true
}
if strings.Contains(normalized, "/Chassis/") &&
strings.Contains(normalized, "/PCIeDevices/") &&
strings.Contains(normalized, "/PCIeFunctions/") {
// Chassis-level PCIeFunctions links are frequently noisy/slow on some BMCs
// and duplicate data we already collect from PCIe devices/functions elsewhere.
return false
}
if strings.Contains(normalized, "/Memory/") {
after := strings.SplitN(normalized, "/Memory/", 2)
if len(after) == 2 && strings.Count(after[1], "/") >= 1 {
@@ -3867,23 +3860,31 @@ func parseNIC(doc map[string]interface{}) models.NetworkAdapter {
var linkSpeed string
var maxLinkSpeed string
if controllers, ok := doc["Controllers"].([]interface{}); ok && len(controllers) > 0 {
if ctrl, ok := controllers[0].(map[string]interface{}); ok {
totalPortCount := 0
for _, ctrlAny := range controllers {
ctrl, ok := ctrlAny.(map[string]interface{})
if !ok {
continue
}
ctrlLocation := redfishLocationLabel(ctrl["Location"])
location = firstNonEmpty(location, ctrlLocation)
if isWeakRedfishNICSlotLabel(slot) {
slot = firstNonEmpty(ctrlLocation, slot)
}
firmware = asString(ctrl["FirmwarePackageVersion"])
if caps, ok := ctrl["ControllerCapabilities"].(map[string]interface{}); ok {
portCount = sanitizeNetworkPortCount(asInt(caps["NetworkPortCount"]))
if normalizeRedfishIdentityField(firmware) == "" {
firmware = findFirstNormalizedStringByKeys(ctrl, "FirmwarePackageVersion", "FirmwareVersion")
}
if pcieIf, ok := ctrl["PCIeInterface"].(map[string]interface{}); ok {
if caps, ok := ctrl["ControllerCapabilities"].(map[string]interface{}); ok {
totalPortCount += sanitizeNetworkPortCount(asInt(caps["NetworkPortCount"]))
}
if pcieIf, ok := ctrl["PCIeInterface"].(map[string]interface{}); ok && linkWidth == 0 && maxLinkWidth == 0 && linkSpeed == "" && maxLinkSpeed == "" {
linkWidth = asInt(pcieIf["LanesInUse"])
maxLinkWidth = asInt(pcieIf["MaxLanes"])
linkSpeed = firstNonEmpty(asString(pcieIf["PCIeType"]), asString(pcieIf["CurrentLinkSpeedGTs"]), asString(pcieIf["CurrentLinkSpeed"]))
maxLinkSpeed = firstNonEmpty(asString(pcieIf["MaxPCIeType"]), asString(pcieIf["MaxLinkSpeedGTs"]), asString(pcieIf["MaxLinkSpeed"]))
}
}
portCount = sanitizeNetworkPortCount(totalPortCount)
}
return models.NetworkAdapter{
@@ -3913,10 +3914,14 @@ func isWeakRedfishNICSlotLabel(slot string) bool {
if slot == "" {
return true
}
lower := strings.ToLower(slot)
if isNumericString(slot) {
return true
}
if strings.EqualFold(slot, "nic") || strings.HasPrefix(strings.ToLower(slot), "nic") && !strings.Contains(strings.ToLower(slot), "slot") {
if strings.EqualFold(slot, "nic") || strings.HasPrefix(lower, "nic") && !strings.Contains(lower, "slot") {
return true
}
if strings.HasPrefix(lower, "devtype") {
return true
}
return false
@@ -3956,6 +3961,16 @@ func enrichNICFromPCIe(nic *models.NetworkAdapter, pcieDoc map[string]interface{
if nic == nil {
return
}
pcieSlot := redfishLocationLabel(pcieDoc["Slot"])
if pcieSlot == "" {
pcieSlot = redfishLocationLabel(pcieDoc["Location"])
}
if isWeakRedfishNICSlotLabel(nic.Slot) && pcieSlot != "" {
nic.Slot = pcieSlot
}
if strings.TrimSpace(nic.Location) == "" && pcieSlot != "" {
nic.Location = pcieSlot
}
if strings.TrimSpace(nic.BDF) == "" {
nic.BDF = firstNonEmpty(asString(pcieDoc["BDF"]), buildBDFfromOemPublic(pcieDoc))
}
@@ -3977,6 +3992,15 @@ func enrichNICFromPCIe(nic *models.NetworkAdapter, pcieDoc map[string]interface{
if strings.TrimSpace(nic.MaxLinkSpeed) == "" {
nic.MaxLinkSpeed = firstNonEmpty(asString(pcieDoc["MaxLinkSpeedGTs"]), asString(pcieDoc["MaxLinkSpeed"]))
}
if normalizeRedfishIdentityField(nic.SerialNumber) == "" {
nic.SerialNumber = findFirstNormalizedStringByKeys(pcieDoc, "SerialNumber")
}
if normalizeRedfishIdentityField(nic.PartNumber) == "" {
nic.PartNumber = findFirstNormalizedStringByKeys(pcieDoc, "PartNumber", "ProductPartNumber")
}
if normalizeRedfishIdentityField(nic.Firmware) == "" {
nic.Firmware = findFirstNormalizedStringByKeys(pcieDoc, "FirmwareVersion", "FirmwarePackageVersion")
}
for _, fn := range functionDocs {
if strings.TrimSpace(nic.BDF) == "" {
nic.BDF = sanitizeRedfishBDF(asString(fn["FunctionId"]))
@@ -3999,6 +4023,15 @@ func enrichNICFromPCIe(nic *models.NetworkAdapter, pcieDoc map[string]interface{
if strings.TrimSpace(nic.MaxLinkSpeed) == "" {
nic.MaxLinkSpeed = firstNonEmpty(asString(fn["MaxLinkSpeedGTs"]), asString(fn["MaxLinkSpeed"]))
}
if normalizeRedfishIdentityField(nic.SerialNumber) == "" {
nic.SerialNumber = findFirstNormalizedStringByKeys(fn, "SerialNumber")
}
if normalizeRedfishIdentityField(nic.PartNumber) == "" {
nic.PartNumber = findFirstNormalizedStringByKeys(fn, "PartNumber", "ProductPartNumber")
}
if normalizeRedfishIdentityField(nic.Firmware) == "" {
nic.Firmware = findFirstNormalizedStringByKeys(fn, "FirmwareVersion", "FirmwarePackageVersion")
}
}
if strings.TrimSpace(nic.Vendor) == "" {
nic.Vendor = pciids.VendorName(nic.VendorID)