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  }