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

     1  package link
     2  
     3  import (
     4  	"os"
     5  	"slices"
     6  	"testing"
     7  
     8  	"github.com/cilium/ebpf"
     9  	"github.com/cilium/ebpf/internal/testutils"
    10  
    11  	"github.com/go-quicktest/qt"
    12  )
    13  
    14  func TestQueryPrograms(t *testing.T) {
    15  	for name, fn := range map[string]func(*testing.T) (*ebpf.Program, Link, QueryOptions){
    16  		"cgroup":      queryCgroupProgAttachFixtures,
    17  		"cgroup link": queryCgroupLinkFixtures,
    18  		"netns":       queryNetNSFixtures,
    19  		"tcx":         queryTCXFixtures,
    20  	} {
    21  		t.Run(name, func(t *testing.T) {
    22  			prog, link, opts := fn(t)
    23  			result, err := QueryPrograms(opts)
    24  			testutils.SkipIfNotSupported(t, err)
    25  			qt.Assert(t, qt.IsNil(err))
    26  
    27  			progInfo, err := prog.Info()
    28  			qt.Assert(t, qt.IsNil(err))
    29  			progID, _ := progInfo.ID()
    30  
    31  			i := slices.IndexFunc(result.Programs, func(ap AttachedProgram) bool {
    32  				return ap.ID == progID
    33  			})
    34  			qt.Assert(t, qt.Not(qt.Equals(i, -1)))
    35  
    36  			if name == "tcx" {
    37  				qt.Assert(t, qt.Not(qt.Equals(result.Revision, 0)))
    38  			}
    39  
    40  			if result.HaveLinkInfo() {
    41  				ap := result.Programs[i]
    42  				linkInfo, err := link.Info()
    43  				qt.Assert(t, qt.IsNil(err))
    44  
    45  				linkID, ok := ap.LinkID()
    46  				qt.Assert(t, qt.IsTrue(ok))
    47  				qt.Assert(t, qt.Equals(linkID, linkInfo.ID))
    48  			}
    49  		})
    50  	}
    51  }
    52  
    53  func queryCgroupProgAttachFixtures(t *testing.T) (*ebpf.Program, Link, QueryOptions) {
    54  	cgroup, prog := mustCgroupFixtures(t)
    55  
    56  	link, err := newProgAttachCgroup(cgroup, ebpf.AttachCGroupInetEgress, prog, flagAllowOverride)
    57  	if err != nil {
    58  		t.Fatal("Can't create link:", err)
    59  	}
    60  	t.Cleanup(func() {
    61  		qt.Assert(t, qt.IsNil(link.Close()))
    62  	})
    63  
    64  	return prog, nil, QueryOptions{
    65  		Target: int(cgroup.Fd()),
    66  		Attach: ebpf.AttachCGroupInetEgress,
    67  	}
    68  }
    69  
    70  func queryCgroupLinkFixtures(t *testing.T) (*ebpf.Program, Link, QueryOptions) {
    71  	cgroup, prog := mustCgroupFixtures(t)
    72  
    73  	link, err := newLinkCgroup(cgroup, ebpf.AttachCGroupInetEgress, prog)
    74  	testutils.SkipIfNotSupported(t, err)
    75  	if err != nil {
    76  		t.Fatal("Can't create link:", err)
    77  	}
    78  	t.Cleanup(func() {
    79  		qt.Assert(t, qt.IsNil(link.Close()))
    80  	})
    81  
    82  	return prog, nil, QueryOptions{
    83  		Target: int(cgroup.Fd()),
    84  		Attach: ebpf.AttachCGroupInetEgress,
    85  	}
    86  }
    87  
    88  func queryNetNSFixtures(t *testing.T) (*ebpf.Program, Link, QueryOptions) {
    89  	testutils.SkipOnOldKernel(t, "4.20", "flow_dissector program")
    90  
    91  	prog := mustLoadProgram(t, ebpf.FlowDissector, ebpf.AttachFlowDissector, "")
    92  
    93  	// RawAttachProgramOptions.Target needs to be 0, as PROG_ATTACH with namespaces
    94  	// only works with the threads current netns. Any other fd will be rejected.
    95  	if err := RawAttachProgram(RawAttachProgramOptions{
    96  		Target:  0,
    97  		Program: prog,
    98  		Attach:  ebpf.AttachFlowDissector,
    99  	}); err != nil {
   100  		t.Fatal(err)
   101  	}
   102  
   103  	t.Cleanup(func() {
   104  		err := RawDetachProgram(RawDetachProgramOptions{
   105  			Target:  0,
   106  			Program: prog,
   107  			Attach:  ebpf.AttachFlowDissector,
   108  		})
   109  		if err != nil {
   110  			t.Fatal(err)
   111  		}
   112  	})
   113  
   114  	netns, err := os.Open("/proc/self/ns/net")
   115  	qt.Assert(t, qt.IsNil(err))
   116  	t.Cleanup(func() { netns.Close() })
   117  
   118  	return prog, nil, QueryOptions{
   119  		Target: int(netns.Fd()),
   120  		Attach: ebpf.AttachFlowDissector,
   121  	}
   122  }
   123  
   124  func queryTCXFixtures(t *testing.T) (*ebpf.Program, Link, QueryOptions) {
   125  	testutils.SkipOnOldKernel(t, "6.6", "TCX link")
   126  
   127  	prog := mustLoadProgram(t, ebpf.SchedCLS, ebpf.AttachTCXIngress, "")
   128  
   129  	link, iface := mustAttachTCX(t, prog, ebpf.AttachTCXIngress)
   130  
   131  	return prog, link, QueryOptions{
   132  		Target: iface,
   133  		Attach: ebpf.AttachTCXIngress,
   134  	}
   135  }