mirror of
https://github.com/kubernetes-sigs/node-feature-discovery.git
synced 2024-12-14 11:57:51 +00:00
Implement RDT detection in go
Get rid of the dependency on intel-cmt-cat library and rdt helper binaries written in C. Significantly simplifies the build procedure. Implements minimal support (in assembler) for getting the raw data from the CPUID instruction. Also, implement a stub so that the code works on other architectures than amd64, too.
This commit is contained in:
parent
91b0714ab7
commit
e866b6ee1c
12 changed files with 151 additions and 238 deletions
17
Dockerfile
17
Dockerfile
|
@ -5,22 +5,8 @@ ADD . /go/src/sigs.k8s.io/node-feature-discovery
|
|||
|
||||
WORKDIR /go/src/sigs.k8s.io/node-feature-discovery
|
||||
|
||||
ENV CMT_CAT_VERSION="v1.2.0"
|
||||
|
||||
ARG NFD_VERSION
|
||||
|
||||
RUN case $(dpkg --print-architecture) in \
|
||||
arm64) \
|
||||
echo "skip rdt on Arm64 platform" \
|
||||
;; \
|
||||
*) \
|
||||
git clone --depth 1 -b $CMT_CAT_VERSION https://github.com/intel/intel-cmt-cat.git && \
|
||||
make -C intel-cmt-cat/lib install && \
|
||||
make -C rdt-discovery && \
|
||||
make -C rdt-discovery install \
|
||||
;; \
|
||||
esac
|
||||
|
||||
RUN go get github.com/Masterminds/glide
|
||||
RUN glide install --strip-vendor
|
||||
RUN go install \
|
||||
|
@ -34,10 +20,7 @@ RUN go test .
|
|||
# Create production image for running node feature discovery
|
||||
FROM debian:stretch-slim
|
||||
|
||||
COPY --from=builder /usr/local/bin /usr/local/bin
|
||||
COPY --from=builder /usr/local/lib /usr/local/lib
|
||||
COPY --from=builder /etc/kubernetes/node-feature-discovery /etc/kubernetes/node-feature-discovery
|
||||
RUN ldconfig
|
||||
COPY --from=builder /go/bin/node-feature-discovery /usr/bin/node-feature-discovery
|
||||
|
||||
ENTRYPOINT ["/usr/bin/node-feature-discovery"]
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
CC=gcc
|
||||
LIBDIR=/usr/local/lib
|
||||
INCDIR=../intel-cmt-cat/lib/
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
BINDIR ?= $(PREFIX)/bin
|
||||
|
||||
LDFLAGS=-L$(LIBDIR)
|
||||
LDLIBS=-lpqos
|
||||
CFLAGS=-I$(INCDIR)
|
||||
|
||||
BINARIES = mon-discovery \
|
||||
mon-cmt-discovery \
|
||||
mon-mbm-discovery \
|
||||
l3-alloc-discovery \
|
||||
l2-alloc-discovery \
|
||||
mem-bandwidth-alloc-discovery
|
||||
|
||||
default:
|
||||
$(MAKE) all
|
||||
all:
|
||||
$(CC) $(CFLAGS) -o mon-discovery monitoring-discovery.c $(LDFLAGS) $(LDLIBS)
|
||||
$(CC) $(CFLAGS) -o mon-cmt-discovery monitoring-cmt-discovery.c $(LDFLAGS) $(LDLIBS)
|
||||
$(CC) $(CFLAGS) -o mon-mbm-discovery monitoring-mbm-discovery.c $(LDFLAGS) $(LDLIBS)
|
||||
$(CC) $(CFLAGS) -o l3-alloc-discovery l3-allocation-discovery.c $(LDFLAGS) $(LDLIBS)
|
||||
$(CC) $(CFLAGS) -o l2-alloc-discovery l2-allocation-discovery.c $(LDFLAGS) $(LDLIBS)
|
||||
$(CC) $(CFLAGS) -o mem-bandwidth-alloc-discovery mem-bandwidth-allocation-discovery.c $(LDFLAGS) $(LDLIBS)
|
||||
|
||||
install:
|
||||
install -d $(BINDIR)
|
||||
install -t $(BINDIR) $(BINARIES)
|
|
@ -1,22 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "machine.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
struct cpuid_out res;
|
||||
|
||||
// Logic below from https://github.com/intel/intel-cmt-cat/blob/master/lib/cap.c
|
||||
lcpuid(0x7, 0x0, &res);
|
||||
if (!(res.ebx & (1 << 15))) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
else {
|
||||
lcpuid(0x10, 0x0, &res);
|
||||
if (!(res.ebx & (1 << 2))) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
// If we are here, then L2 cache allocation capability is available.
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "machine.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
struct cpuid_out res;
|
||||
|
||||
// Logic below from https://github.com/intel/intel-cmt-cat/blob/master/lib/cap.c
|
||||
// TODO(balajismaniam): Implement L3 CAT detection using brand string and MSR probing if
|
||||
// not detected using cpuid
|
||||
lcpuid(0x7, 0x0, &res);
|
||||
if (!(res.ebx & (1 << 15))) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
else {
|
||||
lcpuid(0x10, 0x0, &res);
|
||||
if (!(res.ebx & (1 << 1))) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
// If we are here, then L3 cache allocation capability is available.
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "machine.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
struct cpuid_out res;
|
||||
|
||||
// Logic below from https://github.com/intel/intel-cmt-cat/blob/master/lib/cap.c
|
||||
lcpuid(0x7, 0x0, &res);
|
||||
if (!(res.ebx & (1 << 15))) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
else {
|
||||
lcpuid(0x10, 0x0, &res);
|
||||
if (!(res.ebx & (1 << 3))) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
// If we are here, then Memory Bandwidth Allocation capability is available.
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "machine.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
struct cpuid_out res;
|
||||
|
||||
// Logic below from https://github.com/intel/intel-cmt-cat/blob/master/lib/cap.c
|
||||
lcpuid(0x7, 0x0, &res);
|
||||
if (!(res.ebx & (1 << 12))) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
// check for overall monitoring capability first
|
||||
lcpuid(0xf, 0x0, &res);
|
||||
if (!(res.edx & (1 << 1))) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
// check for more detailed capability, CMT monitoring
|
||||
lcpuid(0xf, 0x1, &res);
|
||||
if (!(res.edx & (1 << 0))) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// If we are here, then CMT cache monitoring capability is available.
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "machine.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
struct cpuid_out res;
|
||||
|
||||
// Logic below from https://github.com/intel/intel-cmt-cat/blob/master/lib/cap.c
|
||||
lcpuid(0x7, 0x0, &res);
|
||||
if (!(res.ebx & (1 << 12))) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
else {
|
||||
lcpuid(0xf, 0x0, &res);
|
||||
if (!(res.edx & (1 << 1))) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
// If we are here, then cache monitoring capability is available.
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "machine.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
struct cpuid_out res;
|
||||
|
||||
// Logic below from https://github.com/intel/intel-cmt-cat/blob/master/lib/cap.c
|
||||
lcpuid(0x7, 0x0, &res);
|
||||
if (!(res.ebx & (1 << 12))) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
// check for overall monitoring capability first
|
||||
lcpuid(0xf, 0x0, &res);
|
||||
if (!(res.edx & (1 << 1))) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
// check for more detailed capability, MBM monitoring
|
||||
lcpuid(0xf, 0x1, &res);
|
||||
if ((res.edx & (3 << 1)) != (3 << 1)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// If we are here, then MBM cache monitoring capability is available.
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -17,9 +17,6 @@ limitations under the License.
|
|||
package rdt
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"sigs.k8s.io/node-feature-discovery/source"
|
||||
)
|
||||
|
||||
|
@ -33,52 +30,10 @@ func (s Source) Name() string { return "rdt" }
|
|||
func (s Source) Discover() (source.Features, error) {
|
||||
features := source.Features{}
|
||||
|
||||
cmd := exec.Command("bash", "-c", "mon-discovery")
|
||||
if err := cmd.Run(); err != nil {
|
||||
glog.Errorf("support for RDT monitoring was not detected: %v", err)
|
||||
} else {
|
||||
// RDT monitoring detected.
|
||||
features["RDTMON"] = true
|
||||
}
|
||||
rdtFeatures := discoverRDT()
|
||||
|
||||
cmd = exec.Command("bash", "-c", "mon-cmt-discovery")
|
||||
if err := cmd.Run(); err != nil {
|
||||
glog.Errorf("support for RDT CMT monitoring was not detected: %v", err)
|
||||
} else {
|
||||
// RDT CMT monitoring detected.
|
||||
features["RDTCMT"] = true
|
||||
}
|
||||
|
||||
cmd = exec.Command("bash", "-c", "mon-mbm-discovery")
|
||||
if err := cmd.Run(); err != nil {
|
||||
glog.Errorf("support for RDT MBM monitoring was not detected: %v", err)
|
||||
} else {
|
||||
// RDT MBM monitoring detected.
|
||||
features["RDTMBM"] = true
|
||||
}
|
||||
|
||||
cmd = exec.Command("bash", "-c", "l3-alloc-discovery")
|
||||
if err := cmd.Run(); err != nil {
|
||||
glog.Errorf("support for RDT L3 allocation was not detected: %v", err)
|
||||
} else {
|
||||
// RDT L3 cache allocation detected.
|
||||
features["RDTL3CA"] = true
|
||||
}
|
||||
|
||||
cmd = exec.Command("bash", "-c", "l2-alloc-discovery")
|
||||
if err := cmd.Run(); err != nil {
|
||||
glog.Errorf("support for RDT L2 allocation was not detected: %v", err)
|
||||
} else {
|
||||
// RDT L2 cache allocation detected.
|
||||
features["RDTL2CA"] = true
|
||||
}
|
||||
|
||||
cmd = exec.Command("bash", "-c", "mem-bandwidth-alloc-discovery")
|
||||
if err := cmd.Run(); err != nil {
|
||||
glog.Errorf("support for RDT Memory bandwidth allocation was not detected: %v", err)
|
||||
} else {
|
||||
// RDT Memory bandwidth allocation detected.
|
||||
features["RDTMBA"] = true
|
||||
for _, f := range rdtFeatures {
|
||||
features[f] = true
|
||||
}
|
||||
|
||||
return features, nil
|
||||
|
|
98
source/rdt/rdt_amd64.go
Normal file
98
source/rdt/rdt_amd64.go
Normal file
|
@ -0,0 +1,98 @@
|
|||
// +build amd64
|
||||
|
||||
/*
|
||||
Copyright 2018 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 rdt
|
||||
|
||||
type CpuidRet struct {
|
||||
EAX, EBX, ECX, EDX uint32
|
||||
}
|
||||
|
||||
const (
|
||||
// CPUID EAX input values
|
||||
LEAF_EXT_FEATURE_FLAGS = 0x07
|
||||
LEAF_RDT_MONITORING = 0x0f
|
||||
LEAF_RDT_ALLOCATION = 0x10
|
||||
|
||||
// CPUID ECX input values
|
||||
RDT_MONITORING_SUBLEAF_L3 = 1
|
||||
|
||||
// CPUID bitmasks
|
||||
EXT_FEATURE_FLAGS_EBX_RDT_M = 1 << 12
|
||||
EXT_FEATURE_FLAGS_EBX_RDT_A = 1 << 15
|
||||
RDT_MONITORING_EDX_L3_MONITORING = 1 << 1
|
||||
RDT_MONITORING_SUBLEAF_L3_EDX_L3_OCCUPANCY_MONITORING = 1 << 0
|
||||
RDT_MONITORING_SUBLEAF_L3_EDX_L3_TOTAL_BANDWIDTH_MONITORING = 1 << 1
|
||||
RDT_MONITORING_SUBLEAF_L3_EDX_L3_LOCAL_BANDWIDTH_MONITORING = 1 << 2
|
||||
RDT_ALLOCATION_EBX_L3_CACHE_ALLOCATION = 1 << 1
|
||||
RDT_ALLOCATION_EBX_L2_CACHE_ALLOCATION = 1 << 2
|
||||
RDT_ALLOCATION_EBX_MEMORY_BANDWIDTH_ALLOCATION = 1 << 3
|
||||
)
|
||||
|
||||
func discoverRDT() []string {
|
||||
features := []string{}
|
||||
|
||||
// Read cpuid information
|
||||
extFeatures := cpuid(LEAF_EXT_FEATURE_FLAGS, 0)
|
||||
rdtMonitoring := cpuid(LEAF_RDT_MONITORING, 0)
|
||||
rdtL3Monitoring := cpuid(LEAF_RDT_MONITORING, RDT_MONITORING_SUBLEAF_L3)
|
||||
rdtAllocation := cpuid(LEAF_RDT_ALLOCATION, 0)
|
||||
|
||||
// Detect RDT monitoring capabilities
|
||||
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")
|
||||
|
||||
// Cache Monitoring Technology (L3 occupancy monitoring)
|
||||
if rdtL3Monitoring.EDX&RDT_MONITORING_SUBLEAF_L3_EDX_L3_OCCUPANCY_MONITORING != 0 {
|
||||
features = append(features, "RDTCMT")
|
||||
}
|
||||
// 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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Detect RDT allocation capabilities
|
||||
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")
|
||||
}
|
||||
// L2 Cache Allocation
|
||||
if rdtAllocation.EBX&RDT_ALLOCATION_EBX_L2_CACHE_ALLOCATION != 0 {
|
||||
features = append(features, "RDTL2CA")
|
||||
}
|
||||
// Memory Bandwidth Allocation
|
||||
if rdtAllocation.EBX&RDT_ALLOCATION_EBX_MEMORY_BANDWIDTH_ALLOCATION != 0 {
|
||||
features = append(features, "RDTMBA")
|
||||
}
|
||||
}
|
||||
|
||||
return features
|
||||
}
|
||||
|
||||
func cpuid(eax, ecx uint32) CpuidRet {
|
||||
r := CpuidRet{}
|
||||
r.EAX, r.EBX, r.ECX, r.EDX = cpuidAsm(eax, ecx)
|
||||
return r
|
||||
}
|
||||
|
||||
func cpuidAsm(eax_arg, ecx_arg uint32) (eax, ebx, ecx, edx uint32)
|
27
source/rdt/rdt_amd64.s
Normal file
27
source/rdt/rdt_amd64.s
Normal file
|
@ -0,0 +1,27 @@
|
|||
// +build amd64
|
||||
|
||||
/*
|
||||
Copyright 2018 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.
|
||||
*/
|
||||
|
||||
TEXT ·cpuidAsm(SB), 4, $0 // 4 = NOSPLIT
|
||||
MOVL eax_arg+0(FP), AX
|
||||
MOVL ecx_arg+4(FP), CX
|
||||
CPUID
|
||||
MOVL AX, eax+8(FP)
|
||||
MOVL BX, ebx+12(FP)
|
||||
MOVL CX, ecx+16(FP)
|
||||
MOVL DX, edx+20(FP)
|
||||
RET
|
23
source/rdt/rdt_stub.go
Normal file
23
source/rdt/rdt_stub.go
Normal file
|
@ -0,0 +1,23 @@
|
|||
// +build !amd64
|
||||
|
||||
/*
|
||||
Copyright 2018 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 rdt
|
||||
|
||||
func discoverRDT() []string {
|
||||
return []string{}
|
||||
}
|
Loading…
Reference in a new issue