X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/5d5c5d0d5b79ade9a973d55186ffda2638ba2b6e..cb3231590a3c94ab4375e2228bd5e86b0cf1ad7e:/bsd/net/dlil.h diff --git a/bsd/net/dlil.h b/bsd/net/dlil.h index 6cba0b90a..7f2753cba 100644 --- a/bsd/net/dlil.h +++ b/bsd/net/dlil.h @@ -1,70 +1,37 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2019 Apple Inc. All rights reserved. * - * @APPLE_LICENSE_OSREFERENCE_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. + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * 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. * - * 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. + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. * - * @APPLE_LICENSE_OSREFERENCE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. + * 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. * - * Data Link Inteface Layer - * Author: Ted Walker + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ #ifndef DLIL_H #define DLIL_H #ifdef KERNEL + #include #include -#if __STDC__ - -struct ifnet; -struct mbuf; -struct ether_header; -struct sockaddr_dl; - -#endif - - -#ifdef KERNEL_PRIVATE -#define DLIL_LAST_FILTER -1 -#define DLIL_NULL_FILTER -2 - -#define DLIL_WAIT_FOR_FREE -2 - -#define DLIL_BLUEBOX 1 - - - -#include -#include -#include - -#endif KERNEL_PRIVATE - enum { BPF_TAP_DISABLE, BPF_TAP_INPUT, @@ -72,80 +39,6 @@ enum { BPF_TAP_INPUT_OUTPUT }; -#ifdef KERNEL_PRIVATE -struct kev_msg; -struct iff_filter; - -struct dlil_if_flt_str { - caddr_t cookie; - int (*filter_if_input)(caddr_t cookie, - struct ifnet **ifp, - struct mbuf **mbuf_ptr, - char **frame_ptr); - - int (*filter_if_event)(caddr_t cookie, - struct ifnet *ifp, - struct kev_msg *event_msg_ptr); - - int (*filter_if_output)(caddr_t cookie, - struct ifnet **ifp, - struct mbuf **mbuf_ptr); - - - int (*filter_if_ioctl)(caddr_t cookie, - struct ifnet *ifp, - u_long ioctl_code_ptr, - caddr_t ioctl_arg_ptr); - - int (*filter_if_free)(caddr_t cookie, - struct ifnet *ifp); - - int (*filter_detach)(caddr_t cookie); - u_long reserved[2]; -}; - -#define DLIL_PR_FILTER 1 -#define DLIL_IF_FILTER 2 - - - -typedef int (*dl_input_func)(struct mbuf *m, char *frame_header, - struct ifnet *ifp, u_long protocol_family, int sync_ok); -typedef int (*dl_pre_output_func)(struct ifnet *ifp, - u_long protocol_family, - struct mbuf **m, - const struct sockaddr *dest, - caddr_t route_entry, - char *frame_type, - char *dst_addr); - -typedef void (*dl_event_func)(struct ifnet *ifp, struct kev_msg *event); - -typedef int (*dl_offer_func)(struct mbuf *m, char *frame_header); -typedef int (*dl_ioctl_func)(u_long protocol_family, - struct ifnet *ifp, - u_long ioctl_cmd, - caddr_t ioctl_arg); -typedef int (*dl_detached_func)(u_long protocol_family, struct ifnet *ifp); - -/* Obsolete types */ -#define DLIL_DESC_RAW 1 -#define DLIL_DESC_802_2 2 -#define DLIL_DESC_802_2_SNAP 3 -/* - * DLIL_DESC_RAW - obsolete type, data in variants.bitmask or native_type - * if variants.bitmask.proto_id_length, native_type in host - * byte order. - * DLIL_DESC_802_2 - obsolete, data in variants.desc_802_2 - * DLIL_DESC_802_2_SNAP - obsolete, data in variants.desc_802_2_SNAP - * protocol field in host byte order - */ -#endif KERNEL_PRIVATE - -/* Ethernet specific types */ -#define DLIL_DESC_ETYPE2 4 -#define DLIL_DESC_SAP 5 -#define DLIL_DESC_SNAP 6 /* * DLIL_DESC_ETYPE2 - native_type must point to 2 byte ethernet raw protocol, * variants.native_type_length must be set to 2 @@ -161,458 +54,397 @@ typedef int (*dl_detached_func)(u_long protocol_family, struct ifnet *ifp); * The length of the protocol data specified at native_type must be set in * variants.native_type_length. */ +/* Ethernet specific types */ +#define DLIL_DESC_ETYPE2 4 +#define DLIL_DESC_SAP 5 +#define DLIL_DESC_SNAP 6 #ifdef KERNEL_PRIVATE -struct dlil_demux_desc { - TAILQ_ENTRY(dlil_demux_desc) next; - - int type; - u_char *native_type; - - union { - /* Structs in this union are obsolete. They exist for binary compatability only */ - /* Only the native_type_length is used */ - struct { - u_long proto_id_length; /* IN LONGWORDS!!! */ - u_char *proto_id; /* No longer supported by Ethernet family */ - u_char *proto_id_mask; - } bitmask; - - struct { - u_char dsap; - u_char ssap; - u_char control_code; - u_char pad; - } desc_802_2; - - struct { - u_char dsap; /* Ignored, assumed to be 0xAA */ - u_char ssap; /* Ignored, assumed to be 0xAA */ - u_char control_code; /* Ignored, assumed to be 0x03 */ - u_char org[3]; - u_short protocol_type; /* In host byte order */ - } desc_802_2_SNAP; - - /* Length of data pointed to by native_type, must be set correctly */ - u_int32_t native_type_length; - } variants; -}; - -TAILQ_HEAD(ddesc_head_str, dlil_demux_desc); - -struct dlil_proto_reg_str { - struct ddesc_head_str demux_desc_head; - u_long interface_family; - u_long protocol_family; - short unit_number; - int default_proto; /* 0 or 1 */ - dl_input_func input; - dl_pre_output_func pre_output; - dl_event_func event; - dl_offer_func offer; - dl_ioctl_func ioctl; - dl_detached_func detached; - u_long reserved[3]; -}; - - -int dlil_attach_filter(struct ifnet *ifp, const struct iff_filter *if_filter, - interface_filter_t *filter_ref); - -struct ifnet_stat_increment_param; - -int -dlil_input_with_stats(struct ifnet *ifp, struct mbuf *m_head, struct mbuf *m_tail, - const struct ifnet_stat_increment_param *stats); - -int -dlil_input(struct ifnet *ifp, struct mbuf *m_head, struct mbuf *m_tail); - -int -dlil_output_list( - struct ifnet *ifp, - u_long protocol_family, - struct mbuf *packetlist, - caddr_t route, - const struct sockaddr *dest, - int raw); - -int -dlil_output( - struct ifnet *ifp, - u_long protocol_family, - struct mbuf *m, - caddr_t route, - const struct sockaddr *dest, - int raw); - - -int -dlil_ioctl(u_long proto_family, - struct ifnet *ifp, - u_long ioctl_code, - caddr_t ioctl_arg); - -errno_t -dlil_resolve_multi( - struct ifnet *ifp, - const struct sockaddr *proto_addr, - struct sockaddr *ll_addr, - size_t ll_len); +#include +#include +#include +#include +#include +#include +#include +#ifdef BSD_KERNEL_PRIVATE +/* Operations on timespecs. */ +#define net_timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_nsec = 0 + +#define net_timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_nsec) + +#define net_timercmp(tvp, uvp, cmp) \ + (((tvp)->tv_sec == (uvp)->tv_sec) ? \ + ((tvp)->tv_nsec cmp (uvp)->tv_nsec) : \ + ((tvp)->tv_sec cmp (uvp)->tv_sec)) + +#define net_timeradd(tvp, uvp, vvp) do { \ + (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \ + (vvp)->tv_nsec = (tvp)->tv_nsec + (uvp)->tv_nsec; \ + if ((vvp)->tv_nsec >= (long)NSEC_PER_SEC) { \ + (vvp)->tv_sec++; \ + (vvp)->tv_nsec -= NSEC_PER_SEC; \ + } \ +} while (0) + +#define net_timersub(tvp, uvp, vvp) do { \ + (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ + (vvp)->tv_nsec = (tvp)->tv_nsec - (uvp)->tv_nsec; \ + if ((vvp)->tv_nsec < 0) { \ + (vvp)->tv_sec--; \ + (vvp)->tv_nsec += NSEC_PER_SEC; \ + } \ +} while (0) + +#define net_timerusec(tvp, nsp) do { \ + *(nsp) = (tvp)->tv_nsec / NSEC_PER_USEC; \ + if ((tvp)->tv_sec > 0) \ + *(nsp) += ((tvp)->tv_sec * USEC_PER_SEC); \ +} while (0) + +#define net_timernsec(tvp, nsp) do { \ + *(nsp) = (tvp)->tv_nsec; \ + if ((tvp)->tv_sec > 0) \ + *(nsp) += ((tvp)->tv_sec * NSEC_PER_SEC); \ +} while (0) + +#if defined(__x86_64__) || defined(__arm64__) +#define net_nsectimer(nsp, tvp) do { \ + u_int64_t __nsp = *(nsp); \ + net_timerclear(tvp); \ + uint64_t __sec = __nsp / NSEC_PER_SEC; \ + (tvp)->tv_sec = (__darwin_time_t)__sec; \ + (tvp)->tv_nsec = (long)(__nsp - __sec * NSEC_PER_SEC); \ +} while (0) +#else /* 32 bit */ /* - * Send arp internal bypasses the check for - * IPv4LL. + * NSEC needs to be < 2^31*10^9 to be representable in a struct timespec + * because __darwin_time_t is 32 bit on 32-bit platforms. This bound + * is < 2^61. We get a first approximation to convert into seconds using + * the following values. + * a = floor(NSEC / 2^29) + * inv = floor(2^61 / 10^9) + * + * The approximation of seconds is correct or too low by 1 unit. + * So we fix it by computing the remainder. */ -errno_t -dlil_send_arp_internal( - ifnet_t ifp, - u_int16_t arpop, - const struct sockaddr_dl* sender_hw, - const struct sockaddr* sender_proto, - const struct sockaddr_dl* target_hw, - const struct sockaddr* target_proto); - -errno_t -dlil_send_arp( - ifnet_t ifp, - u_int16_t arpop, - const struct sockaddr_dl* sender_hw, - const struct sockaddr* sender_proto, - const struct sockaddr_dl* target_hw, - const struct sockaddr* target_proto); - -int -dlil_ioctl_locked(u_long proto_family, - struct ifnet *ifp, - u_long ioctl_code, - caddr_t ioctl_arg); - -int -dlil_attach_protocol(struct dlil_proto_reg_str *proto); - -int -dlil_detach_protocol(struct ifnet *ifp, u_long protocol_family); - -int -dlil_if_attach(struct ifnet *ifp); - -#ifdef BSD_KERNEL_PRIVATE - -int -dlil_if_attach_with_address( - struct ifnet *ifp, - const struct sockaddr_dl *ll_addr); +#define net_nsectimer(nsp, tvp) do { \ + u_int64_t __nsp = *(nsp); \ + net_timerclear(tvp); \ + uint32_t __a = (uint32_t)(__nsp >> 29); \ + const uint32_t __inv = 0x89705F41; \ + uint32_t __sec = (uint32_t)(((uint64_t)__a * __inv) >> 32); \ + uint32_t __rem = (uint32_t)(__nsp - __sec * NSEC_PER_SEC); \ + __sec += ((__rem >= NSEC_PER_SEC) ? 1 : 0); \ + (tvp)->tv_sec = (__darwin_time_t)__sec; \ + (tvp)->tv_nsec = \ + (long)((__rem >= NSEC_PER_SEC) ? (__rem - NSEC_PER_SEC) : __rem); \ +} while(0) +#endif /* 32 bit */ -int -dlil_attach_protocol_kpi(ifnet_t ifp, protocol_family_t protocol, - const struct ifnet_attach_proto_param *proto_details); - -errno_t dlil_set_bpf_tap(ifnet_t ifp, bpf_tap_mode mode, - bpf_packet_func callback); +struct ifnet; +struct mbuf; +struct ether_header; +struct sockaddr_dl; +struct iff_filter; -#endif +#define DLIL_THREADNAME_LEN 32 -void -dlil_detach_filter(interface_filter_t filter); - -struct dlil_ifmod_reg_str { - int (*add_if)(struct ifnet *ifp); - int (*del_if)(struct ifnet *ifp); - int (*add_proto)(struct ifnet *ifp, u_long protocol_family, - struct ddesc_head_str *demux_desc_head); -#ifdef __KPI_INTERFACE__ - ifnet_del_proto_func del_proto; - ifnet_ioctl_func ifmod_ioctl; -#else - void* del_proto; - void* ifmod_ioctl; +/* + * DLIL input thread info + */ +struct dlil_threading_info { + decl_lck_mtx_data(, input_lck); + lck_grp_t *lck_grp; /* lock group (for lock stats) */ + u_int32_t input_waiting; /* DLIL condition of thread */ + u_int32_t wtot; /* # of wakeup requests */ + char input_name[DLIL_THREADNAME_LEN]; /* name storage */ + struct ifnet *ifp; /* pointer to interface */ + class_queue_t rcvq_pkts; /* queue of pkts */ + struct ifnet_stat_increment_param stats; /* incremental statistics */ + /* + * Thread affinity (workloop and DLIL threads). + */ + boolean_t net_affinity; /* affinity set is available */ + struct thread *input_thr; /* input thread */ + struct thread *wloop_thr; /* workloop thread */ + struct thread *poll_thr; /* poll thread */ + u_int32_t tag; /* affinity tag */ +#if IFNET_INPUT_SANITY_CHK + /* + * For debugging. + */ + u_int64_t input_mbuf_cnt; /* total # of packets processed */ #endif - int (*shutdown)(void); - int (*init_if)(struct ifnet *ifp); - u_long reserved[3]; }; +/* + * DLIL input thread info (for main/loopback input thread) + */ +struct dlil_main_threading_info { + struct dlil_threading_info inp; + class_queue_t lo_rcvq_pkts; /* queue of lo0 pkts */ +}; -int dlil_reg_if_modules(u_long interface_family, - struct dlil_ifmod_reg_str *ifmod_reg); - -/* - -Function : dlil_reg_proto_module - - A DLIL protocol module is a piece of code that know how to handle a certain type - of protocol (PF_INET, PF_INET6, ...) for a certain family of interface (APPLE_IF_FAM_ETHERNET, - APPLE_IF_FAM_PPP, ...). - - dlil_reg_proto_module() allows the registration of such a protocol/interface handler before any - interface is attached. - Typically, the attach and detach function of the protocol handler will call - dlil_{attach/detach}_protocol with the parameter specific to the protocol. - - The goal of this modules is to insulate the actual protocol (IP, IPv6) from the DLIL details. - -Parameters : - 'protocol_family' is PF_INET, PF_INET6, ... - 'interface_family' is APPLE_IF_FAM_ETHERNET, APPLE_IF_FAM_PPP, ... - 'protomod_reg' is the protocol registration structure. - 'attach_proto' funtion is mandatory. - 'detach_proto' funtion is optional (DLIL will manage it). - -Return code : - -0 : - - No error. - -ENOMEM: - - No memory can be allocated for internal data structure. - -EEXIST: - - The protocol family has already been registered for this interface family. - -EINVAL: - - The dlil_protomod_reg_str structure contains incorrect values. - -*/ - -int dlil_reg_proto_module(u_long protocol_family, u_long interface_family, - int (*attach)(struct ifnet *ifp, u_long protocol_family), - int (*detach)(struct ifnet *ifp, u_long protocol_family)); - -/* - -Function : dlil_dereg_proto_module - - dlil_dereg_proto_module() will unregister the protocol module previously - registered with dlil_dereg_proto_module(). - - There is no restriction when to call it. - Interfaces or protoco can be attached, it will not prevent the deregistration of the module. - -Parameters : - 'protocol_family' is PF_INET, PF_INET6, ... - 'interface_family' is APPLE_IF_FAM_ETHERNET, APPLE_IF_FAM_PPP, ... - -Return code : - -0 : - - No error. - -ENOENT: - - No module was registered.. - -*/ - -int dlil_dereg_proto_module(u_long protocol_family, u_long interface_family); - -/* - -Function : dlil_plumb_protocol - - dlil_plumb_protocol() will plumb a protocol to an actual interface. - This will find a registered protocol module and call its attach function. - The module will typically call dlil_attach_protocol with the appropriate parameters. - -Parameters : - 'protocol_family' is PF_INET, PF_INET6, ... - 'ifp' is the interface to plumb the protocol to. - -Return code : - -0 : - - No error. - -ENOENT: - - No module was registered. - -other: - - Error returned by the attach_proto function - -*/ -int dlil_plumb_protocol(u_long protocol_family, struct ifnet *ifp); - -/* - -Function : dlil_unplumb_protocol - - dlil_unplumb_protocol() will unplumb a protocol from an interface. - This will find a registered protocol module and call its detach function. - The module will typically call dlil_detach_protocol with the appropriate parameters. - If no module is found, this function will call dlil_detach_protocol directly. - -Parameters : - 'protocol_family' is PF_INET, PF_INET6, ... - 'ifp' is APPLE_IF_FAM_ETHERNET, APPLE_IF_FAM_PPP, ... - -Return code : - -0 : - - No error. - -ENOENT: - - No module was registered. - -other: - - Error returned by the attach_proto function - -*/ -int dlil_unplumb_protocol(u_long protocol_family, struct ifnet *ifp); - -int -dlil_inject_if_input(struct mbuf *m, char *frame_header, u_long from_id); - -int -dlil_inject_pr_input(struct mbuf *m, char *frame_header, u_long from_id); - -int -dlil_inject_pr_output(struct mbuf *m, - struct sockaddr *dest, - int raw, - char *frame_type, - char *dst_linkaddr, - u_long from_id); +/* + * The following are shared with kpi_protocol.c so that it may wakeup + * the input thread to run through packets queued for protocol input. + */ +#define DLIL_INPUT_RUNNING 0x80000000 +#define DLIL_INPUT_WAITING 0x40000000 +#define DLIL_PROTO_REGISTER 0x20000000 +#define DLIL_PROTO_WAITING 0x10000000 +#define DLIL_INPUT_TERMINATE 0x08000000 +#define DLIL_INPUT_TERMINATE_COMPLETE 0x04000000 -int -dlil_inject_if_output(struct mbuf *m, u_long from_id); +/* + * Flags for dlil_attach_filter() + */ +#define DLIL_IFF_TSO 0x01 /* Interface filter supports TSO */ +#define DLIL_IFF_INTERNAL 0x02 /* Apple internal -- do not count towards stats */ -#ifdef KERNEL_PRIVATE -void -dlil_post_msg(struct ifnet *ifp,u_long event_subclass, u_long event_code, - struct net_event_data *event_data, u_long event_data_len); -#endif +/* Input poll interval definitions */ +#define IF_RXPOLL_INTERVALTIME_MIN (1ULL * 1000) /* 1 us */ +#define IF_RXPOLL_INTERVALTIME (1ULL * 1000 * 1000) /* 1 ms */ -int -dlil_event(struct ifnet *ifp, struct kern_event_msg *event); +extern int dlil_verbose; +extern uint32_t hwcksum_dbg; +extern uint32_t hwcksum_tx; +extern uint32_t hwcksum_rx; +extern struct dlil_threading_info *dlil_main_input_thread; +extern unsigned int net_rxpoll; +extern uint32_t if_rxpoll; +extern uint32_t if_rxpoll_decay; +extern uint32_t if_rxpoll_interval_pkts; +extern uint32_t if_rcvq_maxlen; -int dlil_dereg_if_modules(u_long interface_family); +extern void dlil_init(void); -int -dlil_if_detach(struct ifnet *ifp); +extern errno_t ifp_if_ioctl(struct ifnet *, unsigned long, void *); +extern errno_t ifp_if_output(struct ifnet *, struct mbuf *); +extern void ifp_if_start(struct ifnet *); -void -ifp_reference(struct ifnet *ifp); +extern errno_t dlil_set_bpf_tap(ifnet_t, bpf_tap_mode, bpf_packet_func); -void -ifp_release(struct ifnet *ifp); +/* + * Send arp internal bypasses the check for IPv4LL. + */ +extern errno_t dlil_send_arp_internal(ifnet_t, u_int16_t, + const struct sockaddr_dl *, const struct sockaddr *, + const struct sockaddr_dl *, const struct sockaddr *); +/* + * The following constants are used with the net_thread_mark_apply and + * net_thread_is_unmarked functions to control the bits in the uu_network_marks + * field of the uthread structure. + */ +#define NET_THREAD_HELD_PF 0x1 /* thread is holding PF lock */ +#define NET_THREAD_HELD_DOMAIN 0x2 /* thread is holding domain_proto_mtx */ +#define NET_THREAD_CKREQ_LLADDR 0x4 /* thread reqs MACF check for LLADDR */ -/* +/* + * net_thread_marks_t is a pointer to a phantom structure type used for + * manipulating the uthread:uu_network_marks field. As an example... + * + * static const u_int32_t bits = NET_THREAD_CKREQ_LLADDR; + * struct uthread *uth = get_bsdthread_info(current_thread()); + * + * net_thread_marks_t marks = net_thread_marks_push(bits); + * VERIFY((uth->uu_network_marks & NET_THREAD_CKREQ_LLADDR) != 0); + * net_thread_marks_pop(marks); + * + * The net_thread_marks_push() function returns an encoding of the bits + * that were changed from zero to one in the uu_network_marks field. When + * the net_thread_marks_pop() function later processes that value, it + * resets the bits to their previous value. + * + * The net_thread_unmarks_push() and net_thread_unmarks_pop() functions + * are similar to net_thread_marks_push() and net_thread_marks_pop() except + * they clear the marks bits in the guarded section rather than set them. + * + * The net_thread_is_marked() and net_thread_is_unmarked() functions return + * the subset of the bits that are currently set or cleared (respectively) + * in the uthread:uu_network_marks field. + * + * Finally, the value of the net_thread_marks_none constant is provided for + * comparing for equality with the value returned when no bits in the marks + * field are changed by the push. + * + * It is not significant that a value of type net_thread_marks_t may + * compare as equal to the NULL pointer. + */ +struct net_thread_marks; +typedef const struct net_thread_marks *net_thread_marks_t; -Function : dlil_if_acquire +extern const net_thread_marks_t net_thread_marks_none; - DLIL manages the list of ifnet interfaces allocated using the dlil_if_acquire - function. This list if not the same as the list of attached interfaces, - visible with ifconfig. - This list contains attached as well as detached interfaces. - Detached interfaces are kept in the list to prevent the kernel from crashing - by using an old ifp. +extern net_thread_marks_t net_thread_marks_push(u_int32_t); +extern net_thread_marks_t net_thread_unmarks_push(u_int32_t); +extern void net_thread_marks_pop(net_thread_marks_t); +extern void net_thread_unmarks_pop(net_thread_marks_t); +extern u_int32_t net_thread_is_marked(u_int32_t); +extern u_int32_t net_thread_is_unmarked(u_int32_t); - if it succeeds, dlil_if_acquire returns an ifnet data structure. - This ifnet can either be a new allocated block of memory, or an ifnet - that already existed and that DLIL has found in its list of unused - interface and that matches the family/uniqueid tuple. +extern int dlil_output(ifnet_t, protocol_family_t, mbuf_t, void *, + const struct sockaddr *, int, struct flowadv *); - dlil_if_acquire can fail if the requested interface is already in use, - or if no memory is available to create a new interface. +extern void dlil_input_packet_list(struct ifnet *, struct mbuf *); +extern void dlil_input_packet_list_extended(struct ifnet *, struct mbuf *, + u_int32_t, ifnet_model_t); - The typical sequence of call for a driver will be : - dlil_if_acquire(... &ifp) - ... Fill in the ifnet ... - dlil_if_attach(ifp) - ... Driver work ... - dlil_if_detach(ifp) - dlil_if_release(ifp) +extern errno_t dlil_resolve_multi(struct ifnet *, + const struct sockaddr *, struct sockaddr *, size_t); - Important : ifnet allocated by DLIL are managed by DLIL. DLIL takes care - of them, and keeps them until a driver wants to reuse them, but DLIL may - also decide to free them when not in use by a driver. +extern errno_t dlil_send_arp(ifnet_t, u_int16_t, const struct sockaddr_dl *, + const struct sockaddr *, const struct sockaddr_dl *, + const struct sockaddr *, u_int32_t); - Note : the structure returned will actually be large enough to contain - an arpcom structure (ifnet + ethernet) structure. - Drivers cannot extend the structure and must to store their private - information in if_sofc and if_private. +extern int dlil_attach_filter(ifnet_t, const struct iff_filter *, + interface_filter_t *, u_int32_t); +extern void dlil_detach_filter(interface_filter_t); -Parameters : - 'family' uniquely identifies DLIL interface family. - 'uniqueid' is a unique identifier for that interface, managed by the - driver (for example MAC address for ethernet). - 'uniqueid_len' is the length of the unique id. - 'ifp' contains on output the allocated ifnet. +extern void dlil_proto_unplumb_all(ifnet_t); -Return code : +extern int dlil_post_msg(struct ifnet *, u_int32_t, u_int32_t, + struct net_event_data *, u_int32_t); -0 : +extern void dlil_post_sifflags_msg(struct ifnet *); - If an ifnet matching the uniqueid is found, the matching ifnet is returned - in ifp and the flags IFEF_REUSE and IF_INUSE are set in the if_eflags. - The fields in the ifnet are NOT zeroed and may contain old values that - the driver can reuse. [They are not necessarily the values that were - there when the driver released the ifnet, as protocol might have - continued to update them]. +extern int dlil_post_complete_msg(struct ifnet *, struct kev_msg *); - If no matching ifnet is found, a new structure is allocated and returned - in ifp with all fields initialized to 0. - The flag IF_INUSE is set in the if_eflags. IFEF_REUSE is NOT set. - dlil_if_acquire will copy the uniqueid and keep it for matching purpose. +extern int dlil_alloc_local_stats(struct ifnet *); - If 'uniqueid' is NULL, then dlil_if_acquire will return the first - ifnet that contains a null uniqueid for that family, with the flags - IFEF_REUSE and IF_INUSE set. - If no ifnet is available, a new one will be created. +extern void ifnet_filter_update_tso(boolean_t filter_enable); +extern errno_t dlil_rxpoll_validate_params(struct ifnet_poll_params *); +extern void dlil_rxpoll_update_params(struct ifnet *, + struct ifnet_poll_params *); +extern void ifnet_poll(struct ifnet *); +extern errno_t ifnet_input_poll(struct ifnet *, struct mbuf *, + struct mbuf *, const struct ifnet_stat_increment_param *); -ENOMEM: - If no matching interface is found, and no memory can be allocated, - dlil_if_acquire will return ENOMEM. +/* + * dlil_if_acquire is obsolete. Use ifnet_allocate. + */ +extern int dlil_if_acquire(u_int32_t, const void *, size_t, const char *, struct ifnet **); +/* + * dlil_if_release is obsolete. The equivalent is called automatically when + * an interface is detached. + */ +extern void dlil_if_release(struct ifnet *ifp); +extern errno_t dlil_if_ref(struct ifnet *); +extern errno_t dlil_if_free(struct ifnet *); -EBUSY: +extern int dlil_node_present(struct ifnet *, struct sockaddr *, int32_t, int, + int, u_int8_t[48]); +extern void dlil_node_absent(struct ifnet *, struct sockaddr *); +extern int dlil_node_present_v2(struct ifnet *, struct sockaddr *, struct sockaddr_dl *, int32_t, int, + int, u_int8_t[48]); - If the unique id matches the id of an interface currently in use, - dlil_if_acquire will return EBUSY. - An interface 'in use' is an allocated interface, not necessarily attached. +extern const void *dlil_ifaddr_bytes(const struct sockaddr_dl *, size_t *, + kauth_cred_t *); -*/ +extern void dlil_report_issues(struct ifnet *, u_int8_t[DLIL_MODIDLEN], + u_int8_t[DLIL_MODARGLEN]); -int dlil_if_acquire(u_long family, const void *uniqueid, size_t uniqueid_len, - struct ifnet **ifp); - +#define PROTO_HASH_SLOTS 5 -/* +extern int proto_hash_value(u_int32_t); -Function : dlil_if_release +extern const char *dlil_kev_dl_code_str(u_int32_t); - dlil_if_release will transfer control of the ifnet to DLIL. - DLIL will keep the interface in its list, marking it unused. - The fields will be left in their current state, so the driver can reuse - the ifnet later, by calling dlil_if_acquire. - The if_eflags IF_INUSE will be cleared. - The fields if_output, if_ioctl, if_free and if_set_bpf_tap will be changed - to point to DLIL private functions. - After calling dlil_if_release, the driver can safely terminate and - unload if necessary. - Note: your driver should only call dlil_if_release once your if_free - function has been called. +extern errno_t dlil_rxpoll_set_params(struct ifnet *, + struct ifnet_poll_params *, boolean_t); +extern errno_t dlil_rxpoll_get_params(struct ifnet *, + struct ifnet_poll_params *); -Parameters : - ifp is the pointer to the ifnet to release. +extern errno_t dlil_output_handler(struct ifnet *, struct mbuf *); +extern errno_t dlil_input_handler(struct ifnet *, struct mbuf *, + struct mbuf *, const struct ifnet_stat_increment_param *, + boolean_t, struct thread *); -*/ -void dlil_if_release(struct ifnet *ifp); +/* + * This is mostly called from the context of the DLIL input thread; + * because of that there is no need for atomic operations. + */ +__attribute__((always_inline)) +static inline void +ifp_inc_traffic_class_in(struct ifnet *ifp, struct mbuf *m) +{ + if (!(m->m_flags & M_PKTHDR)) { + return; + } + + switch (m_get_traffic_class(m)) { + case MBUF_TC_BE: + ifp->if_tc.ifi_ibepackets++; + ifp->if_tc.ifi_ibebytes += m->m_pkthdr.len; + break; + case MBUF_TC_BK: + ifp->if_tc.ifi_ibkpackets++; + ifp->if_tc.ifi_ibkbytes += m->m_pkthdr.len; + break; + case MBUF_TC_VI: + ifp->if_tc.ifi_ivipackets++; + ifp->if_tc.ifi_ivibytes += m->m_pkthdr.len; + break; + case MBUF_TC_VO: + ifp->if_tc.ifi_ivopackets++; + ifp->if_tc.ifi_ivobytes += m->m_pkthdr.len; + break; + default: + break; + } + + if (mbuf_is_traffic_class_privileged(m)) { + ifp->if_tc.ifi_ipvpackets++; + ifp->if_tc.ifi_ipvbytes += m->m_pkthdr.len; + } +} +/* + * This is called from DLIL output, hence multiple threads could end + * up modifying the statistics. We trade off acccuracy for performance + * by not using atomic operations here. + */ +__attribute__((always_inline)) +static inline void +ifp_inc_traffic_class_out(struct ifnet *ifp, struct mbuf *m) +{ + if (!(m->m_flags & M_PKTHDR)) { + return; + } + + switch (m_get_traffic_class(m)) { + case MBUF_TC_BE: + ifp->if_tc.ifi_obepackets++; + ifp->if_tc.ifi_obebytes += m->m_pkthdr.len; + break; + case MBUF_TC_BK: + ifp->if_tc.ifi_obkpackets++; + ifp->if_tc.ifi_obkbytes += m->m_pkthdr.len; + break; + case MBUF_TC_VI: + ifp->if_tc.ifi_ovipackets++; + ifp->if_tc.ifi_ovibytes += m->m_pkthdr.len; + break; + case MBUF_TC_VO: + ifp->if_tc.ifi_ovopackets++; + ifp->if_tc.ifi_ovobytes += m->m_pkthdr.len; + break; + default: + break; + } + + if (mbuf_is_traffic_class_privileged(m)) { + ifp->if_tc.ifi_opvpackets++; + ifp->if_tc.ifi_opvbytes += m->m_pkthdr.len; + } +} +#endif /* BSD_KERNEL_PRIVATE */ #endif /* KERNEL_PRIVATE */ #endif /* KERNEL */ #endif /* DLIL_H */