- Protocols of the LwIP Stack
- Protocol Files of LwIP Stack
- Ethernet Controller Interface
- Buffer Management
- Types of pbufs
- APIs for Managing pbufs
Protocols of the LwIP Stack
- IPv4 and IPv6 (Internet Protocol v4 and v6)
- TCP (Transmission Control Protocol)
- UDP (User Datagram Protocol)
- DNS (Domain Name Server)
- SNMP (Simple Network Management Protocol)
- DHCP (Dynamic Host Configuration Protocol)
- PPP (Point to Point Protocol)
- ARP (Address Resolution Protocol)
- ICMP (Internet Control Message Protocol)
- IGMP (Internet Group Management Protocol)

Protocol Files of LwIP Stack
- Application Layer: dhcp.c, dns.c
- Transport Layer: udp.c, tcp.c
- Internet Layer: ip.c
- Network Interface Layer: netif.c
Ethernet Controller Interface
- The official LwIP core stack is hardware-independent and does not include MCU-specific Ethernet MAC/PHY drivers. Hardware-specific drivers are normally provided by the MCU vendor, SDK, BSP, or application.
- For MCU integrations, such as STM32 projects generated by STM32CubeMX, a file named ethernetif.c provides the interface between the LwIP network stack and the underlying Ethernet hardware driver.
- The ethernetif.c is essentially a hardware-abstraction/adaptation layer. It must be implemented or customized for the target MCU, Ethernet MAC, PHY, DMA configuration, and operating environment.
-
The main responsibility of ethernetif.c is to
transfer Ethernet frames between LwIP and the low-level Ethernet driver:
- Transmit: LwIP pbuf → ethernetif.c → Ethernet MAC/DMA driver → Ethernet hardware
- Receive: Ethernet hardware → Ethernet MAC/DMA driver → ethernetif.c → LwIP pbuf
-
Typical functions implemented in
ethernetif.c include:
- low_level_init(): initializes the Ethernet interface and related hardware
- low_level_output(): sends an Ethernet frame
- low_level_input(): receives an Ethernet frame
- ethernetif_input(): passes received packets to the LwIP stack
- ethernetif_init(): initializes and registers the network interface
Buffer Management
- A pbuf (packet buffer) is a core LwIP data structure used to store and manage network packet data.
- A pbuf can either contain dynamically allocated packet data or reference packet data stored elsewhere, including RAM or ROM, depending on the pbuf type and allocation method.
- A single packet may be divided across multiple pbuf structures linked together through the next pointer. This is called a pbuf chain.
- Multiple packets can also be linked using the same next pointer mechanism, forming a packet queue. LwIP distinguishes packet boundaries using fields such as len and tot_len.
-
Important fields in struct pbuf include:
- next: pointer to next pbuf in a pbuf chain
- payload: pointer to packet data
- len: number of data bytes stored in the current pbuf
- tot_len: total number of bytes from the current pbuf to the end of the current packet
- ref (on 4 bits): reference count that indicates the number of pointers that reference the pbuf. A pbuf can be released from memory only when its reference count is zero

Types of pbufs
-
PBUF_POOL
- With PBUF_POOL, pbufs are allocated from a statically configured memory pool containing a fixed number of fixed-size buffers.
- Each allocated pbuf contains both the pbuf structure and a payload buffer.
- If the packet is larger than the payload capacity of a single pool buffer, LwIP allocates multiple pbufs and links them together to form a pbuf chain.
- PBUF_POOL is commonly used for receiving Ethernet packets, where fast and predictable allocation is important.
-
PBUF_RAM
- With PBUF_RAM, memory is dynamically allocated from LwIP’s heap.
- The pbuf structure and its payload are normally allocated as one contiguous block of memory.
- Unlike PBUF_POOL, a PBUF_RAM allocation normally creates a single pbuf large enough to hold the requested packet, rather than chaining multiple fixed-size pool buffers.
- PBUF_RAM is commonly used when constructing or transmitting packets whose size is known at allocation time.
APIs for Managing pbufs
- pbuf_alloc(): Allocates a new pbuf of the specified type and size. For PBUF_POOL, the result may be a chain of multiple pbufs.
- pbuf_realloc(): Shrinks a pbuf or pbuf chain to a specified length. Despite its name, it cannot enlarge a pbuf. Any unused pbufs at the end of the chain are freed.
- pbuf_ref(): Increments the reference count (ref) of a pbuf, indicating that another reference to the pbuf exists.
- pbuf_free(): Decrements the reference count of a pbuf. If the reference count reaches 0, the pbuf is deallocated. For a chain, this process continues until a pbuf with a remaining nonzero reference count is encountered.
- pbuf_clen(): Returns the number of individual pbufs in a pbuf chain.
- pbuf_cat(): Concatenates two pbufs or pbuf chains. It does not increment the reference count of the tail chain; ownership of the caller’s tail reference is transferred to the resulting chain.
- pbuf_chain(): Chains two pbufs or pbuf chains together and increments the reference count of the first pbuf in the tail chain, allowing the caller to retain its own reference to the tail.
- pbuf_dechain(): Detaches the first pbuf from the remainder of a pbuf chain. The first pbuf becomes a standalone pbuf, and the function returns the remaining chain if it is still allocated.
- pbuf_copy_partial(): Copies a specified number of bytes from a pbuf or pbuf chain, starting at a specified offset, into an application-provided buffer.
- pbuf_take(): Copies application-provided data into an existing pbuf or pbuf chain. The destination pbuf must have sufficient capacity.
- pbuf_coalesce(): Converts a chained pbuf into a single contiguous pbuf. If allocation fails, the original pbuf is returned unchanged.
Reference
[1] Light Weight Internet Protocol
[2] Embedded Ethernet Firmware Development Learning Path
Back to top of the page