github.com/cilium/cilium@v1.16.2/bpf/tests/ipsec_from_overlay_generic.h (about) 1 /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ 2 /* Copyright Authors of Cilium */ 3 4 #define NODE_ID 2333 5 #define ENCRYPT_KEY 3 6 #define ENABLE_IPV4 7 #define ENABLE_IPV6 8 #define ENABLE_IPSEC 9 #define TUNNEL_MODE 10 #define ENCAP_IFINDEX 4 11 #define DEST_IFINDEX 5 12 #define DEST_LXC_ID 200 13 14 #include "common.h" 15 #include <bpf/ctx/skb.h> 16 #include "pktgen.h" 17 #define ROUTER_IP 18 #define SECLABEL 19 #define SECLABEL_IPV4 20 #define SECLABEL_IPV6 21 #undef ROUTER_IP 22 #undef SECLABEL 23 #undef SECLABEL_IPV4 24 #undef SECLABEL_IPV6 25 26 #define skb_change_type mock_skb_change_type 27 int mock_skb_change_type(__maybe_unused struct __sk_buff *skb, __u32 type) 28 { 29 if (type != PACKET_HOST) 30 return -1; 31 return 0; 32 } 33 34 #define skb_get_tunnel_key mock_skb_get_tunnel_key 35 int mock_skb_get_tunnel_key(__maybe_unused struct __sk_buff *skb, 36 struct bpf_tunnel_key *to, 37 __maybe_unused __u32 size, 38 __maybe_unused __u32 flags) 39 { 40 to->remote_ipv4 = v4_node_one; 41 /* 0xfffff is the default SECLABEL */ 42 to->tunnel_id = 0xfffff; 43 return 0; 44 } 45 46 __section("mock-handle-policy") 47 int mock_handle_policy(struct __ctx_buff *ctx __maybe_unused) 48 { 49 /* https://github.com/cilium/cilium/blob/v1.16.0-pre.1/bpf/bpf_lxc.c#L2040 */ 50 #if !defined(ENABLE_ROUTING) && !defined(ENABLE_NODEPORT) 51 return TC_ACT_OK; 52 #else 53 return TC_ACT_REDIRECT; 54 #endif 55 } 56 57 struct { 58 __uint(type, BPF_MAP_TYPE_PROG_ARRAY); 59 __uint(key_size, sizeof(__u32)); 60 __uint(max_entries, 256); 61 __array(values, int()); 62 } mock_policy_call_map __section(".maps") = { 63 .values = { 64 [DEST_LXC_ID] = &mock_handle_policy, 65 }, 66 }; 67 68 #define tail_call_dynamic mock_tail_call_dynamic 69 static __always_inline __maybe_unused void 70 mock_tail_call_dynamic(struct __ctx_buff *ctx __maybe_unused, 71 const void *map __maybe_unused, __u32 slot __maybe_unused) 72 { 73 tail_call(ctx, &mock_policy_call_map, slot); 74 } 75 76 static volatile const __u8 *DEST_EP_MAC = mac_three; 77 static volatile const __u8 *DEST_NODE_MAC = mac_four; 78 79 #include "bpf_overlay.c" 80 81 #include "lib/endpoint.h" 82 #include "lib/ipcache.h" 83 #include "lib/node.h" 84 85 #define FROM_OVERLAY 0 86 #define ESP_SEQUENCE 69865 87 88 struct { 89 __uint(type, BPF_MAP_TYPE_PROG_ARRAY); 90 __uint(key_size, sizeof(__u32)); 91 __uint(max_entries, 1); 92 __array(values, int()); 93 } entry_call_map __section(".maps") = { 94 .values = { 95 [FROM_OVERLAY] = &cil_from_overlay, 96 }, 97 }; 98 99 PKTGEN("tc", "ipv4_not_decrypted_ipsec_from_overlay") 100 int ipv4_not_decrypted_ipsec_from_overlay_pktgen(struct __ctx_buff *ctx) 101 { 102 struct pktgen builder; 103 struct ethhdr *l2; 104 struct iphdr *l3; 105 struct ip_esp_hdr *l4; 106 void *data; 107 108 pktgen__init(&builder, ctx); 109 110 l2 = pktgen__push_ethhdr(&builder); 111 if (!l2) 112 return TEST_ERROR; 113 ethhdr__set_macs(l2, (__u8 *)mac_one, (__u8 *)mac_two); 114 115 l3 = pktgen__push_default_iphdr(&builder); 116 if (!l3) 117 return TEST_ERROR; 118 l3->saddr = v4_pod_one; 119 l3->daddr = v4_pod_two; 120 121 l4 = pktgen__push_default_esphdr(&builder); 122 if (!l4) 123 return TEST_ERROR; 124 l4->spi = ENCRYPT_KEY; 125 l4->seq_no = ESP_SEQUENCE; 126 127 data = pktgen__push_data(&builder, default_data, sizeof(default_data)); 128 if (!data) 129 return TEST_ERROR; 130 131 pktgen__finish(&builder); 132 return 0; 133 } 134 135 SETUP("tc", "ipv4_not_decrypted_ipsec_from_overlay") 136 int ipv4_not_decrypted_ipsec_from_overlay_setup(struct __ctx_buff *ctx) 137 { 138 /* We need to populate the node ID map because we'll lookup into it on 139 * ingress to find the node ID to use to match against XFRM IN states. 140 */ 141 node_v4_add_entry(v4_pod_one, NODE_ID, 0); 142 143 tail_call_static(ctx, entry_call_map, FROM_OVERLAY); 144 return TEST_ERROR; 145 } 146 147 CHECK("tc", "ipv4_not_decrypted_ipsec_from_overlay") 148 int ipv4_not_decrypted_ipsec_from_overlay_check(__maybe_unused const struct __ctx_buff *ctx) 149 { 150 void *data; 151 void *data_end; 152 __u32 *status_code; 153 struct ethhdr *l2; 154 struct iphdr *l3; 155 struct ip_esp_hdr *l4; 156 __u8 *payload; 157 158 test_init(); 159 160 data = (void *)(long)ctx->data; 161 data_end = (void *)(long)ctx->data_end; 162 163 if (data + sizeof(*status_code) > data_end) 164 test_fatal("status code out of bounds"); 165 166 status_code = data; 167 assert(*status_code == CTX_ACT_OK); 168 assert(ctx->mark == (MARK_MAGIC_DECRYPT | NODE_ID << 16)); 169 170 l2 = data + sizeof(*status_code); 171 172 if ((void *)l2 + sizeof(struct ethhdr) > data_end) 173 test_fatal("l2 out of bounds"); 174 175 if (l2->h_proto != bpf_htons(ETH_P_IP)) 176 test_fatal("l2 proto hasn't been set to ETH_P_IP"); 177 178 if (memcmp(l2->h_source, (__u8 *)mac_one, ETH_ALEN) != 0) 179 test_fatal("src mac hasn't been set to source ep's mac"); 180 181 if (memcmp(l2->h_dest, (__u8 *)mac_two, ETH_ALEN) != 0) 182 test_fatal("dest mac hasn't been set to dest ep's mac"); 183 184 l3 = (void *)l2 + sizeof(struct ethhdr); 185 186 if ((void *)l3 + sizeof(struct iphdr) > data_end) 187 test_fatal("l3 out of bounds"); 188 189 if (l3->saddr != v4_pod_one) 190 test_fatal("src IP was changed"); 191 192 if (l3->daddr != v4_pod_two) 193 test_fatal("dest IP was changed"); 194 195 if (l3->check != bpf_htons(0xf948)) 196 test_fatal("L3 checksum is invalid: %d", bpf_htons(l3->check)); 197 198 l4 = (void *)l3 + sizeof(struct iphdr); 199 200 if ((void *)l4 + sizeof(struct ip_esp_hdr) > data_end) 201 test_fatal("l4 out of bounds"); 202 203 if (l4->spi != ENCRYPT_KEY) 204 test_fatal("ESP spi was changed"); 205 206 if (l4->seq_no != ESP_SEQUENCE) 207 test_fatal("ESP seq was changed"); 208 209 payload = (void *)l4 + sizeof(struct ip_esp_hdr); 210 if ((void *)payload + sizeof(default_data) > data_end) 211 test_fatal("paylaod out of bounds\n"); 212 213 if (memcmp(payload, default_data, sizeof(default_data)) != 0) 214 test_fatal("tcp payload was changed"); 215 216 test_finish(); 217 } 218 219 PKTGEN("tc", "ipv6_not_decrypted_ipsec_from_overlay") 220 int ipv6_not_decrypted_ipsec_from_overlay_pktgen(struct __ctx_buff *ctx) 221 { 222 struct pktgen builder; 223 struct ethhdr *l2; 224 struct ipv6hdr *l3; 225 struct ip_esp_hdr *l4; 226 void *data; 227 228 pktgen__init(&builder, ctx); 229 230 l2 = pktgen__push_ethhdr(&builder); 231 if (!l2) 232 return TEST_ERROR; 233 ethhdr__set_macs(l2, (__u8 *)mac_one, (__u8 *)mac_two); 234 235 l3 = pktgen__push_default_ipv6hdr(&builder); 236 if (!l3) 237 return TEST_ERROR; 238 ipv6hdr__set_addrs(l3, (__u8 *)v6_pod_one, (__u8 *)v6_pod_two); 239 240 l4 = pktgen__push_default_esphdr(&builder); 241 if (!l4) 242 return TEST_ERROR; 243 l4->spi = ENCRYPT_KEY; 244 l4->seq_no = ESP_SEQUENCE; 245 246 data = pktgen__push_data(&builder, default_data, sizeof(default_data)); 247 if (!data) 248 return TEST_ERROR; 249 250 pktgen__finish(&builder); 251 return 0; 252 } 253 254 SETUP("tc", "ipv6_not_decrypted_ipsec_from_overlay") 255 int ipv6_not_decrypted_ipsec_from_overlay_setup(struct __ctx_buff *ctx) 256 { 257 /* To be able to use memcpy, we need to ensure that the memcpy'ed field is 258 * 8B aligned on the stack. Given the existing node_ip struct, the only way 259 * to achieve that is to align a parent tmp struct. 260 * We can't simply use __bpf_memcpy_builtin because that causes a 261 * relocation error in the lib. 262 */ 263 struct tmp { 264 __u32 _; 265 struct node_key k; 266 } node_ip __align_stack_8 = {}; 267 struct node_value node_value = { 268 .id = NODE_ID, 269 .spi = 0, 270 }; 271 272 /* We need to populate the node ID map because we'll lookup into it on 273 * ingress to find the node ID to use to match against XFRM IN states. 274 */ 275 node_ip.k.family = ENDPOINT_KEY_IPV6; 276 memcpy((__u8 *)&node_ip.k.ip6, (__u8 *)v6_pod_one, 16); 277 map_update_elem(&NODE_MAP_V2, &node_ip.k, &node_value, BPF_ANY); 278 279 tail_call_static(ctx, entry_call_map, FROM_OVERLAY); 280 return TEST_ERROR; 281 } 282 283 CHECK("tc", "ipv6_not_decrypted_ipsec_from_overlay") 284 int ipv6_not_decrypted_ipsec_from_overlay_check(__maybe_unused const struct __ctx_buff *ctx) 285 { 286 void *data; 287 void *data_end; 288 __u32 *status_code; 289 struct ethhdr *l2; 290 struct ipv6hdr *l3; 291 struct ip_esp_hdr *l4; 292 __u8 *payload; 293 294 test_init(); 295 296 data = (void *)(long)ctx->data; 297 data_end = (void *)(long)ctx->data_end; 298 299 if (data + sizeof(*status_code) > data_end) 300 test_fatal("status code out of bounds"); 301 302 status_code = data; 303 assert(*status_code == CTX_ACT_OK); 304 assert(ctx->mark == (MARK_MAGIC_DECRYPT | NODE_ID << 16)); 305 306 l2 = data + sizeof(*status_code); 307 308 if ((void *)l2 + sizeof(struct ethhdr) > data_end) 309 test_fatal("l2 out of bounds"); 310 311 if (l2->h_proto != bpf_htons(ETH_P_IPV6)) 312 test_fatal("l2 proto hasn't been set to ETH_P_IP"); 313 314 if (memcmp(l2->h_source, (__u8 *)mac_one, ETH_ALEN) != 0) 315 test_fatal("src mac hasn't been set to source ep's mac"); 316 317 if (memcmp(l2->h_dest, (__u8 *)mac_two, ETH_ALEN) != 0) 318 test_fatal("dest mac hasn't been set to dest ep's mac"); 319 320 l3 = (void *)l2 + sizeof(struct ethhdr); 321 322 if ((void *)l3 + sizeof(struct ipv6hdr) > data_end) 323 test_fatal("l3 out of bounds"); 324 325 if (memcmp((__u8 *)&l3->saddr, (__u8 *)v6_pod_one, 16) != 0) 326 test_fatal("src IP was changed"); 327 328 if (memcmp((__u8 *)&l3->daddr, (__u8 *)v6_pod_two, 16) != 0) 329 test_fatal("dest IP was changed"); 330 331 l4 = (void *)l3 + sizeof(struct ipv6hdr); 332 333 if ((void *)l4 + sizeof(struct ip_esp_hdr) > data_end) 334 test_fatal("l4 out of bounds"); 335 336 if (l4->spi != ENCRYPT_KEY) 337 test_fatal("ESP spi was changed"); 338 339 if (l4->seq_no != ESP_SEQUENCE) 340 test_fatal("ESP seq was changed"); 341 342 payload = (void *)l4 + sizeof(struct ip_esp_hdr); 343 if ((void *)payload + sizeof(default_data) > data_end) 344 test_fatal("paylaod out of bounds\n"); 345 346 if (memcmp(payload, default_data, sizeof(default_data)) != 0) 347 test_fatal("tcp payload was changed"); 348 349 test_finish(); 350 } 351 352 PKTGEN("tc", "ipv4_decrypted_ipsec_from_overlay") 353 int ipv4_decrypted_ipsec_from_overlay_pktgen(struct __ctx_buff *ctx) 354 { 355 struct pktgen builder; 356 struct tcphdr *l4; 357 void *data; 358 359 pktgen__init(&builder, ctx); 360 361 l4 = pktgen__push_ipv4_tcp_packet(&builder, 362 (__u8 *)mac_one, (__u8 *)mac_two, 363 v4_pod_one, v4_pod_two, 364 tcp_src_one, tcp_svc_one); 365 if (!l4) 366 return TEST_ERROR; 367 368 data = pktgen__push_data(&builder, default_data, sizeof(default_data)); 369 if (!data) 370 return TEST_ERROR; 371 372 pktgen__finish(&builder); 373 return 0; 374 } 375 376 SETUP("tc", "ipv4_decrypted_ipsec_from_overlay") 377 int ipv4_decrypted_ipsec_from_overlay_setup(struct __ctx_buff *ctx) 378 { 379 endpoint_v4_add_entry(v4_pod_two, DEST_IFINDEX, DEST_LXC_ID, 0, 0, 380 (__u8 *)DEST_EP_MAC, (__u8 *)DEST_NODE_MAC); 381 382 ctx->mark = MARK_MAGIC_DECRYPT; 383 tail_call_static(ctx, entry_call_map, FROM_OVERLAY); 384 return TEST_ERROR; 385 } 386 387 CHECK("tc", "ipv4_decrypted_ipsec_from_overlay") 388 int ipv4_decrypted_ipsec_from_overlay_check(__maybe_unused const struct __ctx_buff *ctx) 389 { 390 void *data; 391 void *data_end; 392 __u32 *status_code; 393 struct ethhdr *l2; 394 struct iphdr *l3; 395 struct tcphdr *l4; 396 __u8 *payload; 397 398 test_init(); 399 400 data = (void *)(long)ctx->data; 401 data_end = (void *)(long)ctx->data_end; 402 403 if (data + sizeof(*status_code) > data_end) 404 test_fatal("status code out of bounds"); 405 406 status_code = data; 407 assert(*status_code == EXPECTED_STATUS_CODE_FOR_DECRYPTED); 408 assert(ctx->mark == 0); 409 410 l2 = data + sizeof(*status_code); 411 412 if ((void *)l2 + sizeof(struct ethhdr) > data_end) 413 test_fatal("l2 out of bounds"); 414 415 if (l2->h_proto != bpf_htons(ETH_P_IP)) 416 test_fatal("l2 proto hasn't been set to ETH_P_IP"); 417 418 if (memcmp(l2->h_source, (__u8 *)DEST_NODE_MAC, ETH_ALEN) != 0) 419 test_fatal("src mac hasn't been set to source ep's mac"); 420 421 if (memcmp(l2->h_dest, (__u8 *)DEST_EP_MAC, ETH_ALEN) != 0) 422 test_fatal("dest mac hasn't been set to dest ep's mac"); 423 424 l3 = (void *)l2 + sizeof(struct ethhdr); 425 426 if ((void *)l3 + sizeof(struct iphdr) > data_end) 427 test_fatal("l3 out of bounds"); 428 429 if (l3->saddr != v4_pod_one) 430 test_fatal("src IP was changed"); 431 432 if (l3->daddr != v4_pod_two) 433 test_fatal("dest IP was changed"); 434 435 if (l3->check != bpf_htons(0xfa68)) 436 test_fatal("L3 checksum is invalid: %d", bpf_htons(l3->check)); 437 438 l4 = (void *)l3 + sizeof(struct iphdr); 439 440 if ((void *)l4 + sizeof(struct tcphdr) > data_end) 441 test_fatal("l4 out of bounds"); 442 443 if (l4->source != tcp_src_one) 444 test_fatal("src TCP port was changed"); 445 446 if (l4->dest != tcp_svc_one) 447 test_fatal("dst TCP port was changed"); 448 449 payload = (void *)l4 + sizeof(struct tcphdr); 450 if ((void *)payload + sizeof(default_data) > data_end) 451 test_fatal("paylaod out of bounds\n"); 452 453 if (memcmp(payload, default_data, sizeof(default_data)) != 0) 454 test_fatal("tcp payload was changed"); 455 456 test_finish(); 457 } 458 459 PKTGEN("tc", "ipv6_decrypted_ipsec_from_overlay") 460 int ipv6_decrypted_ipsec_from_overlay_pktgen(struct __ctx_buff *ctx) 461 { 462 struct pktgen builder; 463 struct tcphdr *l4; 464 void *data; 465 466 pktgen__init(&builder, ctx); 467 468 l4 = pktgen__push_ipv6_tcp_packet(&builder, 469 (__u8 *)mac_one, (__u8 *)mac_two, 470 (__u8 *)v6_pod_one, (__u8 *)v6_pod_two, 471 tcp_src_one, tcp_svc_one); 472 if (!l4) 473 return TEST_ERROR; 474 475 data = pktgen__push_data(&builder, default_data, sizeof(default_data)); 476 if (!data) 477 return TEST_ERROR; 478 479 pktgen__finish(&builder); 480 return 0; 481 } 482 483 SETUP("tc", "ipv6_decrypted_ipsec_from_overlay") 484 int ipv6_decrypted_ipsec_from_overlay_setup(struct __ctx_buff *ctx) 485 { 486 endpoint_v6_add_entry((union v6addr *)v6_pod_two, DEST_IFINDEX, DEST_LXC_ID, 487 0, 0, (__u8 *)DEST_EP_MAC, (__u8 *)DEST_NODE_MAC); 488 489 ctx->mark = MARK_MAGIC_DECRYPT; 490 tail_call_static(ctx, entry_call_map, FROM_OVERLAY); 491 return TEST_ERROR; 492 } 493 494 CHECK("tc", "ipv6_decrypted_ipsec_from_overlay") 495 int ipv6_decrypted_ipsec_from_overlay_check(__maybe_unused const struct __ctx_buff *ctx) 496 { 497 void *data; 498 void *data_end; 499 __u32 *status_code; 500 struct ethhdr *l2; 501 struct ipv6hdr *l3; 502 struct tcphdr *l4; 503 __u8 *payload; 504 505 test_init(); 506 507 data = (void *)(long)ctx->data; 508 data_end = (void *)(long)ctx->data_end; 509 510 if (data + sizeof(*status_code) > data_end) 511 test_fatal("status code out of bounds"); 512 513 status_code = data; 514 assert(*status_code == EXPECTED_STATUS_CODE_FOR_DECRYPTED); 515 assert(ctx->mark == 0); 516 517 l2 = data + sizeof(*status_code); 518 519 if ((void *)l2 + sizeof(struct ethhdr) > data_end) 520 test_fatal("l2 out of bounds"); 521 522 if (l2->h_proto != bpf_htons(ETH_P_IPV6)) 523 test_fatal("l2 proto hasn't been set to ETH_P_IP"); 524 525 if (memcmp(l2->h_source, (__u8 *)DEST_NODE_MAC, ETH_ALEN) != 0) 526 test_fatal("src mac hasn't been set to source ep's mac"); 527 528 if (memcmp(l2->h_dest, (__u8 *)DEST_EP_MAC, ETH_ALEN) != 0) 529 test_fatal("dest mac hasn't been set to dest ep's mac"); 530 531 l3 = (void *)l2 + sizeof(struct ethhdr); 532 533 if ((void *)l3 + sizeof(struct ipv6hdr) > data_end) 534 test_fatal("l3 out of bounds"); 535 536 if (memcmp((__u8 *)&l3->saddr, (__u8 *)v6_pod_one, 16) != 0) 537 test_fatal("src IP was changed"); 538 539 if (memcmp((__u8 *)&l3->daddr, (__u8 *)v6_pod_two, 16) != 0) 540 test_fatal("dest IP was changed"); 541 542 l4 = (void *)l3 + sizeof(struct ipv6hdr); 543 544 if ((void *)l4 + sizeof(struct tcphdr) > data_end) 545 test_fatal("l4 out of bounds"); 546 547 if (l4->source != tcp_src_one) 548 test_fatal("src TCP port was changed"); 549 550 if (l4->dest != tcp_svc_one) 551 test_fatal("dst TCP port was changed"); 552 553 payload = (void *)l4 + sizeof(struct tcphdr); 554 if ((void *)payload + sizeof(default_data) > data_end) 555 test_fatal("paylaod out of bounds\n"); 556 557 if (memcmp(payload, default_data, sizeof(default_data)) != 0) 558 test_fatal("tcp payload was changed"); 559 560 test_finish(); 561 }