github.com/cilium/cilium@v1.16.2/pkg/counter/prefixes_test.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package counter
     5  
     6  import (
     7  	"net"
     8  	"net/netip"
     9  	"testing"
    10  
    11  	"github.com/stretchr/testify/require"
    12  )
    13  
    14  func TestReferenceTracker(t *testing.T) {
    15  	v4Prefixes := []netip.Prefix{
    16  		netip.MustParsePrefix("0.0.0.0/0"),
    17  		netip.MustParsePrefix("192.0.0.0/15"),
    18  		netip.MustParsePrefix("192.0.0.0/15"),
    19  		netip.MustParsePrefix("192.0.2.2/31"),
    20  		netip.MustParsePrefix("192.0.2.3/32"),
    21  	}
    22  	v4PrefixesLengths := map[int]int{
    23  		0:  1,
    24  		15: 2,
    25  		31: 1,
    26  		32: 1,
    27  	}
    28  
    29  	result := NewPrefixLengthCounter(128, 32)
    30  
    31  	// Expected output is the combination of defaults and the above prefixes.
    32  	expectedPrefixLengths := make(IntCounter, len(v4PrefixesLengths))
    33  	for k, v := range v4PrefixesLengths {
    34  		expectedPrefixLengths[k] += v
    35  	}
    36  	// New prefixes are added (return true)
    37  	changed, err := result.Add(v4Prefixes)
    38  	require.NoError(t, err)
    39  	require.True(t, changed)
    40  	require.Equal(t, expectedPrefixLengths, result.v4)
    41  
    42  	// When we add the prefixes again, we should increase the reference
    43  	// counts appropriately
    44  	for k, v := range v4PrefixesLengths {
    45  		expectedPrefixLengths[k] += v
    46  	}
    47  	// This time, there are no new prefix lengths (return false).
    48  	changed, err = result.Add(v4Prefixes)
    49  	require.NoError(t, err)
    50  	require.False(t, changed)
    51  	require.Equal(t, expectedPrefixLengths, result.v4)
    52  
    53  	// Delete the /15 prefix and see that it is removed and doesn't affect
    54  	// other counts
    55  	prefixes15 := []netip.Prefix{
    56  		netip.MustParsePrefix("192.0.0.0/15"),
    57  	}
    58  	expectedPrefixLengths[15]--
    59  	require.False(t, result.Delete(prefixes15))
    60  	require.Equal(t, expectedPrefixLengths, result.v4)
    61  
    62  	// Delete some prefix lengths
    63  	for k, v := range v4PrefixesLengths {
    64  		expectedPrefixLengths[k] -= v
    65  	}
    66  	// No change in prefix lengths; each 'prefixes' was referenced twice.
    67  	require.False(t, result.Delete(v4Prefixes))
    68  	require.Equal(t, expectedPrefixLengths, result.v4)
    69  
    70  	// Re-add the /32 prefix and see that it is added back properly.
    71  	expectedPrefixLengths[15]++
    72  	changed, err = result.Add(prefixes15)
    73  	require.NoError(t, err)
    74  	require.False(t, changed)
    75  	require.Equal(t, expectedPrefixLengths, result.v4)
    76  
    77  	// When removing the 'prefixes' again, return true and the set of
    78  	// prefixes should be empty
    79  	require.True(t, result.Delete(v4Prefixes))
    80  	require.Equal(t, IntCounter{}, result.v4)
    81  
    82  	// Add back the v4 prefixes while we add v6 prefixes.
    83  	changed, err = result.Add(v4Prefixes)
    84  	require.NoError(t, err)
    85  	require.True(t, changed)
    86  	require.Equal(t, expectedPrefixLengths, result.v4)
    87  
    88  	v6Prefixes := []netip.Prefix{
    89  		netip.MustParsePrefix("::/0"),
    90  		netip.MustParsePrefix("FD33:DEAD:BEEF:CAFE::/76"),
    91  		netip.MustParsePrefix("FD33:DEAD:BEEF:CAFE::/96"),
    92  		netip.MustParsePrefix("fd33:dead:beef:cafe::91b2:b600/120"),
    93  	}
    94  	v6PrefixesLengths := map[int]int{
    95  		0:   1,
    96  		76:  1,
    97  		96:  1,
    98  		120: 1,
    99  	}
   100  
   101  	expectedPrefixLengths = make(IntCounter, len(v6PrefixesLengths))
   102  
   103  	// Add the v6 prefixes (changed: true)
   104  	for k, v := range v6PrefixesLengths {
   105  		expectedPrefixLengths[k] = v
   106  	}
   107  	changed, err = result.Add(v6Prefixes)
   108  	require.NoError(t, err)
   109  	require.True(t, changed)
   110  	require.Equal(t, expectedPrefixLengths, result.v6)
   111  
   112  	// Add the v6 prefixes again (changed: false)
   113  	for k, v := range v6PrefixesLengths {
   114  		expectedPrefixLengths[k] += v
   115  	}
   116  	changed, err = result.Add(v6Prefixes)
   117  	require.NoError(t, err)
   118  	require.False(t, changed)
   119  	require.Equal(t, expectedPrefixLengths, result.v6)
   120  
   121  	// Now, remove them (changed: false)
   122  	for k, v := range v6PrefixesLengths {
   123  		expectedPrefixLengths[k] -= v
   124  	}
   125  	require.False(t, result.Delete(v6Prefixes))
   126  	require.Equal(t, expectedPrefixLengths, result.v6)
   127  
   128  	// Delete them again (changed: true)
   129  	require.True(t, result.Delete(v6Prefixes))
   130  	require.Equal(t, IntCounter{}, result.v6)
   131  
   132  	// Our v4 prefixes should still be here, unchanged
   133  	expectedPrefixLengths = make(map[int]int, len(v4PrefixesLengths))
   134  	for k, v := range v4PrefixesLengths {
   135  		expectedPrefixLengths[k] += v
   136  	}
   137  	require.Equal(t, expectedPrefixLengths, result.v4)
   138  }
   139  
   140  func TestCheckLimits(t *testing.T) {
   141  	result := NewPrefixLengthCounter(4, 4)
   142  	require.Nil(t, checkLimits(0, 4, result.maxUniquePrefixes4))
   143  	require.NotNil(t, checkLimits(0, 5, result.maxUniquePrefixes4))
   144  	require.Nil(t, checkLimits(0, 4, result.maxUniquePrefixes6))
   145  	require.NotNil(t, checkLimits(0, 5, result.maxUniquePrefixes6))
   146  
   147  	prefixes := []netip.Prefix{
   148  		netip.MustParsePrefix("0.0.0.0/0"),
   149  		netip.MustParsePrefix("192.0.0.0/15"),
   150  		netip.MustParsePrefix("192.0.2.2/31"),
   151  		netip.MustParsePrefix("192.0.2.3/32"),
   152  	}
   153  	changed, err := result.Add(prefixes)
   154  	require.NoError(t, err)
   155  	require.True(t, changed)
   156  
   157  	changed, err = result.Add([]netip.Prefix{netip.MustParsePrefix("192.0.0.0/8")})
   158  	require.Error(t, err)
   159  	require.False(t, changed)
   160  }
   161  
   162  func TestToBPFData(t *testing.T) {
   163  	result := NewPrefixLengthCounter(42, 32)
   164  
   165  	prefixes := []string{
   166  		"192.0.2.0/24",
   167  		"192.0.2.0/32",
   168  		"192.0.64.0/20",
   169  	}
   170  	prefixesToAdd := []netip.Prefix{}
   171  	for _, prefix := range prefixes {
   172  		net := netip.MustParsePrefix(prefix)
   173  		prefixesToAdd = append(prefixesToAdd, net)
   174  	}
   175  
   176  	_, err := result.Add(prefixesToAdd)
   177  	require.NoError(t, err)
   178  
   179  	s6, s4 := result.ToBPFData()
   180  	require.Equal(t, []int{}, s6)
   181  	require.Equal(t, []int{32, 24, 20}, s4)
   182  }
   183  
   184  func TestDefaultPrefixLengthCounter(t *testing.T) {
   185  	result := DefaultPrefixLengthCounter()
   186  	require.Equal(t, 1, result.v4[0])
   187  	require.Equal(t, 1, result.v6[0])
   188  	require.Equal(t, 1, result.v4[net.IPv4len*8])
   189  	require.Equal(t, 1, result.v6[net.IPv6len*8])
   190  }