mbed-os

Fork of mbed-os by erkin yucel

Committer:
elessair
Date:
Sun Oct 23 15:10:02 2016 +0000
Revision:
0:f269e3021894
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
elessair 0:f269e3021894 1 Raw TCP/IP interface for lwIP
elessair 0:f269e3021894 2
elessair 0:f269e3021894 3 Authors: Adam Dunkels, Leon Woestenberg, Christiaan Simons
elessair 0:f269e3021894 4
elessair 0:f269e3021894 5 lwIP provides three Application Program's Interfaces (APIs) for programs
elessair 0:f269e3021894 6 to use for communication with the TCP/IP code:
elessair 0:f269e3021894 7 * low-level "core" / "callback" or "raw" API.
elessair 0:f269e3021894 8 * higher-level "sequential" API.
elessair 0:f269e3021894 9 * BSD-style socket API.
elessair 0:f269e3021894 10
elessair 0:f269e3021894 11 The raw API (sometimes called native API) is an event-driven API designed
elessair 0:f269e3021894 12 to be used without an operating system that implements zero-copy send and
elessair 0:f269e3021894 13 receive. This API is also used by the core stack for interaction between
elessair 0:f269e3021894 14 the various protocols. It is the only API available when running lwIP
elessair 0:f269e3021894 15 without an operating system.
elessair 0:f269e3021894 16
elessair 0:f269e3021894 17 The sequential API provides a way for ordinary, sequential, programs
elessair 0:f269e3021894 18 to use the lwIP stack. It is quite similar to the BSD socket API. The
elessair 0:f269e3021894 19 model of execution is based on the blocking open-read-write-close
elessair 0:f269e3021894 20 paradigm. Since the TCP/IP stack is event based by nature, the TCP/IP
elessair 0:f269e3021894 21 code and the application program must reside in different execution
elessair 0:f269e3021894 22 contexts (threads).
elessair 0:f269e3021894 23
elessair 0:f269e3021894 24 The socket API is a compatibility API for existing applications,
elessair 0:f269e3021894 25 currently it is built on top of the sequential API. It is meant to
elessair 0:f269e3021894 26 provide all functions needed to run socket API applications running
elessair 0:f269e3021894 27 on other platforms (e.g. unix / windows etc.). However, due to limitations
elessair 0:f269e3021894 28 in the specification of this API, there might be incompatibilities
elessair 0:f269e3021894 29 that require small modifications of existing programs.
elessair 0:f269e3021894 30
elessair 0:f269e3021894 31 ** Multithreading
elessair 0:f269e3021894 32
elessair 0:f269e3021894 33 lwIP started targeting single-threaded environments. When adding multi-
elessair 0:f269e3021894 34 threading support, instead of making the core thread-safe, another
elessair 0:f269e3021894 35 approach was chosen: there is one main thread running the lwIP core
elessair 0:f269e3021894 36 (also known as the "tcpip_thread"). When running in a multithreaded
elessair 0:f269e3021894 37 environment, raw API functions MUST only be called from the core thread
elessair 0:f269e3021894 38 since raw API functions are not protected from concurrent access (aside
elessair 0:f269e3021894 39 from pbuf- and memory management functions). Application threads using
elessair 0:f269e3021894 40 the sequential- or socket API communicate with this main thread through
elessair 0:f269e3021894 41 message passing.
elessair 0:f269e3021894 42
elessair 0:f269e3021894 43 As such, the list of functions that may be called from
elessair 0:f269e3021894 44 other threads or an ISR is very limited! Only functions
elessair 0:f269e3021894 45 from these API header files are thread-safe:
elessair 0:f269e3021894 46 - api.h
elessair 0:f269e3021894 47 - netbuf.h
elessair 0:f269e3021894 48 - netdb.h
elessair 0:f269e3021894 49 - netifapi.h
elessair 0:f269e3021894 50 - pppapi.h
elessair 0:f269e3021894 51 - sockets.h
elessair 0:f269e3021894 52 - sys.h
elessair 0:f269e3021894 53
elessair 0:f269e3021894 54 Additionaly, memory (de-)allocation functions may be
elessair 0:f269e3021894 55 called from multiple threads (not ISR!) with NO_SYS=0
elessair 0:f269e3021894 56 since they are protected by SYS_LIGHTWEIGHT_PROT and/or
elessair 0:f269e3021894 57 semaphores.
elessair 0:f269e3021894 58
elessair 0:f269e3021894 59 Netconn or Socket API functions are thread safe against the
elessair 0:f269e3021894 60 core thread but they are not reentrant at the control block
elessair 0:f269e3021894 61 granularity level. That is, a UDP or TCP control block must
elessair 0:f269e3021894 62 not be shared among multiple threads without proper locking.
elessair 0:f269e3021894 63
elessair 0:f269e3021894 64 If SYS_LIGHTWEIGHT_PROT is set to 1 and
elessair 0:f269e3021894 65 LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT is set to 1,
elessair 0:f269e3021894 66 pbuf_free() may also be called from another thread or
elessair 0:f269e3021894 67 an ISR (since only then, mem_free - for PBUF_RAM - may
elessair 0:f269e3021894 68 be called from an ISR: otherwise, the HEAP is only
elessair 0:f269e3021894 69 protected by semaphores).
elessair 0:f269e3021894 70
elessair 0:f269e3021894 71
elessair 0:f269e3021894 72 ** The remainder of this document discusses the "raw" API. **
elessair 0:f269e3021894 73
elessair 0:f269e3021894 74 The raw TCP/IP interface allows the application program to integrate
elessair 0:f269e3021894 75 better with the TCP/IP code. Program execution is event based by
elessair 0:f269e3021894 76 having callback functions being called from within the TCP/IP
elessair 0:f269e3021894 77 code. The TCP/IP code and the application program both run in the same
elessair 0:f269e3021894 78 thread. The sequential API has a much higher overhead and is not very
elessair 0:f269e3021894 79 well suited for small systems since it forces a multithreaded paradigm
elessair 0:f269e3021894 80 on the application.
elessair 0:f269e3021894 81
elessair 0:f269e3021894 82 The raw TCP/IP interface is not only faster in terms of code execution
elessair 0:f269e3021894 83 time but is also less memory intensive. The drawback is that program
elessair 0:f269e3021894 84 development is somewhat harder and application programs written for
elessair 0:f269e3021894 85 the raw TCP/IP interface are more difficult to understand. Still, this
elessair 0:f269e3021894 86 is the preferred way of writing applications that should be small in
elessair 0:f269e3021894 87 code size and memory usage.
elessair 0:f269e3021894 88
elessair 0:f269e3021894 89 All APIs can be used simultaneously by different application
elessair 0:f269e3021894 90 programs. In fact, the sequential API is implemented as an application
elessair 0:f269e3021894 91 program using the raw TCP/IP interface.
elessair 0:f269e3021894 92
elessair 0:f269e3021894 93 Do not confuse the lwIP raw API with raw Ethernet or IP sockets.
elessair 0:f269e3021894 94 The former is a way of interfacing the lwIP network stack (including
elessair 0:f269e3021894 95 TCP and UDP), the later refers to processing raw Ethernet or IP data
elessair 0:f269e3021894 96 instead of TCP connections or UDP packets.
elessair 0:f269e3021894 97
elessair 0:f269e3021894 98 Raw API applications may never block since all packet processing
elessair 0:f269e3021894 99 (input and output) as well as timer processing (TCP mainly) is done
elessair 0:f269e3021894 100 in a single execution context.
elessair 0:f269e3021894 101
elessair 0:f269e3021894 102 --- Callbacks
elessair 0:f269e3021894 103
elessair 0:f269e3021894 104 Program execution is driven by callbacks functions, which are then
elessair 0:f269e3021894 105 invoked by the lwIP core when activity related to that application
elessair 0:f269e3021894 106 occurs. A particular application may register to be notified via a
elessair 0:f269e3021894 107 callback function for events such as incoming data available, outgoing
elessair 0:f269e3021894 108 data sent, error notifications, poll timer expiration, connection
elessair 0:f269e3021894 109 closed, etc. An application can provide a callback function to perform
elessair 0:f269e3021894 110 processing for any or all of these events. Each callback is an ordinary
elessair 0:f269e3021894 111 C function that is called from within the TCP/IP code. Every callback
elessair 0:f269e3021894 112 function is passed the current TCP or UDP connection state as an
elessair 0:f269e3021894 113 argument. Also, in order to be able to keep program specific state,
elessair 0:f269e3021894 114 the callback functions are called with a program specified argument
elessair 0:f269e3021894 115 that is independent of the TCP/IP state.
elessair 0:f269e3021894 116
elessair 0:f269e3021894 117 The function for setting the application connection state is:
elessair 0:f269e3021894 118
elessair 0:f269e3021894 119 - void tcp_arg(struct tcp_pcb *pcb, void *arg)
elessair 0:f269e3021894 120
elessair 0:f269e3021894 121 Specifies the program specific state that should be passed to all
elessair 0:f269e3021894 122 other callback functions. The "pcb" argument is the current TCP
elessair 0:f269e3021894 123 connection control block, and the "arg" argument is the argument
elessair 0:f269e3021894 124 that will be passed to the callbacks.
elessair 0:f269e3021894 125
elessair 0:f269e3021894 126
elessair 0:f269e3021894 127 --- TCP connection setup
elessair 0:f269e3021894 128
elessair 0:f269e3021894 129 The functions used for setting up connections is similar to that of
elessair 0:f269e3021894 130 the sequential API and of the BSD socket API. A new TCP connection
elessair 0:f269e3021894 131 identifier (i.e., a protocol control block - PCB) is created with the
elessair 0:f269e3021894 132 tcp_new() function. This PCB can then be either set to listen for new
elessair 0:f269e3021894 133 incoming connections or be explicitly connected to another host.
elessair 0:f269e3021894 134
elessair 0:f269e3021894 135 - struct tcp_pcb *tcp_new(void)
elessair 0:f269e3021894 136
elessair 0:f269e3021894 137 Creates a new connection identifier (PCB). If memory is not
elessair 0:f269e3021894 138 available for creating the new pcb, NULL is returned.
elessair 0:f269e3021894 139
elessair 0:f269e3021894 140 - err_t tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr,
elessair 0:f269e3021894 141 u16_t port)
elessair 0:f269e3021894 142
elessair 0:f269e3021894 143 Binds the pcb to a local IP address and port number. The IP address
elessair 0:f269e3021894 144 can be specified as IP_ADDR_ANY in order to bind the connection to
elessair 0:f269e3021894 145 all local IP addresses.
elessair 0:f269e3021894 146
elessair 0:f269e3021894 147 If another connection is bound to the same port, the function will
elessair 0:f269e3021894 148 return ERR_USE, otherwise ERR_OK is returned.
elessair 0:f269e3021894 149
elessair 0:f269e3021894 150 - struct tcp_pcb *tcp_listen(struct tcp_pcb *pcb)
elessair 0:f269e3021894 151
elessair 0:f269e3021894 152 Commands a pcb to start listening for incoming connections. When an
elessair 0:f269e3021894 153 incoming connection is accepted, the function specified with the
elessair 0:f269e3021894 154 tcp_accept() function will be called. The pcb will have to be bound
elessair 0:f269e3021894 155 to a local port with the tcp_bind() function.
elessair 0:f269e3021894 156
elessair 0:f269e3021894 157 The tcp_listen() function returns a new connection identifier, and
elessair 0:f269e3021894 158 the one passed as an argument to the function will be
elessair 0:f269e3021894 159 deallocated. The reason for this behavior is that less memory is
elessair 0:f269e3021894 160 needed for a connection that is listening, so tcp_listen() will
elessair 0:f269e3021894 161 reclaim the memory needed for the original connection and allocate a
elessair 0:f269e3021894 162 new smaller memory block for the listening connection.
elessair 0:f269e3021894 163
elessair 0:f269e3021894 164 tcp_listen() may return NULL if no memory was available for the
elessair 0:f269e3021894 165 listening connection. If so, the memory associated with the pcb
elessair 0:f269e3021894 166 passed as an argument to tcp_listen() will not be deallocated.
elessair 0:f269e3021894 167
elessair 0:f269e3021894 168 - struct tcp_pcb *tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
elessair 0:f269e3021894 169
elessair 0:f269e3021894 170 Same as tcp_listen, but limits the number of outstanding connections
elessair 0:f269e3021894 171 in the listen queue to the value specified by the backlog argument.
elessair 0:f269e3021894 172 To use it, your need to set TCP_LISTEN_BACKLOG=1 in your lwipopts.h.
elessair 0:f269e3021894 173
elessair 0:f269e3021894 174 - void tcp_accepted(struct tcp_pcb *pcb)
elessair 0:f269e3021894 175
elessair 0:f269e3021894 176 Inform lwIP that an incoming connection has been accepted. This would
elessair 0:f269e3021894 177 usually be called from the accept callback. This allows lwIP to perform
elessair 0:f269e3021894 178 housekeeping tasks, such as allowing further incoming connections to be
elessair 0:f269e3021894 179 queued in the listen backlog.
elessair 0:f269e3021894 180 ATTENTION: the PCB passed in must be the listening pcb, not the pcb passed
elessair 0:f269e3021894 181 into the accept callback!
elessair 0:f269e3021894 182
elessair 0:f269e3021894 183 - void tcp_accept(struct tcp_pcb *pcb,
elessair 0:f269e3021894 184 err_t (* accept)(void *arg, struct tcp_pcb *newpcb,
elessair 0:f269e3021894 185 err_t err))
elessair 0:f269e3021894 186
elessair 0:f269e3021894 187 Specified the callback function that should be called when a new
elessair 0:f269e3021894 188 connection arrives on a listening connection.
elessair 0:f269e3021894 189
elessair 0:f269e3021894 190 - err_t tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr,
elessair 0:f269e3021894 191 u16_t port, err_t (* connected)(void *arg,
elessair 0:f269e3021894 192 struct tcp_pcb *tpcb,
elessair 0:f269e3021894 193 err_t err));
elessair 0:f269e3021894 194
elessair 0:f269e3021894 195 Sets up the pcb to connect to the remote host and sends the
elessair 0:f269e3021894 196 initial SYN segment which opens the connection.
elessair 0:f269e3021894 197
elessair 0:f269e3021894 198 The tcp_connect() function returns immediately; it does not wait for
elessair 0:f269e3021894 199 the connection to be properly setup. Instead, it will call the
elessair 0:f269e3021894 200 function specified as the fourth argument (the "connected" argument)
elessair 0:f269e3021894 201 when the connection is established. If the connection could not be
elessair 0:f269e3021894 202 properly established, either because the other host refused the
elessair 0:f269e3021894 203 connection or because the other host didn't answer, the "err"
elessair 0:f269e3021894 204 callback function of this pcb (registered with tcp_err, see below)
elessair 0:f269e3021894 205 will be called.
elessair 0:f269e3021894 206
elessair 0:f269e3021894 207 The tcp_connect() function can return ERR_MEM if no memory is
elessair 0:f269e3021894 208 available for enqueueing the SYN segment. If the SYN indeed was
elessair 0:f269e3021894 209 enqueued successfully, the tcp_connect() function returns ERR_OK.
elessair 0:f269e3021894 210
elessair 0:f269e3021894 211
elessair 0:f269e3021894 212 --- Sending TCP data
elessair 0:f269e3021894 213
elessair 0:f269e3021894 214 TCP data is sent by enqueueing the data with a call to
elessair 0:f269e3021894 215 tcp_write(). When the data is successfully transmitted to the remote
elessair 0:f269e3021894 216 host, the application will be notified with a call to a specified
elessair 0:f269e3021894 217 callback function.
elessair 0:f269e3021894 218
elessair 0:f269e3021894 219 - err_t tcp_write(struct tcp_pcb *pcb, const void *dataptr, u16_t len,
elessair 0:f269e3021894 220 u8_t apiflags)
elessair 0:f269e3021894 221
elessair 0:f269e3021894 222 Enqueues the data pointed to by the argument dataptr. The length of
elessair 0:f269e3021894 223 the data is passed as the len parameter. The apiflags can be one or more of:
elessair 0:f269e3021894 224 - TCP_WRITE_FLAG_COPY: indicates whether the new memory should be allocated
elessair 0:f269e3021894 225 for the data to be copied into. If this flag is not given, no new memory
elessair 0:f269e3021894 226 should be allocated and the data should only be referenced by pointer. This
elessair 0:f269e3021894 227 also means that the memory behind dataptr must not change until the data is
elessair 0:f269e3021894 228 ACKed by the remote host
elessair 0:f269e3021894 229 - TCP_WRITE_FLAG_MORE: indicates that more data follows. If this is omitted,
elessair 0:f269e3021894 230 the PSH flag is set in the last segment created by this call to tcp_write.
elessair 0:f269e3021894 231 If this flag is given, the PSH flag is not set.
elessair 0:f269e3021894 232
elessair 0:f269e3021894 233 The tcp_write() function will fail and return ERR_MEM if the length
elessair 0:f269e3021894 234 of the data exceeds the current send buffer size or if the length of
elessair 0:f269e3021894 235 the queue of outgoing segment is larger than the upper limit defined
elessair 0:f269e3021894 236 in lwipopts.h. The number of bytes available in the output queue can
elessair 0:f269e3021894 237 be retrieved with the tcp_sndbuf() function.
elessair 0:f269e3021894 238
elessair 0:f269e3021894 239 The proper way to use this function is to call the function with at
elessair 0:f269e3021894 240 most tcp_sndbuf() bytes of data. If the function returns ERR_MEM,
elessair 0:f269e3021894 241 the application should wait until some of the currently enqueued
elessair 0:f269e3021894 242 data has been successfully received by the other host and try again.
elessair 0:f269e3021894 243
elessair 0:f269e3021894 244 - void tcp_sent(struct tcp_pcb *pcb,
elessair 0:f269e3021894 245 err_t (* sent)(void *arg, struct tcp_pcb *tpcb,
elessair 0:f269e3021894 246 u16_t len))
elessair 0:f269e3021894 247
elessair 0:f269e3021894 248 Specifies the callback function that should be called when data has
elessair 0:f269e3021894 249 successfully been received (i.e., acknowledged) by the remote
elessair 0:f269e3021894 250 host. The len argument passed to the callback function gives the
elessair 0:f269e3021894 251 amount bytes that was acknowledged by the last acknowledgment.
elessair 0:f269e3021894 252
elessair 0:f269e3021894 253
elessair 0:f269e3021894 254 --- Receiving TCP data
elessair 0:f269e3021894 255
elessair 0:f269e3021894 256 TCP data reception is callback based - an application specified
elessair 0:f269e3021894 257 callback function is called when new data arrives. When the
elessair 0:f269e3021894 258 application has taken the data, it has to call the tcp_recved()
elessair 0:f269e3021894 259 function to indicate that TCP can advertise increase the receive
elessair 0:f269e3021894 260 window.
elessair 0:f269e3021894 261
elessair 0:f269e3021894 262 - void tcp_recv(struct tcp_pcb *pcb,
elessair 0:f269e3021894 263 err_t (* recv)(void *arg, struct tcp_pcb *tpcb,
elessair 0:f269e3021894 264 struct pbuf *p, err_t err))
elessair 0:f269e3021894 265
elessair 0:f269e3021894 266 Sets the callback function that will be called when new data
elessair 0:f269e3021894 267 arrives. The callback function will be passed a NULL pbuf to
elessair 0:f269e3021894 268 indicate that the remote host has closed the connection. If
elessair 0:f269e3021894 269 there are no errors and the callback function is to return
elessair 0:f269e3021894 270 ERR_OK, then it must free the pbuf. Otherwise, it must not
elessair 0:f269e3021894 271 free the pbuf so that lwIP core code can store it.
elessair 0:f269e3021894 272
elessair 0:f269e3021894 273 - void tcp_recved(struct tcp_pcb *pcb, u16_t len)
elessair 0:f269e3021894 274
elessair 0:f269e3021894 275 Must be called when the application has received the data. The len
elessair 0:f269e3021894 276 argument indicates the length of the received data.
elessair 0:f269e3021894 277
elessair 0:f269e3021894 278
elessair 0:f269e3021894 279 --- Application polling
elessair 0:f269e3021894 280
elessair 0:f269e3021894 281 When a connection is idle (i.e., no data is either transmitted or
elessair 0:f269e3021894 282 received), lwIP will repeatedly poll the application by calling a
elessair 0:f269e3021894 283 specified callback function. This can be used either as a watchdog
elessair 0:f269e3021894 284 timer for killing connections that have stayed idle for too long, or
elessair 0:f269e3021894 285 as a method of waiting for memory to become available. For instance,
elessair 0:f269e3021894 286 if a call to tcp_write() has failed because memory wasn't available,
elessair 0:f269e3021894 287 the application may use the polling functionality to call tcp_write()
elessair 0:f269e3021894 288 again when the connection has been idle for a while.
elessair 0:f269e3021894 289
elessair 0:f269e3021894 290 - void tcp_poll(struct tcp_pcb *pcb,
elessair 0:f269e3021894 291 err_t (* poll)(void *arg, struct tcp_pcb *tpcb),
elessair 0:f269e3021894 292 u8_t interval)
elessair 0:f269e3021894 293
elessair 0:f269e3021894 294 Specifies the polling interval and the callback function that should
elessair 0:f269e3021894 295 be called to poll the application. The interval is specified in
elessair 0:f269e3021894 296 number of TCP coarse grained timer shots, which typically occurs
elessair 0:f269e3021894 297 twice a second. An interval of 10 means that the application would
elessair 0:f269e3021894 298 be polled every 5 seconds.
elessair 0:f269e3021894 299
elessair 0:f269e3021894 300
elessair 0:f269e3021894 301 --- Closing and aborting connections
elessair 0:f269e3021894 302
elessair 0:f269e3021894 303 - err_t tcp_close(struct tcp_pcb *pcb)
elessair 0:f269e3021894 304
elessair 0:f269e3021894 305 Closes the connection. The function may return ERR_MEM if no memory
elessair 0:f269e3021894 306 was available for closing the connection. If so, the application
elessair 0:f269e3021894 307 should wait and try again either by using the acknowledgment
elessair 0:f269e3021894 308 callback or the polling functionality. If the close succeeds, the
elessair 0:f269e3021894 309 function returns ERR_OK.
elessair 0:f269e3021894 310
elessair 0:f269e3021894 311 The pcb is deallocated by the TCP code after a call to tcp_close().
elessair 0:f269e3021894 312
elessair 0:f269e3021894 313 - void tcp_abort(struct tcp_pcb *pcb)
elessair 0:f269e3021894 314
elessair 0:f269e3021894 315 Aborts the connection by sending a RST (reset) segment to the remote
elessair 0:f269e3021894 316 host. The pcb is deallocated. This function never fails.
elessair 0:f269e3021894 317
elessair 0:f269e3021894 318 ATTENTION: When calling this from one of the TCP callbacks, make
elessair 0:f269e3021894 319 sure you always return ERR_ABRT (and never return ERR_ABRT otherwise
elessair 0:f269e3021894 320 or you will risk accessing deallocated memory or memory leaks!
elessair 0:f269e3021894 321
elessair 0:f269e3021894 322
elessair 0:f269e3021894 323 If a connection is aborted because of an error, the application is
elessair 0:f269e3021894 324 alerted of this event by the err callback. Errors that might abort a
elessair 0:f269e3021894 325 connection are when there is a shortage of memory. The callback
elessair 0:f269e3021894 326 function to be called is set using the tcp_err() function.
elessair 0:f269e3021894 327
elessair 0:f269e3021894 328 - void tcp_err(struct tcp_pcb *pcb, void (* err)(void *arg,
elessair 0:f269e3021894 329 err_t err))
elessair 0:f269e3021894 330
elessair 0:f269e3021894 331 The error callback function does not get the pcb passed to it as a
elessair 0:f269e3021894 332 parameter since the pcb may already have been deallocated.
elessair 0:f269e3021894 333
elessair 0:f269e3021894 334
elessair 0:f269e3021894 335 --- UDP interface
elessair 0:f269e3021894 336
elessair 0:f269e3021894 337 The UDP interface is similar to that of TCP, but due to the lower
elessair 0:f269e3021894 338 level of complexity of UDP, the interface is significantly simpler.
elessair 0:f269e3021894 339
elessair 0:f269e3021894 340 - struct udp_pcb *udp_new(void)
elessair 0:f269e3021894 341
elessair 0:f269e3021894 342 Creates a new UDP pcb which can be used for UDP communication. The
elessair 0:f269e3021894 343 pcb is not active until it has either been bound to a local address
elessair 0:f269e3021894 344 or connected to a remote address.
elessair 0:f269e3021894 345
elessair 0:f269e3021894 346 - void udp_remove(struct udp_pcb *pcb)
elessair 0:f269e3021894 347
elessair 0:f269e3021894 348 Removes and deallocates the pcb.
elessair 0:f269e3021894 349
elessair 0:f269e3021894 350 - err_t udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr,
elessair 0:f269e3021894 351 u16_t port)
elessair 0:f269e3021894 352
elessair 0:f269e3021894 353 Binds the pcb to a local address. The IP-address argument "ipaddr"
elessair 0:f269e3021894 354 can be IP_ADDR_ANY to indicate that it should listen to any local IP
elessair 0:f269e3021894 355 address. The function currently always return ERR_OK.
elessair 0:f269e3021894 356
elessair 0:f269e3021894 357 - err_t udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr,
elessair 0:f269e3021894 358 u16_t port)
elessair 0:f269e3021894 359
elessair 0:f269e3021894 360 Sets the remote end of the pcb. This function does not generate any
elessair 0:f269e3021894 361 network traffic, but only set the remote address of the pcb.
elessair 0:f269e3021894 362
elessair 0:f269e3021894 363 - err_t udp_disconnect(struct udp_pcb *pcb)
elessair 0:f269e3021894 364
elessair 0:f269e3021894 365 Remove the remote end of the pcb. This function does not generate
elessair 0:f269e3021894 366 any network traffic, but only removes the remote address of the pcb.
elessair 0:f269e3021894 367
elessair 0:f269e3021894 368 - err_t udp_send(struct udp_pcb *pcb, struct pbuf *p)
elessair 0:f269e3021894 369
elessair 0:f269e3021894 370 Sends the pbuf p. The pbuf is not deallocated.
elessair 0:f269e3021894 371
elessair 0:f269e3021894 372 - void udp_recv(struct udp_pcb *pcb,
elessair 0:f269e3021894 373 void (* recv)(void *arg, struct udp_pcb *upcb,
elessair 0:f269e3021894 374 struct pbuf *p,
elessair 0:f269e3021894 375 ip_addr_t *addr,
elessair 0:f269e3021894 376 u16_t port),
elessair 0:f269e3021894 377 void *recv_arg)
elessair 0:f269e3021894 378
elessair 0:f269e3021894 379 Specifies a callback function that should be called when a UDP
elessair 0:f269e3021894 380 datagram is received.
elessair 0:f269e3021894 381
elessair 0:f269e3021894 382
elessair 0:f269e3021894 383 --- System initalization
elessair 0:f269e3021894 384
elessair 0:f269e3021894 385 A truly complete and generic sequence for initializing the lwIP stack
elessair 0:f269e3021894 386 cannot be given because it depends on additional initializations for
elessair 0:f269e3021894 387 your runtime environment (e.g. timers).
elessair 0:f269e3021894 388
elessair 0:f269e3021894 389 We can give you some idea on how to proceed when using the raw API.
elessair 0:f269e3021894 390 We assume a configuration using a single Ethernet netif and the
elessair 0:f269e3021894 391 UDP and TCP transport layers, IPv4 and the DHCP client.
elessair 0:f269e3021894 392
elessair 0:f269e3021894 393 Call these functions in the order of appearance:
elessair 0:f269e3021894 394
elessair 0:f269e3021894 395 - lwip_init()
elessair 0:f269e3021894 396
elessair 0:f269e3021894 397 Initialize the lwIP stack and all of its subsystems.
elessair 0:f269e3021894 398
elessair 0:f269e3021894 399 - netif_add(struct netif *netif, const ip4_addr_t *ipaddr,
elessair 0:f269e3021894 400 const ip4_addr_t *netmask, const ip4_addr_t *gw,
elessair 0:f269e3021894 401 void *state, netif_init_fn init, netif_input_fn input)
elessair 0:f269e3021894 402
elessair 0:f269e3021894 403 Adds your network interface to the netif_list. Allocate a struct
elessair 0:f269e3021894 404 netif and pass a pointer to this structure as the first argument.
elessair 0:f269e3021894 405 Give pointers to cleared ip_addr structures when using DHCP,
elessair 0:f269e3021894 406 or fill them with sane numbers otherwise. The state pointer may be NULL.
elessair 0:f269e3021894 407
elessair 0:f269e3021894 408 The init function pointer must point to a initialization function for
elessair 0:f269e3021894 409 your Ethernet netif interface. The following code illustrates its use.
elessair 0:f269e3021894 410
elessair 0:f269e3021894 411 err_t netif_if_init(struct netif *netif)
elessair 0:f269e3021894 412 {
elessair 0:f269e3021894 413 u8_t i;
elessair 0:f269e3021894 414
elessair 0:f269e3021894 415 for (i = 0; i < ETHARP_HWADDR_LEN; i++) {
elessair 0:f269e3021894 416 netif->hwaddr[i] = some_eth_addr[i];
elessair 0:f269e3021894 417 }
elessair 0:f269e3021894 418 init_my_eth_device();
elessair 0:f269e3021894 419 return ERR_OK;
elessair 0:f269e3021894 420 }
elessair 0:f269e3021894 421
elessair 0:f269e3021894 422 For Ethernet drivers, the input function pointer must point to the lwIP
elessair 0:f269e3021894 423 function ethernet_input() declared in "netif/etharp.h". Other drivers
elessair 0:f269e3021894 424 must use ip_input() declared in "lwip/ip.h".
elessair 0:f269e3021894 425
elessair 0:f269e3021894 426 - netif_set_default(struct netif *netif)
elessair 0:f269e3021894 427
elessair 0:f269e3021894 428 Registers the default network interface.
elessair 0:f269e3021894 429
elessair 0:f269e3021894 430 - netif_set_link_up(struct netif *netif)
elessair 0:f269e3021894 431
elessair 0:f269e3021894 432 This is the hardware link state; e.g. whether cable is plugged for wired
elessair 0:f269e3021894 433 Ethernet interface. This function must be called even if you don't know
elessair 0:f269e3021894 434 the current state. Having link up and link down events is optional but
elessair 0:f269e3021894 435 DHCP and IPv6 discover benefit well from those events.
elessair 0:f269e3021894 436
elessair 0:f269e3021894 437 - netif_set_up(struct netif *netif)
elessair 0:f269e3021894 438
elessair 0:f269e3021894 439 This is the administrative (= software) state of the netif, when the
elessair 0:f269e3021894 440 netif is fully configured this function must be called.
elessair 0:f269e3021894 441
elessair 0:f269e3021894 442 - dhcp_start(struct netif *netif)
elessair 0:f269e3021894 443
elessair 0:f269e3021894 444 Creates a new DHCP client for this interface on the first call.
elessair 0:f269e3021894 445
elessair 0:f269e3021894 446 You can peek in the netif->dhcp struct for the actual DHCP status.
elessair 0:f269e3021894 447
elessair 0:f269e3021894 448 - sys_check_timeouts()
elessair 0:f269e3021894 449
elessair 0:f269e3021894 450 When the system is running, you have to periodically call
elessair 0:f269e3021894 451 sys_check_timeouts() which will handle all timers for all protocols in
elessair 0:f269e3021894 452 the stack; add this to your main loop or equivalent.
elessair 0:f269e3021894 453
elessair 0:f269e3021894 454
elessair 0:f269e3021894 455 --- Optimalization hints
elessair 0:f269e3021894 456
elessair 0:f269e3021894 457 The first thing you want to optimize is the lwip_standard_checksum()
elessair 0:f269e3021894 458 routine from src/core/inet.c. You can override this standard
elessair 0:f269e3021894 459 function with the #define LWIP_CHKSUM <your_checksum_routine>.
elessair 0:f269e3021894 460
elessair 0:f269e3021894 461 There are C examples given in inet.c or you might want to
elessair 0:f269e3021894 462 craft an assembly function for this. RFC1071 is a good
elessair 0:f269e3021894 463 introduction to this subject.
elessair 0:f269e3021894 464
elessair 0:f269e3021894 465 Other significant improvements can be made by supplying
elessair 0:f269e3021894 466 assembly or inline replacements for htons() and htonl()
elessair 0:f269e3021894 467 if you're using a little-endian architecture.
elessair 0:f269e3021894 468 #define LWIP_PLATFORM_BYTESWAP 1
elessair 0:f269e3021894 469 #define LWIP_PLATFORM_HTONS(x) <your_htons>
elessair 0:f269e3021894 470 #define LWIP_PLATFORM_HTONL(x) <your_htonl>
elessair 0:f269e3021894 471
elessair 0:f269e3021894 472 Check your network interface driver if it reads at
elessair 0:f269e3021894 473 a higher speed than the maximum wire-speed. If the
elessair 0:f269e3021894 474 hardware isn't serviced frequently and fast enough
elessair 0:f269e3021894 475 buffer overflows are likely to occur.
elessair 0:f269e3021894 476
elessair 0:f269e3021894 477 E.g. when using the cs8900 driver, call cs8900if_service(ethif)
elessair 0:f269e3021894 478 as frequently as possible. When using an RTOS let the cs8900 interrupt
elessair 0:f269e3021894 479 wake a high priority task that services your driver using a binary
elessair 0:f269e3021894 480 semaphore or event flag. Some drivers might allow additional tuning
elessair 0:f269e3021894 481 to match your application and network.
elessair 0:f269e3021894 482
elessair 0:f269e3021894 483 For a production release it is recommended to set LWIP_STATS to 0.
elessair 0:f269e3021894 484 Note that speed performance isn't influenced much by simply setting
elessair 0:f269e3021894 485 high values to the memory options.
elessair 0:f269e3021894 486
elessair 0:f269e3021894 487 For more optimization hints take a look at the lwIP wiki.
elessair 0:f269e3021894 488
elessair 0:f269e3021894 489 --- Zero-copy MACs
elessair 0:f269e3021894 490
elessair 0:f269e3021894 491 To achieve zero-copy on transmit, the data passed to the raw API must
elessair 0:f269e3021894 492 remain unchanged until sent. Because the send- (or write-)functions return
elessair 0:f269e3021894 493 when the packets have been enqueued for sending, data must be kept stable
elessair 0:f269e3021894 494 after that, too.
elessair 0:f269e3021894 495
elessair 0:f269e3021894 496 This implies that PBUF_RAM/PBUF_POOL pbufs passed to raw-API send functions
elessair 0:f269e3021894 497 must *not* be reused by the application unless their ref-count is 1.
elessair 0:f269e3021894 498
elessair 0:f269e3021894 499 For no-copy pbufs (PBUF_ROM/PBUF_REF), data must be kept unchanged, too,
elessair 0:f269e3021894 500 but the stack/driver will/must copy PBUF_REF'ed data when enqueueing, while
elessair 0:f269e3021894 501 PBUF_ROM-pbufs are just enqueued (as ROM-data is expected to never change).
elessair 0:f269e3021894 502
elessair 0:f269e3021894 503 Also, data passed to tcp_write without the copy-flag must not be changed!
elessair 0:f269e3021894 504
elessair 0:f269e3021894 505 Therefore, be careful which type of PBUF you use and if you copy TCP data
elessair 0:f269e3021894 506 or not!