github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/link/program.go (about)

     1  package link
     2  
     3  import (
     4  	"fmt"
     5  	"runtime"
     6  
     7  	"github.com/cilium/ebpf"
     8  	"github.com/cilium/ebpf/internal/sys"
     9  )
    10  
    11  type RawAttachProgramOptions struct {
    12  	// Target to query. This is usually a file descriptor but may refer to
    13  	// something else based on the attach type.
    14  	Target int
    15  	// Program to attach.
    16  	Program *ebpf.Program
    17  	// Attach must match the attach type of Program.
    18  	Attach ebpf.AttachType
    19  	// Attach relative to an anchor. Optional.
    20  	Anchor Anchor
    21  	// Flags control the attach behaviour. Specify an Anchor instead of
    22  	// F_LINK, F_ID, F_BEFORE, F_AFTER and F_REPLACE. Optional.
    23  	Flags uint32
    24  	// Only attach if the internal revision matches the given value.
    25  	ExpectedRevision uint64
    26  }
    27  
    28  // RawAttachProgram is a low level wrapper around BPF_PROG_ATTACH.
    29  //
    30  // You should use one of the higher level abstractions available in this
    31  // package if possible.
    32  func RawAttachProgram(opts RawAttachProgramOptions) error {
    33  	if opts.Flags&anchorFlags != 0 {
    34  		return fmt.Errorf("disallowed flags: use Anchor to specify attach target")
    35  	}
    36  
    37  	attr := sys.ProgAttachAttr{
    38  		TargetFdOrIfindex: uint32(opts.Target),
    39  		AttachBpfFd:       uint32(opts.Program.FD()),
    40  		AttachType:        uint32(opts.Attach),
    41  		AttachFlags:       uint32(opts.Flags),
    42  		ExpectedRevision:  opts.ExpectedRevision,
    43  	}
    44  
    45  	if opts.Anchor != nil {
    46  		fdOrID, flags, err := opts.Anchor.anchor()
    47  		if err != nil {
    48  			return fmt.Errorf("attach program: %w", err)
    49  		}
    50  
    51  		if flags == sys.BPF_F_REPLACE {
    52  			// Ensure that replacing a program works on old kernels.
    53  			attr.ReplaceBpfFd = fdOrID
    54  		} else {
    55  			attr.RelativeFdOrId = fdOrID
    56  			attr.AttachFlags |= flags
    57  		}
    58  	}
    59  
    60  	if err := sys.ProgAttach(&attr); err != nil {
    61  		if haveFeatErr := haveProgAttach(); haveFeatErr != nil {
    62  			return haveFeatErr
    63  		}
    64  		return fmt.Errorf("attach program: %w", err)
    65  	}
    66  	runtime.KeepAlive(opts.Program)
    67  
    68  	return nil
    69  }
    70  
    71  type RawDetachProgramOptions RawAttachProgramOptions
    72  
    73  // RawDetachProgram is a low level wrapper around BPF_PROG_DETACH.
    74  //
    75  // You should use one of the higher level abstractions available in this
    76  // package if possible.
    77  func RawDetachProgram(opts RawDetachProgramOptions) error {
    78  	if opts.Flags&anchorFlags != 0 {
    79  		return fmt.Errorf("disallowed flags: use Anchor to specify attach target")
    80  	}
    81  
    82  	attr := sys.ProgDetachAttr{
    83  		TargetFdOrIfindex: uint32(opts.Target),
    84  		AttachBpfFd:       uint32(opts.Program.FD()),
    85  		AttachType:        uint32(opts.Attach),
    86  		ExpectedRevision:  opts.ExpectedRevision,
    87  	}
    88  
    89  	if opts.Anchor != nil {
    90  		fdOrID, flags, err := opts.Anchor.anchor()
    91  		if err != nil {
    92  			return fmt.Errorf("detach program: %w", err)
    93  		}
    94  
    95  		attr.RelativeFdOrId = fdOrID
    96  		attr.AttachFlags |= flags
    97  	}
    98  
    99  	if err := sys.ProgDetach(&attr); err != nil {
   100  		if haveFeatErr := haveProgAttach(); haveFeatErr != nil {
   101  			return haveFeatErr
   102  		}
   103  		return fmt.Errorf("can't detach program: %w", err)
   104  	}
   105  
   106  	return nil
   107  }