Chapter 164. Sequential API
Table of Contents
- 164.1. Overview
- 164.2. Comparison with BSD sockets
- 164.3. Netbufs
- 164.4. TCP/IP thread
- 164.5. Usage
- 164.6. API reference
- netbuf_new() — Allocate a netbuf structure
- netbuf_delete() — Deallocate a netbuf structure
- netbuf_alloc() — Allocate space in a netbuf
- netbuf_free() — Deallocate buffer memory associated with a netbuf
- netbuf_ref() — Associate a data pointer with a netbuf
- netbuf_len() — Obtain the total length of a netbuf
- netbuf_data() — Obtain a pointer to netbuf data
- netbuf_next() — Traverse internal fragments in a netbuf
- netbuf_first() — Reset fragment pointer to start of netbuf
- netbuf_copy() — Copy all netbuf data to memory pointer
- netbuf_copy_partial() — Copy some netbuf data to memory pointer
- netbuf_chain() — Chain two netbufs together
- netbuf_fromaddr() — Obtain the sender's IPv4 address for a netbuf
- netbuf_fromaddr_ip6() — Obtain the sender's IPv6 address for a netbuf
- netbuf_fromport() — Obtain the sender's port number for a netbuf
- netconn_new() — Create a new connection structure
- netconn_new_with_callback() — Create a new connection structure with a callback
- netconn_new_with_proto_and_callback() — Create a new connection structure with a callback for a specific protocol
- netconn_delete() — Deallocate a netconn
- netconn_type() — Obtain the type of netconn
- netconn_peer() — Obtain the remote host IP address/port of a netconn
- netconn_addr() — Obtain the local host IPv4 address/port of a netconn
- netconn_bind() — Set local IP address/port of a netconn
- netconn_bind_ip6() — Set local IPv6 address/port of a netconn
- netconn_connect() — Connect netconn to remote peer
- netconn_connect_ip6() — Connect netconn to remote peer
- netconn_disconnect() — Disconnect UDP connection
- netconn_listen() — Make a listening TCP netconn
- netconn_accept() — Wait for incoming connections
- netconn_recv() — Wait for data
- netconn_recv_tcp_pbuf() — Wait for data
- netconn_recved() — Update receive window
- netconn_write() — Send data on TCP connection
- netconn_send() — Send data on UDP connection
- netconn_close() — Close a connection
- netconn_shutdown() — Shutdown a connection
- netconn_set_noautorecved() — Set the connection no-auto-recved state
- netconn_get_noautorecved() — Get the connection no-auto-recved state
- netconn_err() — Obtain connection error status
164.1. Overview
As described earlier, the lwIP sequential API provides a straightforward and easy-to-use method of interfacing to the stack. Unlike the raw API, which requires event-driven callbacks, an application can simply call the API functions as needed to perform stack operations such as sending data, receiving data, or manipulating packet buffers or connections. While the raw API may allow for more efficient operation, the sequential API typically allows for simpler application design.
164.2. Comparison with BSD sockets
In design, it is not unlike the BSD sockets API. Some of the terminology differs however: in the sequential API, the term connection is used for any communication link between network peers, and the handle for a connection is termed a netconn. A netconn can be considered analogous to a socket, albeit specific to networking - BSD sockets traditionally represent both network connections and files.
The main reason for superiority over the socket API occurs with buffer management. The BSD socket API was designed to manage the fact that the user and the operating system kernel operate in different address spaces and data must always be copied regardless. This results in not only decreased performance, but also increased footprint as buffers must be allocated to hold the copied data.
164.2.1. BSD API Restrictions
By default the eCos lwIP configurations enable the
option CYGFUN_LWIP_COMPAT_SOCKETS
which means normally you
cannot include both the lwIP
headers <lwip/sockets.h>
or <network.h>
, and
the CYGPKG_IO_FILEIO
package (i.e. POSIX-alike) headers
from the same file.
164.3. Netbufs
Instead of the BSD approach of generic buffers, the sequential API uses netbufs, which are based on pbufs. This allows users to manage buffers directly, including even allowing data to come from ROM. Since pbufs, and hence netbufs, can be chained, this also allows the application and lwIP to avoid the need for large regions of entirely contiguous memory in order to hold data. Instead data can be constructed in chunks, and chained together.
When the application wishes to send data, it can send a netbuf directly with UDP. TCP is different as it is intrinsically a buffering, streaming protocol, which requires data to be kept aside to allow for retransmissions. As a result data is sent using just a pointer to memory and a length. However since TCP data can also reside in ROM, it is possible to indicate that the data does not need copying, and so will persist even if the stack needs to queue the data. This can lead to huge savings of memory. For example, static web page content can reside in ROM, and never need to be copied to RAM.
For both TCP and UDP, incoming data is passed to the application as
netbufs. The application can use API functions to extract the data from
the netbufs - care must be taken as the received data may in fact be
a chain. A convenience function exists to copy out the entirety of
data across the whole chain into a single contiguous region of memory.
Otherwise the application can process data in each netbuf in the
chain in turn. The functions netbuf_first()
and netbuf_next()
can be used to iterate
throught the chain.
164.4. TCP/IP thread
When interacting with the network stack using the sequential API, all operations are not handled by the calling thread, but instead are passed to the lwIP network processing (TCP/IP) thread. Inter-thread communication is used inside lwIP to ensure that at the point the API function returns, operation is either complete, or for asynchronous operations, under way.
For example, to register a timeout callback
the tcpip_timeout()
function can be used from client
threads to cross the thread boundary into the sequential TCP/IP thread. However,
since the actual timeout callback handler registered will be executed within the
sequential TCP/IP thread context, it can subsequently directly call the lwIP
internal sys_timeout()
if it needs to re-schedule its
callback.
164.5. Usage
164.5.1. API declarations
Declarations for all sequential API types and functions may be obtained by
including the <lwip/api.h>
header file:
#include <lwip/api.h>
164.5.2. Types
Objects of type struct netconn and struct netbuf are intended to be used as opaque types and the structure contents are intended to be maintained and viewed only by lwIP itself. User applications accessing internal members do so at their own risk, and future API compatibility is not guaranteed, nor is thread synchronization since lwIP is entitled to change structure contents at any time.
164.5.2.1. IP address representation
Depending on the lwIP configuration some API functions take an IP address, which can either be an IPv4 or an IPv6 address.
The IPv4 type struct ip_addr may be accessed as if it has the following structure:
struct ip_addr { u32_t addr; };
The IPv6 type struct ip6_addr may be accessed as if it has the following structure:
struct ip6_addr { u32_t addr[4]; };
Caution | |
---|---|
API users must use the declarations of these structures from the header file
|
To make it easier to work with either IPv4 or IPv6 addresses the type ipX_addr_t is provided. This is a union of the IPv4 and IPv6 address structures, and may be accessed as if it has the following structure:
typedef union { ip_addr_t ip4; ip6_addr_t ip6; } ipX_addr_t;
See Section 164.5.2.1.3, “ipX Helpers” for an
overview of the IP version neutral address support. As with the caveat regarding
the declarations of the specific IPv4 and IPv6 address structures,
the ipX
declarations should be accessed via including
the <lwip/ip_addr.h>
header file.
164.5.2.1.1. IPv4 Addresses
For convenience, predefined struct ip_addr instances are provided
for the special cases of "any" IP address (0.0.0.0), and the global broadcast
address (255.255.255.255). These instances can be accessed with the macro
defines IP_ADDR_ANY
and IP_ADDR_BROADCAST
which return values of type struct ip_addr *.
The addr
field is a 32-bit integral value representing
the IP address in network byte order (not host byte order).
A variety of convenience function-like macros exist for manipulation or evaluation of IP addresses:
-
IP_ADDR_ANY
-
This macro evaluates to an expression of type struct ip_addr *
identifying an IP address structure which can be used to represent the special "any"
IP address
0.0.0.0
. -
IP_ADDR_BROADCAST
-
This macro evaluates to an expression of type struct ip_addr *
identifying an IP address structure which can be used to represent the special
global IP address
255.255.255.255
. -
IN_CLASSA(a)
-
An expression which evaluates to non-zero if
a
(of type u32_t and in host byte order) is a class A internet address. -
IN_CLASSB(a)
-
An expression which evaluates to non-zero if
a
(of type u32_t and in host byte order) is a class B internet address. -
IN_CLASSC(a)
-
An expression which evaluates to non-zero if
a
(of type u32_t and in host byte order) is a class C internet address. -
IN_CLASSD(a)
-
An expression which evaluates to non-zero if
a
(of type u32_t and in host byte order) is a class D internet address. -
IP4_ADDR(ipaddr, a, b, c, d)
Sets ipaddr (of type struct ip_addr *) to the internet address a.b.c.d. For example:
struct ip_addr host; … IP4_ADDR(host, 192, 168, 1, 1);
-
ip_addr_cmp(addr1, addr2)
-
Returns non-zero if the arguments
addr1
andaddr2
, both of type struct ip_addr * are identical. Zero if they differ. -
ip_addr_netcmp(addr1, addr2, mask)
-
Returns non-zero if the arguments
addr1
andaddr2
, both of type struct ip_addr * are on the same network, as indicated by the network maskmask
which is itself also of type struct ip_addr *. Zero if they are on different networks. -
htons(s)
-
Portably converts
s
of type u16_t from host byte order to a u16_t in network byte order. -
ntohs(s)
-
Portably converts
s
of type u16_t from network byte order to a u16_t in host byte order. -
htonl(l)
-
Portably converts
l
of type u32_t from host byte order to a u32_t in network byte order. -
ntohl(l)
-
Portably converts
l
of type u32_t from network byte order to a u32_t in host byte order.
Some further potentially useful macro definitions can be viewed in
<lwip/ip_addr.h>
.
164.5.2.1.2. IPv6 Addresses
The header file <lwip/ip6_addr.h>
(which is included by default
from <lwip/api.h>
) contains
definitions for many IPv6 address convenience function-like macros, as well as
utility function prototypes.
The following is not an exhaustive list, so the reader is recommended to inspect the header file to get a complete overview of the IPv6 address support macros and functions.
-
IP6_ADDR_ANY
-
This macro evaluates to an expression of type struct ip6_addr
* identifying an IP address structure which can be used to
represent the special "any" IPv6 address
::/128
. It actually just returns the address of the exportedip6_addr_any
variable. -
ip6_addr_copy(dest, src)
-
This implements a fast (no
NULL
check) address copy. -
ip6_addr_set(dest, src)
-
Set the
dest
address from the suppliedsrc
. Ifsrc
isNULL
the destination is written with zeroes. -
ip6_addr_set_zero(ip6addr)
-
Sets the
ip6addr
address to all zeroes. -
ip6_addr_set_any(ip6addr)
-
This explicitly sets the
IP6_ADDR_ANY
address value. -
ip6_addr_set_loopback(ip6addr)
-
This sets the destination
ip6addr
parameters to the::1
loopback address. -
ip6_addr_set_hton(dest, src)
-
Copy the
src
address to thedest
address converting from host to network byte order. -
ip6_addr_netcmp(addr1, addr2)
-
An expression which evaluates to non-zero if the
supplied
addr1
andaddr2
parameters are on the same network, by comparing the most-significant 64-bits of the addresses. -
ip6_addr_cmp(addr1, addr2)
-
An expression which evaluates to non-zero if there is an exact match between the
supplied
addr1
andaddr2
parameters. -
ip6_get_subnet_id(ip6addr)
- This returns in host byte order the 16-bit subnet identifier.
-
ip6_addr_isany(ip6addr)
-
An expression which evaluates to non-zero if
ip6addr
matches theIP6_ADDR_ANY
address (all zeroes). -
ip6_addr_isglobal(ip6addr)
-
An expression which evaluates to non-zero if the
supplied
ip6addr
is a valid global address. -
ip6_addr_islinklocal(ip6addr)
-
An expression which evaluates to non-zero if the
ip6addr
parameter is a valid link-local address. -
ip6_addr_issitelocal(ip6addr)
-
An expression which evaluates to non-zero if the
ip6addr
parameter is a valid site-local address. -
ip6_addr_isuniquelocal(ip6addr)
-
An expression which evaluates to non-zero if the
ip6addr
parameter is a valid unique link-local address. -
ip6_addr_ismulticast(ip6addr)
An expression which evaluates to non-zero if the supplied
ip6addr
is a valid multicast address.There are various other function-like macros provided to further decode whether the multicast address is a loopback, link-local, admin-local, global, etc. address. The definitions for these variants can be found by inspecting the
<lwip/ip6_addr.h>
header file.-
ip6_addr_isallnodes_iflocal(ip6addr)
-
An expression which evaluates to non-zero if the
supplied
ip6addr
matches the IPv6ff01::1
loopback "all nodes" address. -
ip6_addr_isallnodes_linklocal(ip6addr)
-
An expression which evaluates to non-zero if the
supplied
ip6addr
matches the IPv6 link-local "all nodes" address. -
ip6_addr_isallrouters_linklocal(ip6addr)
-
An expression which evaluates to non-zero if the
supplied
ip6addr
matches the IPv6 link-local "all routers" address. -
ip6_addr_set_allnodes_linklocal(ip6addr)
-
Sets the given
ip6addr
to theff02::1
link-local "all nodes" multicast address. -
ip6_addr_set_allrouters_linklocal(ip6addr)
-
Sets the given
ip6addr
to theff02::2
link-local "all routers" multicast address. -
ip6_addr_isinvalid(addr_state)
-
An expression which evaluates to non-zero if the
supplied
addr_state
parameter isIP6_ADDR_INVALID
. -
ip6_addr_isvalid(addr_state)
-
An expression which evaluates to non-zero if the
supplied
addr_state
parameter denotes a valid address state, where theIP6_ADDR_VALID
bitmask is set. -
ip6_addr_istentative(addr_state)
-
An expression which evaluates to non-zero if the
supplied
addr_state
parameter has theIP6_ADDR_TENTATIVE
bitmask set. -
ip6_addr_ispreferred(addr_state)
-
An expression which evaluates to non-zero if the
supplied
addr_state
parameter isIP6_ADDR_PREFERRED
. -
ip6_addr_isdeprecated(addr_state)
-
An expression which evaluates to non-zero if the
supplied
addr_state
parameter isIP6_ADDR_DEPRECATED
. -
int ip6addr_aton(const char *cp, ip6_addr_t *addr)
-
Checks whether
cp
is a valid ASCII representation of an IPv6 address, and if valid converts it to the binary IPv6 address destinationaddr
. The function returns 1 on successful conversion, or 0 on failure. -
char *ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen)
Converts the binary IPv6 address
addr
into an ASCII representation written into the suppliedbuf
buffer ofbuflen
bytes.Returns the
buf
parameter on success if the buffer has been updated to hold the ASCII address representation, orNULL
if the buffer was too small.
164.5.2.1.3. ipX Helpers
Instead of directly referencing the IPv4 or IPv6 versions of the utility
routines, applications should ideally use the common ipX_*
variants. These functions, and function-like macros, take as their first
parameter a boolean is_ipv6
value denoting when zero
that the referenced addresses are IPv4 structures, or when non-zero that the
referenced addresses are IPv6 structures. Note: If IPv6 support is not enabled
for lwIP then the ipX_*
implementations default to only
using IPv4 addresses.
-
ipX_addr_copy(is_ipv6, dest, src)
-
This implements a fast (no
NULL
check) address copy. -
ipX_addr_set(is_ipv6, dest, src)
-
Set the
dest
address from the suppliedsrc
. Ifsrc
isNULL
the destination is written with zeroes. -
ipX_addr_set_ipaddr(is_ipv6, dest, src)
-
Sets the
dest
address parameter from the specifiedsrc
. Ifsrc
isNULL
the destination is written with zeroes. -
ipX_addr_set_zero(is_ipv6, ipaddr)
Sets the address to all zeroes. This is normally the
ANY
address.-
ipX_addr_set_any(is_ipv6, ipaddr)
-
This explicitly sets the
ANY
address. -
ipX_addr_set_loopback(is_ipv6, ipaddr)
-
This sets the destination
ipaddr
to the respective loopback interface address. For IPv4 this is127.0.0.1
and::1
for IPv6. -
ipX_addr_set_hton(is_ipv6, dest, src)
-
Copy the
src
address to thedest
address converting from host to network byte order. -
ipX_addr_cmp(is_ipv6, addr1, addr2)
-
An expression which evaluates to non-zero if there is an exact match between the
supplied
addr1
andaddr2
parameters. -
ipX_addr_isany(is_ipv6, ipaddr)
-
An expression which evaluates to non-zero if
ipaddr
is NULL or points at theANY
address value. -
ipX_addr_ismulticast(is_ipv6, ipaddr)
-
An expression which evaluates to non-zero if
ipaddr
references a valid multicast address value. -
ipX_addr_debug_print(is_ipv6, debug, ipaddr)
-
This debugging helper macro will output the raw IPv4 or IPv6 address via the
printf-alike debug support calls if the relevant lwIP debugging option specified
by the
debug
parameter is enabled.
164.5.2.2. Error codes
While the BSD sockets API uses POSIX standard error codes
(ENOMEM
, EINVAL
, etc.)
the lwIP sequential API has its own separate set of error
code definitions.
These error definitions are used by any API function that returns a value of type err_t. The following table indicates possible error code values and their meaning:
Table 164.1. lwIP sequential API error codes
Code | Meaning |
---|---|
ERR_OK
| No error, operation successful. |
ERR_MEM
| Out of memory error. |
ERR_BUF
| Buffer error. |
ERR_ABRT
| Connection aborted. |
ERR_RST
| Connection reset. |
ERR_CLSD
| Connection closed. |
ERR_CONN
| Not connected. |
ERR_VAL
| Illegal value. |
ERR_ARG
| Illegal argument. |
ERR_RTE
| Routing problem. |
ERR_USE
| Address in use. |
ERR_IF
| Low-level network interface error. |
ERR_ISCONN
| Already connected. |
ERR_TIMEOUT
| Timeout. |
ERR_INPROGRESS
| Operation in progress. |
ERR_WOULDBLOCK
| Operation would block. |
164.6. API reference
- netbuf_new() — Allocate a netbuf structure
- netbuf_delete() — Deallocate a netbuf structure
- netbuf_alloc() — Allocate space in a netbuf
- netbuf_free() — Deallocate buffer memory associated with a netbuf
- netbuf_ref() — Associate a data pointer with a netbuf
- netbuf_len() — Obtain the total length of a netbuf
- netbuf_data() — Obtain a pointer to netbuf data
- netbuf_next() — Traverse internal fragments in a netbuf
- netbuf_first() — Reset fragment pointer to start of netbuf
- netbuf_copy() — Copy all netbuf data to memory pointer
- netbuf_copy_partial() — Copy some netbuf data to memory pointer
- netbuf_chain() — Chain two netbufs together
- netbuf_fromaddr() — Obtain the sender's IPv4 address for a netbuf
- netbuf_fromaddr_ip6() — Obtain the sender's IPv6 address for a netbuf
- netbuf_fromport() — Obtain the sender's port number for a netbuf
- netconn_new() — Create a new connection structure
- netconn_new_with_callback() — Create a new connection structure with a callback
- netconn_new_with_proto_and_callback() — Create a new connection structure with a callback for a specific protocol
- netconn_delete() — Deallocate a netconn
- netconn_type() — Obtain the type of netconn
- netconn_peer() — Obtain the remote host IP address/port of a netconn
- netconn_addr() — Obtain the local host IPv4 address/port of a netconn
- netconn_bind() — Set local IP address/port of a netconn
- netconn_bind_ip6() — Set local IPv6 address/port of a netconn
- netconn_connect() — Connect netconn to remote peer
- netconn_connect_ip6() — Connect netconn to remote peer
- netconn_disconnect() — Disconnect UDP connection
- netconn_listen() — Make a listening TCP netconn
- netconn_accept() — Wait for incoming connections
- netconn_recv() — Wait for data
- netconn_recv_tcp_pbuf() — Wait for data
- netconn_recved() — Update receive window
- netconn_write() — Send data on TCP connection
- netconn_send() — Send data on UDP connection
- netconn_close() — Close a connection
- netconn_shutdown() — Shutdown a connection
- netconn_set_noautorecved() — Set the connection no-auto-recved state
- netconn_get_noautorecved() — Get the connection no-auto-recved state
- netconn_err() — Obtain connection error status
2024-03-18 | LWIP Documentation Notices |