From 025d3bf5f4eeb4a9fb54ee691cf881b9b777081f Mon Sep 17 00:00:00 2001 From: Kang Zhang <100667394+kangclzjc@users.noreply.github.com> Date: Fri, 22 Mar 2024 17:37:16 +0800 Subject: [PATCH] apis: add Resctrl API (#1943) Signed-off-by: Zhang Kang --- apis/extension/resctrl.go | 69 ++++++++++++ apis/extension/resctrl_test.go | 188 +++++++++++++++++++++++++++++++++ 2 files changed, 257 insertions(+) create mode 100644 apis/extension/resctrl.go create mode 100644 apis/extension/resctrl_test.go diff --git a/apis/extension/resctrl.go b/apis/extension/resctrl.go new file mode 100644 index 000000000..2645211b7 --- /dev/null +++ b/apis/extension/resctrl.go @@ -0,0 +1,69 @@ +/* +Copyright 2022 The Koordinator Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package extension + +import ( + "encoding/json" +) + +const ( + // AnnotationResctrl describes the resctrl config of pod + AnnotationResctrl = NodeDomainPrefix + "/resctrl" +) + +type Resctrl struct { + L3 map[int]string + MB map[int]string +} + +type ResctrlConfig struct { + LLC LLC `json:"llc,omitempty"` + MB MB `json:"mb,omitempty"` +} + +type LLC struct { + Schemata SchemataConfig `json:"schemata,omitempty"` + SchemataPerCache []SchemataPerCacheConfig `json:"schemataPerCache,omitempty"` +} + +type MB struct { + Schemata SchemataConfig `json:"schemata,omitempty"` + SchemataPerCache []SchemataPerCacheConfig `json:"schemataPerCache,omitempty"` +} + +type SchemataConfig struct { + Percent int `json:"percent,omitempty"` + Range []int `json:"range,omitempty"` +} + +type SchemataPerCacheConfig struct { + CacheID int `json:"cacheID,omitempty"` + SchemataConfig `json:",inline"` +} + +func GetResctrlInfo(annotations map[string]string) (*ResctrlConfig, error) { + res := &ResctrlConfig{} + data, ok := annotations[AnnotationResctrl] + if !ok { + return res, nil + } + err := json.Unmarshal([]byte(data), &res) + if err != nil { + return nil, err + } + return res, nil +} diff --git a/apis/extension/resctrl_test.go b/apis/extension/resctrl_test.go new file mode 100644 index 000000000..e176f0bdf --- /dev/null +++ b/apis/extension/resctrl_test.go @@ -0,0 +1,188 @@ +/* +Copyright 2022 The Koordinator Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package extension + +import ( + "reflect" + "testing" +) + +func TestGetResctrlInfo(t *testing.T) { + type args struct { + annotation map[string]string + } + + tests := []struct { + name string + args args + want *ResctrlConfig + wantErr bool + }{ + { + name: "only MB parse", + args: args{ + annotation: map[string]string{ + AnnotationResctrl: `{ + "mb": { + "schemata": { + "percent": 35 + }, + "schemataPerCache": [ + { + "cacheid": 0, + "percent": 80 + } + ] + } + }`, + }, + }, + want: &ResctrlConfig{ + MB: MB{ + Schemata: SchemataConfig{ + Percent: 35, + Range: nil, + }, + SchemataPerCache: []SchemataPerCacheConfig{{ + CacheID: 0, + SchemataConfig: SchemataConfig{ + Percent: 80, + Range: nil, + }, + }}, + }, + }, + }, + { + name: "only LLC parse", + args: args{ + annotation: map[string]string{ + AnnotationResctrl: ` + { + "llc": { + "schemata": { + "range": [20,80] + }, + "schemataPerCache": [ + { + "cacheid": 0, + "range": [20,30] + } + ] + } + }`, + }, + }, + want: &ResctrlConfig{ + LLC: LLC{ + Schemata: SchemataConfig{ + Percent: 0, + Range: []int{20, 80}, + }, + SchemataPerCache: []SchemataPerCacheConfig{{ + CacheID: 0, + SchemataConfig: SchemataConfig{ + Percent: 0, + Range: []int{20, 30}, + }, + }}, + }, + }, + }, + { + name: "MB and LLC parse", + args: args{ + annotation: map[string]string{ + AnnotationResctrl: ` + { + "mb": { + "schemata": { + "percent": 35 + }, + "schemataPerCache": [ + { + "cacheid": 0, + "percent": 80 + } + ] + }, + "llc": { + "schemata": { + "range": [20,80] + }, + "schemataPerCache": [ + { + "cacheid": 0, + "range": [20,30] + } + ] + } + }`, + }, + }, + want: &ResctrlConfig{ + LLC: LLC{ + Schemata: SchemataConfig{ + Percent: 0, + Range: []int{20, 80}, + }, + SchemataPerCache: []SchemataPerCacheConfig{{ + CacheID: 0, + SchemataConfig: SchemataConfig{ + Percent: 0, + Range: []int{20, 30}, + }, + }}, + }, + MB: MB{ + Schemata: SchemataConfig{ + Percent: 35, + Range: nil, + }, + SchemataPerCache: []SchemataPerCacheConfig{{ + CacheID: 0, + SchemataConfig: SchemataConfig{ + Percent: 80, + Range: nil, + }, + }}, + }, + }, + }, + { + name: "parse error", + args: args{ + annotation: map[string]string{ + AnnotationResctrl: `test`, + }, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GetResctrlInfo(tt.args.annotation) + if (err != nil) != tt.wantErr { + t.Errorf("GetResctrlInfo() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetResctrlInfo() got = %v, want %v", got, tt.want) + } + }) + } +}