xref: /xnu-10063.121.3/bsd/skywalk/nexus/nexus_common.h (revision 2c2f96dc2b9a4408a43d3150ae9c105355ca3daa)
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_LARGE_BUF_SIZE:
135 		nxa->nxa_requested |= NXA_REQ_LARGE_BUF_SIZE;
136 		nxa->nxa_large_buf_size = value;
137 		break;
138 
139 	case NEXUS_ATTR_FLOWADV_MAX:
140 	case NEXUS_ATTR_STATS_SIZE:
141 	case NEXUS_ATTR_SLOT_META_SIZE:
142 	case NEXUS_ATTR_CHECKSUM_OFFLOAD:
143 	case NEXUS_ATTR_USER_PACKET_POOL:
144 	case NEXUS_ATTR_ADV_SIZE:
145 		err = ENOTSUP;
146 		break;
147 
148 	default:
149 		err = EINVAL;
150 		break;
151 	}
152 
153 	return err;
154 }
155 
156 __attribute__((always_inline))
157 static inline int
__nexus_attr_get(const nexus_attr_t nxa,const nexus_attr_type_t type,uint64_t * value)158 __nexus_attr_get(const nexus_attr_t nxa, const nexus_attr_type_t type,
159     uint64_t *value)
160 {
161 	int err = 0;
162 
163 	if (nxa == NULL || value == NULL) {
164 		return EINVAL;
165 	}
166 
167 	switch (type) {
168 	case NEXUS_ATTR_TX_RINGS:
169 		*value = nxa->nxa_tx_rings;
170 		break;
171 
172 	case NEXUS_ATTR_RX_RINGS:
173 		*value = nxa->nxa_rx_rings;
174 		break;
175 
176 	case NEXUS_ATTR_TX_SLOTS:
177 		*value = nxa->nxa_tx_slots;
178 		break;
179 
180 	case NEXUS_ATTR_RX_SLOTS:
181 		*value = nxa->nxa_rx_slots;
182 		break;
183 
184 	case NEXUS_ATTR_SLOT_BUF_SIZE:
185 		*value = nxa->nxa_buf_size;
186 		break;
187 
188 	case NEXUS_ATTR_SLOT_META_SIZE:
189 		*value = nxa->nxa_meta_size;
190 		break;
191 
192 	case NEXUS_ATTR_STATS_SIZE:
193 		*value = nxa->nxa_stats_size;
194 		break;
195 
196 	case NEXUS_ATTR_FLOWADV_MAX:
197 		*value = nxa->nxa_flowadv_max;
198 		break;
199 
200 	case NEXUS_ATTR_ANONYMOUS:
201 		*value = nxa->nxa_anonymous;
202 		break;
203 
204 	case NEXUS_ATTR_PIPES:
205 		*value = nxa->nxa_pipes;
206 		break;
207 
208 	case NEXUS_ATTR_EXTENSIONS:
209 		*value = nxa->nxa_extensions;
210 		break;
211 
212 	case NEXUS_ATTR_MHINTS:
213 		*value = nxa->nxa_mhints;
214 		break;
215 
216 	case NEXUS_ATTR_IFINDEX:
217 		*value = nxa->nxa_ifindex;
218 		break;
219 
220 	case NEXUS_ATTR_QMAP:
221 		*value = nxa->nxa_qmap;
222 		break;
223 
224 	case NEXUS_ATTR_CHECKSUM_OFFLOAD:
225 		*value = nxa->nxa_checksum_offload;
226 		break;
227 
228 	case NEXUS_ATTR_USER_PACKET_POOL:
229 		*value = nxa->nxa_user_packet_pool;
230 		break;
231 
232 	case NEXUS_ATTR_ADV_SIZE:
233 		*value = nxa->nxa_nexusadv_size;
234 		break;
235 
236 	case NEXUS_ATTR_USER_CHANNEL:
237 		*value = nxa->nxa_user_channel;
238 		break;
239 
240 	case NEXUS_ATTR_MAX_FRAGS:
241 		*value = nxa->nxa_max_frags;
242 		break;
243 
244 	case NEXUS_ATTR_REJECT_ON_CLOSE:
245 		*value = nxa->nxa_reject_on_close;
246 		break;
247 
248 	case NEXUS_ATTR_LARGE_BUF_SIZE:
249 		*value = nxa->nxa_large_buf_size;
250 		break;
251 
252 	default:
253 		err = EINVAL;
254 		break;
255 	}
256 
257 	return err;
258 }
259 
260 __attribute__((always_inline))
261 static inline void
__nexus_attr_from_params(nexus_attr_t nxa,const struct nxprov_params * p)262 __nexus_attr_from_params(nexus_attr_t nxa, const struct nxprov_params *p)
263 {
264 	bzero(nxa, sizeof(*nxa));
265 	nxa->nxa_tx_rings = p->nxp_tx_rings;
266 	nxa->nxa_rx_rings = p->nxp_rx_rings;
267 	nxa->nxa_tx_slots = p->nxp_tx_slots;
268 	nxa->nxa_rx_slots = p->nxp_rx_slots;
269 	nxa->nxa_buf_size = p->nxp_buf_size;
270 	nxa->nxa_meta_size = p->nxp_meta_size;
271 	nxa->nxa_stats_size = p->nxp_stats_size;
272 	nxa->nxa_flowadv_max = p->nxp_flowadv_max;
273 	nxa->nxa_anonymous = !!(p->nxp_flags & NXPF_ANONYMOUS);
274 	nxa->nxa_pipes = p->nxp_pipes;
275 	nxa->nxa_extensions = p->nxp_extensions;
276 	nxa->nxa_mhints = p->nxp_mhints;
277 	nxa->nxa_ifindex = p->nxp_ifindex;
278 	nxa->nxa_qmap = p->nxp_qmap;
279 	nxa->nxa_checksum_offload = (p->nxp_capabilities &
280 	    NXPCAP_CHECKSUM_PARTIAL) ? 1 : 0;
281 	nxa->nxa_user_packet_pool = (p->nxp_capabilities &
282 	    NXPCAP_USER_PACKET_POOL) ? 1 : 0;
283 	nxa->nxa_nexusadv_size = p->nxp_nexusadv_size;
284 	nxa->nxa_user_channel = !!(p->nxp_flags & NXPF_USER_CHANNEL);
285 	nxa->nxa_max_frags = p->nxp_max_frags;
286 	nxa->nxa_reject_on_close = (p->nxp_reject_on_close != 0);
287 	nxa->nxa_large_buf_size = p->nxp_large_buf_size;
288 }
289 
290 __attribute__((always_inline))
291 static inline int
__nexus_provider_reg_prepare(struct nxprov_reg * reg,const uint8_t * __null_terminated name,const nexus_type_t type,const nexus_attr_t nxa)292 __nexus_provider_reg_prepare(struct nxprov_reg *reg, const uint8_t *__null_terminated name,
293     const nexus_type_t type, const nexus_attr_t nxa)
294 {
295 	struct nxprov_params *p = &reg->nxpreg_params;
296 	int err = 0;
297 
298 	bzero(reg, sizeof(*reg));
299 	reg->nxpreg_version = NXPROV_REG_CURRENT_VERSION;
300 	p->nxp_namelen = (uint32_t)strlcpy((char *)p->nxp_name,
301 	    (const char *__null_terminated)name, sizeof(nexus_name_t));
302 	if (p->nxp_namelen == 0) {
303 		err = EINVAL;
304 		goto done;
305 	}
306 	p->nxp_type = type;
307 	if (nxa != NULL) {
308 		if (nxa->nxa_requested & NXA_REQ_TX_RINGS) {
309 			reg->nxpreg_requested |= NXPREQ_TX_RINGS;
310 			p->nxp_tx_rings = (uint32_t)nxa->nxa_tx_rings;
311 		}
312 		if (nxa->nxa_requested & NXA_REQ_RX_RINGS) {
313 			reg->nxpreg_requested |= NXPREQ_RX_RINGS;
314 			p->nxp_rx_rings = (uint32_t)nxa->nxa_rx_rings;
315 		}
316 		if (nxa->nxa_requested & NXA_REQ_TX_SLOTS) {
317 			reg->nxpreg_requested |= NXPREQ_TX_SLOTS;
318 			p->nxp_tx_slots = (uint32_t)nxa->nxa_tx_slots;
319 		}
320 		if (nxa->nxa_requested & NXA_REQ_RX_SLOTS) {
321 			reg->nxpreg_requested |= NXPREQ_RX_SLOTS;
322 			p->nxp_rx_slots = (uint32_t)nxa->nxa_rx_slots;
323 		}
324 		if (nxa->nxa_requested & NXA_REQ_BUF_SIZE) {
325 			reg->nxpreg_requested |= NXPREQ_BUF_SIZE;
326 			p->nxp_buf_size = (uint32_t)nxa->nxa_buf_size;
327 		}
328 		if (nxa->nxa_requested & NXA_REQ_ANONYMOUS) {
329 			reg->nxpreg_requested |= NXPREQ_ANONYMOUS;
330 			if (nxa->nxa_anonymous != 0) {
331 				p->nxp_flags |= NXPF_ANONYMOUS;
332 			} else {
333 				p->nxp_flags &= (uint32_t)~NXPF_ANONYMOUS;
334 			}
335 		}
336 		if (nxa->nxa_requested & NXA_REQ_PIPES) {
337 			reg->nxpreg_requested |= NXPREQ_PIPES;
338 			p->nxp_pipes = (uint32_t)nxa->nxa_pipes;
339 		}
340 		if (nxa->nxa_requested & NXA_REQ_EXTENSIONS) {
341 			reg->nxpreg_requested |= NXPREQ_EXTENSIONS;
342 			p->nxp_extensions = (uint32_t)nxa->nxa_extensions;
343 		}
344 		if (nxa->nxa_requested & NXA_REQ_MHINTS) {
345 			reg->nxpreg_requested |= NXPREQ_MHINTS;
346 			p->nxp_mhints = (uint32_t)nxa->nxa_mhints;
347 		}
348 		if (nxa->nxa_requested & NXA_REQ_QMAP) {
349 			if (type != NEXUS_TYPE_NET_IF) {
350 				err = EINVAL;
351 				goto done;
352 			}
353 			if ((nxa->nxa_qmap == NEXUS_QMAP_TYPE_WMM) &&
354 			    (reg->nxpreg_params.nxp_tx_rings !=
355 			    NEXUS_NUM_WMM_QUEUES)) {
356 				err = EINVAL;
357 				goto done;
358 			}
359 			reg->nxpreg_requested |= NXPREQ_QMAP;
360 			p->nxp_qmap = (uint32_t)nxa->nxa_qmap;
361 		}
362 		if (nxa->nxa_requested & NXA_REQ_IFINDEX) {
363 			if (type != NEXUS_TYPE_NET_IF) {
364 				err = EINVAL;
365 				goto done;
366 			}
367 			reg->nxpreg_requested |= NXPREQ_IFINDEX;
368 			p->nxp_ifindex = (uint32_t)nxa->nxa_ifindex;
369 		}
370 		if (nxa->nxa_requested & NXA_REQ_USER_CHANNEL) {
371 			reg->nxpreg_requested |= NXPREQ_USER_CHANNEL;
372 			if (nxa->nxa_user_channel != 0) {
373 				p->nxp_flags |= NXPF_USER_CHANNEL;
374 			} else {
375 				p->nxp_flags &= (uint32_t)~NXPF_USER_CHANNEL;
376 			}
377 		}
378 		if (nxa->nxa_requested & NXA_REQ_MAX_FRAGS) {
379 			if ((type != NEXUS_TYPE_NET_IF) &&
380 			    (type != NEXUS_TYPE_FLOW_SWITCH)) {
381 				err = EINVAL;
382 				goto done;
383 			}
384 			reg->nxpreg_requested |= NXPREQ_MAX_FRAGS;
385 			p->nxp_max_frags = (uint32_t)nxa->nxa_max_frags;
386 		}
387 		if (nxa->nxa_requested & NXA_REQ_REJECT_ON_CLOSE) {
388 			if (type != NEXUS_TYPE_USER_PIPE) {
389 				err = EINVAL;
390 				goto done;
391 			}
392 			reg->nxpreg_requested |= NXPREQ_REJECT_ON_CLOSE;
393 			p->nxp_reject_on_close =
394 			    (nxa->nxa_reject_on_close != 0);
395 		}
396 		if (nxa->nxa_requested & NXA_REQ_LARGE_BUF_SIZE) {
397 			reg->nxpreg_requested |= NXPREQ_LARGE_BUF_SIZE;
398 			p->nxp_large_buf_size =
399 			    (uint32_t)nxa->nxa_large_buf_size;
400 		}
401 	}
402 done:
403 	return err;
404 }
405 
406 __attribute__((always_inline))
407 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)408 __nexus_bind_req_prepare(struct nx_bind_req *nbr, const uuid_t nx_uuid,
409     const nexus_port_t port, const pid_t pid, const uuid_t exec_uuid,
410     const void *key, const uint32_t key_len, const uint32_t bind_flags)
411 {
412 	bzero(nbr, sizeof(*nbr));
413 	if (nx_uuid != NULL) {
414 		bcopy(nx_uuid, nbr->nb_nx_uuid, sizeof(uuid_t));
415 	}
416 	if (exec_uuid != NULL) {
417 		bcopy(exec_uuid, nbr->nb_exec_uuid, sizeof(uuid_t));
418 	}
419 	nbr->nb_port = port;
420 	nbr->nb_pid = pid;
421 	if (bind_flags & NEXUS_BIND_PID) {
422 		nbr->nb_flags |= NBR_MATCH_PID;
423 	}
424 	if (bind_flags & NEXUS_BIND_EXEC_UUID) {
425 		nbr->nb_flags |= NBR_MATCH_EXEC_UUID;
426 	}
427 	if (bind_flags & NEXUS_BIND_KEY) {
428 		nbr->nb_flags |= NBR_MATCH_KEY;
429 		nbr->nb_key = (user_addr_t)key;
430 		nbr->nb_key_len = key_len;
431 	}
432 }
433 
434 __attribute__((always_inline))
435 static inline void
__nexus_unbind_req_prepare(struct nx_unbind_req * nbu,const uuid_t nx_uuid,const nexus_port_t port)436 __nexus_unbind_req_prepare(struct nx_unbind_req *nbu, const uuid_t nx_uuid,
437     const nexus_port_t port)
438 {
439 	bzero(nbu, sizeof(*nbu));
440 	if (nx_uuid != NULL) {
441 		bcopy(nx_uuid, nbu->nu_nx_uuid, sizeof(uuid_t));
442 	}
443 	nbu->nu_port = port;
444 }
445 
446 __attribute__((always_inline))
447 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)448 __nexus_config_req_prepare(struct nx_cfg_req *ncr, const uuid_t nx_uuid,
449     const nxcfg_cmd_t cmd, const void *arg, const size_t arg_len)
450 {
451 	VERIFY(arg_len <= UINT32_MAX);
452 	bzero(ncr, sizeof(*ncr));
453 	if (nx_uuid != NULL) {
454 		bcopy(nx_uuid, ncr->nc_nx_uuid, sizeof(uuid_t));
455 	}
456 	ncr->nc_cmd = cmd;
457 	ncr->nc_req_len = (uint32_t)arg_len;
458 	ncr->nc_req = (user_addr_t)arg;
459 }
460 
461 #endif /* PRIVATE || BSD_KERNEL_PRIVATE */
462 #endif /* !_SKYWALK_NEXUS_COMMON_H_ */
463