diff --git a/pkg/node/node.go b/pkg/node/node.go index 4b98fd1c7d..d7e14ce2e8 100644 --- a/pkg/node/node.go +++ b/pkg/node/node.go @@ -34,6 +34,7 @@ import ( const ( cpuModelDataPath = "/var/lib/kepler/data/cpus.yaml" cpuPmuNamePath = "/sys/devices/cpu/caps/pmu_name" + unknownCPUArch = "unknown" ) type nodeInfo struct { @@ -51,10 +52,10 @@ type Node interface { } type cpuModelData struct { - uarch string `yaml:"uarch"` - family string `yaml:"family"` - model string `yaml:"model"` - stepping string `yaml:"stepping"` + Uarch string `yaml:"uarch"` + Family string `yaml:"family"` + Model string `yaml:"model"` + Stepping string `yaml:"stepping"` } type cpuInfo struct { @@ -121,7 +122,7 @@ func cpuArch() string { return arch } else { klog.Errorf("getCPUArch failure: %s", err) - return "unknown" + return unknownCPUArch } } @@ -215,32 +216,27 @@ func readCPUModelData() ([]byte, error) { return os.ReadFile("./data/cpus.yaml") } -func cpuMicroArchitecture(family, model, stepping string) (string, error) { - yamlBytes, err := readCPUModelData() - if err != nil { - klog.Errorf("failed to read cpus.yaml: %v", err) - return "", err - } +func cpuMicroArchitectureFromModel(yamlBytes []byte, family, model, stepping string) (string, error) { cpus := &cpuInfo{ cpusInfo: []cpuModelData{}, } - err = yaml.Unmarshal(yamlBytes, &cpus.cpusInfo) + err := yaml.Unmarshal(yamlBytes, &cpus.cpusInfo) if err != nil { klog.Errorf("failed to parse cpus.yaml: %v", err) return "", err } for _, info := range cpus.cpusInfo { - if info.family == family { + if info.Family == family { var reModel *regexp.Regexp - reModel, err = regexp.Compile(info.model) + reModel, err = regexp.Compile(info.Model) if err != nil { return "", err } if reModel.FindString(model) == model { - if info.stepping != "" { + if info.Stepping != "" { var reStepping *regexp.Regexp - reStepping, err = regexp.Compile(info.stepping) + reStepping, err = regexp.Compile(info.Stepping) if err != nil { return "", err } @@ -248,11 +244,24 @@ func cpuMicroArchitecture(family, model, stepping string) (string, error) { continue } } - return info.uarch, nil + return info.Uarch, nil } } } klog.V(3).Infof("CPU match not found for family %s, model %s, stepping %s. Use pmu_name as uarch.", family, model, stepping) + return "unknown", fmt.Errorf("CPU match not found") +} + +func cpuMicroArchitecture(family, model, stepping string) (string, error) { + yamlBytes, err := readCPUModelData() + if err != nil { + klog.Errorf("failed to read cpus.yaml: %v", err) + return "", err + } + arch, err := cpuMicroArchitectureFromModel(yamlBytes, family, model, stepping) + if err == nil { + return arch, nil + } return cpuPmuName() } @@ -262,7 +271,7 @@ func cpuPmuName() (string, error) { klog.V(3).Infoln(err) return "", err } - return string(data), nil + return strings.TrimSpace(string(data)), nil } func getCPUArchitecture() (string, error) { diff --git a/pkg/node/node_test.go b/pkg/node/node_test.go new file mode 100644 index 0000000000..082467a539 --- /dev/null +++ b/pkg/node/node_test.go @@ -0,0 +1,53 @@ +package node + +import ( + "strings" + "testing" +) + +func TestCpuMicroArchitecture(t *testing.T) { + // Mock data for testing + mockData := ` +- uarch: "Skylake" + family: "6" + model: "85" + stepping: "4" +- uarch: "Willow Cove" + family: "6" + model: "(140|141)" + stepping: "4" +- uarch: Coffee Lake + family: 6 + model: (142|158) + stepping: (10|11|12|13) +- uarch: "Broadwell" + family: "6" + model: "61" + stepping: "" +` + + tests := []struct { + family string + model string + stepping string + expected string + }{ + {"6", "85", "4", "Skylake"}, + {"6", "140", "4", "Willow Cove"}, + {"6", "141", "4", "Willow Cove"}, + {"6", "142", "10", "Coffee Lake"}, + {"6", "158", "13", "Coffee Lake"}, + {"6", "61", "3", "Broadwell"}, + {"6", "99", "1", unknownCPUArch}, // No match case + } + + for _, test := range tests { + uarch, err := cpuMicroArchitectureFromModel([]byte(mockData), test.family, test.model, test.stepping) + if err != nil && test.expected != "unknown" { + t.Errorf("Unexpected error: %v", err) + } + if !strings.Contains(uarch, test.expected) { + t.Errorf("Expected %s, got %s", test.expected, uarch) + } + } +}