github.com/cilium/cilium@v1.16.2/bpf/tests/tc_host_encrypted_overlay.c (about) 1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 /* Copyright Authors of Cilium */ 3 4 #include "common.h" 5 6 #include <bpf/ctx/skb.h> 7 #include "pktgen.h" 8 9 /* Set ETH_HLEN to 14 to indicate that the packet has a 14 byte ethernet header */ 10 #define ETH_HLEN 14 11 12 /* Enable code paths under test */ 13 #define ENABLE_IPV4 1 14 #define ENABLE_IPSEC 1 15 #define ENABLE_ENCRYPTED_OVERLAY 1 16 17 #define TUNNEL_MODE 1 18 #define TUNNEL_PROTOCOL TUNNEL_PROTOCOL_VXLAN 19 #define TUNNEL_PORT 8472 20 #define ENCAP_IFINDEX 25 21 22 #define NODE1_IP v4_ext_one 23 #define NODE1_TUNNEL_SPORT 1337 24 25 #define NODE2_IP v4_ext_two 26 #define NODE1_SPI 5 27 #define NODE2_ID 123 28 #define NODE2_SPI 6 29 30 #define POD1_IP v4_pod_one 31 #define POD1_IFACE 100 32 #define POD2_IP v4_pod_two 33 34 #define POD1_SEC_IDENTITY 112233 35 36 static volatile const __u8 *node1_mac = mac_one; 37 static volatile const __u8 *node2_mac = mac_two; 38 39 static volatile const __u8 *pod1_mac = mac_three; 40 static volatile const __u8 *pod2_mac = mac_four; 41 42 #define ctx_redirect mock_ctx_redirect 43 44 static __always_inline __maybe_unused int 45 mock_ctx_redirect(const struct __sk_buff *ctx __maybe_unused, 46 int ifindex __maybe_unused, __u32 flags __maybe_unused) 47 { 48 if ((__u32)ifindex != ctx->ifindex) 49 return CTX_ACT_DROP; 50 if (flags != BPF_F_INGRESS) 51 return CTX_ACT_DROP; 52 53 return CTX_ACT_REDIRECT; 54 } 55 56 #define SECCTX_FROM_IPCACHE 1 57 58 #include "bpf_host.c" 59 60 #include "lib/endpoint.h" 61 #include "lib/node.h" 62 63 #define TO_NETDEV 0 64 65 struct { 66 __uint(type, BPF_MAP_TYPE_PROG_ARRAY); 67 __uint(key_size, sizeof(__u32)); 68 __uint(max_entries, 1); 69 __array(values, int()); 70 } entry_call_map __section(".maps") = { 71 .values = { 72 [TO_NETDEV] = &cil_to_netdev, 73 }, 74 }; 75 76 PKTGEN("tc", "tc_host_encrypted_overlay_01") 77 int host_encrypted_overlay_01_pktgen(struct __ctx_buff *ctx) 78 { 79 struct vxlanhdr *vxlan; 80 struct iphdr *inner_l3; 81 struct pktgen builder; 82 83 /* Init packet builder */ 84 pktgen__init(&builder, ctx); 85 86 vxlan = pktgen__push_ipv4_vxlan_packet(&builder, 87 (__u8 *)node1_mac, (__u8 *)node2_mac, 88 NODE1_IP, NODE2_IP, 89 NODE1_TUNNEL_SPORT, TUNNEL_PORT); 90 if (!vxlan) 91 return TEST_ERROR; 92 93 vxlan->vx_vni = sec_identity_to_tunnel_vni(ENCRYPTED_OVERLAY_ID); 94 95 inner_l3 = pktgen__push_ipv4_packet(&builder, 96 (__u8 *)pod1_mac, (__u8 *)pod2_mac, 97 POD1_IP, POD2_IP); 98 if (!inner_l3) 99 return TEST_ERROR; 100 101 /* Calc lengths, set protocol fields and calc checksums */ 102 pktgen__finish(&builder); 103 104 return 0; 105 } 106 107 SETUP("tc", "tc_host_encrypted_overlay_01") 108 int tc_host_encrypted_overlay_01_setup(struct __ctx_buff *ctx) 109 { 110 struct encrypt_config encrypt_value = { .encrypt_key = NODE1_SPI }; 111 __u32 encrypt_key = 0; 112 113 endpoint_v4_add_entry(POD1_IP, POD1_IFACE, 0, 0, POD1_SEC_IDENTITY, 114 (__u8 *)pod1_mac, (__u8 *)node1_mac); 115 node_v4_add_entry(NODE2_IP, NODE2_ID, NODE2_SPI); 116 map_update_elem(&ENCRYPT_MAP, &encrypt_key, &encrypt_value, BPF_ANY); 117 118 set_identity_mark(ctx, ENCRYPTED_OVERLAY_ID, MARK_MAGIC_OVERLAY); 119 120 /* Jump into the entrypoint */ 121 tail_call_static(ctx, entry_call_map, TO_NETDEV); 122 /* Fail if we didn't jump */ 123 return TEST_ERROR; 124 } 125 126 CHECK("tc", "tc_host_encrypted_overlay_01") 127 int tc_host_encrypted_overlay_01_check(const struct __ctx_buff *ctx) 128 { 129 struct vxlanhdr *vxlan; 130 void *data, *data_end; 131 __u32 *status_code; 132 struct udphdr *l4; 133 struct ethhdr *l2; 134 struct iphdr *l3; 135 136 test_init(); 137 138 data = (void *)(long)ctx_data(ctx); 139 data_end = (void *)(long)ctx->data_end; 140 141 if (data + sizeof(__u32) > data_end) 142 test_fatal("status code out of bounds"); 143 144 status_code = data; 145 146 assert(*status_code == CTX_ACT_REDIRECT); 147 148 l2 = data + sizeof(__u32); 149 if ((void *)l2 + sizeof(*l2) > data_end) 150 test_fatal("l2 out of bounds"); 151 152 l3 = (void *)l2 + sizeof(*l2); 153 if ((void *)l3 + sizeof(*l3) > data_end) 154 test_fatal("l3 out of bounds"); 155 156 l4 = (void *)l3 + sizeof(*l3); 157 if ((void *)l4 + sizeof(*l4) > data_end) 158 test_fatal("l4 out of bounds"); 159 160 vxlan = (void *)l4 + sizeof(*l4); 161 if ((void *)vxlan + sizeof(*vxlan) > data_end) 162 test_fatal("vxlan out of bounds"); 163 164 if (memcmp(l2->h_source, (__u8 *)node1_mac, ETH_ALEN) != 0) 165 test_fatal("src MAC is not the node MAC") 166 if (memcmp(l2->h_dest, (__u8 *)node1_mac, ETH_ALEN) != 0) 167 test_fatal("dst MAC has not been updated") 168 169 if (l3->saddr != NODE1_IP) 170 test_fatal("src IP has changed"); 171 172 if (l3->daddr != NODE2_IP) 173 test_fatal("dst IP has changed"); 174 175 if (l3->check != bpf_htons(0x7da4)) 176 test_fatal("L3 checksum is invalid: %d", bpf_htons(l3->check)); 177 178 if (l4->source != NODE1_TUNNEL_SPORT) 179 test_fatal("src port has changed"); 180 181 if (l4->dest != TUNNEL_PORT) 182 test_fatal("dst port has changed"); 183 184 if (tunnel_vni_to_sec_identity(vxlan->vx_vni) != POD1_SEC_IDENTITY) 185 test_fatal("VNI has not been updated"); 186 187 assert(ctx->mark == (or_encrypt_key(NODE1_SPI) | (NODE2_ID << 16))); 188 assert(ctx_load_meta(ctx, CB_ENCRYPT_IDENTITY) == POD1_SEC_IDENTITY); 189 190 test_finish(); 191 }