xref: /xnu-12377.41.6/libsyscall/wrappers/skywalk/os_nexus.c (revision bbb1b6f9e71b8cdde6e5cd6f4841f207dee3d828)
1 /*
2  * Copyright (c) 2015-2022 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 #include <stdlib.h>
31 #include <string.h>
32 #include <strings.h>
33 #include <unistd.h>
34 #include <errno.h>
35 #include <net/if_var.h>
36 #include <skywalk/os_skywalk_private.h>
37 
38 #ifndef LIBSYSCALL_INTERFACE
39 #error "LIBSYSCALL_INTERFACE not defined"
40 #endif /* !LIBSYSCALL_INTERFACE */
41 
42 nexus_attr_t
os_nexus_attr_create(void)43 os_nexus_attr_create(void)
44 {
45 	struct nexus_attr *nxa;
46 
47 	nxa = malloc(sizeof(*nxa));
48 	if (nxa != NULL) {
49 		bzero(nxa, sizeof(*nxa));
50 	}
51 	return nxa;
52 }
53 
54 nexus_attr_t
os_nexus_attr_clone(const nexus_attr_t nxa)55 os_nexus_attr_clone(const nexus_attr_t nxa)
56 {
57 	struct nexus_attr *nnxa = NULL;
58 
59 	nnxa = os_nexus_attr_create();
60 	if (nnxa != NULL && nxa != NULL) {
61 		bcopy(nxa, nnxa, sizeof(*nnxa));
62 	}
63 
64 	return nnxa;
65 }
66 
67 int
os_nexus_attr_set(const nexus_attr_t nxa,const nexus_attr_type_t type,const uint64_t value)68 os_nexus_attr_set(const nexus_attr_t nxa, const nexus_attr_type_t type,
69     const uint64_t value)
70 {
71 	return __nexus_attr_set(nxa, type, value);
72 }
73 
74 int
os_nexus_attr_get(const nexus_attr_t nxa,const nexus_attr_type_t type,uint64_t * value)75 os_nexus_attr_get(const nexus_attr_t nxa, const nexus_attr_type_t type,
76     uint64_t *value)
77 {
78 	return __nexus_attr_get(nxa, type, value);
79 }
80 
81 void
os_nexus_attr_destroy(nexus_attr_t nxa)82 os_nexus_attr_destroy(nexus_attr_t nxa)
83 {
84 	free(nxa);
85 }
86 
87 nexus_controller_t
os_nexus_controller_create(void)88 os_nexus_controller_create(void)
89 {
90 	struct nexus_controller *ncd = NULL;
91 	struct nxctl_init init;
92 	int fd;
93 
94 	bzero(&init, sizeof(init));
95 	init.ni_version = NEXUSCTL_INIT_CURRENT_VERSION;
96 
97 	fd = __nexus_open(&init, sizeof(init));
98 	if (fd == -1) {
99 		goto done;
100 	}
101 
102 	ncd = malloc(sizeof(*ncd));
103 	if (ncd == NULL) {
104 		(void) guarded_close_np(fd, &init.ni_guard);
105 		goto done;
106 	}
107 	bzero(ncd, sizeof(*ncd));
108 	ncd->ncd_fd = fd;
109 	ncd->ncd_guard = init.ni_guard;
110 done:
111 	return ncd;
112 }
113 
114 int
os_nexus_controller_get_fd(const nexus_controller_t ncd)115 os_nexus_controller_get_fd(const nexus_controller_t ncd)
116 {
117 	return ncd->ncd_fd;
118 }
119 
120 int
os_nexus_controller_register_provider(const nexus_controller_t ncd,const nexus_name_t name,const nexus_type_t type,const nexus_attr_t nxa,uuid_t * prov_uuid)121 os_nexus_controller_register_provider(const nexus_controller_t ncd,
122     const nexus_name_t name, const nexus_type_t type,
123     const nexus_attr_t nxa, uuid_t *prov_uuid)
124 {
125 	struct nxprov_reg reg;
126 	int err;
127 
128 	if ((err = __nexus_provider_reg_prepare(&reg, name, type, nxa)) == 0) {
129 		err = __nexus_register(ncd->ncd_fd, &reg, sizeof(reg),
130 		    prov_uuid, sizeof(uuid_t));
131 	}
132 	return err;
133 }
134 
135 int
os_nexus_controller_deregister_provider(const nexus_controller_t ncd,const uuid_t prov_uuid)136 os_nexus_controller_deregister_provider(const nexus_controller_t ncd,
137     const uuid_t prov_uuid)
138 {
139 	return __nexus_deregister(ncd->ncd_fd, prov_uuid, sizeof(uuid_t));
140 }
141 
142 int
os_nexus_controller_alloc_provider_instance(const nexus_controller_t ncd,const uuid_t prov_uuid,uuid_t * nx_uuid)143 os_nexus_controller_alloc_provider_instance(const nexus_controller_t ncd,
144     const uuid_t prov_uuid, uuid_t *nx_uuid)
145 {
146 	return __nexus_create(ncd->ncd_fd, prov_uuid, sizeof(uuid_t),
147 	           nx_uuid, sizeof(uuid_t));
148 }
149 
150 int
os_nexus_controller_free_provider_instance(const nexus_controller_t ncd,const uuid_t nx_uuid)151 os_nexus_controller_free_provider_instance(const nexus_controller_t ncd,
152     const uuid_t nx_uuid)
153 {
154 	return __nexus_destroy(ncd->ncd_fd, nx_uuid, sizeof(uuid_t));
155 }
156 
157 int
os_nexus_controller_bind_provider_instance(const nexus_controller_t ncd,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,uint32_t bind_flags)158 os_nexus_controller_bind_provider_instance(const nexus_controller_t ncd,
159     const uuid_t nx_uuid, const nexus_port_t port, const pid_t pid,
160     const uuid_t exec_uuid, const void *key, const uint32_t key_len,
161     uint32_t bind_flags)
162 {
163 	struct nx_bind_req nbr;
164 
165 	__nexus_bind_req_prepare(&nbr, nx_uuid, port, pid, exec_uuid,
166 	    key, key_len, bind_flags);
167 
168 	return __nexus_set_opt(ncd->ncd_fd, NXOPT_NEXUS_BIND,
169 	           &nbr, sizeof(nbr));
170 }
171 
172 int
os_nexus_controller_unbind_provider_instance(const nexus_controller_t ncd,const uuid_t nx_uuid,const nexus_port_t port)173 os_nexus_controller_unbind_provider_instance(const nexus_controller_t ncd,
174     const uuid_t nx_uuid, const nexus_port_t port)
175 {
176 	struct nx_unbind_req nbu;
177 
178 	__nexus_unbind_req_prepare(&nbu, nx_uuid, port);
179 
180 	return __nexus_set_opt(ncd->ncd_fd, NXOPT_NEXUS_UNBIND,
181 	           &nbu, sizeof(nbu));
182 }
183 
184 int
os_nexus_controller_read_provider_attr(const nexus_controller_t ncd,const uuid_t prov_uuid,nexus_attr_t nxa)185 os_nexus_controller_read_provider_attr(const nexus_controller_t ncd,
186     const uuid_t prov_uuid, nexus_attr_t nxa)
187 {
188 	struct nxprov_reg_ent nre;
189 	uint32_t nre_len = sizeof(nre);
190 	struct nxprov_params *p = &nre.npre_prov_params;
191 	int ret = 0;
192 
193 	if (nxa == NULL) {
194 		return EINVAL;
195 	}
196 
197 	bzero(&nre, sizeof(nre));
198 	bcopy(prov_uuid, nre.npre_prov_uuid, sizeof(uuid_t));
199 	ret = __nexus_get_opt(ncd->ncd_fd, NXOPT_NEXUS_PROV_ENTRY,
200 	    &nre, &nre_len);
201 
202 	if (ret == 0) {
203 		__nexus_attr_from_params(nxa, p);
204 	}
205 
206 	return ret;
207 }
208 
209 static int
add_traffic_rule_inet(const nexus_controller_t ncd,const char * ifname,const struct ifnet_traffic_descriptor_inet * td,const struct ifnet_traffic_rule_action_steer * ra,const uint32_t flags,uuid_t * rule_uuid)210 add_traffic_rule_inet(const nexus_controller_t ncd,
211     const char *ifname, const struct ifnet_traffic_descriptor_inet *td,
212     const struct ifnet_traffic_rule_action_steer *ra, const uint32_t flags,
213     uuid_t *rule_uuid)
214 {
215 	struct nxctl_add_traffic_rule_inet_iocargs args;
216 	int err;
217 
218 	bzero(&args, sizeof(args));
219 	if (ifname != NULL) {
220 		(void) strlcpy(args.atri_ifname, ifname, IFNAMSIZ);
221 	}
222 	bcopy(td, &args.atri_td, sizeof(args.atri_td));
223 	bcopy(ra, &args.atri_ra, sizeof(args.atri_ra));
224 
225 	if ((flags & NXCTL_ADD_TRAFFIC_RULE_FLAG_PERSIST) != 0) {
226 		args.atri_flags |= NXIOC_ADD_TRAFFIC_RULE_FLAG_PERSIST;
227 	}
228 	err = ioctl(ncd->ncd_fd, NXIOC_ADD_TRAFFIC_RULE_INET, &args);
229 	if (err < 0) {
230 		return errno;
231 	}
232 	bcopy(&args.atri_uuid, rule_uuid, sizeof(args.atri_uuid));
233 	return 0;
234 }
235 
236 static int
add_traffic_rule_eth(const nexus_controller_t ncd,const char * ifname,const struct ifnet_traffic_descriptor_eth * td,const struct ifnet_traffic_rule_action_steer * ra,const uint32_t flags,uuid_t * rule_uuid)237 add_traffic_rule_eth(const nexus_controller_t ncd,
238     const char *ifname, const struct ifnet_traffic_descriptor_eth *td,
239     const struct ifnet_traffic_rule_action_steer *ra, const uint32_t flags,
240     uuid_t *rule_uuid)
241 {
242 	struct nxctl_add_traffic_rule_eth_iocargs args;
243 	int err;
244 
245 	bzero(&args, sizeof(args));
246 	if (ifname != NULL) {
247 		(void) strlcpy(args.atre_ifname, ifname, IFNAMSIZ);
248 	}
249 	bcopy(td, &args.atre_td, sizeof(args.atre_td));
250 	bcopy(ra, &args.atre_ra, sizeof(args.atre_ra));
251 
252 	if ((flags & NXCTL_ADD_TRAFFIC_RULE_FLAG_PERSIST) != 0) {
253 		args.atre_flags |= NXIOC_ADD_TRAFFIC_RULE_FLAG_PERSIST;
254 	}
255 	err = ioctl(ncd->ncd_fd, NXIOC_ADD_TRAFFIC_RULE_ETH, &args);
256 	if (err < 0) {
257 		return errno;
258 	}
259 	bcopy(&args.atre_uuid, rule_uuid, sizeof(args.atre_uuid));
260 	return 0;
261 }
262 
263 int
os_nexus_controller_add_traffic_rule(const nexus_controller_t ncd,const char * ifname,const struct ifnet_traffic_descriptor_common * td,const struct ifnet_traffic_rule_action * ra,const uint32_t flags,uuid_t * rule_uuid)264 os_nexus_controller_add_traffic_rule(const nexus_controller_t ncd,
265     const char *ifname, const struct ifnet_traffic_descriptor_common *td,
266     const struct ifnet_traffic_rule_action *ra, const uint32_t flags,
267     uuid_t *rule_uuid)
268 {
269 	/* only support the steer action for now */
270 	if (ra->ra_type != IFNET_TRAFFIC_RULE_ACTION_STEER) {
271 		return ENOTSUP;
272 	}
273 	if (ra->ra_len != sizeof(struct ifnet_traffic_rule_action_steer)) {
274 		return EINVAL;
275 	}
276 	/* only support the inet descriptor type for now */
277 	switch (td->itd_type) {
278 	case IFNET_TRAFFIC_DESCRIPTOR_TYPE_INET: {
279 		if (td->itd_len !=
280 		    sizeof(struct ifnet_traffic_descriptor_inet)) {
281 			return EINVAL;
282 		}
283 		return add_traffic_rule_inet(ncd, ifname,
284 		           (const struct ifnet_traffic_descriptor_inet *)td,
285 		           (const struct ifnet_traffic_rule_action_steer *)ra,
286 		           flags, rule_uuid);
287 	}
288 	case IFNET_TRAFFIC_DESCRIPTOR_TYPE_ETH: {
289 		if (td->itd_len !=
290 		    sizeof(struct ifnet_traffic_descriptor_eth)) {
291 			return EINVAL;
292 		}
293 		return add_traffic_rule_eth(ncd, ifname,
294 		           (const struct ifnet_traffic_descriptor_eth *)td,
295 		           (const struct ifnet_traffic_rule_action_steer *)ra,
296 		           flags, rule_uuid);
297 	}
298 	default:
299 		return ENOTSUP;
300 	}
301 }
302 
303 int
os_nexus_controller_remove_traffic_rule(const nexus_controller_t ncd,const uuid_t rule_uuid)304 os_nexus_controller_remove_traffic_rule(const nexus_controller_t ncd,
305     const uuid_t rule_uuid)
306 {
307 	struct nxctl_remove_traffic_rule_iocargs args;
308 	int err;
309 
310 	bzero(&args, sizeof(args));
311 	bcopy(rule_uuid, &args.rtr_uuid, sizeof(args.rtr_uuid));
312 
313 	err = ioctl(ncd->ncd_fd, NXIOC_REMOVE_TRAFFIC_RULE, &args);
314 	if (err < 0) {
315 		return errno;
316 	}
317 	return 0;
318 }
319 
320 static boolean_t
rule_iterate(struct nxctl_traffic_rule_generic_iocinfo * ginfo,struct ifnet_traffic_descriptor_common * td,struct ifnet_traffic_rule_action * ra,nexus_traffic_rule_iterator_t itr,void * itr_arg)321 rule_iterate(struct nxctl_traffic_rule_generic_iocinfo *ginfo,
322     struct ifnet_traffic_descriptor_common *td,
323     struct ifnet_traffic_rule_action *ra,
324     nexus_traffic_rule_iterator_t itr, void *itr_arg)
325 {
326 	struct nexus_traffic_rule_info itr_info;
327 
328 	bzero(&itr_info, sizeof(itr_info));
329 	itr_info.nri_rule_uuid = &ginfo->trg_uuid;
330 	itr_info.nri_owner = ginfo->trg_procname;
331 	itr_info.nri_ifname = ginfo->trg_ifname;
332 	itr_info.nri_td = td;
333 	itr_info.nri_ra = ra;
334 
335 	if (!itr(itr_arg, &itr_info)) {
336 		return false;
337 	}
338 	return true;
339 }
340 
341 static void
inet_rule_iterate(void * buf,uint32_t count,nexus_traffic_rule_iterator_t itr,void * itr_arg)342 inet_rule_iterate(void *buf, uint32_t count,
343     nexus_traffic_rule_iterator_t itr, void *itr_arg)
344 {
345 	struct nxctl_traffic_rule_inet_iocinfo *info = buf;
346 
347 	for (uint32_t c = 0; c < count; c++) {
348 		if (!rule_iterate(&info->tri_common, &info->tri_td.inet_common,
349 		    &info->tri_ra.ras_common, itr, itr_arg)) {
350 			break;
351 		}
352 		info++;
353 	}
354 }
355 
356 static void
eth_rule_iterate(void * buf,uint32_t count,nexus_traffic_rule_iterator_t itr,void * itr_arg)357 eth_rule_iterate(void *buf, uint32_t count,
358     nexus_traffic_rule_iterator_t itr, void *itr_arg)
359 {
360 	struct nxctl_traffic_rule_eth_iocinfo *info = buf;
361 
362 	for (uint32_t c = 0; c < count; c++) {
363 		if (!rule_iterate(&info->tre_common, &info->tre_td.eth_common,
364 		    &info->tre_ra.ras_common, itr, itr_arg)) {
365 			break;
366 		}
367 		info++;
368 	}
369 }
370 
371 struct traffic_rule_type {
372 	uint8_t tr_type;
373 	uint32_t tr_size;
374 	uint32_t tr_count;
375 	void (*tr_iterate)(void *, uint32_t,
376 	    nexus_traffic_rule_iterator_t, void *);
377 };
378 #define NTRDEFAULTCOUNT 512
379 static struct traffic_rule_type traffic_rule_types[] = {
380 	{IFNET_TRAFFIC_DESCRIPTOR_TYPE_INET,
381 	 sizeof(struct nxctl_traffic_rule_inet_iocinfo),
382 	 NTRDEFAULTCOUNT, inet_rule_iterate},
383 	{IFNET_TRAFFIC_DESCRIPTOR_TYPE_ETH,
384 	 sizeof(struct nxctl_traffic_rule_eth_iocinfo),
385 	 NTRDEFAULTCOUNT, eth_rule_iterate},
386 };
387 #define NTRTYPES (sizeof(traffic_rule_types)/sizeof(struct traffic_rule_type))
388 
389 int
os_nexus_controller_iterate_traffic_rules(const nexus_controller_t ncd,nexus_traffic_rule_iterator_t itr,void * itr_arg)390 os_nexus_controller_iterate_traffic_rules(const nexus_controller_t ncd,
391     nexus_traffic_rule_iterator_t itr, void *itr_arg)
392 {
393 	struct nxctl_get_traffic_rules_iocargs args;
394 	struct traffic_rule_type *t;
395 	int i, err;
396 
397 	for (i = 0; i < NTRTYPES; i++) {
398 		t = &traffic_rule_types[i];
399 		bzero(&args, sizeof(args));
400 		args.gtr_type = t->tr_type;
401 		args.gtr_size = t->tr_size;
402 		args.gtr_count = t->tr_count;
403 		args.gtr_buf = malloc(args.gtr_size * args.gtr_count);
404 		if (args.gtr_buf == NULL) {
405 			return ENOMEM;
406 		}
407 		err = ioctl(ncd->ncd_fd, NXIOC_GET_TRAFFIC_RULES, &args);
408 		if (err < 0) {
409 			err = errno;
410 			free(args.gtr_buf);
411 			return err;
412 		}
413 		if (args.gtr_count > 0) {
414 			t->tr_iterate(args.gtr_buf, args.gtr_count,
415 			    itr, itr_arg);
416 		}
417 		free(args.gtr_buf);
418 	}
419 	return 0;
420 }
421 
422 void
os_nexus_controller_destroy(nexus_controller_t ncd)423 os_nexus_controller_destroy(nexus_controller_t ncd)
424 {
425 	if (ncd->ncd_fd != -1) {
426 		(void) guarded_close_np(ncd->ncd_fd, &ncd->ncd_guard);
427 	}
428 	free(ncd);
429 }
430 
431 int
__os_nexus_ifattach(const nexus_controller_t ncd,const uuid_t nx_uuid,const char * ifname,const uuid_t netif_uuid,boolean_t host,uuid_t * nx_if_uuid)432 __os_nexus_ifattach(const nexus_controller_t ncd,
433     const uuid_t nx_uuid, const char *ifname, const uuid_t netif_uuid,
434     boolean_t host, uuid_t *nx_if_uuid)
435 {
436 	struct nx_cfg_req ncr;
437 	struct nx_spec_req nsr;
438 	int ret;
439 
440 	bzero(&nsr, sizeof(nsr));
441 	if (ifname != NULL) {
442 		(void) strlcpy(nsr.nsr_name, ifname, sizeof(nsr.nsr_name));
443 	} else {
444 		bcopy(netif_uuid, nsr.nsr_uuid, sizeof(uuid_t));
445 		nsr.nsr_flags |= NXSPECREQ_UUID;
446 	}
447 
448 	if (host) {
449 		nsr.nsr_flags |= NXSPECREQ_HOST;
450 	}
451 
452 	__nexus_config_req_prepare(&ncr, nx_uuid, NXCFG_CMD_ATTACH,
453 	    &nsr, sizeof(nsr));
454 
455 	ret = __nexus_set_opt(ncd->ncd_fd, NXOPT_NEXUS_CONFIG,
456 	    &ncr, sizeof(ncr));
457 
458 	if (ret == 0) {
459 		bcopy(nsr.nsr_if_uuid, nx_if_uuid, sizeof(uuid_t));
460 	}
461 
462 	return ret;
463 }
464 
465 int
__os_nexus_ifdetach(const nexus_controller_t ncd,const uuid_t nx_uuid,const uuid_t nx_if_uuid)466 __os_nexus_ifdetach(const nexus_controller_t ncd, const uuid_t nx_uuid,
467     const uuid_t nx_if_uuid)
468 {
469 	struct nx_cfg_req ncr;
470 	struct nx_spec_req nsr;
471 
472 	bzero(&nsr, sizeof(nsr));
473 	bcopy(nx_if_uuid, nsr.nsr_if_uuid, sizeof(uuid_t));
474 
475 	__nexus_config_req_prepare(&ncr, nx_uuid, NXCFG_CMD_DETACH,
476 	    &nsr, sizeof(nsr));
477 
478 	return __nexus_set_opt(ncd->ncd_fd, NXOPT_NEXUS_CONFIG,
479 	           &ncr, sizeof(ncr));
480 }
481 
482 int
__os_nexus_flow_add(const nexus_controller_t ncd,const uuid_t nx_uuid,const struct nx_flow_req * nfr)483 __os_nexus_flow_add(const nexus_controller_t ncd, const uuid_t nx_uuid,
484     const struct nx_flow_req *nfr)
485 {
486 	struct nx_cfg_req ncr;
487 
488 	__nexus_config_req_prepare(&ncr, nx_uuid, NXCFG_CMD_FLOW_ADD,
489 	    nfr, sizeof(*nfr));
490 
491 	return __nexus_set_opt(ncd->ncd_fd, NXOPT_NEXUS_CONFIG,
492 	           &ncr, sizeof(ncr));
493 }
494 
495 int
__os_nexus_flow_del(const nexus_controller_t ncd,const uuid_t nx_uuid,const struct nx_flow_req * nfr)496 __os_nexus_flow_del(const nexus_controller_t ncd, const uuid_t nx_uuid,
497     const struct nx_flow_req *nfr)
498 {
499 	struct nx_cfg_req ncr;
500 
501 	__nexus_config_req_prepare(&ncr, nx_uuid, NXCFG_CMD_FLOW_DEL,
502 	    nfr, sizeof(*nfr));
503 
504 	return __nexus_set_opt(ncd->ncd_fd, NXOPT_NEXUS_CONFIG,
505 	           &ncr, sizeof(ncr));
506 }
507 
508 static int
__os_nexus_config_flow(const uuid_t nx_uuid,struct nx_flow_req * nfr)509 __os_nexus_config_flow(const uuid_t nx_uuid, struct nx_flow_req *nfr)
510 {
511 	struct nx_cfg_req ncr;
512 
513 	__nexus_config_req_prepare(&ncr, nx_uuid, NXCFG_CMD_FLOW_CONFIG,
514 	    nfr, sizeof(*nfr));
515 
516 	return __nexus_set_opt(__OS_NEXUS_SHARED_USER_CONTROLLER_FD,
517 	           NXOPT_NEXUS_CONFIG, &ncr, sizeof(ncr));
518 }
519 
520 int
os_nexus_flow_set_wake_from_sleep(const uuid_t nx_uuid,const uuid_t flow_uuid,bool enable)521 os_nexus_flow_set_wake_from_sleep(const uuid_t nx_uuid, const uuid_t flow_uuid,
522     bool enable)
523 {
524 	struct nx_flow_req nfr = {0};
525 	memcpy(nfr.nfr_flow_uuid, flow_uuid, sizeof(uuid_t));
526 	nfr.nfr_flags = enable ? 0 : NXFLOWREQF_NOWAKEFROMSLEEP;
527 
528 	return __os_nexus_config_flow(nx_uuid, &nfr);
529 }
530 
531 int
__os_nexus_get_llink_info(const nexus_controller_t ncd,const uuid_t nx_uuid,const struct nx_llink_info_req * nlir,size_t len)532 __os_nexus_get_llink_info(const nexus_controller_t ncd, const uuid_t nx_uuid,
533     const struct nx_llink_info_req *nlir, size_t len)
534 {
535 	struct nx_cfg_req ncr;
536 
537 	__nexus_config_req_prepare(&ncr, nx_uuid, NXCFG_CMD_GET_LLINK_INFO,
538 	    nlir, len);
539 
540 	return __nexus_set_opt(ncd->ncd_fd, NXOPT_NEXUS_CONFIG,
541 	           &ncr, sizeof(ncr));
542 }
543 
544 int
os_nexus_flow_set_connection_idle(const uuid_t nx_uuid,const uuid_t flow_uuid,bool enable)545 os_nexus_flow_set_connection_idle(const uuid_t nx_uuid, const uuid_t flow_uuid,
546     bool enable)
547 {
548 	struct nx_flow_req nfr = {0};
549 	memcpy(nfr.nfr_flow_uuid, flow_uuid, sizeof(uuid_t));
550 	nfr.nfr_flags = enable ? NXFLOWREQF_CONNECTION_IDLE :
551 	    NXFLOWREQF_CONNECTION_REUSED;
552 
553 	return __os_nexus_config_flow(nx_uuid, &nfr);
554 }
555