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

     1  package link
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/cilium/ebpf"
     7  	"github.com/cilium/ebpf/internal/sys"
     8  )
     9  
    10  const anchorFlags = sys.BPF_F_REPLACE |
    11  	sys.BPF_F_BEFORE |
    12  	sys.BPF_F_AFTER |
    13  	sys.BPF_F_ID |
    14  	sys.BPF_F_LINK_MPROG
    15  
    16  // Anchor is a reference to a link or program.
    17  //
    18  // It is used to describe where an attachment or detachment should take place
    19  // for link types which support multiple attachment.
    20  type Anchor interface {
    21  	// anchor returns an fd or ID and a set of flags.
    22  	//
    23  	// By default fdOrID is taken to reference a program, but BPF_F_LINK_MPROG
    24  	// changes this to refer to a link instead.
    25  	//
    26  	// BPF_F_BEFORE, BPF_F_AFTER, BPF_F_REPLACE modify where a link or program
    27  	// is attached. The default behaviour if none of these flags is specified
    28  	// matches BPF_F_AFTER.
    29  	anchor() (fdOrID, flags uint32, _ error)
    30  }
    31  
    32  type firstAnchor struct{}
    33  
    34  func (firstAnchor) anchor() (fdOrID, flags uint32, _ error) {
    35  	return 0, sys.BPF_F_BEFORE, nil
    36  }
    37  
    38  // Head is the position before all other programs or links.
    39  func Head() Anchor {
    40  	return firstAnchor{}
    41  }
    42  
    43  type lastAnchor struct{}
    44  
    45  func (lastAnchor) anchor() (fdOrID, flags uint32, _ error) {
    46  	return 0, sys.BPF_F_AFTER, nil
    47  }
    48  
    49  // Tail is the position after all other programs or links.
    50  func Tail() Anchor {
    51  	return lastAnchor{}
    52  }
    53  
    54  // Before is the position just in front of target.
    55  func BeforeLink(target Link) Anchor {
    56  	return anchor{target, sys.BPF_F_BEFORE}
    57  }
    58  
    59  // After is the position just after target.
    60  func AfterLink(target Link) Anchor {
    61  	return anchor{target, sys.BPF_F_AFTER}
    62  }
    63  
    64  // Before is the position just in front of target.
    65  func BeforeLinkByID(target ID) Anchor {
    66  	return anchor{target, sys.BPF_F_BEFORE}
    67  }
    68  
    69  // After is the position just after target.
    70  func AfterLinkByID(target ID) Anchor {
    71  	return anchor{target, sys.BPF_F_AFTER}
    72  }
    73  
    74  // Before is the position just in front of target.
    75  func BeforeProgram(target *ebpf.Program) Anchor {
    76  	return anchor{target, sys.BPF_F_BEFORE}
    77  }
    78  
    79  // After is the position just after target.
    80  func AfterProgram(target *ebpf.Program) Anchor {
    81  	return anchor{target, sys.BPF_F_AFTER}
    82  }
    83  
    84  // Replace the target itself.
    85  func ReplaceProgram(target *ebpf.Program) Anchor {
    86  	return anchor{target, sys.BPF_F_REPLACE}
    87  }
    88  
    89  // Before is the position just in front of target.
    90  func BeforeProgramByID(target ebpf.ProgramID) Anchor {
    91  	return anchor{target, sys.BPF_F_BEFORE}
    92  }
    93  
    94  // After is the position just after target.
    95  func AfterProgramByID(target ebpf.ProgramID) Anchor {
    96  	return anchor{target, sys.BPF_F_AFTER}
    97  }
    98  
    99  // Replace the target itself.
   100  func ReplaceProgramByID(target ebpf.ProgramID) Anchor {
   101  	return anchor{target, sys.BPF_F_REPLACE}
   102  }
   103  
   104  type anchor struct {
   105  	target   any
   106  	position uint32
   107  }
   108  
   109  func (ap anchor) anchor() (fdOrID, flags uint32, _ error) {
   110  	var typeFlag uint32
   111  	switch target := ap.target.(type) {
   112  	case *ebpf.Program:
   113  		fd := target.FD()
   114  		if fd < 0 {
   115  			return 0, 0, sys.ErrClosedFd
   116  		}
   117  		fdOrID = uint32(fd)
   118  		typeFlag = 0
   119  	case ebpf.ProgramID:
   120  		fdOrID = uint32(target)
   121  		typeFlag = sys.BPF_F_ID
   122  	case interface{ FD() int }:
   123  		fd := target.FD()
   124  		if fd < 0 {
   125  			return 0, 0, sys.ErrClosedFd
   126  		}
   127  		fdOrID = uint32(fd)
   128  		typeFlag = sys.BPF_F_LINK_MPROG
   129  	case ID:
   130  		fdOrID = uint32(target)
   131  		typeFlag = sys.BPF_F_LINK_MPROG | sys.BPF_F_ID
   132  	default:
   133  		return 0, 0, fmt.Errorf("invalid target %T", ap.target)
   134  	}
   135  
   136  	return fdOrID, ap.position | typeFlag, nil
   137  }