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