This chapter describes the network interface KPI. This programming interface allows a KEXT to attach new network interfaces, communicate with and manipulate network interfaces, and create new virtual interfaces.
The mechanism recommended for supporting new interfaces depends on the nature of the interface. The recommended mechanisms are:
Ethernet drivers—subclass the IOEthernetController
and IOEthernetInterface
classes from the I/O Kit’s I/O Networking Family.
Other hardware network controllers—subclass the IONetworkController
and IONetworkInterface
classes.
Virtual interfaces—the interface KPI described in this section is recommended.
This chapter also describes protocol plumbers. Protocol plumbers are used to attach network protocols to interfaces.
If you are creating support for an interface type that the stack does not already support (such as ATM), regardless of whether your KEXT uses the I/O Kit, you must register protocol plumbers for attaching existing protocols to the new interface type.
Note: Since more than one developer might attempt to register plumbers for a given interface type, your KEXT should be prepared to handle such a situation. If the demux descriptors are standard, it should be possible for your KEXT to work with a third-party plumber.
The functionality in a network interface is utilized by both the interface driver and the protocol stacks, as shown in Figure 7-1.
Network Interface Callbacks
Installing and Removing Network Interfaces
Protocol Plumbers
Sending Data
Receiving Data
Your network interface should define the following callbacks, which are called by protocols and drivers:
ifnet_add_proto_func
, which is called whenever a protocol is attached to the interface.
ifnet_check_multi
, which is called when a multicast address is added to an interface. This allows the interface to reject invalid multicast addresses before they are added to the interface.
ifnet_del_proto_func
, which is called when a protocol is detached from the interface.
ifnet_demux_func
, which is called with a raw packet from the interface, and returns the protocol family value of the protocol that should process the packet. It can do this using either the demux descriptors registered with ifnet_add_proto_func
or hard-coded logic. If the packet does not match any protocol, the function should return ENOENT
.
ifnet_detached_func
, which is called when your interface is detached.
ifnet_event_func
, which is called when an event occurs on a particular interface.
ifnet_framer_func
, which is called with outgoing packets before sending them to outgoing interface filters, and is expected to wrap the packet with a stack frame appropriate to the interface type.
ifnet_ioctl_func
, which is called whenever an ioctl is received for the interface. The network interface is expected to pass these on to the I/O Kit driver if it is necessary and appropriate to do so. All undefined ioctls are reserved for future Apple use. You should use kern_control
if you need to add additional control mechanisms.
ifnet_output_func
, which is called with a packet that is ready to be sent out the wire. The network interface is expected to transmit the packet and free the mbuf associated with it. For network interfaces backed by I/O Kit drivers, this callback generally calls a function in the I/O Kit driver that handles both of these tasks.
ifnet_set_bpf_tap
, which is called by the stack to set the BPF tap function that is installed on the interface. This callback is optional, but recommended; if you do not add this function, BPF cannot be used with your interface.
Note: To support BPF, in addition to defining an ifnet_set_bpf_tap
callback, your KEXT must also call bpfattach
after attaching the interface to the stack.
Good examples of many of these functions can be found in bsd/net/ether_if_module.c
in the xnu
(kernel) source tree.
The following functions are typically called (in the following order) to support the dynamic insertion and removal of network interfaces:
ifnet_allocate
, which allocates an interface structure.
ifnet_attach
, which attaches an interface to the global interface list.
bpfattach
, which enables BPF support on an interface (optional).
ifnet_detach
, which removes an interface from the global interface list.
ifnet_release
, which releases a reference to an interface structure. If the reference count reaches zero (0), the structure will be freed. This release matches the ifnet_allocate
call earlier, and should be called after calling ifnet_detach
.
The related function ifnet_reference
can be used (generally by other KEXTs) to increase the reference count of an interface structure. These calls must be balanced by an equal number of calls to ifnet_release
.
Protocol plumbers, as mentioned previously, are responsible for attaching a protocol to a network interface. When a protocol needs to attach to an interface, it calls a function that looks up the plumber designated for that protocol and interface type, then calls that plumber’s plumb handler.
Protocol plumbers define the following callbacks, which are called by protocols:
proto_plumb_handler
, which is called to attach a protocol to an interface. This typically consists of a call to the interface’s ifnet_attach_protocol
callback.
proto_unplumb_handler
, which is called to detach a protocol from an interface. The unplumb handler should call the ifnet_detach_protocol
function, but may do other cleanup such as freeing any storage allocated in the proto_plumb_handler
callback.
Note: The protocol unplumb handler is optional. If it is NULL
, the stack will directly call ifnet_detach_protocol
to unplumb the protocol. The plumber only needs to specify an unplumb handler if it needs to do additional cleanup.
When attaching a protocol to an interface, the protocol plumber typically fills in the following fields in the ifnet_attach_proto_param
structure, many of which may be defined as part of the protocol itself. This mechanism provides the opportunity for the protocol plumber to intercept these calls and take interface-specific actions where needed.
proto_media_detached
(optional), which is used to notify the protocol that it is being detached.
proto_media_event
(optional), which is called to notify a protocol about interface-specific events.
proto_media_input
(required), which is used to deliver an inbound packet to the protocol for processing.
proto_media_ioctl
(optional), which is typically the protocol’s ioctl handling function.
proto_media_preout
(required), which is called just before a packet is transmitted. This allows the protocol to specify a media-specific frame type and destination.
proto_media_resolve_multi
(optional), which is used to obtain a link layer address for a given protocol layer multicast address. This is only necessary if your interface supports multicast.
proto_media_send_arp
(optional), which is used to obtain the link layer address corresponding to a given protocol layer unicast address. This is necessary for all non-point-to-point interfaces.
Examples of these functions can be found in bsd/net/ether_inet_pr_module.c
in the xnu
(kernel) source tree.
The following steps describe the process of sending a packet, using Ethernet as the example medium:
The ip_output
routine in the IP protocol stack calls ifnet_output
.
The ifnet_output
function calls the protocol plumber’s proto_media_preout
function. In the case of IP, this function calls inet_arp_lookup
.
If the ARP cache does not contain an entry for the IP address, inet_arp_lookup
then calls the protocol plumber’s proto_media_send_arp
callback to resolve the target IP address into a media access control (MAC) address.
When the proto_media_preout
callback returns, the ifnet_output
function calls the network interface’s ifnet_framer_func
function. This framing function prepends interface-specific frame data to the packet.
If any interface filters are present, their iff_output_func
callbacks are called consecutively.
The ifnet_output
function calls the network interface’s ifnet_output_func
callback, which transmits the packet and frees the mbuf.
The following steps describe the process of receiving a packet:
The hardware driver or its support code calls ifnet_input
with pointers to its ifnet
structure (ifnet_t
) and mbuf
chain (mbuf_t
).
The packet is queued. Processing resumes on a different thread.
The ifnet_input
function calls the network interface’s ifnet_demux_func
function for the interface.
The demultiplexing function identifies the frame and returns a protocol_family_t
value to indicate which protocol should handle the packet.
The ifnet_input
function calls the attached interface filters (if any) sequentially.
Any packets not matching an attached protocol are dropped, as are any promiscuous packets.
The ifnet_input
function calls the protocol plumber’s proto_media_input
function. The plumber is specific to a given protocol/interface combination.
Note: The Ethernet-specific module for IP receives the frame and delivers the packet to the protocol's proto_input
routine.
© 2003, 2009 Apple Inc. All Rights Reserved. (Last updated: 2009-03-02)