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