github.com/cilium/cilium@v1.16.2/pkg/endpoint/id/id.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package id 5 6 import ( 7 "fmt" 8 "math" 9 "net/netip" 10 "strconv" 11 "strings" 12 ) 13 14 // MaxEndpointID is the maximum endpoint identifier. 15 const MaxEndpointID = math.MaxUint16 16 17 // PrefixType describes the type of endpoint identifier 18 type PrefixType string 19 20 func (s PrefixType) String() string { return string(s) } 21 22 const ( 23 // CiliumLocalIdPrefix is a numeric identifier with local scope. It has 24 // no cluster wide meaning and is only unique in the scope of a single 25 // agent. An endpoint is guaranteed to always have a local scope identifier. 26 CiliumLocalIdPrefix PrefixType = "cilium-local" 27 28 // CiliumGlobalIdPrefix is an endpoint identifier with global scope. 29 // This addressing mechanism is currently unused. 30 CiliumGlobalIdPrefix PrefixType = "cilium-global" 31 32 // ContainerIdPrefix is used to address an endpoint via its primary 33 // container ID. The container ID is specific to the container runtime 34 // in use. Only the primary container that defines the networking scope 35 // can be used to address an endpoint. 36 // This can only be used to look up endpoints which have not opted-out of 37 // legacy identifiers. 38 // Deprecated. Use CNIAttachmentIdPrefix instead 39 ContainerIdPrefix PrefixType = "container-id" 40 41 // CNIAttachmentIdPrefix is used to address an endpoint via its primary 42 // container ID and container interface passed to the CNI plugin. 43 // This attachment ID uniquely identifies a CNI ADD and CNI DEL invocation pair. 44 CNIAttachmentIdPrefix PrefixType = "cni-attachment-id" 45 46 // DockerEndpointPrefix is used to address an endpoint via the Docker 47 // endpoint ID. This method is only possible if the endpoint was 48 // created via the cilium-docker plugin and the container is backed by 49 // the libnetwork abstraction. 50 DockerEndpointPrefix PrefixType = "docker-endpoint" 51 52 // ContainerNamePrefix is used to address the endpoint via the 53 // container's name. This addressing mechanism depends on the container 54 // runtime. Only the primary container that the networking scope can be 55 // used to address an endpoint. 56 // This can only be used to look up endpoints which have not opted-out of 57 // legacy identifiers. 58 // Deprecated. Use CNIAttachmentIdPrefix instead 59 ContainerNamePrefix PrefixType = "container-name" 60 61 // CEPNamePrefix is used to address an endpoint via its Kubernetes 62 // CiliumEndpoint resource name. This addressing only works if the endpoint 63 // is represented as a Kubernetes CiliumEndpoint resource. 64 CEPNamePrefix PrefixType = "cep-name" 65 66 // PodNamePrefix is used to address an endpoint via the Kubernetes pod 67 // name. This addressing only works if the endpoint represents as 68 // Kubernetes pod. 69 // This can only be used to look up endpoints which have not opted-out of 70 // legacy identifiers. 71 // Deprecated. May not be unique. Use CEPNamePrefix instead. 72 PodNamePrefix PrefixType = "pod-name" 73 74 // IPv4Prefix is used to address an endpoint via the endpoint's IPv4 75 // address. 76 IPv4Prefix PrefixType = "ipv4" 77 78 // IPv6Prefix is the prefix used to refer to an endpoint via IPv6 address 79 IPv6Prefix PrefixType = "ipv6" 80 ) 81 82 // NewCiliumID returns a new endpoint identifier of type CiliumLocalIdPrefix 83 func NewCiliumID(id int64) string { 84 return NewID(CiliumLocalIdPrefix, strconv.FormatInt(id, 10)) 85 } 86 87 // NewID returns a new endpoint identifier 88 func NewID(prefix PrefixType, id string) string { 89 return string(prefix) + ":" + id 90 } 91 92 // NewIPPrefixID returns an identifier based on the IP address specified. If ip 93 // is invalid, an empty string is returned. 94 func NewIPPrefixID(ip netip.Addr) string { 95 if ip.IsValid() { 96 if ip.Is4() { 97 return NewID(IPv4Prefix, ip.String()) 98 } 99 return NewID(IPv6Prefix, ip.String()) 100 } 101 return "" 102 } 103 104 // NewCNIAttachmentID returns an identifier based on the CNI attachment ID. If 105 // the containerIfName is empty, only the containerID will be used. 106 func NewCNIAttachmentID(containerID, containerIfName string) string { 107 id := containerID 108 if containerIfName != "" { 109 id = containerID + ":" + containerIfName 110 } 111 return NewID(CNIAttachmentIdPrefix, id) 112 } 113 114 // splitID splits ID into prefix and id. No validation is performed on prefix. 115 func splitID(id string) (PrefixType, string) { 116 if idx := strings.IndexByte(id, ':'); idx > -1 { 117 return PrefixType(id[:idx]), id[idx+1:] 118 } 119 120 // default prefix 121 return CiliumLocalIdPrefix, id 122 } 123 124 // ParseCiliumID parses id as cilium endpoint id and returns numeric portion. 125 func ParseCiliumID(id string) (int64, error) { 126 prefix, id := splitID(id) 127 if prefix != CiliumLocalIdPrefix { 128 return 0, fmt.Errorf("not a cilium identifier") 129 } 130 n, err := strconv.ParseInt(id, 0, 64) 131 if err != nil || n < 0 { 132 return 0, fmt.Errorf("invalid numeric cilium id: %w", err) 133 } 134 if n > MaxEndpointID { 135 return 0, fmt.Errorf("endpoint id too large: %d", n) 136 } 137 return n, nil 138 } 139 140 // Parse parses a string as an endpoint identified consists of an optional 141 // prefix [prefix:] followed by the identifier. 142 func Parse(id string) (PrefixType, string, error) { 143 prefix, id := splitID(id) 144 switch prefix { 145 case CiliumLocalIdPrefix, 146 CiliumGlobalIdPrefix, 147 CNIAttachmentIdPrefix, 148 ContainerIdPrefix, 149 DockerEndpointPrefix, 150 ContainerNamePrefix, 151 CEPNamePrefix, 152 PodNamePrefix, 153 IPv4Prefix, 154 IPv6Prefix: 155 return prefix, id, nil 156 } 157 158 return "", "", fmt.Errorf("unknown endpoint ID prefix \"%s\"", prefix) 159 }