github.com/cilium/cilium@v1.16.2/pkg/socketlb/cgroup_test.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package socketlb
     5  
     6  import (
     7  	"errors"
     8  	"os"
     9  	"path/filepath"
    10  	"testing"
    11  
    12  	"github.com/cilium/ebpf"
    13  	"github.com/cilium/ebpf/asm"
    14  	"github.com/cilium/ebpf/link"
    15  
    16  	"github.com/cilium/cilium/pkg/testutils"
    17  )
    18  
    19  func mustCgroupProgram(t *testing.T) *ebpf.Program {
    20  	p, err := ebpf.NewProgram(&ebpf.ProgramSpec{
    21  		Type: ebpf.CGroupSKB,
    22  		Instructions: asm.Instructions{
    23  			asm.Mov.Imm(asm.R0, 0),
    24  			asm.Return(),
    25  		},
    26  		License: "Apache-2.0",
    27  	})
    28  	if err != nil {
    29  		t.Skipf("cgroup programs not supported: %s", err)
    30  	}
    31  	return p
    32  }
    33  
    34  // Attach a program to a clean cgroup hook, no replacing necessary.
    35  func TestAttachCgroup(t *testing.T) {
    36  	testutils.PrivilegedTest(t)
    37  
    38  	coll := &ebpf.Collection{
    39  		Programs: map[string]*ebpf.Program{"test": mustCgroupProgram(t)},
    40  	}
    41  	linkPath := testutils.TempBPFFS(t)
    42  	cgroupPath := testutils.TempCgroup(t)
    43  
    44  	if err := attachCgroup(coll, "test", cgroupPath, linkPath); err != nil {
    45  		t.Fatal(err)
    46  	}
    47  
    48  	if err := detachCgroup("test", cgroupPath, linkPath); err != nil {
    49  		t.Fatal(err)
    50  	}
    51  }
    52  
    53  // Replace an existing program attached using PROG_ATTACH. On newer kernels,
    54  // this will attempt to replace a PROG_ATTACH with a bpf_link.
    55  func TestAttachCgroupWithPreviousAttach(t *testing.T) {
    56  	testutils.PrivilegedTest(t)
    57  
    58  	prog := mustCgroupProgram(t)
    59  	coll := &ebpf.Collection{
    60  		Programs: map[string]*ebpf.Program{"test": prog},
    61  	}
    62  
    63  	linkPath := testutils.TempBPFFS(t)
    64  	cgroupPath := testutils.TempCgroup(t)
    65  	f, err := os.Open(cgroupPath)
    66  	if err != nil {
    67  		t.Fatal(err)
    68  	}
    69  
    70  	if err := link.RawAttachProgram(link.RawAttachProgramOptions{
    71  		Target:  int(f.Fd()),
    72  		Program: prog,
    73  		// Dummy attach type, must match the conclusion made by attachCgroup.
    74  		Attach: ebpf.AttachCGroupInetIngress,
    75  	}); err != nil {
    76  		t.Fatal(err)
    77  	}
    78  
    79  	if err := attachCgroup(coll, "test", cgroupPath, linkPath); err != nil {
    80  		t.Fatal(err)
    81  	}
    82  
    83  	if err := detachCgroup("test", cgroupPath, linkPath); err != nil {
    84  		t.Fatal(err)
    85  	}
    86  }
    87  
    88  // On kernels that support it, update a bpf_link attachment by opening a pin.
    89  func TestAttachCgroupWithExistingLink(t *testing.T) {
    90  	testutils.PrivilegedTest(t)
    91  
    92  	prog := mustCgroupProgram(t)
    93  	coll := &ebpf.Collection{
    94  		Programs: map[string]*ebpf.Program{"test": prog},
    95  	}
    96  
    97  	linkPath := testutils.TempBPFFS(t)
    98  	cgroupPath := testutils.TempCgroup(t)
    99  	f, err := os.Open(cgroupPath)
   100  	if err != nil {
   101  		t.Fatal(err)
   102  	}
   103  
   104  	l, err := link.AttachRawLink(link.RawLinkOptions{
   105  		Target:  int(f.Fd()),
   106  		Program: prog,
   107  		// Dummy attach type, must match the conclusion made by attachCgroup.
   108  		Attach: ebpf.AttachCGroupInetIngress,
   109  	})
   110  	if errors.Is(err, ebpf.ErrNotSupported) {
   111  		t.Skip("bpf_link is not supported")
   112  	}
   113  	if err != nil {
   114  		t.Fatal(err)
   115  	}
   116  
   117  	if err := l.Pin(filepath.Join(linkPath, "test")); err != nil {
   118  		t.Fatal(err)
   119  	}
   120  
   121  	if err := attachCgroup(coll, "test", cgroupPath, linkPath); err != nil {
   122  		t.Fatal(err)
   123  	}
   124  
   125  	if err := detachCgroup("test", cgroupPath, linkPath); err != nil {
   126  		t.Fatal(err)
   127  	}
   128  }
   129  
   130  // Detach an existing PROG_ATTACH.
   131  func TestDetachCGroupWithPreviousAttach(t *testing.T) {
   132  	testutils.PrivilegedTest(t)
   133  
   134  	prog := mustCgroupProgram(t)
   135  	linkPath := testutils.TempBPFFS(t)
   136  	cgroupPath := testutils.TempCgroup(t)
   137  	f, err := os.Open(cgroupPath)
   138  	if err != nil {
   139  		t.Fatal(err)
   140  	}
   141  
   142  	if err := link.RawAttachProgram(link.RawAttachProgramOptions{
   143  		Target:  int(f.Fd()),
   144  		Program: prog,
   145  		// Dummy attach type, must match the conclusion made by attachCgroup.
   146  		Attach: ebpf.AttachCGroupInetIngress,
   147  	}); err != nil {
   148  		t.Fatal(err)
   149  	}
   150  
   151  	if err := detachCgroup("test", cgroupPath, linkPath); err != nil {
   152  		t.Fatal(err)
   153  	}
   154  }
   155  
   156  // Detach an existing bpf_link.
   157  func TestDetachCGroupWithExistingLink(t *testing.T) {
   158  	testutils.PrivilegedTest(t)
   159  
   160  	prog := mustCgroupProgram(t)
   161  	linkPath := testutils.TempBPFFS(t)
   162  	cgroupPath := testutils.TempCgroup(t)
   163  	f, err := os.Open(cgroupPath)
   164  	if err != nil {
   165  		t.Fatal(err)
   166  	}
   167  
   168  	l, err := link.AttachRawLink(link.RawLinkOptions{
   169  		Target:  int(f.Fd()),
   170  		Program: prog,
   171  		// Dummy attach type, must match the conclusion made by attachCgroup.
   172  		Attach: ebpf.AttachCGroupInetIngress,
   173  	})
   174  	if errors.Is(err, ebpf.ErrNotSupported) {
   175  		t.Skip("bpf_link is not supported")
   176  	}
   177  	if err != nil {
   178  		t.Fatal(err)
   179  	}
   180  	if err := l.Pin(filepath.Join(linkPath, "test")); err != nil {
   181  		t.Fatal(err)
   182  	}
   183  
   184  	if err := detachCgroup("test", cgroupPath, linkPath); err != nil {
   185  		t.Fatal(err)
   186  	}
   187  }