github.com/cilium/cilium@v1.16.2/pkg/maps/nat/per_cluster_nat_test.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package nat 5 6 import ( 7 "testing" 8 9 "github.com/cilium/ebpf/rlimit" 10 "github.com/stretchr/testify/require" 11 12 "github.com/cilium/cilium/pkg/bpf" 13 cmtypes "github.com/cilium/cilium/pkg/clustermesh/types" 14 "github.com/cilium/cilium/pkg/option" 15 "github.com/cilium/cilium/pkg/testutils" 16 ) 17 18 func setup(tb testing.TB) { 19 testutils.PrivilegedTest(tb) 20 21 bpf.CheckOrMountFS("") 22 require.NoError(tb, rlimit.RemoveMemlock(), "Failed to set memlock rlimit") 23 24 // Override the map names to avoid clashing with the real ones. 25 ClusterOuterMapNameTestOverride("test") 26 } 27 28 func path(tb testing.TB, m *bpf.Map) string { 29 path, err := m.Path() 30 require.NoError(tb, err, "Failed to retrieve map path") 31 return path 32 } 33 34 func TestPerClusterMaps(t *testing.T) { 35 setup(t) 36 37 maps := newPerClusterNATMaps(true, true, option.NATMapEntriesGlobalDefault) 38 require.NotNil(t, maps.v4Map, "Failed to initialize maps") 39 require.NotNil(t, maps.v6Map, "Failed to initialize maps") 40 41 require.NoError(t, maps.OpenOrCreate(), "Failed to create outer maps") 42 require.FileExists(t, path(t, maps.v4Map.Map), "Failed to create outer maps") 43 require.FileExists(t, path(t, maps.v6Map.Map), "Failed to create outer maps") 44 45 t.Cleanup(func() { 46 require.NoError(t, maps.Close()) 47 require.NoError(t, CleanupPerClusterNATMaps(true, true), "Failed to cleanup maps") 48 }) 49 50 // ClusterID 0 should never be used 51 require.Error(t, maps.CreateClusterNATMaps(0), "ClusterID 0 should never be used") 52 require.Error(t, maps.DeleteClusterNATMaps(0), "ClusterID 0 should never be used") 53 _, err := GetClusterNATMap(0, IPv4) 54 require.Error(t, err, "ClusterID 0 should never be used") 55 56 // ClusterID beyond the ClusterIDMax should never be used 57 require.Error(t, maps.CreateClusterNATMaps(cmtypes.ClusterIDMax+1), "ClusterID beyond the ClusterIDMax should never be used") 58 require.Error(t, maps.DeleteClusterNATMaps(cmtypes.ClusterIDMax+1), "ClusterID beyond the ClusterIDMax should never be used") 59 _, err = GetClusterNATMap(cmtypes.ClusterIDMax+1, IPv6) 60 require.Error(t, err, "ClusterID beyond the ClusterIDMax should never be used") 61 62 // Basic update 63 require.NoError(t, maps.CreateClusterNATMaps(1), "Failed to create maps") 64 require.NoError(t, maps.CreateClusterNATMaps(cmtypes.ClusterIDMax), "Failed to create maps") 65 66 for _, id := range []uint32{1, cmtypes.ClusterIDMax} { 67 for _, om := range []*perClusterNATMap{maps.v4Map, maps.v6Map} { 68 // After update, the outer map should be updated with the inner map 69 value, err := om.Lookup(&PerClusterNATMapKey{id}) 70 require.NoError(t, err, "Outer map not updated correctly (id=%v, family=%v)", id, om.family) 71 require.NotZero(t, value, "Outer map not updated correctly (id=%v, family=%v)", id, om.family) 72 73 // After update, the inner map should exist 74 require.FileExists(t, path(t, &om.newInnerMap(id).Map), "Inner map not correctly present (id=%v, family=%v)", id, om.family) 75 76 // After update, it should be possible to get and open the inner map 77 im, err := GetClusterNATMap(id, om.family) 78 require.NotNil(t, im, "Failed to get inner map (id=%v, family=%v)", id, om.family) 79 require.NoError(t, err, "Failed to get inner map (id=%v, family=%v)", id, om.family) 80 require.NoError(t, im.Open(), "Failed to open inner map (id=%v, family=%v)", id, om.family) 81 im.Close() 82 } 83 } 84 85 // An update for an already existing entry should succeed 86 require.NoError(t, maps.CreateClusterNATMaps(cmtypes.ClusterIDMax), "Failed to create maps") 87 88 // Basic delete 89 require.NoError(t, maps.DeleteClusterNATMaps(1), "Failed to delete maps") 90 require.NoError(t, maps.DeleteClusterNATMaps(cmtypes.ClusterIDMax), "Failed to delete maps") 91 92 for _, id := range []uint32{1, cmtypes.ClusterIDMax} { 93 for _, om := range []*perClusterNATMap{maps.v4Map, maps.v6Map} { 94 // After delete, the outer map shouldn't contain the entry 95 _, err := om.Lookup(&PerClusterNATMapKey{id}) 96 require.Error(t, err, "Outer map not updated correctly (id=%v, family=%v)", id, om.family) 97 98 // After delete, the inner map should not exist 99 require.NoFileExists(t, path(t, &om.newInnerMap(id).Map), "Inner map not correctly deleted (id=%v, family=%v)", id, om.family) 100 101 // After delete, it should be no longer be possible to open the inner map 102 im, err := GetClusterNATMap(id, om.family) 103 require.NotNil(t, im, "Failed to get inner map (id=%v, family=%v)", id, om.family) 104 require.NoError(t, err, "Failed to get inner map (id=%v, family=%v)", id, om.family) 105 require.Error(t, im.Open(), "Should have failed to open inner map (id=%v, family=%v)", id, om.family) 106 } 107 } 108 109 // A deletion for an already deleted entry should succeed 110 require.NoError(t, maps.DeleteClusterNATMaps(cmtypes.ClusterIDMax), "Failed to delete maps") 111 } 112 113 func TestPerClusterMapsCleanup(t *testing.T) { 114 setup(t) 115 116 tests := []struct { 117 name string 118 ipv4, ipv6 bool 119 }{ 120 {name: "IPv4", ipv4: true}, 121 {name: "IPv6", ipv6: true}, 122 {name: "dual", ipv4: true, ipv6: true}, 123 } 124 125 for _, tt := range tests { 126 t.Run(tt.name, func(t *testing.T) { 127 // Pick up edge and middle values since filling all slots consumes too much memory. 128 ids := []uint32{1, 128, cmtypes.ClusterIDMax} 129 maps := newPerClusterNATMaps(true, true, option.NATMapEntriesGlobalDefault) 130 131 require.NoError(t, maps.OpenOrCreate(), "Failed to create outer maps") 132 t.Cleanup(func() { 133 require.NoError(t, maps.Close()) 134 // This also ensures that the cleanup succeeds even if the outer maps don't exist 135 require.NoError(t, CleanupPerClusterNATMaps(true, true), "Failed to cleanup maps") 136 }) 137 138 for _, id := range ids { 139 require.NoError(t, maps.CreateClusterNATMaps(id), "Failed to create maps (id=%v)", id) 140 } 141 142 require.NoError(t, CleanupPerClusterNATMaps(tt.ipv4, tt.ipv6), "Failed to cleanup maps") 143 144 for _, om := range []*perClusterNATMap{maps.v4Map, maps.v6Map} { 145 must := require.FileExists 146 if om.family == IPv4 && tt.ipv4 || om.family == IPv6 && tt.ipv6 { 147 must = require.NoFileExists 148 } 149 150 for _, id := range ids { 151 must(t, path(t, &om.newInnerMap(id).Map), "Inner map not correctly deleted (id=%v, family=%v)", id, om.family) 152 } 153 154 must(t, path(t, om.Map), "Outer map not correctly deleted (family=%v)", om.family) 155 } 156 }) 157 } 158 }