xref: /xnu-12377.61.12/tests/skywalk/skywalk_test_utils.h (revision 4d495c6e23c53686cf65f45067f79024cf5dcee8)
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