From 0e78eba40eb8c6f925e3752dcde0eb61fa73dac3 Mon Sep 17 00:00:00 2001 From: PiotrProkop Date: Thu, 6 Apr 2023 09:53:25 +0200 Subject: [PATCH] Advertise RDT L3 num_closid Signed-off-by: PiotrProkop --- docs/usage/customization-guide.md | 3 +- source/cpu/cpu.go | 10 ++++-- source/cpu/rdt_amd64.go | 60 ++++++++++++++++++++++++++----- source/cpu/rdt_stub.go | 4 +-- 4 files changed, 62 insertions(+), 15 deletions(-) diff --git a/docs/usage/customization-guide.md b/docs/usage/customization-guide.md index 6ca45bed5e..192467360e 100644 --- a/docs/usage/customization-guide.md +++ b/docs/usage/customization-guide.md @@ -601,8 +601,9 @@ The following features are available for matching: | | | **`status`** | string | Status of the driver, possible values are 'active' and 'passive' | | | **`turbo`** | bool | 'true' if turbo frequencies are enabled, otherwise 'false' | | | **`scaling`** | string | Active scaling_governor, possible values are 'powersave' or 'performance'. -| **`cpu.rdt`** | flag | | | Intel RDT capabilities supported by the system +| **`cpu.rdt`** | attribute | | | Intel RDT capabilities supported by the system | | | **``** | | RDT capability is supported, see [RDT flags](#intel-rdt-flags) for details +| | | **`RDTL3CA_NUM_CLOSID`** | int | The number or available CLOSID (Class of service ID) for Intel L3 Cache Allocation Technology | **`cpu.security`** | attribute | | | Features related to security and trusted execution environments | | | **`sgx.enabled`** | bool | `true` if Intel SGX (Software Guard Extensions) has been enabled, otherwise does not exist | | | **`se.enabled`** | bool | `true` if IBM Secure Execution for Linux is available and has been enabled, otherwise does not exist diff --git a/source/cpu/cpu.go b/source/cpu/cpu.go index 6341169025..33ffe3096a 100644 --- a/source/cpu/cpu.go +++ b/source/cpu/cpu.go @@ -164,8 +164,12 @@ func (s *cpuSource) GetLabels() (source.FeatureLabels, error) { } // RDT - for k := range features.Flags[RdtFeature].Elements { - labels["rdt."+k] = true + for k, v := range features.Attributes[RdtFeature].Elements { + if k == "RDTL3CA_NUM_CLOSID" { + continue + } + + labels["rdt."+k] = v } // Security @@ -227,7 +231,7 @@ func (s *cpuSource) Discover() error { s.features.Attributes[PstateFeature] = nfdv1alpha1.NewAttributeFeatures(pstate) // Detect RDT features - s.features.Flags[RdtFeature] = nfdv1alpha1.NewFlagFeatures(discoverRDT()...) + s.features.Attributes[RdtFeature] = nfdv1alpha1.NewAttributeFeatures(discoverRDT()) // Detect available guest protection(SGX,TDX,SEV) features s.features.Attributes[SecurityFeature] = nfdv1alpha1.NewAttributeFeatures(discoverSecurity()) diff --git a/source/cpu/rdt_amd64.go b/source/cpu/rdt_amd64.go index 07d110288b..30143a37c6 100644 --- a/source/cpu/rdt_amd64.go +++ b/source/cpu/rdt_amd64.go @@ -20,6 +20,14 @@ limitations under the License. package cpu import ( + "bytes" + "os" + "path/filepath" + "strconv" + + "github.com/opencontainers/runc/libcontainer/intelrdt" + "k8s.io/klog/v2" + "sigs.k8s.io/node-feature-discovery/pkg/cpuid" ) @@ -44,8 +52,8 @@ const ( RDT_ALLOCATION_EBX_MEMORY_BANDWIDTH_ALLOCATION = 1 << 3 ) -func discoverRDT() []string { - features := []string{} +func discoverRDT() map[string]string { + attributes := map[string]string{} // Read cpuid information extFeatures := cpuid.Cpuid(LEAF_EXT_FEATURE_FLAGS, 0) @@ -57,16 +65,16 @@ func discoverRDT() []string { if extFeatures.EBX&EXT_FEATURE_FLAGS_EBX_RDT_M != 0 { if rdtMonitoring.EDX&RDT_MONITORING_EDX_L3_MONITORING != 0 { // Monitoring is supported - features = append(features, "RDTMON") + attributes["RDTMON"] = "true" // Cache Monitoring Technology (L3 occupancy monitoring) if rdtL3Monitoring.EDX&RDT_MONITORING_SUBLEAF_L3_EDX_L3_OCCUPANCY_MONITORING != 0 { - features = append(features, "RDTCMT") + attributes["RDTCMT"] = "true" } // Memore Bandwidth Monitoring (L3 local&total bandwidth monitoring) if rdtL3Monitoring.EDX&RDT_MONITORING_SUBLEAF_L3_EDX_L3_TOTAL_BANDWIDTH_MONITORING != 0 && rdtL3Monitoring.EDX&RDT_MONITORING_SUBLEAF_L3_EDX_L3_LOCAL_BANDWIDTH_MONITORING != 0 { - features = append(features, "RDTMBM") + attributes["RDTMBM"] = "true" } } } @@ -75,17 +83,51 @@ func discoverRDT() []string { if extFeatures.EBX&EXT_FEATURE_FLAGS_EBX_RDT_A != 0 { // L3 Cache Allocation if rdtAllocation.EBX&RDT_ALLOCATION_EBX_L3_CACHE_ALLOCATION != 0 { - features = append(features, "RDTL3CA") + attributes["RDTL3CA"] = "true" + numClosID := getNumClosID("L3") + if numClosID > -1 { + attributes["RDTL3CA_NUM_CLOSID"] = strconv.FormatInt(int64(numClosID), 10) + } } // L2 Cache Allocation if rdtAllocation.EBX&RDT_ALLOCATION_EBX_L2_CACHE_ALLOCATION != 0 { - features = append(features, "RDTL2CA") + attributes["RDTL2CA"] = "true" } // Memory Bandwidth Allocation if rdtAllocation.EBX&RDT_ALLOCATION_EBX_MEMORY_BANDWIDTH_ALLOCATION != 0 { - features = append(features, "RDTMBA") + attributes["RDTMBA"] = "true" } } - return features + return attributes +} + +func getNumClosID(level string) int64 { + resctrlRootDir, err := intelrdt.Root() + if err != nil { + klog.V(4).ErrorS(err, "can't find resctrl filesystem") + return -1 + } + + closidFile := filepath.Join(resctrlRootDir, "info", level, "num_closids") + + if _, err := os.Stat(closidFile); err != nil { + klog.V(4).ErrorS(err, "failed to stat file", "fileName", closidFile) + return -1 + } + + closidsBytes, err := os.ReadFile(filepath.Join(resctrlRootDir, "info", level, "num_closids")) + if err != nil { + klog.V(4).ErrorS(err, "failed to read file", "fileName", closidFile) + return -1 + } + + numClosIDs, err := strconv.ParseInt(string(bytes.TrimSpace(closidsBytes)), 10, 64) + if err != nil { + klog.V(4).ErrorS(err, "failed to ParseInt", "num_closids", string(bytes.TrimSpace(closidsBytes))) + return -1 + } + + // subtract 1 for default control group + return numClosIDs - 1 } diff --git a/source/cpu/rdt_stub.go b/source/cpu/rdt_stub.go index addad4c001..d1482dbe87 100644 --- a/source/cpu/rdt_stub.go +++ b/source/cpu/rdt_stub.go @@ -19,6 +19,6 @@ limitations under the License. package cpu -func discoverRDT() []string { - return []string{} +func discoverRDT() map[string]string { + return map[string]string{} }