Skip to content

Comments

[2/3] Add 'Devlink Params configuration' implementation#1036

Open
e0ne wants to merge 8 commits intok8snetworkplumbingwg:masterfrom
e0ne:devlink-params-implementation
Open

[2/3] Add 'Devlink Params configuration' implementation#1036
e0ne wants to merge 8 commits intok8snetworkplumbingwg:masterfrom
e0ne:devlink-params-implementation

Conversation

@e0ne
Copy link
Collaborator

@e0ne e0ne commented Feb 17, 2026

No description provided.

e0ne and others added 8 commits February 17, 2026 15:57
Signed-off-by: Ivan Kolodiazhnyi <ikolodiazhny@nvidia.com>
Signed-off-by: Ivan Kolodiazhnyi <ikolodiazhny@nvidia.com>
Signed-off-by: Ivan Kolodiazhnyi <ikolodiazhny@nvidia.com>

fd
Signed-off-by: Ivan Kolodiazhnyi <ikolodiazhny@nvidia.com>
Signed-off-by: Ivan Kolodiazhnyi <ikolodiazhny@nvidia.com>
Signed-off-by: Ivan Kolodiazhnyi <ikolodiazhny@nvidia.com>
fix: Don't modify multiport param by default
When SriovNetworkNodePolicy specifies groupingPolicy: all, the operator
should create a single OVS bridge with all matching PFs as uplinks.
Previously, it was incorrectly creating separate bridges for each PF.
@github-actions
Copy link

Thanks for your PR,
To run vendors CIs, Maintainers can use one of:

  • /test-all: To run all tests for all vendors.
  • /test-e2e-all: To run all E2E tests for all vendors.
  • /test-e2e-nvidia-all: To run all E2E tests for NVIDIA vendor.

To skip the vendors CIs, Maintainers can use one of:

  • /skip-all: To skip all tests for all vendors.
  • /skip-e2e-all: To skip all E2E tests for all vendors.
  • /skip-e2e-nvidia-all: To skip all E2E tests for NVIDIA vendor.
    Best regards.

@gemini-code-assist
Copy link

Summary of Changes

Hello @e0ne, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly extends the SR-IOV Network Operator's capabilities by introducing comprehensive support for configuring devlink parameters on network interface cards. It provides a new API for users to specify these parameters, implements the underlying logic for their discovery and application on host machines, and integrates this functionality into the existing configuration and reconciliation loops. Additionally, it refines OVS bridge management to support grouping multiple uplinks into a single bridge, enhancing flexibility for complex network setups.

Highlights

  • Devlink Parameters API Extension: Introduced new API types, DevlinkParam and DevlinkParams, to allow configuration of low-level device parameters via SriovNetworkNodePolicySpec, Interface, InterfaceExt, and VirtualFunction structs.
  • Devlink Parameter Comparison Logic: Added a NeedToUpdateDevlinkParams helper function to compare desired and current devlink parameters, integrating this check into the NeedToUpdateSriov function to trigger updates when necessary.
  • Grouped OVS Bridge Configuration: Implemented support for an OVS bridge GroupingPolicy set to 'all', which creates a single OVS bridge with multiple uplinks. The NeedToUpdateBridges function was updated to ignore the GroupingPolicy field during comparison.
  • Host-level Devlink Parameter Management: Enhanced host-level network utilities to discover (GetDevlinkDeviceParams) and apply (SetDevlinkDeviceParam) devlink parameters, including helper functions for type conversion.
  • Mellanox Plugin Integration: Updated the Mellanox plugin to handle the esw_multiport devlink parameter, translating it into the LAG_RESOURCE_ALLOCATION firmware setting and triggering reboots if firmware changes are required.
  • SR-IOV Interface Configuration Workflow: Modified the ConfigSriovInterfaces workflow to apply devlink parameters after all other interface configurations are complete, ensuring dependencies like switchdev mode and VF creation are met.
Changelog
  • api/v1/helper.go
    • Added NeedToUpdateDevlinkParams function to compare devlink parameters.
    • Updated NeedToUpdateSriov to include devlink parameter comparison.
    • Modified Apply to pass DevlinkParams to interface objects.
    • Implemented logic for GroupingPolicy 'all' in ApplyBridgeConfig.
  • api/v1/helper_test.go
    • Added test cases for ApplyBridgeConfig with GroupingPolicy 'all'.
    • Added test case for NeedToUpdateBridges to ignore GroupingPolicy differences.
  • api/v1/sriovnetworknodepolicy_types.go
    • Defined new DevlinkParam and DevlinkParams structs.
    • Added DevlinkParams field to SriovNetworkNodePolicySpec.
    • Added GroupingPolicy field to Bridge struct with validation enums.
  • api/v1/sriovnetworknodestate_types.go
    • Added DevlinkParams field to Interface, InterfaceExt, and VirtualFunction structs.
    • Added GroupingPolicy field to Bridges struct with validation enums.
  • api/v1/zz_generated.deepcopy.go
    • Generated deepcopy methods for DevlinkParam and DevlinkParams.
    • Updated deepcopy methods for Interface, InterfaceExt, SriovNetworkNodePolicySpec, and VirtualFunction to include DevlinkParams.
  • config/crd/bases/sriovnetwork.openshift.io_sriovnetworknodepolicies.yaml
    • Updated CRD schema to include devlinkParams and groupingPolicy fields.
  • config/crd/bases/sriovnetwork.openshift.io_sriovnetworknodestates.yaml
    • Updated CRD schema to include devlinkParams and groupingPolicy fields.
  • deployment/sriov-network-operator-chart/crds/sriovnetwork.openshift.io_sriovnetworknodepolicies.yaml
    • Updated Helm chart CRD schema to include devlinkParams and groupingPolicy fields.
  • deployment/sriov-network-operator-chart/crds/sriovnetwork.openshift.io_sriovnetworknodestates.yaml
    • Updated Helm chart CRD schema to include devlinkParams and groupingPolicy fields.
  • doc/design/devlink-params-configuration.md
    • Added a new design document outlining the devlink parameters configuration.
  • pkg/consts/constants.go
    • Added constants for DevlinkParamApplyOnPf, DevlinkParamApplyOnVf, DevlinkParamApplyOnSf, OvsGroupingPolicyPerPF, OvsGroupingPolicyPerVF, and OvsGroupingPolicyAll.
  • pkg/helper/mock/mock_helper.go
    • Added mock for GetDevlinkDeviceParams.
  • pkg/host/internal/bridge/ovs/mock/mock_ovs.go
    • Added mock for AddInterfaceToOVSBridge.
  • pkg/host/internal/bridge/ovs/ovs.go
    • Added AddInterfaceToOVSBridge method to add interfaces to OVS bridges.
    • Modified CreateOVSBridge to support multiple uplinks and handle OvsGroupingPolicyAll.
    • Updated getCurrentBridgeState to correctly process multiple uplinks for a bridge.
  • pkg/host/internal/bridge/ovs/ovs_test.go
    • Added test cases for GetOVSBridges to verify behavior with multiple and partial uplinks.
  • pkg/host/internal/lib/netlink/mock/mock_netlink.go
    • Added mock for DevlinkGetDeviceParams.
  • pkg/host/internal/lib/netlink/netlink.go
    • Added DevlinkGetDeviceParams method to retrieve all devlink parameters for a device.
  • pkg/host/internal/network/network.go
    • Added GetDevlinkDeviceParams to retrieve all devlink parameters for a PCI address.
    • Introduced devlinkValueToString and devlinkCmodeToString helper functions for parameter conversion.
    • Refactored GetDevlinkDeviceParam to utilize the new devlinkValueToString helper.
  • pkg/host/internal/sriov/sriov.go
    • Updated DiscoverSriovDevices to fetch and populate DevlinkParams for interfaces.
    • Added applyDevlinkPfParam, applyDevlinkVfParam, and applyDevlinkParams functions to apply devlink settings.
    • Modified ConfigSriovInterfaces to call applyDevlinkParams after other interface configurations.
  • pkg/host/internal/sriov/sriov_test.go
    • Added test cases for DiscoverSriovDevices to include devlink parameters.
    • Added test case for ConfigSriovInterfaces to ensure devlink parameters are applied correctly.
  • pkg/host/mock/mock_host.go
    • Added mock for GetDevlinkDeviceParams.
  • pkg/host/types/interfaces.go
    • Added GetDevlinkDeviceParams to the NetworkInterface interface.
    • Updated the description for ConfigureBridges to clarify handling of GroupingPolicy 'all'.
  • pkg/plugins/generic/generic_plugin.go
    • Added a comment clarifying that bridge grouping for 'all' policy is now handled in the controller.
  • pkg/plugins/mellanox/mellanox_plugin.go
    • Updated OnNodeStateChange to include handling of esw_multiport devlink parameter via HandleESwitchParams.
  • pkg/vendors/mellanox/mellanox.go
    • Added Multiport field to MlxNic struct.
    • Introduced constants devlinkMultiportParamName, devlinkMultiportEnableValue, and LagResourceAllocation.
    • Updated MlxConfigFW to configure LAG_RESOURCE_ALLOCATION based on Multiport.
    • Modified GetMlxNicFwData to read LAG_RESOURCE_ALLOCATION from firmware.
    • Added HandleESwitchParams and isESwitchParamsRequireChange functions to manage esw_multiport firmware settings.
  • pkg/vendors/mellanox/mellanox_test.go
    • Added test cases for MlxConfigFW to include LAG_RESOURCE_ALLOCATION.
    • Added extensive test cases for HandleESwitchParams covering various scenarios for esw_multiport.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for configuring devlink parameters and adds a grouping policy for OVS bridges. The changes span across the API types, CRDs, helper functions, and vendor-specific logic. The implementation looks mostly correct, but I've found a few issues related to efficiency, error handling, and robustness. Specifically, there's an inefficient loop that can be optimized, an ignored error that could lead to silent failures, and a case-sensitive comparison that could cause issues with user-provided configurations. I've also pointed out a minor typo and some confusing text in the new design document. My suggestions aim to address these points to improve the quality and reliability of the new features.

Comment on lines +407 to +417
for _, v := range p.Values {
// only CLI-visible cmodes
strVal, _ := n.devlinkValueToString(p.Type, v.Data)
switch v.CMODE {
case nl.DEVLINK_PARAM_CMODE_RUNTIME,
nl.DEVLINK_PARAM_CMODE_DRIVERINIT,
nl.DEVLINK_PARAM_CMODE_PERMANENT:
merged[p.Name][v.CMODE] = strVal
}
}
}

Choose a reason for hiding this comment

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

high

The error returned by n.devlinkValueToString is being ignored. This could lead to silent failures if the value conversion fails, potentially causing incorrect devlink parameters to be processed or stored. The error should be checked and handled appropriately.

		for _, v := range p.Values {
			// only CLI-visible cmodes
			strVal, err := n.devlinkValueToString(p.Type, v.Data)
			if err != nil {
				log.Log.Error(err, "Failed to decode devlink param value", "device", pciAddr, "param", p.Name)
				return nil, err
			}
			switch v.CMODE {
			case nl.DEVLINK_PARAM_CMODE_RUNTIME,
				nl.DEVLINK_PARAM_CMODE_DRIVERINIT,
				nl.DEVLINK_PARAM_CMODE_PERMANENT:
				merged[p.Name][v.CMODE] = strVal
			}
		}

}
for _, param := range iface.DevlinkParams.Params {
var err error
switch param.ApplyOn {

Choose a reason for hiding this comment

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

high

The CRD for DevlinkParam allows applyOn to be specified in both uppercase and lowercase (e.g., PF, pf). However, this switch statement performs a case-sensitive comparison against uppercase constants. This will cause the logic to fail for lowercase values. To make the implementation robust, you should convert the param.ApplyOn value to uppercase before the comparison.

Suggested change
switch param.ApplyOn {
switch strings.ToUpper(param.ApplyOn) {

Comment on lines +527 to +533
for _, uplink := range uplinks {
state.Spec.Bridges.OVS = slices.DeleteFunc(state.Spec.Bridges.OVS, func(br OVSConfigExt) bool {
return slices.ContainsFunc(br.Uplinks, func(u OVSUplinkConfigExt) bool {
return u.PciAddress == uplink.PciAddress
})
})
}

Choose a reason for hiding this comment

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

medium

The current implementation for removing existing individual per-PF bridges is inefficient. It iterates through all uplinks and, for each, re-scans and re-slices state.Spec.Bridges.OVS. This results in a complexity of roughly O(U * B), where U is the number of uplinks and B is the number of bridges, and involves multiple memory allocations. A more efficient approach would be to first collect all PCI addresses of the uplinks into a set for quick lookups, and then iterate through the bridges once to remove the ones that contain any of these uplinks.

Suggested change
for _, uplink := range uplinks {
state.Spec.Bridges.OVS = slices.DeleteFunc(state.Spec.Bridges.OVS, func(br OVSConfigExt) bool {
return slices.ContainsFunc(br.Uplinks, func(u OVSUplinkConfigExt) bool {
return u.PciAddress == uplink.PciAddress
})
})
}
pciAddressesToRemove := make(map[string]struct{})
for _, uplink := range uplinks {
pciAddressesToRemove[uplink.PciAddress] = struct{}{}
}
state.Spec.Bridges.OVS = slices.DeleteFunc(state.Spec.Bridges.OVS, func(br OVSConfigExt) bool {
for _, u := range br.Uplinks {
if _, found := pciAddressesToRemove[u.PciAddress]; found {
return true
}
}
return false
})

Comment on lines +53 to +55
SriovNetworkPoolConfig is used only for OpenShift to provide configuration for
OVS Hardware Offloading. We can extend it to add configuration for the drain
pool. E.g.:

Choose a reason for hiding this comment

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

medium

This paragraph seems to be a copy-paste error from another document. It discusses SriovNetworkPoolConfig and drain pools, which is unrelated to the devlink parameters being added to SriovNetworkNodePolicy in this design. This should be removed to avoid confusion.

Comment on lines +462 to +478
requsted, found := false, false
for _, devlinkParam := range iface.DevlinkParams.Params {
if devlinkParam.Name != devlinkMultiportParamName {
continue
}
requsted = true

for _, devlinkParamStatus := range ifaceStatus.DevlinkParams.Params {
if devlinkParamStatus.Name == devlinkMultiportParamName {
found = true
if iface.Name == ifaceStatus.Name && devlinkParam.Value != devlinkParamStatus.Value {
return true, &devlinkParam
}
}
}
}
if requsted && !found {

Choose a reason for hiding this comment

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

medium

There is a typo in the variable name requsted. It should be requested for better readability and correctness. This should be fixed in all its occurrences within this function.

Suggested change
requsted, found := false, false
for _, devlinkParam := range iface.DevlinkParams.Params {
if devlinkParam.Name != devlinkMultiportParamName {
continue
}
requsted = true
for _, devlinkParamStatus := range ifaceStatus.DevlinkParams.Params {
if devlinkParamStatus.Name == devlinkMultiportParamName {
found = true
if iface.Name == ifaceStatus.Name && devlinkParam.Value != devlinkParamStatus.Value {
return true, &devlinkParam
}
}
}
}
if requsted && !found {
requested, found := false, false
for _, devlinkParam := range iface.DevlinkParams.Params {
if devlinkParam.Name != devlinkMultiportParamName {
continue
}
requested = true
for _, devlinkParamStatus := range ifaceStatus.DevlinkParams.Params {
if devlinkParamStatus.Name == devlinkMultiportParamName {
found = true
if iface.Name == ifaceStatus.Name && devlinkParam.Value != devlinkParamStatus.Value {
return true, &devlinkParam
}
}
}
}
if requested && !found {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants