xref: /xnu-11215.81.4/tests/skywalk/skywalk_test_utils.h (revision d4514f0bc1d3f944c22d92e68b646ac3fb40d452)
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 typedef uint32_t sktu_if_flag_t;
50 
51 typedef struct sktc_nexus_handles {
52 	nexus_controller_t controller;
53 	uuid_t fsw_prov_uuid;
54 	uuid_t fsw_nx_uuid;
55 	uuid_t fsw_nx_host_attach_uuid;
56 	uuid_t fsw_nx_dev_attach_uuid;
57 	uuid_t netif_prov_uuid;
58 	uuid_t netif_nx_uuid;
59 	uuid_t netif_nx_attach_uuid;
60 	char netif_ifname[IFNAMSIZ];
61 	struct in_addr netif_addr;
62 	struct in_addr netif_mask;
63 	struct in6_addr netif_ip6_addr;
64 	uint8_t netif_ip6_prefix_len;
65 } * sktu_nexus_t;
66 
67 typedef struct ip_udp_hdr {
68 	struct ip       ip;
69 	struct udphdr   udp;
70 } ip_udp_header_t;
71 
72 typedef struct ip6_udp_hdr {
73 	struct ip6_hdr  ip6;
74 	struct udphdr   udp;
75 } ip6_udp_header_t;
76 
77 typedef struct udp_pseudo_hdr {
78 	struct in_addr  src_ip;
79 	struct in_addr  dst_ip;
80 	char            zero;
81 	char            proto;
82 	unsigned short  length;
83 } udp_pseudo_hdr_t;
84 
85 struct ipv4_udp_pseudo_hdr {
86 	struct in_addr  src_ip;
87 	struct in_addr  dst_ip;
88 	uint8_t         zero;
89 	uint8_t         proto;
90 	unsigned short  length;
91 };
92 
93 struct ipv6_udp_pseudo_hdr {
94 	struct in6_addr src_ip;
95 	struct in6_addr dst_ip;
96 	uint32_t        length;
97 	uint8_t         zero[3];
98 	uint8_t         proto;
99 };
100 
101 typedef struct tcp_pseudo_hdr {
102 	struct in_addr  src_ip;
103 	struct in_addr  dst_ip;
104 	uint8_t         zero;
105 	uint8_t         proto;
106 	unsigned short  length;
107 } tcp_pseudo_hdr_t;
108 
109 struct ipv4_tcp_pseudo_hdr {
110 	struct in_addr  src_ip;
111 	struct in_addr  dst_ip;
112 	uint8_t         zero;
113 	uint8_t         proto;
114 	uint16_t        length;
115 };
116 
117 struct ipv6_tcp_pseudo_hdr {
118 	struct in6_addr src_ip;
119 	struct in6_addr dst_ip;
120 	uint32_t        length;
121 	uint8_t         zero[3];
122 	uint8_t         proto;
123 };
124 
125 typedef struct {
126 	struct ip       ip;
127 	struct tcphdr   tcp;
128 } ip_tcp_header_t;
129 
130 typedef union {
131 	ip_udp_header_t udp;
132 	ip_tcp_header_t tcp;
133 } ip_udp_tcp_header_u;
134 
135 #define SKTU_MAX_MTU_PAYLOAD_LEN (1500 - (sizeof(struct ip6_hdr) + sizeof(struct tcphdr) - sizeof(uint32_t)))
136 typedef struct {
137 	uint32_t        packet_number;
138 	char            data[SKTU_MAX_MTU_PAYLOAD_LEN];
139 } my_payload, *my_payload_t;
140 
141 // sktu_frame is a universal container that holds packet buffer and metadata.
142 // It's used when packet_t isn't available (like for utun fd), or isn't
143 // available yet (like before packet gets allocated from channel).
144 #define SKTU_FRAME_BUF_SIZE (16 * 1024)
145 typedef struct sktu_frame {
146 	// meta data
147 	uuid_t                  flow_uuid;
148 
149 	bool                    csum_offload;
150 	uint16_t                csum_flags;
151 	uint16_t                csum_start;
152 	uint16_t                csum_stuff;
153 
154 	size_t                  len;
155 
156 	// data
157 	char                    bytes[SKTU_FRAME_BUF_SIZE];
158 } *sktu_frame_t;
159 
160 typedef struct {
161 	channel_t               chan;
162 	int                     fd;
163 	nexus_port_t            port;
164 	channel_ring_t          rx_ring;
165 	channel_ring_t          tx_ring;
166 	struct in_addr          ip_addr;
167 	struct in6_addr         ip6_addr;
168 	struct ether_addr       mac_addr;
169 	boolean_t               user_packet_pool;
170 } channel_port, *channel_port_t, *sktu_channel_port_t;
171 
172 struct sktu_flow;
173 
174 #define CSUM_OFFLOAD true
175 #define NO_CSUM_OFFLOAD false
176 
177 struct sktu_flow_ops {
178 	size_t (*create_input_frames)(struct sktu_flow *flow,
179 	    struct sktu_frame **frames, size_t max_frames, const void *data,
180 	    size_t data_len);
181 
182 	size_t (*create_output_frames)(struct sktu_flow *flow,
183 	    struct sktu_frame **frames, size_t max_frames, const void *data,
184 	    size_t data_len, bool csum_offload);
185 };
186 
187 typedef struct sktu_flow {
188 	bool                    is_nexus_flow;
189 
190 	uint8_t                 ipver;
191 	void                    *src_ip;
192 	void                    *dst_ip;
193 	size_t                  ip_addr_len;
194 	uint16_t                sport;
195 	uint16_t                dport;
196 	uint8_t                 ip_protocol;
197 
198 	size_t                  mtu;
199 
200 	// nexus flow fields
201 	struct nx_flow_req      nfr;
202 	sktu_nexus_t            nexus;
203 	nexus_port_t            nx_port;
204 	uuid_t                  uuid;
205 
206 	// socket flow fields
207 	int                     sock_fd;
208 
209 	// ops
210 	struct sktu_flow_ops    _flow_ops;
211 #define create_input_frames     _flow_ops.create_input_frames
212 #define create_output_frames    _flow_ops.create_output_frames
213 } *sktu_nexus_flow_t;
214 
215 channel_t
216 sktu_channel_create_extended(const uuid_t uuid,
217     const nexus_port_t port, const ring_dir_t dir,
218     const ring_id_t rid, const channel_attr_t attr,
219     uint64_t exclusive, uint64_t monitor,
220     uint64_t txlowatunit, uint64_t txlowatval,
221     uint64_t rxlowatunit, uint64_t rxlowatval,
222     uint64_t userpacketpool, uint64_t defunctok,
223     uint64_t event_ring, uint64_t low_latency);
224 void permutefuncP(int n, int *permute, void (*func)(int, int *permute));
225 void permutefuncH(int n, int *permute, void (*func)(int, int *permute));
226 void permutefuncR(int n, int *permute, void (*func)(int, int *permute), int total, unsigned seed);
227 void permutefuncZ(int n, int *permute, void (*func)(int, int *permute));
228 
229 void sktc_create_flowswitch(struct sktc_nexus_handles *handles, int i);
230 void sktc_create_flowswitch_no_address(struct sktc_nexus_handles *handles,
231     uint64_t tx_slots, uint64_t rx_slots, uint64_t buf_size, uint64_t max_frags,
232     uint64_t anonymous);
233 void sktc_nexus_handles_assign_address(struct sktc_nexus_handles *handles);
234 
235 void sktc_cleanup_flowswitch(struct sktc_nexus_handles *handles);
236 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);
237 int sktc_unbind_flow(nexus_controller_t ncd, const uuid_t fsw, const uuid_t flow);
238 
239 char * skt_nfr_print(struct nx_flow_req *nfr, char *buf, size_t buf_max);
240 
241 struct sktu_flow * _sktu_create_nexus_flow(sktu_nexus_t nexus,
242     nexus_port_t nx_port, uint8_t af, void *src, void *dst, uint8_t proto,
243     uint16_t sport, uint16_t dport, uint32_t flags);
244 struct sktu_flow * sktu_create_nexus_flow(sktu_nexus_t nexus, uint8_t af,
245     void *src, void *dst, uint8_t proto, uint16_t sport, uint16_t dport);
246 struct sktu_flow * sktu_create_nexus_low_latency_flow(sktu_nexus_t nexus,
247     uint8_t af, void *src, void *dst, uint8_t proto, uint16_t sport,
248     uint16_t dport);
249 struct sktu_flow * sktu_create_nexus_flow_with_nx_port(sktu_nexus_t nexus,
250     nexus_port_t nx_port, uint8_t af, void *src, void *dst, uint8_t proto,
251     uint16_t sport, uint16_t dport);
252 void _sktu_destroy_nexus_flow(struct sktu_flow *flow);
253 #define sktu_destroy_nexus_flow(f) \
254 do { \
255 	_sktu_destroy_nexus_flow(f); \
256 	f = NULL; \
257 } while (0)
258 int sktu_get_nexus_flow_stats(uuid_t flow_uuid, struct sk_stats_flow *sf);
259 int sktu_get_nexus_flowswitch_stats(struct sk_stats_flow_switch **sfsw, size_t *len);
260 void __fsw_stats_print(struct fsw_stats *s);
261 
262 uint32_t sktc_chew_random(channel_t channel, channel_ring_t ring, sync_mode_t mode, bool dosync, uint32_t avail);
263 void sktc_pump_ring_nslots_kq(channel_t channel, channel_ring_t ring, sync_mode_t mode, bool dosync, uint64_t nslots, bool verbose);
264 void sktc_pump_ring_nslots_select(channel_t channel, channel_ring_t ring, sync_mode_t mode, bool dosync, uint64_t nslots, bool verbose);
265 void sktc_pump_ring_nslots_poll(channel_t channel, channel_ring_t ring, sync_mode_t mode, bool dosync, uint64_t nslots, bool verbose);
266 
267 void sktc_raise_file_limit(int new);
268 
269 int sktu_create_interface(sktu_if_type_t type, sktu_if_flag_t flags);
270 channel_t sktu_create_interface_channel(sktu_if_type_t type, int tunsock);
271 void sktu_get_interface_name(sktu_if_type_t type, int s, char name[IFNAMSIZ]);
272 
273 void sktu_dump_buffer(FILE *f, const char *title, const void *p, size_t len);
274 int sysctl_buf(char *oid_name, void **buffer, size_t *len, void *newp, size_t newlen);
275 uint32_t sktu_set_inject_error_rmask(uint32_t *);
276 boolean_t sktu_check_interface_ipv4_address(char *ifname, uint32_t ipaddr);
277 int sktu_create_pfkeysock(void);
278 void sktu_create_sa(int keysock, const char ifname[IFXNAMSIZ], uint32_t spi,
279     struct in_addr *src, struct in_addr *dst);
280 
281 extern unsigned short in_cksum(void * pkt, int len, int sum0);
282 extern uint16_t in_pseudo(uint32_t a, uint32_t b, uint32_t c);
283 extern uint16_t in6_pseudo(const struct in6_addr *src, const struct in6_addr *dst, uint32_t x);
284 
285 extern void sktu_channel_port_init(channel_port_t ch_port, uuid_t instance,
286     nexus_port_t nx_port, bool enable_upp, bool enable_event_ring, bool low_latency);
287 
288 extern void skt_channel_port_send(channel_port_t port, uuid_t flow_id,
289     int protocol, uint16_t src_port, struct in_addr dst_ip, uint16_t dst_port,
290     my_payload_t payload, int payload_length, uint32_t limit,
291     boolean_t must_complete_batch, boolean_t connect,
292     packet_svc_class_t svc_class, boolean_t csum_offload,
293     void (^packet_prehook)(packet_t p));
294 
295 extern void skt_channel_port_receive(int child, channel_port_t port,
296     uint16_t our_port, struct in_addr peer_ip, uint32_t limit,
297     uint32_t *receive_count, uint32_t *receive_index, boolean_t errors_ok,
298     uint32_t * pkts_dropped);
299 
300 extern void sktu_channel_port_tx_bulk(channel_port_t port,
301     struct sktu_frame **frames, uint32_t n);
302 
303 extern packet_t sktu_channel_port_frame_to_pkt(channel_port_t port,
304     struct sktu_frame *frame);
305 extern uint32_t sktu_channel_port_tx_burst_pkt(channel_port_t port,
306     packet_t *frames, uint32_t n);
307 extern uint32_t sktu_channel_port_rx_burst(channel_port_t port,
308     struct sktu_frame **frames, uint32_t n);
309 extern uint32_t sktu_channel_port_tx_burst(channel_port_t port,
310     struct sktu_frame **frames, uint32_t n);
311 
312 extern uint32_t sktu_utun_fd_rx_burst(int utun_fd, struct sktu_frame **frames,
313     uint32_t n);
314 
315 extern void sktu_utun_fd_tx_burst(int utun_fd, struct sktu_frame **frames,
316     uint32_t n);
317 
318 extern struct sktu_frame * sktu_frame_alloc();
319 #define sktu_frame_free(frame) \
320 do { \
321 	free(frame); \
322 	frame = NULL; \
323 } while (0)
324 
325 extern void sktu_frames_free(struct sktu_frame **frames, size_t n);
326 
327 extern size_t sktu_create_ip_frames(struct sktu_frame **frames, size_t n,
328     void *src_ip, void *dst_ip, uint8_t proto, const void *sdu, size_t sdu_len,
329     size_t mtu, uint16_t csum_flags, uint16_t csum_start, uint16_t csum_stuff);
330 extern size_t sktu_create_ip6_frames(struct sktu_frame **frames, size_t n,
331     void *src_ip, void *dst_ip, uint8_t proto, const void *sdu, size_t sdu_len,
332     size_t mtu, uint16_t csum_flags, uint16_t csum_start, uint16_t csum_stuff);
333 extern size_t sktu_create_tcp_frames(struct sktu_frame **frames, size_t n,
334     uint8_t ipver, void *src_ip, void *dst_ip, uint16_t sport, uint16_t dport,
335     const void *data, size_t data_len, size_t mtu, bool csum_offload);
336 extern size_t sktu_create_udp_frames(struct sktu_frame **frames, size_t n,
337     uint8_t ipver, void *src_ip, void *dst_ip, uint16_t sport, uint16_t dport,
338     const void *data, size_t data_len, size_t mtu, bool csum_offload);
339 
340 extern int sktu_parse_ipv4_frame(struct sktu_frame *frame, void *ip_payload,
341     uint32_t *ip_payload_len);
342 extern int sktu_parse_tcp4_frame(struct sktu_frame *frame, void *tcp_payload,
343     uint32_t *tcp_payload_len);
344 extern int sktu_parse_udp4_frame(struct sktu_frame *frame, void *udp_payload,
345     uint32_t *udp_payload_len);
346 
347 #endif /* _SKYWALK_TEST_UTILS_H_ */
348