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 }