xref: /xnu-11215.41.3/tests/skywalk/skt_netifcompat.c (revision 33de042d024d46de5ff4e89f2471de6608e37fa4)
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 
29 #include <assert.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <stdio.h>
33 #include <unistd.h>
34 #include <errno.h>
35 #include <darwintest.h>
36 
37 #include "skywalk_test_common.h"
38 #include "skywalk_test_driver.h"
39 #include "skywalk_test_utils.h"
40 
41 static channel_t channel;
42 static uuid_t if_uuid;
43 
44 static void
skt_netifcompat_common(void)45 skt_netifcompat_common(void)
46 {
47 	int error;
48 	struct sktc_nexus_attr attr = SKTC_NEXUS_ATTR_INIT();
49 
50 	strncpy((char *)attr.name, "skywalk_test_net_if",
51 	    sizeof(nexus_name_t) - 1);
52 	attr.type = NEXUS_TYPE_NET_IF;
53 	attr.anonymous = 1;
54 	attr.userchannel = 1;
55 
56 	sktc_setup_nexus(&attr);
57 
58 	channel = sktu_channel_create_extended(sktc_instance_uuid, NEXUS_PORT_NET_IF_HOST,
59 	    CHANNEL_DIR_TX_RX, CHANNEL_RING_ID_ANY, NULL,
60 	    -1, -1, -1, -1, -1, -1, -1, 1, -1, -1);
61 	assert(!channel);
62 
63 	channel = sktu_channel_create_extended(sktc_instance_uuid, NEXUS_PORT_NET_IF_DEV,
64 	    CHANNEL_DIR_TX_RX, CHANNEL_RING_ID_ANY, NULL,
65 	    -1, -1, -1, -1, -1, -1, -1, 1, -1, -1);
66 	assert(!channel);
67 
68 	uuid_generate_random(if_uuid);
69 	error = __os_nexus_ifdetach(sktc_nexus_controller,
70 	    sktc_instance_uuid, if_uuid);
71 	SKTC_ASSERT_ERR(error == -1);
72 	SKT_LOG("error %d errno %d\n", error, errno);
73 	SKTC_ASSERT_ERR(errno == ESRCH);
74 
75 	uuid_clear(if_uuid);
76 	error = __os_nexus_ifdetach(sktc_nexus_controller,
77 	    sktc_instance_uuid, if_uuid);
78 	SKTC_ASSERT_ERR(error == -1);
79 	SKTC_ASSERT_ERR(errno == EINVAL);
80 
81 	error = __os_nexus_ifattach(sktc_nexus_controller,
82 	    sktc_instance_uuid, FETH0_NAME, NULL, false, &if_uuid);
83 	SKTC_ASSERT_ERR(!error);
84 
85 	channel = sktu_channel_create_extended(sktc_instance_uuid, NEXUS_PORT_NET_IF_DEV,
86 	    CHANNEL_DIR_TX_RX, CHANNEL_RING_ID_ANY, NULL,
87 	    -1, -1, -1, -1, -1, -1, -1, 1, -1, -1);
88 	if (channel != NULL) {
89 		error = __os_nexus_ifdetach(sktc_nexus_controller,
90 		    sktc_instance_uuid, if_uuid);
91 		SKTC_ASSERT_ERR(error == -1);
92 		SKTC_ASSERT_ERR(errno == EBUSY);
93 	}
94 }
95 
96 static int
skt_netifcompata_main(int argc,char * argv[])97 skt_netifcompata_main(int argc, char *argv[])
98 {
99 	int error;
100 
101 	skt_netifcompat_common();
102 	if (channel != NULL) {
103 		os_channel_destroy(channel);
104 	}
105 
106 	error = __os_nexus_ifdetach(sktc_nexus_controller,
107 	    sktc_instance_uuid, if_uuid);
108 	SKTC_ASSERT_ERR(!error);
109 
110 	error = __os_nexus_ifdetach(sktc_nexus_controller,
111 	    sktc_instance_uuid, if_uuid);
112 	SKTC_ASSERT_ERR(error == -1);
113 	SKTC_ASSERT_ERR(errno == ESRCH);
114 
115 	sktc_cleanup_nexus();
116 
117 	return 0;
118 }
119 
120 static int
skt_netifcompatb_main(int argc,char * argv[])121 skt_netifcompatb_main(int argc, char *argv[])
122 {
123 	skt_netifcompat_common();
124 
125 	sktc_cleanup_nexus();
126 
127 	/* Skip detach since controller is closed */
128 	if (channel != NULL) {
129 		os_channel_destroy(channel);
130 	}
131 
132 	return 0;
133 }
134 
135 static int
skt_netifcompatc_main(int argc,char * argv[])136 skt_netifcompatc_main(int argc, char *argv[])
137 {
138 	int error;
139 	skt_netifcompat_common();
140 
141 	/* This is the guts of sktc_cleanup_nexus() expanded here
142 	 * so that we can detach and close after we've freed the instance
143 	 */
144 	assert(sktc_nexus_controller);
145 	assert(!uuid_is_null(sktc_provider_uuid));
146 	assert(!uuid_is_null(sktc_instance_uuid));
147 
148 	error = os_nexus_controller_free_provider_instance(sktc_nexus_controller,
149 	    sktc_instance_uuid);
150 	SKTC_ASSERT_ERR(!error);
151 
152 	/* We've freed the provider, but there's a channel still open to it.
153 	 * We can then no longer detach it, is that correct?
154 	 */
155 	error = __os_nexus_ifdetach(sktc_nexus_controller,
156 	    sktc_instance_uuid, if_uuid);
157 	if (channel != NULL) {
158 		SKTC_ASSERT_ERR(error == -1);
159 		SKTC_ASSERT_ERR(errno == ENOENT);
160 	}
161 	error = os_nexus_controller_deregister_provider(sktc_nexus_controller,
162 	    sktc_provider_uuid);
163 	SKTC_ASSERT_ERR(!error);
164 
165 	os_nexus_controller_destroy(sktc_nexus_controller);
166 	sktc_nexus_controller = NULL;
167 	if (channel != NULL) {
168 		os_channel_destroy(channel);
169 	}
170 
171 	return 0;
172 }
173 
174 struct skywalk_test skt_netifcompata = {
175 	"netifcompata", "setup and teardown netifcompat on feth0",
176 	SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_NETIF,
177 	skt_netifcompata_main, { NULL },
178 	sktc_ifnet_feth0_create, sktc_ifnet_feth0_destroy,
179 };
180 
181 struct skywalk_test skt_netifcompatb = {
182 	"netifcompatb", "setup and teardown netifcompat on feth0 with deferred close channel",
183 	SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_NETIF,
184 	skt_netifcompatb_main, { NULL },
185 	sktc_ifnet_feth0_create, sktc_ifnet_feth0_destroy,
186 };
187 
188 struct skywalk_test skt_netifcompatc = {
189 	"netifcompatc", "setup and teardown netifcompat on feth0 with deferred detach and close channel",
190 	SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_NETIF,
191 	skt_netifcompatc_main, { NULL },
192 	sktc_ifnet_feth0_create, sktc_ifnet_feth0_destroy,
193 };
194 
195 /****************************************************************/
196 
197 static void
skt_fsw_common(const char * name)198 skt_fsw_common(const char *name)
199 {
200 	int error;
201 	uuid_t ms_provider;
202 	uuid_t ms_instance;
203 	uuid_t ms_attach;
204 	uuid_t scratch;
205 	struct sktc_nexus_attr attr = SKTC_NEXUS_ATTR_INIT();
206 
207 	strncpy((char *)attr.name, name, sizeof(nexus_name_t) - 1);
208 	attr.type = NEXUS_TYPE_FLOW_SWITCH;
209 	attr.anonymous = 1;
210 
211 	skt_netifcompat_common();
212 
213 	sktc_build_nexus(sktc_nexus_controller, &attr, &ms_provider,
214 	    &ms_instance);
215 
216 	if (channel != NULL) {
217 		/*
218 		 * There is a channel open to the net-if dev port, so this
219 		 * attach will fail
220 		 */
221 		error = __os_nexus_ifattach(sktc_nexus_controller,
222 		    ms_instance, NULL, sktc_instance_uuid, false, &ms_attach);
223 		SKT_LOG("%s:%d error %d errno %d\n", __func__, __LINE__,
224 		    error, errno);
225 		SKTC_ASSERT_ERR(error == -1);
226 		SKTC_ASSERT_ERR(errno == EBUSY);
227 
228 		/* Close the channel so the attach will succeed */
229 		os_channel_destroy(channel);
230 	}
231 	error = __os_nexus_ifattach(sktc_nexus_controller,
232 	    ms_instance, NULL, sktc_instance_uuid, false, &ms_attach);
233 	SKT_LOG("%s:%d error %d errno %d\n", __func__, __LINE__, error, errno);
234 	SKTC_ASSERT_ERR(!error);
235 
236 	uuid_clear(scratch);
237 	error = __os_nexus_ifattach(sktc_nexus_controller,
238 	    ms_instance, NULL, sktc_instance_uuid, false, &scratch);
239 	SKT_LOG("%s:%d error %d errno %d\n", __func__, __LINE__, error, errno);
240 	SKTC_ASSERT_ERR(error == -1);
241 	SKTC_ASSERT_ERR(errno == EEXIST);
242 	assert(uuid_is_null(scratch));
243 
244 	/*
245 	 * flowswitch doesn't allow opening a channel without a flow bound
246 	 * to the port.
247 	 */
248 	uuid_t flow_id;
249 	uuid_generate(flow_id);
250 	error = sktc_bind_tcp4_flow(sktc_nexus_controller, ms_instance,
251 	    0, NEXUS_PORT_FLOW_SWITCH_CLIENT, flow_id);
252 	SKTC_ASSERT_ERR(error == 0);
253 
254 	/* must fail without user packet pool set (flow switch) */
255 	assert(sktu_channel_create_extended(ms_instance, 2,
256 	    CHANNEL_DIR_TX_RX, CHANNEL_RING_ID_ANY, NULL,
257 	    -1, -1, -1, -1, -1, -1, -1, 1, -1, -1) == NULL);
258 
259 	/* Open and close channel to the flow switch */
260 	channel = sktu_channel_create_extended(ms_instance, 2,
261 	    CHANNEL_DIR_TX_RX, CHANNEL_RING_ID_ANY, NULL,
262 	    -1, -1, -1, -1, -1, -1, 1, 1, -1, -1);
263 	assert(channel);
264 
265 	os_channel_destroy(channel);
266 
267 	error = __os_nexus_ifdetach(sktc_nexus_controller,
268 	    ms_instance, ms_attach);
269 	SKT_LOG("%s:%d error %d errno %d\n", __func__, __LINE__, error, errno);
270 	SKTC_ASSERT_ERR(!error);
271 
272 	error = os_nexus_controller_free_provider_instance(sktc_nexus_controller,
273 	    ms_instance);
274 	SKT_LOG("%s:%d error %d errno %d\n", __func__, __LINE__, error, errno);
275 	SKTC_ASSERT_ERR(!error);
276 	uuid_clear(ms_instance);
277 
278 	error = os_nexus_controller_deregister_provider(sktc_nexus_controller,
279 	    ms_provider);
280 	SKT_LOG("%s:%d error %d errno %d\n", __func__, __LINE__, error, errno);
281 	SKTC_ASSERT_ERR(!error);
282 	uuid_clear(ms_provider);
283 
284 	sktc_cleanup_nexus();
285 }
286 
287 static int
skt_netifms_main(int argc,char * argv[])288 skt_netifms_main(int argc, char *argv[])
289 {
290 	skt_fsw_common("skywalk_test_fsw");
291 	return 0;
292 }
293 
294 struct skywalk_test skt_netiffsw = {
295 	"netifms", "setup compat netif and attach to flowswitch",
296 	SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_NETIF |
297 	SK_FEATURE_NEXUS_FLOWSWITCH | SK_FEATURE_NETNS,
298 	skt_netifms_main, { NULL },
299 	sktc_ifnet_feth0_create, sktc_ifnet_feth0_destroy,
300 };
301 
302 int
skt_netifdelete_main(int argc,char * argv[])303 skt_netifdelete_main(int argc, char *argv[])
304 {
305 	uuid_t attach;
306 	int error;
307 	struct sktc_nexus_attr attr = SKTC_NEXUS_ATTR_INIT();
308 
309 	strncpy((char *)attr.name, "skt_netifdelete_netif",
310 	    sizeof(nexus_name_t) - 1);
311 	attr.type = NEXUS_TYPE_NET_IF;
312 	attr.anonymous = 1;
313 	attr.userchannel = 1;
314 
315 	sktc_ifnet_feth0_create();
316 
317 	sktc_setup_nexus(&attr);
318 
319 	error = __os_nexus_ifattach(sktc_nexus_controller,
320 	    sktc_instance_uuid, FETH0_NAME, NULL, false, &attach);
321 	SKT_LOG("%s:%d error %d errno %d\n", __func__, __LINE__, error, errno);
322 	SKTC_ASSERT_ERR(!error);
323 
324 	sktc_ifnet_feth0_destroy();
325 
326 	error = __os_nexus_ifdetach(sktc_nexus_controller,
327 	    sktc_instance_uuid, attach);
328 	SKT_LOG("%s:%d error %d errno %d\n", __func__, __LINE__, error, errno);
329 	SKTC_ASSERT_ERR(!error);
330 
331 	sktc_cleanup_nexus();
332 
333 	return 0;
334 }
335 
336 struct skywalk_test skt_netifdelete = {
337 	"netifdelete", "tear down an ifp while it's attached to a netif",
338 	SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_NETIF,
339 	skt_netifdelete_main,
340 };
341