github.com/cilium/cilium@v1.16.2/bpf/tests/tc_lxc_lb6_no_backend.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  
     6  #include <bpf/ctx/skb.h>
     7  #include "pktgen.h"
     8  
     9  /* Set ETH_HLEN to 14 to indicate that the packet has a 14 byte ethernet header */
    10  #define ETH_HLEN 14
    11  
    12  /* Enable code paths under test */
    13  #define ENABLE_IPV6
    14  #undef ENABLE_PER_PACKET_LB
    15  #define SERVICE_NO_BACKEND_RESPONSE
    16  
    17  #define CLIENT_IP		v6_pod_one
    18  #define CLIENT_PORT		__bpf_htons(111)
    19  
    20  #define FRONTEND_IP		v6_pod_two
    21  #define FRONTEND_PORT		tcp_svc_one
    22  
    23  #define BACKEND_IP		v6_node_two
    24  #define BACKEND_PORT		__bpf_htons(8080)
    25  
    26  static volatile const __u8 *client_mac = mac_one;
    27  /* this matches the default node_config.h: */
    28  static volatile const __u8 lb_mac[ETH_ALEN] = { 0xce, 0x72, 0xa7, 0x03, 0x88, 0x56 };
    29  
    30  #include <bpf_lxc.c>
    31  
    32  #include "lib/ipcache.h"
    33  #include "lib/lb.h"
    34  
    35  #define FROM_CONTAINER	0
    36  
    37  struct {
    38  	__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
    39  	__uint(key_size, sizeof(__u32));
    40  	__uint(max_entries, 2);
    41  	__array(values, int());
    42  } entry_call_map __section(".maps") = {
    43  	.values = {
    44  		[FROM_CONTAINER] = &cil_from_container,
    45  	},
    46  };
    47  
    48  /* Test that a SVC without backends returns a TCP RST or ICMP error */
    49  PKTGEN("tc", "tc_lxc_no_backend")
    50  int lxc_no_backend_pktgen(struct __ctx_buff *ctx)
    51  {
    52  	struct pktgen builder;
    53  	struct tcphdr *l4;
    54  	void *data;
    55  
    56  	/* Init packet builder */
    57  	pktgen__init(&builder, ctx);
    58  
    59  	l4 = pktgen__push_ipv6_tcp_packet(&builder,
    60  					  (__u8 *)client_mac, (__u8 *)lb_mac,
    61  					  (__u8 *)CLIENT_IP,
    62  					  (__u8 *)FRONTEND_IP,
    63  					  tcp_src_one, tcp_svc_one);
    64  	if (!l4)
    65  		return TEST_ERROR;
    66  
    67  	data = pktgen__push_data(&builder, default_data, sizeof(default_data));
    68  	if (!data)
    69  		return TEST_ERROR;
    70  
    71  	/* Calc lengths, set protocol fields and calc checksums */
    72  	pktgen__finish(&builder);
    73  
    74  	return 0;
    75  }
    76  
    77  SETUP("tc", "tc_lxc_no_backend")
    78  int lxc_no_backend_setup(struct __ctx_buff *ctx)
    79  {
    80  	__u16 revnat_id = 1;
    81  
    82  	union v6addr frontend_ip = {};
    83  
    84  	memcpy(frontend_ip.addr, (void *)FRONTEND_IP, 16);
    85  
    86  	lb_v6_add_service(&frontend_ip, FRONTEND_PORT, 1, revnat_id);
    87  
    88  	union v6addr backend_ip = {};
    89  
    90  	memcpy(backend_ip.addr, (void *)BACKEND_IP, 16);
    91  
    92  	ipcache_v6_add_entry(&backend_ip, 0, 112233, 0, 0);
    93  
    94  	/* Jump into the entrypoint */
    95  	tail_call_static(ctx, entry_call_map, FROM_CONTAINER);
    96  
    97  	/* Fail if we didn't jump */
    98  	return TEST_ERROR;
    99  }
   100  
   101  CHECK("tc", "tc_lxc_no_backend")
   102  int lxc_no_backend_check(__maybe_unused const struct __ctx_buff *ctx)
   103  {
   104  	void *data, *data_end;
   105  	__u32 *status_code;
   106  	struct ethhdr *l2;
   107  	struct ipv6hdr *l3;
   108  	struct icmp6hdr *l4;
   109  
   110  	test_init();
   111  
   112  	data = (void *)(long)ctx_data(ctx);
   113  	data_end = (void *)(long)ctx->data_end;
   114  
   115  	if (data + sizeof(__u32) > data_end)
   116  		test_fatal("status code out of bounds");
   117  
   118  	status_code = data;
   119  
   120  	test_log("Status code: %d", *status_code);
   121  	assert(*status_code == CTX_ACT_REDIRECT);
   122  
   123  	l2 = data + sizeof(__u32);
   124  	if ((void *)l2 + sizeof(struct ethhdr) > data_end)
   125  		test_fatal("l2 header out of bounds");
   126  
   127  	assert(memcmp(l2->h_dest, (__u8 *)client_mac, sizeof(lb_mac)) == 0);
   128  	assert(memcmp(l2->h_source, (__u8 *)lb_mac, sizeof(lb_mac)) == 0);
   129  	assert(l2->h_proto == __bpf_htons(ETH_P_IPV6));
   130  
   131  	l3 = data + sizeof(__u32) + sizeof(struct ethhdr);
   132  	if ((void *)l3 + sizeof(struct ipv6hdr) > data_end)
   133  		test_fatal("l3 header out of bounds");
   134  
   135  	assert(l3->hop_limit == 64);
   136  	assert(l3->version == 6);
   137  	assert(l3->nexthdr == IPPROTO_ICMPV6);
   138  
   139  	l4 = data + sizeof(__u32) + sizeof(struct ethhdr) + sizeof(struct ipv6hdr);
   140  	if ((void *) l4 + sizeof(struct icmp6hdr) > data_end)
   141  		test_fatal("l4 header out of bounds");
   142  
   143  	assert(l4->icmp6_type == ICMPV6_DEST_UNREACH);
   144  	assert(l4->icmp6_code == ICMPV6_PORT_UNREACH);
   145  
   146  	/* reference checksum is calculated with wireshark by dumping the
   147  	 * context with the runner option and importing the packet into
   148  	 * wireshark
   149  	 */
   150  	assert(l4->icmp6_cksum == bpf_htons(0x7da8));
   151  
   152  	test_finish();
   153  }