Skip to content

Conversation

@andreaskaris
Copy link
Contributor

@andreaskaris andreaskaris commented Oct 21, 2025

Summary

Convert the Priority field from int32 to *int32 across all BPF program types (TC, TCX, XDP) and their cluster variants.

Fixes #484

Motivation

Making Priority a pointer allows users to set the priority to 0, or to use the default behavior. This provides better API semantics and allows bpfman to apply its own default priority logic when the field is omitted. Following OpenShift API guide best practices, the default value is now set via the controller rather than the CRD definition.

Changes

Core API Changes (commit 7a20559)

  • API Changes: Changed Priority field type from int32 to *int32 in:

    • ClTcAttachInfo / ClTcAttachInfoState
    • ClTcxAttachInfo / ClTcxAttachInfoState
    • ClXdpAttachInfo / ClXdpAttachInfoState
    • TcAttachInfo / TcAttachInfoState
    • TcxAttachInfo / TcxAttachInfoState
    • XdpAttachInfo / XdpAttachInfoState
  • Kubebuilder Annotations: Removed +kubebuilder:default:=1000 annotations - the default is now set by the controller rather than via the API, following OpenShift API guide best practices

  • Helper Function: Added GetPriority() helper in pkg/helpers to handle nil pointer cases and provide default value of 1000

  • Controller Updates: Updated all reconcilers to use GetPriority() helper:

    • Cluster-scoped: cl_tc_program.go, cl_tcx_program.go, cl_xdp_program.go
    • Namespace-scoped: ns_tc_program.go, ns_tcx_program.go, ns_xdp_program.go
  • Generated Code: Updated CRDs, deepcopy functions, and CSV manifests

  • Tests: Updated all test files to use ptr.To() for priority values

Test Infrastructure Improvements (commits 7c42d03, 229e32f)

  • Table-Driven Tests (commit 7c42d03): Refactored BPF application tests to use table-driven pattern with reusable helper functions:

    • createFakeClusterReconciler() / createFakeNamespaceReconciler() for setup
    • runClusterReconciler() / runNamespaceReconciler() for execution
    • verifyClusterBpfApplicationState() / verifyNamespaceBpfApplicationState() for validation
    • verifyClusterBpfProgramState() / verifyNamespaceBpfProgramState() for status checks
  • Mockable Network Namespace Cache (commit 229e32f): Extracted NetnsCache into a mockable interface:

    • Defined NetNsCache interface with GetNetNsId() and Reset() methods
    • Implemented ReconcilerNetNsCache with original caching logic
    • Added MockNetNsCache for testing with predefined namespace mappings
    • Enabled proper unit testing without filesystem dependencies

Priority Field Testing (commit 5cd629f)

  • Unit Tests: Added tests for priority field handling:
    • Verify nil priority defaults to 1000
    • Verify explicit priority values are correctly set
    • Verify zero priority is allowed
    • Coverage for both cluster-scoped and namespace-scoped BPF applications
    • Verify priority is correctly reflected in program status

Testing

  • Unit tests updated and priority field tests added
  • Integration tests updated

@andreaskaris andreaskaris marked this pull request as draft October 21, 2025 17:02
@andreaskaris andreaskaris force-pushed the issues484 branch 3 times, most recently from 0be6ca4 to 6b87e7d Compare October 21, 2025 18:01
@andreaskaris
Copy link
Contributor Author

andreaskaris commented Oct 21, 2025

With this fix, applications can now have priority 0:

[root@centos9-bpfman bpfman]# kubectl apply -f /root/bytecode.yaml 
clusterbpfapplication.bpfman.io/go-xdp-counter-example created
[root@centos9-bpfman bpfman]# 
[root@centos9-bpfman bpfman]# 
[root@centos9-bpfman bpfman]# 
[root@centos9-bpfman bpfman]# kubectl get clusterbpfapplication
NAME                     NODESELECTOR   STATUS    AGE
go-xdp-counter-example                  Success   20s
[root@centos9-bpfman bpfman]# kubectl apply -f /root/bytecode.yaml ^C
[root@centos9-bpfman bpfman]# kubectl get clusterbpfapplicationstate  -o yaml 
apiVersion: v1
items:
- apiVersion: bpfman.io/v1alpha1
  kind: ClusterBpfApplicationState
  metadata:
    creationTimestamp: "2025-10-21T18:14:19Z"
    finalizers:
    - bpfman.io.clbpfapplicationcontroller/finalizer
    generation: 1
    labels:
      bpfman.io/ownedByProgram: go-xdp-counter-example
      kubernetes.io/hostname: bpfman-deployment-control-plane
    name: go-xdp-counter-example-33a1ac2f
    ownerReferences:
    - apiVersion: bpfman.io/v1alpha1
      blockOwnerDeletion: true
      controller: true
      kind: ClusterBpfApplication
      name: go-xdp-counter-example
      uid: ad361693-6d2c-486f-a1b8-9fa3dae8a5ee
    resourceVersion: "1967"
    uid: 48ec7d07-8c22-4244-8010-8fc769e7b188
  status:
    appLoadStatus: LoadSuccess
    conditions:
    - lastTransitionTime: "2025-10-21T18:14:30Z"
      message: The BPF application has been successfully loaded and attached
      reason: Success
      status: "True"
      type: Success
    node: bpfman-deployment-control-plane
    programs:
    - name: xdp_stats
      programId: 2397
      programLinkStatus: Success
      type: XDP
      xdp:
        links:
        - interfaceName: eth0
          linkId: 1752065740
          linkStatus: Attached
          priority: 0
          proceedOn:
          - Pass
          - DispatcherReturn
          shouldAttach: true
          uuid: 915b77d2-6723-4cb1-a83f-2640a82143bb
    updateCount: 2
kind: List
metadata:
  resourceVersion: ""
[root@centos9-bpfman bpfman]# kubectl exec -n bpfman               bpfman-daemon-7rnsn -it -- /bin/bash
Defaulted container "bpfman" out of: bpfman, bpfman-agent, node-driver-registrar, mount-bpffs (init)
groups: cannot find name for group ID 2000
root@bpfman-deployment-control-plane:/# ./bpfman get link 1752065740
 Bpfman State                                                            
 BPF Function:       xdp_stats                                           
 Program Type:       xdp                                                 
 Program ID:         2397                                                
 Link ID:            1752065740                                          
 Interface:          eth0                                                
 Priority:           0                                                   
 Position:           0                                                   
 Proceed On:         pass, dispatcher_return                             
 Network Namespace:  None                                                
 Metadata:           bpfman.io/uuid=915b77d2-6723-4cb1-a83f-2640a82143bb 

@andreaskaris andreaskaris changed the title Issues484 Convert the Priority field from int32 to *int32 across all BPF program types (TC, TCX, XDP) and their cluster variants Oct 22, 2025
@andreaskaris andreaskaris force-pushed the issues484 branch 10 times, most recently from 3e45d88 to 5cd629f Compare October 23, 2025 00:19
Convert the Priority field from int32 to *int32 across all BPF program
types (TC, TCX, XDP) and their cluster variants. This change:

- Removes the default value of 1000 from kubebuilder annotations
- Makes the Priority field truly optional in the API
- Updates all AttachInfo and AttachInfoState structs
- Adds a GetPriority helper function to handle nil pointer cases
- Updates all reconcilers to use the helper function
- Regenerates CRDs and deepcopy code
- Updates tests to use ptr.To() for priority values

This allows users to omit the priority field when they want to use
bpfman's default behavior, rather than always setting an explicit
value. It also follows API best practices to set the default value via
the controller, and not via the CRD definition.

Signed-off-by: Andreas Karis <[email protected]>
Convert cluster and namespace BPF application tests to table-driven
structure for better maintainability and test coverage. Extract common
test functionality into reusable helper functions:
- createFakeClusterReconciler() and createFakeNamespaceReconciler() for
  setup
- runClusterReconciler() and runNamespaceReconciler() for execution
- verifyClusterBpfApplicationState() and
  verifyNamespaceBpfApplicationState()
- verifyClusterBpfProgramState() and verifyNamespaceBpfProgramState()

Inline program definitions within test cases, simplify reconciler setup
in GetBpfAppState tests, and add comprehensive verification of program
status across multiple reconciliation cycles.

Signed-off-by: Andreas Karis <[email protected]>
Extract the NetnsCache map and getNetnsId method from ReconcilerCommon
into a new NetNsCache interface with ReconcilerNetNsCache implementation.
This enables proper unit testing by allowing tests to inject a
MockNetNsCache instead of relying on actual filesystem operations.

Changes:
- Define NetNsCache interface with GetNetNsId and Reset methods
- Implement ReconcilerNetNsCache with the original caching logic
- Update all reconcilers to use NetNsCache.GetNetNsId() instead of
  ReconcilerCommon.getNetnsId()
- Add MockNetNsCache for testing with predefined namespace mappings
- Initialize NetNsCache in main.go and test setup

Signed-off-by: Andreas Karis <[email protected]>
Add unit tests for XDP, TC, and TCX programs to verify that:
- nil priority defaults to 1000
- explicit priority values are correctly set
- zero priority is allowed

The tests cover both cluster-scoped and namespace-scoped BPF
applications, ensuring the priority field is properly handled
and reflected in the program status.

Signed-off-by: Andreas Karis <[email protected]>
@andreaskaris andreaskaris force-pushed the issues484 branch 6 times, most recently from 2cb3797 to af2a346 Compare October 23, 2025 18:41
func TestTcGoCounter(t *testing.T) {
t.Log("deploying tc counter program")
require.NoError(t, clusters.KustomizeDeployForCluster(ctx, env.Cluster(), tcGoCounterKustomize))
addCleanup(func(context.Context) error {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Note: functions added via addCleanup are run exactly once, and that at the end of all tests. The problem with that is that this will conflict when multiple tests add the same cleanup. Instead, use t.Cleanup which runs after each test. It's also probably not necessary to throw an error on cleanup, therefore don't..?

Add integration tests to verify BPF program links are correctly ordered
by priority across XDP, TC, and TCX program types.

The new verification framework validates link ordering on each cluster
node by comparing ClusterBpfApplicationState data against actual bpfman
daemon state.

Signed-off-by: Andreas Karis <[email protected]>
@andreaskaris andreaskaris marked this pull request as ready for review October 23, 2025 18:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bpfman-operator does not allow priority 0, defaults to 1000 instead

1 participant