/* * 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_PRIVATE_H_ #define _SKYWALK_OS_NEXUS_PRIVATE_H_ #if defined(PRIVATE) || defined(BSD_KERNEL_PRIVATE) #include #include #include #include #include #include #include #include #include /* * Ephemeral port, for NEXUSDOMCAPF_EPHEMERAL capable nexus. */ #define NEXUS_PORT_ANY ((nexus_port_t)-1) #define NEXUS_PORT_MAX ((nexus_port_t)-1) typedef nexus_port_t nexus_port_size_t; #define NEXUSCTL_INIT_VERSION_1 1 #define NEXUSCTL_INIT_CURRENT_VERSION NEXUSCTL_INIT_VERSION_1 /* * Nexus controller init parameters. */ struct nxctl_init { uint32_t ni_version; /* in: NEXUSCTL_INIT_CURRENT_VERSION */ uint32_t __ni_align; /* reserved */ guardid_t ni_guard; /* out: guard ID */ }; /* * Nexus metadata type. * * Be mindful that due to the use of tagged pointers for packets, this * type gets encoded along with the subtype, with the requirement that the * object addresses are aligned on 64-byte boundary at the minimum. That * leaves a total of 4 bits: 2 for type and another 2 for subtype, therefore * limiting the maximum enum value to 3. */ typedef enum { NEXUS_META_TYPE_INVALID = 0, /* invalid type */ NEXUS_META_TYPE_QUANTUM, /* struct __quantum */ NEXUS_META_TYPE_PACKET, /* struct __packet */ NEXUS_META_TYPE_RESERVED, /* for future */ NEXUS_META_TYPE_MAX = NEXUS_META_TYPE_RESERVED } nexus_meta_type_t; typedef enum { NEXUS_META_SUBTYPE_INVALID = 0, /* invalid subtype */ NEXUS_META_SUBTYPE_PAYLOAD, /* normal payload mode */ NEXUS_META_SUBTYPE_RAW, /* raw (link layer) mode */ NEXUS_META_SUBTYPE_RESERVED, /* for future */ NEXUS_META_SUBTYPE_MAX = NEXUS_META_SUBTYPE_RESERVED } nexus_meta_subtype_t; /* * Nexus provider parameters. */ struct nxprov_params { nexus_name_t nxp_name; /* name */ uint32_t nxp_namelen; /* length of name */ nexus_type_t nxp_type; /* NEXUS_TYPE_* */ nexus_meta_type_t nxp_md_type; /* NEXUS_META_TYPE_* */ nexus_meta_subtype_t nxp_md_subtype; /* NEXUS_META_SUBTYPE_* */ uint32_t nxp_flags; /* NXPF_* */ uint32_t nxp_format; /* provider-defined */ uint32_t nxp_tx_rings; /* # of channel transmit rings */ uint32_t nxp_rx_rings; /* # of channel receive rings */ uint32_t nxp_tx_slots; /* # of slots per channel TX ring */ uint32_t nxp_rx_slots; /* # of slots per channel RX ring */ uint32_t nxp_buf_size; /* size of each buffer */ uint32_t nxp_meta_size; /* size of metadata per slot */ uint32_t nxp_stats_size; /* size of statistics region */ uint32_t nxp_pipes; /* number of pipes */ nexus_extension_t nxp_extensions; /* extension specific parameter(s) */ uint32_t nxp_mhints; /* memory usage hints */ uint32_t nxp_ifindex; /* network interface index */ uint32_t nxp_flowadv_max; /* max flow advisory entries */ nexus_qmap_type_t nxp_qmap; /* queue mapping type */ uint32_t nxp_capabilities; /* nexus capabilities */ uint32_t nxp_nexusadv_size; /* nexus advisory region size */ uint32_t nxp_max_frags; /* max fragments per packet */ /* * reject channel operations if the peer has closed the channel. * Only valid for user-pipe nexus. */ boolean_t nxp_reject_on_close; uint32_t nxp_large_buf_size; /* size of large buffer */ } __attribute__((aligned(64))); /* valid values for nxp_flags */ #define NXPF_ANONYMOUS 0x1 /* allow anonymous channel clients */ #define NXPF_USER_CHANNEL 0x2 /* allow user channel open */ #define NXPF_NETIF_LLINK 0x4 /* use netif logical link */ #ifdef KERNEL #define NXPF_MASK (NXPF_ANONYMOUS | NXPF_USER_CHANNEL | NXPF_NETIF_LLINK) #endif /* KERNEL */ #define NXPF_BITS \ "\020\01ANONYMOUS\02USER_CHANNEL" /* valid values for nxp_capabilities */ #define NXPCAP_CHECKSUM_PARTIAL 0x1 /* partial checksum */ #define NXPCAP_USER_PACKET_POOL 0x2 /* user packet pool */ #define NXPCAP_USER_CHANNEL 0x4 /* allow user channel access */ #define NXPCAP_BITS \ "\020\01CHECKSUM_PARTIAL\02USER_PKT_POOL\03USER_CHANNEL" #define NXPROV_REG_VERSION_1 1 #define NXPROV_REG_CURRENT_VERSION NXPROV_REG_VERSION_1 /* * Nexus provider registration parameters. */ struct nxprov_reg { uint32_t nxpreg_version; /* NXPROV_REG_CURRENT_VERSION */ uint32_t nxpreg_requested; /* customized attributes */ struct nxprov_params nxpreg_params; /* Nexus provider parameters */ }; /* * Flags for nxpreq_requested; keep in sync with NXA_REQ_* flags. * Note that these are 32-bit, whereas nxa_requested is 64-bit * wide; for now this won't matter. */ #define NXPREQ_TX_RINGS (1U << 0) /* 0x00000001 */ #define NXPREQ_RX_RINGS (1U << 1) /* 0x00000002 */ #define NXPREQ_TX_SLOTS (1U << 2) /* 0x00000004 */ #define NXPREQ_RX_SLOTS (1U << 3) /* 0x00000008 */ #define NXPREQ_BUF_SIZE (1U << 4) /* 0x00000010 */ #define NXPREQ_META_SIZE (1U << 5) /* 0x00000020 */ #define NXPREQ_STATS_SIZE (1U << 6) /* 0x00000040 */ #define NXPREQ_ANONYMOUS (1U << 7) /* 0x00000080 */ #define NXPREQ_PIPES (1U << 8) /* 0x00000100 */ #define NXPREQ_EXTENSIONS (1U << 9) /* 0x00000200 */ #define NXPREQ_MHINTS (1U << 10) /* 0x00000400 */ #define NXPREQ_FLOWADV_MAX (1U << 11) /* 0x00000800 */ #define NXPREQ_QMAP (1U << 12) /* 0x00001000 */ #define NXPREQ_CHECKSUM_OFFLOAD (1U << 13) /* 0x00002000 */ #define NXPREQ_USER_PACKET_POOL (1U << 14) /* 0x00004000 */ #define NXPREQ_CAPABILITIES (1U << 15) /* 0x00008000 */ #define NXPREQ_NEXUSADV_SIZE (1U << 16) /* 0x00010000 */ #define NXPREQ_IFINDEX (1U << 17) /* 0x00020000 */ #define NXPREQ_USER_CHANNEL (1U << 18) /* 0x00040000 */ #define NXPREQ_MAX_FRAGS (1U << 19) /* 0x00080000 */ #define NXPREQ_REJECT_ON_CLOSE (1U << 20) /* 0x00100000 */ #define NXPREQ_LARGE_BUF_SIZE (1U << 21) /* 0x00200000 */ #define NXPREQ_BITS \ "\020\01TX_RINGS\02RX_RINGS\03TX_SLOTS\04RX_SLOTS\05BUF_SIZE" \ "\06META_SIZE\07STATS_SIZE\010ANONYMOUS\011EXTRA_BUFS\012PIPES" \ "\013EXTENSIONS\014MHINTS\015FLOWADV_MAX\016QMAP" \ "\017CKSUM_OFFLOAD\020USER_PKT_POOL\021CAPABS\022NEXUSADV_SIZE" \ "\023IFINDEX\024USER_CHANNEL\025MAX_FRAGS\026REJ_CLOSE\027LBUF_SIZE" /* * Nexus provider registration entry. Also argument for NXOPT_NEXUS_PROV_ENTRY. */ struct nxprov_reg_ent { uuid_t npre_prov_uuid; /* Nexus provider UUID */ struct nxprov_params npre_prov_params; /* Nexus provider parameters */ }; /* * Nexus options. */ #define NXOPT_NEXUS_PROV_LIST 1 /* (get) list all provider UUIDS */ #define NXOPT_NEXUS_PROV_ENTRY 2 /* (get) get params of a provider */ #define NXOPT_NEXUS_LIST 20 /* (get) list all Nexus instances */ #define NXOPT_NEXUS_BIND 21 /* (set) bind a Nexus port */ #define NXOPT_NEXUS_UNBIND 22 /* (set) unbind a Nexus port */ #define NXOPT_CHANNEL_LIST 30 /* (get) list all Channel instances */ #define NXOPT_NEXUS_CONFIG 40 /* (set) nexus specific config */ /* * Argument structure for NXOPT_NEXUS_PROV_LIST. */ struct nxprov_list_req { uint32_t nrl_num_regs; /* array count */ uint32_t __nrl_align; /* reserved */ user_addr_t nrl_regs; /* array of nexus_reg_ent */ }; /* * Argument structure for NXOPT_NEXUS_LIST. */ struct nx_list_req { uuid_t nl_prov_uuid; /* nexus provider UUID */ uint32_t nl_num_nx_uuids; /* array count */ uint32_t __nl_align; /* reserved */ user_addr_t nl_nx_uuids; /* array of nexus UUIDs */ }; /* * Argument structure for NXOPT_NEXUS_BIND. */ struct nx_bind_req { uuid_t nb_nx_uuid; /* nexus instance UUID */ nexus_port_t nb_port; /* nexus instance port */ uint32_t nb_flags; /* NBR_* match flags */ uuid_t nb_exec_uuid; /* executable UUID */ user_addr_t nb_key; /* key blob */ uint32_t nb_key_len; /* key blob length */ pid_t nb_pid; /* client PID */ }; #define NBR_MATCH_PID 0x1 /* match against PID */ #define NBR_MATCH_EXEC_UUID 0x2 /* match executable's UUID */ #define NBR_MATCH_KEY 0x4 /* match key blob */ #ifdef KERNEL #define NBR_MATCH_MASK \ (NBR_MATCH_PID | NBR_MATCH_EXEC_UUID | NBR_MATCH_KEY) #endif /* KERNEL */ /* * Argument structure for NXOPT_NEXUS_UNBIND. */ struct nx_unbind_req { uuid_t nu_nx_uuid; /* nexus instance UUID */ nexus_port_t nu_port; /* nexus instance port */ }; /* * Argument structure for NXOPT_CHANNEL_LIST. */ struct ch_list_req { uuid_t cl_nx_uuid; /* nexus instance UUID */ uint32_t cl_num_ch_uuids; /* array count */ uint32_t __cl_align; /* reserved */ user_addr_t cl_ch_uuids; /* array of channel UUIDs */ }; /* * Skywalk Nexus MIB * * We will use the name MIB now to refer to things that we expose to outside * world for management/telemetry purpose. * * General rule of thumb of this MIB structure is to keep it simple. * Try to avoid variable length field and hierarchical representation wherever * possible. Simple retrieval would return either a single object (simple type * or fixed length compound type) or an object array of same type. This makes * parsing the retrieved information a lot easier. * * For now, we use sysctl as the way MIB interface is exposed. Additional * interfaces could be syscall (e.g. via a nexus controller), etc. */ #define NXMIB_NETIF_STATS (((uint32_t)1) << 1) #define NXMIB_FSW_STATS (((uint32_t)1) << 2) #define NXMIB_FLOW (((uint32_t)1) << 3) #define NXMIB_FLOW_ADV (((uint32_t)1) << 4) #define NXMIB_FLOW_OWNER (((uint32_t)1) << 5) #define NXMIB_FLOW_ROUTE (((uint32_t)1) << 6) #define NXMIB_LLINK_LIST (((uint32_t)1) << 7) #define NXMIB_NETIF_QUEUE_STATS (((uint32_t)1) << 8) #define NXMIB_QUIC_STATS (((uint32_t)1) << 27) #define NXMIB_UDP_STATS (((uint32_t)1) << 28) #define NXMIB_TCP_STATS (((uint32_t)1) << 29) #define NXMIB_IP6_STATS (((uint32_t)1) << 30) #define NXMIB_IP_STATS (((uint32_t)1) << 31) #define NXMIB_USERSTACK_STATS (NXMIB_IP_STATS | NXMIB_IP6_STATS \ | NXMIB_TCP_STATS | NXMIB_UDP_STATS \ | NXMIB_QUIC_STATS) #define NXMIB_FILTER_NX_UUID (((uint64_t)1) << 0) #define NXMIB_FILTER_FLOW_ID (((uint64_t)1) << 1) #define NXMIB_FILTER_PID (((uint64_t)1) << 2) #define NXMIB_FILTER_INFO_TUPLE (((uint64_t)1) << 3) /* * Nexus MIB filter: used to retrieve only those matching the filter value. */ struct nexus_mib_filter { uint32_t nmf_type; /* MIB type */ uint64_t nmf_bitmap; /* bitmap of following fields */ uuid_t nmf_nx_uuid; /* nexus instance uuid */ uuid_t nmf_flow_id; /* flow rule id */ pid_t nmf_pid; /* owner pid */ struct info_tuple nmf_info_tuple; /* flow tuple */ }; /* * Nexus-specific config commands. */ typedef enum { NXCFG_CMD_ATTACH = 0, /* attach an object to a nexus */ NXCFG_CMD_DETACH = 1, /* detach an object from a nexus */ NXCFG_CMD_FLOW_ADD = 20, /* add a flow to a nexus */ NXCFG_CMD_FLOW_DEL = 21, /* delete a flow from nexus */ NXCFG_CMD_FLOW_CONFIG = 22, /* configure a flow in nexus */ NXCFG_CMD_NETEM = 30, /* config packet scheduler */ NXCFG_CMD_GET_LLINK_INFO = 40, /* collect llink info */ } nxcfg_cmd_t; #define NX_SPEC_IF_NAMELEN 64 /* * Argument struture for NXOPT_NEXUS_CONFIG. */ struct nx_cfg_req { uuid_t nc_nx_uuid; /* nexus instance UUID */ nxcfg_cmd_t nc_cmd; /* NXCFG_CMD_* */ uint32_t nc_req_len; /* size of request struct */ user_addr_t nc_req; /* address of request struct */ }; /* * Argument structure for NXCFG_CMD_{ATTACH,DETACH} */ struct nx_spec_req { union { char nsru_name[NX_SPEC_IF_NAMELEN]; uuid_t nsru_uuid; #ifdef KERNEL struct ifnet *nsru_ifp; #endif /* KERNEL */ } nsr_u __attribute__((aligned(sizeof(uint64_t)))); /* in */ uint32_t nsr_flags; /* in */ uuid_t nsr_if_uuid; /* attach: out, detach: in */ }; #define nsr_name nsr_u.nsru_name #define nsr_uuid nsr_u.nsru_uuid #ifdef KERNEL #define nsr_ifp nsr_u.nsru_ifp #endif /* KERNEL */ #define NXSPECREQ_UUID 0x1 /* nsr_name is uuid_t else ifname */ #define NXSPECREQ_HOST 0x2 /* attach to host port */ #ifdef KERNEL /* mask off userland-settable bits */ #define NXSPECREQ_MASK (NXSPECREQ_UUID | NXSPECREQ_HOST) #define NXSPECREQ_IFP 0x1000 /* (embryonic) ifnet */ #endif /* KERNEL */ /* * Structure for flow demuxing for parent/child flows */ #define FLOW_DEMUX_MAX_LEN 32 struct flow_demux_pattern { uint16_t fdp_offset; uint16_t fdp_len; uint8_t fdp_mask[FLOW_DEMUX_MAX_LEN]; uint8_t fdp_value[FLOW_DEMUX_MAX_LEN]; }; #define MAX_FLOW_DEMUX_PATTERN 4 /* * Argument structure for NXCFG_CMD_FLOW_{BIND,UNBIND} */ struct nx_flow_req { nexus_port_t nfr_nx_port; uint16_t nfr_ethertype; ether_addr_t nfr_etheraddr; union sockaddr_in_4_6 nfr_saddr; union sockaddr_in_4_6 nfr_daddr; uint8_t nfr_ip_protocol; uint8_t nfr_transport_protocol; uint16_t nfr_flags; uuid_t nfr_flow_uuid; packet_svc_class_t nfr_svc_class; uuid_t nfr_euuid; uint32_t nfr_policy_id; uint32_t nfr_skip_policy_id; pid_t nfr_epid; flowadv_idx_t nfr_flowadv_idx; uuid_t nfr_bind_key; uint64_t nfr_qset_id; uuid_t nfr_parent_flow_uuid; uint8_t nfr_flow_demux_count; struct flow_demux_pattern nfr_flow_demux_patterns[MAX_FLOW_DEMUX_PATTERN]; // below is reserved kernel-only fields union { #ifdef KERNEL struct { char _nfr_kernel_field_start[0]; void *nfr_context; struct proc *nfr_proc; struct ifnet *nfr_ifp; struct flow_route *nfr_route; struct ns_token *nfr_port_reservation; struct protons_token *nfr_proto_reservation; struct flow_stats *nfr_flow_stats; pid_t nfr_pid; uint32_t nfr_saddr_gencnt; void *nfr_ipsec_reservation; uint32_t nfr_inp_flowhash; #if defined(__LP64__) uint8_t _nfr_kernel_pad[4]; #else /* !__LP64__ */ uint8_t _nfr_kernel_pad[36]; #endif /* !__LP64__ */ char _nfr_kernel_field_end[0]; }; #endif /* KERNEL */ struct { uint8_t _nfr_opaque[80]; /* should be at the same offset as _nfr_kernel_field_end above */ char _nfr_common_field_end[0]; }; }; }; /* valid flags for nfr_flags */ #define NXFLOWREQF_TRACK 0x0001 /* enable state tracking */ #define NXFLOWREQF_QOS_MARKING 0x0002 /* allow qos marking */ #define NXFLOWREQF_FILTER 0x0004 /* interpose filter */ #define NXFLOWREQF_CUSTOM_ETHER 0x0008 /* custom ethertype */ #define NXFLOWREQF_IPV6_ULA 0x0010 /* ipv6 ula */ #define NXFLOWREQF_LISTENER 0x0020 /* listener */ #define NXFLOWREQF_OVERRIDE_ADDRESS_SELECTION 0x0040 /* override system address selection */ #define NXFLOWREQF_USE_STABLE_ADDRESS 0x0080 /* if override local, use stable address */ #define NXFLOWREQF_FLOWADV 0x0100 /* allocate flow advisory */ #define NXFLOWREQF_ASIS 0x0200 /* create flow as is in nfr */ #define NXFLOWREQF_LOW_LATENCY 0x0400 /* low latency flow */ #define NXFLOWREQF_NOWAKEFROMSLEEP 0x0800 /* Don't wake for traffic to this flow */ #define NXFLOWREQF_REUSEPORT 0x1000 /* Don't wake for traffic to this flow */ #define NXFLOWREQF_PARENT 0x4000 /* Parent flow */ #define NXFLOWREQF_BITS \ "\020\01TRACK\02QOS_MARKING\03FILTER\04CUSTOM_ETHER\05IPV6_ULA" \ "\06LISTENER\07OVERRIDE_ADDRESS_SELECTION\010USE_STABLE_ADDRESS" \ "\011ALLOC_FLOWADV\012ASIS\013LOW_LATENCY\014NOWAKEUPFROMSLEEP" \ "\015REUSEPORT\017PARENT" struct flow_ip_addr { union { struct in_addr _v4; struct in6_addr _v6; uint8_t _addr8[16]; uint16_t _addr16[8]; uint32_t _addr32[4]; uint64_t _addr64[2]; }; }; struct flow_key { uint16_t fk_mask; uint8_t fk_ipver; uint8_t fk_proto; uint16_t fk_sport; uint16_t fk_dport; struct flow_ip_addr fk_src; struct flow_ip_addr fk_dst; uint64_t fk_pad[1]; /* pad to 48 bytes */ } __attribute__((__aligned__(16))); #define fk_src4 fk_src._v4 #define fk_dst4 fk_dst._v4 #define fk_src6 fk_src._v6 #define fk_dst6 fk_dst._v6 #define FLOW_KEY_LEN sizeof(struct flow_key) #define FK_HASH_SEED 0xabcd #define FKMASK_IPVER (((uint16_t)1) << 0) #define FKMASK_PROTO (((uint16_t)1) << 1) #define FKMASK_SRC (((uint16_t)1) << 2) #define FKMASK_SPORT (((uint16_t)1) << 3) #define FKMASK_DST (((uint16_t)1) << 4) #define FKMASK_DPORT (((uint16_t)1) << 5) #define FKMASK_2TUPLE (FKMASK_PROTO | FKMASK_SPORT) #define FKMASK_3TUPLE (FKMASK_2TUPLE | FKMASK_IPVER | FKMASK_SRC) #define FKMASK_4TUPLE (FKMASK_3TUPLE | FKMASK_DPORT) #define FKMASK_5TUPLE (FKMASK_4TUPLE | FKMASK_DST) #define FKMASK_IPFLOW1 FKMASK_PROTO #define FKMASK_IPFLOW2 (FKMASK_IPFLOW1 | FKMASK_IPVER | FKMASK_SRC) #define FKMASK_IPFLOW3 (FKMASK_IPFLOW2 | FKMASK_DST) #define FKMASK_IDX_MAX 7 extern const struct flow_key fk_mask_2tuple; extern const struct flow_key fk_mask_3tuple; extern const struct flow_key fk_mask_4tuple; extern const struct flow_key fk_mask_5tuple; extern const struct flow_key fk_mask_ipflow1; extern const struct flow_key fk_mask_ipflow2; extern const struct flow_key fk_mask_ipflow3; #define FLOW_KEY_CLEAR(_fk) do { \ _CASSERT(FLOW_KEY_LEN == 48); \ _CASSERT(FLOW_KEY_LEN == sizeof(struct flow_key)); \ sk_zero_48(_fk); \ } while (0) #ifdef KERNEL /* mask off userland-settable bits */ #define NXFLOWREQF_MASK \ (NXFLOWREQF_TRACK | NXFLOWREQF_QOS_MARKING | NXFLOWREQF_FILTER | \ NXFLOWREQF_CUSTOM_ETHER | NXFLOWREQF_IPV6_ULA | NXFLOWREQF_LISTENER | \ NXFLOWREQF_OVERRIDE_ADDRESS_SELECTION | NXFLOWREQF_USE_STABLE_ADDRESS | \ NXFLOWREQF_FLOWADV | NXFLOWREQF_LOW_LATENCY | NXFLOWREQF_NOWAKEFROMSLEEP | \ NXFLOWREQF_REUSEPORT | NXFLOWREQF_PARENT) #define NXFLOWREQF_EXT_PORT_RSV 0x1000 /* external port reservation */ #define NXFLOWREQF_EXT_PROTO_RSV 0x2000 /* external proto reservation */ static inline void nx_flow_req_internalize(struct nx_flow_req *req) { _CASSERT(offsetof(struct nx_flow_req, _nfr_kernel_field_end) == offsetof(struct nx_flow_req, _nfr_common_field_end)); /* init kernel only fields */ bzero(&req->_nfr_opaque, sizeof(req->_nfr_opaque)); req->nfr_flags &= NXFLOWREQF_MASK; req->nfr_context = NULL; req->nfr_flow_stats = NULL; req->nfr_port_reservation = NULL; } static inline void nx_flow_req_externalize(struct nx_flow_req *req) { /* neutralize kernel only fields */ bzero(&req->_nfr_opaque, sizeof(req->_nfr_opaque)); req->nfr_flags &= NXFLOWREQF_MASK; } #endif /* KERNEL */ struct nx_qset_info { uint64_t nqi_id; uint16_t nqi_flags; uint8_t nqi_num_rx_queues; uint8_t nqi_num_tx_queues; }; #define NETIF_LLINK_MAX_QSETS 256 struct nx_llink_info { uuid_t nli_netif_uuid; /* nexus netif instance uuid */ uint64_t nli_link_id; uint16_t nli_link_id_internal; uint8_t nli_state; uint8_t nli_flags; uint16_t nli_qset_cnt; struct nx_qset_info nli_qset[NETIF_LLINK_MAX_QSETS]; }; #define NETIF_LLINK_INFO_VERSION 0x01 struct nx_llink_info_req { uint16_t nlir_version; uint16_t nlir_llink_cnt; struct nx_llink_info nlir_llink[0]; }; /* * Nexus controller descriptor. */ struct nexus_controller { #ifndef KERNEL int ncd_fd; guardid_t ncd_guard; #else /* KERNEL */ struct nxctl *ncd_nxctl; #endif /* KERNEL */ }; /* For nexus ops without having to create a nexus controller */ #define __OS_NEXUS_SHARED_USER_CONTROLLER_FD (-1) /* * Nexus attributes. */ struct nexus_attr { uint64_t nxa_requested; /* customized attributes */ uint64_t nxa_tx_rings; /* # of channel transmit rings */ uint64_t nxa_rx_rings; /* # of channel receive rings */ uint64_t nxa_tx_slots; /* # of slots per channel TX ring */ uint64_t nxa_rx_slots; /* # of slots per channel RX ring */ uint64_t nxa_buf_size; /* size of each buffer */ uint64_t nxa_meta_size; /* size of metadata per buffer */ uint64_t nxa_stats_size; /* size of statistics region */ uint64_t nxa_anonymous; /* bool: allow anonymous clients */ uint64_t nxa_pipes; /* number of pipes */ uint64_t nxa_extensions; /* extension-specific attribute */ uint64_t nxa_mhints; /* memory usage hints */ uint64_t nxa_ifindex; /* network interface index */ uint64_t nxa_flowadv_max; /* max flow advisory entries */ uint64_t nxa_qmap; /* queue mapping type */ uint64_t nxa_checksum_offload; /* partial checksum offload */ uint64_t nxa_user_packet_pool; /* user packet pool */ uint64_t nxa_nexusadv_size; /* size of advisory region */ uint64_t nxa_user_channel; /* user channel open allowed */ uint64_t nxa_max_frags; /* max fragments per packet */ /* * reject channel operations if the nexus peer has closed the channel. * valid only for user-pipe nexus. */ uint64_t nxa_reject_on_close; uint64_t nxa_large_buf_size; /* size of large buffer */ }; /* * Flags for nxa_requested; keep in sync with NXPREQ_* flags. * Note that these are 64-bit, whereas nxpreq_requested is * 32-bit wide; for not this won't matter. */ #define NXA_REQ_TX_RINGS (1ULL << 0) /* 0x0000000000000001 */ #define NXA_REQ_RX_RINGS (1ULL << 1) /* 0x0000000000000002 */ #define NXA_REQ_TX_SLOTS (1ULL << 2) /* 0x0000000000000004 */ #define NXA_REQ_RX_SLOTS (1ULL << 3) /* 0x0000000000000008 */ #define NXA_REQ_BUF_SIZE (1ULL << 4) /* 0x0000000000000010 */ #define NXA_REQ_META_SIZE (1ULL << 5) /* 0x0000000000000020 */ #define NXA_REQ_STATS_SIZE (1ULL << 6) /* 0x0000000000000040 */ #define NXA_REQ_ANONYMOUS (1ULL << 7) /* 0x0000000000000080 */ #define NXA_REQ_PIPES (1ULL << 8) /* 0x0000000000000100 */ #define NXA_REQ_EXTENSIONS (1ULL << 9) /* 0x0000000000000200 */ #define NXA_REQ_MHINTS (1ULL << 10) /* 0x0000000000000400 */ #define NXA_REQ_FLOWADV_MAX (1ULL << 11) /* 0x0000000000000800 */ #define NXA_REQ_QMAP (1ULL << 12) /* 0x0000000000001000 */ #define NXA_REQ_CHECKSUM_OFFLOAD (1ULL << 13) /* 0x0000000000002000 */ #define NXA_REQ_USER_PACKET_POOL (1ULL << 14) /* 0x0000000000004000 */ #define NXA_REQ_CAPABILITIES (1ULL << 15) /* 0x0000000000008000 */ #define NXA_REQ_NEXUSADV_SIZE (1ULL << 16) /* 0x0000000000010000 */ #define NXA_REQ_IFINDEX (1ULL << 17) /* 0x0000000000020000 */ #define NXA_REQ_USER_CHANNEL (1ULL << 18) /* 0x0000000000040000 */ #define NXA_REQ_MAX_FRAGS (1ULL << 19) /* 0x0000000000080000 */ #define NXA_REQ_REJECT_ON_CLOSE (1ULL << 20) /* 0x0000000000100000 */ #define NXA_REQ_LARGE_BUF_SIZE (1ULL << 21) /* 0x0000000000200000 */ #ifndef KERNEL #if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) __BEGIN_DECLS /* system calls */ extern int __nexus_open(struct nxctl_init *init, const uint32_t init_len); extern int __nexus_register(int ctl, struct nxprov_reg *reg, const uint32_t reg_len, uuid_t *prov_uuid, const uint32_t prov_uuid_len); extern int __nexus_deregister(int ctl, const uuid_t prov_uuid, const uint32_t prov_uuid_len); extern int __nexus_create(int ctl, const uuid_t prov_uuid, const uint32_t prov_uuid_len, uuid_t *nx_uuid, const uint32_t nx_uuid_len); extern int __nexus_destroy(int ctl, const uuid_t nx_uuid, const uint32_t nx_uuid_len); extern int __nexus_get_opt(int ctl, const uint32_t opt, void *aoptval, uint32_t *aoptlen); extern int __nexus_set_opt(int ctl, const uint32_t opt, const void *aoptval, const uint32_t optlen); /* private nexus controller APIs */ extern int __os_nexus_ifattach(const nexus_controller_t ctl, const uuid_t nx_uuid, const char *ifname, const uuid_t netif_uuid, boolean_t host, uuid_t *nx_if_uuid); extern int __os_nexus_ifdetach(const nexus_controller_t ctl, const uuid_t nx_uuid, const uuid_t nx_if_uuid); /* private flow APIs */ extern int __os_nexus_flow_add(const nexus_controller_t ncd, const uuid_t nx_uuid, const struct nx_flow_req *nfr); extern int __os_nexus_flow_del(const nexus_controller_t ncd, const uuid_t nx_uuid, const struct nx_flow_req *nfr); extern 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); extern int os_nexus_flow_set_wake_from_sleep(const uuid_t nx_uuid, const uuid_t flow_uuid, bool enable); __END_DECLS #endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ #endif /* !KERNEL */ #if defined(LIBSYSCALL_INTERFACE) || defined(BSD_KERNEL_PRIVATE) #include #include #endif /* LIBSYSCALL_INTERFACE || BSD_KERNEL_PRIVATE */ #endif /* PRIVATE || BSD_KERNEL_PRIVATE */ #endif /* !_SKYWALK_OS_NEXUS_PRIVATE_H_ */