Skip to content

CNF-23471: Dedicate cpus for dpdk vswitch#1546

Open
Tal-or wants to merge 7 commits into
openshift:mainfrom
Tal-or:dedicate_cpus_for_dpdk_vswitch
Open

CNF-23471: Dedicate cpus for dpdk vswitch#1546
Tal-or wants to merge 7 commits into
openshift:mainfrom
Tal-or:dedicate_cpus_for_dpdk_vswitch

Conversation

@Tal-or

@Tal-or Tal-or commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Add spec.cpu.ovsDpdk field to the PerformanceProfile v2 API, enabling users to designate CPUs for exclusive use by OVS-DPDK.

The OVS-DPDK CPUs receives full kernel-level scheduling isolation, are excluded from kubelet scheduling and IRQ balancing, and remain protected from interference across pod lifecycle events.

The controller validates that the cluster meets the prerequisites for the isolation and reports a Degraded status if they are not satisfied.
In addition "performance.openshift.io/disable-load-balancing-ovs-dpdk" annotation was added to disable kernel load balancing on the ovsDpdk CPUs. This PR makes it optional since an extra step is needed from the OVS process side to make this feature fully functional, so we don't want to decouple this extra isolation capability from the general set of parameters we configure for the ovs dpdk set.

Includes unit and e2e test coverage.

This work inspired by: https://github.com/mcoquelin/cluster-node-tuning-operator/commits/release-4.20-ovs-dpdk/

Signed-off-by: Talor Itzhak titzhak@redhat.com

Summary by CodeRabbit

  • New Features
    • Added spec.cpu.ovsDpdk support to reserve fully isolated CPUs for OVS-DPDK, including validation and reconciliation.
    • Added an annotation to optionally disable OVS-DPDK load balancing.
    • Generated OVS-DPDK CPU pinning (slice/cgroup setup) and updated boot/kubelet reserved CPU handling and tuned isolation.
  • Bug Fixes
    • Improved IRQ-banning and affinity masking so OVS-DPDK CPUs are correctly excluded from default_smp_affinity, including consistent CRI-O restore behavior.
  • Tests
    • Expanded unit, Ginkgo, and E2E coverage for OVS-DPDK CPU prerequisites, validation, and end-to-end behavior.

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

This PR adds OVS-DPDK CPU-set handling across the PerformanceProfile API, validation, controller flow, machine config rendering, runtime scripts, and e2e coverage. It also updates docs, generated fixtures, and test helpers to match the new field and prerequisite checks.

Changes

OVS-DPDK CPU flow

Layer / File(s) Summary
API and validation
docs/performanceprofile/performance_profile.md, manifests/20-performance-profile.crd.yaml, pkg/apis/performanceprofile/v2/performanceprofile_types.go, pkg/apis/performanceprofile/v2/performanceprofile_validation.go, pkg/apis/performanceprofile/v2/performanceprofile_validation_test.go, pkg/performanceprofile/controller/performanceprofile/components/utils.go, pkg/performanceprofile/controller/performanceprofile/components/utils_test.go
Adds spec.cpu.ovsDpdk, the OVS-DPDK disable-load-balancing annotation constant, CPU-list parsing/validation support, overlap/fuzz coverage, and matching docs/CRD updates.
Runtime scripts and ignition
assets/performanceprofile/scripts/clear-irqbalance-banned-cpus.sh, assets/performanceprofile/scripts/ovs-dpdk-cpus-configure.sh, pkg/performanceprofile/controller/performanceprofile/components/components.go, pkg/performanceprofile/controller/performanceprofile/components/machineconfig/machineconfig.go, pkg/performanceprofile/controller/performanceprofile/components/machineconfig/machineconfig_test.go, pkg/performanceprofile/controller/performanceprofile/components/assets_scripts_test.go, test/e2e/performanceprofile/testdata/render-expected-output/**/*.yaml
Threads OVS-DPDK CPU values through MachineConfig options, script rendering, systemd units, cgroup setup, and the matching fixture/test expectations.
Kubelet and tuned CPU sets
pkg/performanceprofile/controller/performanceprofile/components/kubeletconfig/kubeletconfig.go, pkg/performanceprofile/controller/performanceprofile/components/kubeletconfig/kubeletconfig_test.go, pkg/performanceprofile/controller/performanceprofile/components/tuned/tuned.go, pkg/performanceprofile/controller/performanceprofile/components/tuned/tuned_test.go
Unions OVS-DPDK CPUs into kubelet reserved CPUs and tuned isolated CPUs, and adds strict CPU reservation inspection plus tests.
Prerequisite validation and status handling
pkg/performanceprofile/controller/performanceprofile/components/profile/profile.go, pkg/performanceprofile/controller/performanceprofile/components/handler/handler.go, pkg/performanceprofile/controller/performanceprofile/hypershift/components/handler.go, pkg/performanceprofile/controller/performanceprofile/status/errors.go, pkg/performanceprofile/controller/performanceprofile/status/status.go, pkg/performanceprofile/controller/performanceprofile_controller.go, pkg/performanceprofile/controller/performanceprofile_controller_test.go
Adds prerequisite validation, derived option population, a dedicated prerequisite error and condition reason, and controller handling for that error path.
E2E coverage and helpers
test/e2e/performanceprofile/functests/2_performance_update/ovsdpdk.go, test/e2e/performanceprofile/functests/3_performance_status/status.go, test/e2e/performanceprofile/functests/7_performance_kubelet_node/cgroups.go, test/e2e/performanceprofile/functests/utils/cluster/cluster.go, test/e2e/performanceprofile/functests/utils/label/label.go, test/e2e/performanceprofile/functests/utils/pods/pods.go
Adds OVS-DPDK prerequisite and placement e2e tests, updates workload-partitioning helpers, and adds pod failure diagnostics.
Rendered MachineConfig testdata
test/e2e/performanceprofile/testdata/render-expected-output/**/*.yaml
Updates embedded boot-time scripts and OVS slice entry ordering in generated MachineConfig fixtures.

Estimated code review effort: 4 (Complex) | ~75 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 11

❌ Failed checks (1 warning, 10 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 48.39% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Stable And Deterministic Test Names ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Test Structure And Quality ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Microshift Test Compatibility ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Single Node Openshift (Sno) Test Compatibility ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Topology-Aware Scheduling Compatibility ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Ote Binary Stdout Contract ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Ipv6 And Disconnected Network Test Compatibility ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
No-Weak-Crypto ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Container-Privileges ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
No-Sensitive-Data-In-Logs ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and matches the main change: dedicating CPUs for OVS-DPDK/vswitch use.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


Comment @coderabbitai help to get the list of available commands.

@openshift-ci openshift-ci Bot requested review from ffromani and yanirq June 14, 2026 11:29
@openshift-ci

openshift-ci Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: Tal-or
Once this PR has been reviewed and has the lgtm label, please assign yanirq for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@Tal-or Tal-or changed the title Dedicate cpus for dpdk vswitch CNF-23471: Dedicate cpus for dpdk vswitch Jun 14, 2026
@openshift-ci-robot

openshift-ci-robot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

@Tal-or: This pull request references CNF-23471 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "5.0.0" version, but no target version was set.

Details

In response to this:

Add spec.cpu.dedicated and spec.net.disableOvsDynamicPinning fields to the PerformanceProfile v2 API, enabling users to designate CPUs for exclusive use by infrastructure networking workloads such as DPDK-based vSwitch/vRouter.

Dedicated CPUs receive full kernel-level scheduling isolation, are excluded from kubelet scheduling and IRQ balancing, and remain protected from interference across pod lifecycle events.

The controller validates that the cluster meets the prerequisites for dedicated CPU isolation and reports a Degraded status if they are not satisfied.
Setting disableOvsDynamicPinning prevents OVN-Kubernetes from dynamically adjusting OVS thread CPU affinity on the target nodes.

Includes unit and e2e test coverage.

Signed-off-by: Talor Itzhak titzhak@redhat.com

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Jun 14, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/performanceprofile/controller/performanceprofile/components/machineconfig/machineconfig.go (1)

565-595: ⚠️ Potential issue | 🟡 Minor

Handle CPUListToHexMask conversion errors in getIRQBalanceBannedCPUsOptions instead of logging and continuing.

While DedicatedCPUs strings are validated by other components (kubeletconfig and tuned) during profile creation, getIRQBalanceBannedCPUsOptions (line 587) logs the conversion error but returns a machineconfig unit without the DEDICATED_CPUS environment variable set. This violates fail-fast principles—if the hex mask conversion fails, the machine config generation should also fail rather than silently proceeding with incomplete configuration. Although downstream validation in kubeletconfig.New() and tuned.NewNodePerformance() will prevent the profile from being applied if the string is invalid, machineconfig.New() should propagate the error instead of logging and returning a partial result.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@pkg/performanceprofile/controller/performanceprofile/components/machineconfig/machineconfig.go`
around lines 565 - 595, The getIRQBalanceBannedCPUsOptions function currently
logs the CPUListToHexMask conversion error and returns incomplete options
instead of failing fast. Modify the function signature to return both a slice of
unit options and an error. When the CPUListToHexMask conversion fails, propagate
the error by returning it instead of logging and continuing. Then update all
callers of getIRQBalanceBannedCPUsOptions to handle the returned error and
propagate it up to the machineconfig.New() function so that the entire machine
config generation fails on conversion errors rather than creating a partial
configuration.
🧹 Nitpick comments (4)
manifests/20-performance-profile.crd.yaml (1)

512-521: ⚡ Quick win

Consider documenting prerequisites in the CRD description.

The CRD description provides detailed implementation effects but doesn't mention the prerequisites documented in the Go API types. The Go struct (performanceprofile_types.go:141-147) states "WorkloadPartitioning or --strict-cpu-reservation kubelet CPUManager policy option are a prerequisite for this feature." Users relying on CRD documentation (e.g., via kubectl explain) won't see this requirement.

📝 Suggested improvement
                    dedicated:
                      description: |-
                        Dedicated defines a set of CPUs fully isolated from the operating system
                        and Kubernetes scheduling, intended for exclusive use by user-space
                        processes (for example, infrastructure networking workloads such as
                        DPDK-based vSwitch or vRouter). These CPUs receive full kernel-level
                        isolation (isolcpus=domain,managed_irq, nohz_full, rcu_nocbs), are
                        excluded from Kubelet scheduling (all QoS classes), banned from
                        irqbalance, and excluded from systemd CPU affinity.
+                       
+                       Prerequisites: Either Workload Partitioning (CPUPartitioningAllNodes)
+                       or the strict-cpu-reservation Kubelet CPUManager policy option must be
+                       enabled. Without these prerequisites, Burstable and BestEffort QoS pods
+                       may still be scheduled on dedicated CPUs.
                      type: string
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@manifests/20-performance-profile.crd.yaml` around lines 512 - 521, The
"dedicated" CPU configuration description in the CRD is missing important
prerequisite information that is documented in the Go API types
(performanceprofile_types.go). Add a statement to the description field
documenting that WorkloadPartitioning or --strict-cpu-reservation kubelet
CPUManager policy option is a prerequisite for using this feature. This ensures
users viewing the CRD documentation via kubectl explain or similar tools will be
aware of the necessary prerequisites before attempting to use this feature.
pkg/performanceprofile/controller/performanceprofile/components/tuned/tuned_test.go (1)

732-751: ⚡ Quick win

Strengthen dedicated CPU assertions to avoid false positives.

The new checks are permissive/tautological: ContainElements won’t catch extra CPUs, and asserting cmdline_cpu_part equals a constant doesn’t validate dedicated propagation. Prefer exact cpuset equality (or explicit negative checks) for isolated_cores, and assert behavior derived from that value.

Suggested assertion tightening
-			Expect(set.List()).To(ContainElements(4, 5, 10, 11))
+			expected, err := cpuset.Parse("4-5,10-11")
+			Expect(err).ToNot(HaveOccurred())
+			Expect(set.Equals(expected)).To(BeTrue())
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@pkg/performanceprofile/controller/performanceprofile/components/tuned/tuned_test.go`
around lines 732 - 751, The test assertions for dedicated CPU handling are too
permissive and could miss failures. In the first test ("should include dedicated
CPUs in isolated_cores"), replace the ContainElements assertion on set.List()
with an exact equality check to ensure isolated_cores contains precisely the
expected CPUs and no extras. In the second test ("should include dedicated CPUs
in nohz_full and rcu_nocbs via isolated_cores"), instead of just verifying that
cmdline_cpu_part matches a constant string, directly assert that the nohz_full
and rcu_nocbs kernel parameters in the bootloader section actually include the
dedicated CPUs (10-11), confirming the values are properly derived from
isolated_cores rather than just checking a static string.
test/e2e/performanceprofile/functests/2_performance_update/dedicatedcpus.go (2)

148-174: ⚡ Quick win

Kernel cmdline CPU regex patterns may produce false positives.

The regex patterns isolcpus=\S*%d, nohz_full=\S*%d, and rcu_nocbs=\S*%d use \S* (any non-whitespace) before the CPU number. This can match incorrectly when checking for a CPU like "2" in ranges such as "1-20" or multi-digit CPUs like "12".

Consider using more precise patterns that account for CPU list/range syntax (e.g., comma-separated, hyphen-separated), or adding word boundaries where appropriate.

♻️ More precise regex example

For CPU lists that use commas and hyphens:

-				Expect(cmdlineStr).To(
-					MatchRegexp(`isolcpus=\S*%d`, cpu),
-					fmt.Sprintf("isolcpus should include CPU %d (isolated+dedicated)", cpu))
+				// Match CPU as standalone number, start/end of range, or in comma-separated list
+				cpuPattern := fmt.Sprintf(`isolcpus=[^ ]*(\b%d\b|%d-|\-%d)`, cpu, cpu, cpu)
+				Expect(cmdlineStr).To(
+					MatchRegexp(cpuPattern),
+					fmt.Sprintf("isolcpus should include CPU %d (isolated+dedicated)", cpu))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/e2e/performanceprofile/functests/2_performance_update/dedicatedcpus.go`
around lines 148 - 174, The regex patterns used in the MatchRegexp calls for
isolcpus, nohz_full, and rcu_nocbs are too loose with the `\S*%d` format, which
can match false positives (e.g., matching "2" within "1-20" or "12"). Replace
these patterns with more precise regex that accounts for CPU list syntax using
comma and hyphen delimiters, such as patterns that match CPU numbers preceded by
commas, hyphens, or the start of the parameter value, and followed by commas,
hyphens, or end of parameter. Apply this fix to all three kernel parameter regex
patterns in the MatchRegexp calls for isolcpus, nohz_full, and rcu_nocbs within
the dedicated CPUs verification loops.

278-282: ⚡ Quick win

Add assertion for IRQBALANCE_BANNED_CPUS while GU pod is running.

The test logs IRQBALANCE_BANNED_CPUS while the GU pod is running (line 278-282) but does not assert that it still contains the dedicated CPU hex mask. Currently, only the post-deletion check (lines 290-299) verifies the mask is preserved. Adding an assertion here would strengthen the test by confirming the mask remains stable throughout the pod lifecycle, not just after deletion.

📝 Proposed assertion
 			By("Verifying IRQBALANCE_BANNED_CPUS still includes dedicated CPUs with pod running")
 			irqConf, err = nodes.ExecCommand(ctx, node, []string{"cat", "/rootfs/etc/sysconfig/irqbalance"})
 			Expect(err).ToNot(HaveOccurred())
 			irqConfWithPod := testutils.ToString(irqConf)
 			testlog.Infof("IRQBALANCE_BANNED_CPUS with pod: %s", irqConfWithPod)
+			Expect(irqConfWithPod).To(ContainSubstring(fmt.Sprintf("IRQBALANCE_BANNED_CPUS=%s", dedicatedHexMask)),
+				"IRQBALANCE_BANNED_CPUS should still contain dedicated CPU hex mask while pod is running")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/e2e/performanceprofile/functests/2_performance_update/dedicatedcpus.go`
around lines 278 - 282, After logging the irqConfWithPod value on line 282, add
an assertion to verify that IRQBALANCE_BANNED_CPUS still contains the dedicated
CPU hex mask while the GU pod is running. This assertion should validate the
same mask that is checked in the post-deletion verification (lines 290-299),
ensuring the dedicated CPUs are properly reserved throughout the pod lifecycle,
not just after the pod is removed. Reference the existing assertion logic from
the later check to maintain consistency in how the mask validation is performed.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@assets/performanceprofile/scripts/clear-irqbalance-banned-cpus.sh`:
- Around line 41-59: The script pads `BANNED_CPUS` with leading zeros to match
the expected width but does not handle cases where `BANNED_CPUS` is already
wider than `n * 8` characters, causing substring extraction to use incorrect
positions. After calculating `n` from the `smp` array, add validation to check
if the length of `BANNED_CPUS` exceeds `n * 8` characters. If it does, either
truncate `BANNED_CPUS` to the rightmost `n * 8` characters to preserve the
significant bits (or exit with an error message indicating the banned CPU mask
is incompatible with the system topology). This ensures the substring extraction
in the loop at line 53 (the `ban=` assignment) correctly extracts the
appropriate 8-character chunks for each 32-bit group.

In `@assets/performanceprofile/scripts/dedicated-cpus-configure.sh`:
- Around line 9-26: The script assigns the DEDICATED_CPUS variable from the
template but does not validate that it contains a non-empty value before writing
it to multiple cgroup files (cpuset.cpus.exclusive, cpuset.cpus, and
cpuset.cpus.partition). Add a validation check immediately after the
DEDICATED_CPUS assignment to verify the variable is not empty, and exit with a
descriptive error message if it is empty, similar to the existing check for the
CGROUP_PATH directory. This will prevent invalid cgroup states from being
created due to empty template values.

In
`@pkg/performanceprofile/controller/performanceprofile/components/kubeletconfig/kubeletconfig.go`:
- Around line 247-261: The HasStrictCPUReservation function silently ignores
errors when json.Unmarshal fails, which prevents operators from debugging
malformed KubeletConfig payloads. Modify the error handling in the
HasStrictCPUReservation function where json.Unmarshal is called to log the error
before returning false. You will need to add a logger parameter to the function
or access a logger instance available in the package, then log the actual error
returned from the json.Unmarshal call to provide visibility into why the
function returns false.

---

Outside diff comments:
In
`@pkg/performanceprofile/controller/performanceprofile/components/machineconfig/machineconfig.go`:
- Around line 565-595: The getIRQBalanceBannedCPUsOptions function currently
logs the CPUListToHexMask conversion error and returns incomplete options
instead of failing fast. Modify the function signature to return both a slice of
unit options and an error. When the CPUListToHexMask conversion fails, propagate
the error by returning it instead of logging and continuing. Then update all
callers of getIRQBalanceBannedCPUsOptions to handle the returned error and
propagate it up to the machineconfig.New() function so that the entire machine
config generation fails on conversion errors rather than creating a partial
configuration.

---

Nitpick comments:
In `@manifests/20-performance-profile.crd.yaml`:
- Around line 512-521: The "dedicated" CPU configuration description in the CRD
is missing important prerequisite information that is documented in the Go API
types (performanceprofile_types.go). Add a statement to the description field
documenting that WorkloadPartitioning or --strict-cpu-reservation kubelet
CPUManager policy option is a prerequisite for using this feature. This ensures
users viewing the CRD documentation via kubectl explain or similar tools will be
aware of the necessary prerequisites before attempting to use this feature.

In
`@pkg/performanceprofile/controller/performanceprofile/components/tuned/tuned_test.go`:
- Around line 732-751: The test assertions for dedicated CPU handling are too
permissive and could miss failures. In the first test ("should include dedicated
CPUs in isolated_cores"), replace the ContainElements assertion on set.List()
with an exact equality check to ensure isolated_cores contains precisely the
expected CPUs and no extras. In the second test ("should include dedicated CPUs
in nohz_full and rcu_nocbs via isolated_cores"), instead of just verifying that
cmdline_cpu_part matches a constant string, directly assert that the nohz_full
and rcu_nocbs kernel parameters in the bootloader section actually include the
dedicated CPUs (10-11), confirming the values are properly derived from
isolated_cores rather than just checking a static string.

In `@test/e2e/performanceprofile/functests/2_performance_update/dedicatedcpus.go`:
- Around line 148-174: The regex patterns used in the MatchRegexp calls for
isolcpus, nohz_full, and rcu_nocbs are too loose with the `\S*%d` format, which
can match false positives (e.g., matching "2" within "1-20" or "12"). Replace
these patterns with more precise regex that accounts for CPU list syntax using
comma and hyphen delimiters, such as patterns that match CPU numbers preceded by
commas, hyphens, or the start of the parameter value, and followed by commas,
hyphens, or end of parameter. Apply this fix to all three kernel parameter regex
patterns in the MatchRegexp calls for isolcpus, nohz_full, and rcu_nocbs within
the dedicated CPUs verification loops.
- Around line 278-282: After logging the irqConfWithPod value on line 282, add
an assertion to verify that IRQBALANCE_BANNED_CPUS still contains the dedicated
CPU hex mask while the GU pod is running. This assertion should validate the
same mask that is checked in the post-deletion verification (lines 290-299),
ensuring the dedicated CPUs are properly reserved throughout the pod lifecycle,
not just after the pod is removed. Reference the existing assertion logic from
the later check to maintain consistency in how the mask validation is performed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: d5b28947-9021-4a26-8c35-72850a71ac2e

📥 Commits

Reviewing files that changed from the base of the PR and between 07687ef and 06b8810.

⛔ Files ignored due to path filters (1)
  • pkg/apis/performanceprofile/v2/zz_generated.deepcopy.go is excluded by !**/zz_generated*
📒 Files selected for processing (27)
  • assets/performanceprofile/configs/dedicatedcpus.slice
  • assets/performanceprofile/scripts/clear-irqbalance-banned-cpus.sh
  • assets/performanceprofile/scripts/dedicated-cpus-configure.sh
  • manifests/20-performance-profile.crd.yaml
  • pkg/apis/performanceprofile/v2/performanceprofile_types.go
  • pkg/apis/performanceprofile/v2/performanceprofile_validation.go
  • pkg/apis/performanceprofile/v2/performanceprofile_validation_test.go
  • pkg/performanceprofile/controller/performanceprofile/components/components.go
  • pkg/performanceprofile/controller/performanceprofile/components/handler/handler.go
  • pkg/performanceprofile/controller/performanceprofile/components/kubeletconfig/kubeletconfig.go
  • pkg/performanceprofile/controller/performanceprofile/components/kubeletconfig/kubeletconfig_test.go
  • pkg/performanceprofile/controller/performanceprofile/components/machineconfig/machineconfig.go
  • pkg/performanceprofile/controller/performanceprofile/components/machineconfig/machineconfig_test.go
  • pkg/performanceprofile/controller/performanceprofile/components/profile/profile.go
  • pkg/performanceprofile/controller/performanceprofile/components/tuned/tuned.go
  • pkg/performanceprofile/controller/performanceprofile/components/tuned/tuned_test.go
  • pkg/performanceprofile/controller/performanceprofile/components/utils.go
  • pkg/performanceprofile/controller/performanceprofile/components/utils_test.go
  • pkg/performanceprofile/controller/performanceprofile/hypershift/components/handler.go
  • pkg/performanceprofile/controller/performanceprofile/status/errors.go
  • pkg/performanceprofile/controller/performanceprofile/status/status.go
  • pkg/performanceprofile/controller/performanceprofile_controller.go
  • pkg/performanceprofile/controller/performanceprofile_controller_test.go
  • test/e2e/performanceprofile/functests/2_performance_update/dedicatedcpus.go
  • test/e2e/performanceprofile/functests/3_performance_status/status.go
  • test/e2e/performanceprofile/functests/7_performance_kubelet_node/cgroups.go
  • test/e2e/performanceprofile/functests/utils/label/label.go

Comment thread assets/performanceprofile/scripts/clear-irqbalance-banned-cpus.sh
Comment thread assets/performanceprofile/scripts/dedicated-cpus-configure.sh Outdated
@Tal-or Tal-or force-pushed the dedicate_cpus_for_dpdk_vswitch branch from 06b8810 to da5383b Compare June 14, 2026 16:15
@openshift-ci openshift-ci Bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jun 14, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/e2e/performanceprofile/functests/2_performance_update/dedicatedcpus.go`:
- Around line 123-128: The ResourceVersion comparison logic is broken because
initialProfile.ResourceVersion is assigned to equal
currentProfile.ResourceVersion on line 123, making the condition on line 126
that checks if initialProfile.ResourceVersion != currentProfile.ResourceVersion
always false. To fix this, capture the ResourceVersion value from currentProfile
into a separate variable before calling UpdateWithRetry on initialProfile, then
compare the ResourceVersion of initialProfile after the update against that
captured value to determine whether to call WaitForTuningUpdating and
WaitForTuningUpdated.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 8a529944-7ec1-4ca7-94e0-208d31d38f09

📥 Commits

Reviewing files that changed from the base of the PR and between 06b8810 and da5383b.

📒 Files selected for processing (31)
  • assets/performanceprofile/configs/dedicatedcpus.slice
  • assets/performanceprofile/scripts/clear-irqbalance-banned-cpus.sh
  • assets/performanceprofile/scripts/dedicated-cpus-configure.sh
  • pkg/performanceprofile/controller/performanceprofile/components/kubeletconfig/kubeletconfig.go
  • pkg/performanceprofile/controller/performanceprofile/components/kubeletconfig/kubeletconfig_test.go
  • pkg/performanceprofile/controller/performanceprofile/components/machineconfig/machineconfig.go
  • pkg/performanceprofile/controller/performanceprofile/components/machineconfig/machineconfig_test.go
  • pkg/performanceprofile/controller/performanceprofile/components/tuned/tuned.go
  • pkg/performanceprofile/controller/performanceprofile/components/tuned/tuned_test.go
  • test/e2e/performanceprofile/functests/2_performance_update/dedicatedcpus.go
  • test/e2e/performanceprofile/functests/3_performance_status/status.go
  • test/e2e/performanceprofile/functests/7_performance_kubelet_node/cgroups.go
  • test/e2e/performanceprofile/functests/utils/cluster/cluster.go
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/extra-mcp/openshift-bootstrap-master_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/extra-mcp/openshift-bootstrap-master_tuned.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/extra-mcp/openshift-bootstrap-worker_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/extra-mcp/openshift-bootstrap-worker_tuned.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/no-mcp/openshift-bootstrap-master_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/no-mcp/openshift-bootstrap-master_tuned.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/no-mcp/openshift-bootstrap-worker_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/no-mcp/openshift-bootstrap-worker_tuned.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/arm/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/arm/manual_tuned.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/cpuFrequency/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/cpuFrequency/manual_tuned.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/manual_tuned.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/pp-norps/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/pp-norps/manual_tuned.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/no-ref/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/no-ref/manual_tuned.yaml
✅ Files skipped from review due to trivial changes (8)
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/extra-mcp/openshift-bootstrap-master_tuned.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/arm/manual_tuned.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/extra-mcp/openshift-bootstrap-worker_tuned.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/no-mcp/openshift-bootstrap-worker_tuned.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/pp-norps/manual_tuned.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/no-mcp/openshift-bootstrap-master_tuned.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/no-ref/manual_tuned.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/manual_tuned.yaml
🚧 Files skipped from review as they are similar to previous changes (11)
  • test/e2e/performanceprofile/functests/7_performance_kubelet_node/cgroups.go
  • assets/performanceprofile/scripts/dedicated-cpus-configure.sh
  • pkg/performanceprofile/controller/performanceprofile/components/tuned/tuned.go
  • assets/performanceprofile/scripts/clear-irqbalance-banned-cpus.sh
  • pkg/performanceprofile/controller/performanceprofile/components/tuned/tuned_test.go
  • assets/performanceprofile/configs/dedicatedcpus.slice
  • pkg/performanceprofile/controller/performanceprofile/components/machineconfig/machineconfig_test.go
  • test/e2e/performanceprofile/functests/3_performance_status/status.go
  • pkg/performanceprofile/controller/performanceprofile/components/kubeletconfig/kubeletconfig.go
  • pkg/performanceprofile/controller/performanceprofile/components/machineconfig/machineconfig.go
  • pkg/performanceprofile/controller/performanceprofile/components/kubeletconfig/kubeletconfig_test.go

Comment thread test/e2e/performanceprofile/functests/2_performance_update/dedicatedcpus.go Outdated
@Tal-or Tal-or force-pushed the dedicate_cpus_for_dpdk_vswitch branch from da5383b to d99723e Compare June 15, 2026 05:28
@openshift-ci openshift-ci Bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jun 15, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/e2e/performanceprofile/functests/2_performance_update/dedicatedcpus.go`:
- Around line 277-282: The test code logs the irqbalance configuration content
in `irqConfWithPod` but never asserts that it actually contains the dedicated
CPU mask as indicated by the "Verifying IRQBALANCE_BANNED_CPUS still includes
dedicated CPUs with pod running" message. After logging the content, add an
assertion that verifies `irqConfWithPod` contains the expected dedicated CPU
mask value to catch regressions where the configuration changes while the pod is
running.

In `@test/e2e/performanceprofile/functests/7_performance_kubelet_node/cgroups.go`:
- Around line 755-808: The test modifies the cluster profile (setting
DisableOvsDynamicPinning to true) and creates a GU pod, but the cleanup logic
that reverts the profile and deletes the pod only runs if all preceding
assertions pass. If any assertion fails, the cluster state remains mutated and
can affect subsequent tests. Use Ginkgo's DeferCleanup hook at the beginning of
the test (after saving the original spec) to guarantee that both the GU pod
deletion and profile reversion happen regardless of assertion failures. Wrap the
pod deletion logic and the profile revert logic (which currently happens at the
end with savedSpec restoration) inside a DeferCleanup callback that will execute
even if tests fail earlier.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: b187dc62-06d1-4163-9577-b3001646f97e

📥 Commits

Reviewing files that changed from the base of the PR and between da5383b and d99723e.

⛔ Files ignored due to path filters (1)
  • pkg/apis/performanceprofile/v2/zz_generated.deepcopy.go is excluded by !**/zz_generated*
📒 Files selected for processing (37)
  • assets/performanceprofile/configs/dedicatedcpus.slice
  • assets/performanceprofile/scripts/clear-irqbalance-banned-cpus.sh
  • assets/performanceprofile/scripts/dedicated-cpus-configure.sh
  • manifests/20-performance-profile.crd.yaml
  • pkg/apis/performanceprofile/v2/performanceprofile_types.go
  • pkg/apis/performanceprofile/v2/performanceprofile_validation.go
  • pkg/apis/performanceprofile/v2/performanceprofile_validation_test.go
  • pkg/performanceprofile/controller/performanceprofile/components/components.go
  • pkg/performanceprofile/controller/performanceprofile/components/handler/handler.go
  • pkg/performanceprofile/controller/performanceprofile/components/kubeletconfig/kubeletconfig.go
  • pkg/performanceprofile/controller/performanceprofile/components/kubeletconfig/kubeletconfig_test.go
  • pkg/performanceprofile/controller/performanceprofile/components/machineconfig/machineconfig.go
  • pkg/performanceprofile/controller/performanceprofile/components/machineconfig/machineconfig_test.go
  • pkg/performanceprofile/controller/performanceprofile/components/profile/profile.go
  • pkg/performanceprofile/controller/performanceprofile/components/tuned/tuned.go
  • pkg/performanceprofile/controller/performanceprofile/components/tuned/tuned_test.go
  • pkg/performanceprofile/controller/performanceprofile/components/utils.go
  • pkg/performanceprofile/controller/performanceprofile/components/utils_test.go
  • pkg/performanceprofile/controller/performanceprofile/hypershift/components/handler.go
  • pkg/performanceprofile/controller/performanceprofile/status/errors.go
  • pkg/performanceprofile/controller/performanceprofile/status/status.go
  • pkg/performanceprofile/controller/performanceprofile_controller.go
  • pkg/performanceprofile/controller/performanceprofile_controller_test.go
  • test/e2e/performanceprofile/functests/2_performance_update/dedicatedcpus.go
  • test/e2e/performanceprofile/functests/3_performance_status/status.go
  • test/e2e/performanceprofile/functests/7_performance_kubelet_node/cgroups.go
  • test/e2e/performanceprofile/functests/utils/cluster/cluster.go
  • test/e2e/performanceprofile/functests/utils/label/label.go
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/extra-mcp/openshift-bootstrap-master_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/extra-mcp/openshift-bootstrap-worker_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/no-mcp/openshift-bootstrap-master_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/no-mcp/openshift-bootstrap-worker_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/arm/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/cpuFrequency/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/pp-norps/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/no-ref/manual_machineconfig.yaml
✅ Files skipped from review due to trivial changes (3)
  • pkg/performanceprofile/controller/performanceprofile/status/status.go
  • assets/performanceprofile/configs/dedicatedcpus.slice
  • test/e2e/performanceprofile/functests/utils/label/label.go
🚧 Files skipped from review as they are similar to previous changes (29)
  • pkg/performanceprofile/controller/performanceprofile/status/errors.go
  • test/e2e/performanceprofile/functests/utils/cluster/cluster.go
  • pkg/performanceprofile/controller/performanceprofile/components/components.go
  • pkg/apis/performanceprofile/v2/performanceprofile_validation.go
  • assets/performanceprofile/scripts/dedicated-cpus-configure.sh
  • pkg/performanceprofile/controller/performanceprofile/components/tuned/tuned.go
  • pkg/performanceprofile/controller/performanceprofile/components/utils_test.go
  • test/e2e/performanceprofile/testdata/render-expected-output/no-ref/manual_machineconfig.yaml
  • pkg/performanceprofile/controller/performanceprofile/components/profile/profile.go
  • pkg/performanceprofile/controller/performanceprofile_controller.go
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/no-mcp/openshift-bootstrap-worker_machineconfig.yaml
  • test/e2e/performanceprofile/functests/3_performance_status/status.go
  • pkg/performanceprofile/controller/performanceprofile/components/utils.go
  • pkg/apis/performanceprofile/v2/performanceprofile_types.go
  • manifests/20-performance-profile.crd.yaml
  • pkg/performanceprofile/controller/performanceprofile/hypershift/components/handler.go
  • pkg/apis/performanceprofile/v2/performanceprofile_validation_test.go
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/extra-mcp/openshift-bootstrap-master_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/arm/manual_machineconfig.yaml
  • pkg/performanceprofile/controller/performanceprofile/components/machineconfig/machineconfig_test.go
  • pkg/performanceprofile/controller/performanceprofile/components/kubeletconfig/kubeletconfig.go
  • pkg/performanceprofile/controller/performanceprofile_controller_test.go
  • assets/performanceprofile/scripts/clear-irqbalance-banned-cpus.sh
  • test/e2e/performanceprofile/testdata/render-expected-output/default/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/pp-norps/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/no-mcp/openshift-bootstrap-master_machineconfig.yaml
  • pkg/performanceprofile/controller/performanceprofile/components/kubeletconfig/kubeletconfig_test.go
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/extra-mcp/openshift-bootstrap-worker_machineconfig.yaml
  • pkg/performanceprofile/controller/performanceprofile/components/machineconfig/machineconfig.go

Comment thread test/e2e/performanceprofile/functests/2_performance_update/dedicatedcpus.go Outdated
Comment on lines +755 to +808
By("Setting disableOvsDynamicPinning=true on the profile")
currentProfile, err := profiles.GetByNodeLabels(testutils.NodeSelectorLabels)
Expect(err).ToNot(HaveOccurred())
savedSpec := *currentProfile.Spec.DeepCopy()

if currentProfile.Spec.Net == nil {
currentProfile.Spec.Net = &performancev2.Net{}
}
currentProfile.Spec.Net.DisableOvsDynamicPinning = ptr.To(true)
profiles.UpdateWithRetry(currentProfile)

profilesupdate.WaitForTuningUpdating(ctx, currentProfile)
profilesupdate.WaitForTuningUpdated(ctx, currentProfile)

By("Verifying the activation file is absent after disabling")
_, err = nodes.ExecCommand(ctx, workerRTNode, cmd)
Expect(err).To(HaveOccurred(),
"activation file should not exist when disableOvsDynamicPinning=true")

By("Verifying OVS processes retain their systemd service affinity")
ovsAffinitiesAfter := getOvsAffinities(ctx, ovsSystemdServices, workerRTNode)
for pid, mask := range ovsAffinitiesAfter {
testlog.Infof("OVS pid %s affinity with dynamic pinning disabled: %s", pid, mask)
}

By("Creating a GU pod and verifying OVS affinity does not change")
guPod := createGuPod(ctx, workerRTNode)
ovsAffinitiesWithPod := getOvsAffinities(ctx, ovsSystemdServices, workerRTNode)
for pid, mask := range ovsAffinitiesWithPod {
testlog.Infof("OVS pid %s affinity with GU pod (dynamic pinning disabled): %s", pid, mask)
if afterMask, ok := ovsAffinitiesAfter[pid]; ok {
Expect(mask.Equals(afterMask)).To(BeTrue(),
fmt.Sprintf("OVS pid %s affinity should not change with dynamic pinning disabled (before: %s, after: %s)",
pid, afterMask, mask))
}
}

By("Deleting the GU pod")
Expect(pods.DeleteAndSync(ctx, testclient.DataPlaneClient, guPod)).To(Succeed())

By("Reverting the profile to re-enable OVS dynamic pinning")
currentProfile, err = profiles.GetByNodeLabels(testutils.NodeSelectorLabels)
Expect(err).ToNot(HaveOccurred())
currentProfile.Spec = savedSpec
profiles.UpdateWithRetry(currentProfile)

profilesupdate.WaitForTuningUpdating(ctx, currentProfile)
profilesupdate.WaitForTuningUpdated(ctx, currentProfile)

By("Verifying the activation file is back after re-enabling")
_, err = nodes.ExecCommand(ctx, workerRTNode, cmd)
Expect(err).ToNot(HaveOccurred(),
"activation file should exist after re-enabling OVS dynamic pinning")
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Guarantee rollback/cleanup even when assertions fail.

This spec updates the cluster profile and creates a GU pod, but cleanup/revert runs only on the happy path. Any earlier failure can leave mutated cluster state behind and cascade into later tests.

Suggested hardening (use Ginkgo cleanup hooks)
- savedSpec := *currentProfile.Spec.DeepCopy()
+ savedSpec := *currentProfile.Spec.DeepCopy()
+ var guPod *corev1.Pod
+ DeferCleanup(func() {
+   if guPod != nil {
+     _ = pods.DeleteAndSync(ctx, testclient.DataPlaneClient, guPod)
+   }
+   p, err := profiles.GetByNodeLabels(testutils.NodeSelectorLabels)
+   if err == nil {
+     p.Spec = savedSpec
+     profiles.UpdateWithRetry(p)
+     profilesupdate.WaitForTuningUpdating(ctx, p)
+     profilesupdate.WaitForTuningUpdated(ctx, p)
+   }
+ })
...
- guPod := createGuPod(ctx, workerRTNode)
+ guPod = createGuPod(ctx, workerRTNode)
...
- By("Reverting the profile to re-enable OVS dynamic pinning")
- currentProfile, err = profiles.GetByNodeLabels(testutils.NodeSelectorLabels)
- ...

As per coding guidelines, "Review Ginkgo test code for proper setup and cleanup: use BeforeEach/AfterEach for setup and cleanup. Flag tests that create cluster-scoped resources without cleanup".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/e2e/performanceprofile/functests/7_performance_kubelet_node/cgroups.go`
around lines 755 - 808, The test modifies the cluster profile (setting
DisableOvsDynamicPinning to true) and creates a GU pod, but the cleanup logic
that reverts the profile and deletes the pod only runs if all preceding
assertions pass. If any assertion fails, the cluster state remains mutated and
can affect subsequent tests. Use Ginkgo's DeferCleanup hook at the beginning of
the test (after saving the original spec) to guarantee that both the GU pod
deletion and profile reversion happen regardless of assertion failures. Wrap the
pod deletion logic and the profile revert logic (which currently happens at the
end with savedSpec restoration) inside a DeferCleanup callback that will execute
even if tests fail earlier.

Source: Coding guidelines

@Tal-or Tal-or force-pushed the dedicate_cpus_for_dpdk_vswitch branch from d99723e to daee559 Compare June 15, 2026 05:48

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/e2e/performanceprofile/functests/2_performance_update/dedicatedcpus.go`:
- Around line 192-197: Add assertions to validate that the default_smp_affinity
value excludes dedicated CPUs, rather than only logging the value. In the
dedicatedcpus.go file at lines 192-197, after logging smpAffinityStr, add an
Expect assertion to verify that the smpAffinityStr contains the correct affinity
mask that excludes dedicated CPUs. Apply the same assertion pattern at the
sibling locations in the same file at lines 239-244 and 298-303, ensuring each
verification step includes both the informational log and a concrete assertion
that validates the expected behavior instead of leaving the check untested.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 3bc8e3b8-924f-44f4-a51e-3af12547d98d

📥 Commits

Reviewing files that changed from the base of the PR and between d99723e and daee559.

📒 Files selected for processing (22)
  • assets/performanceprofile/configs/dedicatedcpus.slice
  • assets/performanceprofile/scripts/clear-irqbalance-banned-cpus.sh
  • assets/performanceprofile/scripts/dedicated-cpus-configure.sh
  • pkg/performanceprofile/controller/performanceprofile/components/kubeletconfig/kubeletconfig.go
  • pkg/performanceprofile/controller/performanceprofile/components/kubeletconfig/kubeletconfig_test.go
  • pkg/performanceprofile/controller/performanceprofile/components/machineconfig/machineconfig.go
  • pkg/performanceprofile/controller/performanceprofile/components/machineconfig/machineconfig_test.go
  • pkg/performanceprofile/controller/performanceprofile/components/tuned/tuned.go
  • pkg/performanceprofile/controller/performanceprofile/components/tuned/tuned_test.go
  • test/e2e/performanceprofile/functests/2_performance_update/dedicatedcpus.go
  • test/e2e/performanceprofile/functests/3_performance_status/status.go
  • test/e2e/performanceprofile/functests/7_performance_kubelet_node/cgroups.go
  • test/e2e/performanceprofile/functests/utils/cluster/cluster.go
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/extra-mcp/openshift-bootstrap-master_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/extra-mcp/openshift-bootstrap-worker_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/no-mcp/openshift-bootstrap-master_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/no-mcp/openshift-bootstrap-worker_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/arm/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/cpuFrequency/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/pp-norps/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/no-ref/manual_machineconfig.yaml
🚧 Files skipped from review as they are similar to previous changes (20)
  • assets/performanceprofile/configs/dedicatedcpus.slice
  • assets/performanceprofile/scripts/dedicated-cpus-configure.sh
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/extra-mcp/openshift-bootstrap-worker_machineconfig.yaml
  • test/e2e/performanceprofile/functests/utils/cluster/cluster.go
  • pkg/performanceprofile/controller/performanceprofile/components/machineconfig/machineconfig_test.go
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/no-mcp/openshift-bootstrap-master_machineconfig.yaml
  • pkg/performanceprofile/controller/performanceprofile/components/tuned/tuned.go
  • pkg/performanceprofile/controller/performanceprofile/components/tuned/tuned_test.go
  • test/e2e/performanceprofile/testdata/render-expected-output/default/arm/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/cpuFrequency/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/pp-norps/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/no-ref/manual_machineconfig.yaml
  • test/e2e/performanceprofile/functests/3_performance_status/status.go
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/no-mcp/openshift-bootstrap-worker_machineconfig.yaml
  • assets/performanceprofile/scripts/clear-irqbalance-banned-cpus.sh
  • pkg/performanceprofile/controller/performanceprofile/components/kubeletconfig/kubeletconfig_test.go
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/extra-mcp/openshift-bootstrap-master_machineconfig.yaml
  • test/e2e/performanceprofile/functests/7_performance_kubelet_node/cgroups.go
  • pkg/performanceprofile/controller/performanceprofile/components/kubeletconfig/kubeletconfig.go
  • pkg/performanceprofile/controller/performanceprofile/components/machineconfig/machineconfig.go

Comment thread test/e2e/performanceprofile/functests/2_performance_update/dedicatedcpus.go Outdated
@Tal-or Tal-or force-pushed the dedicate_cpus_for_dpdk_vswitch branch from daee559 to 787f61e Compare June 15, 2026 09:11

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
test/e2e/performanceprofile/functests/2_performance_update/dedicatedcpus.go (1)

92-98: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Merge strict-cpu-reservation instead of replacing the whole experimental annotation.

Line 97 overwrites any existing kubeletconfig.experimental payload, so this e2e update can temporarily drop unrelated kubelet options from the target profile. Preserve existing JSON and only set cpuManagerPolicyOptions["strict-cpu-reservation"].

Suggested approach
 import (
 	"context"
+	"encoding/json"
 	"fmt"
 	"strings"
 	"time"
@@
 		if !isWPEnabled {
 			testlog.Infof("Workload partitioning not enabled, adding strict-cpu-reservation via experimental annotation")
 			if currentProfile.Annotations == nil {
 				currentProfile.Annotations = make(map[string]string)
 			}
-			currentProfile.Annotations["kubeletconfig.experimental"] = `{"cpuManagerPolicyOptions": {"strict-cpu-reservation": "true"}}`
+			experimental := map[string]interface{}{}
+			if raw := currentProfile.Annotations["kubeletconfig.experimental"]; raw != "" {
+				Expect(json.Unmarshal([]byte(raw), &experimental)).To(Succeed())
+			}
+			policyOptions, ok := experimental["cpuManagerPolicyOptions"].(map[string]interface{})
+			if !ok {
+				policyOptions = map[string]interface{}{}
+				experimental["cpuManagerPolicyOptions"] = policyOptions
+			}
+			policyOptions["strict-cpu-reservation"] = "true"
+			raw, err := json.Marshal(experimental)
+			Expect(err).ToNot(HaveOccurred())
+			currentProfile.Annotations["kubeletconfig.experimental"] = string(raw)
 		}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/e2e/performanceprofile/functests/2_performance_update/dedicatedcpus.go`
around lines 92 - 98, The annotation assignment at line 97 in the
dedicatedcpus.go file unconditionally overwrites the entire
`kubeletconfig.experimental` annotation value, losing any existing kubelet
configuration options. Instead of directly assigning a new JSON string, check if
the annotation already exists, parse the existing JSON payload, merge the
`cpuManagerPolicyOptions.strict-cpu-reservation` setting into it while
preserving other existing options, and only then set the merged result back to
the annotation. This ensures unrelated kubelet options are not dropped during
the e2e update.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/e2e/performanceprofile/functests/2_performance_update/dedicatedcpus.go`:
- Around line 267-285: Register pod cleanup immediately after the testpod is
successfully created using DeferCleanup to ensure the pod is cleaned up even if
the test fails at any subsequent step. Add a DeferCleanup call right after the
successful testclient.DataPlaneClient.Create(ctx, testpod) call that registers
deletion of the testpod, while keeping the explicit Delete call at line 282 to
maintain the test's lifecycle assertion flow. This ensures that if
WaitForCondition, the QoS assertion, or any later check fails, the pod will
still be cleaned up and not left running when AfterAll reverts the profile.

---

Duplicate comments:
In `@test/e2e/performanceprofile/functests/2_performance_update/dedicatedcpus.go`:
- Around line 92-98: The annotation assignment at line 97 in the
dedicatedcpus.go file unconditionally overwrites the entire
`kubeletconfig.experimental` annotation value, losing any existing kubelet
configuration options. Instead of directly assigning a new JSON string, check if
the annotation already exists, parse the existing JSON payload, merge the
`cpuManagerPolicyOptions.strict-cpu-reservation` setting into it while
preserving other existing options, and only then set the merged result back to
the annotation. This ensures unrelated kubelet options are not dropped during
the e2e update.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 915ee603-f527-41d5-bdaf-93cf27bf5671

📥 Commits

Reviewing files that changed from the base of the PR and between daee559 and 787f61e.

📒 Files selected for processing (13)
  • test/e2e/performanceprofile/functests/2_performance_update/dedicatedcpus.go
  • test/e2e/performanceprofile/functests/3_performance_status/status.go
  • test/e2e/performanceprofile/functests/7_performance_kubelet_node/cgroups.go
  • test/e2e/performanceprofile/functests/utils/cluster/cluster.go
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/extra-mcp/openshift-bootstrap-master_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/extra-mcp/openshift-bootstrap-worker_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/no-mcp/openshift-bootstrap-master_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/no-mcp/openshift-bootstrap-worker_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/arm/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/cpuFrequency/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/pp-norps/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/no-ref/manual_machineconfig.yaml
🚧 Files skipped from review as they are similar to previous changes (9)
  • test/e2e/performanceprofile/testdata/render-expected-output/no-ref/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/no-mcp/openshift-bootstrap-worker_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/no-mcp/openshift-bootstrap-master_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/extra-mcp/openshift-bootstrap-master_machineconfig.yaml
  • test/e2e/performanceprofile/functests/7_performance_kubelet_node/cgroups.go
  • test/e2e/performanceprofile/testdata/render-expected-output/default/arm/manual_machineconfig.yaml
  • test/e2e/performanceprofile/functests/3_performance_status/status.go
  • test/e2e/performanceprofile/testdata/render-expected-output/default/pp-norps/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/cpuFrequency/manual_machineconfig.yaml

@Tal-or Tal-or force-pushed the dedicate_cpus_for_dpdk_vswitch branch 4 times, most recently from b10178c to c58e443 Compare June 16, 2026 09:46
@Tal-or

Tal-or commented Jun 16, 2026

Copy link
Copy Markdown
Contributor Author

/retest

1 similar comment
@Tal-or

Tal-or commented Jun 16, 2026

Copy link
Copy Markdown
Contributor Author

/retest

@Tal-or Tal-or force-pushed the dedicate_cpus_for_dpdk_vswitch branch from c58e443 to f398b31 Compare June 29, 2026 08:31
@Tal-or

Tal-or commented Jun 29, 2026

Copy link
Copy Markdown
Contributor Author

/retest

@amorenoz

amorenoz commented Jun 29, 2026

Copy link
Copy Markdown

Setting disableOvsDynamicPinning prevents OVN-Kubernetes from dynamically adjusting OVS thread CPU affinity on the target nodes.

@Tal-or Disabling OVS Pinning will have a negative impact if we enable workload partitioning. For our use-case we are trying to make ovn-kubernetes skip pmd threads instead: ovn-kubernetes/ovn-kubernetes#6500.

Are there any additional reasons you want to expose this to the API?

@Tal-or

Tal-or commented Jun 29, 2026

Copy link
Copy Markdown
Contributor Author

Setting disableOvsDynamicPinning prevents OVN-Kubernetes from dynamically adjusting OVS thread CPU affinity on the target nodes.

@Tal-or Disabling OVS Pinning will have a negative impact if we enable workload partitioning. For our use-case we are trying to make ovn-kubernetes skip pmd threads instead: ovn-kubernetes/ovn-kubernetes#6500.

Are there any additional reasons you want to expose this to the API?

@amorenoz we're disabling the dynamic pinning so they won't interfere with the OVS DPDK.
I see that that's what you're trying to do on ovn-kubernetes/ovn-kubernetes#6500.

But setting disableOvsDynamicPinning: true will give you exactly that - it will remove the enabler file which in turn shut the ovs dynamic pinning and then the ovsvswitchd and ovsdb services will be bound to reserved CPUs, and won't spill over to the other cores.

@yanirq

yanirq commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

/cc @MarSik

@openshift-ci openshift-ci Bot requested a review from MarSik June 30, 2026 09:20
@mcoquelin

Copy link
Copy Markdown

Hi @Tal-or,

I am currently testing this PR with OVS-DPDK.
I am not clear once the 'dedicated' CPU set is configured in the performance profile, how ovs-vswitchd can use it.
Given ovs-vswitchd uses ovs.slice and not dedicatedcpus.slice, how can I pin only the PMD threads to dedicated CPUs?

@jmencak jmencak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was looking at this from the end-user perspective. I wanted to test this, but I didn't get past issues starting kubelet when configuring:

  kubeletConfig: 
    cpuManagerPolicy: static
    cpuManagerPolicyOptions:
      strict-cpu-reservation: "true"

I left some comments WRT validating user input. I also wonder if we're handling overlapping of Dedicated CPUs with other CPU types correctly.

if dedicatedCPUs != "" {
dedicatedMask, err := components.CPUListToHexMask(dedicatedCPUs)
if err != nil {
klog.Errorf("failed to convert dedicated CPUs %q to hex mask: %v", dedicatedCPUs, err)

@jmencak jmencak Jul 3, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this ever happen? If so (e.g. no webhook to check user-supplied values, or insufficient check for user error input), is the error in the logs sufficient to inform the user about the failure? I.e. the fact IRQ banning is not applied properly as user expected (DEDICATED_CPUS unset)? There will probably be no error status condition set in PerformanceProfile, right? Also, isn't the bad value (0) going to get propagated to default_smp_affinity?

Edit: empty dedicated CPUs will end up with Degraded PerformanceProfile, so I guess that's what we want. Alternatively, we may decide not to allow empty dedicated CPUs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it should be checked during the API validation. I'll revise this code, thanks.

Comment thread assets/performanceprofile/scripts/clear-irqbalance-banned-cpus.sh
Comment thread test/e2e/performanceprofile/functests/utils/pods/pods.go Outdated
@Tal-or Tal-or force-pushed the dedicate_cpus_for_dpdk_vswitch branch 2 times, most recently from 85a0a8c to 388eb0f Compare July 9, 2026 12:39
@Tal-or Tal-or marked this pull request as draft July 9, 2026 12:40
@openshift-ci openshift-ci Bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jul 9, 2026
@Tal-or Tal-or force-pushed the dedicate_cpus_for_dpdk_vswitch branch 2 times, most recently from 85fe14d to dd82c29 Compare July 9, 2026 13:38
@Tal-or

Tal-or commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@Tal-or

Tal-or commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai reedit release note summary for PR description

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

@Tal-or Sure, I'll regenerate the release notes summary for the PR description.

✅ Action performed

Summary regeneration triggered.

@Tal-or Tal-or force-pushed the dedicate_cpus_for_dpdk_vswitch branch 2 times, most recently from 3d17715 to 081b505 Compare July 9, 2026 13:55

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

♻️ Duplicate comments (1)
test/e2e/performanceprofile/functests/2_performance_update/ovsdpdk.go (1)

304-328: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

GU pod is not cleaned up if an assertion fails before the explicit Delete at Line 339.

If WaitForCondition, the QoS assertion (Line 327), or the banned-CPU assertion (Lines 330-336) fails, testpod is left running with no cleanup path since deletion only happens explicitly later in the happy path.

🔧 Suggested fix
 			err = testclient.DataPlaneClient.Create(ctx, testpod)
 			Expect(err).ToNot(HaveOccurred())
+			DeferCleanup(func() {
+				cleanupCtx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
+				defer cancel()
+				err := testclient.DataPlaneClient.Delete(cleanupCtx, testpod)
+				Expect(client.IgnoreNotFound(err)).ToNot(HaveOccurred())
+			})
 
 			podKey := client.ObjectKeyFromObject(testpod)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/e2e/performanceprofile/functests/2_performance_update/ovsdpdk.go` around
lines 304 - 328, The GU pod created in the OVS DPDK performance update test is
only deleted in the happy path, so failures in WaitForCondition, the QOS
assertion, or the banned-CPU check can leave it behind. Add a cleanup path
immediately after creating the pod in the test flow (around the testpod setup
and Create/WaitForCondition logic) so deletion always runs on failure, using the
existing testpod variable and the test client cleanup pattern rather than
relying on the later explicit Delete.
🧹 Nitpick comments (1)
pkg/performanceprofile/controller/performanceprofile/components/assets_scripts_test.go (1)

131-170: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a 3-group (>64 CPU) test case to fulfill the earlier test-coverage commitment.

All DescribeTable entries use at most 2 hex groups (≤64 CPUs). jmencak specifically asked for coverage on systems with more than 64 CPUs to avoid silent bugs, and this was acknowledged ("Agreed, will do."). Consider adding an entry with 3 groups, e.g. "ffffffff,ffffffff,ffffffff" with a banned mask spanning the third group, to validate the loop's generality beyond 2 groups.

Suggested additional entry
Entry("three groups (>64 cpus), ban in highest group", "ffffffff,ffffffff,ffffffff", "0000000c0000000000000000", "fffffff3,ffffffff,ffffffff"),
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@pkg/performanceprofile/controller/performanceprofile/components/assets_scripts_test.go`
around lines 131 - 170, Add a new DescribeTable entry in assets_scripts_test.go
for a 3-group OVS_DPDK_CPUS mask to cover systems with more than 64 CPUs, since
all current cases in the ClearIRQBalanceBannedCPUs test only exercise up to two
hex groups. Update the table around the existing ClearIRQBalanceBannedCPUs
entries to include a case where the banned CPUs are in the highest group, and
assert the resulting default_smp_affinity preserves the other two groups
unchanged while clearing the targeted bits.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/apis/performanceprofile/v2/performanceprofile_types.go`:
- Around line 145-150: Fix the grammar in the OvsDpdk field comment so the
generated CRD/docs are correct: in the comment on OvsDpdk, change the sentence
about “WorkloadPartitioning or --strict-cpu-reservation kubelet CPUManager
policy option” to use a singular verb (“is a prerequisite”). Keep the rest of
the descriptive text unchanged so the comment remains the source for oc explain
and documentation generation.

In
`@pkg/performanceprofile/controller/performanceprofile/components/machineconfig/machineconfig_test.go`:
- Around line 608-623: The negative test in
New/clear-irqbalance-banned-cpus.service is checking the wrong string and can
pass even if the behavior is broken. Update the assertion in the
machineconfig_test.go case to verify the service contents do not contain
OVS_DPDK_CPUS, matching the positive expectation used in the nearby test for
OvsDpdkCPUs, and keep the check scoped to the
clear-irqbalance-banned-cpus.service unit content.

In
`@pkg/performanceprofile/controller/performanceprofile/components/machineconfig/machineconfig.go`:
- Around line 556-577: getIRQBalanceBannedCPUsOptions is swallowing
CPUListToHexMask failures and silently omitting the OVS_DPDK_CPUS environment
option; change it to return an error instead of just logging and returning opts.
Update the caller that builds the MachineConfig to handle this error explicitly,
so the failure is surfaced and can mark the profile Degraded rather than
producing a partially rendered config. Ensure the error path stays tied to
getIRQBalanceBannedCPUsOptions and the MachineConfig generation flow that
consumes its result.

In
`@pkg/performanceprofile/controller/performanceprofile/components/tuned/tuned_test.go`:
- Around line 744-764: The two tests in tuned_test.go only validate static or
unrelated values, so they do not prove OvsDpdk CPUs are handled correctly.
Update the test around getTunedStructuredData to assert the rendered bootloader
cmdline fields that expand isolated_cores and not_isolated_cores_expanded, and
verify the resulting nohz_full/rcu_nocbs/systemd.cpu_affinity values actually
include or exclude the OvsDpdk CPU set. Use the existing helpers and symbols
like getTunedStructuredData, bootLoaderSection, variables, and isolated_cores to
locate the right assertions.

In `@pkg/performanceprofile/controller/performanceprofile/status/errors.go`:
- Around line 16-22: The error text produced by NewOvsDpdkCPUsPrerequisiteError
in errors.go uses lowercase “ovs-dpdk cpus”, but the test in
performanceprofile_controller_test.go expects a capitalized substring, so the
case-sensitive match will fail. Update the test expectation to match the actual
message returned by NewOvsDpdkCPUsPrerequisiteError (or otherwise make both
strings identical), keeping the substring consistent with the error string used
by OvsDpdkCPUsPrerequisiteError.

In `@test/e2e/performanceprofile/functests/2_performance_update/ovsdpdk.go`:
- Around line 88-100: The BeforeAll setup in ovsdpdk.go adds
currentProfile.Annotations["kubeletconfig.experimental"] when workload
partitioning is disabled, but AfterAll only restores Spec and removes the
OvsDpdk disable annotation. Update the AfterAll cleanup to also delete the
kubeletconfig.experimental annotation (or restore annotations to their original
state) in the same currentProfile handling path so the suite leaves no lingering
cluster state.

---

Duplicate comments:
In `@test/e2e/performanceprofile/functests/2_performance_update/ovsdpdk.go`:
- Around line 304-328: The GU pod created in the OVS DPDK performance update
test is only deleted in the happy path, so failures in WaitForCondition, the QOS
assertion, or the banned-CPU check can leave it behind. Add a cleanup path
immediately after creating the pod in the test flow (around the testpod setup
and Create/WaitForCondition logic) so deletion always runs on failure, using the
existing testpod variable and the test client cleanup pattern rather than
relying on the later explicit Delete.

---

Nitpick comments:
In
`@pkg/performanceprofile/controller/performanceprofile/components/assets_scripts_test.go`:
- Around line 131-170: Add a new DescribeTable entry in assets_scripts_test.go
for a 3-group OVS_DPDK_CPUS mask to cover systems with more than 64 CPUs, since
all current cases in the ClearIRQBalanceBannedCPUs test only exercise up to two
hex groups. Update the table around the existing ClearIRQBalanceBannedCPUs
entries to include a case where the banned CPUs are in the highest group, and
assert the resulting default_smp_affinity preserves the other two groups
unchanged while clearing the targeted bits.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: b91ca69d-721e-4b66-b14c-0b8cc502918c

📥 Commits

Reviewing files that changed from the base of the PR and between daee559 and dd82c29.

⛔ Files ignored due to path filters (1)
  • pkg/apis/performanceprofile/v2/zz_generated.deepcopy.go is excluded by !**/zz_generated*
📒 Files selected for processing (39)
  • assets/performanceprofile/scripts/clear-irqbalance-banned-cpus.sh
  • assets/performanceprofile/scripts/ovs-dpdk-cpus-configure.sh
  • docs/performanceprofile/performance_profile.md
  • manifests/20-performance-profile.crd.yaml
  • pkg/apis/performanceprofile/v2/performanceprofile_types.go
  • pkg/apis/performanceprofile/v2/performanceprofile_validation.go
  • pkg/apis/performanceprofile/v2/performanceprofile_validation_test.go
  • pkg/performanceprofile/controller/performanceprofile/components/assets_scripts_test.go
  • pkg/performanceprofile/controller/performanceprofile/components/components.go
  • pkg/performanceprofile/controller/performanceprofile/components/handler/handler.go
  • pkg/performanceprofile/controller/performanceprofile/components/kubeletconfig/kubeletconfig.go
  • pkg/performanceprofile/controller/performanceprofile/components/kubeletconfig/kubeletconfig_test.go
  • pkg/performanceprofile/controller/performanceprofile/components/machineconfig/machineconfig.go
  • pkg/performanceprofile/controller/performanceprofile/components/machineconfig/machineconfig_test.go
  • pkg/performanceprofile/controller/performanceprofile/components/profile/profile.go
  • pkg/performanceprofile/controller/performanceprofile/components/tuned/tuned.go
  • pkg/performanceprofile/controller/performanceprofile/components/tuned/tuned_test.go
  • pkg/performanceprofile/controller/performanceprofile/components/utils.go
  • pkg/performanceprofile/controller/performanceprofile/components/utils_test.go
  • pkg/performanceprofile/controller/performanceprofile/hypershift/components/handler.go
  • pkg/performanceprofile/controller/performanceprofile/status/errors.go
  • pkg/performanceprofile/controller/performanceprofile/status/status.go
  • pkg/performanceprofile/controller/performanceprofile_controller.go
  • pkg/performanceprofile/controller/performanceprofile_controller_test.go
  • test/e2e/performanceprofile/functests/2_performance_update/ovsdpdk.go
  • test/e2e/performanceprofile/functests/3_performance_status/status.go
  • test/e2e/performanceprofile/functests/7_performance_kubelet_node/cgroups.go
  • test/e2e/performanceprofile/functests/utils/cluster/cluster.go
  • test/e2e/performanceprofile/functests/utils/label/label.go
  • test/e2e/performanceprofile/functests/utils/pods/pods.go
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/extra-mcp/openshift-bootstrap-master_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/extra-mcp/openshift-bootstrap-worker_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/no-mcp/openshift-bootstrap-master_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/no-mcp/openshift-bootstrap-worker_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/arm/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/cpuFrequency/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/pp-norps/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/no-ref/manual_machineconfig.yaml
✅ Files skipped from review due to trivial changes (1)
  • test/e2e/performanceprofile/functests/utils/label/label.go
🚧 Files skipped from review as they are similar to previous changes (6)
  • pkg/performanceprofile/controller/performanceprofile/components/utils_test.go
  • test/e2e/performanceprofile/functests/utils/cluster/cluster.go
  • test/e2e/performanceprofile/testdata/render-expected-output/default/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/default/cpuFrequency/manual_machineconfig.yaml
  • test/e2e/performanceprofile/testdata/render-expected-output/bootstrap/extra-mcp/openshift-bootstrap-worker_machineconfig.yaml
  • pkg/performanceprofile/controller/performanceprofile/components/kubeletconfig/kubeletconfig.go

Comment thread pkg/apis/performanceprofile/v2/performanceprofile_types.go
@Tal-or Tal-or force-pushed the dedicate_cpus_for_dpdk_vswitch branch from 081b505 to c72f93c Compare July 9, 2026 14:35
@Tal-or Tal-or marked this pull request as ready for review July 9, 2026 14:37
@openshift-ci openshift-ci Bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jul 9, 2026
@openshift-ci openshift-ci Bot requested a review from jmencak July 9, 2026 14:38
@openshift-ci

openshift-ci Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

@Tal-or: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e-gcp-pao-workloadhints c72f93c link true /test e2e-gcp-pao-workloadhints
ci/prow/e2e-gcp-pao-updating-profile c72f93c link true /test e2e-gcp-pao-updating-profile
ci/prow/vet c72f93c link true /test vet
ci/prow/e2e-hypershift-pao c72f93c link true /test e2e-hypershift-pao
ci/prow/e2e-aws-operator c72f93c link true /test e2e-aws-operator
ci/prow/unit c72f93c link true /test unit
ci/prow/verify c72f93c link true /test verify
ci/prow/e2e-gcp-pao c72f93c link true /test e2e-gcp-pao
ci/prow/verify-deps c72f93c link true /test verify-deps
ci/prow/e2e-aws-nto-ext c72f93c link false /test e2e-aws-nto-ext
ci/prow/e2e-aws-ovn c72f93c link true /test e2e-aws-ovn
ci/prow/e2e-aws-ovn-techpreview c72f93c link true /test e2e-aws-ovn-techpreview
ci/prow/lint c72f93c link true /test lint
ci/prow/e2e-no-cluster c72f93c link true /test e2e-no-cluster
ci/prow/images c72f93c link true /test images
ci/prow/e2e-upgrade c72f93c link true /test e2e-upgrade
ci/prow/e2e-hypershift c72f93c link true /test e2e-hypershift
ci/prow/okd-scos-images c72f93c link true /test okd-scos-images

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Tal-or added 7 commits July 9, 2026 17:40
… API

Add a new optional field spec.cpu.ovsDpdk (type CPUSet) for reserving CPUs
for ovsDpdk PMD threads. Add annotation constant
performance.openshift.io/disable-load-balancing-ovs-dpdk to control cgroup
partition type (isolated vs member).

Update CPU validation to account for ovsDpdk CPUs, NewCPULists to accept
ovsDpdk parameter, and add OvsDpdk feature label for E2E tests.

Update API docs via make generate-docs.

AIA: Primarily AI, New content, Human-initiated, Reviewed, Claude Opus 4.6 v1.0
Signed-off-by: Talor Itzhak <titzhak@redhat.com>
…pdk CPUs

Add OvsDpdkCPUsPrerequisiteError and ConditionOvsDpdkCPUsPrerequisiteNotMet
for validating that ovsDpdk CPUs require either workload partitioning or
CPU partitioning mode enabled.

Add MachineConfigOptions fields OvsDpdkCPUs and DisableLoadBalancingForOvsDpdk,
with annotation-based toggle using strconv.ParseBool.

AIA: Primarily AI, New content, Human-initiated, Reviewed, Claude Opus 4.6 v1.0
Signed-off-by: Talor Itzhak <titzhak@redhat.com>
When spec.cpu.ovsDpdk is set, union those CPUs into the kubelet's
reservedSystemCPUs so they are not available for pod scheduling.

AIA: Primarily AI, New content, Human-initiated, Reviewed, Claude Opus 4.6 v1.0
Signed-off-by: Talor Itzhak <titzhak@redhat.com>
When spec.cpu.ovsDpdk is set, union those CPUs into isolated_cores so
they receive the same tuned parameters as isolated CPUs (isolcpus,
nohz_full, rcu_nocbs) and are excluded from systemd.cpu_affinity.

AIA: Primarily AI, New content, Human-initiated, Reviewed, Claude Opus 4.6 v1.0
Signed-off-by: Talor Itzhak <titzhak@redhat.com>
When spec.cpu.ovsDpdk is configured:

- Create nested ovsdpdk.slice inside ovs.slice/ovs-vswitchd.service/
  with cpuset.cpus.partition type controlled by annotation
  (isolated when disable-load-balancing-ovs-dpdk is truthy, member default)
- Expand ovs-vswitchd.service drop-in with Environment=OVS_DPDK_CPUS
- Ban ovsDpdk CPUs from IRQ balancing and clear them from
  /proc/irq/default_smp_affinity
- Always write OVS dynamic pinning trigger file
- Add ovs-dpdk-cpus-configure oneshot service (After=ovs-vswitchd.service)

Template-baked partition type ensures annotation changes trigger MCO
rollout (handles isolated-to-member transition correctly).

Add bash unit tests for the SMP affinity hex mask manipulation logic.

AIA: Primarily AI, New content, Human-initiated, Reviewed, Claude Opus 4.6 v1.0
Signed-off-by: Talor Itzhak <titzhak@redhat.com>
Add E2E tests for ovsDpdk CPU feature:
- Update test verifying nested ovsdpdk.slice inside
  ovs.slice/ovs-vswitchd.service/ with cpuset.cpus.partition
- Status test for OvsDpdkCPUsPrerequisiteNotMet condition
- Parse kernel cmdline CPU lists as cpusets instead of regex
- Pass explicit client to IsWorkloadPartitioningEnabled

AIA: Primarily AI, New content, Human-initiated, Reviewed, Claude Opus 4.6 v1.0
Signed-off-by: Talor Itzhak <titzhak@redhat.com>
AIA: Primarily AI, New content, Human-initiated, Reviewed, Claude Opus 4.6 v1.0
Signed-off-by: Talor Itzhak <titzhak@redhat.com>
@Tal-or Tal-or force-pushed the dedicate_cpus_for_dpdk_vswitch branch from c72f93c to d721d98 Compare July 9, 2026 14:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants