github.com/cilium/cilium@v1.16.2/pkg/datapath/linux/ipsec/xfrm_state_cache_test.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package ipsec
     5  
     6  import (
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/require"
    10  	"github.com/vishvananda/netlink"
    11  
    12  	"github.com/cilium/cilium/pkg/datapath/linux/linux_defaults"
    13  	"github.com/cilium/cilium/pkg/option"
    14  	"github.com/cilium/cilium/pkg/time"
    15  
    16  	baseclocktest "k8s.io/utils/clock/testing"
    17  )
    18  
    19  func TestXfrmStateListCache(t *testing.T) {
    20  	setupIPSecSuitePrivileged(t)
    21  
    22  	backupOption := option.Config.EnableIPSecXfrmStateCaching
    23  	defer func() {
    24  		option.Config.EnableIPSecXfrmStateCaching = backupOption
    25  	}()
    26  	option.Config.EnableIPSecXfrmStateCaching = true
    27  
    28  	fakeClock := baseclocktest.NewFakeClock(time.Now())
    29  	xfrmStateCache := newTestableXfrmStateListCache(
    30  		time.Second,
    31  		fakeClock,
    32  	)
    33  
    34  	require.True(t, xfrmStateCache.isExpired(), "Cache should be expired in the beginning")
    35  
    36  	cleanIPSecStatesAndPolicies(t)
    37  	state := initDummyXfrmState()
    38  	err := createDummyXfrmState(state)
    39  	require.NoError(t, err)
    40  
    41  	// Make sure that cache is correctly fetched in the beginning
    42  	stateList, err := xfrmStateCache.XfrmStateList()
    43  	require.NoError(t, err)
    44  	require.Len(t, stateList, 1)
    45  	require.Equal(t, state.Spi, stateList[0].Spi)
    46  
    47  	cleanIPSecStatesAndPolicies(t)
    48  	// Check that cache does not expire instantly
    49  	stateList, err = xfrmStateCache.XfrmStateList()
    50  	require.NoError(t, err)
    51  	require.Len(t, stateList, 1)
    52  
    53  	// Move time by half second and make sure cache still did not expire
    54  	fakeClock.Step(time.Millisecond * 500)
    55  	require.False(t, xfrmStateCache.isExpired(), "Cache should not be expired before timeout")
    56  	stateList, err = xfrmStateCache.XfrmStateList()
    57  	require.NoError(t, err)
    58  	require.Len(t, stateList, 1)
    59  
    60  	// Invalidate cache by moving time by 501 more miliseconds
    61  	fakeClock.Step(time.Millisecond * 501)
    62  	require.True(t, xfrmStateCache.isExpired(), "Cache should be expired after timeout")
    63  	stateList, err = xfrmStateCache.XfrmStateList()
    64  	require.NoError(t, err)
    65  	require.Len(t, stateList, 0)
    66  
    67  	// Create new xfrm state and check that cache is atomatically updated
    68  	require.True(t, xfrmStateCache.isExpired(), "Cache should be expired when list is empty")
    69  	err = xfrmStateCache.XfrmStateAdd(state)
    70  	require.NoError(t, err)
    71  	require.True(t, xfrmStateCache.isExpired(), "Cache should be expired after adding new state")
    72  	stateList, err = xfrmStateCache.XfrmStateList()
    73  	require.NoError(t, err)
    74  	require.Len(t, stateList, 1)
    75  	require.Equal(t, stateList[0].OutputMark.Value, uint32(linux_defaults.RouteMarkDecrypt))
    76  
    77  	// Update xfrm state and check that cache is automatically updated
    78  	require.False(t, xfrmStateCache.isExpired(), "Cache should not be expired before timeout")
    79  	// Switch to encrypt as this is the only value we update
    80  	state.OutputMark.Value = linux_defaults.RouteMarkEncrypt
    81  	err = xfrmStateCache.XfrmStateUpdate(state)
    82  	require.NoError(t, err)
    83  	require.True(t, xfrmStateCache.isExpired(), "Cache should be expired after updating state")
    84  	stateList, err = xfrmStateCache.XfrmStateList()
    85  	require.NoError(t, err)
    86  	require.Len(t, stateList, 1)
    87  	require.Equal(t, stateList[0].OutputMark.Value, uint32(linux_defaults.RouteMarkEncrypt))
    88  
    89  	// Delete xfrm state and check that cache is automatically updated
    90  	require.False(t, xfrmStateCache.isExpired(), "Cache should not be expired before timeout")
    91  	err = xfrmStateCache.XfrmStateDel(state)
    92  	require.NoError(t, err)
    93  	require.True(t, xfrmStateCache.isExpired(), "Cache should be expired after deleting state")
    94  	stateList, err = xfrmStateCache.XfrmStateList()
    95  	require.NoError(t, err)
    96  	require.Len(t, stateList, 0)
    97  }
    98  
    99  func TestXfrmStateListCacheDisabled(t *testing.T) {
   100  	setupIPSecSuitePrivileged(t)
   101  
   102  	backupOption := option.Config.EnableIPSecXfrmStateCaching
   103  	defer func() {
   104  		option.Config.EnableIPSecXfrmStateCaching = backupOption
   105  	}()
   106  	option.Config.EnableIPSecXfrmStateCaching = false
   107  
   108  	xfrmStateCache := newTestableXfrmStateListCache(
   109  		time.Second,
   110  		baseclocktest.NewFakeClock(time.Now()),
   111  	)
   112  
   113  	state := initDummyXfrmState()
   114  	err := createDummyXfrmState(state)
   115  	require.NoError(t, err)
   116  
   117  	require.True(t, xfrmStateCache.isExpired(), "Cache should be expired in the beginning")
   118  	// Make sure that cache is correctly fetched in the beginning
   119  	stateList, err := xfrmStateCache.XfrmStateList()
   120  	require.NoError(t, err)
   121  	require.Len(t, stateList, 1)
   122  
   123  	// And is still expired
   124  	require.True(t, xfrmStateCache.isExpired(), "Cache should be stil expired as it's disabled")
   125  }
   126  
   127  func cleanIPSecStatesAndPolicies(t *testing.T) {
   128  	xfrmStateList, err := netlink.XfrmStateList(netlink.FAMILY_ALL)
   129  	if err != nil {
   130  		t.Fatalf("Can't list XFRM states: %v", err)
   131  	}
   132  
   133  	for _, s := range xfrmStateList {
   134  		if err := netlink.XfrmStateDel(&s); err != nil {
   135  			t.Fatalf("Can't delete XFRM state: %v", err)
   136  		}
   137  
   138  	}
   139  
   140  	xfrmPolicyList, err := netlink.XfrmPolicyList(netlink.FAMILY_ALL)
   141  	if err != nil {
   142  		t.Fatalf("Can't list XFRM policies: %v", err)
   143  	}
   144  
   145  	for _, p := range xfrmPolicyList {
   146  		if err := netlink.XfrmPolicyDel(&p); err != nil {
   147  			t.Fatalf("Can't delete XFRM policy: %v", err)
   148  		}
   149  	}
   150  }