xref: /xnu-8020.121.3/bsd/skywalk/nexus/nexus_common.h (revision fdd8201d7b966f0c3ea610489d29bd841d358941)
1 /*
2  * Copyright (c) 2015-2021 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 #ifndef _SKYWALK_NEXUS_COMMON_H_
30 #define _SKYWALK_NEXUS_COMMON_H_
31 
32 #if defined(PRIVATE) || defined(BSD_KERNEL_PRIVATE)
33 /*
34  * Routines common to kernel and userland.  This file is intended to be
35  * included by code implementing the nexus controller logic, in particular,
36  * the Skywalk kernel and libsyscall code.
37  */
38 
39 #include <skywalk/os_nexus_private.h>
40 #include <sys/errno.h>
41 
42 #ifndef KERNEL
43 #if !defined(LIBSYSCALL_INTERFACE)
44 #error "LIBSYSCALL_INTERFACE not defined"
45 #endif /* !LIBSYSCALL_INTERFACE */
46 #endif /* !KERNEL */
47 
48 __attribute__((always_inline))
49 static inline int
__nexus_attr_set(const nexus_attr_t nxa,const nexus_attr_type_t type,const uint64_t value)50 __nexus_attr_set(const nexus_attr_t nxa, const nexus_attr_type_t type,
51     const uint64_t value)
52 {
53 	int err = 0;
54 
55 	if (nxa == NULL) {
56 		return EINVAL;
57 	}
58 
59 	switch (type) {
60 	case NEXUS_ATTR_TX_RINGS:
61 		nxa->nxa_requested |= NXA_REQ_TX_RINGS;
62 		nxa->nxa_tx_rings = value;
63 		break;
64 
65 	case NEXUS_ATTR_RX_RINGS:
66 		nxa->nxa_requested |= NXA_REQ_RX_RINGS;
67 		nxa->nxa_rx_rings = value;
68 		break;
69 
70 	case NEXUS_ATTR_TX_SLOTS:
71 		nxa->nxa_requested |= NXA_REQ_TX_SLOTS;
72 		nxa->nxa_tx_slots = value;
73 		break;
74 
75 	case NEXUS_ATTR_RX_SLOTS:
76 		nxa->nxa_requested |= NXA_REQ_RX_SLOTS;
77 		nxa->nxa_rx_slots = value;
78 		break;
79 
80 	case NEXUS_ATTR_SLOT_BUF_SIZE:
81 		nxa->nxa_requested |= NXA_REQ_BUF_SIZE;
82 		nxa->nxa_buf_size = value;
83 		break;
84 
85 	case NEXUS_ATTR_ANONYMOUS:
86 		nxa->nxa_requested |= NXA_REQ_ANONYMOUS;
87 		nxa->nxa_anonymous = value;
88 		break;
89 
90 	case NEXUS_ATTR_PIPES:
91 		nxa->nxa_requested |= NXA_REQ_PIPES;
92 		nxa->nxa_pipes = value;
93 		break;
94 
95 	case NEXUS_ATTR_EXTENSIONS:
96 		nxa->nxa_requested |= NXA_REQ_EXTENSIONS;
97 		nxa->nxa_extensions = value;
98 		break;
99 
100 	case NEXUS_ATTR_MHINTS:
101 		nxa->nxa_requested |= NXA_REQ_MHINTS;
102 		nxa->nxa_mhints = value;
103 		break;
104 
105 	case NEXUS_ATTR_QMAP:
106 		nxa->nxa_requested |= NXA_REQ_QMAP;
107 		nxa->nxa_qmap = value;
108 		break;
109 
110 	case NEXUS_ATTR_IFINDEX:
111 #if !defined(LIBSYSCALL_INTERFACE)
112 		nxa->nxa_requested |= NXA_REQ_IFINDEX;
113 		nxa->nxa_ifindex = value;
114 #else /* LIBSYSCALL_INTERFACE */
115 		err = ENOTSUP;
116 #endif /* LIBSYSCALL_INTERFACE */
117 		break;
118 
119 	case NEXUS_ATTR_USER_CHANNEL:
120 		nxa->nxa_requested |= NXA_REQ_USER_CHANNEL;
121 		nxa->nxa_user_channel = value;
122 		break;
123 
124 	case NEXUS_ATTR_MAX_FRAGS:
125 		nxa->nxa_requested |= NXA_REQ_MAX_FRAGS;
126 		nxa->nxa_max_frags = value;
127 		break;
128 
129 	case NEXUS_ATTR_REJECT_ON_CLOSE:
130 		nxa->nxa_requested |= NXA_REQ_REJECT_ON_CLOSE;
131 		nxa->nxa_reject_on_close = (value != 0);
132 		break;
133 
134 	case NEXUS_ATTR_FLOWADV_MAX:
135 	case NEXUS_ATTR_STATS_SIZE:
136 	case NEXUS_ATTR_SLOT_META_SIZE:
137 	case NEXUS_ATTR_CHECKSUM_OFFLOAD:
138 	case NEXUS_ATTR_USER_PACKET_POOL:
139 	case NEXUS_ATTR_ADV_SIZE:
140 		err = ENOTSUP;
141 		break;
142 
143 	default:
144 		err = EINVAL;
145 		break;
146 	}
147 
148 	return err;
149 }
150 
151 __attribute__((always_inline))
152 static inline int
__nexus_attr_get(const nexus_attr_t nxa,const nexus_attr_type_t type,uint64_t * value)153 __nexus_attr_get(const nexus_attr_t nxa, const nexus_attr_type_t type,
154     uint64_t *value)
155 {
156 	int err = 0;
157 
158 	if (nxa == NULL || value == NULL) {
159 		return EINVAL;
160 	}
161 
162 	switch (type) {
163 	case NEXUS_ATTR_TX_RINGS:
164 		*value = nxa->nxa_tx_rings;
165 		break;
166 
167 	case NEXUS_ATTR_RX_RINGS:
168 		*value = nxa->nxa_rx_rings;
169 		break;
170 
171 	case NEXUS_ATTR_TX_SLOTS:
172 		*value = nxa->nxa_tx_slots;
173 		break;
174 
175 	case NEXUS_ATTR_RX_SLOTS:
176 		*value = nxa->nxa_rx_slots;
177 		break;
178 
179 	case NEXUS_ATTR_SLOT_BUF_SIZE:
180 		*value = nxa->nxa_buf_size;
181 		break;
182 
183 	case NEXUS_ATTR_SLOT_META_SIZE:
184 		*value = nxa->nxa_meta_size;
185 		break;
186 
187 	case NEXUS_ATTR_STATS_SIZE:
188 		*value = nxa->nxa_stats_size;
189 		break;
190 
191 	case NEXUS_ATTR_FLOWADV_MAX:
192 		*value = nxa->nxa_flowadv_max;
193 		break;
194 
195 	case NEXUS_ATTR_ANONYMOUS:
196 		*value = nxa->nxa_anonymous;
197 		break;
198 
199 	case NEXUS_ATTR_PIPES:
200 		*value = nxa->nxa_pipes;
201 		break;
202 
203 	case NEXUS_ATTR_EXTENSIONS:
204 		*value = nxa->nxa_extensions;
205 		break;
206 
207 	case NEXUS_ATTR_MHINTS:
208 		*value = nxa->nxa_mhints;
209 		break;
210 
211 	case NEXUS_ATTR_IFINDEX:
212 		*value = nxa->nxa_ifindex;
213 		break;
214 
215 	case NEXUS_ATTR_QMAP:
216 		*value = nxa->nxa_qmap;
217 		break;
218 
219 	case NEXUS_ATTR_CHECKSUM_OFFLOAD:
220 		*value = nxa->nxa_checksum_offload;
221 		break;
222 
223 	case NEXUS_ATTR_USER_PACKET_POOL:
224 		*value = nxa->nxa_user_packet_pool;
225 		break;
226 
227 	case NEXUS_ATTR_ADV_SIZE:
228 		*value = nxa->nxa_nexusadv_size;
229 		break;
230 
231 	case NEXUS_ATTR_USER_CHANNEL:
232 		*value = nxa->nxa_user_channel;
233 		break;
234 
235 	case NEXUS_ATTR_MAX_FRAGS:
236 		*value = nxa->nxa_max_frags;
237 		break;
238 
239 	case NEXUS_ATTR_REJECT_ON_CLOSE:
240 		*value = nxa->nxa_reject_on_close;
241 		break;
242 
243 	default:
244 		err = EINVAL;
245 		break;
246 	}
247 
248 	return err;
249 }
250 
251 __attribute__((always_inline))
252 static inline void
__nexus_attr_from_params(nexus_attr_t nxa,const struct nxprov_params * p)253 __nexus_attr_from_params(nexus_attr_t nxa, const struct nxprov_params *p)
254 {
255 	bzero(nxa, sizeof(*nxa));
256 	nxa->nxa_tx_rings = p->nxp_tx_rings;
257 	nxa->nxa_rx_rings = p->nxp_rx_rings;
258 	nxa->nxa_tx_slots = p->nxp_tx_slots;
259 	nxa->nxa_rx_slots = p->nxp_rx_slots;
260 	nxa->nxa_buf_size = p->nxp_buf_size;
261 	nxa->nxa_meta_size = p->nxp_meta_size;
262 	nxa->nxa_stats_size = p->nxp_stats_size;
263 	nxa->nxa_flowadv_max = p->nxp_flowadv_max;
264 	nxa->nxa_anonymous = !!(p->nxp_flags & NXPF_ANONYMOUS);
265 	nxa->nxa_pipes = p->nxp_pipes;
266 	nxa->nxa_extensions = p->nxp_extensions;
267 	nxa->nxa_mhints = p->nxp_mhints;
268 	nxa->nxa_ifindex = p->nxp_ifindex;
269 	nxa->nxa_qmap = p->nxp_qmap;
270 	nxa->nxa_checksum_offload = (p->nxp_capabilities &
271 	    NXPCAP_CHECKSUM_PARTIAL) ? 1 : 0;
272 	nxa->nxa_user_packet_pool = (p->nxp_capabilities &
273 	    NXPCAP_USER_PACKET_POOL) ? 1 : 0;
274 	nxa->nxa_nexusadv_size = p->nxp_nexusadv_size;
275 	nxa->nxa_user_channel = !!(p->nxp_flags & NXPF_USER_CHANNEL);
276 	nxa->nxa_max_frags = p->nxp_max_frags;
277 	nxa->nxa_reject_on_close = (p->nxp_reject_on_close != 0);
278 }
279 
280 __attribute__((always_inline))
281 static inline int
__nexus_provider_reg_prepare(struct nxprov_reg * reg,const nexus_name_t name,const nexus_type_t type,const nexus_attr_t nxa)282 __nexus_provider_reg_prepare(struct nxprov_reg *reg, const nexus_name_t name,
283     const nexus_type_t type, const nexus_attr_t nxa)
284 {
285 	struct nxprov_params *p = &reg->nxpreg_params;
286 	int err = 0;
287 
288 	bzero(reg, sizeof(*reg));
289 	reg->nxpreg_version = NXPROV_REG_CURRENT_VERSION;
290 	p->nxp_namelen = (uint32_t)strlcpy((char *)p->nxp_name,
291 	    (const char *)name, sizeof(nexus_name_t));
292 	if (p->nxp_namelen == 0) {
293 		err = EINVAL;
294 		goto done;
295 	}
296 	p->nxp_type = type;
297 	if (nxa != NULL) {
298 		if (nxa->nxa_requested & NXA_REQ_TX_RINGS) {
299 			reg->nxpreg_requested |= NXPREQ_TX_RINGS;
300 			p->nxp_tx_rings = (uint32_t)nxa->nxa_tx_rings;
301 		}
302 		if (nxa->nxa_requested & NXA_REQ_RX_RINGS) {
303 			reg->nxpreg_requested |= NXPREQ_RX_RINGS;
304 			p->nxp_rx_rings = (uint32_t)nxa->nxa_rx_rings;
305 		}
306 		if (nxa->nxa_requested & NXA_REQ_TX_SLOTS) {
307 			reg->nxpreg_requested |= NXPREQ_TX_SLOTS;
308 			p->nxp_tx_slots = (uint32_t)nxa->nxa_tx_slots;
309 		}
310 		if (nxa->nxa_requested & NXA_REQ_RX_SLOTS) {
311 			reg->nxpreg_requested |= NXPREQ_RX_SLOTS;
312 			p->nxp_rx_slots = (uint32_t)nxa->nxa_rx_slots;
313 		}
314 		if (nxa->nxa_requested & NXA_REQ_BUF_SIZE) {
315 			reg->nxpreg_requested |= NXPREQ_BUF_SIZE;
316 			p->nxp_buf_size = (uint32_t)nxa->nxa_buf_size;
317 		}
318 		if (nxa->nxa_requested & NXA_REQ_ANONYMOUS) {
319 			reg->nxpreg_requested |= NXPREQ_ANONYMOUS;
320 			if (nxa->nxa_anonymous != 0) {
321 				p->nxp_flags |= NXPF_ANONYMOUS;
322 			} else {
323 				p->nxp_flags &= (uint32_t)~NXPF_ANONYMOUS;
324 			}
325 		}
326 		if (nxa->nxa_requested & NXA_REQ_PIPES) {
327 			reg->nxpreg_requested |= NXPREQ_PIPES;
328 			p->nxp_pipes = (uint32_t)nxa->nxa_pipes;
329 		}
330 		if (nxa->nxa_requested & NXA_REQ_EXTENSIONS) {
331 			reg->nxpreg_requested |= NXPREQ_EXTENSIONS;
332 			p->nxp_extensions = (uint32_t)nxa->nxa_extensions;
333 		}
334 		if (nxa->nxa_requested & NXA_REQ_MHINTS) {
335 			reg->nxpreg_requested |= NXPREQ_MHINTS;
336 			p->nxp_mhints = (uint32_t)nxa->nxa_mhints;
337 		}
338 		if (nxa->nxa_requested & NXA_REQ_QMAP) {
339 			if (type != NEXUS_TYPE_NET_IF) {
340 				err = EINVAL;
341 				goto done;
342 			}
343 			if ((nxa->nxa_qmap == NEXUS_QMAP_TYPE_WMM) &&
344 			    (reg->nxpreg_params.nxp_tx_rings !=
345 			    NEXUS_NUM_WMM_QUEUES)) {
346 				err = EINVAL;
347 				goto done;
348 			}
349 			reg->nxpreg_requested |= NXPREQ_QMAP;
350 			p->nxp_qmap = (uint32_t)nxa->nxa_qmap;
351 		}
352 		if (nxa->nxa_requested & NXA_REQ_IFINDEX) {
353 			if (type != NEXUS_TYPE_NET_IF) {
354 				err = EINVAL;
355 				goto done;
356 			}
357 			reg->nxpreg_requested |= NXPREQ_IFINDEX;
358 			p->nxp_ifindex = (uint32_t)nxa->nxa_ifindex;
359 		}
360 		if (nxa->nxa_requested & NXA_REQ_USER_CHANNEL) {
361 			reg->nxpreg_requested |= NXPREQ_USER_CHANNEL;
362 			if (nxa->nxa_user_channel != 0) {
363 				p->nxp_flags |= NXPF_USER_CHANNEL;
364 			} else {
365 				p->nxp_flags &= (uint32_t)~NXPF_USER_CHANNEL;
366 			}
367 		}
368 		if (nxa->nxa_requested & NXA_REQ_MAX_FRAGS) {
369 			if ((type != NEXUS_TYPE_NET_IF) &&
370 			    (type != NEXUS_TYPE_FLOW_SWITCH)) {
371 				err = EINVAL;
372 				goto done;
373 			}
374 			reg->nxpreg_requested |= NXPREQ_MAX_FRAGS;
375 			p->nxp_max_frags = (uint32_t)nxa->nxa_max_frags;
376 		}
377 		if (nxa->nxa_requested & NXA_REQ_REJECT_ON_CLOSE) {
378 			if (type != NEXUS_TYPE_USER_PIPE) {
379 				err = EINVAL;
380 				goto done;
381 			}
382 			reg->nxpreg_requested |= NXPREQ_REJECT_ON_CLOSE;
383 			p->nxp_reject_on_close =
384 			    (nxa->nxa_reject_on_close != 0);
385 		}
386 	}
387 done:
388 	return err;
389 }
390 
391 __attribute__((always_inline))
392 static inline void
__nexus_bind_req_prepare(struct nx_bind_req * nbr,const uuid_t nx_uuid,const nexus_port_t port,const pid_t pid,const uuid_t exec_uuid,const void * key,const uint32_t key_len,const uint32_t bind_flags)393 __nexus_bind_req_prepare(struct nx_bind_req *nbr, const uuid_t nx_uuid,
394     const nexus_port_t port, const pid_t pid, const uuid_t exec_uuid,
395     const void *key, const uint32_t key_len, const uint32_t bind_flags)
396 {
397 	bzero(nbr, sizeof(*nbr));
398 	if (nx_uuid != NULL) {
399 		bcopy(nx_uuid, nbr->nb_nx_uuid, sizeof(uuid_t));
400 	}
401 	if (exec_uuid != NULL) {
402 		bcopy(exec_uuid, nbr->nb_exec_uuid, sizeof(uuid_t));
403 	}
404 	nbr->nb_port = port;
405 	nbr->nb_pid = pid;
406 	if (bind_flags & NEXUS_BIND_PID) {
407 		nbr->nb_flags |= NBR_MATCH_PID;
408 	}
409 	if (bind_flags & NEXUS_BIND_EXEC_UUID) {
410 		nbr->nb_flags |= NBR_MATCH_EXEC_UUID;
411 	}
412 	if (bind_flags & NEXUS_BIND_KEY) {
413 		nbr->nb_flags |= NBR_MATCH_KEY;
414 		nbr->nb_key = (user_addr_t)key;
415 		nbr->nb_key_len = key_len;
416 	}
417 }
418 
419 __attribute__((always_inline))
420 static inline void
__nexus_unbind_req_prepare(struct nx_unbind_req * nbu,const uuid_t nx_uuid,const nexus_port_t port)421 __nexus_unbind_req_prepare(struct nx_unbind_req *nbu, const uuid_t nx_uuid,
422     const nexus_port_t port)
423 {
424 	bzero(nbu, sizeof(*nbu));
425 	if (nx_uuid != NULL) {
426 		bcopy(nx_uuid, nbu->nu_nx_uuid, sizeof(uuid_t));
427 	}
428 	nbu->nu_port = port;
429 }
430 
431 __attribute__((always_inline))
432 static inline void
__nexus_config_req_prepare(struct nx_cfg_req * ncr,const uuid_t nx_uuid,const nxcfg_cmd_t cmd,const void * arg,const size_t arg_len)433 __nexus_config_req_prepare(struct nx_cfg_req *ncr, const uuid_t nx_uuid,
434     const nxcfg_cmd_t cmd, const void *arg, const size_t arg_len)
435 {
436 	VERIFY(arg_len <= UINT32_MAX);
437 	bzero(ncr, sizeof(*ncr));
438 	if (nx_uuid != NULL) {
439 		bcopy(nx_uuid, ncr->nc_nx_uuid, sizeof(uuid_t));
440 	}
441 	ncr->nc_cmd = cmd;
442 	ncr->nc_req_len = (uint32_t)arg_len;
443 	ncr->nc_req = (user_addr_t)arg;
444 }
445 
446 #endif /* PRIVATE || BSD_KERNEL_PRIVATE */
447 #endif /* !_SKYWALK_NEXUS_COMMON_H_ */
448