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  }