Unverified Commit 3b4473f4 authored by Kubernetes Prow Robot's avatar Kubernetes Prow Robot Committed by GitHub

Merge pull request #72913 from nolancon/topology-manager-socket-mask

Add Socket Mask for Topology Manager
parents 3c3c1b11 b7f6b8f8
...@@ -166,6 +166,7 @@ filegroup( ...@@ -166,6 +166,7 @@ filegroup(
"//pkg/kubelet/cm/cpumanager:all-srcs", "//pkg/kubelet/cm/cpumanager:all-srcs",
"//pkg/kubelet/cm/cpuset:all-srcs", "//pkg/kubelet/cm/cpuset:all-srcs",
"//pkg/kubelet/cm/devicemanager:all-srcs", "//pkg/kubelet/cm/devicemanager:all-srcs",
"//pkg/kubelet/cm/topologymanager/socketmask:all-srcs",
"//pkg/kubelet/cm/util:all-srcs", "//pkg/kubelet/cm/util:all-srcs",
], ],
tags = ["automanaged"], tags = ["automanaged"],
......
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = ["socketmask.go"],
importpath = "k8s.io/kubernetes/pkg/kubelet/cm/topologymanager/socketmask",
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_test",
srcs = ["socketmask_test.go"],
embed = [":go_default_library"],
)
/*
Copyright 2019 The Kubernetes 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 socketmask
import (
"fmt"
)
//SocketMask interface allows hint providers to create SocketMasks for TopologyHints
type SocketMask interface {
Add(sockets ...int) error
Remove(sockets ...int) error
And(masks ...SocketMask)
Or(masks ...SocketMask)
Clear()
Fill()
IsEqual(mask SocketMask) bool
IsEmpty() bool
IsSet(socket int) bool
String() string
Count() int
GetSockets() []int
}
type socketMask uint64
//NewSocketMask creates a new SocketMask
func NewSocketMask(sockets ...int) (SocketMask, error) {
s := socketMask(0)
err := (&s).Add(sockets...)
if err != nil {
return nil, err
}
return &s, nil
}
//Add adds the sockets with topology affinity to the SocketMask
func (s *socketMask) Add(sockets ...int) error {
mask := *s
for _, i := range sockets {
if i < 0 || i >= 64 {
return fmt.Errorf("socket number must be in range 0-63")
}
mask |= 1 << uint64(i)
}
*s = mask
return nil
}
//Remove removes specified sockets from SocketMask
func (s *socketMask) Remove(sockets ...int) error {
mask := *s
for _, i := range sockets {
if i < 0 || i >= 64 {
return fmt.Errorf("socket number must be in range 0-63")
}
mask &^= 1 << uint64(i)
}
*s = mask
return nil
}
//And performs and operation on all bits in masks
func (s *socketMask) And(masks ...SocketMask) {
for _, m := range masks {
*s &= *m.(*socketMask)
}
}
//Or performs or operation on all bits in masks
func (s *socketMask) Or(masks ...SocketMask) {
for _, m := range masks {
*s |= *m.(*socketMask)
}
}
//Clear resets all bits in mask to zero
func (s *socketMask) Clear() {
*s = 0
}
//Fill sets all bits in mask to one
func (s *socketMask) Fill() {
*s = socketMask(^uint64(0))
}
//IsEmpty checks mask to see if all bits are zero
func (s *socketMask) IsEmpty() bool {
return *s == 0
}
//IsSet checks socket in mask to see if bit is set to one
func (s *socketMask) IsSet(socket int) bool {
if socket < 0 || socket >= 64 {
return false
}
return (*s & (1 << uint64(socket))) > 0
}
//IsEqual checks if masks are equal
func (s *socketMask) IsEqual(mask SocketMask) bool {
return *s == *mask.(*socketMask)
}
//String converts mask to string
func (s *socketMask) String() string {
str := ""
for i := uint64(0); i < 64; i++ {
if (*s & (1 << i)) > 0 {
str += "1"
} else {
str += "0"
}
}
return str
}
//Count counts number of bits in mask set to one
func (s *socketMask) Count() int {
count := 0
for i := uint64(0); i < 64; i++ {
if (*s & (1 << i)) > 0 {
count++
}
}
return count
}
//GetSockets returns each socket number with bits set to one
func (s *socketMask) GetSockets() []int {
var sockets []int
for i := uint64(0); i < 64; i++ {
if (*s & (1 << i)) > 0 {
sockets = append(sockets, int(i))
}
}
return sockets
}
/*
Copyright 2019 The Kubernetes 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 socketmask
import (
"reflect"
"testing"
)
func TestNewSocketMask(t *testing.T) {
tcases := []struct {
name string
socket int
expectedMask string
}{
{
name: "New SocketMask with socket 0 set",
socket: int(0),
expectedMask: "1000000000000000000000000000000000000000000000000000000000000000",
},
}
for _, tc := range tcases {
sm, _ := NewSocketMask(0)
if sm.String() != tc.expectedMask {
t.Errorf("Expected mask to be %v, got %v", tc.expectedMask, sm)
}
}
}
func TestAdd(t *testing.T) {
tcases := []struct {
name string
firstSocket int
secondSocket int
expectedMask string
}{
{
name: "Reset bit 1 SocketMask to 0",
firstSocket: 0,
secondSocket: 1,
expectedMask: "1100000000000000000000000000000000000000000000000000000000000000",
},
}
for _, tc := range tcases {
mask, _ := NewSocketMask()
mask.Add(tc.firstSocket, tc.secondSocket)
if mask.String() != tc.expectedMask {
t.Errorf("Expected mask to be %v, got %v", tc.expectedMask, mask)
}
}
}
func TestRemove(t *testing.T) {
tcases := []struct {
name string
firstSocketSet int
secondSocketSet int
firstSocketRemove int
expectedMask string
}{
{
name: "Reset bit 1 SocketMask to 0",
firstSocketSet: 0,
secondSocketSet: 1,
firstSocketRemove: 0,
expectedMask: "0100000000000000000000000000000000000000000000000000000000000000",
},
}
for _, tc := range tcases {
mask, _ := NewSocketMask(tc.firstSocketSet, tc.secondSocketSet)
mask.Remove(tc.firstSocketRemove)
if mask.String() != tc.expectedMask {
t.Errorf("Expected mask to be %v, got %v", tc.expectedMask, mask)
}
}
}
func TestAnd(t *testing.T) {
tcases := []struct {
name string
firstMaskBit int
secondMaskBit int
andMask string
}{
{
name: "And socket masks",
firstMaskBit: 0,
secondMaskBit: 0,
andMask: "1000000000000000000000000000000000000000000000000000000000000000",
},
}
for _, tc := range tcases {
firstMask, _ := NewSocketMask(tc.firstMaskBit)
secondMask, _ := NewSocketMask(tc.secondMaskBit)
firstMask.And(secondMask)
if firstMask.String() != string(tc.andMask) {
t.Errorf("Expected mask to be %v, got %v", tc.andMask, firstMask)
}
}
}
func TestOr(t *testing.T) {
tcases := []struct {
name string
firstMaskBit int
secondMaskBit int
orMask string
}{
{
name: "Or socket masks",
firstMaskBit: int(0),
secondMaskBit: int(1),
orMask: "1100000000000000000000000000000000000000000000000000000000000000",
},
}
for _, tc := range tcases {
firstMask, _ := NewSocketMask(tc.firstMaskBit)
secondMask, _ := NewSocketMask(tc.secondMaskBit)
firstMask.Or(secondMask)
if firstMask.String() != string(tc.orMask) {
t.Errorf("Expected mask to be %v, got %v", tc.orMask, firstMask)
}
}
}
func TestClear(t *testing.T) {
tcases := []struct {
name string
firstBit int
secondBit int
clearedMask string
}{
{
name: "Clear socket masks",
firstBit: int(0),
secondBit: int(1),
clearedMask: "0000000000000000000000000000000000000000000000000000000000000000",
},
}
for _, tc := range tcases {
mask, _ := NewSocketMask(tc.firstBit, tc.secondBit)
mask.Clear()
if mask.String() != string(tc.clearedMask) {
t.Errorf("Expected mask to be %v, got %v", tc.clearedMask, mask)
}
}
}
func TestFill(t *testing.T) {
tcases := []struct {
name string
filledMask string
}{
{
name: "Fill socket masks",
filledMask: "1111111111111111111111111111111111111111111111111111111111111111",
},
}
for _, tc := range tcases {
mask, _ := NewSocketMask()
mask.Fill()
if mask.String() != string(tc.filledMask) {
t.Errorf("Expected mask to be %v, got %v", tc.filledMask, mask)
}
}
}
func TestIsEmpty(t *testing.T) {
tcases := []struct {
name string
maskBit int
expectedEmpty bool
}{
{
name: "Check if mask is empty",
maskBit: int(0),
expectedEmpty: false,
},
}
for _, tc := range tcases {
mask, _ := NewSocketMask(tc.maskBit)
empty := mask.IsEmpty()
if empty {
t.Errorf("Expected value to be %v, got %v", tc.expectedEmpty, empty)
}
}
}
func TestIsSet(t *testing.T) {
tcases := []struct {
name string
maskBit int
expectedSet bool
}{
{
name: "Check if mask bit is set",
maskBit: int(0),
expectedSet: true,
},
}
for _, tc := range tcases {
mask, _ := NewSocketMask(tc.maskBit)
set := mask.IsSet(tc.maskBit)
if !set {
t.Errorf("Expected value to be %v, got %v", tc.expectedSet, set)
}
}
}
func TestIsEqual(t *testing.T) {
tcases := []struct {
name string
firstMaskBit int
secondMaskBit int
isEqual bool
}{
{
name: "And socket masks",
firstMaskBit: int(0),
secondMaskBit: int(0),
isEqual: true,
},
}
for _, tc := range tcases {
firstMask, _ := NewSocketMask(tc.firstMaskBit)
secondMask, _ := NewSocketMask(tc.secondMaskBit)
isEqual := firstMask.IsEqual(secondMask)
if !isEqual {
t.Errorf("Expected mask to be %v, got %v", tc.isEqual, isEqual)
}
}
}
func TestCount(t *testing.T) {
tcases := []struct {
name string
maskBit int
expectedCount int
}{
{
name: "Count number of bits set in full mask",
maskBit: 0,
expectedCount: 1,
},
}
for _, tc := range tcases {
mask, _ := NewSocketMask(tc.maskBit)
count := mask.Count()
if count != tc.expectedCount {
t.Errorf("Expected value to be %v, got %v", tc.expectedCount, count)
}
}
}
func TestGetSockets(t *testing.T) {
tcases := []struct {
name string
firstSocket int
secondSocket int
expectedSockets []int
}{
{
name: "Get number of each socket which has been set",
firstSocket: 0,
secondSocket: 1,
expectedSockets: []int{0, 1},
},
}
for _, tc := range tcases {
mask, _ := NewSocketMask(tc.firstSocket, tc.secondSocket)
sockets := mask.GetSockets()
if !reflect.DeepEqual(sockets, tc.expectedSockets) {
t.Errorf("Expected value to be %v, got %v", tc.expectedSockets, sockets)
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment