1 /*
2 * Copyright (c) 2017-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
29 #include <assert.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <stdio.h>
33 #include <unistd.h>
34 #include <uuid/uuid.h>
35 #include <sys/select.h>
36 #include <poll.h>
37 #include <sys/event.h>
38 #include <sys/sysctl.h>
39 #include <darwintest.h>
40 #include "skywalk_test_driver.h"
41 #include "skywalk_test_common.h"
42 #include "skywalk_test_utils.h"
43
44 /* Copied from skt_oneslot */
45
46 static int
skt_shutdown_common(int argc,char * argv[],int method)47 skt_shutdown_common(int argc, char *argv[], int method)
48 {
49 int error;
50 channel_t channel;
51 uuid_t channel_uuid;
52 ring_id_t ringid;
53 channel_ring_t ring;
54 channel_slot_t slot;
55 uint32_t avail;
56 slot_prop_t prop;
57 int channelfd, sock_fd;
58 fd_set rfdset, wfdset, efdset;
59 struct pollfd fds, sock_fds;
60 int kq;
61 struct kevent kev, sock_kev;
62 uint64_t ts;
63
64 error = uuid_parse(argv[3], channel_uuid);
65 SKTC_ASSERT_ERR(!error);
66
67 channel = sktu_channel_create_extended(channel_uuid, 0,
68 CHANNEL_DIR_TX_RX, CHANNEL_RING_ID_ANY, NULL,
69 -1, -1, -1, -1, -1, -1, -1, 1, -1, -1);
70 assert(channel);
71
72 channelfd = os_channel_get_fd(channel);
73 assert(channelfd != -1);
74
75 sock_fd = socket(PF_INET, SOCK_STREAM, 0);
76 assert(sock_fd != -1);
77
78 error = pid_shutdown_sockets(getpid(),
79 SHUTDOWN_SOCKET_LEVEL_DISCONNECT_ALL);
80 SKTC_ASSERT_ERR(!error);
81
82 switch (method) {
83 case 0:
84 FD_ZERO(&rfdset);
85 FD_ZERO(&wfdset);
86 FD_ZERO(&efdset);
87 FD_SET(channelfd, &rfdset);
88 FD_SET(channelfd, &wfdset);
89 FD_SET(channelfd, &efdset);
90 error = select(channelfd + 1, &rfdset, &wfdset, &efdset, NULL);
91 SKTC_ASSERT_ERR(error != -1);
92 SKTC_ASSERT_ERR(error == 1);
93 assert(!FD_ISSET(channelfd, &rfdset));
94 assert(!FD_ISSET(channelfd, &wfdset));
95 assert(FD_ISSET(channelfd, &efdset));
96 break;
97 case 1:
98 sock_fds.fd = sock_fd;
99 fds.events = sock_fds.events = POLLWRNORM;
100 fds.revents = sock_fds.revents = 0;
101 /* socket */
102 error = poll(&sock_fds, 1, -1);
103 T_LOG("poll sock POLLWRNORM: error(%d) events(0x%x)"
104 " revents(0x%x)\n", error, sock_fds.events,
105 sock_fds.revents);
106 SKTC_ASSERT_ERR(error != -1);
107 SKTC_ASSERT_ERR(error == 1);
108 assert(sock_fds.fd == sock_fd);
109 assert(sock_fds.events == POLLWRNORM);
110 assert((sock_fds.revents & POLLHUP) != 0);
111 /* channel */
112 fds.fd = channelfd;
113 error = poll(&fds, 1, -1);
114 T_LOG("poll chan POLLWRNORM: error(%d) events(0x%x)"
115 " revents(0x%x)\n", error, fds.events, fds.revents);
116 SKTC_ASSERT_ERR(error != -1);
117 SKTC_ASSERT_ERR(error == 1);
118 /* ensure that the return values match with socket */
119 assert(fds.fd == channelfd);
120 assert(fds.events == sock_fds.events);
121 assert(fds.revents == sock_fds.revents);
122 break;
123 case 2:
124 /* socket */
125 kq = kqueue();
126 assert(kq != -1);
127 /* event registration */
128 EV_SET(&sock_kev, sock_fd, EVFILT_WRITE, EV_ADD | EV_ENABLE,
129 0, 0, NULL);
130 error = kevent(kq, &sock_kev, 1, &sock_kev, 1, NULL);
131 T_LOG("kqueue sock EVFILT_WRITE: error(%d) "
132 "flags(0x%x) fflags(0x%x) data(0x%lx)\n",
133 error, sock_kev.flags, sock_kev.fflags, sock_kev.data);
134 SKTC_ASSERT_ERR(error != -1);
135 SKTC_ASSERT_ERR(error == 1);
136 assert(sock_kev.filter == EVFILT_WRITE);
137 assert(sock_kev.ident == sock_fd);
138 assert(sock_kev.udata == NULL);
139 assert(sock_kev.flags & EV_ADD);
140 assert(sock_kev.flags & EV_ENABLE);
141 assert(sock_kev.flags & EV_EOF);
142 /* event processing */
143 error = kevent(kq, NULL, 0, &sock_kev, 1, NULL);
144 SKTC_ASSERT_ERR(error != -1);
145 SKTC_ASSERT_ERR(error == 1);
146 assert(sock_kev.filter == EVFILT_WRITE);
147 assert(sock_kev.ident == sock_fd);
148 assert(sock_kev.udata == NULL);
149 assert(sock_kev.flags & EV_ADD);
150 assert(sock_kev.flags & EV_ENABLE);
151 assert(sock_kev.flags & EV_EOF);
152 close(kq);
153 /* channel */
154 kq = kqueue();
155 assert(kq != -1);
156 EV_SET(&kev, channelfd, EVFILT_WRITE, EV_ADD | EV_ENABLE,
157 0, 0, NULL);
158 /*
159 * event registration on a defunct channel should
160 * return EV_EOF
161 */
162 error = kevent(kq, &kev, 1, &kev, 1, NULL);
163 T_LOG("kqueue chan EVFILT_WRITE: error(%d) "
164 "flags(0x%x) fflags(0x%x) data(0x%lx)\n",
165 error, kev.flags, kev.fflags, kev.data);
166 SKTC_ASSERT_ERR(error != -1);
167 SKTC_ASSERT_ERR(error == 1);
168 /* ensure that the return values match with socket */
169 assert(kev.filter == sock_kev.filter);
170 assert(kev.ident == channelfd);
171 assert(kev.udata == sock_kev.udata);
172 assert(kev.flags == sock_kev.flags);
173 assert(kev.data == 0);
174 /*
175 * event processing on a defunct channel should
176 * return EV_EOF
177 */
178 error = kevent(kq, NULL, 0, &kev, 1, NULL);
179 SKTC_ASSERT_ERR(error != -1);
180 SKTC_ASSERT_ERR(error == 1);
181 /* ensure that the return values match with socket */
182 assert(kev.filter == sock_kev.filter);
183 assert(kev.ident == channelfd);
184 assert(kev.udata == sock_kev.udata);
185 assert(kev.flags == sock_kev.flags);
186 assert(kev.data == 0);
187 close(kq);
188 /* check EVFILT_NW_CHANNEL filter */
189 kq = kqueue();
190 assert(kq != -1);
191 EV_SET(&kev, channelfd, EVFILT_NW_CHANNEL, EV_ADD | EV_ENABLE,
192 0, 0, NULL);
193 error = kevent(kq, &kev, 1, &kev, 1, NULL);
194 T_LOG("kqueue EVFILT_NW_CHANNEL: error(%d) "
195 "flags(0x%x) fflags(0x%x) data(0x%lx)\n",
196 error, kev.flags, kev.fflags, kev.data);
197 SKTC_ASSERT_ERR(error != -1);
198 SKTC_ASSERT_ERR(error == 1);
199 assert(kev.filter == EVFILT_NW_CHANNEL);
200 assert(kev.ident == channelfd);
201 assert(kev.udata == NULL);
202 assert(kev.flags & EV_ADD);
203 assert(kev.flags & EV_ENABLE);
204 assert(kev.flags & EV_EOF);
205 assert(kev.data == 0);
206 error = kevent(kq, NULL, 0, &kev, 1, NULL);
207 SKTC_ASSERT_ERR(error != -1);
208 SKTC_ASSERT_ERR(error == 1);
209 assert(kev.filter == EVFILT_NW_CHANNEL);
210 assert(kev.udata == NULL);
211 assert(kev.flags & EV_ADD);
212 assert(kev.flags & EV_ENABLE);
213 assert(kev.flags & EV_EOF);
214 assert(kev.data == 0);
215 break;
216 default:
217 abort();
218 }
219
220 error = os_channel_is_defunct(channel);
221 assert(error != 0);
222
223 ringid = os_channel_ring_id(channel, CHANNEL_FIRST_TX_RING);
224 ring = os_channel_tx_ring(channel, ringid);
225 assert(ring);
226
227 avail = os_channel_available_slot_count(ring);
228 assert(!avail);
229
230 slot = os_channel_get_next_slot(ring, NULL, &prop);
231 assert(!slot);
232
233 error = os_channel_advance_slot(ring, slot);
234 SKTC_ASSERT_ERR(error == ENXIO);
235
236 error = os_channel_sync(channel, CHANNEL_SYNC_TX);
237 SKTC_ASSERT_ERR(error == -1);
238 SKTC_ASSERT_ERR(errno == ENXIO);
239
240 error = os_channel_pending(ring);
241 assert(error == 0);
242
243 ts = os_channel_ring_sync_time(ring);
244 assert(ts == 0);
245
246 ts = os_channel_ring_notify_time(ring);
247 assert(ts == 0);
248
249 switch (method) {
250 case 0:
251 FD_ZERO(&rfdset);
252 FD_ZERO(&wfdset);
253 FD_ZERO(&efdset);
254 FD_SET(channelfd, &rfdset);
255 FD_SET(channelfd, &wfdset);
256 FD_SET(channelfd, &efdset);
257 error = select(channelfd + 1, &rfdset, &wfdset, &efdset, NULL);
258 SKTC_ASSERT_ERR(error != -1);
259 SKTC_ASSERT_ERR(error == 1);
260 assert(!FD_ISSET(channelfd, &rfdset));
261 assert(!FD_ISSET(channelfd, &wfdset));
262 assert(FD_ISSET(channelfd, &efdset));
263 break;
264 case 1:
265 sock_fds.fd = sock_fd;
266 fds.events = sock_fds.events = POLLRDNORM;
267 fds.revents = sock_fds.revents = 0;
268 /* socket */
269 error = poll(&sock_fds, 1, -1);
270 T_LOG("poll sock POLLRDNORM: error(%d) events(0x%x)"
271 " revents(0x%x)\n", error, sock_fds.events,
272 sock_fds.revents);
273 SKTC_ASSERT_ERR(error != -1);
274 SKTC_ASSERT_ERR(error == 1);
275 assert(sock_fds.fd == sock_fd);
276 assert(sock_fds.events == POLLRDNORM);
277 assert((sock_fds.revents & POLLHUP) != 0);
278 /* channel */
279 fds.fd = channelfd;
280 error = poll(&fds, 1, -1);
281 T_LOG("poll chan POLLRDNORM: error(%d) events(0x%x)"
282 " revents(0x%x)\n", error, fds.events, fds.revents);
283 SKTC_ASSERT_ERR(error != -1);
284 SKTC_ASSERT_ERR(error == 1);
285 /* ensure that the return values match with socket */
286 assert(fds.fd == channelfd);
287 assert(fds.events == sock_fds.events);
288 assert(fds.revents == sock_fds.revents);
289 break;
290 case 2:
291 /* socket */
292 kq = kqueue();
293 assert(kq != -1);
294 /* event registration */
295 EV_SET(&sock_kev, sock_fd, EVFILT_READ, EV_ADD | EV_ENABLE,
296 0, 0, NULL);
297 error = kevent(kq, &sock_kev, 1, &sock_kev, 1, NULL);
298 T_LOG("kqueue sock EVFILT_READ: error(%d) "
299 "flags(0x%x) fflags(0x%x) data(0x%lx)\n",
300 error, sock_kev.flags, sock_kev.fflags, sock_kev.data);
301 SKTC_ASSERT_ERR(error != -1);
302 SKTC_ASSERT_ERR(error == 1);
303 assert(sock_kev.filter == EVFILT_READ);
304 assert(sock_kev.ident == sock_fd);
305 assert(sock_kev.udata == NULL);
306 assert(sock_kev.flags & EV_ADD);
307 assert(sock_kev.flags & EV_ENABLE);
308 assert(sock_kev.flags & EV_EOF);
309 /* event processing */
310 error = kevent(kq, NULL, 0, &sock_kev, 1, NULL);
311 SKTC_ASSERT_ERR(error != -1);
312 SKTC_ASSERT_ERR(error == 1);
313 assert(sock_kev.filter == EVFILT_READ);
314 assert(sock_kev.ident == sock_fd);
315 assert(sock_kev.udata == NULL);
316 assert(sock_kev.flags & EV_ADD);
317 assert(sock_kev.flags & EV_ENABLE);
318 assert(sock_kev.flags & EV_EOF);
319 close(kq);
320 /* channel */
321 kq = kqueue();
322 assert(kq != -1);
323 EV_SET(&kev, channelfd, EVFILT_READ, EV_ADD | EV_ENABLE,
324 0, 0, NULL);
325 /*
326 * event registration on a defunct channel should
327 * return EV_EOF
328 */
329 error = kevent(kq, &kev, 1, &kev, 1, NULL);
330 T_LOG("kqueue chan EVFILT_READ: error(%d) "
331 "flags(0x%x) fflags(0x%x) data(0x%lx)\n",
332 error, kev.flags, kev.fflags, kev.data);
333 SKTC_ASSERT_ERR(error != -1);
334 SKTC_ASSERT_ERR(error == 1);
335 /* ensure that the return values match with socket */
336 assert(kev.filter == sock_kev.filter);
337 assert(kev.ident == channelfd);
338 assert(kev.udata == sock_kev.udata);
339 assert(kev.flags == sock_kev.flags);
340 assert(kev.data == 0);
341 /*
342 * event processing on a defunct channel should
343 * return EV_EOF
344 */
345 error = kevent(kq, NULL, 0, &kev, 1, NULL);
346 SKTC_ASSERT_ERR(error != -1);
347 SKTC_ASSERT_ERR(error == 1);
348 /* ensure that the return values match with socket */
349 assert(kev.filter == sock_kev.filter);
350 assert(kev.ident == channelfd);
351 assert(kev.udata == sock_kev.udata);
352 assert(kev.flags == sock_kev.flags);
353 assert(kev.data == 0);
354 close(kq);
355 break;
356 default:
357 abort();
358 }
359
360 ringid = os_channel_ring_id(channel, CHANNEL_FIRST_RX_RING);
361 ring = os_channel_rx_ring(channel, ringid);
362 assert(ring);
363
364 avail = os_channel_available_slot_count(ring);
365 assert(!avail);
366
367 slot = os_channel_get_next_slot(ring, NULL, &prop);
368 assert(!slot);
369
370 //T_LOG("Got message \"%s\" len %d\n", (char *)prop.sp_buf_ptr, prop.sp_len);
371
372 // XXX test this?
373 //prop.sp_len = 0;
374 //os_channel_set_slot_properties(ring, slot, &prop);
375
376 /* slot is NULL here */
377 error = os_channel_advance_slot(ring, slot);
378 SKTC_ASSERT_ERR(error == ENXIO);
379
380 error = os_channel_sync(channel, CHANNEL_SYNC_RX);
381 SKTC_ASSERT_ERR(error == -1);
382 SKTC_ASSERT_ERR(errno == ENXIO);
383
384 os_channel_destroy(channel);
385
386 return 0;
387 }
388
389 static int
skt_shutdown_select_main(int argc,char * argv[])390 skt_shutdown_select_main(int argc, char *argv[])
391 {
392 return skt_shutdown_common(argc, argv, 0);
393 }
394
395 static int
skt_shutdown_poll_main(int argc,char * argv[])396 skt_shutdown_poll_main(int argc, char *argv[])
397 {
398 return skt_shutdown_common(argc, argv, 1);
399 }
400
401 static int
skt_shutdown_kqueue_main(int argc,char * argv[])402 skt_shutdown_kqueue_main(int argc, char *argv[])
403 {
404 return skt_shutdown_common(argc, argv, 2);
405 }
406
407 struct skywalk_test skt_shutdownus = {
408 "shutdownus", "shuts down channel on upipe and calls select",
409 SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_USER_PIPE,
410 skt_shutdown_select_main, SKTC_GENERIC_UPIPE_ARGV,
411 sktc_generic_upipe_nexus_init, sktc_cleanup_nexus,
412 };
413
414 struct skywalk_test skt_shutdownks = {
415 "shutdownks", "shuts down channel on kpipe and calls select",
416 SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_KERNEL_PIPE | SK_FEATURE_NEXUS_KERNEL_PIPE_LOOPBACK,
417 skt_shutdown_select_main, SKTC_GENERIC_KPIPE_ARGV,
418 sktc_generic_kpipe_init, sktc_generic_kpipe_fini,
419 };
420
421 struct skywalk_test skt_shutdownup = {
422 "shutdownup", "shuts down channel on upipe and calls poll",
423 SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_USER_PIPE,
424 skt_shutdown_poll_main, SKTC_GENERIC_UPIPE_ARGV,
425 sktc_generic_upipe_nexus_init, sktc_cleanup_nexus,
426 };
427
428 struct skywalk_test skt_shutdownkp = {
429 "shutdownkp", "shuts down channel on kpipe and calls poll",
430 SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_KERNEL_PIPE | SK_FEATURE_NEXUS_KERNEL_PIPE_LOOPBACK,
431 skt_shutdown_poll_main, SKTC_GENERIC_KPIPE_ARGV,
432 sktc_generic_kpipe_init, sktc_generic_kpipe_fini,
433 };
434
435 struct skywalk_test skt_shutdownuk = {
436 "shutdownuk", "shuts down channel on upipe and calls kqueue",
437 SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_USER_PIPE,
438 skt_shutdown_kqueue_main, SKTC_GENERIC_UPIPE_ARGV,
439 sktc_generic_upipe_nexus_init, sktc_cleanup_nexus,
440 };
441
442 struct skywalk_test skt_shutdownkk = {
443 "shutdownkk", "shuts down channel on kpipe and calls kqueue",
444 SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_KERNEL_PIPE | SK_FEATURE_NEXUS_KERNEL_PIPE_LOOPBACK,
445 skt_shutdown_kqueue_main, SKTC_GENERIC_KPIPE_ARGV,
446 sktc_generic_kpipe_init, sktc_generic_kpipe_fini,
447 };
448