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 */