xref: /xnu-11215.41.3/tests/skywalk/skt_shutdown.c (revision 33de042d024d46de5ff4e89f2471de6608e37fa4)
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