github.com/cilium/cilium@v1.16.2/pkg/datapath/loader/tcx_test.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  //go:build linux
     5  
     6  package loader
     7  
     8  import (
     9  	"errors"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/stretchr/testify/require"
    14  
    15  	"github.com/cilium/ebpf"
    16  	"github.com/cilium/ebpf/link"
    17  
    18  	"github.com/cilium/cilium/pkg/datapath/linux/probes"
    19  	"github.com/cilium/cilium/pkg/testutils"
    20  	"github.com/cilium/cilium/pkg/testutils/netns"
    21  )
    22  
    23  func TestAttachDetachTCX(t *testing.T) {
    24  	testutils.PrivilegedTest(t)
    25  
    26  	skipTCXUnsupported(t)
    27  
    28  	ns := netns.NewNetNS(t)
    29  	ns.Do(func() error {
    30  		prog := mustTCProgramWithName(t, "cil_test")
    31  		linkDir := testutils.TempBPFFS(t)
    32  
    33  		// Attaching the same program twice should result in a link create and update.
    34  		require.NoError(t, upsertTCXProgram(lo, prog, "cil_test", linkDir, directionToParent(dirEgress)))
    35  		require.NoError(t, upsertTCXProgram(lo, prog, "cil_test", linkDir, directionToParent(dirEgress)))
    36  
    37  		// Query tcx programs.
    38  		hasPrograms, err := hasCiliumTCXLinks(lo, ebpf.AttachTCXEgress)
    39  		require.NoError(t, err)
    40  		require.True(t, hasPrograms)
    41  
    42  		// Detach the program.
    43  		err = detachSKBProgram(lo, "cil_test", linkDir, directionToParent(dirEgress))
    44  		require.NoError(t, err)
    45  
    46  		// bpf_prog_query is eventually-consistent, retries may be necessary.
    47  		require.NoError(t, testutils.WaitUntil(func() bool {
    48  			hasPrograms, err := hasCiliumTCXLinks(lo, ebpf.AttachTCXIngress)
    49  			require.NoError(t, err)
    50  			return !hasPrograms
    51  		}, time.Second))
    52  
    53  		return nil
    54  	})
    55  }
    56  
    57  func TestHasCiliumTCXLinks(t *testing.T) {
    58  	testutils.PrivilegedTest(t)
    59  
    60  	skipTCXUnsupported(t)
    61  
    62  	ns := netns.NewNetNS(t)
    63  	ns.Do(func() error {
    64  		// No tcx progs attached, expect false.
    65  		hasPrograms, err := hasCiliumTCXLinks(lo, ebpf.AttachTCXEgress)
    66  		require.NoError(t, err)
    67  		require.False(t, hasPrograms)
    68  
    69  		l1, err := link.AttachTCX(link.TCXOptions{
    70  			Program:   mustTCProgram(t),
    71  			Attach:    ebpf.AttachTCXEgress,
    72  			Interface: lo.Attrs().Index,
    73  			Anchor:    link.Tail(),
    74  		})
    75  		require.NoError(t, err)
    76  
    77  		// tcx program without cil_ prefix is attached, expect false.
    78  		hasPrograms, err = hasCiliumTCXLinks(lo, ebpf.AttachTCXEgress)
    79  		require.NoError(t, err)
    80  		require.False(t, hasPrograms)
    81  
    82  		l2, err := link.AttachTCX(link.TCXOptions{
    83  			Program:   mustTCProgramWithName(t, "cil_test"),
    84  			Attach:    ebpf.AttachTCXEgress,
    85  			Interface: lo.Attrs().Index,
    86  			Anchor:    link.Tail(),
    87  		})
    88  		require.NoError(t, err)
    89  
    90  		// tcx program with cil_ prefix is attached, expect true.
    91  		hasPrograms, err = hasCiliumTCXLinks(lo, ebpf.AttachTCXEgress)
    92  		require.NoError(t, err)
    93  		require.True(t, hasPrograms)
    94  
    95  		require.NoError(t, l1.Close())
    96  		require.NoError(t, l2.Close())
    97  
    98  		return nil
    99  	})
   100  }
   101  
   102  func skipTCXUnsupported(tb testing.TB) {
   103  	tb.Helper()
   104  
   105  	err := probes.HaveTCX()
   106  	if errors.Is(err, ebpf.ErrNotSupported) {
   107  		tb.Skip("tcx is not supported")
   108  	}
   109  	if err != nil {
   110  		tb.Fatalf("probing tcx support: %s", err)
   111  	}
   112  }