123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- package link
- import (
- "errors"
- "unsafe"
- "github.com/cilium/ebpf"
- "github.com/cilium/ebpf/asm"
- "github.com/cilium/ebpf/internal"
- "github.com/cilium/ebpf/internal/unix"
- )
- // Type is the kind of link.
- type Type uint32
- // Valid link types.
- //
- // Equivalent to enum bpf_link_type.
- const (
- UnspecifiedType Type = iota
- RawTracepointType
- TracingType
- CgroupType
- IterType
- NetNsType
- XDPType
- )
- var haveProgAttach = internal.FeatureTest("BPF_PROG_ATTACH", "4.10", func() error {
- prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{
- Type: ebpf.CGroupSKB,
- AttachType: ebpf.AttachCGroupInetIngress,
- License: "MIT",
- Instructions: asm.Instructions{
- asm.Mov.Imm(asm.R0, 0),
- asm.Return(),
- },
- })
- if err != nil {
- return internal.ErrNotSupported
- }
- // BPF_PROG_ATTACH was introduced at the same time as CGgroupSKB,
- // so being able to load the program is enough to infer that we
- // have the syscall.
- prog.Close()
- return nil
- })
- var haveProgAttachReplace = internal.FeatureTest("BPF_PROG_ATTACH atomic replacement", "5.5", func() error {
- if err := haveProgAttach(); err != nil {
- return err
- }
- prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{
- Type: ebpf.CGroupSKB,
- AttachType: ebpf.AttachCGroupInetIngress,
- License: "MIT",
- Instructions: asm.Instructions{
- asm.Mov.Imm(asm.R0, 0),
- asm.Return(),
- },
- })
- if err != nil {
- return internal.ErrNotSupported
- }
- defer prog.Close()
- // We know that we have BPF_PROG_ATTACH since we can load CGroupSKB programs.
- // If passing BPF_F_REPLACE gives us EINVAL we know that the feature isn't
- // present.
- attr := internal.BPFProgAttachAttr{
- // We rely on this being checked after attachFlags.
- TargetFd: ^uint32(0),
- AttachBpfFd: uint32(prog.FD()),
- AttachType: uint32(ebpf.AttachCGroupInetIngress),
- AttachFlags: uint32(flagReplace),
- }
- err = internal.BPFProgAttach(&attr)
- if errors.Is(err, unix.EINVAL) {
- return internal.ErrNotSupported
- }
- if errors.Is(err, unix.EBADF) {
- return nil
- }
- return err
- })
- type bpfLinkCreateAttr struct {
- progFd uint32
- targetFd uint32
- attachType ebpf.AttachType
- flags uint32
- }
- func bpfLinkCreate(attr *bpfLinkCreateAttr) (*internal.FD, error) {
- ptr, err := internal.BPF(internal.BPF_LINK_CREATE, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
- if err != nil {
- return nil, err
- }
- return internal.NewFD(uint32(ptr)), nil
- }
- type bpfLinkUpdateAttr struct {
- linkFd uint32
- newProgFd uint32
- flags uint32
- oldProgFd uint32
- }
- func bpfLinkUpdate(attr *bpfLinkUpdateAttr) error {
- _, err := internal.BPF(internal.BPF_LINK_UPDATE, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
- return err
- }
- var haveBPFLink = internal.FeatureTest("bpf_link", "5.7", func() error {
- prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{
- Type: ebpf.CGroupSKB,
- AttachType: ebpf.AttachCGroupInetIngress,
- License: "MIT",
- Instructions: asm.Instructions{
- asm.Mov.Imm(asm.R0, 0),
- asm.Return(),
- },
- })
- if err != nil {
- return internal.ErrNotSupported
- }
- defer prog.Close()
- attr := bpfLinkCreateAttr{
- // This is a hopefully invalid file descriptor, which triggers EBADF.
- targetFd: ^uint32(0),
- progFd: uint32(prog.FD()),
- attachType: ebpf.AttachCGroupInetIngress,
- }
- _, err = bpfLinkCreate(&attr)
- if errors.Is(err, unix.EINVAL) {
- return internal.ErrNotSupported
- }
- if errors.Is(err, unix.EBADF) {
- return nil
- }
- return err
- })
- type bpfIterCreateAttr struct {
- linkFd uint32
- flags uint32
- }
- func bpfIterCreate(attr *bpfIterCreateAttr) (*internal.FD, error) {
- ptr, err := internal.BPF(internal.BPF_ITER_CREATE, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
- if err == nil {
- return internal.NewFD(uint32(ptr)), nil
- }
- return nil, err
- }
- type bpfRawTracepointOpenAttr struct {
- name internal.Pointer
- fd uint32
- _ uint32
- }
- func bpfRawTracepointOpen(attr *bpfRawTracepointOpenAttr) (*internal.FD, error) {
- ptr, err := internal.BPF(internal.BPF_RAW_TRACEPOINT_OPEN, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
- if err == nil {
- return internal.NewFD(uint32(ptr)), nil
- }
- return nil, err
- }
|