1 /* 2 * Copyright (c) 2016-2024 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 #ifndef _SKYWALK_TEST_UTILS_H_ 29 #define _SKYWALK_TEST_UTILS_H_ 30 31 #include <skywalk/os_skywalk_private.h> 32 #include <netinet/in.h> 33 #include <netinet/ip.h> 34 #include <netinet/ip6.h> 35 #include <netinet/udp.h> 36 #include <netinet/tcp.h> 37 #include <stdbool.h> 38 #include <stdio.h> 39 40 41 typedef enum sktu_if_type { 42 SKTU_IFT_UTUN = 1, 43 SKTU_IFT_IPSEC = 2, 44 SKTU_IFT_FETH = 3, 45 } sktu_if_type_t; 46 47 #define SKTU_IFF_ENABLE_NETIF 0x00000001 // no-netif (txstart bsd interface) by default 48 #define SKTU_IFF_NO_ATTACH_FSW 0x00000002 // auto-attach fsw for netif by default 49 #define SKTU_IFF_ENABLE_CHANNEL 0x00000004 // auto-attach kpipe 50 typedef uint32_t sktu_if_flag_t; 51 52 typedef struct sktc_nexus_handles { 53 nexus_controller_t controller; 54 uuid_t fsw_prov_uuid; 55 uuid_t fsw_nx_uuid; 56 uuid_t fsw_nx_host_attach_uuid; 57 uuid_t fsw_nx_dev_attach_uuid; 58 uuid_t netif_prov_uuid; 59 uuid_t netif_nx_uuid; 60 uuid_t netif_nx_attach_uuid; 61 char netif_ifname[IFNAMSIZ]; 62 struct in_addr netif_addr; 63 struct in_addr netif_mask; 64 struct in6_addr netif_ip6_addr; 65 uint8_t netif_ip6_prefix_len; 66 } * sktu_nexus_t; 67 68 typedef struct ip_udp_hdr { 69 struct ip ip; 70 struct udphdr udp; 71 } ip_udp_header_t; 72 73 typedef struct ip6_udp_hdr { 74 struct ip6_hdr ip6; 75 struct udphdr udp; 76 } ip6_udp_header_t; 77 78 typedef struct udp_pseudo_hdr { 79 struct in_addr src_ip; 80 struct in_addr dst_ip; 81 char zero; 82 char proto; 83 unsigned short length; 84 } udp_pseudo_hdr_t; 85 86 struct ipv4_udp_pseudo_hdr { 87 struct in_addr src_ip; 88 struct in_addr dst_ip; 89 uint8_t zero; 90 uint8_t proto; 91 unsigned short length; 92 }; 93 94 struct ipv6_udp_pseudo_hdr { 95 struct in6_addr src_ip; 96 struct in6_addr dst_ip; 97 uint32_t length; 98 uint8_t zero[3]; 99 uint8_t proto; 100 }; 101 102 typedef struct tcp_pseudo_hdr { 103 struct in_addr src_ip; 104 struct in_addr dst_ip; 105 uint8_t zero; 106 uint8_t proto; 107 unsigned short length; 108 } tcp_pseudo_hdr_t; 109 110 struct ipv4_tcp_pseudo_hdr { 111 struct in_addr src_ip; 112 struct in_addr dst_ip; 113 uint8_t zero; 114 uint8_t proto; 115 uint16_t length; 116 }; 117 118 struct ipv6_tcp_pseudo_hdr { 119 struct in6_addr src_ip; 120 struct in6_addr dst_ip; 121 uint32_t length; 122 uint8_t zero[3]; 123 uint8_t proto; 124 }; 125 126 typedef struct { 127 struct ip ip; 128 struct tcphdr tcp; 129 } ip_tcp_header_t; 130 131 typedef union { 132 ip_udp_header_t udp; 133 ip_tcp_header_t tcp; 134 } ip_udp_tcp_header_u; 135 136 #define SKTU_MAX_MTU_PAYLOAD_LEN (1500 - (sizeof(struct ip6_hdr) + sizeof(struct tcphdr) - sizeof(uint32_t))) 137 typedef struct { 138 uint32_t packet_number; 139 char data[SKTU_MAX_MTU_PAYLOAD_LEN]; 140 } my_payload, *my_payload_t; 141 142 // sktu_frame is a universal container that holds packet buffer and metadata. 143 // It's used when packet_t isn't available (like for utun fd), or isn't 144 // available yet (like before packet gets allocated from channel). 145 #define SKTU_FRAME_BUF_SIZE (16 * 1024) 146 typedef struct sktu_frame { 147 // meta data 148 uuid_t flow_uuid; 149 150 bool csum_offload; 151 uint16_t csum_flags; 152 uint16_t csum_start; 153 uint16_t csum_stuff; 154 155 size_t len; 156 157 // data 158 char bytes[SKTU_FRAME_BUF_SIZE]; 159 } *sktu_frame_t; 160 161 typedef struct { 162 channel_t chan; 163 int fd; 164 nexus_port_t port; 165 channel_ring_t rx_ring; 166 channel_ring_t tx_ring; 167 struct in_addr ip_addr; 168 struct in6_addr ip6_addr; 169 struct ether_addr mac_addr; 170 boolean_t user_packet_pool; 171 } channel_port, *channel_port_t, *sktu_channel_port_t; 172 173 struct sktu_flow; 174 175 #define CSUM_OFFLOAD true 176 #define NO_CSUM_OFFLOAD false 177 178 struct sktu_flow_ops { 179 size_t (*create_input_frames)(struct sktu_flow *flow, 180 struct sktu_frame **frames, size_t max_frames, const void *data, 181 size_t data_len); 182 183 size_t (*create_output_frames)(struct sktu_flow *flow, 184 struct sktu_frame **frames, size_t max_frames, const void *data, 185 size_t data_len, bool csum_offload); 186 }; 187 188 typedef struct sktu_flow { 189 bool is_nexus_flow; 190 191 uint8_t ipver; 192 void *src_ip; 193 void *dst_ip; 194 size_t ip_addr_len; 195 uint16_t sport; 196 uint16_t dport; 197 uint8_t ip_protocol; 198 199 size_t mtu; 200 201 // nexus flow fields 202 struct nx_flow_req nfr; 203 sktu_nexus_t nexus; 204 nexus_port_t nx_port; 205 uuid_t uuid; 206 207 // socket flow fields 208 int sock_fd; 209 210 // ops 211 struct sktu_flow_ops _flow_ops; 212 #define create_input_frames _flow_ops.create_input_frames 213 #define create_output_frames _flow_ops.create_output_frames 214 } *sktu_nexus_flow_t; 215 216 channel_t 217 sktu_channel_create_extended(const uuid_t uuid, const nexus_port_t port, 218 const ring_dir_t dir, const ring_id_t rid, const channel_attr_t attr, 219 uint64_t exclusive, uint64_t txlowatunit, uint64_t txlowatval, 220 uint64_t rxlowatunit, uint64_t rxlowatval, uint64_t userpacketpool, 221 uint64_t defunctok, uint64_t event_ring, uint64_t low_latency); 222 void permutefuncP(int n, int *permute, void (*func)(int, int *permute)); 223 void permutefuncH(int n, int *permute, void (*func)(int, int *permute)); 224 void permutefuncR(int n, int *permute, void (*func)(int, int *permute), int total, unsigned seed); 225 void permutefuncZ(int n, int *permute, void (*func)(int, int *permute)); 226 227 void sktc_create_flowswitch(struct sktc_nexus_handles *handles, int i); 228 void sktc_create_flowswitch_no_address(struct sktc_nexus_handles *handles, 229 uint64_t tx_slots, uint64_t rx_slots, uint64_t buf_size, uint64_t max_frags, 230 uint64_t anonymous); 231 void sktc_nexus_handles_assign_address(struct sktc_nexus_handles *handles); 232 233 void sktc_cleanup_flowswitch(struct sktc_nexus_handles *handles); 234 int sktc_bind_tcp4_flow(nexus_controller_t ncd, const uuid_t fsw, in_port_t in_port, nexus_port_t nx_port, const uuid_t flow); 235 int sktc_unbind_flow(nexus_controller_t ncd, const uuid_t fsw, const uuid_t flow); 236 237 char * skt_nfr_print(struct nx_flow_req *nfr, char *buf, size_t buf_max); 238 239 struct sktu_flow * _sktu_create_nexus_flow(sktu_nexus_t nexus, 240 nexus_port_t nx_port, uint8_t af, void *src, void *dst, uint8_t proto, 241 uint16_t sport, uint16_t dport, uint32_t flags); 242 struct sktu_flow * sktu_create_nexus_flow(sktu_nexus_t nexus, uint8_t af, 243 void *src, void *dst, uint8_t proto, uint16_t sport, uint16_t dport); 244 struct sktu_flow * sktu_create_nexus_low_latency_flow(sktu_nexus_t nexus, 245 uint8_t af, void *src, void *dst, uint8_t proto, uint16_t sport, 246 uint16_t dport); 247 struct sktu_flow * sktu_create_nexus_flow_with_nx_port(sktu_nexus_t nexus, 248 nexus_port_t nx_port, uint8_t af, void *src, void *dst, uint8_t proto, 249 uint16_t sport, uint16_t dport); 250 void _sktu_destroy_nexus_flow(struct sktu_flow *flow); 251 #define sktu_destroy_nexus_flow(f) \ 252 do { \ 253 _sktu_destroy_nexus_flow(f); \ 254 f = NULL; \ 255 } while (0) 256 int sktu_get_nexus_flow_stats(uuid_t flow_uuid, struct sk_stats_flow *sf); 257 int sktu_get_nexus_flowswitch_stats(struct sk_stats_flow_switch **sfsw, size_t *len); 258 void __fsw_stats_print(struct fsw_stats *s); 259 260 uint32_t sktc_chew_random(channel_t channel, channel_ring_t ring, sync_mode_t mode, bool dosync, uint32_t avail); 261 void sktc_pump_ring_nslots_kq(channel_t channel, channel_ring_t ring, sync_mode_t mode, bool dosync, uint64_t nslots, bool verbose); 262 void sktc_pump_ring_nslots_select(channel_t channel, channel_ring_t ring, sync_mode_t mode, bool dosync, uint64_t nslots, bool verbose); 263 void sktc_pump_ring_nslots_poll(channel_t channel, channel_ring_t ring, sync_mode_t mode, bool dosync, uint64_t nslots, bool verbose); 264 265 void sktc_raise_file_limit(int new); 266 267 int sktu_create_interface(sktu_if_type_t type, sktu_if_flag_t flags); 268 channel_t sktu_create_interface_channel(sktu_if_type_t type, int tunsock); 269 void sktu_get_interface_name(sktu_if_type_t type, int s, char name[IFNAMSIZ]); 270 271 void sktu_dump_buffer(FILE *f, const char *title, const void *p, size_t len); 272 int sysctl_buf(char *oid_name, void **buffer, size_t *len, void *newp, size_t newlen); 273 uint32_t sktu_set_inject_error_rmask(uint32_t *); 274 boolean_t sktu_check_interface_ipv4_address(char *ifname, uint32_t ipaddr); 275 int sktu_create_pfkeysock(void); 276 void sktu_create_sa(int keysock, const char ifname[IFXNAMSIZ], uint32_t spi, 277 struct in_addr *src, struct in_addr *dst); 278 279 extern unsigned short in_cksum(void * pkt, int len, int sum0); 280 extern uint16_t in_pseudo(uint32_t a, uint32_t b, uint32_t c); 281 extern uint16_t in6_pseudo(const struct in6_addr *src, const struct in6_addr *dst, uint32_t x); 282 283 extern void sktu_channel_port_init(channel_port_t ch_port, uuid_t instance, 284 nexus_port_t nx_port, bool enable_upp, bool enable_event_ring, bool low_latency); 285 286 extern void skt_channel_port_send(channel_port_t port, uuid_t flow_id, 287 int protocol, uint16_t src_port, struct in_addr dst_ip, uint16_t dst_port, 288 my_payload_t payload, int payload_length, uint32_t limit, 289 boolean_t must_complete_batch, boolean_t connect, 290 packet_svc_class_t svc_class, boolean_t csum_offload, 291 void (^packet_prehook)(packet_t p)); 292 293 extern void skt_channel_port_receive(int child, channel_port_t port, 294 uint16_t our_port, struct in_addr peer_ip, uint32_t limit, 295 uint32_t *receive_count, uint32_t *receive_index, boolean_t errors_ok, 296 uint32_t * pkts_dropped); 297 298 extern void sktu_channel_port_tx_bulk(channel_port_t port, 299 struct sktu_frame **frames, uint32_t n); 300 301 extern packet_t sktu_channel_port_frame_to_pkt(channel_port_t port, 302 struct sktu_frame *frame); 303 extern uint32_t sktu_channel_port_tx_burst_pkt(channel_port_t port, 304 packet_t *frames, uint32_t n); 305 extern uint32_t sktu_channel_port_rx_burst(channel_port_t port, 306 struct sktu_frame **frames, uint32_t n); 307 extern uint32_t sktu_channel_port_tx_burst(channel_port_t port, 308 struct sktu_frame **frames, uint32_t n); 309 310 extern uint32_t sktu_utun_fd_rx_burst(int utun_fd, struct sktu_frame **frames, 311 uint32_t n); 312 313 extern void sktu_utun_fd_tx_burst(int utun_fd, struct sktu_frame **frames, 314 uint32_t n); 315 316 extern struct sktu_frame * sktu_frame_alloc(); 317 #define sktu_frame_free(frame) \ 318 do { \ 319 free(frame); \ 320 frame = NULL; \ 321 } while (0) 322 323 extern void sktu_frames_free(struct sktu_frame **frames, size_t n); 324 325 extern size_t sktu_create_ip_frames(struct sktu_frame **frames, size_t n, 326 void *src_ip, void *dst_ip, uint8_t proto, const void *sdu, size_t sdu_len, 327 size_t mtu, uint16_t csum_flags, uint16_t csum_start, uint16_t csum_stuff); 328 extern size_t sktu_create_ip6_frames(struct sktu_frame **frames, size_t n, 329 void *src_ip, void *dst_ip, uint8_t proto, const void *sdu, size_t sdu_len, 330 size_t mtu, uint16_t csum_flags, uint16_t csum_start, uint16_t csum_stuff); 331 extern size_t sktu_create_tcp_frames(struct sktu_frame **frames, size_t n, 332 uint8_t ipver, void *src_ip, void *dst_ip, uint16_t sport, uint16_t dport, 333 const void *data, size_t data_len, size_t mtu, bool csum_offload); 334 extern size_t sktu_create_udp_frames(struct sktu_frame **frames, size_t n, 335 uint8_t ipver, void *src_ip, void *dst_ip, uint16_t sport, uint16_t dport, 336 const void *data, size_t data_len, size_t mtu, bool csum_offload); 337 338 extern int sktu_parse_ipv4_frame(struct sktu_frame *frame, void *ip_payload, 339 uint32_t *ip_payload_len); 340 extern int sktu_parse_tcp4_frame(struct sktu_frame *frame, void *tcp_payload, 341 uint32_t *tcp_payload_len); 342 extern int sktu_parse_udp4_frame(struct sktu_frame *frame, void *udp_payload, 343 uint32_t *udp_payload_len); 344 345 #endif /* _SKYWALK_TEST_UTILS_H_ */ 346