github.com/cilium/cilium@v1.16.2/pkg/identity/cache/local_test.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package cache 5 6 import ( 7 "fmt" 8 "net/netip" 9 "testing" 10 11 "github.com/stretchr/testify/assert" 12 "github.com/stretchr/testify/require" 13 14 "github.com/cilium/cilium/pkg/identity" 15 "github.com/cilium/cilium/pkg/labels" 16 "github.com/cilium/cilium/pkg/testutils" 17 ) 18 19 func TestBumpNextNumericIdentity(t *testing.T) { 20 testutils.IntegrationTest(t) 21 22 minID, maxID := identity.NumericIdentity(1), identity.NumericIdentity(5) 23 scope := identity.NumericIdentity(0x42_00_00_00) 24 cache := newLocalIdentityCache(scope, minID, maxID, nil) 25 26 for i := minID; i <= maxID; i++ { 27 require.Equal(t, i, cache.nextNumericIdentity) 28 cache.bumpNextNumericIdentity() 29 } 30 31 // ID must have overflowed and must be back to minID 32 require.Equal(t, minID, cache.nextNumericIdentity) 33 } 34 35 func TestLocalIdentityCache(t *testing.T) { 36 testutils.IntegrationTest(t) 37 38 minID, maxID := identity.NumericIdentity(1), identity.NumericIdentity(5) 39 scope := identity.NumericIdentity(0x42_00_00_00) 40 cache := newLocalIdentityCache(scope, minID, maxID, nil) 41 42 identities := map[identity.NumericIdentity]*identity.Identity{} 43 44 // allocate identities for all available numeric identities with a 45 // unique label 46 for i := minID; i <= maxID; i++ { 47 id, isNew, err := cache.lookupOrCreate(labels.NewLabelsFromModel([]string{fmt.Sprintf("%d", i)}), identity.InvalidIdentity, false) 48 require.Nil(t, err) 49 require.Equal(t, true, isNew) 50 require.Equal(t, scope+i, id.ID) 51 identities[id.ID] = id 52 } 53 54 // allocate the same labels again. This must be successful and the same 55 // identities must be returned. 56 for i := minID; i <= maxID; i++ { 57 id, isNew, err := cache.lookupOrCreate(labels.NewLabelsFromModel([]string{fmt.Sprintf("%d", i)}), identity.InvalidIdentity, false) 58 require.Equal(t, false, isNew) 59 require.Nil(t, err) 60 61 // The returned identity must be identical 62 require.EqualValues(t, identities[id.ID], id) 63 } 64 65 // Allocation must fail as we are out of IDs 66 _, _, err := cache.lookupOrCreate(labels.NewLabelsFromModel([]string{"foo"}), identity.InvalidIdentity, false) 67 require.NotNil(t, err) 68 69 // release all identities, this must decrement the reference count but not release the identities yet 70 for _, id := range identities { 71 require.Equal(t, false, cache.release(id, false)) 72 } 73 74 // lookup must still be successful 75 for i := minID; i <= maxID; i++ { 76 require.NotNil(t, cache.lookup(labels.NewLabelsFromModel([]string{fmt.Sprintf("%d", i)}))) 77 require.NotNil(t, cache.lookupByID(i|scope)) 78 } 79 80 // release the identities a second time, this must cause the identity 81 // to be forgotten 82 for _, id := range identities { 83 require.Equal(t, true, cache.release(id, false)) 84 } 85 86 // allocate all identities again 87 for i := minID; i <= maxID; i++ { 88 id, isNew, err := cache.lookupOrCreate(labels.NewLabelsFromModel([]string{fmt.Sprintf("%d", i)}), identity.InvalidIdentity, false) 89 require.Nil(t, err) 90 require.Equal(t, true, isNew) 91 identities[id.ID] = id 92 } 93 94 // release a random identity in the middle 95 randomID := identity.NumericIdentity(3) | scope 96 require.Equal(t, true, cache.release(identities[randomID], false)) 97 98 id, isNew, err := cache.lookupOrCreate(labels.NewLabelsFromModel([]string{"foo"}), identity.InvalidIdentity, false) 99 require.Nil(t, err) 100 require.Equal(t, true, isNew) 101 // the selected numeric identity must be the one released before 102 require.Equal(t, randomID, id.ID) 103 } 104 105 func TestOldNID(t *testing.T) { 106 minID, maxID := identity.NumericIdentity(1), identity.NumericIdentity(10) 107 scope := identity.NumericIdentity(0x42_00_00_00) 108 c := newLocalIdentityCache(scope, minID, maxID, nil) 109 110 // Request identity, it should work 111 l := labels.GetCIDRLabels(netip.MustParsePrefix("1.1.1.1/32")) 112 id, _, _ := c.lookupOrCreate(l, scope, false) 113 assert.NotNil(t, id) 114 assert.EqualValues(t, scope, id.ID) 115 116 // Re-request identity, it should not 117 l = labels.GetCIDRLabels(netip.MustParsePrefix("1.1.1.2/32")) 118 id, _, _ = c.lookupOrCreate(l, scope, false) 119 assert.NotNil(t, id) 120 assert.EqualValues(t, scope+1, id.ID) 121 122 // Withhold the next identity, it should be skipped 123 c.withhold([]identity.NumericIdentity{scope + 2}) 124 125 l = labels.GetCIDRLabels(netip.MustParsePrefix("1.1.1.3/32")) 126 id, _, _ = c.lookupOrCreate(l, 0, false) 127 assert.NotNil(t, id) 128 assert.EqualValues(t, scope+3, id.ID) 129 130 // Request a withheld identity, it should succeed 131 l = labels.GetCIDRLabels(netip.MustParsePrefix("1.1.1.4/32")) 132 id2, _, _ := c.lookupOrCreate(l, scope+2, false) 133 assert.NotNil(t, id2) 134 assert.EqualValues(t, scope+2, id2.ID) 135 136 // Request a withheld and allocated identity, it should be ignored 137 l = labels.GetCIDRLabels(netip.MustParsePrefix("1.1.1.5/32")) 138 id, _, _ = c.lookupOrCreate(l, scope+2, false) 139 assert.NotNil(t, id) 140 assert.EqualValues(t, scope+4, id.ID) 141 142 // Unwithhold and release an identity, requesting should now succeed 143 c.unwithhold([]identity.NumericIdentity{scope + 2}) 144 c.release(id2, false) 145 l = labels.GetCIDRLabels(netip.MustParsePrefix("1.1.1.6/32")) 146 id, _, _ = c.lookupOrCreate(l, scope+2, false) 147 assert.NotNil(t, id) 148 assert.EqualValues(t, scope+2, id.ID) 149 150 // Request an identity out of scope, it should not be honored 151 l = labels.GetCIDRLabels(netip.MustParsePrefix("1.1.1.7/32")) 152 id, _, _ = c.lookupOrCreate(l, scope-2, false) 153 assert.NotNil(t, id) 154 assert.EqualValues(t, scope+5, id.ID) 155 156 // Withhold all identities; allocator should fall back to a (random) withheld identity 157 c.withhold([]identity.NumericIdentity{scope + 6, scope + 7, scope + 8, scope + 9, scope + 10}) 158 159 l = labels.GetCIDRLabels(netip.MustParsePrefix("1.1.1.8/32")) 160 id, _, _ = c.lookupOrCreate(l, scope-2, false) 161 assert.NotNil(t, id) 162 // actual value is random, just need it to succeed 163 assert.True(t, id.ID >= scope+6 && id.ID <= scope+10, "%d <= %d <= %d", scope+6, id.ID, scope+10) 164 }