github.com/cilium/cilium@v1.16.2/pkg/policy/types/types.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Hubble 3 4 package types 5 6 import ( 7 "math/bits" 8 "strconv" 9 10 "github.com/cilium/cilium/pkg/policy/trafficdirection" 11 ) 12 13 // MapStatePrefixLen is the length, in bits, of the Key when converted 14 // to binary minus the sizeof the identity field (which is not indexed). 15 const MapStatePrefixLen = uint(32) 16 17 // Key is the userspace representation of a policy key in BPF. It is 18 // intentionally duplicated from pkg/maps/policymap to avoid pulling in the 19 // BPF dependency to this package. 20 type Key struct { 21 // Identity is the numeric identity to / from which traffic is allowed. 22 Identity uint32 23 // DestPort is the port at L4 to / from which traffic is allowed, in 24 // host-byte order. 25 DestPort uint16 26 // InvertedPortMask is the mask that should be applied to the DestPort to 27 // define a range of ports for the policy-key, encoded as the bitwise inverse 28 // of its true/useful value. This is done so that the default value of the 29 // Key is a full port mask (that is, "0" represents 0xffff), as that is 30 // the most likely value to be used. InvertedPortMask is also, conveniently, 31 // the number or ports on top of DestPort that define that range. That is 32 // the end port is equal to the DestPort added to the InvertedPortMask. 33 // 34 // It is **not** the prefix that is applied for the BPF key entries. 35 // That value is calculated in the maps/policymap package. 36 // 37 // For example: 38 // range 2-3 would be DestPort:2 and InvertedPortMask:0x1 (i.e 0xfffe) 39 // range 32768-49151 would be DestPort:32768 and InvertedPortMask:0x3fff (i.e. 0xc000) 40 InvertedPortMask uint16 41 // NextHdr is the protocol which is allowed. 42 Nexthdr uint8 43 // TrafficDirection indicates in which direction Identity is allowed 44 // communication (egress or ingress). 45 TrafficDirection uint8 46 } 47 48 // PortMask returns the bitwise mask that should be applied 49 // to the DestPort. 50 func (k Key) PortMask() uint16 { 51 return ^k.InvertedPortMask 52 } 53 54 // String returns a string representation of the Key 55 func (k Key) String() string { 56 dPort := strconv.FormatUint(uint64(k.DestPort), 10) 57 if k.DestPort != 0 && k.InvertedPortMask != 0 { 58 dPort += "-" + strconv.FormatUint(uint64(k.DestPort+k.InvertedPortMask), 10) 59 } 60 return "Identity=" + strconv.FormatUint(uint64(k.Identity), 10) + 61 ",DestPort=" + dPort + 62 ",Nexthdr=" + strconv.FormatUint(uint64(k.Nexthdr), 10) + 63 ",TrafficDirection=" + strconv.FormatUint(uint64(k.TrafficDirection), 10) 64 } 65 66 // IsIngress returns true if the key refers to an ingress policy key 67 func (k Key) IsIngress() bool { 68 return k.TrafficDirection == trafficdirection.Ingress.Uint8() 69 } 70 71 // IsEgress returns true if the key refers to an egress policy key 72 func (k Key) IsEgress() bool { 73 return k.TrafficDirection == trafficdirection.Egress.Uint8() 74 } 75 76 // EndPort returns the end-port of the Key based on the Mask. 77 func (k Key) EndPort() uint16 { 78 return k.DestPort + k.InvertedPortMask 79 } 80 81 // PortProtoIsBroader returns true if the receiver Key has broader 82 // port-protocol than the argument Key. That is a port-protocol 83 // that covers the argument Key's port-protocol and is larger. 84 // An equal port-protocol will return false. 85 func (k Key) PortProtoIsBroader(c Key) bool { 86 if k.Nexthdr == 0 && c.Nexthdr != 0 { 87 return k.PortIsEqual(c) || k.PortIsBroader(c) 88 } 89 return k.Nexthdr == c.Nexthdr && k.PortIsBroader(c) 90 } 91 92 // PortProtoIsEqual returns true if the port-protocols of the 93 // two keys are exactly equal. 94 func (k Key) PortProtoIsEqual(c Key) bool { 95 return k.DestPort == c.DestPort && 96 k.InvertedPortMask == c.InvertedPortMask && 97 k.Nexthdr == c.Nexthdr 98 } 99 100 // PortIsBroader returns true if the receiver Key's 101 // port range covers the argument Key's port range, 102 // but returns false if they are equal. 103 func (k Key) PortIsBroader(c Key) bool { 104 if k.DestPort == 0 && c.DestPort != 0 { 105 return true 106 } 107 if k.DestPort != 0 && c.DestPort == 0 { 108 return false 109 } 110 kEP := k.EndPort() 111 cEP := c.EndPort() 112 return k.DestPort <= c.DestPort && kEP >= cEP && 113 // The port ranges cannot be exactly equal. 114 (k.DestPort != c.DestPort || kEP != cEP) 115 } 116 117 // PortIsEqual returns true if the port ranges 118 // between the two keys are exactly equal. 119 func (k Key) PortIsEqual(c Key) bool { 120 return k.DestPort == c.DestPort && 121 k.InvertedPortMask == c.InvertedPortMask 122 } 123 124 // PrefixLength returns the prefix lenth of the key 125 // for indexing it for the userspace cache (not the 126 // BPF map or datapath). 127 func (k Key) PrefixLength() uint { 128 keyPrefix := MapStatePrefixLen 129 portPrefix := uint(16) 130 if k.DestPort != 0 { 131 // It is not possible for k.InvertedPortMask 132 // to be incorrectly set, but even if 133 // it was the default value of "0" is 134 // what we want. 135 portPrefix = uint(bits.TrailingZeros16(k.PortMask())) 136 } 137 keyPrefix -= portPrefix 138 // If the port is fully wildcarded then 139 // we can also wildcard the protocol 140 // (if it is also wildcarded). 141 if portPrefix == 16 && k.Nexthdr == 0 { 142 keyPrefix -= 8 143 } 144 return keyPrefix 145 } 146 147 // CommonPrefix implements the CommonPrefix method for the 148 // bitlpm.Key interface. Identity is not indexed and is instead, 149 // saved as a simple map per TrafficDirection-Protocol-Port index 150 // key. 151 func (k Key) CommonPrefix(b Key) uint { 152 v := bits.LeadingZeros8(k.TrafficDirection ^ b.TrafficDirection) 153 if v != 8 { 154 return uint(v) 155 } 156 v += bits.LeadingZeros8(k.Nexthdr ^ b.Nexthdr) 157 if v != 16 { 158 return uint(v) 159 } 160 return uint(v + bits.LeadingZeros16(k.DestPort^b.DestPort)) 161 } 162 163 // BitValueAt implements the BitValueAt method for the 164 // bitlpm.Key interface. 165 func (k Key) BitValueAt(i uint) uint8 { 166 if i < 8 { 167 return min(k.TrafficDirection&(1<<(7-i)), 1) 168 } 169 if i < 16 { 170 return min(k.Nexthdr&(1<<(7-(i-8))), 1) 171 } 172 return uint8(min(k.DestPort&(1<<(15-(i-16))), 1)) 173 } 174 175 // Value implements the Value method for the 176 // bitlpm.Key interface. 177 func (k Key) Value() Key { 178 return k 179 } 180 181 type Keys map[Key]struct{}