/* * Copyright (c) 2015-2022 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. The rights granted to you under the License * may not be used to create, or enable the creation or redistribution of, * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ #ifndef _SKYWALK_OS_NEXUS_H_ #define _SKYWALK_OS_NEXUS_H_ #ifdef PRIVATE #include #include #include #include #include #ifdef KERNEL_PRIVATE struct ifnet_interface_advisory; #endif /* KERNEL_PRIVATE */ struct ifnet_traffic_descriptor_common; struct ifnet_traffic_rule_action; /* * Nexus terminology and overview. The relationship between the objects are * as follows: * * domain --> domain_provider --> nexus_provider --> nexus * * Skywalk comes with several nexus domains (types). Each domain has one or * more domain providers; the system comes with a built-in (default) domain * provider per domain. Additional domain providers may be attached, but * this ability is reserved to kernel subsystems. The domain specifies the * nexus semantics, including the permitted topology, number and definition * of ports, memory regions, etc. * * Each domain provider may have one or more nexus providers registered to it. * This allows different parameters (rings, slots, buffer metadata) to be * configured on a per-nexus provider basis. * * Nexus instances can then be allocated based on a registered nexus provider. * All instances associated with a given nexus provider share the same set of * parameters that are configured for that nexus provider. * * Channels are then opened to nexus instances. */ /* * Nexus types. * * Userland code may only register Nexus providers against the USER_PIPE * and FLOW_SWITCH types. The rest are reserved for kernel subsystems. */ typedef enum { NEXUS_TYPE_USER_PIPE, /* pipe (user) */ NEXUS_TYPE_KERNEL_PIPE, /* pipe (kernel) */ NEXUS_TYPE_NET_IF, /* network interface (kernel) */ NEXUS_TYPE_FLOW_SWITCH, /* flow switch (user/kernel) */ #ifdef BSD_KERNEL_PRIVATE /* * Monitor nexus isn't directly usable on its own; we just * need a type definition here for it to act as a pseudo * domain provider. */ NEXUS_TYPE_MONITOR, /* monitor (user) */ NEXUS_TYPE_MAX, /* this needs to be last */ NEXUS_TYPE_UNDEFINED = -1, /* for kernel internal use */ #endif /* BSD_KERNEL_PRIVATE */ } nexus_type_t; /* * Nexus provider name. */ typedef uint8_t nexus_name_t[64]; /* * Nexus instance port. */ typedef uint16_t nexus_port_t; /* * User pipe Nexus has at most two ports: one client and server. */ #define NEXUS_PORT_USER_PIPE_CLIENT 0 #define NEXUS_PORT_USER_PIPE_SERVER 1 /* * Kernel pipe Nexus has at most one port for the client. */ #define NEXUS_PORT_KERNEL_PIPE_CLIENT 0 /* * Network Interface Nexus can have any number of ports. * Port 0 and 1 are reserved for DEV and HOST. The other ports * (2 and above) can be of the types: filter, custom ethertype, * or low latency. */ #define NEXUS_PORT_NET_IF_DEV 0 #define NEXUS_PORT_NET_IF_HOST 1 #define NEXUS_PORT_NET_IF_CLIENT 2 /* * Flow switch has its first N ports reserved; the following is the first * client usable port. The last usable depends on the configured number * of nexus ports. */ #define NEXUS_PORT_FLOW_SWITCH_CLIENT 2 /* * Opaque handles. */ struct nexus_controller; struct nexus_attr; typedef struct nexus_controller *nexus_controller_t; typedef struct nexus_attr *nexus_attr_t; /* * Nexus attribute types. */ typedef enum { NEXUS_ATTR_TX_RINGS, /* (g/s) # of transmit rings */ NEXUS_ATTR_RX_RINGS, /* (g/s) # of receive rings */ NEXUS_ATTR_TX_SLOTS, /* (g/s) # of slots per transmit ring */ NEXUS_ATTR_RX_SLOTS, /* (g/s) # of slots per receive ring */ NEXUS_ATTR_SLOT_BUF_SIZE, /* (g/s) buffer per slot (bytes) */ NEXUS_ATTR_SLOT_META_SIZE, /* (g) metadata per slot (bytes) */ NEXUS_ATTR_ANONYMOUS, /* (g/s) allow anonymous clients */ NEXUS_ATTR_MHINTS, /* (g/s) memory usage hints */ NEXUS_ATTR_PIPES, /* (g/s) # of pipes */ NEXUS_ATTR_EXTENSIONS, /* (g/s) extension-specific attr */ NEXUS_ATTR_IFINDEX, /* (g) network interface index */ NEXUS_ATTR_STATS_SIZE, /* (g) statistics region size (bytes) */ NEXUS_ATTR_FLOWADV_MAX, /* (g) max flow advisory entries */ NEXUS_ATTR_QMAP, /* (g/s) queue mapping type */ NEXUS_ATTR_CHECKSUM_OFFLOAD, /* (g) partial checksum offload */ NEXUS_ATTR_USER_PACKET_POOL, /* (g) user packet pool */ NEXUS_ATTR_ADV_SIZE, /* (g) nexus advisory region size */ NEXUS_ATTR_USER_CHANNEL, /* (g/s) allow user channel open */ NEXUS_ATTR_MAX_FRAGS, /* (g/s) max fragments in a packets */ /* * (g/s) reject channel operations on nexus if the peer has closed * the channel. * The os channel will appear as defunct to the active peer. */ NEXUS_ATTR_REJECT_ON_CLOSE, NEXUS_ATTR_LARGE_BUF_SIZE, /* (g/s) size of large buffer (bytes) */ } nexus_attr_type_t; /* * XXX: this is temporary and should be removed later. */ #define OS_NEXUS_HAS_USER_PACKET_POOL 1 /* * Memory usage hint attributes that can be specified for NEXUS_ATTR_MHINTS * These can be OR'ed to specified multiple hints */ /* No hint, default behaviour */ #define NEXUS_MHINTS_NORMAL 0x0 /* Application expects to access the channels soon */ #define NEXUS_MHINTS_WILLNEED 0x1 /* Application expects low latency for bursty traffic */ #define NEXUS_MHINTS_LOWLATENCY 0x2 /* Application expects high usage of channel memory */ #define NEXUS_MHINTS_HIUSE 0x4 /* * Extension attributes. */ typedef enum { NEXUS_EXTENSION_TYPE_MAXTYPE = 0, } nexus_extension_t; /* * Nexus queue mapping types. */ typedef enum { NEXUS_QMAP_TYPE_INVALID = 0, /* invalid type */ NEXUS_QMAP_TYPE_DEFAULT, /* 10:1 mapping */ NEXUS_QMAP_TYPE_WMM, /* 802.11 WMM */ } nexus_qmap_type_t; #define NEXUS_NUM_WMM_QUEUES 4 /* number of WMM access categories */ /* * Nexus buffer metadata template. * * Each Nexus provider implementation will define an overlay of this structure; * the top of the structure always begins with this common area. The contents * of this common area, as well as the rest of the per-buffer metadata region * are left to the provider to define. * * This structure is aligned for efficient copy and accesses. */ typedef struct nexus_mdata { union { uuid_t __uuid; /* flow UUID */ uint8_t __val8[16]; uint16_t __val16[8]; uint32_t __val32[4]; uint64_t __val64[2]; } __flowid_u; #define nm_flowid_uuid __flowid_u.__uuid #define nm_flowid_val8 __flowid_u.__val8 #define nm_flowid_val16 __flowid_u.__val16 #define nm_flowid_val32 __flowid_u.__val32 #define nm_flowid_val64 __flowid_u.__val64 } nexus_mdata_t __attribute((aligned(8))); /* * Nexus bind flags. */ #define NEXUS_BIND_PID 0x1 /* bind to a process ID */ #define NEXUS_BIND_EXEC_UUID 0x2 /* bind to a process exec's UUID */ #define NEXUS_BIND_KEY 0x4 /* bind to a key blob */ /* * Maximum length of key blob (in bytes). */ #define NEXUS_MAX_KEY_LEN 1024 #ifndef KERNEL /* * User APIs. */ #if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) __BEGIN_DECLS /* * Creates a Nexus attribute object. * * This must be paired with a os_nexus_attr_destroy() on the handle. */ extern nexus_attr_t os_nexus_attr_create(void); /* * Clones a Nexus attribute object. If source attribute is NULL * it behaves just like os_nexus_attr_create(); * * This must be paired with a os_nexus_attr_destroy() on the handle. */ extern nexus_attr_t os_nexus_attr_clone(const nexus_attr_t attr); /* * Sets a value for a given attribute type on a Nexus attribute object. */ extern int os_nexus_attr_set(nexus_attr_t attr, const nexus_attr_type_t type, const uint64_t value); /* * Gets a value for a given attribute type on a Nexus attribute object. */ extern int os_nexus_attr_get(const nexus_attr_t attr, const nexus_attr_type_t type, uint64_t *value); /* * Destroys a Nexus attribute object. */ extern void os_nexus_attr_destroy(nexus_attr_t attr); /* * Opens a handle to the Nexus controller. * * This must be paired with a os_nexus_controller_destroy() on the handle, in * order to remove any remaining active providers and free resources. */ extern nexus_controller_t os_nexus_controller_create(void); /* * Retrieves the file descriptor associated with the Nexus controller. */ extern int os_nexus_controller_get_fd(const nexus_controller_t ctl); /* * Registers a Nexus provider. * * Anonymous Nexus provider mode implies the freedom to connect to the Nexus * instance from any channel client. Alternatively, named mode requires the * Nexus provider to explicitly bind a Nexus instance port to a set of client * attributes. This mode (named) is the default behavior, and is done so to * encourage Nexus providers to explicitly know about the clients that it's * communicating with. Specifying anonymous mode can be done via the Nexus * attribute NEXUS_ATTR_ANONYMOUS, by setting it to a non-zero value. * * The client binding attributes include the process ID, the executable UUID, * and/or a key blob. Only a client possessing those will be allowed to open * a channel to the Nexus instance port. */ extern int os_nexus_controller_register_provider(const nexus_controller_t ctl, const nexus_name_t name, const nexus_type_t type, const nexus_attr_t attr, uuid_t *prov_uuid); /* * Deregisters a Nexus provider. */ extern int os_nexus_controller_deregister_provider(const nexus_controller_t ctl, const uuid_t prov_uuid); /* * Creates a Nexus instance of a registered provider. */ extern int os_nexus_controller_alloc_provider_instance( const nexus_controller_t ctl, const uuid_t prov_uuid, uuid_t *nx_uuid); /* * Destroys a Nexus instance. */ extern int os_nexus_controller_free_provider_instance( const nexus_controller_t ctl, const uuid_t nx_uuid); /* * Bind a port of a Nexus instance to one or more attributes associated with * a channel client: process ID, process executable's UUID, or key blob. * This is only applicable to named Nexus provider. * * Binding to a process ID implies allowing only a channel client with such * PID to open the Nexus port. * * Binding to an executable UUID allows a channel client (regardless of PID * or instance) with such executable UUID to open the Nexus port. When this * is requested by a provider that doesn't have the client's executable UUID, * a valid client PID must be provided (with the executable UUID zeroed out) * in order for the kernel to retrieve the executable UUID from the process * and to use that as the bind attribute. Else, a non-zero executable UUID * can be specified (PID is ignored in this case) by the provider. * * Binding to a key blob allows a channel client possessing the identical * key blob to open the Nexus port. The key blob is opaque to the system, * and is left to the Nexus provider to interpret and relay to its client. * * A Nexus provider must choose to select one or a combination of those * attributes for securing access to a port of a named Nexus instance. * The provider is also responsible for detecting if the client has gone * away, and either to unbind the Nexus instance port indefinitely, or * reissue another bind with the new client binding attributes for that * same port. This is to handle cases where the client terminates and * is expected to reattach to the same port. * * All port bindings belonging to a Nexus instance will be automatically * removed when the Nexus instance is destroyed. */ extern int os_nexus_controller_bind_provider_instance( const nexus_controller_t ctl, 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); /* * Unbind a previously-bound port of a Nexus instance. This is only * applicable to named Nexus provider. A previously-bound Nexus instance * port cannot be bound again until this call is issued. */ extern int os_nexus_controller_unbind_provider_instance( const nexus_controller_t ctl, const uuid_t nx_uuid, const nexus_port_t port); /* * Retrieves current Nexus provider attributes into the nexus_attr_t handle. */ extern int os_nexus_controller_read_provider_attr(const nexus_controller_t ctl, const uuid_t prov_uuid, nexus_attr_t attr); /* * Traffic rules APIs. */ /* Persist after controller close. */ #define NXCTL_ADD_TRAFFIC_RULE_FLAG_PERSIST 0x0001 extern int os_nexus_controller_add_traffic_rule(const nexus_controller_t ctl, 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); extern int os_nexus_controller_remove_traffic_rule(const nexus_controller_t ctl, const uuid_t rule_uuid); struct nexus_traffic_rule_info { uuid_t *nri_rule_uuid; char *nri_owner; char *nri_ifname; struct ifnet_traffic_descriptor_common *nri_td; struct ifnet_traffic_rule_action *nri_ra; uint32_t nri_flags; }; /* Return TRUE to continue, FALSE to exit. */ typedef boolean_t (nexus_traffic_rule_iterator_t)(void *, const struct nexus_traffic_rule_info *); extern int os_nexus_controller_iterate_traffic_rules(const nexus_controller_t ctl, nexus_traffic_rule_iterator_t itr, void *itr_arg); /* * Destroys a Nexus controller handle. */ extern void os_nexus_controller_destroy(nexus_controller_t ctl); __END_DECLS #endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ #else /* KERNEL */ /* * Kernel APIs. */ #include #include /* * Nexus domain provider name. */ typedef uint8_t nexus_domain_provider_name_t[64]; /* * Opaque handles. */ struct nxctl; struct kern_slot_prop; struct kern_nexus; struct kern_nexus_provider; struct kern_nexus_domain_provider; struct kern_channel; struct __kern_channel_ring; struct __slot_desc; struct __pbufpool; typedef struct kern_pbufpool *kern_pbufpool_t; typedef struct kern_nexus *kern_nexus_t; typedef struct kern_nexus_provider *kern_nexus_provider_t; typedef struct kern_nexus_domain_provider *kern_nexus_domain_provider_t; typedef struct kern_channel *kern_channel_t; typedef struct __kern_channel_ring *kern_channel_ring_t; typedef struct __slot_desc *kern_channel_slot_t; typedef struct netif_llink *kern_netif_llink_t; typedef struct netif_qset *kern_netif_qset_t; typedef struct netif_queue *kern_netif_queue_t; /* * Domain provider callback routines. */ /* * @typedef nxdom_prov_init_fn_t * @abstract Domain provider initializer callback. * @param domprov Domain provider handle. * @discussion This will be called after kern_nexus_register_domain_provider(). * @result Non-zero result will abort the domain provider registration. */ typedef errno_t (*nxdom_prov_init_fn_t)(kern_nexus_domain_provider_t domprov); /* * @typedef nxdom_prov_fini_fn_t * @abstract Domain provider teardown callback. * @param domprov Domain provider handle. * @discussion This will happen after kern_nexus_deregister_domain_provider(). * A provider must not unload or free resources associated to the domain * provider instance until this callback is invoked. */ typedef void (*nxdom_prov_fini_fn_t)(kern_nexus_domain_provider_t domprov); /* * Domain provider init. */ struct kern_nexus_domain_provider_init { uint32_t nxdpi_version; /* current version */ uint32_t nxdpi_flags; /* for future */ nxdom_prov_init_fn_t nxdpi_init; /* required */ nxdom_prov_fini_fn_t nxdpi_fini; /* required */ }; #define KERN_NEXUS_DOMAIN_PROVIDER_VERSION_1 1 #define KERN_NEXUS_DOMAIN_PROVIDER_NETIF 2 #define KERN_NEXUS_DOMAIN_PROVIDER_CURRENT_VERSION \ KERN_NEXUS_DOMAIN_PROVIDER_VERSION_1 /* * Nexus provider callback routines. */ /* * @typedef nxprov_pre_connect_fn_t * @abstract Nexus provider channel connecting callback. * @param nexus_prov Nexus provider handle. * @param proc The process associated with the channel. * @param nexus The nexus instance. * @param channel The channel that has been created and being connected * to the nexus instances's port. * @param channel_context Pointer to provider-specific context that can be * associated with the channel. Upon a successful return, this can * later be retrieved via subsequent calls to kern_channel_get_context(). * @result Non-zero result will deny the channel from being connected. * @discussion This is invoked when a channel is opened to the nexus port. * Upon success, client's ring and slot callbacks will be called. * The channel is not usable until the nxprov_connected_fn_t() is * invoked. Client must refrain from channel activities until then. */ typedef errno_t (*nxprov_pre_connect_fn_t)(kern_nexus_provider_t nexus_prov, proc_t proc, kern_nexus_t nexus, nexus_port_t port, kern_channel_t channel, void **channel_context); /* * @typedef nxprov_connected_fn_t * @abstract Nexus provider channel connected callback. * @param nexus_prov Nexus provider handle. * @param nexus The nexus instance. * @param channel The channel that has been created and fully connected * to the nexus instances's port. * @result Non-zero result will deny the channel from being connected. * @discussion This is invoked when all ring and slot initializations have * been completed, and that the channel is ready for activities. */ typedef errno_t (*nxprov_connected_fn_t)(kern_nexus_provider_t nexus_prov, kern_nexus_t nexus, kern_channel_t channel); /* * @typedef nxprov_pre_disconnect_fn_t * @abstract Nexus provider channel disconnecting callback. * @param nexus_prov Nexus provider handle. * @param nexus The nexus instance. * @param channel The channel that has been decommissioned. * @param channel_context The context that was originally set o the channel * at the time nxprov_pre_connect_fn_t() callback was invoked. * @discussion Following this call, all ring and slot finish callbacks will * be invoked. Client must quiesce all channel activities upon getting * this callback. The final disconnect completion will be indicated * through a call to the nxprov_disconnected_fn_t() callback. */ typedef void (*nxprov_pre_disconnect_fn_t)(kern_nexus_provider_t nexus_prov, kern_nexus_t nexus, kern_channel_t channel); /* * @typedef nxprov_disconnected_fn_t * @abstract Nexus provider channel disconnect callback. * @param nexus_prov Nexus provider handle. * @param nexus The nexus instance. * @param channel The channel that has been decommissioned. * @param channel_context The context that was originally set o the channel * at the time nxprov_pre_connect_fn_t() callback was invoked. * @discussion The provider must free any resources associated with the * channel context set at nxprov_pre_connect_fn_t() time, since the channel * instance is no longer valid upon return. */ typedef void (*nxprov_disconnected_fn_t)(kern_nexus_provider_t nexus_prov, kern_nexus_t nexus, kern_channel_t channel); /* * @typedef nxprov_ring_init_fn_t * @abstract Nexus provider ring setup callback. * @param nexus_prov Nexus provider handle. * @param nexus The nexus instance. * @param channel The channel associated with the ring. * @param ring The ring that has been prepared. * @param is_tx_ring True if ring is used for TX direction, otherwise RX. * @param ring_id Ring identification number. * @param ring_context Pointer to provider-specific context that can be * associated with the ring. Upon a successful return, this context * can later be retrieved via subsequent calls to * kern_channel_ring_get_context(). * @result Non-zero result will abort the ring initialization. */ typedef errno_t (*nxprov_ring_init_fn_t)(kern_nexus_provider_t nexus_prov, kern_nexus_t nexus, kern_channel_t channel, kern_channel_ring_t ring, boolean_t is_tx_ring, void **ring_context); /* * @typedef nxprov_ring_fini_fn_t * @abstract Nexus provider ring teardown callback. * @param nexus_prov Nexus provider handle. * @param nexus The nexus instance. * @param channel The channel associated with the ring. * @param ring The ring that has been decommissioned. * @discussion The provider must free any resources associated with the * ring context set at nxprov_ring_init_fn_t() time, since the ring is * no longer valid upon return. This call will be issued after all * slots belonging to the ring has been decommisioned, via * nxprov_slot_fini_fn_t(). */ typedef void (*nxprov_ring_fini_fn_t)(kern_nexus_provider_t nexus_prov, kern_nexus_t nexus, kern_channel_ring_t ring); /* * @typedef nxprov_slot_init_fn_t * @abstract Nexus provider channel slot setup callback. * @param nexus_prov Nexus provider handle. * @param nexus The nexus instance. * @param ring The ring associated with the slot. * @param slot The slot that has been prepared. * @param slot_index The index of the slot in the ring. * @param slot_prop_addr This has been deprecated; callee must set to NULL. * @param slot_context Pointer to provider-specific context that can be * associated with the slot in the given ring. Upon a successful return, * this context can later be retrieved via subsequent calls to * kern_channel_slot_get_context(). * @result Non-zero result will abort the slot initialization. */ typedef errno_t (*nxprov_slot_init_fn_t)(kern_nexus_provider_t nexus_prov, kern_nexus_t nexus, kern_channel_ring_t ring, kern_channel_slot_t slot, uint32_t slot_index, struct kern_slot_prop **slot_prop_addr, void **slot_context); /* * @typedef nxprov_slot_fini_fn_t * @abstract Nexus provider channel slot teardown callback. * @param nexus_prov Nexus provider handle. * @param nexus The nexus instance. * @param ring The ring associated with the slot. * @param slot The slot that has been decommissioned. * @param slot_index The index of the slot in the ring. * @discussion The provider must free any resources associated with the * slot context set at nxprov_slot_init_fn_t() time, since the slot * instance is no longer valid upon return. */ typedef void (*nxprov_slot_fini_fn_t)(kern_nexus_provider_t nexus_prov, kern_nexus_t nexus, kern_channel_ring_t ring, kern_channel_slot_t slot, uint32_t slot_index); /* * @typedef nxprov_sync_tx_fn_t * @abstract Nexus provider channel sync (TX) callback. * @param nexus_prov Nexus provider handle. * @param nexus The nexus instance. * @param ring The ring associated with the slot. * @param flags See KERN_NEXUS_SYNCF flags. */ typedef errno_t (*nxprov_sync_tx_fn_t)(kern_nexus_provider_t nexus_prov, kern_nexus_t nexus, kern_channel_ring_t ring, uint32_t flags); /* * @typedef nxprov_sync_rx_fn_t * @abstract Nexus provider channel sync (RX) callback. * @param nexus_prov Nexus provider handle. * @param nexus The nexus instance. * @param ring The ring associated with the slot. * @param flags See KERN_NEXUS_SYNCF flags. */ typedef errno_t (*nxprov_sync_rx_fn_t)(kern_nexus_provider_t nexus_prov, kern_nexus_t nexus, kern_channel_ring_t ring, uint32_t flags); /* * Valid flags for {tx,rx}sync callbacks. */ #define KERN_NEXUS_SYNCF_COMMIT 0x1 /* force reclaim/update */ /* * @typedef nxprov_tx_doorbell_fn_t * @abstract Nexus provider TX doorbell callback, required for netif. * @param nexus_prov Nexus provider handle. * @param nexus The nexus instance. * @param ring The ring associated with the doorbell. * @param flags See KERN_NEXUS_TXDOORBELLF flags. */ typedef errno_t (*nxprov_tx_doorbell_fn_t)(kern_nexus_provider_t nexus_prov, kern_nexus_t nexus, kern_channel_ring_t ring, uint32_t flags); /* * Valid flags for tx doorbell callback. */ /* call kern_channel_tx_refill() in async context */ #define KERN_NEXUS_TXDOORBELLF_ASYNC_REFILL 0x1 /* * @typedef nxprov_sync_packets_fn_t * @abstract Nexus provider get packets callback, required for netif. * @param nexus_prov Nexus provider handle. * @param nexus The nexus instance. * @param ring The device ring. * @param packets Array of packet chains * @param count: * RX: caller sets this to the array size. on return, this count * is set to actual number of packets returned. * TX: not implemented * @param flags none for now. */ typedef errno_t (*nxprov_sync_packets_fn_t)(kern_nexus_provider_t nexus_prov, kern_nexus_t nexus, kern_channel_ring_t ring, uint64_t packets[], uint32_t *count, uint32_t flags); /* * @typedef nxprov_capab_config_fn_t * @abstract Nexus provider capabilities configuration callback, * required for netif. * @param nexus_prov Nexus provider handle. * @param nexus The nexus instance. * @param capab The capability being queried. * @param contents Structure describing the capability. * @param len Input: length of buffer for holding contents. * Output: length of actual size of contents. */ typedef enum { /* periodic interface advisory notifications */ KERN_NEXUS_CAPAB_INTERFACE_ADVISORY = 1, /* extends queue set functionality: e.g. notify steering info */ KERN_NEXUS_CAPAB_QSET_EXTENSIONS, } kern_nexus_capab_t; typedef errno_t (*nxprov_capab_config_fn_t)(kern_nexus_provider_t nexus_prov, kern_nexus_t nexus, kern_nexus_capab_t capab, void *contents, uint32_t *len); /* * struct kern_nexus_capab_interface_advisory * @abstract Interface advisory capability configuration callback. * @param kncia_version Version of the capability structure. * @param kncia_notify The notification interface provided by kernel. * @param kncia_config The configuration interface provided by nexus provider. */ #define KERN_NEXUS_CAPAB_INTERFACE_ADVISORY_VERSION_1 1 typedef errno_t (*kern_nexus_capab_interface_advisory_config_fn_t)( void *provider_context, bool enable); typedef errno_t (*kern_nexus_capab_interface_advisory_notify_fn_t)( void *kern_context, const struct ifnet_interface_advisory *adv_info); struct kern_nexus_capab_interface_advisory { uint32_t kncia_version; void * const kncia_kern_context; void *kncia_provider_context; const kern_nexus_capab_interface_advisory_notify_fn_t kncia_notify; kern_nexus_capab_interface_advisory_config_fn_t kncia_config; }; /* * struct kern_nexus_capab_qset_extensions * @abstract qset extensions configuration callback. * @param cqe_version Version of the capability structure. * @param cqe_notify_steering_info callback provided by nexus provider. * @param cqe_prov_ctx provider context for the above callback. */ #define KERN_NEXUS_CAPAB_QSET_EXTENSIONS_VERSION_1 1 typedef errno_t (*kern_nexus_capab_qsext_notify_steering_info_fn_t)( void *provider_context, void *qset_context, struct ifnet_traffic_descriptor_common *td, bool add); struct kern_nexus_capab_qset_extensions { uint32_t cqe_version; void *cqe_prov_ctx; kern_nexus_capab_qsext_notify_steering_info_fn_t cqe_notify_steering_info; }; /* * Nexus provider init (version 1) */ struct kern_nexus_provider_init { uint32_t nxpi_version; /* current version */ uint32_t nxpi_flags; /* see NXPIF_* */ nxprov_pre_connect_fn_t nxpi_pre_connect; /* required */ nxprov_connected_fn_t nxpi_connected; /* required */ nxprov_pre_disconnect_fn_t nxpi_pre_disconnect; /* required */ nxprov_disconnected_fn_t nxpi_disconnected; /* required */ nxprov_ring_init_fn_t nxpi_ring_init; /* optional */ nxprov_ring_fini_fn_t nxpi_ring_fini; /* optional */ nxprov_slot_init_fn_t nxpi_slot_init; /* optional */ nxprov_slot_fini_fn_t nxpi_slot_fini; /* optional */ nxprov_sync_tx_fn_t nxpi_sync_tx; /* required */ nxprov_sync_rx_fn_t nxpi_sync_rx; /* required */ nxprov_tx_doorbell_fn_t nxpi_tx_doorbell; /* required (netif) */ nxprov_sync_packets_fn_t nxpi_rx_sync_packets; /* optional (netif) */ nxprov_sync_packets_fn_t nxpi_tx_sync_packets; /* optional (netif) */ nxprov_capab_config_fn_t nxpi_config_capab; /* optional (netif) */ }; /* * @typedef nxprov_qset_init_fn_t * @abstract Nexus provider netif qset setup callback. * @param nexus_prov Nexus provider handle. * @param nexus The nexus instance. * @param llink_ctx The context associated with the logical link owning this * qset (provider owned). Retreived during logical link * creation. * @param qset_idx The index of the qset within this logical link. * @param qset_id The encoded id of the qset. Meant to be propagated to userspace * and passed down later during qset selection. * @param qset The netif qset to be initialized (xnu owned). Meant to be * used for upcalls to xnu. * @param qset_ctx The qset context (provider owned output arg). Meant to * be used for downcalls to the provider involving this qset. * @result Non-zero result will abort the queue initialization. */ typedef errno_t (*nxprov_qset_init_fn_t)(kern_nexus_provider_t nexus_prov, kern_nexus_t nexus, void *llink_ctx, uint8_t qset_idx, uint64_t qset_id, kern_netif_qset_t qset, void **qset_ctx); /* * @typedef nxprov_qset_fini_fn_t * @abstract Nexus provider netif qset teardown callback. * @param nexus_prov Nexus provider handle. * @param nexus The nexus instance. * @param qset_ctx The qset context retrieved from nxprov_qset_init_fn_t * (provider owned). * @discussion The provider must free any resources associated with the * qset context set at nxprov_qset_init_fn_t() time, since the qset is * no longer valid upon return. */ typedef void (*nxprov_qset_fini_fn_t)(kern_nexus_provider_t nexus_prov, kern_nexus_t nexus, void *qset_ctx); /* * @typedef nxprov_queue_init_fn_t * @abstract Nexus provider netif queue setup callback. * @param nexus_prov Nexus provider handle. * @param nexus The nexus instance. * @param qset_ctx The context associated with the qset owning this queue * (provider owned). Retreived from nxprov_qset_init_fn_t. * @param qidx The index of the queue within this qset. * @param queue The netif queue to be initialized (xnu owned). Meant to be * used for upcalls to xnu. * @param tx True if the queue is used for TX direction, otherwise RX. * @param queue_ctx The queue context (provider owned output arg). Meant to * be used for downcalls to the provider involving this queue. * @result Non-zero result will abort the queue initialization. */ typedef errno_t (*nxprov_queue_init_fn_t)(kern_nexus_provider_t nexus_prov, kern_nexus_t nexus, void *qset_ctx, uint8_t qidx, bool tx, kern_netif_queue_t queue, void **queue_ctx); /* * @typedef nxprov_queue_fini_fn_t * @abstract Nexus provider netif queue teardown callback. * @param nexus_prov Nexus provider handle. * @param nexus The nexus instance. * @param queue_ctx The queue context retrieved from nxprov_queue_init_fn_t * (provider owned). * @discussion The provider must free any resources associated with the * queue context set at nxprov_queue_init_fn_t() time, since the queue is * no longer valid upon return. */ typedef void (*nxprov_queue_fini_fn_t)(kern_nexus_provider_t nexus_prov, kern_nexus_t nexus, void *queue_ctx); /* * @typedef nxprov_tx_qset_notify_fn_t * @abstract Nexus provider TX notify callback, required for netif. * @param nexus_prov Nexus provider handle. * @param nexus The nexus instance. * @param qset_ctx The qset_ctx owned by the qset to be notified (provider * owned). Retrieved from nxprov_qset_init_fn_t. * @param flags unused for now. */ typedef errno_t (*nxprov_tx_qset_notify_fn_t)(kern_nexus_provider_t nexus_prov, kern_nexus_t nexus, void *qset_ctx, uint32_t flags); /* * Nexus provider initialization parameters specific to netif (version 2) */ struct kern_nexus_netif_provider_init { uint32_t nxnpi_version; /* current version */ uint32_t nxnpi_flags; /* see NXPIF_* */ nxprov_pre_connect_fn_t nxnpi_pre_connect; /* required */ nxprov_connected_fn_t nxnpi_connected; /* required */ nxprov_pre_disconnect_fn_t nxnpi_pre_disconnect; /* required */ nxprov_disconnected_fn_t nxnpi_disconnected; /* required */ nxprov_qset_init_fn_t nxnpi_qset_init; /* required */ nxprov_qset_fini_fn_t nxnpi_qset_fini; /* required */ nxprov_queue_init_fn_t nxnpi_queue_init; /* required */ nxprov_queue_fini_fn_t nxnpi_queue_fini; /* required */ nxprov_tx_qset_notify_fn_t nxnpi_tx_qset_notify; /* required */ nxprov_capab_config_fn_t nxnpi_config_capab; /* required */ }; #define KERN_NEXUS_PROVIDER_VERSION_1 1 #define KERN_NEXUS_PROVIDER_VERSION_NETIF 2 /* specific to netif */ #define KERN_NEXUS_PROVIDER_CURRENT_VERSION KERN_NEXUS_PROVIDER_VERSION_1 /* * Valid values for nxpi_flags. */ #define NXPIF_VIRTUAL_DEVICE 0x1 /* device is virtual (no DMA) */ #define NXPIF_MONOLITHIC 0x4 /* single segment mode */ #define NXPIF_INHIBIT_CACHE 0x8 /* caching-inhibited */ /* * Network Interface Nexus instance callback routines. */ /* * @typedef nxnet_prepare_fn_t * @abstract Network Interface nexus instance preparer callback. * @param nexus The nexus instance. * @param ifp The interface associated with the nexus instance. * @discussion The prepare callback routine specified by nxneti_prepare will * be invoked on a newly-allocated interface that is not yet attached. * A non-zero value returned by the callback routine will abort the * operation; otherwise, the interface will then be associated with * the nexus prior to being fully attached to the system. */ typedef errno_t (*nxnet_prepare_fn_t)(kern_nexus_t nexus, ifnet_t ifp); /* * Nexus (Non-Networking) instance init. * * If supplied, packet buffer pool must have been created as KBIF_QUANTUM. */ struct kern_nexus_init { uint32_t nxi_version; /* current version */ uint32_t nxi_flags; /* see NXIF_* */ kern_pbufpool_t nxi_tx_pbufpool; /* optional */ kern_pbufpool_t nxi_rx_pbufpool; /* optional */ }; #define KERN_NEXUS_VERSION_1 1 #define KERN_NEXUS_CURRENT_VERSION KERN_NEXUS_VERSION_1 /* * Network Interface Nexus instance init. * * If supplied, packet buffer pool must NOT have been created as KBIF_QUANTUM. * packet buffer pool is a required parameter if the nexus provider is * operating in netif logical link mode. */ struct kern_nexus_net_init { uint32_t nxneti_version; /* current version */ uint32_t nxneti_flags; /* see NXNETF_* */ struct ifnet_init_eparams *nxneti_eparams; /* required */ struct sockaddr_dl *nxneti_lladdr; /* optional */ nxnet_prepare_fn_t nxneti_prepare; /* optional */ kern_pbufpool_t nxneti_tx_pbufpool; /* optional */ kern_pbufpool_t nxneti_rx_pbufpool; /* optional */ struct kern_nexus_netif_llink_init *nxneti_llink; /* optional */ }; #define KERN_NEXUS_NET_VERSION_1 1 #define KERN_NEXUS_NET_VERSION_2 2 #define KERN_NEXUS_NET_CURRENT_VERSION KERN_NEXUS_NET_VERSION_1 struct kern_nexus_netif_llink_qset_init { uint32_t nlqi_flags; uint8_t nlqi_num_rxqs; uint8_t nlqi_num_txqs; }; /* * nxnetllq_flags values. */ /* default qset of the logical link */ #define KERN_NEXUS_NET_LLINK_QSET_DEFAULT 0x1 /* qset needs AQM */ #define KERN_NEXUS_NET_LLINK_QSET_AQM 0x2 /* qset is low latency */ #define KERN_NEXUS_NET_LLINK_QSET_LOW_LATENCY 0x4 /* qset in WMM mode */ #define KERN_NEXUS_NET_LLINK_QSET_WMM_MODE 0x8 typedef uint64_t kern_nexus_netif_llink_id_t; struct kern_nexus_netif_llink_init { uint32_t nli_flags; uint8_t nli_num_qsets; void *nli_ctx; kern_nexus_netif_llink_id_t nli_link_id; struct kern_nexus_netif_llink_qset_init *nli_qsets; }; /* * nxnetll_flags values. */ /* default logical link */ #define KERN_NEXUS_NET_LLINK_DEFAULT 0x1 __BEGIN_DECLS /* * Attributes. */ extern errno_t kern_nexus_attr_create(nexus_attr_t *); extern errno_t kern_nexus_attr_clone(const nexus_attr_t attr, nexus_attr_t *); extern errno_t kern_nexus_attr_set(nexus_attr_t attr, const nexus_attr_type_t type, const uint64_t value); extern errno_t kern_nexus_attr_get(const nexus_attr_t attr, const nexus_attr_type_t type, uint64_t *value); extern void kern_nexus_attr_destroy(nexus_attr_t attr); /* * Domain provider. * * At present we allow only NEXUS_TYPE_{KERNEL_PIPE,NET_IF} external * providers to be registered. */ extern errno_t kern_nexus_register_domain_provider(const nexus_type_t type, const nexus_domain_provider_name_t name, const struct kern_nexus_domain_provider_init *init, const uint32_t init_len, uuid_t *dom_prov_uuid); extern errno_t kern_nexus_deregister_domain_provider( const uuid_t dom_prov_uuid); extern errno_t kern_nexus_get_default_domain_provider(const nexus_type_t type, uuid_t *dom_prov_uuid); /* * Nexus provider. */ typedef void (*nexus_ctx_release_fn_t)(void *const ctx); extern errno_t kern_nexus_controller_create(nexus_controller_t *ctl); extern errno_t kern_nexus_controller_register_provider( const nexus_controller_t ctl, const uuid_t dom_prov_uuid, const nexus_name_t, const struct kern_nexus_provider_init *init, const uint32_t init_len, const nexus_attr_t nxa, uuid_t *nx_prov_uuid); extern errno_t kern_nexus_controller_deregister_provider( const nexus_controller_t ctl, const uuid_t nx_prov_uuid); extern errno_t kern_nexus_controller_alloc_provider_instance( const nexus_controller_t ctl, const uuid_t nx_prov_uuid, const void *nexus_context, nexus_ctx_release_fn_t nexus_context_release, uuid_t *nx_uuid, const struct kern_nexus_init *init); extern errno_t kern_nexus_controller_alloc_net_provider_instance( const nexus_controller_t ctl, const uuid_t nx_prov_uuid, const void *nexus_context, nexus_ctx_release_fn_t nexus_context_release, uuid_t *nx_uuid, const struct kern_nexus_net_init *init, ifnet_t *); extern errno_t kern_nexus_controller_free_provider_instance( const nexus_controller_t ctl, const uuid_t nx_uuid); extern errno_t kern_nexus_controller_bind_provider_instance( const nexus_controller_t ctl, const uuid_t nx_uuid, 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); extern errno_t kern_nexus_controller_unbind_provider_instance( const nexus_controller_t ctl, const uuid_t nx_uuid, const nexus_port_t port); extern errno_t kern_nexus_controller_read_provider_attr( const nexus_controller_t ctl, const uuid_t nx_prov_uuid, nexus_attr_t attr); extern void kern_nexus_controller_destroy(nexus_controller_t ctl); extern void kern_nexus_stop(const kern_nexus_t nx); /* * Netif specific. */ extern errno_t kern_netif_queue_tx_dequeue(kern_netif_queue_t, uint32_t, uint32_t, boolean_t *, uint64_t *); #define KERN_NETIF_QUEUE_RX_ENQUEUE_FLAG_FLUSH 0x0001 extern void kern_netif_queue_rx_enqueue(kern_netif_queue_t, uint64_t, uint32_t, uint32_t); extern errno_t kern_nexus_netif_llink_add(struct kern_nexus *, struct kern_nexus_netif_llink_init *); extern errno_t kern_nexus_netif_llink_remove(struct kern_nexus *, kern_nexus_netif_llink_id_t); extern errno_t kern_netif_qset_tx_queue_len(kern_netif_qset_t, uint32_t, uint32_t *, uint32_t *); extern void kern_netif_set_qset_combined(kern_netif_qset_t qset); extern void kern_netif_set_qset_separate(kern_netif_qset_t qset); /* * Misc. */ extern void *kern_nexus_get_context(const kern_nexus_t nexus); extern errno_t kern_nexus_get_pbufpool(const kern_nexus_t nexus, kern_pbufpool_t *tx_pbufpool, kern_pbufpool_t *rx_pbufpool); /* * Non-exported KPIs. */ extern int kern_nexus_ifattach(nexus_controller_t, const uuid_t nx_uuid, struct ifnet *ifp, const uuid_t nx_attachee, boolean_t host, uuid_t *nx_if_uuid); extern int kern_nexus_ifdetach(const nexus_controller_t ctl, const uuid_t nx_uuid, const uuid_t nx_if_uuid); extern int kern_nexus_get_netif_instance(struct ifnet *ifp, uuid_t nx_uuid); extern int kern_nexus_get_flowswitch_instance(struct ifnet *ifp, uuid_t nx_uuid); extern nexus_controller_t kern_nexus_shared_controller(void); extern void kern_nexus_register_netagents(void); extern void kern_nexus_deregister_netagents(void); extern void kern_nexus_update_netagents(void); extern int kern_nexus_interface_add_netagent(struct ifnet *); extern int kern_nexus_interface_remove_netagent(struct ifnet *); extern int kern_nexus_set_netif_input_tbr_rate(struct ifnet *ifp, uint64_t rate); extern int kern_nexus_set_if_netem_params( const nexus_controller_t ctl, const uuid_t nx_uuid, void *data, size_t data_len); extern int kern_nexus_flow_add(const nexus_controller_t ncd, const uuid_t nx_uuid, void *data, size_t data_len); extern int kern_nexus_flow_del(const nexus_controller_t ncd, const uuid_t nx_uuid, void *data, size_t data_len); __END_DECLS #endif /* KERNEL */ #endif /* PRIVATE */ #endif /* !_SKYWALK_OS_NEXUS_H_ */