Using lwIP with or without an operating system

There has been a few questions about how lwIP can be used in a standalone environment (i.e., an environment without a multi-threaded operating system) lately. The purpose of this document is to describe how lwIP is designed to be used with and without a multi-threaded operating system.

The lwIP single-threaded core

The core of lwIP consists of the actual implementations of the IP, ICMP, UDP, and TCP protocols, as well as the support functions such as buffer and memory management. The core components are the only ones that are needed when lwIP is to be run in a single-threaded (non-OS) environment.

The core components can be viewed as a software library which has the following interface:

Because none of the core functions ever needs to block when run in a single-threaded environment, the sys_arch (the operating system abstraction layer) does not need to implement locking semaphores or mailboxes. In future versions of lwIP, the dependancy of the sys_arch will be removed in the single-threaded case.

A simple main loop for a single-threaded system might look like this:

  while(1) {
    if(poll_driver(netif) == PACKET_READY) {
      pbuf = get_packet(netif);
      ip_input(pbuf, netif);
    }

    if(clock() - last_time == 100 * CLOCK_MS) {
      tcp_tmr();
      last_time = clock();
    }    
  }

lwIP in a multi-threaded system

lwIP is designed to be able to be run in a multi-threaded system with applications running in concurrent threads. The model used in this case is that all TCP/IP processing is done in a single thread. The application thread communicate with the TCP/IP thread using the sequential API.

The inter-thread communication is implemented in the two files api_lib.c and api_msg.c. The former contains the functions used by the application programs and the latter implements the TCP/IP stack interface. A third file, tcpip.c, handles incoming packets and timer events as described in the previous section.

When run in a multi-threaded environment, incoming packets are handled by the function tcpip_input(), which takes the same arguments as the ip_input() function. The difference between the two functions is that the tcpip_input() function does not process the incoming packet immediately. It merely puts the packet on a queue which later is drained by the TCP/IP thread.

When being run in a multi-threaded system, timer events are taken care of internally in tcpip.c.

UPDATED($Date: 2003/01/20 14:13:31 $)