github.com/cilium/cilium@v1.16.2/bpf/tests/tc_nodeport_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 #define ENABLE_NODEPORT 15 #define SERVICE_NO_BACKEND_RESPONSE 16 17 #define DISABLE_LOOPBACK_LB 18 19 #define CLIENT_IP v6_pod_one 20 #define CLIENT_PORT __bpf_htons(111) 21 22 #define FRONTEND_IP v6_pod_two 23 #define FRONTEND_PORT tcp_svc_one 24 25 #define BACKEND_IP v6_node_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_ipv6_tcp_packet(&builder, 64 (__u8 *)client_mac, (__u8 *)lb_mac, 65 (__u8 *)CLIENT_IP, 66 (__u8 *)FRONTEND_IP, 67 tcp_src_one, tcp_svc_one); 68 if (!l4) 69 return TEST_ERROR; 70 71 data = pktgen__push_data(&builder, default_data, sizeof(default_data)); 72 if (!data) 73 return TEST_ERROR; 74 75 /* Calc lengths, set protocol fields and calc checksums */ 76 pktgen__finish(&builder); 77 78 return 0; 79 } 80 81 SETUP("tc", "tc_nodeport_no_backend") 82 int nodeport_no_backend_setup(struct __ctx_buff *ctx) 83 { 84 __u16 revnat_id = 1; 85 86 union v6addr frontend_ip = {}; 87 88 memcpy(frontend_ip.addr, (void *)FRONTEND_IP, 16); 89 90 lb_v6_add_service(&frontend_ip, FRONTEND_PORT, 1, revnat_id); 91 92 union v6addr backend_ip = {}; 93 94 memcpy(backend_ip.addr, (void *)BACKEND_IP, 16); 95 96 ipcache_v6_add_entry(&backend_ip, 0, 112233, 0, 0); 97 98 /* Jump into the entrypoint */ 99 tail_call_static(ctx, entry_call_map, FROM_NETDEV); 100 101 /* Fail if we didn't jump */ 102 return TEST_ERROR; 103 } 104 105 CHECK("tc", "tc_nodeport_no_backend") 106 int nodeport_no_backend_check(__maybe_unused const struct __ctx_buff *ctx) 107 { 108 void *data, *data_end; 109 __u32 *status_code; 110 struct ethhdr *l2; 111 struct ipv6hdr *l3; 112 struct icmp6hdr *l4; 113 struct ratelimit_value *value; 114 115 test_init(); 116 117 data = (void *)(long)ctx_data(ctx); 118 data_end = (void *)(long)ctx->data_end; 119 120 if (data + sizeof(__u32) > data_end) 121 test_fatal("status code out of bounds"); 122 123 status_code = data; 124 125 test_log("Status code: %d", *status_code); 126 assert(*status_code == CTX_ACT_REDIRECT); 127 128 l2 = data + sizeof(__u32); 129 if ((void *)l2 + sizeof(struct ethhdr) > data_end) 130 test_fatal("l2 header out of bounds"); 131 132 assert(memcmp(l2->h_dest, (__u8 *)client_mac, sizeof(lb_mac)) == 0); 133 assert(memcmp(l2->h_source, (__u8 *)lb_mac, sizeof(lb_mac)) == 0); 134 assert(l2->h_proto == __bpf_htons(ETH_P_IPV6)); 135 136 l3 = data + sizeof(__u32) + sizeof(struct ethhdr); 137 if ((void *)l3 + sizeof(struct ipv6hdr) > data_end) 138 test_fatal("l3 header out of bounds"); 139 140 assert(l3->hop_limit == 64); 141 assert(l3->version == 6); 142 assert(l3->nexthdr == IPPROTO_ICMPV6); 143 144 l4 = data + sizeof(__u32) + sizeof(struct ethhdr) + sizeof(struct ipv6hdr); 145 if ((void *) l4 + sizeof(struct icmp6hdr) > data_end) 146 test_fatal("l4 header out of bounds"); 147 148 assert(l4->icmp6_type == ICMPV6_DEST_UNREACH); 149 assert(l4->icmp6_code == ICMPV6_PORT_UNREACH); 150 151 /* reference checksum is calculated with wireshark by dumping the 152 * context with the runner option and importing the packet into 153 * wireshark 154 */ 155 assert(l4->icmp6_cksum == bpf_htons(0x7da8)); 156 157 struct ratelimit_key key = { 158 .netdev_idx = 1, 159 }; 160 161 value = map_lookup_elem(&RATELIMIT_MAP, &key); 162 if (!value) 163 test_fatal("ratelimit map lookup failed"); 164 165 assert(value->tokens > 0); 166 167 test_finish(); 168 }