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 }