Skip to content

Commit

Permalink
Additional changes for BpfApplication object
Browse files Browse the repository at this point in the history
- Handle setting owner and object type
- If reconcile is complete with one program/object, continue with the
  next one

These changes have not been tested.  Still need to write a unit test

Signed-off-by: Andre Fredette <afredette@redhat.com>
  • Loading branch information
anfredette committed Jun 6, 2024
1 parent dfc771b commit 4158e39
Show file tree
Hide file tree
Showing 13 changed files with 212 additions and 493 deletions.
478 changes: 46 additions & 432 deletions config/crd/bases/bpfman.io_bpfapplications.yaml

Large diffs are not rendered by default.

35 changes: 27 additions & 8 deletions controllers/bpfman-agent/application-program.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ func (r *BpfApplicationReconciler) Reconcile(ctx context.Context, req ctrl.Reque
r.currentApp = &bpfmaniov1alpha1.BpfApplication{}
r.ourNode = &v1.Node{}
r.Logger = ctrl.Log.WithName("application")
r.appOwner = &bpfmaniov1alpha1.BpfApplication{}

ctxLogger := log.FromContext(ctx)
ctxLogger.Info("Reconcile Application: Enter", "ReconcileKey", req)
Expand All @@ -75,9 +76,12 @@ func (r *BpfApplicationReconciler) Reconcile(ctx context.Context, req ctrl.Reque

var res ctrl.Result
var err error
var complete bool

for _, a := range appPrograms.Items {
complete = false
for _, p := range a.Spec.Programs {
complete = false
switch p.Type {
case bpfmaniov1alpha1.ProgTypeFentry:
fentryProgram := bpfmaniov1alpha1.FentryProgram{
Expand All @@ -95,7 +99,7 @@ func (r *BpfApplicationReconciler) Reconcile(ctx context.Context, req ctrl.Reque
}
fentryObjects := []client.Object{&fentryProgram}
// Reconcile FentryProgram.
res, err = r.reconcileCommon(ctx, rec, fentryObjects)
complete, res, err = r.reconcileCommon(ctx, rec, fentryObjects)

case bpfmaniov1alpha1.ProgTypeFexit:
fexitProgram := bpfmaniov1alpha1.FexitProgram{
Expand All @@ -113,7 +117,7 @@ func (r *BpfApplicationReconciler) Reconcile(ctx context.Context, req ctrl.Reque
}
fexitObjects := []client.Object{&fexitProgram}
// Reconcile FexitProgram.
res, err = r.reconcileCommon(ctx, rec, fexitObjects)
complete, res, err = r.reconcileCommon(ctx, rec, fexitObjects)

case bpfmaniov1alpha1.ProgTypeKprobe,
bpfmaniov1alpha1.ProgTypeKretprobe:
Expand All @@ -132,7 +136,7 @@ func (r *BpfApplicationReconciler) Reconcile(ctx context.Context, req ctrl.Reque
}
kprobeObjects := []client.Object{&kprobeProgram}
// Reconcile KprobeProgram or KpretprobeProgram.
res, err = r.reconcileCommon(ctx, rec, kprobeObjects)
complete, res, err = r.reconcileCommon(ctx, rec, kprobeObjects)

case bpfmaniov1alpha1.ProgTypeUprobe,
bpfmaniov1alpha1.ProgTypeUretprobe:
Expand All @@ -151,7 +155,7 @@ func (r *BpfApplicationReconciler) Reconcile(ctx context.Context, req ctrl.Reque
}
uprobeObjects := []client.Object{&uprobeProgram}
// Reconcile UprobeProgram or UpretprobeProgram.
res, err = r.reconcileCommon(ctx, rec, uprobeObjects)
complete, res, err = r.reconcileCommon(ctx, rec, uprobeObjects)

case bpfmaniov1alpha1.ProgTypeTracepoint:
tracepointProgram := bpfmaniov1alpha1.TracepointProgram{
Expand All @@ -169,7 +173,7 @@ func (r *BpfApplicationReconciler) Reconcile(ctx context.Context, req ctrl.Reque
}
tracepointObjects := []client.Object{&tracepointProgram}
// Reconcile TracepointProgram.
res, err = r.reconcileCommon(ctx, rec, tracepointObjects)
complete, res, err = r.reconcileCommon(ctx, rec, tracepointObjects)

case bpfmaniov1alpha1.ProgTypeTC,
bpfmaniov1alpha1.ProgTypeTCX:
Expand All @@ -188,7 +192,7 @@ func (r *BpfApplicationReconciler) Reconcile(ctx context.Context, req ctrl.Reque
}
tcObjects := []client.Object{&tcProgram}
// Reconcile TcProgram.
res, err = r.reconcileCommon(ctx, rec, tcObjects)
complete, res, err = r.reconcileCommon(ctx, rec, tcObjects)

case bpfmaniov1alpha1.ProgTypeXDP:
xdpProgram := bpfmaniov1alpha1.XdpProgram{
Expand All @@ -206,12 +210,26 @@ func (r *BpfApplicationReconciler) Reconcile(ctx context.Context, req ctrl.Reque
}
xdpObjects := []client.Object{&xdpProgram}
// Reconcile XdpProgram.
res, err = r.reconcileCommon(ctx, rec, xdpObjects)
complete, res, err = r.reconcileCommon(ctx, rec, xdpObjects)

default:
r.Logger.Info("Unsupported Bpf program type", "ProgType", p.Type)
return ctrl.Result{Requeue: false}, nil
continue
}

if complete {
// We've completed reconciling this program, continue to the next one
continue
} else {
return res, err
}
}

if complete {
// We've completed reconciling all programs for this application, continue to the next one
continue
} else {
return res, err
}
}

Expand All @@ -227,6 +245,7 @@ func (r *BpfApplicationReconciler) SetupWithManager(mgr ctrl.Manager) error {
For(&bpfmaniov1alpha1.BpfApplication{}, builder.WithPredicates(predicate.And(predicate.GenerationChangedPredicate{}, predicate.ResourceVersionChangedPredicate{}))).
Owns(&bpfmaniov1alpha1.BpfProgram{},
builder.WithPredicates(predicate.And(
internal.BpfProgramTypePredicate(internal.ApplicationString),
internal.BpfProgramNodePredicate(r.NodeName)),
),
).
Expand Down
12 changes: 3 additions & 9 deletions controllers/bpfman-agent/application-program_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,16 @@ func TestBpfApplicationControllerCreate(t *testing.T) {
Spec: bpfmaniov1alpha1.BpfApplicationSpec{
BpfAppCommon: bpfmaniov1alpha1.BpfAppCommon{
NodeSelector: metav1.LabelSelector{},
ByteCode: bpfmaniov1alpha1.BytecodeSelector{
Path: &bytecodePath,
},
},
Programs: []bpfmaniov1alpha1.BpfApplicationProgram{
{
Type: bpfmaniov1alpha1.ProgTypeFentry,
Fentry: &bpfmaniov1alpha1.FentryProgramInfo{
BpfProgramCommon: bpfmaniov1alpha1.BpfProgramCommon{
BpfFunctionName: bpfFentryFunctionName,
ByteCode: bpfmaniov1alpha1.BytecodeSelector{
Path: &bytecodePath,
},
},
FunctionName: functionFentryName,
},
Expand All @@ -53,9 +53,6 @@ func TestBpfApplicationControllerCreate(t *testing.T) {
Kprobe: &bpfmaniov1alpha1.KprobeProgramInfo{
BpfProgramCommon: bpfmaniov1alpha1.BpfProgramCommon{
BpfFunctionName: bpfKprobeFunctionName,
ByteCode: bpfmaniov1alpha1.BytecodeSelector{
Path: &bytecodePath,
},
},
FunctionName: functionKprobeName,
Offset: uint64(offset),
Expand All @@ -67,9 +64,6 @@ func TestBpfApplicationControllerCreate(t *testing.T) {
Tracepoint: &bpfmaniov1alpha1.TracepointProgramInfo{
BpfProgramCommon: bpfmaniov1alpha1.BpfProgramCommon{
BpfFunctionName: bpfTracepointFunctionName,
ByteCode: bpfmaniov1alpha1.BytecodeSelector{
Path: &bytecodePath,
},
},
Names: []string{tracepointName},
},
Expand Down
29 changes: 18 additions & 11 deletions controllers/bpfman-agent/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ type ReconcilerCommon struct {
Logger logr.Logger
NodeName string
progId *uint32
appOwner metav1.Object // Set if the owner is an application
}

// bpfmanReconciler defines a generic bpfProgram K8s object reconciler which can
Expand All @@ -88,6 +89,9 @@ type bpfmanReconciler interface {
// getFinalizer returns the string used for the finalizer to prevent the
// BpfProgram object from deletion until cleanup can be performed
getFinalizer() string
// getOwner returns the owner of the BpfProgram object. This is either the
// *Program or the BpfApplicationProgram that created it.
getOwner() metav1.Object
// getRecType returns the type of the reconciler. This is often the string
// representation of the ProgramType, but in cases where there are multiple
// reconcilers for a single ProgramType, it may be different (e.g., uprobe,
Expand Down Expand Up @@ -119,21 +123,24 @@ type bpfmanReconciler interface {
}

// reconcileCommon is the common reconciler loop called by each bpfman
// reconciler. It reconciles each program in the list. reconcileCommon should
// not return error because it will trigger an infinite reconcile loop.
// Instead, it should report the error to user and retry if specified. For some
// errors the controller may decide not to retry. Note: This only results in
// calls to bpfman if we need to change something
// reconciler. It reconciles each program in the list. The boolean return
// value is set to true if we've made it through all the programs in the list
// without anything being updated and a reque has not been requested. Otherwise,
// it's set to false. reconcileCommon should not return error because it will
// trigger an infinite reconcile loop. Instead, it should report the error to
// user and retry if specified. For some errors the controller may decide not to
// retry. Note: This only results in calls to bpfman if we need to change
// something
func (r *ReconcilerCommon) reconcileCommon(ctx context.Context, rec bpfmanReconciler,
programs []client.Object) (ctrl.Result, error) {
programs []client.Object) (bool, ctrl.Result, error) {

r.Logger.V(1).Info("Start reconcileCommon()")

// Get existing ebpf state from bpfman.
loadedBpfPrograms, err := bpfmanagentinternal.ListBpfmanPrograms(ctx, r.BpfmanClient, rec.getProgType())
if err != nil {
r.Logger.Error(err, "failed to list loaded bpfman programs")
return ctrl.Result{Requeue: true, RequeueAfter: retryDurationAgent}, nil
return false, ctrl.Result{Requeue: true, RequeueAfter: retryDurationAgent}, nil
}

requeue := false // initialize requeue to false
Expand All @@ -144,7 +151,7 @@ func (r *ReconcilerCommon) reconcileCommon(ctx context.Context, rec bpfmanReconc
err := rec.setCurrentProgram(program)
if err != nil {
r.Logger.Error(err, "Failed to set current program")
return ctrl.Result{Requeue: true, RequeueAfter: retryDurationAgent}, nil
return false, ctrl.Result{Requeue: true, RequeueAfter: retryDurationAgent}, nil
}

result, err := r.reconcileProgram(ctx, rec, program, loadedBpfPrograms)
Expand All @@ -157,7 +164,7 @@ func (r *ReconcilerCommon) reconcileCommon(ctx context.Context, rec bpfmanReconc
// continue with next program
case internal.Updated:
// return
return ctrl.Result{Requeue: false}, nil
return false, ctrl.Result{Requeue: false}, nil
case internal.Requeue:
// remember to do a requeue when we're done and continue with next program
requeue = true
Expand All @@ -166,11 +173,11 @@ func (r *ReconcilerCommon) reconcileCommon(ctx context.Context, rec bpfmanReconc

if requeue {
// A requeue has been requested
return ctrl.Result{RequeueAfter: retryDurationAgent}, nil
return false, ctrl.Result{RequeueAfter: retryDurationAgent}, nil
} else {
// We've made it through all the programs in the list without anything being
// updated and a reque has not been requested.
return ctrl.Result{Requeue: false}, nil
return true, ctrl.Result{Requeue: false}, nil
}
}

Expand Down
19 changes: 16 additions & 3 deletions controllers/bpfman-agent/fentry-program.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,20 @@ func (r *FentryProgramReconciler) getFinalizer() string {
return internal.FentryProgramControllerFinalizer
}

func (r *FentryProgramReconciler) getOwner() metav1.Object {
if r.appOwner == nil {
return r.currentFentryProgram
} else {
return r.appOwner
}
}

func (r *FentryProgramReconciler) getRecType() string {
return internal.FentryString
if r.appOwner == nil {
return internal.FentryString
} else {
return internal.ApplicationString
}
}

func (r *FentryProgramReconciler) getProgType() internal.ProgramType {
Expand Down Expand Up @@ -122,7 +134,7 @@ func (r *FentryProgramReconciler) getExpectedBpfPrograms(ctx context.Context) (*

annotations := map[string]string{internal.FentryProgramFunction: r.currentFentryProgram.Spec.FunctionName}

prog, err := r.createBpfProgram(bpfProgramName, r.getFinalizer(), r.currentFentryProgram, r.getRecType(), annotations)
prog, err := r.createBpfProgram(bpfProgramName, r.getFinalizer(), r.getOwner(), r.getRecType(), annotations)
if err != nil {
return nil, fmt.Errorf("failed to create BpfProgram %s: %v", bpfProgramName, err)
}
Expand Down Expand Up @@ -168,7 +180,8 @@ func (r *FentryProgramReconciler) Reconcile(ctx context.Context, req ctrl.Reques
}

// Reconcile each FentryProgram.
return r.reconcileCommon(ctx, r, fentryObjects)
_, result, err := r.reconcileCommon(ctx, r, fentryObjects)
return result, err
}

func (r *FentryProgramReconciler) getLoadRequest(bpfProgram *bpfmaniov1alpha1.BpfProgram, mapOwnerId *uint32) (*gobpfman.LoadRequest, error) {
Expand Down
19 changes: 16 additions & 3 deletions controllers/bpfman-agent/fexit-program.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,20 @@ func (r *FexitProgramReconciler) getFinalizer() string {
return internal.FexitProgramControllerFinalizer
}

func (r *FexitProgramReconciler) getOwner() metav1.Object {
if r.appOwner == nil {
return r.currentFexitProgram
} else {
return r.appOwner
}
}

func (r *FexitProgramReconciler) getRecType() string {
return internal.FexitString
if r.appOwner == nil {
return internal.FexitString
} else {
return internal.ApplicationString
}
}

func (r *FexitProgramReconciler) getProgType() internal.ProgramType {
Expand Down Expand Up @@ -122,7 +134,7 @@ func (r *FexitProgramReconciler) getExpectedBpfPrograms(ctx context.Context) (*b

annotations := map[string]string{internal.FexitProgramFunction: r.currentFexitProgram.Spec.FunctionName}

prog, err := r.createBpfProgram(bpfProgramName, r.getFinalizer(), r.currentFexitProgram, r.getRecType(), annotations)
prog, err := r.createBpfProgram(bpfProgramName, r.getFinalizer(), r.getOwner(), r.getRecType(), annotations)
if err != nil {
return nil, fmt.Errorf("failed to create BpfProgram %s: %v", bpfProgramName, err)
}
Expand Down Expand Up @@ -168,7 +180,8 @@ func (r *FexitProgramReconciler) Reconcile(ctx context.Context, req ctrl.Request
}

// Reconcile each FexitProgram.
return r.reconcileCommon(ctx, r, fexitObjects)
_, result, err := r.reconcileCommon(ctx, r, fexitObjects)
return result, err
}

func (r *FexitProgramReconciler) getLoadRequest(bpfProgram *bpfmaniov1alpha1.BpfProgram, mapOwnerId *uint32) (*gobpfman.LoadRequest, error) {
Expand Down
19 changes: 16 additions & 3 deletions controllers/bpfman-agent/kprobe-program.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,20 @@ func (r *KprobeProgramReconciler) getFinalizer() string {
return internal.KprobeProgramControllerFinalizer
}

func (r *KprobeProgramReconciler) getOwner() metav1.Object {
if r.appOwner == nil {
return r.currentKprobeProgram
} else {
return r.appOwner
}
}

func (r *KprobeProgramReconciler) getRecType() string {
return internal.Kprobe.String()
if r.appOwner == nil {
return internal.Kprobe.String()
} else {
return internal.ApplicationString
}
}

func (r *KprobeProgramReconciler) getProgType() internal.ProgramType {
Expand Down Expand Up @@ -122,7 +134,7 @@ func (r *KprobeProgramReconciler) getExpectedBpfPrograms(ctx context.Context) (*

annotations := map[string]string{internal.KprobeProgramFunction: r.currentKprobeProgram.Spec.FunctionName}

prog, err := r.createBpfProgram(bpfProgramName, r.getFinalizer(), r.currentKprobeProgram, r.getRecType(), annotations)
prog, err := r.createBpfProgram(bpfProgramName, r.getFinalizer(), r.getOwner(), r.getRecType(), annotations)
if err != nil {
return nil, fmt.Errorf("failed to create BpfProgram %s: %v", bpfProgramName, err)
}
Expand Down Expand Up @@ -168,7 +180,8 @@ func (r *KprobeProgramReconciler) Reconcile(ctx context.Context, req ctrl.Reques
}

// Reconcile each KprobeProgram.
return r.reconcileCommon(ctx, r, kprobeObjects)
_, result, err := r.reconcileCommon(ctx, r, kprobeObjects)
return result, err
}

func (r *KprobeProgramReconciler) getLoadRequest(bpfProgram *bpfmaniov1alpha1.BpfProgram, mapOwnerId *uint32) (*gobpfman.LoadRequest, error) {
Expand Down
19 changes: 16 additions & 3 deletions controllers/bpfman-agent/tc-program.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,20 @@ func (r *TcProgramReconciler) getFinalizer() string {
return internal.TcProgramControllerFinalizer
}

func (r *TcProgramReconciler) getOwner() metav1.Object {
if r.appOwner == nil {
return r.currentTcProgram
} else {
return r.appOwner
}
}

func (r *TcProgramReconciler) getRecType() string {
return internal.Tc.String()
if r.appOwner == nil {
return internal.Tc.String()
} else {
return internal.ApplicationString
}
}

func (r *TcProgramReconciler) getProgType() internal.ProgramType {
Expand Down Expand Up @@ -164,7 +176,7 @@ func (r *TcProgramReconciler) getExpectedBpfPrograms(ctx context.Context) (*bpfm
bpfProgramName := fmt.Sprintf("%s-%s-%s", r.currentTcProgram.Name, r.NodeName, iface)
annotations := map[string]string{internal.TcProgramInterface: iface}

prog, err := r.createBpfProgram(bpfProgramName, r.getFinalizer(), r.currentTcProgram, r.getRecType(), annotations)
prog, err := r.createBpfProgram(bpfProgramName, r.getFinalizer(), r.getOwner(), r.getRecType(), annotations)
if err != nil {
return nil, fmt.Errorf("failed to create BpfProgram %s: %v", bpfProgramName, err)
}
Expand Down Expand Up @@ -211,7 +223,8 @@ func (r *TcProgramReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
}

// Reconcile each TcProgram.
return r.reconcileCommon(ctx, r, tcObjects)
_, result, err := r.reconcileCommon(ctx, r, tcObjects)
return result, err
}

func (r *TcProgramReconciler) getLoadRequest(bpfProgram *bpfmaniov1alpha1.BpfProgram, mapOwnerId *uint32) (*gobpfman.LoadRequest, error) {
Expand Down
Loading

0 comments on commit 4158e39

Please sign in to comment.