github.com/cilium/cilium@v1.16.2/bpf/tests/ipv6_ndp_from_netdev_test.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  #include <bpf/ctx/skb.h>
     6  #include "pktgen.h"
     7  #define ROUTER_IP
     8  #define HOST_IP
     9  #undef ROUTER_IP
    10  #undef HOST_IP
    11  
    12  #define ENABLE_IPV4
    13  #define ENABLE_IPV6
    14  #define SECCTX_FROM_IPCACHE 1
    15  
    16  #include "bpf_host.c"
    17  
    18  #include "lib/ipcache.h"
    19  #include "lib/endpoint.h"
    20  
    21  #define FROM_NETDEV 0
    22  
    23  struct {
    24  	__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
    25  	__uint(key_size, sizeof(__u32));
    26  	__uint(max_entries, 1);
    27  	__array(values, int());
    28  } entry_call_map __section(".maps") = {
    29  	.values = {
    30  		[FROM_NETDEV] = &cil_from_netdev,
    31  	},
    32  };
    33  
    34  PKTGEN("tc", "01_ipv6_from_netdev_ns_for_pod")
    35  int ipv6_from_netdev_ns_for_pod_pktgen(struct __ctx_buff *ctx)
    36  {
    37  	struct pktgen builder;
    38  	struct icmp6hdr *l4;
    39  	void *data;
    40  
    41  	pktgen__init(&builder, ctx);
    42  
    43  	l4 = pktgen__push_ipv6_icmp6_packet(&builder,
    44  					    (__u8 *)mac_one, (__u8 *)mac_two,
    45  					    (__u8 *)v6_pod_one, (__u8 *)v6_pod_two,
    46  					    ICMP6_NS_MSG_TYPE);
    47  	if (!l4)
    48  		return TEST_ERROR;
    49  
    50  	data = pktgen__push_data(&builder, (__u8 *)v6_pod_three, 16);
    51  	if (!data)
    52  		return TEST_ERROR;
    53  
    54  	__u8 options[] = {0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1};
    55  
    56  	data = pktgen__push_data(&builder, (__u8 *)options, 8);
    57  
    58  	pktgen__finish(&builder);
    59  	return 0;
    60  }
    61  
    62  SETUP("tc", "01_ipv6_from_netdev_ns_for_pod")
    63  int ipv6_from_netdev_ns_for_pod_setup(struct __ctx_buff *ctx)
    64  {
    65  	endpoint_v6_add_entry((union v6addr *)v6_pod_three, 0, 0, 0, 0,
    66  			      (__u8 *)mac_three, (__u8 *)mac_two);
    67  	tail_call_static(ctx, entry_call_map, FROM_NETDEV);
    68  	return TEST_ERROR;
    69  }
    70  
    71  CHECK("tc", "01_ipv6_from_netdev_ns_for_pod")
    72  int ipv6_from_netdev_ns_for_pod_check(const struct __ctx_buff *ctx)
    73  {
    74  	void *data;
    75  	void *data_end;
    76  	__u32 *status_code;
    77  	struct ethhdr *l2;
    78  	struct ipv6hdr *l3;
    79  	struct icmp6hdr *l4;
    80  	void *payload;
    81  
    82  	test_init();
    83  
    84  	data = (void *)(long)ctx->data;
    85  	data_end = (void *)(long)ctx->data_end;
    86  
    87  	if (data + sizeof(*status_code) > data_end)
    88  		test_fatal("status code out of bounds");
    89  
    90  	status_code = data;
    91  	printk("status_code: %d\n", *status_code);
    92  	assert(*status_code == CTX_ACT_REDIRECT);
    93  
    94  	l2 = data + sizeof(*status_code);
    95  
    96  	if ((void *)l2 + sizeof(struct ethhdr) > data_end)
    97  		test_fatal("l2 out of bounds");
    98  
    99  	if (l2->h_proto != bpf_htons(ETH_P_IPV6))
   100  		test_fatal("l2 proto hasn't been set to ETH_P_IP");
   101  
   102  	union macaddr node_mac = THIS_INTERFACE_MAC;
   103  
   104  	if (memcmp(l2->h_source, (__u8 *)&node_mac.addr, ETH_ALEN) != 0)
   105  		test_fatal("src mac hasn't been set to node mac");
   106  
   107  	if (memcmp(l2->h_dest, (__u8 *)mac_one, ETH_ALEN) != 0)
   108  		test_fatal("dest mac hasn't been set to source mac");
   109  
   110  	l3 = (void *)l2 + sizeof(struct ethhdr);
   111  
   112  	if ((void *)l3 + sizeof(struct ipv6hdr) > data_end)
   113  		test_fatal("l3 out of bounds");
   114  
   115  	union v6addr router_ip;
   116  
   117  	BPF_V6(router_ip, ROUTER_IP);
   118  	if (memcmp((__u8 *)&l3->saddr, (__u8 *)&router_ip, 16) != 0)
   119  		test_fatal("src IP hasn't been set to router IP");
   120  
   121  	if (memcmp((__u8 *)&l3->daddr, (__u8 *)v6_pod_one, 16) != 0)
   122  		test_fatal("dest IP hasn't been set to source IP");
   123  
   124  	l4 = (void *)l3 + sizeof(struct ipv6hdr);
   125  
   126  	if ((void *)l4 + sizeof(struct icmp6hdr) > data_end)
   127  		test_fatal("l4 out of bounds");
   128  
   129  	if (l4->icmp6_type != ICMP6_NA_MSG_TYPE)
   130  		test_fatal("icmp6 type hasn't been set to ICMP6_NA_MSG_TYPE");
   131  
   132  	payload = (void *)l4 + sizeof(struct icmp6hdr);
   133  	if ((void *)payload + 24 > data_end)
   134  		test_fatal("payload out of bounds");
   135  
   136  	void *target = payload;
   137  
   138  	if (memcmp(target, (__u8 *)v6_pod_three, 16) != 0)
   139  		test_fatal("icmp6 payload target hasn't been set properly");
   140  
   141  	void *target_lladdr = payload + 16 + 2;
   142  
   143  	if (memcmp(target_lladdr, (__u8 *)&node_mac.addr, ETH_ALEN) != 0)
   144  		test_fatal("icmp6 payload target_lladdr hasn't been set properly");
   145  
   146  	test_finish();
   147  }
   148  
   149  PKTGEN("tc", "02_ipv6_from_netdev_ns_for_node_ip")
   150  int ipv6_from_netdev_ns_for_node_ip_pktgen(struct __ctx_buff *ctx)
   151  {
   152  	struct pktgen builder;
   153  	struct icmp6hdr *l4;
   154  	void *data;
   155  
   156  	pktgen__init(&builder, ctx);
   157  
   158  	l4 = pktgen__push_ipv6_icmp6_packet(&builder,
   159  					    (__u8 *)mac_one, (__u8 *)mac_two,
   160  					    (__u8 *)v6_pod_one, (__u8 *)v6_pod_two,
   161  					    ICMP6_NS_MSG_TYPE);
   162  	if (!l4)
   163  		return TEST_ERROR;
   164  
   165  	union v6addr node_ip;
   166  
   167  	BPF_V6(node_ip, HOST_IP);
   168  	data = pktgen__push_data(&builder, (__u8 *)&node_ip, 16);
   169  	if (!data)
   170  		return TEST_ERROR;
   171  
   172  	__u8 options[] = {0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1};
   173  
   174  	data = pktgen__push_data(&builder, (__u8 *)options, 8);
   175  
   176  	pktgen__finish(&builder);
   177  	return 0;
   178  }
   179  
   180  SETUP("tc", "02_ipv6_from_netdev_ns_for_node_ip")
   181  int ipv6_from_netdev_ns_for_node_ip_setup(struct __ctx_buff *ctx)
   182  {
   183  	union v6addr node_ip;
   184  
   185  	BPF_V6(node_ip, HOST_IP);
   186  	endpoint_v6_add_entry((union v6addr *)&node_ip, 0, 0, ENDPOINT_F_HOST, 0,
   187  			      (__u8 *)mac_three, (__u8 *)mac_two);
   188  	tail_call_static(ctx, entry_call_map, FROM_NETDEV);
   189  	return TEST_ERROR;
   190  }
   191  
   192  CHECK("tc", "02_ipv6_from_netdev_ns_for_node_ip")
   193  int ipv6_from_netdev_ns_for_node_ip_check(const struct __ctx_buff *ctx)
   194  {
   195  	void *data;
   196  	void *data_end;
   197  	__u32 *status_code;
   198  	struct ethhdr *l2;
   199  	struct ipv6hdr *l3;
   200  	struct icmp6hdr *l4;
   201  	void *payload;
   202  
   203  	test_init();
   204  
   205  	data = (void *)(long)ctx->data;
   206  	data_end = (void *)(long)ctx->data_end;
   207  
   208  	if (data + sizeof(*status_code) > data_end)
   209  		test_fatal("status code out of bounds");
   210  
   211  	status_code = data;
   212  	printk("status_code: %d\n", *status_code);
   213  	assert(*status_code == CTX_ACT_OK);
   214  
   215  	l2 = data + sizeof(*status_code);
   216  	if ((void *)l2 + sizeof(struct ethhdr) > data_end)
   217  		test_fatal("l2 out of bounds");
   218  
   219  	if (l2->h_proto != bpf_htons(ETH_P_IPV6))
   220  		test_fatal("l2 proto hasn't been set to ETH_P_IP");
   221  
   222  	if (memcmp(l2->h_source, (__u8 *)mac_one, ETH_ALEN) != 0)
   223  		test_fatal("src mac hasn't been set to source ep's mac");
   224  
   225  	if (memcmp(l2->h_dest, (__u8 *)mac_two, ETH_ALEN) != 0)
   226  		test_fatal("dest mac hasn't been set to dest ep's mac");
   227  
   228  	l3 = (void *)l2 + sizeof(struct ethhdr);
   229  
   230  	if ((void *)l3 + sizeof(struct ipv6hdr) > data_end)
   231  		test_fatal("l3 out of bounds");
   232  
   233  	if (memcmp((__u8 *)&l3->saddr, (__u8 *)v6_pod_one, 16) != 0)
   234  		test_fatal("src IP was changed");
   235  
   236  	if (memcmp((__u8 *)&l3->daddr, (__u8 *)v6_pod_two, 16) != 0)
   237  		test_fatal("dest IP was changed");
   238  
   239  	l4 = (void *)l3 + sizeof(struct ipv6hdr);
   240  
   241  	if ((void *)l4 + sizeof(struct icmp6hdr) > data_end)
   242  		test_fatal("l4 out of bounds");
   243  
   244  	if (l4->icmp6_type != ICMP6_NS_MSG_TYPE)
   245  		test_fatal("icmp6 type was changed");
   246  
   247  	payload = (void *)l4 + sizeof(struct icmp6hdr);
   248  	if ((void *)payload + 24 > data_end)
   249  		test_fatal("payload out of bounds");
   250  
   251  	union v6addr node_ip;
   252  
   253  	BPF_V6(node_ip, HOST_IP);
   254  	if (memcmp(payload, (__u8 *)&node_ip, 16) != 0)
   255  		test_fatal("icmp6 payload target was changed");
   256  
   257  	test_finish();
   258  }