github.com/imran-kn/cilium-fork@v1.6.9/pkg/bpf/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 bpf 16 17 import ( 18 "bufio" 19 "bytes" 20 "fmt" 21 "os" 22 "regexp" 23 "time" 24 25 "github.com/cilium/cilium/pkg/controller" 26 "github.com/cilium/cilium/pkg/logging/logfields" 27 28 "github.com/sirupsen/logrus" 29 ) 30 31 // MapType is an enumeration for valid BPF map types 32 type MapType int 33 34 // This enumeration must be in sync with enum bpf_prog_type in <linux/bpf.h> 35 const ( 36 MapTypeUnspec MapType = iota 37 MapTypeHash 38 MapTypeArray 39 MapTypeProgArray 40 MapTypePerfEventArray 41 MapTypePerCPUHash 42 MapTypePerCPUArray 43 MapTypeStackTrace 44 MapTypeCgroupArray 45 MapTypeLRUHash 46 MapTypeLRUPerCPUHash 47 MapTypeLPMTrie 48 MapTypeArrayOfMaps 49 MapTypeHashOfMaps 50 MapTypeDevMap 51 MapTypeSockMap 52 MapTypeCPUMap 53 MapTypeXSKMap 54 MapTypeSockHash 55 // MapTypeMaximum is the maximum supported known map type. 56 MapTypeMaximum 57 58 // maxSyncErrors is the maximum consecutive errors syncing before the 59 // controller bails out 60 maxSyncErrors = 512 61 62 // errorResolverSchedulerMinInterval is the minimum interval for the 63 // error resolver to be scheduled. This minimum interval ensures not to 64 // overschedule if a large number of updates fail in a row. 65 errorResolverSchedulerMinInterval = 5 * time.Second 66 67 // errorResolverSchedulerDelay is the delay to update the controller 68 // after determination that a run is needed. The delay allows to 69 // schedule the resolver after series of updates have failed. 70 errorResolverSchedulerDelay = 200 * time.Millisecond 71 ) 72 73 var ( 74 mapControllers = controller.NewManager() 75 76 // supportedMapTypes maps from a MapType to a bool indicating whether 77 // the currently running kernel supports the map type. 78 supportedMapTypes = make(map[MapType]bool) 79 ) 80 81 func (t MapType) String() string { 82 switch t { 83 case MapTypeHash: 84 return "Hash" 85 case MapTypeArray: 86 return "Array" 87 case MapTypeProgArray: 88 return "Program array" 89 case MapTypePerfEventArray: 90 return "Event array" 91 case MapTypePerCPUHash: 92 return "Per-CPU hash" 93 case MapTypePerCPUArray: 94 return "Per-CPU array" 95 case MapTypeStackTrace: 96 return "Stack trace" 97 case MapTypeCgroupArray: 98 return "Cgroup array" 99 case MapTypeLRUHash: 100 return "LRU hash" 101 case MapTypeLRUPerCPUHash: 102 return "LRU per-CPU hash" 103 case MapTypeLPMTrie: 104 return "Longest prefix match trie" 105 case MapTypeArrayOfMaps: 106 return "Array of maps" 107 case MapTypeHashOfMaps: 108 return "Hash of maps" 109 case MapTypeDevMap: 110 return "Device Map" 111 case MapTypeSockMap: 112 return "Socket Map" 113 case MapTypeCPUMap: 114 return "CPU Redirect Map" 115 case MapTypeSockHash: 116 return "Socket Hash" 117 } 118 119 return "Unknown" 120 } 121 122 func (t MapType) allowsPreallocation() bool { 123 return t != MapTypeLPMTrie 124 } 125 126 func (t MapType) requiresPreallocation() bool { 127 switch t { 128 case MapTypeHash, MapTypePerCPUHash, MapTypeLPMTrie, MapTypeHashOfMaps: 129 return false 130 } 131 return true 132 } 133 134 // DesiredAction is the action to be performed on the BPF map 135 type DesiredAction int 136 137 const ( 138 // OK indicates that to further action is required and the entry is in 139 // sync 140 OK DesiredAction = iota 141 142 // Insert indicates that the entry needs to be created or updated 143 Insert 144 145 // Delete indicates that the entry needs to be deleted 146 Delete 147 ) 148 149 func (d DesiredAction) String() string { 150 switch d { 151 case OK: 152 return "sync" 153 case Insert: 154 return "to-be-inserted" 155 case Delete: 156 return "to-be-deleted" 157 default: 158 return "unknown" 159 } 160 } 161 162 // mapTypeToFeatureString maps a MapType into a string defined by run_probes.sh 163 func mapTypeToFeatureString(mt MapType) string { 164 var featureString string 165 switch mt { 166 case MapTypeLPMTrie: 167 featureString = fmt.Sprintf("#define HAVE_LPM_MAP_TYPE") 168 case MapTypeLRUHash: 169 featureString = fmt.Sprintf("#define HAVE_LRU_MAP_TYPE") 170 default: 171 break 172 } 173 return featureString 174 } 175 176 // ReadFeatureProbes reads the bpf_features.h file at the specified path (as 177 // generated by bpf/run_probes.sh), and stores the results of the kernel 178 // feature probing. 179 func ReadFeatureProbes(filename string) { 180 f, err := os.Open(filename) 181 if err != nil { 182 // Should not happen; the caller ensured that the file exists 183 log.WithFields(logrus.Fields{ 184 logfields.Path: filename, 185 }).WithError(err).Fatal("Failed to read feature probes") 186 } 187 defer f.Close() 188 scanner := bufio.NewScanner(f) 189 for scanner.Scan() { 190 for mapType := MapTypeHash; mapType < MapTypeMaximum; mapType++ { 191 featureString := mapTypeToFeatureString(mapType) 192 if featureString != "" && 193 bytes.Equal(scanner.Bytes(), []byte(featureString)) { 194 log.Debugf("Detected support for map type %s", mapType.String()) 195 supportedMapTypes[mapType] = true 196 } 197 } 198 } 199 200 for mapType := MapTypeHash; mapType < MapTypeMaximum; mapType++ { 201 if mapTypeToFeatureString(mapType) == "" { 202 log.Debugf("Skipping support detection for map type %s", mapType.String()) 203 } else if _, probed := supportedMapTypes[mapType]; !probed { 204 log.Debugf("Detected no support for map type %s", mapType.String()) 205 supportedMapTypes[mapType] = false 206 } 207 } 208 } 209 210 // GetMapType determines whether the specified map type is supported by the 211 // kernel (as determined by ReadFeatureProbes()), and if the map type is not 212 // supported, returns a more primitive map type that may be used to implement 213 // the map on older implementations. Otherwise, returns the specified map type. 214 func GetMapType(t MapType) MapType { 215 switch t { 216 case MapTypeLPMTrie: 217 fallthrough 218 case MapTypeLRUHash: 219 if !supportedMapTypes[t] { 220 return MapTypeHash 221 } 222 } 223 return t 224 } 225 226 var commonNameRegexps = []*regexp.Regexp{ 227 regexp.MustCompile(`^(cilium_)(.+)_reserved_[0-9]+$`), 228 regexp.MustCompile(`^(cilium_)(.+)_netdev_ns_[0-9]+$`), 229 regexp.MustCompile(`^(cilium_)(.+)_overlay_[0-9]+$`), 230 regexp.MustCompile(`^(cilium_)(.+)_[0-9]+$`), 231 regexp.MustCompile(`^(cilium_)(.+)+$`), 232 } 233 234 func extractCommonName(name string) string { 235 for _, r := range commonNameRegexps { 236 if replaced := r.ReplaceAllString(name, `$2`); replaced != name { 237 return replaced 238 } 239 } 240 241 return name 242 }