Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package kubevirt for openSUSE:Factory checked in at 2023-05-02 16:19:38 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/kubevirt (Old) and /work/SRC/openSUSE:Factory/.kubevirt.new.1533 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "kubevirt" Tue May 2 16:19:38 2023 rev:55 rq:1084028 version:0.59.0 Changes: -------- --- /work/SRC/openSUSE:Factory/kubevirt/kubevirt.changes 2023-03-17 17:04:51.621869367 +0100 +++ /work/SRC/openSUSE:Factory/.kubevirt.new.1533/kubevirt.changes 2023-05-02 16:24:23.743720810 +0200 @@ -1,0 +2,6 @@ +Tue May 2 12:01:29 UTC 2023 - Vasily Ulyanov <vasily.ulya...@suse.com> + +- TSC frequencies: add 250PPM tolerance (bsc#1210906) + 0002-TSC-frequencies-add-250PPM-tolerance.patch + +------------------------------------------------------------------- New: ---- 0002-TSC-frequencies-add-250PPM-tolerance.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ kubevirt.spec ++++++ --- /var/tmp/diff_new_pack.Ej8Wek/_old 2023-05-02 16:24:24.319724226 +0200 +++ /var/tmp/diff_new_pack.Ej8Wek/_new 2023-05-02 16:24:24.323724250 +0200 @@ -29,6 +29,7 @@ Source3: %{url}/releases/download/v%{version}/disks-images-provider.yaml Source100: %{name}-rpmlintrc Patch0: 0001-Vulnerability-fix-limit-operator-secrets-permission.patch +Patch1: 0002-TSC-frequencies-add-250PPM-tolerance.patch BuildRequires: glibc-devel-static BuildRequires: golang-packaging BuildRequires: pkgconfig ++++++ 0002-TSC-frequencies-add-250PPM-tolerance.patch ++++++ >From 5b2375575346dc36d63aa2a68174db48a4439dbe Mon Sep 17 00:00:00 2001 From: Jed Lejosne <j...@redhat.com> Date: Thu, 20 Apr 2023 16:45:47 -0400 Subject: [PATCH] TSC frequencies: add 250PPM tolerance It is possible to migrate VMs to nodes that have a TSC frequency within 250PPM of theirs. This adds support for it by tagging nodes with VMI frequencies within the tolerance range. Signed-off-by: Jed Lejosne <j...@redhat.com> --- pkg/virt-controller/watch/topology/filter.go | 8 ++++++ pkg/virt-controller/watch/topology/tsc.go | 26 ++++++++++++++----- .../watch/topology/tsc_test.go | 21 ++++++++++----- 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/pkg/virt-controller/watch/topology/filter.go b/pkg/virt-controller/watch/topology/filter.go index 0108f5a41..ddf05489a 100644 --- a/pkg/virt-controller/watch/topology/filter.go +++ b/pkg/virt-controller/watch/topology/filter.go @@ -1,6 +1,8 @@ package topology import ( + "math" + v1 "k8s.io/api/core/v1" virtv1 "kubevirt.io/api/core/v1" @@ -10,6 +12,7 @@ import ( const TSCFrequencyLabel = virtv1.CPUTimerLabel + "tsc-frequency" const TSCFrequencySchedulingLabel = "scheduling.node.kubevirt.io/tsc-frequency" const TSCScalableLabel = virtv1.CPUTimerLabel + "tsc-scalable" +const TSCTolerancePPM float64 = 250 type FilterPredicateFunc func(node *v1.Node) bool @@ -89,3 +92,8 @@ func FilterNodesFromCache(objs []interface{}, predicates ...FilterPredicateFunc) } return match } + +// ToleranceForFrequency returns TSCTolerancePPM parts per million of freq, rounded down to the nearest Hz +func ToleranceForFrequency(freq int64) int64 { + return int64(math.Floor(float64(freq) * (TSCTolerancePPM / 1000000))) +} diff --git a/pkg/virt-controller/watch/topology/tsc.go b/pkg/virt-controller/watch/topology/tsc.go index ebde09aa6..06795deab 100644 --- a/pkg/virt-controller/watch/topology/tsc.go +++ b/pkg/virt-controller/watch/topology/tsc.go @@ -85,14 +85,24 @@ func TSCFrequenciesOnNode(node *v1.Node) (frequencies []int64) { return } -func CalculateTSCLabelDiff(frequenciesInUse []int64, frequenciesOnNode []int64, nodeFrequency int64, scalable bool) (toAdd []int64, toRemove []int64) { - if scalable { - frequenciesInUse = append(frequenciesInUse, nodeFrequency) - } else { - frequenciesInUse = []int64{nodeFrequency} +func distance(freq1, freq2 int64) int64 { + if freq1 > freq2 { + return freq1 - freq2 } + return freq2 - freq1 +} + +func CalculateTSCLabelDiff(frequenciesInUse []int64, frequenciesOnNode []int64, nodeFrequency int64, scalable bool) (toAdd []int64, toRemove []int64) { + frequenciesInUse = append(frequenciesInUse, nodeFrequency) + tolerance := ToleranceForFrequency(nodeFrequency) requiredMap := map[int64]struct{}{} for _, freq := range frequenciesInUse { + if !scalable && distance(freq, nodeFrequency) > tolerance { + // A non-scalable node can only accept frequencies that are within Qemu's tolerance: + // nodeFrequency*(1-0.000250) < acceptableFrequency < nodeFrequency*(1+0.000250). + // Skip the frequencies that are outside that range + continue + } requiredMap[freq] = struct{}{} } @@ -102,8 +112,10 @@ func CalculateTSCLabelDiff(frequenciesInUse []int64, frequenciesOnNode []int64, } } - for _, freq := range frequenciesInUse { - if freq <= nodeFrequency { + for freq := range requiredMap { + // For the non-scalable case, the map was already sanitized above. + // For the scalable case, a node can accept frequencies that are either lower than its own or within the tolerance range + if !scalable || freq <= nodeFrequency || distance(freq, nodeFrequency) <= tolerance { toAdd = append(toAdd, freq) } } diff --git a/pkg/virt-controller/watch/topology/tsc_test.go b/pkg/virt-controller/watch/topology/tsc_test.go index 61f439745..c066d9c65 100644 --- a/pkg/virt-controller/watch/topology/tsc_test.go +++ b/pkg/virt-controller/watch/topology/tsc_test.go @@ -42,8 +42,8 @@ var _ = Describe("TSC", func() { DescribeTable("should calculate the node label diff", func(frequenciesInUse []int64, frequenciesOnNode []int64, nodeFrequency int64, scalable bool, expectedToAdd []int64, expectedToRemove []int64) { toAdd, toRemove := topology.CalculateTSCLabelDiff(frequenciesInUse, frequenciesOnNode, nodeFrequency, scalable) - Expect(toAdd).To(Equal(expectedToAdd)) - Expect(toRemove).To(Equal(expectedToRemove)) + Expect(toAdd).To(ConsistOf(expectedToAdd)) + Expect(toRemove).To(ConsistOf(expectedToRemove)) }, Entry( "on a scalable node", @@ -56,15 +56,15 @@ var _ = Describe("TSC", func() { ), Entry( "on a scalable node where not all required frequencies are compatible", - []int64{1, 2, 3, 200}, + []int64{1, 2, 3, 123130, 200000}, // 123130 is above but within 250 PPM []int64{2, 4}, - int64(123), + int64(123123), true, - []int64{1, 2, 3, 123}, + []int64{1, 2, 3, 123123, 123130}, []int64{4}, ), Entry( - "on a not scalable node where only the node frequency can be set", + "on a non-scalable node where only the node frequency can be set", []int64{1, 2, 3}, []int64{2, 4}, int64(123), @@ -72,6 +72,15 @@ var _ = Describe("TSC", func() { []int64{123}, []int64{2, 4}, ), + Entry( + "on a non-scalable node where other node frequencies are close-enough", + []int64{1, 2, 123120, 123130}, // 250 PPM of 123123 is 30 + []int64{2, 4}, + int64(123123), + false, + []int64{123123, 123120, 123130}, + []int64{2, 4}, + ), ) Context("needs to be set when", func() { -- 2.40.0