github.com/imran-kn/cilium-fork@v1.6.9/pkg/policy/mapstate.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 policy 16 17 import ( 18 "github.com/cilium/cilium/pkg/identity" 19 "github.com/cilium/cilium/pkg/lock" 20 "github.com/cilium/cilium/pkg/logging/logfields" 21 "github.com/cilium/cilium/pkg/option" 22 "github.com/cilium/cilium/pkg/policy/trafficdirection" 23 24 "github.com/sirupsen/logrus" 25 ) 26 27 var ( 28 // localHostKey represents an ingress L3 allow from the local host. 29 localHostKey = Key{ 30 Identity: identity.ReservedIdentityHost.Uint32(), 31 TrafficDirection: trafficdirection.Ingress.Uint8(), 32 } 33 ) 34 35 // MapState is a state of a policy map. 36 type MapState map[Key]MapStateEntry 37 38 // Key is the userspace representation of a policy key in BPF. It is 39 // intentionally duplicated from pkg/maps/policymap to avoid pulling in the 40 // BPF dependency to this package. 41 type Key struct { 42 // Identity is the numeric identity to / from which traffic is allowed. 43 Identity uint32 44 // DestPort is the port at L4 to / from which traffic is allowed, in 45 // host-byte order. 46 DestPort uint16 47 // NextHdr is the protocol which is allowed. 48 Nexthdr uint8 49 // TrafficDirection indicates in which direction Identity is allowed 50 // communication (egress or ingress). 51 TrafficDirection uint8 52 } 53 54 // IsIngress returns true if the key refers to an ingress policy key 55 func (k Key) IsIngress() bool { 56 return k.TrafficDirection == trafficdirection.Ingress.Uint8() 57 } 58 59 // IsEgress returns true if the key refers to an egress policy key 60 func (k Key) IsEgress() bool { 61 return k.TrafficDirection == trafficdirection.Egress.Uint8() 62 } 63 64 // MapStateEntry is the configuration associated with a Key in a 65 // MapState. This is a minimized version of policymap.PolicyEntry. 66 type MapStateEntry struct { 67 // The proxy port, in host byte order. 68 // If 0 (default), there is no proxy redirection for the corresponding 69 // Key. 70 ProxyPort uint16 71 } 72 73 // DetermineAllowLocalhostIngress determines whether communication should be allowed 74 // from the localhost. It inserts the Key corresponding to the localhost in 75 // the desiredPolicyKeys if the localhost is allowed to communicate with the 76 // endpoint. 77 func (keys MapState) DetermineAllowLocalhostIngress(l4Policy *L4Policy) { 78 79 if option.Config.AlwaysAllowLocalhost() || (l4Policy != nil && l4Policy.HasRedirect()) { 80 keys[localHostKey] = MapStateEntry{} 81 } 82 } 83 84 // AllowAllIdentities translates all identities in selectorCache to their 85 // corresponding Keys in the specified direction (ingress, egress) which allows 86 // all at L3. 87 func (keys MapState) AllowAllIdentities(ingress, egress bool) { 88 if ingress { 89 keyToAdd := Key{ 90 Identity: 0, 91 DestPort: 0, 92 Nexthdr: 0, 93 TrafficDirection: trafficdirection.Ingress.Uint8(), 94 } 95 keys[keyToAdd] = MapStateEntry{} 96 } 97 if egress { 98 keyToAdd := Key{ 99 Identity: 0, 100 DestPort: 0, 101 Nexthdr: 0, 102 TrafficDirection: trafficdirection.Egress.Uint8(), 103 } 104 keys[keyToAdd] = MapStateEntry{} 105 } 106 } 107 108 // MapChanges collects updates to the endpoint policy on the 109 // granularity of individual mapstate key-value pairs for both adds 110 // and deletes. 'mutex' must be held for any access. 111 type MapChanges struct { 112 mutex lock.Mutex 113 adds MapState 114 deletes MapState 115 } 116 117 // AccumulateMapChanges accumulates the given changes to the 118 // MapChanges, updating both maps for each add and delete, as 119 // applicable. 120 // 121 // The caller is responsible for making sure the same identity is not 122 // present in both 'adds' and 'deletes'. Accross multiple calls we 123 // maintain the adds and deletes within the MapChanges are disjoint in 124 // cases where an identity is first added and then deleted, or first 125 // deleted and then added. 126 func (mc *MapChanges) AccumulateMapChanges(adds, deletes []identity.NumericIdentity, 127 port uint16, proto uint8, direction trafficdirection.TrafficDirection) { 128 key := Key{ 129 // The actual identity is set in the loops below 130 Identity: 0, 131 // NOTE: Port is in host byte-order! 132 DestPort: port, 133 Nexthdr: proto, 134 TrafficDirection: direction.Uint8(), 135 } 136 value := MapStateEntry{ 137 ProxyPort: 0, // Will be updated by the caller when applicable 138 } 139 140 if option.Config.Debug { 141 log.WithFields(logrus.Fields{ 142 logfields.AddedPolicyID: adds, 143 logfields.DeletedPolicyID: deletes, 144 logfields.Port: port, 145 logfields.Protocol: proto, 146 logfields.TrafficDirection: direction, 147 }).Debug("AccumulateMapChanges") 148 } 149 150 mc.mutex.Lock() 151 if len(adds) > 0 { 152 if mc.adds == nil { 153 mc.adds = make(MapState) 154 } 155 for _, id := range adds { 156 key.Identity = id.Uint32() 157 mc.adds[key] = value 158 // Remove a potential previously deleted key 159 if mc.deletes != nil { 160 delete(mc.deletes, key) 161 } 162 } 163 } 164 if len(deletes) > 0 { 165 if mc.deletes == nil { 166 mc.deletes = make(MapState) 167 } 168 for _, id := range deletes { 169 key.Identity = id.Uint32() 170 mc.deletes[key] = value 171 // Remove a potential previously added key 172 if mc.adds != nil { 173 delete(mc.adds, key) 174 } 175 } 176 } 177 mc.mutex.Unlock() 178 } 179 180 // ConsumeMapChanges transfers the changes from MapChanges to the caller. 181 // May return nil maps. 182 func (mc *MapChanges) ConsumeMapChanges() (adds, deletes MapState) { 183 mc.mutex.Lock() 184 adds = mc.adds 185 mc.adds = nil 186 deletes = mc.deletes 187 mc.deletes = nil 188 mc.mutex.Unlock() 189 return adds, deletes 190 }