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

     1  package link
     2  
     3  import (
     4  	"fmt"
     5  	"sync/atomic"
     6  	"testing"
     7  
     8  	"github.com/cilium/ebpf"
     9  	"github.com/cilium/ebpf/internal/testutils"
    10  	"github.com/go-quicktest/qt"
    11  	"github.com/jsimonetti/rtnetlink/v2"
    12  	"github.com/jsimonetti/rtnetlink/v2/driver"
    13  	"golang.org/x/sys/unix"
    14  )
    15  
    16  func TestAttachNetkit(t *testing.T) {
    17  	testutils.SkipOnOldKernel(t, "6.7", "Netkit Device")
    18  
    19  	prog := mustLoadProgram(t, ebpf.SchedCLS, ebpf.AttachNetkitPrimary, "")
    20  	link, _ := mustAttachNetkit(t, prog, ebpf.AttachNetkitPrimary)
    21  
    22  	testLink(t, link, prog)
    23  }
    24  
    25  func TestNetkitAnchor(t *testing.T) {
    26  	testutils.SkipOnOldKernel(t, "6.7", "Netkit Device")
    27  
    28  	a := mustLoadProgram(t, ebpf.SchedCLS, ebpf.AttachNetkitPrimary, "")
    29  	b := mustLoadProgram(t, ebpf.SchedCLS, ebpf.AttachNetkitPrimary, "")
    30  
    31  	linkA, ifIndex := mustAttachNetkit(t, a, ebpf.AttachNetkitPrimary)
    32  
    33  	programInfo, err := a.Info()
    34  	qt.Assert(t, qt.IsNil(err))
    35  	programID, _ := programInfo.ID()
    36  
    37  	linkInfo, err := linkA.Info()
    38  	qt.Assert(t, qt.IsNil(err))
    39  	linkID := linkInfo.ID
    40  
    41  	for _, anchor := range []Anchor{
    42  		Head(),
    43  		Tail(),
    44  		BeforeProgram(a),
    45  		BeforeProgramByID(programID),
    46  		AfterLink(linkA),
    47  		AfterLinkByID(linkID),
    48  	} {
    49  		t.Run(fmt.Sprintf("%T", anchor), func(t *testing.T) {
    50  			linkB, err := AttachNetkit(NetkitOptions{
    51  				Program:   b,
    52  				Attach:    ebpf.AttachNetkitPrimary,
    53  				Interface: ifIndex,
    54  				Anchor:    anchor,
    55  			})
    56  			qt.Assert(t, qt.IsNil(err))
    57  			qt.Assert(t, qt.IsNil(linkB.Close()))
    58  		})
    59  	}
    60  }
    61  
    62  // The last ifindex we created.
    63  var prevIfindex atomic.Uint32
    64  
    65  func init() { prevIfindex.Store(1000 - 1) }
    66  
    67  func mustAttachNetkit(tb testing.TB, prog *ebpf.Program, attachType ebpf.AttachType) (Link, int) {
    68  	var err error
    69  	conn, err := rtnetlink.Dial(nil)
    70  	qt.Assert(tb, qt.IsNil(err))
    71  	tb.Cleanup(func() {
    72  		qt.Assert(tb, qt.IsNil(conn.Close()))
    73  	})
    74  
    75  	ifIndex := prevIfindex.Add(1)
    76  
    77  	layer2 := driver.NetkitModeL2
    78  	blackhole := driver.NetkitPolicyDrop
    79  	err = conn.Link.New(&rtnetlink.LinkMessage{
    80  		Family: unix.AF_UNSPEC,
    81  		Index:  ifIndex,
    82  		Flags:  unix.IFF_UP,
    83  		Change: unix.IFF_UP,
    84  		Attributes: &rtnetlink.LinkAttributes{
    85  			Info: &rtnetlink.LinkInfo{
    86  				Kind: "netkit",
    87  				Data: &driver.Netkit{
    88  					Mode:       &layer2,
    89  					PeerPolicy: &blackhole,
    90  				},
    91  			},
    92  		},
    93  	})
    94  	qt.Assert(tb, qt.IsNil(err))
    95  	tb.Cleanup(func() {
    96  		qt.Assert(tb, qt.IsNil(conn.Link.Delete(uint32(ifIndex))))
    97  	})
    98  
    99  	link, err := AttachNetkit(NetkitOptions{
   100  		Program:   prog,
   101  		Attach:    attachType,
   102  		Interface: int(ifIndex),
   103  	})
   104  	qt.Assert(tb, qt.IsNil(err))
   105  	tb.Cleanup(func() {
   106  		qt.Assert(tb, qt.IsNil(link.Close()))
   107  	})
   108  
   109  	return link, int(ifIndex)
   110  }