github.com/cilium/cilium@v1.16.2/bpf/tests/tc_nodeport_lb4_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_IPV4
    14  #define ENABLE_NODEPORT
    15  #define SERVICE_NO_BACKEND_RESPONSE
    16  
    17  #define DISABLE_LOOPBACK_LB
    18  
    19  #define CLIENT_IP		v4_ext_one
    20  #define CLIENT_PORT		__bpf_htons(111)
    21  
    22  #define FRONTEND_IP		v4_svc_two
    23  #define FRONTEND_PORT		tcp_svc_one
    24  
    25  #define BACKEND_IP		v4_pod_two
    26  #define BACKEND_PORT		__bpf_htons(8080)
    27  
    28  static volatile const __u8 *client_mac = mac_one;
    29  /* this matches the default node_config.h: */
    30  static volatile const __u8 lb_mac[ETH_ALEN] = { 0xce, 0x72, 0xa7, 0x03, 0x88, 0x56 };
    31  
    32  #include <bpf_host.c>
    33  
    34  #include "lib/ipcache.h"
    35  #include "lib/lb.h"
    36  
    37  #define FROM_NETDEV	0
    38  #define TO_NETDEV	1
    39  
    40  struct {
    41  	__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
    42  	__uint(key_size, sizeof(__u32));
    43  	__uint(max_entries, 2);
    44  	__array(values, int());
    45  } entry_call_map __section(".maps") = {
    46  	.values = {
    47  		[FROM_NETDEV] = &cil_from_netdev,
    48  		[TO_NETDEV] = &cil_to_netdev,
    49  	},
    50  };
    51  
    52  /* Test that a SVC without backends returns a TCP RST or ICMP error */
    53  PKTGEN("tc", "tc_nodeport_no_backend")
    54  int nodeport_no_backend_pktgen(struct __ctx_buff *ctx)
    55  {
    56  	struct pktgen builder;
    57  	struct tcphdr *l4;
    58  	void *data;
    59  
    60  	/* Init packet builder */
    61  	pktgen__init(&builder, ctx);
    62  
    63  	l4 = pktgen__push_ipv4_tcp_packet(&builder,
    64  					  (__u8 *)client_mac, (__u8 *)lb_mac,
    65  					  CLIENT_IP, FRONTEND_IP,
    66  					  CLIENT_PORT, FRONTEND_PORT);
    67  	if (!l4)
    68  		return TEST_ERROR;
    69  
    70  	data = pktgen__push_data(&builder, default_data, sizeof(default_data));
    71  	if (!data)
    72  		return TEST_ERROR;
    73  
    74  	/* Calc lengths, set protocol fields and calc checksums */
    75  	pktgen__finish(&builder);
    76  
    77  	return 0;
    78  }
    79  
    80  SETUP("tc", "tc_nodeport_no_backend")
    81  int nodeport_no_backend_setup(struct __ctx_buff *ctx)
    82  {
    83  	__u16 revnat_id = 1;
    84  
    85  	lb_v4_add_service(FRONTEND_IP, FRONTEND_PORT, 1, revnat_id);
    86  
    87  	ipcache_v4_add_entry(BACKEND_IP, 0, 112233, 0, 0);
    88  
    89  	/* Jump into the entrypoint */
    90  	tail_call_static(ctx, entry_call_map, FROM_NETDEV);
    91  
    92  	/* Fail if we didn't jump */
    93  	return TEST_ERROR;
    94  }
    95  
    96  CHECK("tc", "tc_nodeport_no_backend")
    97  int nodeport_no_backend_check(__maybe_unused const struct __ctx_buff *ctx)
    98  {
    99  	void *data, *data_end;
   100  	__u32 *status_code;
   101  	struct ethhdr *l2;
   102  	struct iphdr *l3;
   103  	struct icmphdr *l4;
   104  
   105  	test_init();
   106  
   107  	data = (void *)(long)ctx_data(ctx);
   108  	data_end = (void *)(long)ctx->data_end;
   109  
   110  	if (data + sizeof(__u32) > data_end)
   111  		test_fatal("status code out of bounds");
   112  
   113  	status_code = data;
   114  
   115  	test_log("Status code: %d", *status_code);
   116  	assert(*status_code == CTX_ACT_REDIRECT);
   117  
   118  	l2 = data + sizeof(__u32);
   119  	if ((void *)l2 + sizeof(struct ethhdr) > data_end)
   120  		test_fatal("l2 header out of bounds");
   121  
   122  	assert(memcmp(l2->h_dest, (__u8 *)client_mac, sizeof(lb_mac)) == 0);
   123  	assert(memcmp(l2->h_source, (__u8 *)lb_mac, sizeof(lb_mac)) == 0);
   124  	assert(l2->h_proto == __bpf_htons(ETH_P_IP));
   125  
   126  	l3 = data + sizeof(__u32) + sizeof(struct ethhdr);
   127  	if ((void *)l3 + sizeof(struct iphdr) > data_end)
   128  		test_fatal("l3 header out of bounds");
   129  
   130  	assert(l3->ihl == 5);
   131  	assert(l3->version == 4);
   132  	assert(l3->tos == 0);
   133  	assert(l3->ttl == 64);
   134  	assert(l3->protocol == IPPROTO_ICMP);
   135  
   136  	if (l3->check != bpf_htons(0x4b8e))
   137  		test_fatal("L3 checksum is invalid: %d", bpf_htons(l3->check));
   138  
   139  	l4 = data + sizeof(__u32) + sizeof(struct ethhdr) + sizeof(struct iphdr);
   140  	if ((void *) l4 + sizeof(struct icmphdr) > data_end)
   141  		test_fatal("l4 header out of bounds");
   142  
   143  	assert(l4->type == ICMP_DEST_UNREACH);
   144  	assert(l4->code == ICMP_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->checksum == bpf_htons(0x2de7));
   151  
   152  	test_finish();
   153  }