github.com/elfadel/cilium@v1.6.12/pkg/datapath/maps/map.go (about) 1 // Copyright 2016-2019 Authors of Cilium 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package maps 16 17 import ( 18 "os" 19 "path" 20 "path/filepath" 21 "strconv" 22 "strings" 23 24 "github.com/cilium/cilium/pkg/bpf" 25 "github.com/cilium/cilium/pkg/datapath/loader" 26 "github.com/cilium/cilium/pkg/endpoint" 27 "github.com/cilium/cilium/pkg/endpointmanager" 28 "github.com/cilium/cilium/pkg/logging" 29 "github.com/cilium/cilium/pkg/logging/logfields" 30 bpfconfig "github.com/cilium/cilium/pkg/maps/configmap" 31 "github.com/cilium/cilium/pkg/maps/ctmap" 32 "github.com/cilium/cilium/pkg/maps/policymap" 33 "github.com/cilium/cilium/pkg/option" 34 ) 35 36 var ( 37 log = logging.DefaultLogger.WithField(logfields.LogSubsys, "datapath-maps") 38 39 globalSweeper = newMapSweeper(&realEPManager{}) 40 ) 41 42 // endpointManager checks against its list of the current endpoints to determine 43 // whether map paths should be removed, and implements map removal. 44 // 45 // This interface is provided to abstract epmanager/filesystem access for unit 46 // testing. 47 type endpointManager interface { 48 endpointExists(endpointID uint16) bool 49 removeDatapathMapping(endpointID uint16) error 50 removeMapPath(path string) 51 } 52 53 // realEPManager provides an implementation of endpointManager that is backed 54 // by the endpointmanager and policymap packages, and when removeMapPath is 55 // invoked, it cleans up paths on the actual filesystem. 56 type realEPManager struct{} 57 58 func (gw *realEPManager) endpointExists(endpointID uint16) bool { 59 if ep := endpointmanager.LookupCiliumID(endpointID); ep != nil { 60 return true 61 } 62 return false 63 } 64 65 // removeDatapathMapping unlinks the endpointID from the global policy map, preventing 66 // packets that arrive on this node from being forwarded to the endpoint that 67 // used to exist with the specified ID. 68 func (gw *realEPManager) removeDatapathMapping(endpointID uint16) error { 69 return policymap.RemoveGlobalMapping(uint32(endpointID)) 70 } 71 72 // removeMapPath removes the specified path from the filesystem. 73 func (gw *realEPManager) removeMapPath(path string) { 74 if err := os.RemoveAll(path); err != nil { 75 log.WithError(err).WithField(logfields.Path, path).Warn("Error while deleting stale map file") 76 } else { 77 log.WithField(logfields.Path, path).Info("Removed stale bpf map") 78 } 79 } 80 81 // mapSweeper is responsible for checking stale map paths on the filesystem 82 // and garbage collecting the endpoint if the corresponding endpoint no longer 83 // exists. 84 type mapSweeper struct { 85 endpointManager 86 } 87 88 // newMapSweeper creates an object that walks map paths and garbage-collects 89 // them. 90 func newMapSweeper(g endpointManager) *mapSweeper { 91 return &mapSweeper{ 92 endpointManager: g, 93 } 94 } 95 96 // deleteMapIfStale uses the endpointManager implementation to determine for 97 // the given path whether it should be deleted, and if so deletes the path. 98 func (ms *mapSweeper) deleteMapIfStale(path string, filename string, endpointID string) { 99 if tmp, err := strconv.ParseUint(endpointID, 10, 16); err == nil { 100 epID := uint16(tmp) 101 if ms.endpointExists(epID) { 102 prefix := strings.TrimSuffix(filename, endpointID) 103 if filename != bpf.LocalMapName(prefix, epID) { 104 ms.removeMapPath(path) 105 } 106 } else { 107 err2 := ms.removeDatapathMapping(epID) 108 if err2 != nil { 109 log.WithError(err2).Debugf("Failed to remove ID %d from global policy map", tmp) 110 } 111 ms.removeMapPath(path) 112 } 113 } 114 } 115 116 func (ms *mapSweeper) checkStaleGlobalMap(path string, filename string) { 117 globalCTinUse := endpointmanager.HasGlobalCT() || option.Config.EnableNodePort || 118 !option.Config.InstallIptRules && option.Config.Masquerade 119 120 if !globalCTinUse && ctmap.NameIsGlobal(filename) { 121 ms.removeMapPath(path) 122 } 123 } 124 125 func (ms *mapSweeper) walk(path string, _ os.FileInfo, _ error) error { 126 filename := filepath.Base(path) 127 128 mapPrefix := []string{ 129 policymap.MapName, 130 ctmap.MapNameTCP6, 131 ctmap.MapNameTCP4, 132 ctmap.MapNameAny6, 133 ctmap.MapNameAny4, 134 loader.CallsMapName, 135 bpfconfig.MapNamePrefix, 136 endpoint.IpvlanMapName, 137 } 138 139 ms.checkStaleGlobalMap(path, filename) 140 141 for _, m := range mapPrefix { 142 if strings.HasPrefix(filename, m) { 143 if endpointID := strings.TrimPrefix(filename, m); endpointID != filename { 144 ms.deleteMapIfStale(path, filename, endpointID) 145 } 146 } 147 } 148 149 return nil 150 } 151 152 // CollectStaleMapGarbage cleans up stale content in the BPF maps from the 153 // datapath. 154 func CollectStaleMapGarbage() { 155 if err := filepath.Walk(bpf.MapPrefixPath(), globalSweeper.walk); err != nil { 156 log.WithError(err).Warn("Error while scanning for stale maps") 157 } 158 } 159 160 // RemoveDisabledMaps removes BPF maps in the filesystem for features that have 161 // been disabled. The maps may still be in use in which case they will continue 162 // to live until the BPF program using them is being replaced. 163 func RemoveDisabledMaps() { 164 maps := []string{} 165 166 if !option.Config.EnableIPv6 { 167 maps = append(maps, []string{ 168 "cilium_ct6_global", 169 "cilium_ct_any6_global", 170 "cilium_lb6_reverse_nat", 171 "cilium_lb6_rr_seq", 172 "cilium_lb6_services", 173 "cilium_lb6_services_v2", 174 "cilium_lb6_rr_seq_v2", 175 "cilium_lb6_backends", 176 "cilium_lb6_reverse_sk", 177 "cilium_snat_v6_external", 178 "cilium_proxy6"}...) 179 } 180 181 if !option.Config.EnableIPv4 { 182 maps = append(maps, []string{ 183 "cilium_ct4_global", 184 "cilium_ct_any4_global", 185 "cilium_lb4_reverse_nat", 186 "cilium_lb4_rr_seq", 187 "cilium_lb4_services", 188 "cilium_lb4_services_v2", 189 "cilium_lb4_rr_seq_v2", 190 "cilium_lb4_backends", 191 "cilium_lb4_reverse_sk", 192 "cilium_snat_v4_external", 193 "cilium_proxy4"}...) 194 } 195 196 for _, m := range maps { 197 p := path.Join(bpf.MapPrefixPath(), m) 198 if _, err := os.Stat(p); !os.IsNotExist(err) { 199 globalSweeper.removeMapPath(p) 200 } 201 } 202 }