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  }