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 /*
30 * I discovered a couple of issues with __os_nexus_flow_add, so here's some tests
31 */
32
33 #include <assert.h>
34 #include <errno.h>
35 #include <stdio.h>
36 #include <spawn.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <uuid/uuid.h>
40 #include <arpa/inet.h>
41 #include <darwintest.h>
42 #include "skywalk_test_driver.h"
43 #include "skywalk_test_utils.h"
44 #include "skywalk_test_common.h"
45
46 int
skt_fswbind_common(nexus_port_t nx_port1,nexus_port_t nx_port2,bool use_port2)47 skt_fswbind_common(nexus_port_t nx_port1, nexus_port_t nx_port2, bool use_port2)
48 {
49 struct nx_flow_req nfr;
50 struct sktc_nexus_handles handles;
51 uuid_t flow1, flow2;
52 int error;
53 char buf[31];
54 uuid_string_t uuidstr;
55
56 sktc_create_flowswitch(&handles, 0);
57
58 uuid_generate_random(flow1);
59
60 memset(&nfr, 0, sizeof(nfr));
61 nfr.nfr_ip_protocol = IPPROTO_TCP;
62 nfr.nfr_nx_port = nx_port1;
63 nfr.nfr_saddr.sa.sa_len = sizeof(struct sockaddr_in);
64 nfr.nfr_saddr.sa.sa_family = AF_INET;
65 nfr.nfr_saddr.sin.sin_port = htons(0);
66 nfr.nfr_saddr.sin.sin_addr.s_addr = htonl(INADDR_ANY);
67 uuid_copy(nfr.nfr_flow_uuid, flow1);
68
69 uuid_unparse(nfr.nfr_flow_uuid, uuidstr);
70 inet_ntop(AF_INET, &nfr.nfr_saddr.sin.sin_addr.s_addr, buf, sizeof(buf));
71 T_LOG("before: nx_port %3d Flow %s %s addr %s port %d\n",
72 nfr.nfr_nx_port, uuidstr, (nfr.nfr_ip_protocol == IPPROTO_TCP) ? "tcp" : "udp",
73 buf, ntohs(nfr.nfr_saddr.sin.sin_port));
74
75 error = __os_nexus_flow_add(handles.controller, handles.fsw_nx_uuid, &nfr);
76 if (error) {
77 return error;
78 }
79
80 uuid_unparse(nfr.nfr_flow_uuid, uuidstr);
81 inet_ntop(AF_INET, &nfr.nfr_saddr.sin.sin_addr.s_addr, buf, sizeof(buf));
82 T_LOG("after: nx_port %3d Flow %s %s addr %s port %d\n",
83 nfr.nfr_nx_port, uuidstr, (nfr.nfr_ip_protocol == IPPROTO_TCP) ? "tcp" : "udp",
84 buf, ntohs(nfr.nfr_saddr.sin.sin_port));
85
86 assert(nfr.nfr_nx_port == nx_port1 || nx_port1 == NEXUS_PORT_ANY);
87 assert(!uuid_compare(nfr.nfr_flow_uuid, flow1));
88
89 if (use_port2) {
90 uuid_generate_random(flow2);
91
92 memset(&nfr, 0, sizeof(nfr));
93 nfr.nfr_ip_protocol = IPPROTO_TCP;
94 nfr.nfr_nx_port = nx_port2;
95 nfr.nfr_saddr.sa.sa_len = sizeof(struct sockaddr_in);
96 nfr.nfr_saddr.sa.sa_family = AF_INET;
97 nfr.nfr_saddr.sin.sin_port = htons(0);
98 nfr.nfr_saddr.sin.sin_addr.s_addr = htonl(INADDR_ANY);
99 uuid_copy(nfr.nfr_flow_uuid, flow2);
100
101 uuid_unparse(nfr.nfr_flow_uuid, uuidstr);
102 inet_ntop(AF_INET, &nfr.nfr_saddr.sin.sin_addr.s_addr, buf, sizeof(buf));
103 T_LOG("before: nx_port %3d Flow %s %s addr %s port %d\n",
104 nfr.nfr_nx_port, uuidstr, (nfr.nfr_ip_protocol == IPPROTO_TCP) ? "tcp" : "udp",
105 buf, ntohs(nfr.nfr_saddr.sin.sin_port));
106
107 error = __os_nexus_flow_add(handles.controller, handles.fsw_nx_uuid, &nfr);
108 if (error) {
109 return error;
110 }
111
112 uuid_unparse(nfr.nfr_flow_uuid, uuidstr);
113 inet_ntop(AF_INET, &nfr.nfr_saddr.sin.sin_addr.s_addr, buf, sizeof(buf));
114 T_LOG("after: nx_port %3d Flow %s %s addr %s port %d\n",
115 nfr.nfr_nx_port, uuidstr, (nfr.nfr_ip_protocol == IPPROTO_TCP) ? "tcp" : "udp",
116 buf, ntohs(nfr.nfr_saddr.sin.sin_port));
117
118 assert(nfr.nfr_nx_port == nx_port2);
119 assert(!uuid_compare(nfr.nfr_flow_uuid, flow2));
120 }
121
122 memset(&nfr, 0, sizeof(nfr));
123 uuid_copy(nfr.nfr_flow_uuid, flow1);
124
125 error = __os_nexus_flow_del(handles.controller, handles.fsw_nx_uuid, &nfr);
126 SKTC_ASSERT_ERR(!error);
127
128 if (use_port2) {
129 memset(&nfr, 0, sizeof(nfr));
130 uuid_copy(nfr.nfr_flow_uuid, flow2);
131
132 error = __os_nexus_flow_del(handles.controller, handles.fsw_nx_uuid, &nfr);
133 SKTC_ASSERT_ERR(!error);
134 }
135
136 sktc_cleanup_flowswitch(&handles);
137
138 return 0;
139 }
140
141 int
skt_fswbindany_main(int argc,char * argv[])142 skt_fswbindany_main(int argc, char *argv[])
143 {
144 int error = skt_fswbind_common(NEXUS_PORT_ANY, 0, false);
145 SKTC_ASSERT_ERR(!error); /* Expected to pass */
146 return 0;
147 }
148
149 int
skt_fswbind0_main(int argc,char * argv[])150 skt_fswbind0_main(int argc, char *argv[])
151 {
152 int error = skt_fswbind_common(0, 0, false);
153 SKTC_ASSERT_ERR(error); /* Expected to fail */
154 return 0;
155 }
156
157 int
skt_fswbind1_main(int argc,char * argv[])158 skt_fswbind1_main(int argc, char *argv[])
159 {
160 int error = skt_fswbind_common(1, 0, false);
161 SKTC_ASSERT_ERR(error); /* Expected to fail */
162 return 0;
163 }
164
165 int
skt_fswbind512_main(int argc,char * argv[])166 skt_fswbind512_main(int argc, char *argv[])
167 {
168 int error = skt_fswbind_common(512, 0, false);
169 SKTC_ASSERT_ERR(error); /* Expected to fail */
170 return 0;
171 }
172
173 int
skt_fswbind2_main(int argc,char * argv[])174 skt_fswbind2_main(int argc, char *argv[])
175 {
176 int error = skt_fswbind_common(2, 0, false);
177 SKTC_ASSERT_ERR(!error);
178 return 0;
179 }
180
181 int
skt_fswbind5_main(int argc,char * argv[])182 skt_fswbind5_main(int argc, char *argv[])
183 {
184 int error = skt_fswbind_common(5, 0, false);
185 SKTC_ASSERT_ERR(!error);
186 return 0;
187 }
188
189 int
skt_fswbind25_main(int argc,char * argv[])190 skt_fswbind25_main(int argc, char *argv[])
191 {
192 int error = skt_fswbind_common(2, 5, true);
193 SKTC_ASSERT_ERR(!error);
194 return 0;
195 }
196
197 struct skywalk_test skt_fswbindany = {
198 "fswbindany", "attempts to bind to port -1 of flow switch",
199 SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_NETIF | SK_FEATURE_NEXUS_FLOWSWITCH,
200 skt_fswbindany_main, { NULL }, sktc_ifnet_feth0_create, sktc_ifnet_feth0_destroy,
201 };
202
203 struct skywalk_test skt_fswbind0 = {
204 "fswbind0", "attempts to bind to port 0 of flow switch",
205 SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_NETIF | SK_FEATURE_NEXUS_FLOWSWITCH,
206 skt_fswbind0_main, { NULL }, sktc_ifnet_feth0_create, sktc_ifnet_feth0_destroy,
207 };
208
209 struct skywalk_test skt_fswbind1 = {
210 "fswbind1", "attempts to bind to port 1 of flow switch",
211 SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_NETIF | SK_FEATURE_NEXUS_FLOWSWITCH,
212 skt_fswbind1_main, { NULL }, sktc_ifnet_feth0_create, sktc_ifnet_feth0_destroy,
213 };
214
215 struct skywalk_test skt_fswbind512 = {
216 "fswbind512", "attempts to bind to port 512 of flow switch",
217 SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_NETIF | SK_FEATURE_NEXUS_FLOWSWITCH,
218 skt_fswbind512_main, { NULL }, sktc_ifnet_feth0_create, sktc_ifnet_feth0_destroy,
219 };
220
221 struct skywalk_test skt_fswbind2 = {
222 "fswbind2", "attempts to bind to port 2 of flow switch",
223 SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_NETIF | SK_FEATURE_NEXUS_FLOWSWITCH | SK_FEATURE_NETNS,
224 skt_fswbind2_main, { NULL }, sktc_ifnet_feth0_create, sktc_ifnet_feth0_destroy,
225 };
226
227 struct skywalk_test skt_fswbind5 = {
228 "fswbind5", "attempts to bind to port 5 of flow switch",
229 SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_NETIF | SK_FEATURE_NEXUS_FLOWSWITCH | SK_FEATURE_NETNS,
230 skt_fswbind5_main, { NULL }, sktc_ifnet_feth0_create, sktc_ifnet_feth0_destroy,
231 };
232
233 struct skywalk_test skt_fswbind25 = {
234 "fswbind25", "attempts to bind to port 2 and 5 of flow switch",
235 SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_NETIF | SK_FEATURE_NEXUS_FLOWSWITCH | SK_FEATURE_NETNS,
236 skt_fswbind25_main, { NULL }, sktc_ifnet_feth0_create, sktc_ifnet_feth0_destroy,
237 };
238