github.com/cilium/cilium@v1.16.2/bpf/lib/high_scale_ipcache.h (about)

     1  /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
     2  /* Copyright Authors of Cilium */
     3  
     4  #pragma once
     5  
     6  #include "ipv4.h"
     7  #include "l4.h"
     8  #include "maps.h"
     9  
    10  #ifdef ENABLE_HIGH_SCALE_IPCACHE
    11  /* WORLD_CIDR_STATIC_PREFIX4 gets sizeof non-IP, non-prefix part of
    12   * world_cidrs_key4.
    13   */
    14  # define WORLD_CIDR_STATIC_PREFIX4						\
    15  	(8 * (sizeof(struct world_cidrs_key4) - sizeof(struct bpf_lpm_trie_key)	\
    16  	      - sizeof(__u32)))
    17  #define WORLD_CIDR_PREFIX_LEN4(PREFIX) (WORLD_CIDR_STATIC_PREFIX4 + (PREFIX))
    18  
    19  static __always_inline __maybe_unused bool
    20  world_cidrs_lookup4(__u32 addr)
    21  {
    22  	__u8 *matches;
    23  	struct world_cidrs_key4 key = {
    24  		.lpm_key = { WORLD_CIDR_PREFIX_LEN4(V4_CACHE_KEY_LEN), {} },
    25  		.ip = addr,
    26  	};
    27  
    28  	key.ip &= GET_PREFIX(V4_CACHE_KEY_LEN);
    29  	matches = map_lookup_elem(&WORLD_CIDRS4_MAP, &key);
    30  	return matches != NULL;
    31  }
    32  
    33  static __always_inline bool
    34  needs_encapsulation(__u32 addr)
    35  {
    36  # ifndef ENABLE_ROUTING
    37  	/* If endpoint routes are enabled, we need to check if the destination
    38  	 * is a local endpoint, in which case we don't want to encapsulate. If
    39  	 * endpoint routes are disabled, we don't need to check this because we
    40  	 * will never reach this point and the packet will be redirected to the
    41  	 * destination endpoint directly.
    42  	 */
    43  	if (__lookup_ip4_endpoint(addr))
    44  		return false;
    45  # endif /* ENABLE_ROUTING */
    46  	/* If the destination doesn't match one of the world CIDRs, we assume
    47  	 * it's destined to a remote pod. In that case, since the high-scale
    48  	 * ipcache is enabled, we want to encapsulate with the remote pod's IP
    49  	 * itself.
    50  	 */
    51  	return !world_cidrs_lookup4(addr);
    52  }
    53  
    54  static __always_inline int
    55  decapsulate_overlay(struct __ctx_buff *ctx, __u32 *src_id)
    56  {
    57  	struct geneve_dsr_opt4 dsr_opt __maybe_unused;
    58  	struct genevehdr geneve __maybe_unused;
    59  	__u32 opt_len __maybe_unused;
    60  	void *data, *data_end;
    61  	__u16 dport, proto;
    62  	struct iphdr *ip4;
    63  	int shrink;
    64  	__u32 off;
    65  
    66  	if (!validate_ethertype(ctx, &proto))
    67  		return DROP_UNSUPPORTED_L2;
    68  	if (proto != bpf_htons(ETH_P_IP))
    69  		return CTX_ACT_OK;
    70  
    71  	if (!revalidate_data_pull(ctx, &data, &data_end, &ip4))
    72  		return DROP_INVALID;
    73  	if (ip4->protocol != IPPROTO_UDP)
    74  		return CTX_ACT_OK;
    75  
    76  	off = ((void *)ip4 - data) + ipv4_hdrlen(ip4) +
    77  	      offsetof(struct udphdr, dest);
    78  	if (l4_load_port(ctx, off, &dport) < 0)
    79  		return DROP_INVALID;
    80  
    81  	if (dport != bpf_htons(TUNNEL_PORT))
    82  		return CTX_ACT_OK;
    83  
    84  	switch (TUNNEL_PROTOCOL) {
    85  	case TUNNEL_PROTOCOL_GENEVE:
    86  		off = ((void *)ip4 - data) + ipv4_hdrlen(ip4) + sizeof(struct udphdr);
    87  		if (ctx_load_bytes(ctx, off, &geneve, sizeof(geneve)) < 0)
    88  			return DROP_INVALID;
    89  
    90  		opt_len = geneve.opt_len * 4;
    91  		memcpy(src_id, &geneve.vni, sizeof(__u32));
    92  
    93  #if defined(ENABLE_DSR) && DSR_ENCAP_MODE == DSR_ENCAP_GENEVE
    94  		ctx_store_meta(ctx, CB_HSIPC_ADDR_V4, 0);
    95  
    96  		if (opt_len && opt_len >= sizeof(dsr_opt)) {
    97  			if (ctx_load_bytes(ctx, off + sizeof(geneve), &dsr_opt,
    98  					   sizeof(dsr_opt)) < 0)
    99  				return DROP_INVALID;
   100  
   101  			if (dsr_opt.hdr.opt_class == bpf_htons(DSR_GENEVE_OPT_CLASS) &&
   102  			    dsr_opt.hdr.type == DSR_GENEVE_OPT_TYPE) {
   103  				ctx_store_meta(ctx, CB_HSIPC_ADDR_V4, dsr_opt.addr);
   104  				ctx_store_meta(ctx, CB_HSIPC_PORT, dsr_opt.port);
   105  			}
   106  		}
   107  #endif /* ENABLE_DSR && DSR_ENCAP_MODE == DSR_ENCAP_GENEVE */
   108  
   109  		shrink = ipv4_hdrlen(ip4) + sizeof(struct udphdr) +
   110  			 sizeof(struct genevehdr) + opt_len +
   111  			 sizeof(struct ethhdr);
   112  		break;
   113  	case TUNNEL_PROTOCOL_VXLAN:
   114  		shrink = ipv4_hdrlen(ip4) + sizeof(struct udphdr) +
   115  			 sizeof(struct vxlanhdr) + sizeof(struct ethhdr);
   116  		off = ((void *)ip4 - data) + ipv4_hdrlen(ip4) +
   117  		      sizeof(struct udphdr) +
   118  		      offsetof(struct vxlanhdr, vx_vni);
   119  
   120  		if (ctx_load_bytes(ctx, off, src_id, sizeof(__u32)) < 0)
   121  			return DROP_INVALID;
   122  		break;
   123  	default:
   124  		/* If the tunnel type is neither VXLAN nor GENEVE, we have an issue. */
   125  		__throw_build_bug();
   126  	}
   127  
   128  	*src_id = tunnel_vni_to_sec_identity(*src_id);
   129  	ctx_store_meta(ctx, CB_SRC_LABEL, *src_id);
   130  
   131  	if (ctx_adjust_hroom(ctx, -shrink, BPF_ADJ_ROOM_MAC, ctx_adjust_hroom_flags()))
   132  		return DROP_INVALID;
   133  
   134  	return ctx_redirect(ctx, ENCAP_IFINDEX, BPF_F_INGRESS);
   135  }
   136  #endif /* ENABLE_HIGH_SCALE_IPCACHE */