fix: parse Inspur PCIe CPU affinity

This commit is contained in:
Mikhail Chusavitin
2026-09-14 10:48:47 +03:00
parent 9ac38c2914
commit 8794e0adec
6 changed files with 140 additions and 54 deletions
+29 -31
View File
@@ -65,20 +65,15 @@ func ParsePCIeSlotDeviceNames(content []byte) map[int]string {
func parsePCIeRESTJSON(content []byte) (PCIeRESTInfo, bool) {
text := string(content)
startMarker := "RESTful PCIE Device info:"
endMarker := "BMC sdr Info:"
startIdx := strings.Index(text, startMarker)
if startIdx == -1 {
return nil, false
}
endIdx := strings.Index(text[startIdx:], endMarker)
if endIdx == -1 {
endIdx = len(text) - startIdx
}
jsonText := strings.TrimSpace(text[startIdx+len(startMarker) : startIdx+endIdx])
jsonText := strings.TrimSpace(text[startIdx+len(startMarker):])
var info PCIeRESTInfo
if err := json.Unmarshal([]byte(jsonText), &info); err != nil {
if err := json.NewDecoder(strings.NewReader(jsonText)).Decode(&info); err != nil {
return nil, false
}
return info, true
@@ -118,27 +113,8 @@ func ParsePCIeNVMeLocToSlot(content []byte) map[int]int {
// ParsePCIeDevices parses RESTful PCIE Device info from devicefrusdr.log
func ParsePCIeDevices(content []byte) []models.PCIeDevice {
text := string(content)
// Find RESTful PCIE Device info section
startMarker := "RESTful PCIE Device info:"
endMarker := "BMC sdr Info:"
startIdx := strings.Index(text, startMarker)
if startIdx == -1 {
return nil
}
endIdx := strings.Index(text[startIdx:], endMarker)
if endIdx == -1 {
endIdx = len(text) - startIdx
}
jsonText := text[startIdx+len(startMarker) : startIdx+endIdx]
jsonText = strings.TrimSpace(jsonText)
var pcieInfo PCIeRESTInfo
if err := json.Unmarshal([]byte(jsonText), &pcieInfo); err != nil {
pcieInfo, ok := parsePCIeRESTJSON(content)
if !ok {
return nil
}
@@ -156,8 +132,9 @@ func ParsePCIeDevices(content []byte) []models.PCIeDevice {
deviceClass := determineDeviceClass(pcie.DevType, pcie.DevSubtype, pcie.DeviceName)
_, pciDeviceName := pciids.DeviceInfo(pcie.VendorID, pcie.DeviceID)
// Build BDF string in canonical form (bb:dd.f)
bdf := formatBDF(pcie.BusNum, pcie.DevNum, pcie.FuncNum)
// Use the domain-qualified BDF as the canonical slot identity. Keep the
// physical locator as descriptive evidence for affinity parsing.
bdf := fullBDF(pcie.BusNum, pcie.DevNum, pcie.FuncNum)
partNumber := strings.TrimSpace(pcie.PartNum)
if partNumber == "" {
@@ -177,7 +154,8 @@ func ParsePCIeDevices(content []byte) []models.PCIeDevice {
}
device := models.PCIeDevice{
Slot: pcie.Location,
Slot: bdf,
Description: strings.TrimSpace(pcie.Location),
VendorID: pcie.VendorID,
DeviceID: pcie.DeviceID,
BDF: bdf,
@@ -190,6 +168,7 @@ func ParsePCIeDevices(content []byte) []models.PCIeDevice {
PartNumber: partNumber,
SerialNumber: strings.TrimSpace(pcie.SerialNum),
Status: pcieRESTStatus(pcie.Status),
NUMANode: parseInspurCPUAffinity(pcie.Location, pcie.DeviceLocator),
}
devices = append(devices, device)
@@ -198,6 +177,22 @@ func ParsePCIeDevices(content []byte) []models.PCIeDevice {
return devices
}
var inspurCPUAffinityRegex = regexp.MustCompile(`(?i)(?:^|[^a-z0-9])CPU(\d+)(?:[^0-9]|$)`)
func parseInspurCPUAffinity(locations ...string) *int {
for _, location := range locations {
match := inspurCPUAffinityRegex.FindStringSubmatch(strings.TrimSpace(location))
if match == nil {
continue
}
value, err := strconv.Atoi(match[1])
if err == nil {
return &value
}
}
return nil
}
// pcieRESTStatus maps the RESTful PCIE Device info "status" flag (1 = OK) to
// the shared status vocabulary. Only the observed OK case is mapped — the
// meaning of other values isn't confirmed in the source, so it's left
@@ -329,6 +324,9 @@ func enrichPCIeDevice(dst *models.PCIeDevice, src models.PCIeDevice) {
if dst.Present == nil {
dst.Present = src.Present
}
if dst.NUMANode == nil {
dst.NUMANode = src.NUMANode
}
if strings.TrimSpace(dst.Status) == "" {
dst.Status = src.Status
}