github.com/cilium/cilium@v1.16.2/bpf/tests/ipsec_from_lxc_generic.h (about) 1 /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ 2 /* Copyright Authors of Cilium */ 3 4 #include "common.h" 5 #include <bpf/ctx/skb.h> 6 #include "pktgen.h" 7 #define ROUTER_IP 8 #undef ROUTER_IP 9 10 #define NODE_ID 2333 11 #define ENCRYPT_KEY 3 12 #define ENABLE_IPV4 13 #define ENABLE_IPV6 14 #define ENABLE_IPSEC 15 #define ENCAP_IFINDEX 4 16 17 #include "bpf_lxc.c" 18 19 #include "lib/ipcache.h" 20 #include "lib/node.h" 21 #include "lib/policy.h" 22 23 #define FROM_CONTAINER 0 24 25 struct { 26 __uint(type, BPF_MAP_TYPE_PROG_ARRAY); 27 __uint(key_size, sizeof(__u32)); 28 __uint(max_entries, 1); 29 __array(values, int()); 30 } entry_call_map __section(".maps") = { 31 .values = { 32 [FROM_CONTAINER] = &cil_from_container, 33 }, 34 }; 35 36 static __always_inline int 37 pktgen_from_lxc(struct __ctx_buff *ctx) 38 { 39 struct pktgen builder; 40 struct tcphdr *l4; 41 void *data; 42 43 pktgen__init(&builder, ctx); 44 45 l4 = pktgen__push_ipv4_tcp_packet(&builder, 46 (__u8 *)mac_one, (__u8 *)mac_two, 47 v4_pod_one, v4_pod_two, 48 tcp_src_one, tcp_svc_one); 49 if (!l4) 50 return TEST_ERROR; 51 52 data = pktgen__push_data(&builder, default_data, sizeof(default_data)); 53 if (!data) 54 return TEST_ERROR; 55 56 pktgen__finish(&builder); 57 return 0; 58 } 59 60 PKTGEN("tc", "01_ipv4_from_lxc_no_node_id") 61 int ipv4_from_lxc_no_node_id_pktgen(struct __ctx_buff *ctx) 62 { 63 return pktgen_from_lxc(ctx); 64 } 65 66 SETUP("tc", "01_ipv4_from_lxc_no_node_id") 67 int ipv4_from_lxc_no_node_id_setup(struct __ctx_buff *ctx) 68 { 69 policy_add_egress_allow_all_entry(); 70 71 ipcache_v4_add_entry(v4_pod_two, 0, 233, v4_node_two, ENCRYPT_KEY); 72 73 __u32 encrypt_key = 0; 74 struct encrypt_config encrypt_value = { .encrypt_key = ENCRYPT_KEY }; 75 76 map_update_elem(&ENCRYPT_MAP, &encrypt_key, &encrypt_value, BPF_ANY); 77 78 tail_call_static(ctx, entry_call_map, FROM_CONTAINER); 79 return TEST_ERROR; 80 } 81 82 CHECK("tc", "01_ipv4_from_lxc_no_node_id") 83 int ipv4_from_lxc_no_node_id_check(__maybe_unused const struct __ctx_buff *ctx) 84 { 85 void *data; 86 void *data_end; 87 __u32 *status_code; 88 89 struct metrics_value *entry = NULL; 90 struct metrics_key key = {}; 91 92 test_init(); 93 94 data = (void *)(long)ctx->data; 95 data_end = (void *)(long)ctx->data_end; 96 97 if (data + sizeof(*status_code) > data_end) 98 test_fatal("status code out of bounds"); 99 100 status_code = data; 101 assert(*status_code == CTX_ACT_DROP); 102 103 key.reason = (__u8)-DROP_NO_NODE_ID; 104 key.dir = METRIC_EGRESS; 105 entry = map_lookup_elem(&METRICS_MAP, &key); 106 if (!entry) 107 test_fatal("metrics entry not found"); 108 109 __u64 count = 1; 110 111 assert_metrics_count(key, count); 112 113 test_finish(); 114 } 115 116 PKTGEN("tc", "02_ipv4_from_lxc_encrypt") 117 int ipv4_from_lxc_encrypt_pktgen(struct __ctx_buff *ctx) 118 { 119 return pktgen_from_lxc(ctx); 120 } 121 122 SETUP("tc", "02_ipv4_from_lxc_encrypt") 123 int ipv4_from_lxc_encrypt_setup(struct __ctx_buff *ctx) 124 { 125 node_v4_add_entry(v4_node_two, NODE_ID, 0); 126 127 tail_call_static(ctx, entry_call_map, FROM_CONTAINER); 128 return TEST_ERROR; 129 } 130 131 CHECK("tc", "02_ipv4_from_lxc_encrypt") 132 int ipv4_from_lxc_encrypt_check(__maybe_unused const struct __ctx_buff *ctx) 133 { 134 void *data; 135 void *data_end; 136 __u32 *status_code; 137 struct ethhdr *l2; 138 struct iphdr *l3; 139 struct tcphdr *l4; 140 __u8 *payload; 141 142 test_init(); 143 144 data = (void *)(long)ctx->data; 145 data_end = (void *)(long)ctx->data_end; 146 147 if (data + sizeof(*status_code) > data_end) 148 test_fatal("status code out of bounds"); 149 150 status_code = data; 151 assert(*status_code == CTX_ACT_OK); 152 assert(ctx->mark == (NODE_ID << 16 | ENCRYPT_KEY << 12 | MARK_MAGIC_ENCRYPT)); 153 assert(ctx_load_meta(ctx, CB_ENCRYPT_IDENTITY) == SECLABEL_IPV4); 154 155 l2 = data + sizeof(*status_code); 156 157 if ((void *)l2 + sizeof(struct ethhdr) > data_end) 158 test_fatal("l2 out of bounds"); 159 160 if (l2->h_proto != bpf_htons(ETH_P_IP)) 161 test_fatal("l2 proto hasn't been set to ETH_P_IP"); 162 163 if (memcmp(l2->h_source, (__u8 *)mac_one, ETH_ALEN) != 0) 164 test_fatal("src mac hasn't been set to source ep's mac"); 165 166 if (memcmp(l2->h_dest, (__u8 *)EXPECTED_DEST_MAC, ETH_ALEN) != 0) 167 test_fatal("dest mac hasn't been set to dest ep's mac"); 168 169 l3 = (void *)l2 + sizeof(struct ethhdr); 170 171 if ((void *)l3 + sizeof(struct iphdr) > data_end) 172 test_fatal("l3 out of bounds"); 173 174 if (l3->saddr != v4_pod_one) 175 test_fatal("src IP was changed"); 176 177 if (l3->daddr != v4_pod_two) 178 test_fatal("dest IP was changed"); 179 180 l4 = (void *)l3 + sizeof(struct iphdr); 181 182 if ((void *)l4 + sizeof(struct tcphdr) > data_end) 183 test_fatal("l4 out of bounds"); 184 185 if (l4->source != tcp_src_one) 186 test_fatal("src TCP port was changed"); 187 188 if (l4->dest != tcp_svc_one) 189 test_fatal("dst TCP port was changed"); 190 191 payload = (void *)l4 + sizeof(struct tcphdr); 192 if ((void *)payload + sizeof(default_data) > data_end) 193 test_fatal("paylaod out of bounds\n"); 194 195 if (memcmp(payload, default_data, sizeof(default_data)) != 0) 196 test_fatal("tcp payload was changed"); 197 198 test_finish(); 199 } 200 201 PKTGEN("tc", "03_ipv4_from_lxc_new_local_key") 202 int ipv4_from_lxc_new_local_key_pktgen(struct __ctx_buff *ctx) 203 { 204 return pktgen_from_lxc(ctx); 205 } 206 207 SETUP("tc", "03_ipv4_from_lxc_new_local_key") 208 int ipv4_from_lxc_new_local_key_setup(struct __ctx_buff *ctx) 209 { 210 /* The new key is configured locally but not yet on the destination node. 211 */ 212 __u32 encrypt_key = 0; 213 struct encrypt_config encrypt_value = { .encrypt_key = ENCRYPT_KEY + 1 }; 214 215 map_update_elem(&ENCRYPT_MAP, &encrypt_key, &encrypt_value, BPF_ANY); 216 217 tail_call_static(ctx, entry_call_map, FROM_CONTAINER); 218 return TEST_ERROR; 219 } 220 221 CHECK("tc", "03_ipv4_from_lxc_new_local_key") 222 int ipv4_from_lxc_new_local_key_check(__maybe_unused const struct __ctx_buff *ctx) 223 { 224 void *data; 225 void *data_end; 226 __u32 *status_code; 227 228 test_init(); 229 230 data = (void *)(long)ctx->data; 231 data_end = (void *)(long)ctx->data_end; 232 233 if (data + sizeof(*status_code) > data_end) 234 test_fatal("status code out of bounds"); 235 236 status_code = data; 237 assert(*status_code == CTX_ACT_OK); 238 assert(ctx->mark == (NODE_ID << 16 | ENCRYPT_KEY << 12 | MARK_MAGIC_ENCRYPT)); 239 assert(ctx_load_meta(ctx, CB_ENCRYPT_IDENTITY) == SECLABEL_IPV4); 240 241 test_finish(); 242 } 243 244 PKTGEN("tc", "04_ipv4_from_lxc_new_remote_key") 245 int ipv4_from_lxc_new_remote_key_pktgen(struct __ctx_buff *ctx) 246 { 247 return pktgen_from_lxc(ctx); 248 } 249 250 SETUP("tc", "04_ipv4_from_lxc_new_remote_key") 251 int ipv4_from_lxc_new_remote_key_setup(struct __ctx_buff *ctx) 252 { 253 /* The new key is configured on the destination node but not yet locally. 254 */ 255 ipcache_v4_add_entry(v4_pod_two, 0, 233, v4_node_two, ENCRYPT_KEY + 1); 256 257 __u32 encrypt_key = 0; 258 struct encrypt_config encrypt_value = { .encrypt_key = ENCRYPT_KEY }; 259 260 map_update_elem(&ENCRYPT_MAP, &encrypt_key, &encrypt_value, BPF_ANY); 261 262 tail_call_static(ctx, entry_call_map, FROM_CONTAINER); 263 return TEST_ERROR; 264 } 265 266 CHECK("tc", "04_ipv4_from_lxc_new_remote_key") 267 int ipv4_from_lxc_new_remote_key_check(__maybe_unused const struct __ctx_buff *ctx) 268 { 269 void *data; 270 void *data_end; 271 __u32 *status_code; 272 273 test_init(); 274 275 data = (void *)(long)ctx->data; 276 data_end = (void *)(long)ctx->data_end; 277 278 if (data + sizeof(*status_code) > data_end) 279 test_fatal("status code out of bounds"); 280 281 status_code = data; 282 assert(*status_code == CTX_ACT_OK); 283 assert(ctx->mark == (NODE_ID << 16 | ENCRYPT_KEY << 12 | MARK_MAGIC_ENCRYPT)); 284 assert(ctx_load_meta(ctx, CB_ENCRYPT_IDENTITY) == SECLABEL_IPV4); 285 286 test_finish(); 287 } 288 289 PKTGEN("tc", "05_ipv6_from_lxc_encrypt") 290 int ipv6_from_lxc_encrypt_pktgen(struct __ctx_buff *ctx) 291 { 292 struct pktgen builder; 293 struct tcphdr *l4; 294 void *data; 295 296 pktgen__init(&builder, ctx); 297 298 l4 = pktgen__push_ipv6_tcp_packet(&builder, 299 (__u8 *)mac_one, (__u8 *)mac_two, 300 (__u8 *)v6_pod_one, (__u8 *)&v6_pod_two, 301 tcp_src_one, tcp_svc_one); 302 if (!l4) 303 return TEST_ERROR; 304 305 data = pktgen__push_data(&builder, default_data, sizeof(default_data)); 306 if (!data) 307 return TEST_ERROR; 308 309 pktgen__finish(&builder); 310 return 0; 311 } 312 313 SETUP("tc", "05_ipv6_from_lxc_encrypt") 314 int ipv6_from_lxc_encrypt_setup(struct __ctx_buff *ctx) 315 { 316 policy_add_egress_allow_all_entry(); 317 318 ipcache_v6_add_entry((union v6addr *)v6_pod_two, 0, 233, v4_node_two, ENCRYPT_KEY); 319 320 __u32 encrypt_key = 0; 321 struct encrypt_config encrypt_value = { .encrypt_key = ENCRYPT_KEY }; 322 323 map_update_elem(&ENCRYPT_MAP, &encrypt_key, &encrypt_value, BPF_ANY); 324 325 node_v4_add_entry(v4_node_two, NODE_ID, 0); 326 327 tail_call_static(ctx, entry_call_map, FROM_CONTAINER); 328 return TEST_ERROR; 329 } 330 331 CHECK("tc", "05_ipv6_from_lxc_encrypt") 332 int ipv6_from_lxc_encrypt_check(__maybe_unused const struct __ctx_buff *ctx) 333 { 334 void *data; 335 void *data_end; 336 __u32 *status_code; 337 struct ethhdr *l2; 338 struct ipv6hdr *l3; 339 struct tcphdr *l4; 340 __u8 *payload; 341 342 test_init(); 343 344 data = (void *)(long)ctx->data; 345 data_end = (void *)(long)ctx->data_end; 346 347 if (data + sizeof(*status_code) > data_end) 348 test_fatal("status code out of bounds"); 349 350 status_code = data; 351 assert(*status_code == CTX_ACT_OK); 352 assert(ctx->mark == (NODE_ID << 16 | ENCRYPT_KEY << 12 | MARK_MAGIC_ENCRYPT)); 353 assert(ctx_load_meta(ctx, CB_ENCRYPT_IDENTITY) == SECLABEL_IPV6); 354 355 l2 = data + sizeof(*status_code); 356 357 if ((void *)l2 + sizeof(struct ethhdr) > data_end) 358 test_fatal("l2 out of bounds"); 359 360 if (l2->h_proto != bpf_htons(ETH_P_IPV6)) 361 test_fatal("l2 proto hasn't been set to ETH_P_IPV6"); 362 363 if (memcmp(l2->h_source, (__u8 *)mac_one, ETH_ALEN) != 0) 364 test_fatal("src mac hasn't been set to source ep's mac"); 365 366 if (memcmp(l2->h_dest, (__u8 *)EXPECTED_DEST_MAC, ETH_ALEN) != 0) 367 test_fatal("dest mac hasn't been set to dest ep's mac"); 368 369 l3 = (void *)l2 + sizeof(struct ethhdr); 370 371 if ((void *)l3 + sizeof(struct ipv6hdr) > data_end) 372 test_fatal("l3 out of bounds"); 373 374 if (memcmp((__u8 *)&l3->saddr, (__u8 *)v6_pod_one, 16) != 0) 375 test_fatal("src IP was changed"); 376 377 if (memcmp((__u8 *)&l3->daddr, (__u8 *)v6_pod_two, 16) != 0) 378 test_fatal("dest IP was changed"); 379 380 l4 = (void *)l3 + sizeof(struct ipv6hdr); 381 382 if ((void *)l4 + sizeof(struct tcphdr) > data_end) 383 test_fatal("l4 out of bounds"); 384 385 if (l4->source != tcp_src_one) 386 test_fatal("src TCP port was changed"); 387 388 if (l4->dest != tcp_svc_one) 389 test_fatal("dst TCP port was changed"); 390 391 payload = (void *)l4 + sizeof(struct tcphdr); 392 if ((void *)payload + sizeof(default_data) > data_end) 393 test_fatal("paylaod out of bounds\n"); 394 395 if (memcmp(payload, default_data, sizeof(default_data)) != 0) 396 test_fatal("tcp payload was changed"); 397 test_finish(); 398 }