1*d6eebaa4SHervé Poussineau /**
2*d6eebaa4SHervé Poussineau  * @defgroup lwip lwIP
3*d6eebaa4SHervé Poussineau  *
4*d6eebaa4SHervé Poussineau  * @defgroup infrastructure Infrastructure
5*d6eebaa4SHervé Poussineau  *
6*d6eebaa4SHervé Poussineau  * @defgroup api APIs
7*d6eebaa4SHervé Poussineau  * lwIP provides three Application Program's Interfaces (APIs) for programs
8*d6eebaa4SHervé Poussineau  * to use for communication with the TCP/IP code:
9*d6eebaa4SHervé Poussineau  * - low-level "core" / "callback" or @ref callbackstyle_api.
10*d6eebaa4SHervé Poussineau  * - higher-level @ref sequential_api.
11*d6eebaa4SHervé Poussineau  * - BSD-style @ref socket.
12*d6eebaa4SHervé Poussineau  *
13*d6eebaa4SHervé Poussineau  * The raw TCP/IP interface allows the application program to integrate
14*d6eebaa4SHervé Poussineau  * better with the TCP/IP code. Program execution is event based by
15*d6eebaa4SHervé Poussineau  * having callback functions being called from within the TCP/IP
16*d6eebaa4SHervé Poussineau  * code. The TCP/IP code and the application program both run in the same
17*d6eebaa4SHervé Poussineau  * thread. The sequential API has a much higher overhead and is not very
18*d6eebaa4SHervé Poussineau  * well suited for small systems since it forces a multithreaded paradigm
19*d6eebaa4SHervé Poussineau  * on the application.
20*d6eebaa4SHervé Poussineau  *
21*d6eebaa4SHervé Poussineau  * The raw TCP/IP interface is not only faster in terms of code execution
22*d6eebaa4SHervé Poussineau  * time but is also less memory intensive. The drawback is that program
23*d6eebaa4SHervé Poussineau  * development is somewhat harder and application programs written for
24*d6eebaa4SHervé Poussineau  * the raw TCP/IP interface are more difficult to understand. Still, this
25*d6eebaa4SHervé Poussineau  * is the preferred way of writing applications that should be small in
26*d6eebaa4SHervé Poussineau  * code size and memory usage.
27*d6eebaa4SHervé Poussineau  *
28*d6eebaa4SHervé Poussineau  * All APIs can be used simultaneously by different application
29*d6eebaa4SHervé Poussineau  * programs. In fact, the sequential API is implemented as an application
30*d6eebaa4SHervé Poussineau  * program using the raw TCP/IP interface.
31*d6eebaa4SHervé Poussineau  *
32*d6eebaa4SHervé Poussineau  * Do not confuse the lwIP raw API with raw Ethernet or IP sockets.
33*d6eebaa4SHervé Poussineau  * The former is a way of interfacing the lwIP network stack (including
34*d6eebaa4SHervé Poussineau  * TCP and UDP), the latter refers to processing raw Ethernet or IP data
35*d6eebaa4SHervé Poussineau  * instead of TCP connections or UDP packets.
36*d6eebaa4SHervé Poussineau  *
37*d6eebaa4SHervé Poussineau  * Raw API applications may never block since all packet processing
38*d6eebaa4SHervé Poussineau  * (input and output) as well as timer processing (TCP mainly) is done
39*d6eebaa4SHervé Poussineau  * in a single execution context.
40*d6eebaa4SHervé Poussineau  *
41*d6eebaa4SHervé Poussineau  * @defgroup callbackstyle_api "raw" APIs
42*d6eebaa4SHervé Poussineau  * @ingroup api
43*d6eebaa4SHervé Poussineau  * Non thread-safe APIs, callback style for maximum performance and minimum
44*d6eebaa4SHervé Poussineau  * memory footprint.
45*d6eebaa4SHervé Poussineau  * Program execution is driven by callbacks functions, which are then
46*d6eebaa4SHervé Poussineau  * invoked by the lwIP core when activity related to that application
47*d6eebaa4SHervé Poussineau  * occurs. A particular application may register to be notified via a
48*d6eebaa4SHervé Poussineau  * callback function for events such as incoming data available, outgoing
49*d6eebaa4SHervé Poussineau  * data sent, error notifications, poll timer expiration, connection
50*d6eebaa4SHervé Poussineau  * closed, etc. An application can provide a callback function to perform
51*d6eebaa4SHervé Poussineau  * processing for any or all of these events. Each callback is an ordinary
52*d6eebaa4SHervé Poussineau  * C function that is called from within the TCP/IP code. Every callback
53*d6eebaa4SHervé Poussineau  * function is passed the current TCP or UDP connection state as an
54*d6eebaa4SHervé Poussineau  * argument. Also, in order to be able to keep program specific state,
55*d6eebaa4SHervé Poussineau  * the callback functions are called with a program specified argument
56*d6eebaa4SHervé Poussineau  * that is independent of the TCP/IP state.
57*d6eebaa4SHervé Poussineau  * The raw API (sometimes called native API) is an event-driven API designed
58*d6eebaa4SHervé Poussineau  * to be used without an operating system that implements zero-copy send and
59*d6eebaa4SHervé Poussineau  * receive. This API is also used by the core stack for interaction between
60*d6eebaa4SHervé Poussineau  * the various protocols. It is the only API available when running lwIP
61*d6eebaa4SHervé Poussineau  * without an operating system.
62*d6eebaa4SHervé Poussineau  *
63*d6eebaa4SHervé Poussineau  * @defgroup sequential_api Sequential-style APIs
64*d6eebaa4SHervé Poussineau  * @ingroup api
65*d6eebaa4SHervé Poussineau  * Sequential-style APIs, blocking functions. More overhead, but can be called
66*d6eebaa4SHervé Poussineau  * from any thread except TCPIP thread.
67*d6eebaa4SHervé Poussineau  * The sequential API provides a way for ordinary, sequential, programs
68*d6eebaa4SHervé Poussineau  * to use the lwIP stack. It is quite similar to the BSD socket API. The
69*d6eebaa4SHervé Poussineau  * model of execution is based on the blocking open-read-write-close
70*d6eebaa4SHervé Poussineau  * paradigm. Since the TCP/IP stack is event based by nature, the TCP/IP
71*d6eebaa4SHervé Poussineau  * code and the application program must reside in different execution
72*d6eebaa4SHervé Poussineau  * contexts (threads).
73*d6eebaa4SHervé Poussineau  *
74*d6eebaa4SHervé Poussineau  * @defgroup socket Socket API
75*d6eebaa4SHervé Poussineau  * @ingroup api
76*d6eebaa4SHervé Poussineau  * BSD-style socket API.<br>
77*d6eebaa4SHervé Poussineau  * Thread-safe, to be called from non-TCPIP threads only.<br>
78*d6eebaa4SHervé Poussineau  * Can be activated by defining @ref LWIP_SOCKET to 1.<br>
79*d6eebaa4SHervé Poussineau  * Header is in posix/sys/socket.h<br>
80*d6eebaa4SHervé Poussineau  * The socket API is a compatibility API for existing applications,
81*d6eebaa4SHervé Poussineau  * currently it is built on top of the sequential API. It is meant to
82*d6eebaa4SHervé Poussineau  * provide all functions needed to run socket API applications running
83*d6eebaa4SHervé Poussineau  * on other platforms (e.g. unix / windows etc.). However, due to limitations
84*d6eebaa4SHervé Poussineau  * in the specification of this API, there might be incompatibilities
85*d6eebaa4SHervé Poussineau  * that require small modifications of existing programs.
86*d6eebaa4SHervé Poussineau  *
87*d6eebaa4SHervé Poussineau  * @defgroup netifs NETIFs
88*d6eebaa4SHervé Poussineau  *
89*d6eebaa4SHervé Poussineau  * @defgroup apps Applications
90*d6eebaa4SHervé Poussineau  */
91*d6eebaa4SHervé Poussineau 
92*d6eebaa4SHervé Poussineau /**
93*d6eebaa4SHervé Poussineau  * @mainpage Overview
94*d6eebaa4SHervé Poussineau  * @verbinclude "README"
95*d6eebaa4SHervé Poussineau  */
96*d6eebaa4SHervé Poussineau 
97*d6eebaa4SHervé Poussineau /**
98*d6eebaa4SHervé Poussineau  * @page upgrading Upgrading
99*d6eebaa4SHervé Poussineau  * @verbinclude "UPGRADING"
100*d6eebaa4SHervé Poussineau  */
101*d6eebaa4SHervé Poussineau 
102*d6eebaa4SHervé Poussineau /**
103*d6eebaa4SHervé Poussineau  * @page changelog Changelog
104*d6eebaa4SHervé Poussineau  *
105*d6eebaa4SHervé Poussineau  * 2.1.0
106*d6eebaa4SHervé Poussineau  * -----
107*d6eebaa4SHervé Poussineau  * * Support TLS via new @ref altcp_api connection API (https, smtps, mqtt over TLS)
108*d6eebaa4SHervé Poussineau  * * Switch to cmake as the main build system (Makefile file lists are still
109*d6eebaa4SHervé Poussineau  *   maintained for now)
110*d6eebaa4SHervé Poussineau  * * Improve IPv6 support: support address scopes, support stateless DHCPv6, bugfixes
111*d6eebaa4SHervé Poussineau  * * Add debug helper asserts to ensure threading/locking requirements are met
112*d6eebaa4SHervé Poussineau  * * Add sys_mbox_trypost_fromisr() and tcpip_callbackmsg_trycallback_fromisr()
113*d6eebaa4SHervé Poussineau  *   (for FreeRTOS, mainly)
114*d6eebaa4SHervé Poussineau  * * socket API: support poll(), sendmsg() and recvmsg(); fix problems on close
115*d6eebaa4SHervé Poussineau  *
116*d6eebaa4SHervé Poussineau  * Detailed Changelog
117*d6eebaa4SHervé Poussineau  * ------------------
118*d6eebaa4SHervé Poussineau  * @verbinclude "CHANGELOG"
119*d6eebaa4SHervé Poussineau  */
120*d6eebaa4SHervé Poussineau 
121*d6eebaa4SHervé Poussineau /**
122*d6eebaa4SHervé Poussineau  * @page contrib How to contribute to lwIP
123*d6eebaa4SHervé Poussineau  * @verbinclude "contrib.txt"
124*d6eebaa4SHervé Poussineau  */
125*d6eebaa4SHervé Poussineau 
126*d6eebaa4SHervé Poussineau /**
127*d6eebaa4SHervé Poussineau  * @page cmake CMake build system
128*d6eebaa4SHervé Poussineau  * @verbinclude "BUILDING"
129*d6eebaa4SHervé Poussineau  */
130*d6eebaa4SHervé Poussineau 
131*d6eebaa4SHervé Poussineau /**
132*d6eebaa4SHervé Poussineau  * @page pitfalls Common pitfalls
133*d6eebaa4SHervé Poussineau  *
134*d6eebaa4SHervé Poussineau  * Multiple Execution Contexts in lwIP code
135*d6eebaa4SHervé Poussineau  * ========================================
136*d6eebaa4SHervé Poussineau  *
137*d6eebaa4SHervé Poussineau  * The most common source of lwIP problems is to have multiple execution contexts
138*d6eebaa4SHervé Poussineau  * inside the lwIP code.
139*d6eebaa4SHervé Poussineau  *
140*d6eebaa4SHervé Poussineau  * lwIP can be used in two basic modes: @ref lwip_nosys (no OS/RTOS
141*d6eebaa4SHervé Poussineau  * running on target system) or @ref lwip_os (there is an OS running
142*d6eebaa4SHervé Poussineau  * on the target system).
143*d6eebaa4SHervé Poussineau  *
144*d6eebaa4SHervé Poussineau  * See also: @ref multithreading (especially the part about @ref LWIP_ASSERT_CORE_LOCKED()!)
145*d6eebaa4SHervé Poussineau  *
146*d6eebaa4SHervé Poussineau  * Mainloop Mode
147*d6eebaa4SHervé Poussineau  * -------------
148*d6eebaa4SHervé Poussineau  * In mainloop mode, only @ref callbackstyle_api can be used.
149*d6eebaa4SHervé Poussineau  * The user has two possibilities to ensure there is only one
150*d6eebaa4SHervé Poussineau  * execution context at a time in lwIP:
151*d6eebaa4SHervé Poussineau  *
152*d6eebaa4SHervé Poussineau  * 1) Deliver RX ethernet packets directly in interrupt context to lwIP
153*d6eebaa4SHervé Poussineau  *    by calling netif->input directly in interrupt. This implies all lwIP
154*d6eebaa4SHervé Poussineau  *    callback functions are called in IRQ context, which may cause further
155*d6eebaa4SHervé Poussineau  *    problems in application code: IRQ is blocked for a long time, multiple
156*d6eebaa4SHervé Poussineau  *    execution contexts in application code etc. When the application wants
157*d6eebaa4SHervé Poussineau  *    to call lwIP, it only needs to disable interrupts during the call.
158*d6eebaa4SHervé Poussineau  *    If timers are involved, even more locking code is needed to lock out
159*d6eebaa4SHervé Poussineau  *    timer IRQ and ethernet IRQ from each other, assuming these may be nested.
160*d6eebaa4SHervé Poussineau  *
161*d6eebaa4SHervé Poussineau  * 2) Run lwIP in a mainloop. There is example code here: @ref lwip_nosys.
162*d6eebaa4SHervé Poussineau  *    lwIP is _ONLY_ called from mainloop callstacks here. The ethernet IRQ
163*d6eebaa4SHervé Poussineau  *    has to put received telegrams into a queue which is polled in the
164*d6eebaa4SHervé Poussineau  *    mainloop. Ensure lwIP is _NEVER_ called from an interrupt, e.g.
165*d6eebaa4SHervé Poussineau  *    some SPI IRQ wants to forward data to udp_send() or tcp_write()!
166*d6eebaa4SHervé Poussineau  *
167*d6eebaa4SHervé Poussineau  * OS Mode
168*d6eebaa4SHervé Poussineau  * -------
169*d6eebaa4SHervé Poussineau  * In OS mode, @ref callbackstyle_api AND @ref sequential_api can be used.
170*d6eebaa4SHervé Poussineau  * @ref sequential_api are designed to be called from threads other than
171*d6eebaa4SHervé Poussineau  * the TCPIP thread, so there is nothing to consider here.
172*d6eebaa4SHervé Poussineau  * But @ref callbackstyle_api functions must _ONLY_ be called from
173*d6eebaa4SHervé Poussineau  * TCPIP thread. It is a common error to call these from other threads
174*d6eebaa4SHervé Poussineau  * or from IRQ contexts. ​Ethernet RX needs to deliver incoming packets
175*d6eebaa4SHervé Poussineau  * in the correct way by sending a message to TCPIP thread, this is
176*d6eebaa4SHervé Poussineau  * implemented in tcpip_input().​​
177*d6eebaa4SHervé Poussineau  * Again, ensure lwIP is _NEVER_ called from an interrupt, e.g.
178*d6eebaa4SHervé Poussineau  * some SPI IRQ wants to forward data to udp_send() or tcp_write()!
179*d6eebaa4SHervé Poussineau  *
180*d6eebaa4SHervé Poussineau  * 1) tcpip_callback() can be used get called back from TCPIP thread,
181*d6eebaa4SHervé Poussineau  *    it is safe to call any @ref callbackstyle_api from there.
182*d6eebaa4SHervé Poussineau  *
183*d6eebaa4SHervé Poussineau  * 2) Use @ref LWIP_TCPIP_CORE_LOCKING. All @ref callbackstyle_api
184*d6eebaa4SHervé Poussineau  *    functions can be called when lwIP core lock is acquired, see
185*d6eebaa4SHervé Poussineau  *    @ref LOCK_TCPIP_CORE() and @ref UNLOCK_TCPIP_CORE().
186*d6eebaa4SHervé Poussineau  *    These macros cannot be used in an interrupt context!
187*d6eebaa4SHervé Poussineau  *    Note the OS must correctly handle priority inversion for this.
188*d6eebaa4SHervé Poussineau  *
189*d6eebaa4SHervé Poussineau  * Cache / DMA issues
190*d6eebaa4SHervé Poussineau  * ==================
191*d6eebaa4SHervé Poussineau  *
192*d6eebaa4SHervé Poussineau  * DMA-capable ethernet hardware and zero-copy RX
193*d6eebaa4SHervé Poussineau  * ----------------------------------------------
194*d6eebaa4SHervé Poussineau  *
195*d6eebaa4SHervé Poussineau  * lwIP changes the content of RECEIVED pbufs in the TCP code path.
196*d6eebaa4SHervé Poussineau  * This implies one or more cacheline(s) of the RX pbuf become dirty
197*d6eebaa4SHervé Poussineau  * and need to be flushed before the memory is handed over to the
198*d6eebaa4SHervé Poussineau  * DMA ethernet hardware for the next telegram to be received.
199*d6eebaa4SHervé Poussineau  * See http://lists.nongnu.org/archive/html/lwip-devel/2017-12/msg00070.html
200*d6eebaa4SHervé Poussineau  * for a more detailed explanation.
201*d6eebaa4SHervé Poussineau  * Also keep in mind the user application may also write into pbufs,
202*d6eebaa4SHervé Poussineau  * so it is generally a bug not to flush the data cache before handing
203*d6eebaa4SHervé Poussineau  * a buffer to DMA hardware.
204*d6eebaa4SHervé Poussineau  *
205*d6eebaa4SHervé Poussineau  * DMA-capable ethernet hardware and cacheline alignment
206*d6eebaa4SHervé Poussineau  * -----------------------------------------------------
207*d6eebaa4SHervé Poussineau  * Nice description about DMA capable hardware and buffer handling:
208*d6eebaa4SHervé Poussineau  * http://www.pebblebay.com/a-guide-to-using-direct-memory-access-in-embedded-systems-part-two/
209*d6eebaa4SHervé Poussineau  * Read especially sections "Cache coherency" and "Buffer alignment".
210*d6eebaa4SHervé Poussineau  */
211*d6eebaa4SHervé Poussineau 
212*d6eebaa4SHervé Poussineau /**
213*d6eebaa4SHervé Poussineau  * @page mem_err Debugging memory pool sizes
214*d6eebaa4SHervé Poussineau  * If you have issues with lwIP and you are using memory pools, check that your pools
215*d6eebaa4SHervé Poussineau  * are correctly sized.<br>
216*d6eebaa4SHervé Poussineau  * To debug pool sizes, \#define LWIP_STATS and MEMP_STATS to 1. Check the global variable
217*d6eebaa4SHervé Poussineau  * lwip_stats.memp[] using a debugger. If the "err" member of a pool is > 0, the pool
218*d6eebaa4SHervé Poussineau  * may be too small for your application and you need to increase its size.
219*d6eebaa4SHervé Poussineau  */
220*d6eebaa4SHervé Poussineau 
221*d6eebaa4SHervé Poussineau /**
222*d6eebaa4SHervé Poussineau  * @page bugs Reporting bugs
223*d6eebaa4SHervé Poussineau  * Please report bugs in the lwIP bug tracker at savannah.<br>
224*d6eebaa4SHervé Poussineau  * BEFORE submitting, please check if the bug has already been reported!<br>
225*d6eebaa4SHervé Poussineau  * https://savannah.nongnu.org/bugs/?group=lwip
226*d6eebaa4SHervé Poussineau  */
227*d6eebaa4SHervé Poussineau 
228*d6eebaa4SHervé Poussineau /**
229*d6eebaa4SHervé Poussineau  * @page zerocopyrx Zero-copy RX
230*d6eebaa4SHervé Poussineau  * The following code is an example for zero-copy RX ethernet driver:
231*d6eebaa4SHervé Poussineau  * @include ZeroCopyRx.c
232*d6eebaa4SHervé Poussineau  */
233*d6eebaa4SHervé Poussineau 
234*d6eebaa4SHervé Poussineau /**
235*d6eebaa4SHervé Poussineau  * @defgroup lwip_nosys Mainloop mode ("NO_SYS")
236*d6eebaa4SHervé Poussineau  * @ingroup lwip
237*d6eebaa4SHervé Poussineau  * Use this mode if you do not run an OS on your system. \#define NO_SYS to 1.
238*d6eebaa4SHervé Poussineau  * Feed incoming packets to netif->input(pbuf, netif) function from mainloop,
239*d6eebaa4SHervé Poussineau  * *not* *from* *interrupt* *context*. You can allocate a @ref pbuf in interrupt
240*d6eebaa4SHervé Poussineau  * context and put them into a queue which is processed from mainloop.<br>
241*d6eebaa4SHervé Poussineau  * Call sys_check_timeouts() periodically in the mainloop.<br>
242*d6eebaa4SHervé Poussineau  * Porting: implement all functions in @ref sys_time, @ref sys_prot and
243*d6eebaa4SHervé Poussineau  * @ref compiler_abstraction.<br>
244*d6eebaa4SHervé Poussineau  * You can only use @ref callbackstyle_api in this mode.<br>
245*d6eebaa4SHervé Poussineau  * Sample code:
246*d6eebaa4SHervé Poussineau  * @include NO_SYS_SampleCode.c
247*d6eebaa4SHervé Poussineau  */
248*d6eebaa4SHervé Poussineau 
249*d6eebaa4SHervé Poussineau /**
250*d6eebaa4SHervé Poussineau  * @defgroup lwip_os OS mode (TCPIP thread)
251*d6eebaa4SHervé Poussineau  * @ingroup lwip
252*d6eebaa4SHervé Poussineau  * Use this mode if you run an OS on your system. It is recommended to
253*d6eebaa4SHervé Poussineau  * use an RTOS that correctly handles priority inversion and
254*d6eebaa4SHervé Poussineau  * to use @ref LWIP_TCPIP_CORE_LOCKING.<br>
255*d6eebaa4SHervé Poussineau  * Porting: implement all functions in @ref sys_layer.<br>
256*d6eebaa4SHervé Poussineau  * You can use @ref callbackstyle_api together with @ref tcpip_callback,
257*d6eebaa4SHervé Poussineau  * and all @ref sequential_api.
258*d6eebaa4SHervé Poussineau  */
259*d6eebaa4SHervé Poussineau 
260*d6eebaa4SHervé Poussineau /**
261*d6eebaa4SHervé Poussineau  * @page sys_init System initialization
262*d6eebaa4SHervé Poussineau A truly complete and generic sequence for initializing the lwIP stack
263*d6eebaa4SHervé Poussineau cannot be given because it depends on additional initializations for
264*d6eebaa4SHervé Poussineau your runtime environment (e.g. timers).
265*d6eebaa4SHervé Poussineau 
266*d6eebaa4SHervé Poussineau We can give you some idea on how to proceed when using the raw API.
267*d6eebaa4SHervé Poussineau We assume a configuration using a single Ethernet netif and the
268*d6eebaa4SHervé Poussineau UDP and TCP transport layers, IPv4 and the DHCP client.
269*d6eebaa4SHervé Poussineau 
270*d6eebaa4SHervé Poussineau Call these functions in the order of appearance:
271*d6eebaa4SHervé Poussineau 
272*d6eebaa4SHervé Poussineau - lwip_init(): Initialize the lwIP stack and all of its subsystems.
273*d6eebaa4SHervé Poussineau 
274*d6eebaa4SHervé Poussineau - netif_add(struct netif *netif, ...):
275*d6eebaa4SHervé Poussineau   Adds your network interface to the netif_list. Allocate a struct
276*d6eebaa4SHervé Poussineau   netif and pass a pointer to this structure as the first argument.
277*d6eebaa4SHervé Poussineau   Give pointers to cleared ip_addr structures when using DHCP,
278*d6eebaa4SHervé Poussineau   or fill them with sane numbers otherwise. The state pointer may be NULL.
279*d6eebaa4SHervé Poussineau 
280*d6eebaa4SHervé Poussineau   The init function pointer must point to a initialization function for
281*d6eebaa4SHervé Poussineau   your Ethernet netif interface. The following code illustrates its use.
282*d6eebaa4SHervé Poussineau 
283*d6eebaa4SHervé Poussineau @code{.c}
284*d6eebaa4SHervé Poussineau   err_t netif_if_init(struct netif *netif)
285*d6eebaa4SHervé Poussineau   {
286*d6eebaa4SHervé Poussineau     u8_t i;
287*d6eebaa4SHervé Poussineau 
288*d6eebaa4SHervé Poussineau     for (i = 0; i < ETHARP_HWADDR_LEN; i++) {
289*d6eebaa4SHervé Poussineau       netif->hwaddr[i] = some_eth_addr[i];
290*d6eebaa4SHervé Poussineau     }
291*d6eebaa4SHervé Poussineau     init_my_eth_device();
292*d6eebaa4SHervé Poussineau     return ERR_OK;
293*d6eebaa4SHervé Poussineau   }
294*d6eebaa4SHervé Poussineau @endcode
295*d6eebaa4SHervé Poussineau 
296*d6eebaa4SHervé Poussineau   For Ethernet drivers, the input function pointer must point to the lwIP
297*d6eebaa4SHervé Poussineau   function ethernet_input() declared in "netif/etharp.h". Other drivers
298*d6eebaa4SHervé Poussineau   must use ip_input() declared in "lwip/ip.h".
299*d6eebaa4SHervé Poussineau 
300*d6eebaa4SHervé Poussineau - netif_set_default(struct netif *netif)
301*d6eebaa4SHervé Poussineau   Registers the default network interface.
302*d6eebaa4SHervé Poussineau 
303*d6eebaa4SHervé Poussineau - netif_set_link_up(struct netif *netif)
304*d6eebaa4SHervé Poussineau   This is the hardware link state; e.g. whether cable is plugged for wired
305*d6eebaa4SHervé Poussineau   Ethernet interface. This function must be called even if you don't know
306*d6eebaa4SHervé Poussineau   the current state. Having link up and link down events is optional but
307*d6eebaa4SHervé Poussineau   DHCP and IPv6 discover benefit well from those events.
308*d6eebaa4SHervé Poussineau 
309*d6eebaa4SHervé Poussineau - netif_set_up(struct netif *netif)
310*d6eebaa4SHervé Poussineau   This is the administrative (= software) state of the netif, when the
311*d6eebaa4SHervé Poussineau   netif is fully configured this function must be called.
312*d6eebaa4SHervé Poussineau 
313*d6eebaa4SHervé Poussineau - dhcp_start(struct netif *netif)
314*d6eebaa4SHervé Poussineau   Creates a new DHCP client for this interface on the first call.
315*d6eebaa4SHervé Poussineau   You can peek in the netif->dhcp struct for the actual DHCP status.
316*d6eebaa4SHervé Poussineau 
317*d6eebaa4SHervé Poussineau - sys_check_timeouts()
318*d6eebaa4SHervé Poussineau   When the system is running, you have to periodically call
319*d6eebaa4SHervé Poussineau   sys_check_timeouts() which will handle all timers for all protocols in
320*d6eebaa4SHervé Poussineau   the stack; add this to your main loop or equivalent.
321*d6eebaa4SHervé Poussineau  */
322*d6eebaa4SHervé Poussineau 
323*d6eebaa4SHervé Poussineau /**
324*d6eebaa4SHervé Poussineau  * @page multithreading Multithreading
325*d6eebaa4SHervé Poussineau  * lwIP started targeting single-threaded environments. When adding multi-
326*d6eebaa4SHervé Poussineau  * threading support, instead of making the core thread-safe, another
327*d6eebaa4SHervé Poussineau  * approach was chosen: there is one main thread running the lwIP core
328*d6eebaa4SHervé Poussineau  * (also known as the "tcpip_thread"). When running in a multithreaded
329*d6eebaa4SHervé Poussineau  * environment, raw API functions MUST only be called from the core thread
330*d6eebaa4SHervé Poussineau  * since raw API functions are not protected from concurrent access (aside
331*d6eebaa4SHervé Poussineau  * from pbuf- and memory management functions). Application threads using
332*d6eebaa4SHervé Poussineau  * the sequential- or socket API communicate with this main thread through
333*d6eebaa4SHervé Poussineau  * message passing.
334*d6eebaa4SHervé Poussineau  *
335*d6eebaa4SHervé Poussineau  * As such, the list of functions that may be called from
336*d6eebaa4SHervé Poussineau  * other threads or an ISR is very limited! Only functions
337*d6eebaa4SHervé Poussineau  * from these API header files are thread-safe:
338*d6eebaa4SHervé Poussineau  * - api.h
339*d6eebaa4SHervé Poussineau  * - netbuf.h
340*d6eebaa4SHervé Poussineau  * - netdb.h
341*d6eebaa4SHervé Poussineau  * - netifapi.h
342*d6eebaa4SHervé Poussineau  * - pppapi.h
343*d6eebaa4SHervé Poussineau  * - sockets.h
344*d6eebaa4SHervé Poussineau  * - sys.h
345*d6eebaa4SHervé Poussineau  *
346*d6eebaa4SHervé Poussineau  * Additionally, memory (de-)allocation functions may be
347*d6eebaa4SHervé Poussineau  * called from multiple threads (not ISR!) with NO_SYS=0
348*d6eebaa4SHervé Poussineau  * since they are protected by @ref SYS_LIGHTWEIGHT_PROT and/or
349*d6eebaa4SHervé Poussineau  * semaphores.
350*d6eebaa4SHervé Poussineau  *
351*d6eebaa4SHervé Poussineau  * Netconn or Socket API functions are thread safe against the
352*d6eebaa4SHervé Poussineau  * core thread but they are not reentrant at the control block
353*d6eebaa4SHervé Poussineau  * granularity level. That is, a UDP or TCP control block must
354*d6eebaa4SHervé Poussineau  * not be shared among multiple threads without proper locking.
355*d6eebaa4SHervé Poussineau  *
356*d6eebaa4SHervé Poussineau  * If @ref SYS_LIGHTWEIGHT_PROT is set to 1 and
357*d6eebaa4SHervé Poussineau  * @ref LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT is set to 1,
358*d6eebaa4SHervé Poussineau  * pbuf_free() may also be called from another thread or
359*d6eebaa4SHervé Poussineau  * an ISR (since only then, mem_free - for PBUF_RAM - may
360*d6eebaa4SHervé Poussineau  * be called from an ISR: otherwise, the HEAP is only
361*d6eebaa4SHervé Poussineau  * protected by semaphores).
362*d6eebaa4SHervé Poussineau  *
363*d6eebaa4SHervé Poussineau  * How to get threading done right
364*d6eebaa4SHervé Poussineau  * -------------------------------
365*d6eebaa4SHervé Poussineau  *
366*d6eebaa4SHervé Poussineau  * It is strongly recommended to implement the LWIP_ASSERT_CORE_LOCKED()
367*d6eebaa4SHervé Poussineau  * macro in an application that uses multithreading. lwIP code has
368*d6eebaa4SHervé Poussineau  * several places where a check for a correct thread context is
369*d6eebaa4SHervé Poussineau  * implemented which greatly helps the user to get threading done right.
370*d6eebaa4SHervé Poussineau  * See the example sys_arch.c files in unix and Win32 port
371*d6eebaa4SHervé Poussineau  * in the lwIP/contrib subdirectory.
372*d6eebaa4SHervé Poussineau  *
373*d6eebaa4SHervé Poussineau  * In short: Copy the functions sys_mark_tcpip_thread() and
374*d6eebaa4SHervé Poussineau  * sys_check_core_locking() to your port and modify them to work with your OS.
375*d6eebaa4SHervé Poussineau  * Then let @ref LWIP_ASSERT_CORE_LOCKED() and @ref LWIP_MARK_TCPIP_THREAD()
376*d6eebaa4SHervé Poussineau  * point to these functions.
377*d6eebaa4SHervé Poussineau  *
378*d6eebaa4SHervé Poussineau  * If you use @ref LWIP_TCPIP_CORE_LOCKING, you also need to copy and adapt
379*d6eebaa4SHervé Poussineau  * the functions sys_lock_tcpip_core() and sys_unlock_tcpip_core().
380*d6eebaa4SHervé Poussineau  * Let @ref LOCK_TCPIP_CORE() and @ref UNLOCK_TCPIP_CORE() point
381*d6eebaa4SHervé Poussineau  * to these functions.
382*d6eebaa4SHervé Poussineau  */
383*d6eebaa4SHervé Poussineau 
384*d6eebaa4SHervé Poussineau /**
385*d6eebaa4SHervé Poussineau  * @page optimization Optimization hints
386*d6eebaa4SHervé Poussineau The first thing you want to optimize is the lwip_standard_checksum()
387*d6eebaa4SHervé Poussineau routine from src/core/inet.c. You can override this standard
388*d6eebaa4SHervé Poussineau function with the \#define LWIP_CHKSUM your_checksum_routine().
389*d6eebaa4SHervé Poussineau 
390*d6eebaa4SHervé Poussineau There are C examples given in inet.c or you might want to
391*d6eebaa4SHervé Poussineau craft an assembly function for this. RFC1071 is a good
392*d6eebaa4SHervé Poussineau introduction to this subject.
393*d6eebaa4SHervé Poussineau 
394*d6eebaa4SHervé Poussineau Other significant improvements can be made by supplying
395*d6eebaa4SHervé Poussineau assembly or inline replacements for htons() and htonl()
396*d6eebaa4SHervé Poussineau if you're using a little-endian architecture.
397*d6eebaa4SHervé Poussineau \#define lwip_htons(x) your_htons()
398*d6eebaa4SHervé Poussineau \#define lwip_htonl(x) your_htonl()
399*d6eebaa4SHervé Poussineau If you \#define them to htons() and htonl(), you should
400*d6eebaa4SHervé Poussineau \#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS to prevent lwIP from
401*d6eebaa4SHervé Poussineau defining htonx / ntohx compatibility macros.
402*d6eebaa4SHervé Poussineau 
403*d6eebaa4SHervé Poussineau Check your network interface driver if it reads at
404*d6eebaa4SHervé Poussineau a higher speed than the maximum wire-speed. If the
405*d6eebaa4SHervé Poussineau hardware isn't serviced frequently and fast enough
406*d6eebaa4SHervé Poussineau buffer overflows are likely to occur.
407*d6eebaa4SHervé Poussineau 
408*d6eebaa4SHervé Poussineau E.g. when using the cs8900 driver, call cs8900if_service(ethif)
409*d6eebaa4SHervé Poussineau as frequently as possible. When using an RTOS let the cs8900 interrupt
410*d6eebaa4SHervé Poussineau wake a high priority task that services your driver using a binary
411*d6eebaa4SHervé Poussineau semaphore or event flag. Some drivers might allow additional tuning
412*d6eebaa4SHervé Poussineau to match your application and network.
413*d6eebaa4SHervé Poussineau 
414*d6eebaa4SHervé Poussineau For a production release it is recommended to set LWIP_STATS to 0.
415*d6eebaa4SHervé Poussineau Note that speed performance isn't influenced much by simply setting
416*d6eebaa4SHervé Poussineau high values to the memory options.
417*d6eebaa4SHervé Poussineau  */
418