github.com/looshlee/beatles@v0.0.0-20220727174639-742810ab631c/pkg/maps/configmap/configmap.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 configmap 16 17 import ( 18 "bytes" 19 "fmt" 20 "unsafe" 21 22 "github.com/cilium/cilium/common/types" 23 "github.com/cilium/cilium/pkg/bpf" 24 "github.com/cilium/cilium/pkg/logging" 25 "github.com/cilium/cilium/pkg/logging/logfields" 26 "github.com/cilium/cilium/pkg/maps/lxcmap" 27 ) 28 29 var log = logging.DefaultLogger.WithField(logfields.LogSubsys, "map-config") 30 31 const ( 32 // MapNamePrefix is the basename prefix of endpoint config maps. 33 MapNamePrefix = "cilium_ep_config_" 34 35 // MaxEntries represents the maximum number of elements in the map 36 MaxEntries = 1 37 38 // SkipPolicyIngress causes ingress policy to be skipped. 39 SkipPolicyIngress = 1 << 0 40 // SkipPolicyEgress causes ingress policy to be skipped. 41 SkipPolicyEgress = 1 << 1 42 ) 43 44 var ( 45 flagsToString = map[int]string{ 46 SkipPolicyIngress: "SKIP_POLICY_INGRESS", 47 SkipPolicyEgress: "SKIP_POLICY_EGRESS", 48 } 49 50 binMap = map[uint]string{ 51 0: "POLICY_INGRESS", 52 1: "POLICY_EGRESS", 53 } 54 ) 55 56 // Flags is a set of endpoint configuration flags interpreted by BPF code. 57 // 58 // Must be in sync with the enum ep_cfg_flag in <bpf/lib/eps.h> 59 type Flags uint32 60 61 // String converts the specified flags into a human-readable form. 62 func (f Flags) String() string { 63 var buffer bytes.Buffer 64 for i := uint(0); i < 32; i++ { 65 bitVal := int(f & (1 << i)) 66 if bitVal > 0 { 67 if flag, ok := flagsToString[bitVal]; ok { 68 buffer.WriteString(flag) 69 buffer.WriteString(",") 70 continue 71 } 72 } else if bitVal == 0 { 73 if flag, ok := binMap[i]; ok { 74 buffer.WriteString(flag) 75 buffer.WriteString(",") 76 continue 77 } 78 } 79 buffer.WriteString(fmt.Sprintf("%04x,", 1<<i)) 80 } 81 82 return buffer.String() 83 } 84 85 // Key is the key used to index into the config map for an endpoint. 86 // 87 // Must be in sync with the key of CONFIG_MAP in <bpf/lib/maps.h> 88 // +k8s:deepcopy-gen=true 89 // +k8s:deepcopy-gen:interfaces=github.com/cilium/cilium/pkg/bpf.MapKey 90 type Key struct { 91 Bits uint32 92 } 93 94 func (k Key) String() string { 95 return fmt.Sprintf("%d", k.Bits) 96 } 97 98 // GetKeyPtr returns the unsafe pointer to the BPF key 99 func (k *Key) GetKeyPtr() unsafe.Pointer { return unsafe.Pointer(k) } 100 101 // NewValue returns a new empty instance of the structure representing the BPF 102 // map value 103 func (k *Key) NewValue() bpf.MapValue { return &EndpointConfig{} } 104 105 func (cfg *EndpointConfig) String() string { 106 // TODO - use a tabwriter for CLI consistency? 107 return fmt.Sprintf("%s, %d, %d, %s, %s, %d, %d, %s", cfg.Flags.String(), cfg.SecurityIdentity, cfg.SecurityIdentityNB, cfg.IPv4.String(), cfg.IPv6.String(), cfg.LXCID, cfg.LXCIDNB, cfg.NodeMAC.String()) 108 } 109 110 // EndpointConfig represents the value of the endpoint's BPF map. 111 // 112 // Must be in sync with struct ep_config in <bpf/lib/common.h> 113 // +k8s:deepcopy-gen=true 114 // +k8s:deepcopy-gen:interfaces=github.com/cilium/cilium/pkg/bpf.MapValue 115 type EndpointConfig struct { 116 Flags Flags `align:"flags"` 117 // NOTE: everything below this comment is not plumbed yet. This will be done 118 // through future work. See GH-6273. 119 IPv4 types.IPv4 `align:"ipv4Addr"` 120 IPv6 types.IPv6 `align:"ipv6Addr"` 121 // TODO: put lxcmap.MAC into its own pkg? 122 NodeMAC lxcmap.MAC `align:"node_mac"` 123 LXCID uint16 `align:"lxc_id"` 124 LXCIDNB uint16 `align:"lxc_id_nb"` 125 SecurityIdentity uint32 `align:"identity"` 126 SecurityIdentityNB uint32 `align:"identity_nb"` 127 Pad uint32 `align:"pad"` 128 } 129 130 // GetValuePtr returns the unsafe pointer to the BPF value 131 func (cfg *EndpointConfig) GetValuePtr() unsafe.Pointer { return unsafe.Pointer(cfg) } 132 133 // endpoint provides access to the properties of an endpoint that are relevant 134 // for configuring the BPF program for the endpoint. 135 type endpoint interface { 136 GetIngressPolicyEnabledLocked() bool 137 GetEgressPolicyEnabledLocked() bool 138 } 139 140 // EndpointConfigMap is a map type for interfacing with endpoint BPF config. 141 type EndpointConfigMap struct { 142 *bpf.Map 143 path string 144 Fd int 145 } 146 147 // GetConfig creates a EndpointConfig structure using the endpoint's 148 // configuration. The endpoint parameter should have its mutex held. 149 func GetConfig(e endpoint) *EndpointConfig { 150 value := EndpointConfig{} 151 if !e.GetIngressPolicyEnabledLocked() { 152 value.Flags |= SkipPolicyIngress 153 } 154 if !e.GetEgressPolicyEnabledLocked() { 155 value.Flags |= SkipPolicyEgress 156 } 157 158 return &value 159 } 160 161 // Update pushes the configuration options from the specified endpoint into the 162 // configuration map. 163 func (m *EndpointConfigMap) Update(value *EndpointConfig) error { 164 configKey := &Key{Bits: 0} 165 return m.Map.Update(configKey, value) 166 } 167 168 // OpenMapWithName attempts to open or create a BPF config map at the specified 169 // path with the specified name. 170 // On success, it returns a map and whether the map was newly created, or 171 // otherwise an error. 172 func OpenMapWithName(path string) (*EndpointConfigMap, bool, error) { 173 174 newMap := bpf.NewMap(path, 175 bpf.BPF_MAP_TYPE_ARRAY, 176 &Key{}, 177 int(unsafe.Sizeof(uint32(0))), 178 &EndpointConfig{}, 179 int(unsafe.Sizeof(EndpointConfig{})), 180 MaxEntries, 181 0, 182 0, 183 bpf.ConvertKeyValue, 184 ).WithCache() 185 186 isNewMap, err := newMap.OpenOrCreate() 187 188 if err != nil { 189 return nil, false, err 190 } 191 192 m := &EndpointConfigMap{Map: newMap, path: path, Fd: newMap.GetFd()} 193 194 return m, isNewMap, nil 195 }