github.com/cilium/cilium@v1.16.2/bpf/tests/xdp_nodeport_lb4_nat_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/xdp.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 ENABLE_NODEPORT_ACCELERATION
    16  
    17  #define DISABLE_LOOPBACK_LB
    18  
    19  /* Skip ingress policy checks, not needed to validate hairpin flow */
    20  #define USE_BPF_PROG_FOR_INGRESS_POLICY
    21  #undef FORCE_LOCAL_POLICY_EVAL_AT_SOURCE
    22  
    23  #define CLIENT_IP		v4_ext_one
    24  #define CLIENT_PORT		__bpf_htons(111)
    25  
    26  #define FRONTEND_IP		v4_svc_one
    27  #define FRONTEND_PORT		tcp_svc_one
    28  
    29  #define LB_IP			v4_node_one
    30  #define LB_PORT			__bpf_htons(222)
    31  
    32  #define BACKEND_IP		v4_pod_one
    33  #define BACKEND_PORT		__bpf_htons(8080)
    34  
    35  #include <bpf_xdp.c>
    36  
    37  #include "lib/endpoint.h"
    38  #include "lib/ipcache.h"
    39  #include "lib/lb.h"
    40  
    41  static volatile const __u8 *client_mac = mac_one;
    42  static volatile const __u8 *lb_mac = mac_two;
    43  
    44  #define FROM_XDP	0
    45  
    46  struct {
    47  	__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
    48  	__uint(key_size, sizeof(__u32));
    49  	__uint(max_entries, 1);
    50  	__array(values, int());
    51  } entry_call_map __section(".maps") = {
    52  	.values = {
    53  		[FROM_XDP] = &cil_xdp_entry,
    54  	},
    55  };
    56  
    57  /* Test that a remote LB
    58   * - doesn't touch a NATed request,
    59   * - passes it up from XDP to TC
    60   */
    61  PKTGEN("xdp", "xdp_nodeport_nat_backend")
    62  int nodeport_nat_backend_pktgen(struct __ctx_buff *ctx)
    63  {
    64  	struct pktgen builder;
    65  	struct tcphdr *l4;
    66  	void *data;
    67  
    68  	/* Init packet builder */
    69  	pktgen__init(&builder, ctx);
    70  
    71  	l4 = pktgen__push_ipv4_tcp_packet(&builder,
    72  					  (__u8 *)client_mac, (__u8 *)lb_mac,
    73  					  LB_IP, BACKEND_IP,
    74  					  LB_PORT, BACKEND_PORT);
    75  	if (!l4)
    76  		return TEST_ERROR;
    77  
    78  	data = pktgen__push_data(&builder, default_data, sizeof(default_data));
    79  	if (!data)
    80  		return TEST_ERROR;
    81  
    82  	/* Calc lengths, set protocol fields and calc checksums */
    83  	pktgen__finish(&builder);
    84  
    85  	return 0;
    86  }
    87  
    88  SETUP("xdp", "xdp_nodeport_nat_backend")
    89  int nodeport_nat_backend_setup(struct __ctx_buff *ctx)
    90  {
    91  	lb_v4_add_service(FRONTEND_IP, FRONTEND_PORT, 1, 1);
    92  	lb_v4_add_backend(FRONTEND_IP, FRONTEND_PORT, 1, 124,
    93  			  BACKEND_IP, BACKEND_PORT, IPPROTO_TCP, 0);
    94  
    95  	/* add local backend */
    96  	endpoint_v4_add_entry(BACKEND_IP, 0, 0, 0, 0, NULL, NULL);
    97  
    98  	ipcache_v4_add_entry(BACKEND_IP, 0, 112233, 0, 0);
    99  
   100  	/* Jump into the entrypoint */
   101  	tail_call_static(ctx, entry_call_map, FROM_XDP);
   102  	/* Fail if we didn't jump */
   103  	return TEST_ERROR;
   104  }
   105  
   106  CHECK("xdp", "xdp_nodeport_nat_backend")
   107  int nodeport_nat_backend_check(__maybe_unused const struct __ctx_buff *ctx)
   108  {
   109  	void *data, *data_end;
   110  	__u32 *status_code;
   111  	struct tcphdr *l4;
   112  	struct ethhdr *l2;
   113  	struct iphdr *l3;
   114  	__u32 *meta;
   115  
   116  	test_init();
   117  
   118  	data = (void *)(long)ctx_data(ctx);
   119  	data_end = (void *)(long)ctx->data_end;
   120  
   121  	status_code = data;
   122  	if (data + sizeof(__u32) > data_end)
   123  		test_fatal("status code out of bounds");
   124  
   125  	meta = (void *)status_code + sizeof(__u32);
   126  	if ((void *)meta + sizeof(__u32) > data_end)
   127  		test_fatal("meta out of bounds");
   128  
   129  	l2 = (void *)meta + sizeof(__u32);
   130  	if ((void *)l2 + sizeof(struct ethhdr) > data_end)
   131  		test_fatal("l2 out of bounds");
   132  
   133  	l3 = (void *)l2 + sizeof(struct ethhdr);
   134  	if ((void *)l3 + sizeof(struct iphdr) > data_end)
   135  		test_fatal("l3 out of bounds");
   136  
   137  	l4 = (void *)l3 + sizeof(struct iphdr);
   138  	if ((void *)l4 + sizeof(struct tcphdr) > data_end)
   139  		test_fatal("l4 out of bounds");
   140  
   141  	assert(*status_code == CTX_ACT_OK);
   142  
   143  	assert((*meta & XFER_PKT_NO_SVC) == XFER_PKT_NO_SVC);
   144  
   145  	if (memcmp(l2->h_source, (__u8 *)client_mac, ETH_ALEN) != 0)
   146  		test_fatal("src MAC is not the client MAC")
   147  	if (memcmp(l2->h_dest, (__u8 *)lb_mac, ETH_ALEN) != 0)
   148  		test_fatal("dst MAC is not the LB MAC")
   149  
   150  	if (l3->saddr != LB_IP)
   151  		test_fatal("src IP has changed");
   152  
   153  	if (l3->daddr != BACKEND_IP)
   154  		test_fatal("dst IP has changed");
   155  
   156  	if (l3->check != bpf_htons(0xa612))
   157  		test_fatal("L3 checksum is invalid: %d", bpf_htons(l3->check));
   158  
   159  	if (l4->source != LB_PORT)
   160  		test_fatal("src port has changed");
   161  
   162  	if (l4->dest != BACKEND_PORT)
   163  		test_fatal("dst port has changed");
   164  
   165  	test_finish();
   166  }