+ * @function ifnet_allocate
+ * @discussion Allocate an ifnet_t with an initial refcount of 1. Many
+ * parts of the stack do not properly refcount the ifnet_t. In
+ * order to avoid freeing the ifnet_t while some parts of the stack
+ * may contain a reference to it, the ifnet_ts are only recycled,
+ * never freed. A unique id is used to try and recycle the same
+ * ifnet_t when allocating an interface. For example, for an
+ * ethernet interface, the hardware address of the ethernet card is
+ * usually used for the uniqueid. If a PC Card is removed and
+ * inserted again, if the ethernet address of the PC card is used,
+ * the same ifnet_t will be used for the card the second time it is
+ * inserted. In the future, when the ifnet_t is correctly
+ * refcounted by all of the stack, the interfaces may be freed and
+ * the unique ids ignored.
+ * @param init The initial values for the interface. These values can
+ * not be changed after the interface has been allocated.
+ * @param interface The interface allocated upon success.
+ * @result May return ENOMEM if there is insufficient memory or EEXIST
+ * if an interface with the same uniqueid and family has already
+ * been allocated and is in use.
+ */
+#ifdef KERNEL_PRIVATE
+extern errno_t ifnet_allocate_internal(const struct ifnet_init_params *init,
+ ifnet_t *interface);
+
+#define ifnet_allocate(init, interface) \
+ ifnet_allocate_internal((init), (interface))
+#else
+extern errno_t ifnet_allocate(const struct ifnet_init_params *init,
+ ifnet_t *interface);
+#endif /* KERNEL_PRIVATE */
+
+#ifdef KERNEL_PRIVATE
+/*
+ * @function ifnet_allocate_extended
+ * @discussion An extended/newer variant of ifnet_allocate, with additional
+ * support for the new output and input driver models.
+ * @param init The initial values for the interface. These values can
+ * not be changed after the interface has been allocated.
+ * @param interface The interface allocated upon success.
+ * @result May return ENOMEM if there is insufficient memory or EBUSY
+ * if an interface with the same uniqueid/(name + unit) and family has already
+ * been allocated and is in use.
+ */
+extern errno_t ifnet_allocate_extended(const struct ifnet_init_eparams *init,
+ ifnet_t *interface);
+
+/*
+ * @function ifnet_purge
+ * @discussion Purge the output queue of an interface which implements
+ * the new driver output model.
+ * @param interface The interface to purge.
+ */
+extern void ifnet_purge(ifnet_t interface);
+
+/*
+ * @function ifnet_enqueue
+ * @discussion Enqueue a packet to the output queue of an interface
+ * which implements the new driver output model.
+ * @param interface The interface to enqueue the packet to.
+ * @param packet The packet being enqueued; only one packet is allowed
+ * to be enqueued at a time.
+ * @result May return EINVAL if the parameters are invalid; ENXIO if
+ * the interface doesn't implement the new driver output model;
+ * EQFULL if the output queue is flow-controlled; or EQSUSPENDED
+ * if the output queue is suspended. This routine either frees
+ * or consumes the packet; the caller must not modify or free
+ * it after calling this routine. Any attempt to enqueue more
+ * than one packet will cause the entire packet chain to be freed.
+ */
+extern errno_t ifnet_enqueue(ifnet_t interface, mbuf_t packet);
+
+/*
+ * @function ifnet_dequeue
+ * @discussion Dequeue a packet from the output queue of an interface
+ * which implements the new driver output model, and that the
+ * output scheduling model is set to IFNET_SCHED_MODEL_NORMAL.
+ * @param interface The interface to dequeue the packet from.
+ * @param packet Pointer to the packet being dequeued.
+ * @result May return EINVAL if the parameters are invalid, ENXIO if
+ * the interface doesn't implement the new driver output model
+ * or the output scheduling model isn't IFNET_SCHED_MODEL_NORMAL,
+ * or EAGAIN if there is currently no packet available to
+ * be dequeued.
+ */
+extern errno_t ifnet_dequeue(ifnet_t interface, mbuf_t *packet);
+
+/*
+ * @function ifnet_dequeue_service_class
+ * @discussion Dequeue a packet of a particular service class from the
+ * appropriate output queue of an interface which implements the
+ * new driver output model, and that the output scheduling model
+ * is set to IFNET_SCHED_MODEL_DRIVER_MANAGED.
+ * @param interface The interface to dequeue the packet from.
+ * @param sc The service class.
+ * @param packet Pointer to the packet being dequeued.
+ * @result May return EINVAL if the parameters are invalid, ENXIO if
+ * the interface doesn't implement the new driver output model
+ * or if the output scheduling model isn't configured to
+ * IFNET_SCHED_MODEL_DRIVER_MANAGED, or EAGAIN if there
+ * is currently no packet available to be dequeued.
+ */
+extern errno_t ifnet_dequeue_service_class(ifnet_t interface,
+ mbuf_svc_class_t sc, mbuf_t *packet);
+
+/*
+ * @function ifnet_dequeue_multi
+ * @discussion Dequeue one or more packets from the output queue of an
+ * interface which implements the new driver output model, and that
+ * the output scheduling model is set to IFNET_SCHED_MODEL_NORMAL.
+ * The returned packet chain is traversable with mbuf_nextpkt().
+ * @param interface The interface to dequeue the packets from.
+ * @param max The maximum number of packets in the packet chain that
+ * may be returned to the caller; this needs to be a non-zero
+ * value for any packet to be returned.
+ * @param first_packet Pointer to the first packet being dequeued.
+ * @param last_packet Pointer to the last packet being dequeued. Caller
+ * may supply NULL if not interested in value.
+ * @param cnt Pointer to a storage for the number of packets dequeued.
+ * Caller may supply NULL if not interested in value.
+ * @param len Pointer to a storage for the total length (in bytes)
+ * of the dequeued packets. Caller may supply NULL if not
+ * interested in value.
+ * @result May return EINVAL if the parameters are invalid, ENXIO if
+ * the interface doesn't implement the new driver output model
+ * or the output scheduling model isn't IFNET_SCHED_MODEL_NORMAL,
+ * or EAGAIN if there is currently no packet available to
+ * be dequeued.
+ */
+extern errno_t ifnet_dequeue_multi(ifnet_t interface, u_int32_t max,
+ mbuf_t *first_packet, mbuf_t *last_packet, u_int32_t *cnt, u_int32_t *len);
+
+/*
+ * @function ifnet_dequeue_multi_bytes
+ * @discussion Dequeue one or more packets from the output queue of
+ * an interface which implements the new driver output model,
+ * where the scheduling model is set to
+ * IFNET_SCHED_MODEL_NORMAL. The limit is specified in terms
+ * of maximum number of bytes to return. The number of bytes
+ * returned can be slightly higher than the limit so that
+ * packet boundaries can be preserved.
+ * @param interface The interface to dequeue the packets from
+ * @param max_bytes The maximum number of bytes in the packet chain
+ * that may be returned to the caller; this needs to be a
+ * non-zero value for any packet to be returned.
+ * @param first_packet Pointer to the first packet being dequeued
+ * @param last_packet Pointer to the last packet being dequeued
+ * @param cnt Pointer to a storage for the number of bytes dequeued.
+ * Caller may supply NULL if not interested in this value
+ * @param len Pointer to a storage for the total length (in bytes)
+ * of the dequeued packets. Caller may supply NULL if not
+ * interested in this value.
+ * @result May return EINVAL if the parameters are invalid, ENXIO if
+ * the interface doesn't implement the new driver output
+ * model or the output scheduling model isn't
+ * IFNET_SCHED_MODEL_NORMAL, or EAGAIN if there is currently
+ * no packet available to be dequeued
+ */
+extern errno_t ifnet_dequeue_multi_bytes(ifnet_t interface,
+ u_int32_t max_bytes, mbuf_t *first_packet, mbuf_t *last_packet,
+ u_int32_t *cnt, u_int32_t *len);
+
+/*
+ * @function ifnet_dequeue_service_class_multi
+ * @discussion Dequeue one or more packets of a particular service class
+ * from the appropriate output queue of an interface which
+ * implements the new driver output model, and that the output
+ * scheduling model is set to IFNET_SCHED_MODEL_DRIVER_MANAGED.
+ * The returned packet chain is traversable with mbuf_nextpkt().
+ * @param interface The interface to dequeue the packets from.
+ * @param sc The service class.
+ * @param max The maximum number of packets in the packet chain that
+ * may be returned to the caller; this needs to be a non-zero
+ * value for any packet to be returned.
+ * @param first_packet Pointer to the first packet being dequeued.
+ * @param last_packet Pointer to the last packet being dequeued. Caller
+ * may supply NULL if not interested in value.
+ * @param cnt Pointer to a storage for the number of packets dequeued.
+ * Caller may supply NULL if not interested in value.
+ * @param len Pointer to a storage for the total length (in bytes)
+ * of the dequeued packets. Caller may supply NULL if not
+ * interested in value.
+ * @result May return EINVAL if the parameters are invalid, ENXIO if
+ * the interface doesn't implement the new driver output model
+ * or if the output scheduling model isn't configured to
+ * IFNET_SCHED_MODEL_DRIVER_MANAGED, or EAGAIN if there
+ * is currently no packet available to be dequeued.
+ */
+extern errno_t ifnet_dequeue_service_class_multi(ifnet_t interface,
+ mbuf_svc_class_t sc, u_int32_t max, mbuf_t *first_packet,
+ mbuf_t *last_packet, u_int32_t *cnt, u_int32_t *len);
+
+/*
+ * @function ifnet_set_output_sched_model
+ * @discussion Set the output scheduling model of an interface which
+ * implements the new driver output model.
+ * @param interface The interface to set scheduling model on.
+ * @param model The IFNET_SCHED_MODEL value as defined in net/if.h
+ * @result May return EINVAL if the parameters are invalid or ENXIO if
+ * the interface doesn't implement the new driver output model.
+ */
+extern errno_t ifnet_set_output_sched_model(ifnet_t interface,
+ u_int32_t model);
+
+/*
+ * @function ifnet_set_sndq_maxlen
+ * @discussion Set the maximum length of the output queue of an
+ * interface which implements the new driver output model.
+ * This call may be issued post ifnet_allocate_extended in
+ * order to modify the maximum output queue length previously
+ * set at registration time.
+ * @param interface The interface to set the max queue length on.
+ * @param maxqlen The maximum number of packets in the output queue.
+ * @result May return EINVAL if the parameters are invalid or ENXIO if
+ * the interface doesn't implement the new driver output model.
+ */
+extern errno_t ifnet_set_sndq_maxlen(ifnet_t interface, u_int32_t maxqlen);
+
+/*
+ * @function ifnet_get_sndq_maxlen
+ * @discussion Get the maximum length of the output queue of an
+ * interface which implements the new driver output model.
+ * @param interface The interface to get the max queue length on.
+ * @param maxqlen Pointer to a storage for the maximum number of packets
+ * in the output queue for all service classes.
+ * @result May return EINVAL if the parameters are invalid or ENXIO if
+ * the interface doesn't implement the new driver output model.
+ */
+extern errno_t ifnet_get_sndq_maxlen(ifnet_t interface, u_int32_t *maxqlen);
+
+/*
+ * @function ifnet_get_sndq_len
+ * @discussion Get the current length of the output queue of an
+ * interface which implements the new driver output model.
+ * @param interface The interface to get the current queue length on.
+ * @param packets Pointer to a storage for the current number of packets
+ * in the aggregate output queue. This number represents all
+ * enqueued packets regardless of their service classes.
+ * @result May return EINVAL if the parameters are invalid or ENXIO if
+ * the interface doesn't implement the new driver output model.
+ */
+extern errno_t ifnet_get_sndq_len(ifnet_t interface, u_int32_t *packets);
+
+/*
+ * @function ifnet_get_service_class_sndq_len
+ * @discussion Get the current length of the output queue for a specific
+ * service class of an interface which implements the new driver
+ * output model.
+ * @param interface The interface to get the current queue length on.
+ * @param sc The service class.
+ * @param packets Pointer to a storage for the current number of packets
+ * of the specific service class in the output queue; may be
+ * NULL if caller is not interested in getting the value. Note
+ * that multiple service classes may be mapped to an output queue;
+ * this routine reports the packet count of that output queue.
+ * @param bytes Pointer to a storage for the current size (in bytes) of
+ * the output queue specific to the service class; may be NULL if
+ * caller is not interested in getting the value. Note that
+ * multiple service classes may be mapped to an output queue;
+ * this routine reports the length of that output queue.
+ * @result May return EINVAL if the parameters are invalid or ENXIO if
+ * the interface doesn't implement the new driver output model.
+ */
+extern errno_t ifnet_get_service_class_sndq_len(ifnet_t interface,
+ mbuf_svc_class_t sc, u_int32_t *packets, u_int32_t *bytes);
+
+/*
+ * @function ifnet_set_rcvq_maxlen
+ * @discussion Set the maximum length of the input queue of an
+ * interface which implements the new driver input model.
+ * This call may be issued post ifnet_allocate_extended in
+ * order to modify the maximum input queue length previously
+ * set at registration time.
+ * @param interface The interface to set the max queue length on.
+ * @param maxqlen The maximum number of packets in the input queue.
+ * Drivers typically set this to the size of the receive ring
+ * or the total number of descriptors used for the input path.
+ * @result May return EINVAL if the parameters are invalid or ENXIO if
+ * the interface doesn't implement the new driver input model.
+ */
+extern errno_t ifnet_set_rcvq_maxlen(ifnet_t interface, u_int32_t maxqlen);
+
+/*
+ * @function ifnet_get_rcvq_maxlen
+ * @discussion Get the maximum length of the input queue of an
+ * interface which implements the new driver input model.
+ * @param interface The interface to get the max queue length on.
+ * @param maxqlen Pointer to a storage for the maximum number of packets
+ * in the input queue.
+ * @result May return EINVAL if the parameters are invalid or ENXIO if
+ * the interface doesn't implement the new driver input model.
+ */
+extern errno_t ifnet_get_rcvq_maxlen(ifnet_t interface, u_int32_t *maxqlen);
+
+/*
+ * @struct ifnet_poll_params
+ * @discussion This structure is used to define various opportunistic
+ * polling parameters for an interface.
+ * @field flags Currently unused/ignored; must be set to zero.
+ * @field packets_limit The maximum number of packets to be dequeued
+ * each time the driver's input poll callback is invoked while
+ * in polling mode; this corresponds to the max_count parameter
+ * of ifnet_input_poll_func. A zero value indicates the use of
+ * default maximum packets defined by the system.
+ * @field packets_lowat Low watermark packet threshold.
+ * @field packets_hiwat High watermark packet threshold.
+ * @field bytes_lowat Low watermark packet threshold.
+ * @field bytes_hiwat High watermark packet threshold.
+ * The low and high watermark inbound packet and bytes thresholds;
+ * these values may be link rate dependent. Polling is enabled
+ * when the average inbound packets or bytes goes above the
+ * corresponding high watermark value; it stays in that mode until
+ * both of the average inbound packets and bytes go below their
+ * corresponding low watermark values. Zero watermark values
+ * indicates the use of default thresholds as defined by the
+ * system. Both low and high watermark values must either be
+ * zeroes, or both must be non-zeroes with low watermark value
+ * being less than the high watermark value.
+ * @field interval_time The interval time between each invocation of
+ * the driver's input poll callback, in nanoseconds. A zero
+ * value indicates the use of default poll interval time as
+ * defined by the system. If a non-zero value is specified and
+ * is less than the minimum interval time, the latter will be
+ * chosen by the system.
+ */
+struct ifnet_poll_params {
+ u_int32_t flags;
+ u_int32_t packets_limit;
+ u_int32_t packets_lowat;
+ u_int32_t packets_hiwat;
+ u_int32_t bytes_lowat;
+ u_int32_t bytes_hiwat;
+ u_int64_t interval_time;
+ u_int64_t reserved[4];
+};
+
+typedef struct ifnet_poll_params ifnet_poll_params_t;
+
+/*
+ * @function ifnet_set_poll_params
+ * @discussion Configures opportunistic input polling parameters on an
+ * interface. This call may be issued post ifnet_attach in order
+ * to modify the interface's polling parameters. The driver may
+ * alter the default values chosen by the system to achieve the
+ * optimal performance for a given link rate or driver dynamics.
+ * @param interface The interface to configure opportunistic polling on.
+ * @param poll_params Pointer to the polling parameters. If NULL, it
+ * implies that the system should revert the interface's polling
+ * parameter to their default values.
+ * @result May return EINVAL if the parameters are invalid or ENXIO if
+ * the interface doesn't implement the new driver input model.
+ */
+extern errno_t ifnet_set_poll_params(ifnet_t interface,
+ ifnet_poll_params_t *poll_params);
+
+/*
+ * @function ifnet_poll_params
+ * @discussion Retrieves opportunistic input polling parameters on an
+ * interface. This call may be issued post ifnet_attach in order
+ * to retrieve the interface's polling parameters.
+ * @param interface The interface to configure opportunistic polling on.
+ * @param poll_params Pointer to the polling parameters.
+ * @result May return EINVAL if the parameters are invalid or ENXIO if
+ * the interface doesn't implement the new driver input model.
+ */
+extern errno_t ifnet_poll_params(ifnet_t interface,
+ ifnet_poll_params_t *poll_params);
+
+/*
+ * @function ifnet_start
+ * @discussion Trigger the transmission at the driver layer on an
+ * interface which implements the new driver output model.
+ * @param interface The interface to start the transmission on.
+ */
+extern void ifnet_start(ifnet_t interface);
+
+/*
+ * @function ifnet_flowid
+ * @discussion Returns the interface flow ID value, which can be used
+ * by a (virtual) network interface for participating in the
+ * FLOWSRC_IFNET flow advisory mechanism. The flow ID value
+ * is available after the interface is attached.
+ * @param interface The interface to retrieve the flow ID from.
+ * @param flowid Pointer to the flow ID value.
+ * @result May return EINVAL if the parameters are invalid or ENXIO if
+ * the interface doesn't implement the new driver input model.
+ */
+extern errno_t ifnet_flowid(ifnet_t interface, u_int32_t *flowid);
+
+/*
+ * @function ifnet_enable_output
+ * @discussion Enables output on a (virtual) interface if it has been
+ * previously disabled via ifnet_disable_output(). This call
+ * is used to override the flow advisory mechanism typically
+ * used between a (virtual) network interface and a real network
+ * interface beneath it. Under normal circumstances, the flow
+ * advisory mechanism will automatically re-enable the (virtual)
+ * interface's output mechanism when the real network interface
+ * is able to transmit more data. Re-enabling output will cause
+ * the (virtual) interface's start callback to be called again.
+ * @param interface The interface to enable the transmission on.
+ * @result May return EINVAL if the parameters are invalid or ENXIO if
+ * the interface doesn't implement the new driver input model.
+ */
+extern errno_t ifnet_enable_output(ifnet_t interface);
+
+/*
+ * @function ifnet_disable_output
+ * @discussion Disables output on a (virtual) interface. Disabling
+ * output will cause the (virtual) interface's start callback
+ * to go idle. This call is typically used by a (virtual)
+ * interface upon receiving flow control feedbacks from the
+ * real network interface beneath it, in order propagate the
+ * flow control condition to the layers above. Under normal
+ * circumstances, the flow advisory mechanism will automatically
+ * re-enable the (virtual) interface's output mechanism when
+ * the real network interface is able to transmit more data,
+ * as long as the (virtual) interface participates in the
+ * FLOWSRC_IFNET flow advisory for the data that it emits.
+ * @param interface The interface to disable the transmission on.
+ * @result May return EINVAL if the parameters are invalid or ENXIO if
+ * the interface doesn't implement the new driver input model.
+ */
+extern errno_t ifnet_disable_output(ifnet_t interface);
+#endif /* KERNEL_PRIVATE */
+
+/*!
+ * @function ifnet_reference
+ * @discussion Increment the reference count of the ifnet to assure
+ * that it will not go away. The interface must already have at
+ * least one reference.
+ * @param interface The interface to increment the reference count of.
+ * @result May return EINVAL if the interface is not valid.
+ */
+extern errno_t ifnet_reference(ifnet_t interface);
+
+/*!
+ * @function ifnet_release
+ * @discussion Release a reference of the ifnet, this may trigger a
+ * free if the reference count reaches 0.
+ * @param interface The interface to decrement the reference count of
+ * and possibly free.
+ * @result May return EINVAL if the interface is not valid.
+ */
+extern errno_t ifnet_release(ifnet_t interface);
+
+/*!
+ * @function ifnet_attach
+ * @discussion Attaches an interface to the global interface list. The
+ * interface must be setup properly before calling attach. The
+ * stack will take a reference on the interface and hold it until
+ * ifnet_detach is called.
+ *
+ * This function is intended to be called by the driver. A kext
+ * must not call this function on an interface the kext does not
+ * own.
+ * @param interface The interface to attach.
+ * @param ll_addr The link layer address of the interface. This is used
+ * to fill out the first ifaddr in the list of addresses for the
+ * interface. This parameter is not required for interfaces such as
+ * PPP that have no link-layer address.
+ * @result Will return an error if there is anything wrong with the
+ * interface.
+ */
+extern errno_t ifnet_attach(ifnet_t interface,
+ const struct sockaddr_dl *ll_addr);
+
+/*!
+ * @function ifnet_detach
+ * @discussion Detaches the interface.
+ *
+ * Call this to indicate this interface is no longer valid (i.e. PC
+ * Card was removed). This function will begin the process of
+ * removing knowledge of this interface from the stack.
+ *
+ * The function will return before the interface is detached. The
+ * functions you supplied in to the interface may continue to be
+ * called. When the detach has been completed, your detached
+ * function will be called. Your kext must not unload until the
+ * detached function has been called. The interface will be
+ * properly freed when the reference count reaches zero.
+ *
+ * An interface may not be attached again. You must call
+ * ifnet_allocate to create a new interface to attach.
+ *
+ * This function is intended to be called by the driver. A kext
+ * must not call this function on an interface the kext does not
+ * own.
+ * @param interface The interface to detach.
+ * @result 0 on success, otherwise errno error.
+ */
+extern errno_t ifnet_detach(ifnet_t interface);
+
+/*!
+ * @function ifnet_interface_family_find
+ * @discussion Look up the interface family identifier for a string.
+ * If there is no interface family identifier assigned for this string
+ * a new interface family identifier is created and assigned.
+ * It is recommended to use the bundle id of the KEXT as the string
+ * to avoid collisions with other KEXTs.
+ * The lookup operation is not optimized so a module should call this
+ * function once during startup and cache the interface family identifier.
+ * The interface family identifier for a string will not be re-assigned until
+ * the system reboots.
+ * @param module_string A unique string identifying your interface family
+ * @param family_id Upon return, a unique interface family identifier for use with
+ * ifnet_* functions. This identifier is valid until the system
+ * is rebooted.
+ * @result 0 on success, otherwise errno error.
+ */
+extern errno_t ifnet_interface_family_find(const char *module_string, ifnet_family_t *family_id);