...

Source file src/github.com/cilium/ebpf/link/cgroup.go

Documentation: github.com/cilium/ebpf/link

     1  package link
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"os"
     7  
     8  	"github.com/cilium/ebpf"
     9  )
    10  
    11  type cgroupAttachFlags uint32
    12  
    13  // cgroup attach flags
    14  const (
    15  	flagAllowOverride cgroupAttachFlags = 1 << iota
    16  	flagAllowMulti
    17  	flagReplace
    18  )
    19  
    20  type CgroupOptions struct {
    21  	// Path to a cgroupv2 folder.
    22  	Path string
    23  	// One of the AttachCgroup* constants
    24  	Attach ebpf.AttachType
    25  	// Program must be of type CGroup*, and the attach type must match Attach.
    26  	Program *ebpf.Program
    27  }
    28  
    29  // AttachCgroup links a BPF program to a cgroup.
    30  func AttachCgroup(opts CgroupOptions) (Link, error) {
    31  	cgroup, err := os.Open(opts.Path)
    32  	if err != nil {
    33  		return nil, fmt.Errorf("can't open cgroup: %s", err)
    34  	}
    35  
    36  	clone, err := opts.Program.Clone()
    37  	if err != nil {
    38  		cgroup.Close()
    39  		return nil, err
    40  	}
    41  
    42  	var cg Link
    43  	cg, err = newLinkCgroup(cgroup, opts.Attach, clone)
    44  	if errors.Is(err, ErrNotSupported) {
    45  		cg, err = newProgAttachCgroup(cgroup, opts.Attach, clone, flagAllowMulti)
    46  	}
    47  	if errors.Is(err, ErrNotSupported) {
    48  		cg, err = newProgAttachCgroup(cgroup, opts.Attach, clone, flagAllowOverride)
    49  	}
    50  	if err != nil {
    51  		cgroup.Close()
    52  		clone.Close()
    53  		return nil, err
    54  	}
    55  
    56  	return cg, nil
    57  }
    58  
    59  type progAttachCgroup struct {
    60  	cgroup     *os.File
    61  	current    *ebpf.Program
    62  	attachType ebpf.AttachType
    63  	flags      cgroupAttachFlags
    64  }
    65  
    66  var _ Link = (*progAttachCgroup)(nil)
    67  
    68  func (cg *progAttachCgroup) isLink() {}
    69  
    70  func newProgAttachCgroup(cgroup *os.File, attach ebpf.AttachType, prog *ebpf.Program, flags cgroupAttachFlags) (*progAttachCgroup, error) {
    71  	if flags&flagAllowMulti > 0 {
    72  		if err := haveProgAttachReplace(); err != nil {
    73  			return nil, fmt.Errorf("can't support multiple programs: %w", err)
    74  		}
    75  	}
    76  
    77  	err := RawAttachProgram(RawAttachProgramOptions{
    78  		Target:  int(cgroup.Fd()),
    79  		Program: prog,
    80  		Flags:   uint32(flags),
    81  		Attach:  attach,
    82  	})
    83  	if err != nil {
    84  		return nil, fmt.Errorf("cgroup: %w", err)
    85  	}
    86  
    87  	return &progAttachCgroup{cgroup, prog, attach, flags}, nil
    88  }
    89  
    90  func (cg *progAttachCgroup) Close() error {
    91  	defer cg.cgroup.Close()
    92  	defer cg.current.Close()
    93  
    94  	err := RawDetachProgram(RawDetachProgramOptions{
    95  		Target:  int(cg.cgroup.Fd()),
    96  		Program: cg.current,
    97  		Attach:  cg.attachType,
    98  	})
    99  	if err != nil {
   100  		return fmt.Errorf("close cgroup: %s", err)
   101  	}
   102  	return nil
   103  }
   104  
   105  func (cg *progAttachCgroup) Update(prog *ebpf.Program) error {
   106  	new, err := prog.Clone()
   107  	if err != nil {
   108  		return err
   109  	}
   110  
   111  	args := RawAttachProgramOptions{
   112  		Target:  int(cg.cgroup.Fd()),
   113  		Program: prog,
   114  		Attach:  cg.attachType,
   115  		Flags:   uint32(cg.flags),
   116  	}
   117  
   118  	if cg.flags&flagAllowMulti > 0 {
   119  		// Atomically replacing multiple programs requires at least
   120  		// 5.5 (commit 7dd68b3279f17921 "bpf: Support replacing cgroup-bpf
   121  		// program in MULTI mode")
   122  		args.Flags |= uint32(flagReplace)
   123  		args.Replace = cg.current
   124  	}
   125  
   126  	if err := RawAttachProgram(args); err != nil {
   127  		new.Close()
   128  		return fmt.Errorf("can't update cgroup: %s", err)
   129  	}
   130  
   131  	cg.current.Close()
   132  	cg.current = new
   133  	return nil
   134  }
   135  
   136  func (cg *progAttachCgroup) Pin(string) error {
   137  	return fmt.Errorf("can't pin cgroup: %w", ErrNotSupported)
   138  }
   139  
   140  func (cg *progAttachCgroup) Unpin() error {
   141  	return fmt.Errorf("can't pin cgroup: %w", ErrNotSupported)
   142  }
   143  
   144  func (cg *progAttachCgroup) Info() (*Info, error) {
   145  	return nil, fmt.Errorf("can't get cgroup info: %w", ErrNotSupported)
   146  }
   147  
   148  type linkCgroup struct {
   149  	RawLink
   150  }
   151  
   152  var _ Link = (*linkCgroup)(nil)
   153  
   154  func newLinkCgroup(cgroup *os.File, attach ebpf.AttachType, prog *ebpf.Program) (*linkCgroup, error) {
   155  	link, err := AttachRawLink(RawLinkOptions{
   156  		Target:  int(cgroup.Fd()),
   157  		Program: prog,
   158  		Attach:  attach,
   159  	})
   160  	if err != nil {
   161  		return nil, err
   162  	}
   163  
   164  	return &linkCgroup{*link}, err
   165  }
   166  

View as plain text