In lwIP device drivers for physical network hardware are represented by a network interface structure similar to that in BSD. The network interfaces are kept on a global linked list, which is linked by the next pointer in the structure.
Step One: Add the interface
To create a new network interface, the user allocates space for a new
struct netif (but does not initialize any part of it) and calls
struct *netif netif_add(struct netif *mynetif, struct ip_addr *ipaddr, struct ip_addr *netmask, struct ip_addr *gw, void *state, err_t (* init)(struct netif *netif), err_t (* input)(struct pbuf *p, struct netif *netif));
The user specifies an IP address for the interface, its net mask, and gateway address (see IP stack for more details). These can be changed later.
state is a driver-specific structure that defines any other "state" information necessary for the driver to function. Some drivers may require the state variable to be set prior to calling netif_add, but many require this argument to be NULL. Check your driver for more information.
init parameter specifies a driver-initialization function that should be called once the
netif structure has been prepared by
netif_add. This parameter may be
NULL if the driver has already been initialized in your code elsewhere.
The final parameter
input is the function that a driver will call when it has received a new packet. This parameter typically takes one of the following values:
ethernet_input: If you are not using a threaded environment and the driver should use ARP (such as for an Ethernet device), the driver will call this function which permits ARP packets to be handled, as well as IP packets.
ip_input: If you are not using a threaded environment and the interface is not an Ethernet device, the driver will directly call the IP stack.
tcpip_ethinput: If you are using the tcpip application thread (see lwIP and threads), the driver uses ARP, and has defined the
ETHARP_TCPIP_ETHINPUTlwIP option. This function is used for drivers that passes all IP and ARP packets to the input function.
tcpip_input: If you are using the tcpip application thread and have defined
ETHARP_TCPIP_INPUToption. This function is used for drivers that pass only IP packets to the input function. (The driver probably separates out ARP packets and passes these directly to the ARP module). (Someone please recheck this: in lwip 1.4.1 there is no tcpip_ethinput() ; tcp_input() handles ARP packets as well).
Step Two: Bring the interface up
An interface that is "up" is available to your application for input and output, and "down" is the opposite state. Therefore, before you can use the interface, you must bring it up. This can be accomplished depending on how the interface gets its IP address. The up/down functions for each type are:
- Static IP address: use
netif_set_down. Be sure to have set the IP address (during the
netif_addor via a
netif_set_addrcall) before you bring the interface up.
- DHCP: use
dhcp_stop. This will bring the interface up and set its IP address when it can acquire one.
- AUTOIP: use
autoip_stop. This will bring the interface up and set its IP address when it has chosen one.
To test whether a
netif is up, you can use
If you add a
netif that should be considered the "default" interface, then you should next call
netif_set_default for that
netif. When the IP stack tries to route the packet, if it cannot determine the right interface to use, it will send it to the default interface.
If you are using a static IP address, then you can set a network interface's IP address and associated settings with the functions
netif_set_netmask. You can set all three in one function call using
A status callback function is provided by the stack if you set the
LWIP_NETIF_STATUS_CALLBACK option in your lwipopts.h file. The status callback will be called anytime the interface is brought up and down. For example, if you would like to log the IP address chosen by DHCP when it has got one, and know when this address changes, then you can use the status callback hook. To set the status callback for a
void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback);