Skip to content

Commit 3760212

Browse files
committed
cpu: add e2e test for cstates
Signed-off-by: Antti Kervinen <[email protected]>
1 parent c35346b commit 3760212

File tree

2 files changed

+130
-0
lines changed

2 files changed

+130
-0
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
config:
2+
agent:
3+
nodeResourceTopology: true
4+
allocatorTopologyBalancing: false
5+
availableResources:
6+
cpu: cpuset:2-7,10-13 # policy must not touch C-states of unavailable CPUs
7+
reservedResources:
8+
cpu: 750m
9+
10+
pinCPU: true
11+
12+
idleCPUClass: default-class
13+
14+
balloonTypes:
15+
- name: lowlatency-bln
16+
cpuClass: lowlatency-class
17+
18+
control:
19+
cpu:
20+
classes:
21+
lowlatency-class:
22+
disabledCstates: [C4, C6, C8, C10]
23+
default-class:
24+
disabledCstates: []
25+
log:
26+
debug:
27+
- policy
28+
- cpu
29+
extraEnv:
30+
OVERRIDE_SYS_CSTATES: '''[{"cpus": "0-15", "names": ["C1E", "C2", "C4", "C8"], "files": {"disable": "0"}}]'''
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Test balloons with certain CPU c-states disabled
2+
3+
helm-terminate
4+
helm_config=$TEST_DIR/balloons-cstates.cfg helm-launch balloons
5+
6+
# cpuids-of-container returns CPU ids a container is allowed to use, e.g. "1 2 4"
7+
cpuids-of() {
8+
local ctr=$1 # e.g. pod0c0
9+
# return only cpu ids without zero-fill: replace cpu01 -> 1, cpu11 -> 11
10+
pyexec "for cpu in cpus['$ctr']: print(cpu.replace('cpu0','').replace('cpu',''))"
11+
}
12+
13+
# verify-cstates checks the last writes to "disable" files in the
14+
# override fs.
15+
verify-cstates() {
16+
local cpu_ids=$1 # e.g. "1 2 4"
17+
local enabled_cstates=$2 # e.g. "C1E C2"
18+
local disabled_cstates=$3 # e.g. "C6 C8"
19+
local last_n_writes=$4 # expect the write within last N writes, e.g. 6
20+
21+
vm-command "kubectl -n kube-system logs ds/nri-resource-policy-balloons | nl | grep 'cstates override fs: wrote' | tail -n $last_n_writes | nl"
22+
for cpu_id in $cpu_ids; do
23+
for cstate in $enabled_cstates; do
24+
echo "verify last write to cpu$cpu_id cstate=$cstate disable is 0"
25+
grep "cpu${cpu_id} cstate=$cstate disable=" <<< $COMMAND_OUTPUT | tail -n 1 | grep -q 'disable="0"' || {
26+
command-error "expected write 0 not found"
27+
}
28+
done
29+
for cstate in $disabled_cstates; do
30+
echo "verify last write to cpu$cpu_id cstate=$cstate disable is 1"
31+
grep "cpu${cpu_id} cstate=$cstate disable=" <<< $COMMAND_OUTPUT | tail -n 1 | grep -q 'disable="1"' || {
32+
command-error "expected write 1 not found"
33+
}
34+
done
35+
done
36+
}
37+
38+
# verify-cstates-no-writes checks that any c-states of given CPUs have not been written
39+
verify-cstates-no-writes() {
40+
local cpu_ids=$1 # e.g. "1 2 4"
41+
local last_n_writes=$2 # e.g. 100
42+
echo "verify no writes to c-states of CPUs $cpu_ids"
43+
cpu_ids="(${cpu_ids// /|})"
44+
vm-command "kubectl -n kube-system logs ds/nri-resource-policy-balloons | nl | grep -E 'cstates override fs: wrote cpu${cpu_ids} cstate='"
45+
grep -q wrote <<< $COMMAND_OUTPUT && {
46+
command-error "writes to forbidden CPUs found"
47+
}
48+
}
49+
50+
cleanup() {
51+
vm-command "kubectl delete pods --all --now"
52+
}
53+
54+
echo "verify that all c-states of all available CPUs are enabled"
55+
verify-cstates "2 3 4 5 6 7 11 12 13" "C1E C2 C4 C8" "" 36
56+
57+
echo "verify that c-states of CPUs outside AvailableResources have not been written"
58+
verify-cstates-no-writes "0 1 8 9 14 15"
59+
60+
CPUREQ="750m" MEMREQ="100M" CPULIM="750m" MEMLIM=""
61+
POD_ANNOTATION="balloon.balloons.resource-policy.nri.io: lowlatency-bln" CONTCOUNT=1 create balloons-busybox
62+
report allowed
63+
verify 'len(cpus["pod0c0"]) == 1'
64+
echo "verify that CPUs of low-latency pod0 cannot enter C4 or C8"
65+
verify-cstates "$(cpuids-of pod0c0)" "C1E C2" "C4 C8" 4
66+
67+
CPUREQ="3" MEMREQ="100M" CPULIM="" MEMLIM=""
68+
POD_ANNOTATION="balloon.balloons.resource-policy.nri.io: lowlatency-bln" CONTCOUNT=1 create balloons-busybox
69+
report allowed
70+
verify 'cpus["pod0c0"] == cpus["pod1c0"]' \
71+
'len(cpus["pod0c0"]) == 4'
72+
echo "verify that CPUs of low-latency pods pod0 and pod1 cannot enter C4 or C8"
73+
verify-cstates "$(cpuids-of pod1c0)" "C1E C2" "C4 C8" 16
74+
75+
# store CPU ids of maximal cpuset before deleting pods
76+
max_lowlatency_cpus="$(echo $(cpuids-of pod1c0) )"
77+
78+
vm-command 'kubectl delete pod pod1'
79+
report allowed
80+
verify 'len(cpus["pod0c0"]) == 1'
81+
82+
# spaces around each id helps ensuring grep " 1 " never matches cpu 11 but always matches cpu 1
83+
pod0cpus=" $(echo $(cpuids-of pod0c0) ) "
84+
85+
echo "verify that c-states of freed CPUs are enabled again after balloon was deflated"
86+
freed_cpus=""
87+
for cpu_id in $max_lowlatency_cpus; do
88+
grep -q " $cpu_id " <<< $pod0cpus || freed_cpus+=" $cpu_id"
89+
done
90+
echo "verify that all c-states of freed CPUs $freed_cpus (= {$max_lowlatency_cpus} - {$pod0cpus}) are enabled after the balloon got deflated"
91+
verify-cstates "$freed_cpus" "C1E C2 C4 C8" "" 24
92+
93+
echo "verify that c-states of the remaining CPU $(cpuids-of pod0c0) are still configured for low-latency"
94+
verify-cstates "$(cpuids-of pod0c0)" "C1E C2" "C4 C8" 16
95+
96+
vm-command 'kubectl delete pod pod0'
97+
report allowed
98+
99+
echo "verify that after all containers are gone and their destroyed, c-states of all used CPUs are enabled again"
100+
verify-cstates "$max_lowlatency_cpus" "C1E C2 C4 C8" "" 32

0 commit comments

Comments
 (0)