xref: /xnu-11215.41.3/tests/skywalk/skt_flowswitch_ns_reserve.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 <fcntl.h>
32 #include <string.h>
33 #include <stdio.h>
34 #include <unistd.h>
35 #include <pthread.h>
36 #include <uuid/uuid.h>
37 #include <sys/sysctl.h>
38 #include <sys/event.h>
39 #include <netinet/in.h>
40 #include <net/if.h>
41 #include <errno.h>
42 #include <arpa/inet.h>
43 #include <skywalk/os_nexus.h>
44 #include <darwintest.h>
45 #include "skywalk_test_driver.h"
46 #include "skywalk_test_common.h"
47 #include "skywalk_test_utils.h"
48 
49 #define SKT_TCP_MSL_DELAY       1 /* millisecond */
50 #define INVERT_PROTO(p) (((p) == IPPROTO_TCP) ? IPPROTO_UDP : IPPROTO_TCP)
51 
52 #define MESSAGE_STRING  "1234567"
53 struct test_message {
54 	char tm_string[sizeof(MESSAGE_STRING)];
55 };
56 struct thread_arg {
57 	int ta_sock;
58 	int ta_proto;
59 };
60 
61 typedef enum {
62 	kErrorFlagsAssert = 0x1,
63 	kErrorFlagsExpectFailure = 0x2,
64 } ErrorFlags;
65 
66 #define ERROR_FLAGS_NO_ASSERT           0
67 #define ERROR_FLAGS_ASSERT_SUCCESS      kErrorFlagsAssert
68 #define ERROR_FLAGS_ASSERT_FAILURE                      \
69 	(kErrorFlagsAssert | kErrorFlagsExpectFailure)
70 
71 static inline boolean_t
ErrorFlagsAreSet(ErrorFlags flags,ErrorFlags check)72 ErrorFlagsAreSet(ErrorFlags flags, ErrorFlags check)
73 {
74 	return (flags & check) != 0;
75 }
76 
77 const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
78 
79 static void *
reader_thread_bsd(void * arg)80 reader_thread_bsd(void *arg)
81 {
82 	const struct thread_arg *ta = arg;
83 	struct test_message tm;
84 	struct sockaddr sa;
85 	socklen_t slen;
86 	ssize_t rv;
87 
88 	if (ta->ta_proto == IPPROTO_TCP) {
89 		int fd;
90 
91 		/* Accept the first (and only) connection */
92 		fd = accept(ta->ta_sock, &sa, &slen);
93 		assert(fd >= 0);
94 
95 		/* Read the message */
96 		rv = read(fd, &tm, sizeof(tm));
97 		assert(rv == sizeof(tm));
98 		close(fd);
99 	} else {
100 		/* Wait for a message */
101 		rv = recv(ta->ta_sock, &tm, sizeof(tm), MSG_WAITALL);
102 		assert(rv == sizeof(tm));
103 	}
104 
105 	if (strncmp(tm.tm_string, MESSAGE_STRING, sizeof(tm.tm_string))) {
106 		T_LOG("Unexpected message received");
107 		assert(0);
108 	}
109 
110 	return NULL;
111 }
112 
113 static void
skt_flowswitch_ns_bsd(struct sktc_nexus_handles * handles,int proto,void * addr)114 skt_flowswitch_ns_bsd(struct sktc_nexus_handles *handles, int proto, void *addr)
115 {
116 	union sockaddr_in_4_6 saddr = *(union sockaddr_in_4_6 *)addr;
117 	union sockaddr_in_4_6 laddr;
118 	struct test_message tm;
119 	int error, lsock, wsock;
120 	int pf, stype;
121 	pthread_t thread;
122 	ssize_t rv;
123 	char buf0[32], buf1[32];
124 	uuid_string_t uuidstr;
125 	struct thread_arg ta;
126 	struct nx_flow_req nfr;
127 	socklen_t len = sizeof(saddr);
128 
129 	bzero(&laddr, sizeof(laddr));
130 	laddr.sa.sa_family = saddr.sa.sa_family;
131 	laddr.sa.sa_len = saddr.sa.sa_len;
132 	stype = (proto == IPPROTO_TCP) ? SOCK_STREAM : SOCK_DGRAM;
133 	if (saddr.sa.sa_family == AF_INET) {
134 		pf = PF_INET;
135 		inet_ntop(AF_INET, &saddr.sin.sin_addr, buf1, sizeof(buf1));
136 	} else {
137 		pf = PF_INET6;
138 		inet_ntop(AF_INET6, &saddr.sin6.sin6_addr, buf1, sizeof(buf1));
139 	}
140 
141 	T_LOG("BSD: Testing %s over IPv%u %s\n",
142 	    (proto == IPPROTO_TCP) ? "TCP" : "UDP",
143 	    (saddr.sa.sa_family == AF_INET) ? 4 : 6,
144 	    buf1);
145 
146 	/* create & bind a BSD socket to the requested port */
147 	lsock = socket(pf, stype, proto);
148 	assert(lsock >= 0);
149 
150 	error = bind(lsock, &saddr.sa, saddr.sa.sa_len);
151 	SKTC_ASSERT_ERR(error == 0);
152 
153 	/* retrieve the locally bound name of the socket */
154 	error = getsockname(lsock, &saddr.sa, &len);
155 	SKTC_ASSERT_ERR(error == 0);
156 
157 	if (proto == IPPROTO_TCP) {
158 		/* Listen for incoming connections */
159 		error = listen(lsock, 1);
160 		SKTC_ASSERT_ERR(error == 0);
161 	}
162 
163 	/* Create reader thread */
164 	ta.ta_sock = lsock;
165 	ta.ta_proto = proto;
166 	error = pthread_create(&thread, NULL, reader_thread_bsd, &ta);
167 	SKTC_ASSERT_ERR(error == 0);
168 
169 	/* Create another socket for connecting to the first */
170 	wsock = socket(pf, stype, proto);
171 	assert(wsock >= 0);
172 
173 	/* Establish the connection */
174 	error = connect(wsock, &saddr.sa, saddr.sa.sa_len);
175 	SKTC_ASSERT_ERR(error == 0);
176 
177 	/* Write the message */
178 	strncpy(tm.tm_string, MESSAGE_STRING, sizeof(tm.tm_string));
179 	if (proto == IPPROTO_TCP) {
180 		rv = write(wsock, &tm, sizeof(tm));
181 	} else {
182 		rv = send(wsock, &tm, sizeof(tm), 0);
183 	}
184 	assert(rv == sizeof(tm));
185 
186 	/* Reap the listener thread */
187 	error = pthread_join(thread, NULL);
188 	SKTC_ASSERT_ERR(error == 0);
189 
190 	/* Close our end of the connection */
191 	close(wsock);
192 
193 	/* Attempt to bind to the same address/port via Skywalk */
194 	memset(&nfr, 0, sizeof(nfr));
195 	nfr.nfr_ip_protocol = proto;
196 	nfr.nfr_nx_port = NEXUS_PORT_FLOW_SWITCH_CLIENT; /* first usable */
197 	memcpy(&nfr.nfr_saddr, &saddr, sizeof(nfr.nfr_saddr));
198 	uuid_generate_random(nfr.nfr_flow_uuid);
199 
200 	/* 3-tuple bind should fail */
201 	uuid_unparse_upper(nfr.nfr_flow_uuid, uuidstr);
202 
203 	if (saddr.sa.sa_family == AF_INET) {
204 		(void) inet_ntop(AF_INET, &handles->netif_addr, buf0,
205 		    sizeof(buf0));
206 	} else {
207 #if 0
208 		(void) inet_ntop(AF_INET6, &handles->netif_addr6, buf0,
209 		    sizeof(buf0));
210 #else
211 		buf0[0] = '\0';
212 #endif
213 	}
214 
215 	T_LOG("On %s (%s), reserve <%s,%u> through skywalk "
216 	    "(flow %s)\n", handles->netif_ifname, buf0, buf1,
217 	    ntohs(nfr.nfr_saddr.sin.sin_port), uuidstr);
218 	error = __os_nexus_flow_add(handles->controller,
219 	    handles->fsw_nx_uuid, &nfr);
220 	SKTC_ASSERT_ERR(error != 0);
221 
222 	/* 2-tuple bind should also fail */
223 	T_LOG("On %s (%s), reserve <ANY,%u> through skywalk "
224 	    "(flow %s)\n", handles->netif_ifname, buf0,
225 	    ntohs(nfr.nfr_saddr.sin.sin_port), uuidstr);
226 	error = __os_nexus_flow_add(handles->controller,
227 	    handles->fsw_nx_uuid, &nfr);
228 	SKTC_ASSERT_ERR(error != 0);
229 
230 	T_LOG(" %s done\n", __func__);
231 	/* Close the BSD listener socket */
232 	close(lsock);
233 }
234 
235 static void
skt_flowswitch_ns_sky(struct sktc_nexus_handles * handles,int proto,void * addr)236 skt_flowswitch_ns_sky(struct sktc_nexus_handles *handles, int proto, void *addr)
237 {
238 	union sockaddr_in_4_6 saddr = *(union sockaddr_in_4_6 *)addr;
239 	int error, lsock;
240 	int pf, stype, is_wild;
241 	char buf1[32];
242 	uuid_string_t uuidstr;
243 	struct nx_flow_req nfr;
244 	nexus_port_t nx_port = 2;
245 	uuid_t listener_flow;
246 //	uuid_t connected_flow;
247 //	char buf0[32];
248 
249 	stype = (proto == IPPROTO_TCP) ? SOCK_STREAM : SOCK_DGRAM;
250 	if (saddr.sa.sa_family == AF_INET) {
251 		pf =  PF_INET;
252 		is_wild = (saddr.sin.sin_addr.s_addr == INADDR_ANY);
253 		(void) inet_ntop(AF_INET, &saddr.sin.sin_addr, buf1,
254 		    sizeof(buf1));
255 	} else {
256 		pf = PF_INET6;
257 		is_wild = IN6_IS_ADDR_UNSPECIFIED(&saddr.sin6.sin6_addr);
258 		(void) inet_ntop(AF_INET6, &saddr.sin6.sin6_addr, buf1,
259 		    sizeof(buf1));
260 	}
261 
262 	T_LOG("Skywalk: Testing %s over IPv%u %s\n",
263 	    (proto == IPPROTO_TCP) ? "TCP" : "UDP",
264 	    (saddr.sa.sa_family == AF_INET) ? 4 : 6,
265 	    buf1);
266 
267 	/* Bind to port via Skywalk */
268 	uuid_generate_random(listener_flow);
269 	memset(&nfr, 0, sizeof(nfr));
270 	nfr.nfr_ip_protocol = proto;
271 	nfr.nfr_nx_port = nx_port;
272 	memcpy(&nfr.nfr_saddr, &saddr, sizeof(nfr.nfr_saddr));
273 	uuid_copy(nfr.nfr_flow_uuid, listener_flow);
274 	uuid_unparse_upper(nfr.nfr_flow_uuid, uuidstr);
275 	T_LOG("On %s, reserve <%s,%u> through skywalk "
276 	    "(flow %s)\n", handles->netif_ifname, buf1,
277 	    ntohs(nfr.nfr_saddr.sin.sin_port), uuidstr);
278 	error = __os_nexus_flow_add(handles->controller,
279 	    handles->fsw_nx_uuid, &nfr);
280 	SKTC_ASSERT_ERR(error == 0);
281 
282 	memcpy(&saddr, &nfr.nfr_saddr, sizeof(saddr));
283 
284 // Currently doesn't work - No route to host
285 #if 0
286 	/* Test connecting a new flow from the listener */
287 	uuid_generate_random(connected_flow);
288 	memset(&nfr, 0, sizeof(nfr));
289 	nfr.nfr_ip_protocol = proto;
290 	nfr.nfr_nx_port = nx_port;
291 
292 	memcpy(&nfr.nfr_saddr, &saddr, sizeof(nfr.nfr_saddr));
293 	memcpy(&nfr.nfr_daddr, &saddr, sizeof(nfr.nfr_daddr));
294 	if (saddr.sa.sa_family == AF_INET) {
295 		nfr.nfr_saddr.sin.sin_addr.s_addr = htonl(INADDR_ANY);
296 		nfr.nfr_daddr.sin.sin_port += htons(16);
297 		if (is_wild) {
298 			nfr.nfr_daddr.sin.sin_addr = handles->netif_addr;
299 		}
300 		inet_ntop(AF_INET, &nfr.nfr_daddr.sin.sin_addr, buf0,
301 		    sizeof(buf0));
302 	} else {
303 		memcpy(&nfr.nfr_saddr.sin6.sin6_addr, &in6addr_any,
304 		    sizeof(nfr.nfr_saddr.sin6.sin6_addr));
305 		nfr.nfr_daddr.sin6.sin6_port += htons(16);
306 #if 0
307 		if (is_wild) {
308 			nfr.nfr_daddr.sin6.sin6_addr = handles->netif_addr6;
309 		}
310 #endif
311 		inet_ntop(AF_INET6, &nfr.nfr_daddr.sin6.sin6_addr, buf0,
312 		    sizeof(buf0));
313 	}
314 
315 	uuid_copy(nfr.nfr_flow_uuid, connected_flow);
316 	uuid_unparse_upper(nfr.nfr_flow_uuid, uuidstr);
317 	T_LOG("On %s, connect <%s,%u> -> <%s,%u> "
318 	    "(flow %s)\n", handles->netif_ifname,
319 	    buf0, ntohs(nfr.nfr_daddr.sin.sin_port),
320 	    buf1, ntohs(nfr.nfr_saddr.sin.sin_port),
321 	    uuidstr);
322 	error = __os_nexus_flow_add(handles->controller, handles->fsw_nx_uuid, &nfr);
323 	SKTC_ASSERT_ERR(error == 0);
324 #endif
325 
326 	/* create & bind a BSD socket to the requested port */
327 	lsock = socket(pf, stype, proto);
328 	assert(lsock >= 0);
329 
330 	/* BSD bind should fail */
331 	error = bind(lsock, &saddr.sa, saddr.sa.sa_len);
332 	SKTC_ASSERT_ERR(error != 0);
333 
334 	if (is_wild) {
335 		if (saddr.sa.sa_family == AF_INET) {
336 			saddr.sin.sin_addr = handles->netif_addr;
337 		} else {
338 #if 0
339 			saddr.sin6.sin6_addr = handles->netif_addr6;
340 #endif
341 		}
342 
343 		/* BSD bind from non-wildcard should fail */
344 		error = bind(lsock, &saddr.sa, saddr.sa.sa_len);
345 		SKTC_ASSERT_ERR(error != 0);
346 	}
347 
348 	close(lsock);
349 
350 	memset(&nfr, 0, sizeof(nfr));
351 	uuid_copy(nfr.nfr_flow_uuid, listener_flow);
352 
353 	error = __os_nexus_flow_del(handles->controller, handles->fsw_nx_uuid,
354 	    &nfr);
355 	SKTC_ASSERT_ERR(!error);
356 
357 #if 0
358 	memset(&nfr, 0, sizeof(nfr));
359 	uuid_copy(nfr.nfr_flow_uuid, connected_flow);
360 
361 	error = __os_nexus_flow_del(handles->controller, handles->fsw_nx_uuid,
362 	    &nfr);
363 	SKTC_ASSERT_ERR(!error);
364 #endif
365 	T_LOG(" %s done\n", __func__);
366 }
367 
368 static int
skt_ns_sky_bind(struct sktc_nexus_handles * handles,int proto,void * addr,ErrorFlags error_flags,uuid_t flow,uint16_t * bound_port)369 skt_ns_sky_bind(struct  sktc_nexus_handles *handles, int proto, void *addr,
370     ErrorFlags error_flags, uuid_t flow, uint16_t *bound_port)
371 {
372 	union sockaddr_in_4_6 sky_saddr = *(union sockaddr_in_4_6 *)addr;
373 	int error;
374 	int is_wild;
375 	char buf[32];
376 	uuid_string_t uuidstr;
377 	struct nx_flow_req nfr;
378 	nexus_port_t nx_port = 2;
379 	uint16_t port;
380 
381 	if (sky_saddr.sa.sa_family == AF_INET) {
382 		is_wild = (sky_saddr.sin.sin_addr.s_addr == INADDR_ANY);
383 		(void) inet_ntop(AF_INET, &sky_saddr.sin.sin_addr, buf,
384 		    sizeof(buf));
385 		port = sky_saddr.sin.sin_port;
386 	} else {
387 		is_wild = IN6_IS_ADDR_UNSPECIFIED(&sky_saddr.sin6.sin6_addr);
388 		(void) inet_ntop(AF_INET6, &sky_saddr.sin6.sin6_addr, buf,
389 		    sizeof(buf));
390 		port = sky_saddr.sin6.sin6_port;
391 	}
392 
393 	T_LOG("Skywalk: nexus bind %s over IPv%u %s :%d\n",
394 	    (proto == IPPROTO_TCP) ? "TCP" : "UDP",
395 	    (sky_saddr.sa.sa_family == AF_INET) ? 4 : 6, buf, ntohs(port));
396 
397 	/* Bind to port via Skywalk */
398 	uuid_generate_random(flow);
399 	memset(&nfr, 0, sizeof(nfr));
400 	nfr.nfr_ip_protocol = proto;
401 	nfr.nfr_nx_port = nx_port;
402 	memcpy(&nfr.nfr_saddr, &sky_saddr, sizeof(nfr.nfr_saddr));
403 	uuid_copy(nfr.nfr_flow_uuid, flow);
404 	uuid_unparse_upper(nfr.nfr_flow_uuid, uuidstr);
405 	T_LOG("On %s, reserve <%s,%u> through skywalk "
406 	    "(flow %s)\n", handles->netif_ifname, buf,
407 	    ntohs(nfr.nfr_saddr.sin.sin_port), uuidstr);
408 	error = __os_nexus_flow_add(handles->controller, handles->fsw_nx_uuid,
409 	    &nfr);
410 	*bound_port = nfr.nfr_saddr.sin.sin_port;
411 	if (ErrorFlagsAreSet(error_flags, kErrorFlagsAssert)) {
412 		if (ErrorFlagsAreSet(error_flags, kErrorFlagsExpectFailure)) {
413 			SKTC_ASSERT_ERR(error != 0);
414 		} else {
415 			SKTC_ASSERT_ERR(error == 0);
416 		}
417 	}
418 	return error;
419 }
420 
421 static int
skt_ns_sock_bind(struct sktc_nexus_handles * handles,int proto,void * addr,ErrorFlags error_flags,int * lsock,boolean_t ipv6_only,uint16_t * bound_port)422 skt_ns_sock_bind(struct  sktc_nexus_handles *handles, int proto, void *addr,
423     ErrorFlags error_flags, int *lsock, boolean_t ipv6_only,
424     uint16_t *bound_port)
425 {
426 	char buf[32];
427 	int error;
428 	int on = 0;
429 	union sockaddr_in_4_6 bsd_saddr = *(union sockaddr_in_4_6 *)addr;
430 	socklen_t len = sizeof(bsd_saddr);
431 	uint16_t port;
432 
433 	if (bsd_saddr.sa.sa_family == AF_INET) {
434 		(void) inet_ntop(AF_INET, &bsd_saddr.sin.sin_addr, buf,
435 		    sizeof(buf));
436 		port = bsd_saddr.sin.sin_port;
437 	} else {
438 		(void) inet_ntop(AF_INET6, &bsd_saddr.sin6.sin6_addr, buf,
439 		    sizeof(buf));
440 		port = bsd_saddr.sin6.sin6_port;
441 	}
442 	/* create & bind a BSD socket to the requested port */
443 	*lsock = socket(bsd_saddr.sa.sa_family,
444 	    (proto == IPPROTO_TCP) ? SOCK_STREAM : SOCK_DGRAM,
445 	    proto);
446 	assert(*lsock >= 0);
447 
448 	T_LOG("Skywalk: socket bind %s over IPv%u %s :%d\n",
449 	    (proto == IPPROTO_TCP) ? "TCP" : "UDP",
450 	    (bsd_saddr.sa.sa_family == AF_INET) ? 4 : 6, buf, ntohs(port));
451 
452 	if (bsd_saddr.sa.sa_family == AF_INET6) {
453 		if (ipv6_only) {
454 			on = 1;
455 		}
456 		error = setsockopt(*lsock, IPPROTO_IPV6, IPV6_V6ONLY, &on,
457 		    sizeof(on));
458 		SKTC_ASSERT_ERR(error == 0);
459 	}
460 	error = bind(*lsock, &bsd_saddr.sa, bsd_saddr.sa.sa_len);
461 	if (ErrorFlagsAreSet(error_flags, kErrorFlagsAssert)) {
462 		if (ErrorFlagsAreSet(error_flags, kErrorFlagsExpectFailure)) {
463 			SKTC_ASSERT_ERR(error != 0);
464 		} else {
465 			SKTC_ASSERT_ERR(error == 0);
466 		}
467 	}
468 	*bound_port = 0;
469 	if (error == 0) {
470 		/* retrieve the locally bound name of the socket */
471 		if (getsockname(*lsock, &bsd_saddr.sa, &len) == 0) {
472 			*bound_port = bsd_saddr.sin.sin_port;
473 		} else {
474 			assert(0);
475 		}
476 	}
477 	return error;
478 }
479 
480 static void
skt_flowswitch_ns_sky_bsd(struct sktc_nexus_handles * handles,int proto,void * sky_addr,void * bsd_addr,boolean_t sky_bind_first,ErrorFlags sky_err_flags,ErrorFlags bsd_err_flags,boolean_t ipv6_only,boolean_t use_bound_port)481 skt_flowswitch_ns_sky_bsd(struct sktc_nexus_handles *handles, int proto,
482     void *sky_addr, void* bsd_addr, boolean_t sky_bind_first,
483     ErrorFlags sky_err_flags, ErrorFlags bsd_err_flags,
484     boolean_t ipv6_only, boolean_t use_bound_port)
485 {
486 	int error;
487 	struct nx_flow_req nfr;
488 	uint16_t bound_port;
489 	uuid_t flow;
490 	int lsock;
491 
492 	if (sky_bind_first) {
493 		skt_ns_sky_bind(handles, proto, sky_addr, sky_err_flags,
494 		    flow, &bound_port);
495 		if (use_bound_port) {
496 			((struct sockaddr_in *)bsd_addr)->sin_port = bound_port;
497 		}
498 		skt_ns_sock_bind(handles, proto, bsd_addr, bsd_err_flags,
499 		    &lsock, ipv6_only, &bound_port);
500 	} else {
501 		skt_ns_sock_bind(handles, proto, bsd_addr, bsd_err_flags,
502 		    &lsock, ipv6_only, &bound_port);
503 		/*
504 		 * sleep to account for inpcb garbage collection delay.
505 		 */
506 		sleep(1);
507 		if (use_bound_port) {
508 			((struct sockaddr_in *)sky_addr)->sin_port = bound_port;
509 		}
510 		skt_ns_sky_bind(handles, proto, sky_addr, sky_err_flags,
511 		    flow, &bound_port);
512 	}
513 
514 	if (!ErrorFlagsAreSet(sky_err_flags, kErrorFlagsExpectFailure)) {
515 		memset(&nfr, 0, sizeof(nfr));
516 		uuid_copy(nfr.nfr_flow_uuid, flow);
517 		error = __os_nexus_flow_del(handles->controller,
518 		    handles->fsw_nx_uuid, &nfr);
519 		SKTC_ASSERT_ERR(!error);
520 	}
521 	close(lsock);
522 	T_LOG(" %s done\n", __func__);
523 }
524 
525 static void
skt_flowswitch_ns_check_v4mappedv6addr(struct sktc_nexus_handles * handles,uint16_t port)526 skt_flowswitch_ns_check_v4mappedv6addr(struct sktc_nexus_handles *handles,
527     uint16_t port)
528 {
529 	union sockaddr_in_4_6 saddr, saddr2;
530 	struct sockaddr_in *sin;
531 	struct sockaddr_in6 *sin6;
532 	int sock, error, on = 0;
533 	struct nx_flow_req nfr;
534 	char ntopbuf[INET6_ADDRSTRLEN];
535 	uint16_t bound_port;
536 	uuid_t flow;
537 
538 	memset(&saddr, 0, sizeof(saddr));
539 	sin = &saddr.sin;
540 	sin->sin_len = sizeof(struct sockaddr_in);
541 	sin->sin_family = AF_INET;
542 	sin->sin_port = htons(port);
543 	sin->sin_addr.s_addr = htonl(INADDR_ANY);
544 	/* Bind a skywalk flow */
545 	skt_ns_sky_bind(handles, IPPROTO_TCP, sin, FALSE, flow, &bound_port);
546 
547 	sin6 = &saddr2.sin6;
548 	sin6->sin6_len = sizeof(struct sockaddr_in6);
549 	sin6->sin6_family = AF_INET6;
550 	sin6->sin6_port = bound_port;
551 	sin6->sin6_addr = in6addr_any;
552 
553 	/* create & bind a BSD socket */
554 	sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
555 	assert(sock >= 0);
556 
557 	error = setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
558 	SKTC_ASSERT_ERR(error == 0);
559 	/*
560 	 * BSD bind should fail, if not we will attempt a connect on
561 	 * IPv4-mapped-IPv6 address which should trip assertion in stack
562 	 * when it tries to reserve the port in IPv4 domain.
563 	 */
564 	error = bind(sock, (struct sockaddr *)sin6, sin6->sin6_len);
565 	if (error == 0) {
566 		struct sockaddr_in6     daddr = {
567 			.sin6_len = sizeof(daddr),
568 			.sin6_family = AF_INET6,
569 			.sin6_addr = IN6ADDR_V4MAPPED_INIT,
570 		};
571 		uint16_t                dest_port;
572 
573 		/* add mapped IPv4 address */
574 		daddr.sin6_addr.__u6_addr.__u6_addr32[3]
575 		        = handles->netif_addr.s_addr;
576 		dest_port = ntohs(bound_port);
577 		if (dest_port == 65535) {
578 			dest_port--;
579 		} else {
580 			dest_port++;
581 		}
582 		daddr.sin6_port = htons(dest_port);
583 		fcntl(sock, F_SETFL, O_NONBLOCK);
584 		T_LOG(
585 			"Skywalk: tcp socket connect to %s :%d (mapped)\n",
586 			inet_ntop(AF_INET6, &daddr.sin6_addr, ntopbuf,
587 			sizeof(ntopbuf)),
588 			ntohs(daddr.sin6_port));
589 		error = connect(sock, (struct sockaddr *)&daddr, sizeof(daddr));
590 	}
591 	SKTC_ASSERT_ERR(error != 0);
592 	memset(&nfr, 0, sizeof(nfr));
593 	uuid_copy(nfr.nfr_flow_uuid, flow);
594 	error = __os_nexus_flow_del(handles->controller,
595 	    handles->fsw_nx_uuid, &nfr);
596 	SKTC_ASSERT_ERR(error == 0);
597 	close(sock);
598 	T_LOG(" %s done\n", __func__);
599 }
600 
601 static void
skt_flowswitch_ns_check_v4mappedv6addr2(struct sktc_nexus_handles * handles)602 skt_flowswitch_ns_check_v4mappedv6addr2(struct sktc_nexus_handles *handles)
603 {
604 	struct sockaddr_in6     blank_sin6 = {
605 		.sin6_len = sizeof(blank_sin6),
606 		.sin6_family = AF_INET6,
607 	};
608 	uint16_t                bound_port;
609 	struct sockaddr_in6     daddr = {
610 		.sin6_len = sizeof(daddr),
611 		.sin6_family = AF_INET6,
612 		.sin6_addr = IN6ADDR_V4MAPPED_INIT,
613 	};
614 	int                     error;
615 	uuid_t                  flow;
616 	int                     lsock;
617 	struct sockaddr_in6     nam = { 0 };
618 	socklen_t               nam_len;
619 	char                    ntopbuf[INET6_ADDRSTRLEN];
620 	struct sockaddr_in      sin = {
621 		.sin_len = sizeof(sin),
622 		.sin_family = AF_INET,
623 	};
624 	int                     sock;
625 
626 	/* create and bind an IPv6 TCP socket */
627 	sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
628 	assert(sock >= 0);
629 	error = bind(sock, (struct sockaddr *)&blank_sin6, blank_sin6.sin6_len);
630 	assert(error == 0);
631 
632 	/* get the port */
633 	nam_len = sizeof(nam);
634 	error = getsockname(sock, (struct sockaddr *)&nam, &nam_len);
635 	assert(error == 0);
636 
637 	/* bind skywalk flow to same port in IPv4 namespace, this should fail */
638 	sin.sin_port = nam.sin6_port;
639 	error = skt_ns_sky_bind(handles, IPPROTO_TCP, &sin,
640 	    ERROR_FLAGS_NO_ASSERT, flow, &bound_port);
641 	if (error == 0) {
642 		/* this shouldn't have worked <rdar://problem/35525592> */
643 		T_LOG(
644 			"Binding port %d in skywalk should have failed!\n",
645 			ntohs(nam.sin6_port));
646 	}
647 
648 	/* create and bind a listener socket and get the listening port */
649 	lsock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
650 	assert(lsock >= 0);
651 	error = bind(lsock, (struct sockaddr *)&blank_sin6,
652 	    blank_sin6.sin6_len);
653 	assert(error == 0);
654 	error = listen(lsock, 1);
655 	SKTC_ASSERT_ERR(error == 0);
656 	nam_len = sizeof(nam);
657 	error = getsockname(lsock, (struct sockaddr *)&nam, &nam_len);
658 	assert(error == 0);
659 
660 	/* connect the socket, will panic without <rdar://problem/35525592> */
661 	daddr.sin6_addr.__u6_addr.__u6_addr32[3] = handles->netif_addr.s_addr;
662 	daddr.sin6_port = nam.sin6_port; /* listener port */
663 	T_LOG("Skywalk: tcp socket connect to %s :%d (mapped)\n",
664 	    inet_ntop(AF_INET6, &daddr.sin6_addr, ntopbuf, sizeof(ntopbuf)),
665 	    ntohs(daddr.sin6_port));
666 	error = connect(sock, (struct sockaddr *)&daddr, sizeof(daddr));
667 	SKTC_ASSERT_ERR(error == 0);
668 	close(lsock);
669 	close(sock);
670 	T_LOG(" %s done\n", __func__);
671 }
672 
673 static int
skt_flowswitch_ns_reserve_main2(int argc,char * argv[])674 skt_flowswitch_ns_reserve_main2(int argc, char *argv[])
675 {
676 	struct sktc_nexus_handles handles;
677 	union sockaddr_in_4_6 saddr, saddr2;
678 	struct sockaddr_in *sin;
679 	struct sockaddr_in6 *sin6;
680 
681 	srandomdev();
682 
683 	sktc_create_flowswitch(&handles, 0);
684 
685 	/* Use ephemeral port for each step to avoid needing SO_REUSEADDR */
686 
687 	/* Test IPv4 mapped IPv6 address binding */
688 	skt_flowswitch_ns_check_v4mappedv6addr(&handles, 0);
689 
690 	/* Test IPv4-mapped-IPv6 address connect */
691 	skt_flowswitch_ns_check_v4mappedv6addr2(&handles);
692 
693 	/* Test TCP IPv4 wildcard */
694 	memset(&saddr, 0, sizeof(saddr));
695 	sin = &saddr.sin;
696 	sin->sin_len = sizeof(struct sockaddr_in);
697 	sin->sin_family = AF_INET;
698 	sin->sin_port = 0;
699 	sin->sin_addr.s_addr = htonl(INADDR_ANY);
700 	skt_flowswitch_ns_bsd(&handles, IPPROTO_TCP, sin);
701 	sin->sin_port = 0;
702 	skt_flowswitch_ns_sky(&handles, IPPROTO_TCP, sin);
703 
704 	/* Test TCP IPv4 on feth */
705 	sin->sin_port = 0;
706 	sin->sin_addr = handles.netif_addr;
707 	skt_flowswitch_ns_bsd(&handles, IPPROTO_TCP, sin);
708 	sin->sin_port = 0;
709 	skt_flowswitch_ns_sky(&handles, IPPROTO_TCP, sin);
710 
711 	/* Test TCP IPv6 wildcard */
712 	memset(&saddr, 0, sizeof(saddr));
713 	sin6 = &saddr.sin6;
714 	sin6->sin6_len = sizeof(struct sockaddr_in6);
715 	sin6->sin6_family = AF_INET6;
716 	sin6->sin6_port = 0;
717 	memcpy(&sin6->sin6_addr, &in6addr_any, sizeof(sin6->sin6_addr));
718 	skt_flowswitch_ns_bsd(&handles, IPPROTO_TCP, sin6);
719 
720 	/* Test TCP IPv4/IPv6 wildcard */
721 	memset(&saddr, 0, sizeof(saddr));
722 	sin = &saddr.sin;
723 	sin->sin_len = sizeof(struct sockaddr_in);
724 	sin->sin_family = AF_INET;
725 	sin->sin_port = 0;
726 	sin->sin_addr.s_addr = htonl(INADDR_ANY);
727 	memset(&saddr2, 0, sizeof(saddr2));
728 	sin6 = &saddr2.sin6;
729 	sin6->sin6_len = sizeof(struct sockaddr_in6);
730 	sin6->sin6_family = AF_INET6;
731 	sin6->sin6_port = 0;
732 	sin6->sin6_addr = in6addr_any;
733 	skt_flowswitch_ns_sky_bsd(&handles, IPPROTO_TCP, sin, sin6, TRUE,
734 	    ERROR_FLAGS_ASSERT_SUCCESS,
735 	    ERROR_FLAGS_ASSERT_FAILURE,
736 	    FALSE, TRUE);
737 	sin->sin_port = 0;
738 	sin6->sin6_port = 0;
739 	skt_flowswitch_ns_sky_bsd(&handles, IPPROTO_TCP, sin, sin6, FALSE,
740 	    ERROR_FLAGS_ASSERT_FAILURE,
741 	    ERROR_FLAGS_ASSERT_SUCCESS,
742 	    FALSE, TRUE);
743 	sin->sin_port = 0;
744 	sin6->sin6_port = 0;
745 	skt_flowswitch_ns_sky_bsd(&handles, IPPROTO_TCP, sin, sin6, TRUE,
746 	    ERROR_FLAGS_ASSERT_SUCCESS,
747 	    ERROR_FLAGS_ASSERT_SUCCESS,
748 	    TRUE, TRUE);
749 	sin->sin_port = 0;
750 	sin6->sin6_port = 0;
751 	skt_flowswitch_ns_sky_bsd(&handles, IPPROTO_TCP, sin, sin6, FALSE,
752 	    ERROR_FLAGS_ASSERT_FAILURE,
753 	    ERROR_FLAGS_ASSERT_SUCCESS,
754 	    TRUE, TRUE);
755 
756 // Need IPv6 link-local support on feth
757 #if 0
758 	sin6->sin6_port = htons(port);
759 	skt_flowswitch_ns_sky(&handles, IPPROTO_TCP, sin6);
760 	port += 1;
761 
762 	/* Test TCP IPv6 on feth */
763 	sin6->sin6_port = htons(port);
764 	memcpy(&sin6->sin6_addr, &handles->netif_addr6,
765 	    sizeof(sin6->sin6_addr));
766 	skt_flowswitch_ns_bsd(&handles, IPPROTO_TCP, sin6);
767 	port += 1;
768 	sin6->sin6_port = htons(port);
769 	skt_flowswitch_ns_sky(&handles, IPPROTO_TCP, sin6);
770 	port += 1;
771 #endif
772 
773 	/* Test UDP IPv4 wildcard */
774 	memset(&saddr, 0, sizeof(saddr));
775 	sin = &saddr.sin;
776 	sin->sin_len = sizeof(struct sockaddr_in);
777 	sin->sin_family = AF_INET;
778 	sin->sin_port = 0;
779 	sin->sin_addr.s_addr = htonl(INADDR_ANY);
780 	skt_flowswitch_ns_bsd(&handles, IPPROTO_UDP, sin);
781 	sin->sin_port = 0;
782 	skt_flowswitch_ns_sky(&handles, IPPROTO_UDP, sin);
783 
784 	/* Test UDP IPv4 on feth */
785 	sin->sin_port = 0;
786 	sin->sin_addr = handles.netif_addr;
787 	skt_flowswitch_ns_bsd(&handles, IPPROTO_UDP, sin);
788 	sin->sin_port = 0;
789 	skt_flowswitch_ns_sky(&handles, IPPROTO_UDP, sin);
790 
791 	/* Test UDP IPv6 wildcard */
792 	memset(&saddr, 0, sizeof(saddr));
793 	sin6 = &saddr.sin6;
794 	sin6->sin6_len = sizeof(struct sockaddr_in6);
795 	sin6->sin6_family = AF_INET6;
796 	sin6->sin6_port = 0;
797 	memcpy(&sin6->sin6_addr, &in6addr_any, sizeof(sin6->sin6_addr));
798 	skt_flowswitch_ns_bsd(&handles, IPPROTO_UDP, sin6);
799 
800 	/* Test UDP IPv4/IPv6 wildcard */
801 	memset(&saddr, 0, sizeof(saddr));
802 	sin = &saddr.sin;
803 	sin->sin_len = sizeof(struct sockaddr_in);
804 	sin->sin_family = AF_INET;
805 	sin->sin_port = 0;
806 	sin->sin_addr.s_addr = htonl(INADDR_ANY);
807 	memset(&saddr2, 0, sizeof(saddr2));
808 	sin6 = &saddr2.sin6;
809 	sin6->sin6_len = sizeof(struct sockaddr_in6);
810 	sin6->sin6_family = AF_INET6;
811 	sin6->sin6_port = 0;
812 	sin6->sin6_addr = in6addr_any;
813 	skt_flowswitch_ns_sky_bsd(&handles, IPPROTO_UDP, sin, sin6, TRUE,
814 	    ERROR_FLAGS_ASSERT_SUCCESS,
815 	    ERROR_FLAGS_ASSERT_FAILURE,
816 	    FALSE, TRUE);
817 	sin->sin_port = 0;
818 	sin6->sin6_port = 0;
819 	skt_flowswitch_ns_sky_bsd(&handles, IPPROTO_UDP, sin, sin6, FALSE,
820 	    ERROR_FLAGS_ASSERT_FAILURE,
821 	    ERROR_FLAGS_ASSERT_SUCCESS,
822 	    FALSE, TRUE);
823 	sin->sin_port = 0;
824 	sin6->sin6_port = 0;
825 	skt_flowswitch_ns_sky_bsd(&handles, IPPROTO_UDP, sin, sin6, TRUE,
826 	    ERROR_FLAGS_ASSERT_SUCCESS,
827 	    ERROR_FLAGS_ASSERT_SUCCESS,
828 	    TRUE, TRUE);
829 	sin->sin_port = 0;
830 	sin6->sin6_port = 0;
831 	skt_flowswitch_ns_sky_bsd(&handles, IPPROTO_UDP, sin, sin6, FALSE,
832 	    ERROR_FLAGS_ASSERT_FAILURE,
833 	    ERROR_FLAGS_ASSERT_SUCCESS,
834 	    TRUE, TRUE);
835 // Need IPv6 link-local support on feth
836 #if 0
837 	sin6->sin6_port = htons(port);
838 	skt_flowswitch_ns_sky(&handles, IPPROTO_UDP, sin6);
839 	port += 1;
840 
841 	/* Test UDP IPv6 feth */
842 	sin6->sin6_port = htons(port);
843 	memcpy(&sin6->sin6_addr, &handles.netif_addr6,
844 	    sizeof(sin6->sin6_addr));
845 	skt_flowswitch_ns_bsd(&handles, IPPROTO_UDP, sin6);
846 	port += 1;
847 	sin6->sin6_port = htons(port);
848 	skt_flowswitch_ns_sky(&handles, IPPROTO_UDP, sin6);
849 #endif
850 
851 	sktc_cleanup_flowswitch(&handles);
852 
853 	return 0;
854 }
855 
856 #define SKTC_ASSERT_ERR_RETRY(_t, _counter, _retry_label) \
857 do {    \
858 	if (!(_t)) {     \
859 	        T_LOG(\
860 	            "ERROR: %s:%d " #_t ", retry\n", __FILE__, __LINE__);        \
861 	        _counter++;     \
862 	        goto _retry_label;     \
863 	}       \
864 } while (0);
865 
866 #define RETRY_MAX 3
867 
868 static int
skt_flowswitch_ns_reserve_main(int argc,char * argv[])869 skt_flowswitch_ns_reserve_main(int argc, char *argv[])
870 {
871 	char buf0[32], buf1[32];
872 	size_t retries = 0;
873 	int error;
874 	struct sktc_nexus_handles handles;
875 	struct sktc_nexus_handles handles2;
876 	uuid_string_t uuidstr;
877 	struct nx_flow_req nfr;
878 	uuid_t tcp_flow, udp_flow;
879 
880 	struct sockaddr_in sa;
881 	int sock;
882 
883 	srandomdev();
884 
885 start:
886 	memset(&nfr, 0, sizeof(nfr));
887 	nfr.nfr_ip_protocol = IPPROTO_TCP;
888 	nfr.nfr_nx_port = NEXUS_PORT_FLOW_SWITCH_CLIENT; /* first usable */
889 	nfr.nfr_saddr.sa.sa_len = sizeof(struct sockaddr_in);
890 	nfr.nfr_saddr.sa.sa_family = AF_INET;
891 	nfr.nfr_saddr.sin.sin_port = 0; /* pick an ephemeral port */
892 	nfr.nfr_saddr.sin.sin_addr.s_addr = htonl(INADDR_ANY);
893 
894 	T_LOG("--Testing with %s port %d\n",
895 	    (nfr.nfr_ip_protocol == IPPROTO_TCP) ? "tcp" : "udp",
896 	    ntohs(nfr.nfr_saddr.sin.sin_port));
897 
898 	/* bind without flow uuid should fail */
899 	sktc_create_flowswitch(&handles, 0);
900 	(void) inet_ntop(AF_INET, &handles.netif_addr, buf0, sizeof(buf0));
901 	T_LOG("On %s (%s), reserve <ANY,%u> through skywalk "
902 	    "(no flow ID)\n", handles.netif_ifname, buf0,
903 	    ntohs(nfr.nfr_saddr.sin.sin_port));
904 	error = __os_nexus_flow_add(handles.controller,
905 	    handles.fsw_nx_uuid, &nfr);
906 	SKTC_ASSERT_ERR(error == -1 && errno == EINVAL);
907 
908 	uuid_generate_random(tcp_flow);
909 	uuid_generate_random(udp_flow);
910 
911 	/* bind correctly called should succeed */
912 	uuid_copy(nfr.nfr_flow_uuid, tcp_flow);
913 	uuid_unparse_upper(nfr.nfr_flow_uuid, uuidstr);
914 	T_LOG("On %s (%s), reserve <ANY,%u> through skywalk "
915 	    "(flow %s)\n", handles.netif_ifname, buf0,
916 	    ntohs(nfr.nfr_saddr.sin.sin_port), uuidstr);
917 	error = __os_nexus_flow_add(handles.controller,
918 	    handles.fsw_nx_uuid, &nfr);
919 	SKTC_ASSERT_ERR(!error);
920 	assert(htonl(INADDR_ANY) == nfr.nfr_saddr.sin.sin_addr.s_addr);
921 
922 	/* duplicate 2 tuple bind should fail */
923 	(void) inet_ntop(AF_INET, &handles.netif_addr, buf0, sizeof(buf0));
924 	(void) inet_ntop(AF_INET, &nfr.nfr_saddr.sin.sin_addr,
925 	    buf1, sizeof(buf1));
926 	uuid_generate_random(nfr.nfr_flow_uuid);
927 	uuid_unparse_upper(nfr.nfr_flow_uuid, uuidstr);
928 	T_LOG("On %s (%s), confirm <%s,%u> re-binding fails "
929 	    "(flow %s)\n", handles.netif_ifname, buf0, buf1,
930 	    ntohs(nfr.nfr_saddr.sin.sin_port), uuidstr);
931 	error = __os_nexus_flow_add(handles.controller,
932 	    handles.fsw_nx_uuid, &nfr);
933 	SKTC_ASSERT_ERR(error != 0 && (errno == EEXIST || errno == EADDRINUSE));
934 
935 	/* 3 tuple bind sharing the same port should fail */
936 	nfr.nfr_saddr.sin.sin_addr = handles.netif_addr;
937 	(void) inet_ntop(AF_INET, &handles.netif_addr, buf0, sizeof(buf0));
938 	(void) inet_ntop(AF_INET, &nfr.nfr_saddr.sin.sin_addr,
939 	    buf1, sizeof(buf1));
940 	uuid_generate_random(nfr.nfr_flow_uuid);
941 	uuid_unparse_upper(nfr.nfr_flow_uuid, uuidstr);
942 	T_LOG("On %s (%s), confirm <%s,%u> re-binding fails "
943 	    "(flow %s)\n", handles.netif_ifname, buf0, buf1,
944 	    ntohs(nfr.nfr_saddr.sin.sin_port), uuidstr);
945 	error = __os_nexus_flow_add(handles.controller,
946 	    handles.fsw_nx_uuid, &nfr);
947 	SKTC_ASSERT_ERR(error != 0 && (errno == EEXIST || errno == EADDRINUSE));
948 
949 	/* testing with another fsw */
950 	/* bind the same port another fsw is not allowed */
951 	sktc_create_flowswitch(&handles2, 1);
952 	nfr.nfr_saddr.sin.sin_addr.s_addr = htonl(INADDR_ANY);
953 	(void) inet_ntop(AF_INET, &handles2.netif_addr, buf0, sizeof(buf0));
954 	(void) inet_ntop(AF_INET, &nfr.nfr_saddr.sin.sin_addr,
955 	    buf1, sizeof(buf1));
956 	uuid_copy(nfr.nfr_flow_uuid, tcp_flow);
957 	uuid_unparse_upper(nfr.nfr_flow_uuid, uuidstr);
958 	T_LOG("On %s (%s), confirm <%s,%u> binding is not allowed "
959 	    "(flow %s)\n", handles2.netif_ifname, buf0, buf1,
960 	    ntohs(nfr.nfr_saddr.sin.sin_port), uuidstr);
961 	error = __os_nexus_flow_add(handles2.controller,
962 	    handles2.fsw_nx_uuid, &nfr);
963 	//XXX -- [email protected]
964 	// This behavior could change once we add more context(ifnet) into netns
965 	// so that netns becomes the single arbitrator of port resource across
966 	// all ifnet. Then we can allow binding of tuple <any_addr, a_port, if1>
967 	// and <anyaddr, same_port, if2> to go through.
968 	SKTC_ASSERT_ERR(error == -1);
969 	SKTC_ASSERT_ERR(errno == EEXIST || errno == EADDRINUSE);
970 
971 	sktc_cleanup_flowswitch(&handles2);
972 
973 	/* if bound through skywalk, BSD bind should fail */
974 	T_LOG("Confirm port is unavailable to BSD stack\n");
975 	sock = socket(PF_INET,
976 	    (nfr.nfr_ip_protocol == IPPROTO_TCP) ? SOCK_STREAM : SOCK_DGRAM,
977 	    nfr.nfr_ip_protocol);
978 	assert(sock != -1);
979 
980 	memset(&sa, 0, sizeof sa);
981 	sa.sin_family = AF_INET;
982 	sa.sin_port = nfr.nfr_saddr.sin.sin_port;
983 	sa.sin_addr.s_addr = htonl(INADDR_ANY);
984 	error = bind(sock, (struct sockaddr *)&sa, sizeof sa);
985 
986 	SKTC_ASSERT_ERR(error == -1);
987 	SKTC_ASSERT_ERR(errno == EADDRINUSE);
988 
989 	/* bind the same port on UDP, should succeed */
990 	(void) inet_ntop(AF_INET, &handles.netif_addr, buf0, sizeof(buf0));
991 	nfr.nfr_ip_protocol = INVERT_PROTO(nfr.nfr_ip_protocol);
992 	nfr.nfr_saddr.sin.sin_addr.s_addr = htonl(INADDR_ANY);
993 	uuid_copy(nfr.nfr_flow_uuid, udp_flow);
994 	uuid_unparse_upper(nfr.nfr_flow_uuid, uuidstr);
995 	T_LOG("On %s (%s) confirm port number %u is available "
996 	    "on other protocols (flow %s)\n", handles.netif_ifname, buf0,
997 	    ntohs(nfr.nfr_saddr.sin.sin_port), uuidstr);
998 	error = __os_nexus_flow_add(handles.controller,
999 	    handles.fsw_nx_uuid, &nfr);
1000 	SKTC_ASSERT_ERR_RETRY(error == 0, retries, retry);
1001 
1002 	/* release the UDP port binding, should succeed */
1003 	uuid_copy(nfr.nfr_flow_uuid, udp_flow);
1004 	uuid_unparse_upper(nfr.nfr_flow_uuid, uuidstr);
1005 	T_LOG("On %s (%s) release port %u protocol %d (flow %s)\n",
1006 	    handles.netif_ifname, buf0, ntohs(nfr.nfr_saddr.sin.sin_port),
1007 	    nfr.nfr_ip_protocol, uuidstr);
1008 	error = __os_nexus_flow_del(handles.controller,
1009 	    handles.fsw_nx_uuid, &nfr);
1010 	SKTC_ASSERT_ERR(error == 0);
1011 
1012 	/* double release the UDP port binding, should fail */
1013 	uuid_copy(nfr.nfr_flow_uuid, udp_flow);
1014 	uuid_unparse_upper(nfr.nfr_flow_uuid, uuidstr);
1015 	T_LOG("On %s (%s) confirm we can't double-release "
1016 	    "port %u protocol %d (flow %s)\n", handles.netif_ifname, buf0,
1017 	    ntohs(nfr.nfr_saddr.sin.sin_port), nfr.nfr_ip_protocol,
1018 	    uuidstr);
1019 	error = __os_nexus_flow_del(handles.controller,
1020 	    handles.fsw_nx_uuid, &nfr);
1021 	//SKTC_ASSERT_ERR(error != 0);
1022 
1023 	/* Confirm same UDP port is now available on socket */
1024 	T_LOG("Confirm port %u protocol %d is now available to "
1025 	    "BSD stack\n", ntohs(nfr.nfr_saddr.sin.sin_port),
1026 	    nfr.nfr_ip_protocol);
1027 	sock = socket(PF_INET, (nfr.nfr_ip_protocol == IPPROTO_TCP) ?
1028 	    SOCK_STREAM : SOCK_DGRAM, nfr.nfr_ip_protocol);
1029 	SKTC_ASSERT_ERR_RETRY(sock != -1, retries, retry);
1030 
1031 	memset(&sa, 0, sizeof sa);
1032 	sa.sin_family = AF_INET;
1033 	sa.sin_port = nfr.nfr_saddr.sin.sin_port;
1034 	sa.sin_addr.s_addr = htonl(INADDR_ANY);
1035 	error = bind(sock, (struct sockaddr *)&sa, sizeof sa);
1036 	SKTC_ASSERT_ERR(error == 0);
1037 	close(sock);
1038 
1039 	/* release the TCP port skywalk binding */
1040 	nfr.nfr_ip_protocol = INVERT_PROTO(nfr.nfr_ip_protocol);
1041 	uuid_copy(nfr.nfr_flow_uuid, tcp_flow);
1042 	uuid_unparse_upper(nfr.nfr_flow_uuid, uuidstr);
1043 	T_LOG("On %s (%s) release port %u protocol %d (flow %s)\n",
1044 	    handles.netif_ifname, buf0, ntohs(nfr.nfr_saddr.sin.sin_port),
1045 	    nfr.nfr_ip_protocol, uuidstr);
1046 	error = __os_nexus_flow_del(handles.controller,
1047 	    handles.fsw_nx_uuid, &nfr);
1048 	SKTC_ASSERT_ERR(error == 0);
1049 
1050 	/* double release the TCP port binding, should fail */
1051 	uuid_copy(nfr.nfr_flow_uuid, tcp_flow);
1052 	uuid_unparse_upper(nfr.nfr_flow_uuid, uuidstr);
1053 	T_LOG("On %s (%s) confirm we can't double-release "
1054 	    "port %u protocol %d (flow %s)\n", handles.netif_ifname, buf0,
1055 	    ntohs(nfr.nfr_saddr.sin.sin_port), nfr.nfr_ip_protocol,
1056 	    uuidstr);
1057 	error = __os_nexus_flow_del(handles.controller,
1058 	    handles.fsw_nx_uuid, &nfr);
1059 	//SKTC_ASSERT_ERR(error != 0);
1060 
1061 	/* Confirm same TCP port is now available on socket */
1062 	T_LOG("Confirm port %u protocol %d is now available to "
1063 	    "BSD stack\n", ntohs(nfr.nfr_saddr.sin.sin_port),
1064 	    nfr.nfr_ip_protocol);
1065 	sock = socket(PF_INET, (nfr.nfr_ip_protocol == IPPROTO_TCP) ?
1066 	    SOCK_STREAM : SOCK_DGRAM, nfr.nfr_ip_protocol);
1067 	SKTC_ASSERT_ERR_RETRY(sock != -1, retries, retry);
1068 
1069 	memset(&sa, 0, sizeof sa);
1070 	sa.sin_family = AF_INET;
1071 	sa.sin_port = nfr.nfr_saddr.sin.sin_port;
1072 	sa.sin_addr.s_addr = htonl(INADDR_ANY);
1073 
1074 	error = bind(sock, (struct sockaddr *)&sa, sizeof sa);
1075 	SKTC_ASSERT_ERR(error == 0);
1076 
1077 	close(sock);
1078 	retries = 0;
1079 retry:
1080 	sktc_cleanup_flowswitch(&handles);
1081 	if (retries > 0) {
1082 		if (retries < RETRY_MAX) {
1083 			goto start;
1084 		}
1085 		T_LOG("ERROR: exceeds max %d retries\n", RETRY_MAX);
1086 		return -1;
1087 	}
1088 	return 0;
1089 }
1090 
1091 #undef SKTC_ASSERT_ERR_RETRY
1092 #undef RETRY_MAX
1093 
1094 static void
skt_flowswitch_ns_reserve_main2_init(void)1095 skt_flowswitch_ns_reserve_main2_init(void)
1096 {
1097 	sktc_ifnet_feth0_1_create();
1098 	sktc_set_tcp_msl(SKT_TCP_MSL_DELAY);
1099 }
1100 
1101 static void
skt_flowswitch_ns_reserve_main2_cleanup(void)1102 skt_flowswitch_ns_reserve_main2_cleanup(void)
1103 {
1104 	sktc_ifnet_feth0_1_destroy();
1105 	sktc_restore_tcp_msl();
1106 }
1107 
1108 struct skywalk_test skt_flowswitch_ns_reserve = {
1109 	"flowswitch_ns_reserve", "test confirms that flowswitches can reserve L4 ports",
1110 	SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_FLOWSWITCH | SK_FEATURE_NETNS,
1111 	skt_flowswitch_ns_reserve_main, { NULL },
1112 	sktc_ifnet_feth0_1_create, sktc_ifnet_feth0_1_destroy,
1113 };
1114 
1115 struct skywalk_test skt_flowswitch_ns_reserve2 = {
1116 	"flowswitch_ns_reserve2", "throrough test of netns for both BSD & flowswitch, IPv4/v6",
1117 	SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_FLOWSWITCH | SK_FEATURE_NETNS,
1118 	skt_flowswitch_ns_reserve_main2, { NULL },
1119 	skt_flowswitch_ns_reserve_main2_init,
1120 	skt_flowswitch_ns_reserve_main2_cleanup,
1121 };
1122 
1123 /****************************************************************/
1124