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