Skip to content

Commit

Permalink
Initial operator support for Load/Attach Split
Browse files Browse the repository at this point in the history
This commit contains the framework for using the bpfman load/attach split
support when it becomes available.

Support for both cluster-scoped and namespace-scoped CRDs for all supported
program types is included.

Key changes include:
- Updates to the BpfApplication and BpfNsApplication CRDs to support a separate list
  of optional attach points for programs. This allows programs to be loaded before
  attachments are made and enables dynamic attachment updates.
- BpfApplicationState and BpfNsApplicationState CRDs have been added to manage
  per-node information for the BpfApplication and BpfNsApplication CRDs,
  respectively.
- All files and code related to the *Program CRDs have been removed.

See TODO.md for more details about what's left to do.

Signed-off-by: Andre Fredette <[email protected]>
  • Loading branch information
anfredette committed Feb 10, 2025
1 parent d5ffe86 commit 5335cce
Show file tree
Hide file tree
Showing 268 changed files with 13,305 additions and 39,279 deletions.
95 changes: 3 additions & 92 deletions PROJECT
Original file line number Diff line number Diff line change
Expand Up @@ -11,69 +11,6 @@ plugins:
projectName: bpfman-operator
repo: github.com/bpfman
resources:
- api:
crdVersion: v1
controller: true
domain: bpfman.io
kind: BpfProgram
path: github.com/bpfman/bpfman-operator/apis/v1alpha1
version: v1alpha1
- api:
crdVersion: v1
controller: true
domain: bpfman.io
kind: XdpProgram
path: github.com/bpfman/bpfman-operator/apis/v1alpha1
version: v1alpha1
- api:
crdVersion: v1
controller: true
domain: bpfman.io
kind: TcProgram
path: github.com/bpfman/bpfman-operator/apis/v1alpha1
version: v1alpha1
- api:
crdVersion: v1
controller: true
domain: bpfman.io
kind: TcxProgram
path: github.com/bpfman/bpfman-operator/apis/v1alpha1
version: v1alpha1
- api:
crdVersion: v1
controller: true
domain: bpfman.io
kind: TracePointProgram
path: github.com/bpfman/bpfman-operator/apis/v1alpha1
version: v1alpha1
- api:
crdVersion: v1
controller: true
domain: bpfman.io
kind: KprobeProgram
path: github.com/bpfman/bpfman-operator/apis/v1alpha1
version: v1alpha1
- api:
crdVersion: v1
controller: true
domain: bpfman.io
kind: UprobeProgram
path: github.com/bpfman/bpfman-operator/apis/v1alpha1
version: v1alpha1
- api:
crdVersion: v1
controller: true
domain: bpfman.io
kind: FentryProgram
path: github.com/bpfman/bpfman-operator/apis/v1alpha1
version: v1alpha1
- api:
crdVersion: v1
controller: true
domain: bpfman.io
kind: FexitProgram
path: github.com/bpfman/bpfman-operator/apis/v1alpha1
version: v1alpha1
- api:
crdVersion: v1
controller: true
Expand All @@ -86,47 +23,21 @@ resources:
namespaced: true
controller: true
domain: bpfman.io
kind: BpfNsProgram
path: github.com/bpfman/bpfman-operator/apis/v1alpha1
version: v1alpha1
- api:
crdVersion: v1
namespaced: true
controller: true
domain: bpfman.io
kind: XdpNsProgram
path: github.com/bpfman/bpfman-operator/apis/v1alpha1
version: v1alpha1
- api:
crdVersion: v1
namespaced: true
controller: true
domain: bpfman.io
kind: TcNsProgram
path: github.com/bpfman/bpfman-operator/apis/v1alpha1
version: v1alpha1
- api:
crdVersion: v1
namespaced: true
controller: true
domain: bpfman.io
kind: TcxNsProgram
kind: BpfNsApplication
path: github.com/bpfman/bpfman-operator/apis/v1alpha1
version: v1alpha1
- api:
crdVersion: v1
namespaced: true
controller: true
domain: bpfman.io
kind: UprobeNsProgram
kind: BpfApplicationState
path: github.com/bpfman/bpfman-operator/apis/v1alpha1
version: v1alpha1
- api:
crdVersion: v1
namespaced: true
controller: true
domain: bpfman.io
kind: BpfNsApplication
kind: BpfNsApplicationState
path: github.com/bpfman/bpfman-operator/apis/v1alpha1
version: v1alpha1
version: "3"
37 changes: 37 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Intro

The code has support for:
- XDP, TCX, and Fentry programs in the cluster-scoped BpfApplication, and
- XDP and TCX in the namespace-scoped BpfNsApplication

It's written so that Dave's load/attach split code should drop in pretty easily,
but it's not using it yet. I'm simulating the attachments by reloading the code
for each attachment (like we do today).

# Testing:

- Unit tests for the agent and the operator
- The following working samples contain all program types:
- config/samples/bpfman.io_v1alpha1_bpfapplication.yaml
- config/samples/bpfman.io_v1alpha1_fentry_bpfnsapplication.yaml

# TODO:

(In no particular order.)

- ~~Implement Fentry/Fexit solution.~~
- Integrate with the new bpfman code with load/attach split (of course)
- ~~Create a bpf.o file with all the application types for both cluster and~~
~~namespace scoped BpfApplicaitons.~~
- Review the status/condition values. I redid most of the *ApplicationState
item status values, but the actual overall status is still using an existing
ReconcileSuccess value.
- Review all comments and logs.
- ~~Support namespace-scoped BPF Application CRD~~
- ~~Support the rest of the program types.~~
- ~~Delete old directories.~~
- Rename cluster-scoped CRDs and structures to "Cluster*", and remove "ns" from
namespace-scoped CRDs and structures.
- Make sure we have all the old sample programs covered by BpfApplication-based
sample programs and then delete the *Program-based ones.
- More cleanup and testing.
154 changes: 154 additions & 0 deletions apis/v1alpha1/bpfApplicationState_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/*
Copyright 2023 The bpfman Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha1

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1types "k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
)

// BpfApplicationProgramState defines the desired state of BpfApplication
// +union
// +kubebuilder:validation:XValidation:rule="has(self.type) && self.type == 'XDP' ? has(self.xdp) : !has(self.xdp)",message="xdp configuration is required when type is XDP, and forbidden otherwise"
// +kubebuilder:validation:XValidation:rule="has(self.type) && self.type == 'TC' ? has(self.tc) : !has(self.tc)",message="tc configuration is required when type is TC, and forbidden otherwise"
// +kubebuilder:validation:XValidation:rule="has(self.type) && self.type == 'TCX' ? has(self.tcx) : !has(self.tcx)",message="tcx configuration is required when type is TCX, and forbidden otherwise"
// +kubebuilder:validation:XValidation:rule="has(self.type) && self.type == 'Fentry' ? has(self.fentry) : !has(self.fentry)",message="fentry configuration is required when type is Fentry, and forbidden otherwise"
// +kubebuilder:validation:XValidation:rule="has(self.type) && self.type == 'Fexit' ? has(self.fexit) : !has(self.fexit)",message="fexit configuration is required when type is Fexit, and forbidden otherwise"
// +kubebuilder:validation:XValidation:rule="has(self.type) && self.type == 'Kprobe' ? has(self.kprobe) : !has(self.kprobe)",message="kprobe configuration is required when type is Kprobe, and forbidden otherwise"
// +kubebuilder:validation:XValidation:rule="has(self.type) && self.type == 'Uprobe' ? has(self.uprobe) : !has(self.uprobe)",message="uprobe configuration is required when type is Uprobe, and forbidden otherwise"
// +kubebuilder:validation:XValidation:rule="has(self.type) && self.type == 'Tracepoint' ? has(self.tracepoint) : !has(self.tracepoint)",message="tracepoint configuration is required when type is Tracepoint, and forbidden otherwise"
type BpfApplicationProgramState struct {
BpfProgramStateCommon `json:",inline"`
// Type specifies the bpf program type
// +unionDiscriminator
// +kubebuilder:validation:Required
// +kubebuilder:validation:Enum:="XDP";"TC";"TCX";"Fentry";"Fexit";"Kprobe";"Uprobe";"Tracepoint"
Type EBPFProgType `json:"type,omitempty"`

// xdp defines the desired state of the application's XdpPrograms.
// +unionMember
// +optional
XDP *XdpProgramInfoState `json:"xdp,omitempty"`

// tc defines the desired state of the application's TcPrograms.
// +unionMember
// +optional
TC *TcProgramInfoState `json:"tc,omitempty"`

// tcx defines the desired state of the application's TcxPrograms.
// +unionMember
// +optional
TCX *TcxProgramInfoState `json:"tcx,omitempty"`

// fentry defines the desired state of the application's FentryPrograms.
// +unionMember
// +optional
Fentry *FentryProgramInfoState `json:"fentry,omitempty"`

// fexit defines the desired state of the application's FexitPrograms.
// +unionMember
// +optional
Fexit *FexitProgramInfoState `json:"fexit,omitempty"`

// kprobe defines the desired state of the application's KprobePrograms.
// +unionMember
// +optional
Kprobe *KprobeProgramInfoState `json:"kprobe,omitempty"`

// uprobe defines the desired state of the application's UprobePrograms.
// +unionMember
// +optional
Uprobe *UprobeProgramInfoState `json:"uprobe,omitempty"`

// tracepoint defines the desired state of the application's TracepointPrograms.
// +unionMember
// +optional
Tracepoint *TracepointProgramInfoState `json:"tracepoint,omitempty"`
}

// BpfApplicationSpec defines the desired state of BpfApplication
type BpfApplicationStateSpec struct {
// Node is the name of the node for this BpfApplicationStateSpec.
Node string `json:"node"`
// The number of times the BpfApplicationState has been updated. Set to 1
// when the object is created, then it is incremented prior to each update.
// This allows us to verify that the API server has the updated object prior
// to starting a new Reconcile operation.
UpdateCount int64 `json:"updatecount"`
// AppLoadStatus reflects the status of loading the bpf application on the
// given node.
AppLoadStatus AppLoadStatus `json:"apploadstatus"`
// Programs is a list of bpf programs contained in the parent application.
// It is a map from the bpf program name to BpfApplicationProgramState
// elements.
Programs []BpfApplicationProgramState `json:"programs,omitempty"`
}

// +genclient
// +genclient:nonNamespaced
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:resource:scope=Cluster

// BpfApplicationState contains the per-node state of a BpfApplication.
// +kubebuilder:printcolumn:name="Node",type=string,JSONPath=".spec.node"
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.conditions[0].reason`
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
type BpfApplicationState struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec BpfApplicationStateSpec `json:"spec,omitempty"`
Status BpfAppStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true
// BpfApplicationStateList contains a list of BpfApplicationState objects
type BpfApplicationStateList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []BpfApplicationState `json:"items"`
}

func (an BpfApplicationState) GetName() string {
return an.Name
}

func (an BpfApplicationState) GetUID() metav1types.UID {
return an.UID
}

func (an BpfApplicationState) GetAnnotations() map[string]string {
return an.Annotations
}

func (an BpfApplicationState) GetLabels() map[string]string {
return an.Labels
}

func (an BpfApplicationState) GetStatus() *BpfAppStatus {
return &an.Status
}

func (an BpfApplicationState) GetClientObject() client.Object {
return &an
}

func (anl BpfApplicationStateList) GetItems() []BpfApplicationState {
return anl.Items
}
Loading

0 comments on commit 5335cce

Please sign in to comment.