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 }