Compare commits
79 Commits
STABLE-1_1
...
STABLE-1_1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fef5c4c9a0 | ||
|
|
61dc2e7dd5 | ||
|
|
11a820458f | ||
|
|
9e7418090d | ||
|
|
0b3b713123 | ||
|
|
00f8cf57cd | ||
|
|
c55c375b0a | ||
|
|
db76ca248b | ||
|
|
182e1909b2 | ||
|
|
3aea7bc053 | ||
|
|
39c35732de | ||
|
|
6c8850698d | ||
|
|
818a726679 | ||
|
|
f8663a7129 | ||
|
|
7571fe5d13 | ||
|
|
60dc1c22f7 | ||
|
|
02b575e9e4 | ||
|
|
6facaf8f05 | ||
|
|
319a972e75 | ||
|
|
61cdbb30a6 | ||
|
|
5088a38b9f | ||
|
|
f5c6a6d075 | ||
|
|
b5340dd739 | ||
|
|
e1dcfcbb76 | ||
|
|
43d448e73f | ||
|
|
33fbb06604 | ||
|
|
e1b215aa73 | ||
|
|
6a17ef925d | ||
|
|
7599985a0a | ||
|
|
07c0bc288a | ||
|
|
f05d392920 | ||
|
|
e11d57c883 | ||
|
|
baf377679a | ||
|
|
f9355136d8 | ||
|
|
bb76e69567 | ||
|
|
533fc217d4 | ||
|
|
ac5c6695c1 | ||
|
|
3160488352 | ||
|
|
8579e4144f | ||
|
|
6880fa62f8 | ||
|
|
2cf4287197 | ||
|
|
86c774443c | ||
|
|
3b715f4602 | ||
|
|
ec0c2bea6e | ||
|
|
1b3682cfa9 | ||
|
|
2a9ee35411 | ||
|
|
0e0a7d82de | ||
|
|
dfa96852f0 | ||
|
|
a549ec0382 | ||
|
|
c61f01b206 | ||
|
|
15257f4524 | ||
|
|
089378ef87 | ||
|
|
805f495d84 | ||
|
|
928dd94ba6 | ||
|
|
b429918b32 | ||
|
|
62a37a4876 | ||
|
|
0e96ece6c6 | ||
|
|
f1eca32536 | ||
|
|
ed59dc1ada | ||
|
|
a5cd3fcafd | ||
|
|
f3def542ee | ||
|
|
aa249922df | ||
|
|
37a0c57bed | ||
|
|
90b7e68b4e | ||
|
|
1a0c497007 | ||
|
|
fd49ee3c8d | ||
|
|
3488a5c3c4 | ||
|
|
ae4955f59e | ||
|
|
fab107a9df | ||
|
|
bb87d19e84 | ||
|
|
4e309b7992 | ||
|
|
64aa4c716d | ||
|
|
6b0852a21f | ||
|
|
8afd3e882e | ||
|
|
791fa28817 | ||
|
|
3fab752640 | ||
|
|
67dd939d83 | ||
|
|
ec9b447be1 | ||
|
|
99e3fe9ae1 |
119
CHANGELOG
119
CHANGELOG
@@ -5,58 +5,149 @@ FUTURE
|
|||||||
problems with exoteric (/DSP) architectures showing these problems.
|
problems with exoteric (/DSP) architectures showing these problems.
|
||||||
We still have to fix some of these issues neatly.
|
We still have to fix some of these issues neatly.
|
||||||
|
|
||||||
|
* TODO: the ARP layer is not protected against concurrent access. If
|
||||||
|
you run from a multitasking OS, serialize access to ARP (called from
|
||||||
|
your network device driver and from a timeout thread.)
|
||||||
|
|
||||||
|
* TODO: the PPP code is broken in a few ways. There are namespace
|
||||||
|
collisions on BSD systems and many assumptions on word-length
|
||||||
|
(sizeof(int)). In ppp.c an assumption is made on the availability of
|
||||||
|
a thread subsystem. Either PPP needs to be moved to contrib/ports/???
|
||||||
|
or rearranged to be more generic.
|
||||||
|
|
||||||
HISTORY
|
HISTORY
|
||||||
|
|
||||||
(HEAD)
|
(CVS HEAD)
|
||||||
|
|
||||||
|
* [New changes go here]
|
||||||
|
|
||||||
|
(STABLE-1_1_1)
|
||||||
|
|
||||||
|
2006-03-03 Christiaan Simons
|
||||||
|
* ipv4/ip_frag.c: Added bound-checking assertions on ip_reassbitmap
|
||||||
|
access and added pbuf_alloc() return value checks.
|
||||||
|
|
||||||
|
2006-01-01 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
* tcp_{in,out}.c, tcp_out.c: Removed 'even sndbuf' fix in TCP, which is
|
||||||
|
now handled by the checksum routine properly.
|
||||||
|
|
||||||
|
2006-02-27 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
* pbuf.c: Fix alignment; pbuf_init() would not work unless
|
||||||
|
pbuf_pool_memory[] was properly aligned. (Patch by Curt McDowell.)
|
||||||
|
|
||||||
|
2005-12-20 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
* tcp.c: Remove PCBs which stay in LAST_ACK state too long. Patch
|
||||||
|
submitted by Mitrani Hiroshi.
|
||||||
|
|
||||||
|
2005-12-15 Christiaan Simons
|
||||||
|
* inet.c: Disabled the added summing routine to preserve code space.
|
||||||
|
|
||||||
|
2005-12-14 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
* tcp_in.c: Duplicate FIN ACK race condition fix by Kelvin Lawson.
|
||||||
|
Added Curt McDowell's optimized checksumming routine for future
|
||||||
|
inclusion. Need to create test case for unaliged, aligned, odd,
|
||||||
|
even length combination of cases on various endianess machines.
|
||||||
|
|
||||||
|
2005-12-09 Christiaan Simons
|
||||||
|
* inet.c: Rewrote standard checksum routine in proper portable C.
|
||||||
|
|
||||||
|
2005-11-25 Christiaan Simons
|
||||||
|
* udp.c tcp.c: Removed SO_REUSE hack. Should reside in socket code only.
|
||||||
|
* *.c: introduced cc.h LWIP_DEBUG formatters matching the u16_t, s16_t,
|
||||||
|
u32_t, s32_t typedefs. This solves most debug word-length assumes.
|
||||||
|
|
||||||
|
2005-07-17 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
* inet.c: Fixed unaligned 16-bit access in the standard checksum
|
||||||
|
routine by Peter Jolasson.
|
||||||
|
* slipif.c: Fixed implementation assumption of single-pbuf datagrams.
|
||||||
|
|
||||||
|
2005-02-04 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
* tcp_out.c: Fixed uninitialized 'queue' referenced in memerr branch.
|
||||||
|
* tcp_{out|in}.c: Applied patch fixing unaligned access.
|
||||||
|
|
||||||
|
2005-01-04 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
* pbuf.c: Fixed missing semicolon after LWIP_DEBUG statement.
|
||||||
|
|
||||||
|
2005-01-03 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
* udp.c: UDP pcb->recv() was called even when it was NULL.
|
||||||
|
|
||||||
|
(STABLE-1_1_0)
|
||||||
|
|
||||||
|
2004-12-28 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
* etharp.*: Disabled multiple packets on the ARP queue.
|
||||||
|
This clashes with TCP queueing.
|
||||||
|
|
||||||
|
2004-11-28 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
* etharp.*: Fixed race condition from ARP request to ARP timeout.
|
||||||
|
Halved the ARP period, doubled the period counts.
|
||||||
|
ETHARP_MAX_PENDING now should be at least 2. This prevents
|
||||||
|
the counter from reaching 0 right away (which would allow
|
||||||
|
too little time for ARP responses to be received).
|
||||||
|
|
||||||
|
2004-11-25 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
|
* dhcp.c: Decline messages were not multicast but unicast.
|
||||||
|
* etharp.c: ETHARP_CREATE is renamed to ETHARP_TRY_HARD.
|
||||||
|
Do not try hard to insert arbitrary packet's source address,
|
||||||
|
etharp_ip_input() now calls etharp_update() without ETHARP_TRY_HARD.
|
||||||
|
etharp_query() now always DOES call ETHARP_TRY_HARD so that users
|
||||||
|
querying an address will see it appear in the cache (DHCP could
|
||||||
|
suffer from this when a server invalidly gave an in-use address.)
|
||||||
|
* ipv4/ip_addr.h: Renamed ip_addr_maskcmp() to _netcmp() as we are
|
||||||
|
comparing network addresses (identifiers), not the network masks
|
||||||
|
themselves.
|
||||||
|
* ipv4/ip_addr.c: ip_addr_isbroadcast() now checks that the given
|
||||||
|
IP address actually belongs to the network of the given interface.
|
||||||
|
|
||||||
|
2004-11-24 Kieran Mansley <kjm25@cam.ac.uk>
|
||||||
|
* tcp.c: Increment pcb->snd_buf when ACK is received in SYN_SENT state.
|
||||||
|
|
||||||
(STABLE-1_1_0-RC1)
|
(STABLE-1_1_0-RC1)
|
||||||
|
|
||||||
2004-10-16 Kieran Mansley <kjm25@cam.ac.uk>
|
2004-10-16 Kieran Mansley <kjm25@cam.ac.uk>
|
||||||
* tcp.c Add code to tcp_recved() to send an ACK (window update) immediately,
|
* tcp.c: Add code to tcp_recved() to send an ACK (window update) immediately,
|
||||||
even if one is already pending, if the rcv_wnd is above a threshold
|
even if one is already pending, if the rcv_wnd is above a threshold
|
||||||
(currently TCP_WND/2). This avoids waiting for a timer to expire to send a
|
(currently TCP_WND/2). This avoids waiting for a timer to expire to send a
|
||||||
delayed ACK in order to open the window if the stack is only receiving data.
|
delayed ACK in order to open the window if the stack is only receiving data.
|
||||||
|
|
||||||
2004-09-12 Kieran Mansley <kjm25@cam.ac.uk>
|
2004-09-12 Kieran Mansley <kjm25@cam.ac.uk>
|
||||||
* tcp*.* Retransmit time-out handling improvement by Sam Jansen.
|
* tcp*.*: Retransmit time-out handling improvement by Sam Jansen.
|
||||||
|
|
||||||
2004-08-20 Tony Mountifield <tony@softins.co.uk>
|
2004-08-20 Tony Mountifield <tony@softins.co.uk>
|
||||||
* etharp.c Make sure the first pbuf queued on an ARP entry
|
* etharp.c: Make sure the first pbuf queued on an ARP entry
|
||||||
is properly ref counted.
|
is properly ref counted.
|
||||||
|
|
||||||
2004-07-27 Tony Mountifield <tony@softins.co.uk>
|
2004-07-27 Tony Mountifield <tony@softins.co.uk>
|
||||||
* debug.h Added (int) cast in LWIP_DEBUGF() to avoid compiler
|
* debug.h: Added (int) cast in LWIP_DEBUGF() to avoid compiler
|
||||||
warnings about comparison.
|
warnings about comparison.
|
||||||
* pbuf.c Stopped compiler complaining of empty if statement
|
* pbuf.c: Stopped compiler complaining of empty if statement
|
||||||
when LWIP_DEBUGF() empty. Closed an unclosed comment.
|
when LWIP_DEBUGF() empty. Closed an unclosed comment.
|
||||||
* tcp.c Stopped compiler complaining of empty if statement
|
* tcp.c: Stopped compiler complaining of empty if statement
|
||||||
when LWIP_DEBUGF() empty.
|
when LWIP_DEBUGF() empty.
|
||||||
* ip.h Corrected IPH_TOS() macro: returns a byte, so doesn't need htons().
|
* ip.h Corrected IPH_TOS() macro: returns a byte, so doesn't need htons().
|
||||||
* inet.c Added a couple of casts to quiet the compiler.
|
* inet.c: Added a couple of casts to quiet the compiler.
|
||||||
No need to test isascii(c) before isdigit(c) or isxdigit(c).
|
No need to test isascii(c) before isdigit(c) or isxdigit(c).
|
||||||
|
|
||||||
2004-07-22 Tony Mountifield <tony@softins.co.uk>
|
2004-07-22 Tony Mountifield <tony@softins.co.uk>
|
||||||
* inet.c Made data types consistent in inet_ntoa().
|
* inet.c: Made data types consistent in inet_ntoa().
|
||||||
Added casts for return values of checksum routines, to pacify compiler.
|
Added casts for return values of checksum routines, to pacify compiler.
|
||||||
* ip_frag.c, tcp_out.c, sockets.c, pbuf.c
|
* ip_frag.c, tcp_out.c, sockets.c, pbuf.c
|
||||||
Small corrections to some debugging statements, to pacify compiler.
|
Small corrections to some debugging statements, to pacify compiler.
|
||||||
|
|
||||||
2004-07-21 Tony Mountifield <tony@softins.co.uk>
|
2004-07-21 Tony Mountifield <tony@softins.co.uk>
|
||||||
* etharp.c Removed spurious semicolon and added missing end-of-comment.
|
* etharp.c: Removed spurious semicolon and added missing end-of-comment.
|
||||||
* ethernetif.c Updated low_level_output() to match prototype for
|
* ethernetif.c Updated low_level_output() to match prototype for
|
||||||
netif->linkoutput and changed low_level_input() similarly for consistency.
|
netif->linkoutput and changed low_level_input() similarly for consistency.
|
||||||
* api_msg.c Changed recv_raw() from int to u8_t, to match prototype
|
* api_msg.c: Changed recv_raw() from int to u8_t, to match prototype
|
||||||
of raw_recv() in raw.h and so avoid compiler error.
|
of raw_recv() in raw.h and so avoid compiler error.
|
||||||
* sockets.c Added trivial (int) cast to keep compiler happier.
|
* sockets.c: Added trivial (int) cast to keep compiler happier.
|
||||||
* ip.c, netif.c Changed debug statements to use the tidier ip4_addrN() macros.
|
* ip.c, netif.c Changed debug statements to use the tidier ip4_addrN() macros.
|
||||||
|
|
||||||
|
|
||||||
(STABLE-1_0_0)
|
(STABLE-1_0_0)
|
||||||
|
|
||||||
++ Changes:
|
++ Changes:
|
||||||
|
|
||||||
2004-07-05 Leon Woestenberg <leon.woestenberg@gmx.net>
|
2004-07-05 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||||
* sockets.* Restructured LWIP_PRIVATE_TIMEVAL. Make sure
|
* sockets.*: Restructured LWIP_PRIVATE_TIMEVAL. Make sure
|
||||||
your cc.h file defines this either 1 or 0. If non-defined,
|
your cc.h file defines this either 1 or 0. If non-defined,
|
||||||
defaults to 1.
|
defaults to 1.
|
||||||
* .c: Added <string.h> and <errno.h> includes where used.
|
* .c: Added <string.h> and <errno.h> includes where used.
|
||||||
|
|||||||
26
README
26
README
@@ -7,7 +7,7 @@ Science (SICS).
|
|||||||
|
|
||||||
The focus of the lwIP TCP/IP implementation is to reduce the RAM usage
|
The focus of the lwIP TCP/IP implementation is to reduce the RAM usage
|
||||||
while still having a full scale TCP. This making lwIP suitable for use
|
while still having a full scale TCP. This making lwIP suitable for use
|
||||||
in embedded systems with tenths of kilobytes of free RAM and room for
|
in embedded systems with tens of kilobytes of free RAM and room for
|
||||||
around 40 kilobytes of code ROM.
|
around 40 kilobytes of code ROM.
|
||||||
|
|
||||||
FEATURES
|
FEATURES
|
||||||
@@ -42,29 +42,11 @@ CVS source tree.
|
|||||||
The lwIP TCP/IP stack is maintained in the 'lwip' CVS module and
|
The lwIP TCP/IP stack is maintained in the 'lwip' CVS module and
|
||||||
contributions (such as platform ports) are in the 'contrib' module.
|
contributions (such as platform ports) are in the 'contrib' module.
|
||||||
|
|
||||||
The CVS main trunk is the stable branch, which contains bug fixes and
|
See doc/savannah.txt for details on CVS server access for users and
|
||||||
tested features. The latest stable branch can be checked out by doing:
|
developers.
|
||||||
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
|
|
||||||
cvs -z3 -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip co lwip
|
|
||||||
|
|
||||||
The 'STABLE' tag in the stable branch will represent the most stable
|
|
||||||
revision (which may be somewhat older to protect us from errors
|
|
||||||
introduced by merges). This 'STABLE' tagged version can be checked out
|
|
||||||
by doing:
|
|
||||||
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
|
|
||||||
cvs -z3 -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip co -r STABLE lwip
|
|
||||||
|
|
||||||
The 'DEVEL' branch is the active development branch, which contains
|
|
||||||
bleeding edge changes, and may be instable. It can be checkout by doing:
|
|
||||||
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
|
|
||||||
cvs -z3 -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip co -r DEVEL lwip
|
|
||||||
|
|
||||||
The current contrib CVS tree can be checked out by doing:
|
|
||||||
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
|
|
||||||
cvs -z3 -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip co contrib
|
|
||||||
|
|
||||||
Last night's CVS tar ball can be downloaded from:
|
Last night's CVS tar ball can be downloaded from:
|
||||||
http://savannah.gnu.org/cvs.backups/lwip.tar.gz
|
http://savannah.gnu.org/cvs.backups/lwip.tar.gz [CHANGED - NEEDS FIXING]
|
||||||
|
|
||||||
The current CVS trees are web-browsable:
|
The current CVS trees are web-browsable:
|
||||||
http://savannah.nongnu.org/cgi-bin/viewcvs/lwip/lwip/
|
http://savannah.nongnu.org/cgi-bin/viewcvs/lwip/lwip/
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ features of Savannah help us not lose users' input.
|
|||||||
|
|
||||||
1. JavaDoc compliant and Doxygen compatible.
|
1. JavaDoc compliant and Doxygen compatible.
|
||||||
2. Function documentation above functions in .c files, not .h files.
|
2. Function documentation above functions in .c files, not .h files.
|
||||||
(This forces you to synchronize documentation and behaviour.)
|
(This forces you to synchronize documentation and implementation.)
|
||||||
3. Use current documentation style as further reference.
|
3. Use current documentation style as further reference.
|
||||||
|
|
||||||
2.3 Bug reports and patches:
|
2.3 Bug reports and patches:
|
||||||
|
|||||||
112
doc/rawapi.txt
112
doc/rawapi.txt
@@ -1,20 +1,21 @@
|
|||||||
Raw TCP/IP interface for lwIP 0.5
|
Raw TCP/IP interface for lwIP
|
||||||
|
|
||||||
Author: Adam Dunkels
|
Authors: Adam Dunkels, Leon Woestenberg, Christiaan Simons
|
||||||
|
|
||||||
lwIP provides two Application Program's Interfaces (APIs) for programs
|
lwIP provides two Application Program's Interfaces (APIs) for programs
|
||||||
to use for communication with the TCP/IP code: the sequential API
|
to use for communication with the TCP/IP code:
|
||||||
(often just called "the API") and the raw TCP/IP interface. This
|
* low-level "core" / "callback" or "raw" API.
|
||||||
document is intended as a description of the latter. For lwIP versions
|
* higher-level "sequential" API.
|
||||||
lower than 0.5, this API was not documented.
|
|
||||||
|
|
||||||
The sequential API provides a way for ordinary, sequential, programs
|
The sequential API provides a way for ordinary, sequential, programs
|
||||||
to use the lwIP stack. It is quite similar to the BSD socket API. The
|
to use the lwIP stack. It is quite similar to the BSD socket API. The
|
||||||
model of execution is based on the open-read-write-close
|
model of execution is based on the blocking open-read-write-close
|
||||||
paradigm. Since the TCP/IP stack is event based by nature, the TCP/IP
|
paradigm. Since the TCP/IP stack is event based by nature, the TCP/IP
|
||||||
code and the application program must reside in different execution
|
code and the application program must reside in different execution
|
||||||
contexts (threads).
|
contexts (threads).
|
||||||
|
|
||||||
|
** The remainder of this document discusses the "raw" API. **
|
||||||
|
|
||||||
The raw TCP/IP interface allows the application program to integrate
|
The raw TCP/IP interface allows the application program to integrate
|
||||||
better with the TCP/IP code. Program execution is event based by
|
better with the TCP/IP code. Program execution is event based by
|
||||||
having callback functions being called from within the TCP/IP
|
having callback functions being called from within the TCP/IP
|
||||||
@@ -34,7 +35,6 @@ Both APIs can be used simultaneously by different application
|
|||||||
programs. In fact, the sequential API is implemented as an application
|
programs. In fact, the sequential API is implemented as an application
|
||||||
program using the raw TCP/IP interface.
|
program using the raw TCP/IP interface.
|
||||||
|
|
||||||
|
|
||||||
--- Callbacks
|
--- Callbacks
|
||||||
|
|
||||||
Program execution is driven by callbacks. Each callback is an ordinary
|
Program execution is driven by callbacks. Each callback is an ordinary
|
||||||
@@ -289,4 +289,98 @@ level of complexity of UDP, the interface is significantly simpler.
|
|||||||
void *recv_arg)
|
void *recv_arg)
|
||||||
|
|
||||||
Specifies a callback function that should be called when a UDP
|
Specifies a callback function that should be called when a UDP
|
||||||
datagram is received.
|
datagram is received.
|
||||||
|
|
||||||
|
|
||||||
|
--- System initalization
|
||||||
|
|
||||||
|
A truly complete and generic sequence for initializing the lwip stack
|
||||||
|
cannot be given because it depends on the build configuration (lwipopts.h)
|
||||||
|
and additional initializations for your runtime environment (e.g. timers).
|
||||||
|
|
||||||
|
We can give you some idea on how to proceed when using the raw API.
|
||||||
|
We assume a configuration using a single Ethernet netif and the
|
||||||
|
UDP and TCP transport layers, IPv4 and the DHCP client.
|
||||||
|
|
||||||
|
Call these functions in the order of appearance:
|
||||||
|
|
||||||
|
- stats_init()
|
||||||
|
|
||||||
|
Clears the structure where runtime statistics are gathered.
|
||||||
|
|
||||||
|
- sys_init()
|
||||||
|
|
||||||
|
Not of much use since we set the NO_SYS 1 option in lwipopts.h,
|
||||||
|
to be called for easy configuration changes.
|
||||||
|
|
||||||
|
- mem_init()
|
||||||
|
|
||||||
|
Initializes the dynamic memory heap defined by MEM_SIZE.
|
||||||
|
|
||||||
|
- memp_init()
|
||||||
|
|
||||||
|
Initializes the memory pools defined by MEMP_NUM_x.
|
||||||
|
|
||||||
|
- pbuf_init()
|
||||||
|
|
||||||
|
Initializes the pbuf memory pool defined by PBUF_POOL_SIZE.
|
||||||
|
|
||||||
|
- etharp_init()
|
||||||
|
|
||||||
|
Initializes the ARP table and queue.
|
||||||
|
Note: you must call etharp_tmr at a 10 second regular interval
|
||||||
|
after this initialization.
|
||||||
|
|
||||||
|
- ip_init()
|
||||||
|
|
||||||
|
Doesn't do much, it should be called to handle future changes.
|
||||||
|
|
||||||
|
- udp_init()
|
||||||
|
|
||||||
|
Clears the UDP PCB list.
|
||||||
|
|
||||||
|
- tcp_init()
|
||||||
|
|
||||||
|
Clears the TCP PCB list and clears some internal TCP timers.
|
||||||
|
Note: you must call tcp_fasttmr() and tcp_slowtmr() at the
|
||||||
|
predefined regular intervals after this initialization.
|
||||||
|
|
||||||
|
- netif_add(struct netif *netif, struct ip_addr *ipaddr,
|
||||||
|
struct ip_addr *netmask, struct ip_addr *gw,
|
||||||
|
void *state, err_t (* init)(struct netif *netif),
|
||||||
|
err_t (* input)(struct pbuf *p, struct netif *netif))
|
||||||
|
|
||||||
|
Adds your network interface to the netif_list. Allocate a struct
|
||||||
|
netif and pass a pointer to this structure as the first argument.
|
||||||
|
Give pointers to cleared ip_addr structures when using DHCP,
|
||||||
|
or fill them with sane numbers otherwise. The state pointer may be NULL.
|
||||||
|
|
||||||
|
The init function pointer must point to a initialization function for
|
||||||
|
your ethernet netif interface. The following code illustrates it's use.
|
||||||
|
|
||||||
|
err_t netif_if_init(struct netif *netif)
|
||||||
|
{
|
||||||
|
u8_t i;
|
||||||
|
|
||||||
|
for(i = 0; i < 6; i++) netif->hwaddr[i] = some_eth_addr[i];
|
||||||
|
init_my_eth_device();
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
The input function pointer must point to the lwip ip_input().
|
||||||
|
|
||||||
|
- netif_set_default(struct netif *netif)
|
||||||
|
|
||||||
|
Registers the default network interface.
|
||||||
|
|
||||||
|
- netif_set_up(struct netif *netif)
|
||||||
|
|
||||||
|
When the netif is fully configured this function must be called.
|
||||||
|
|
||||||
|
- dhcp_start(struct netif *netif)
|
||||||
|
|
||||||
|
Creates a new DHCP client for this interface on the first call.
|
||||||
|
Note: you must call dhcp_fine_tmr() and dhcp_coarse_tmr() at
|
||||||
|
the predefined regular intervals after starting the client.
|
||||||
|
|
||||||
|
You can peek in the netif->dhcp struct for the actual DHCP status.
|
||||||
|
|||||||
@@ -15,20 +15,15 @@ Table of Contents:
|
|||||||
To perform an anonymous CVS checkout of the main trunk (this is where
|
To perform an anonymous CVS checkout of the main trunk (this is where
|
||||||
bug fixes and incremental enhancements occur), do this:
|
bug fixes and incremental enhancements occur), do this:
|
||||||
|
|
||||||
export CVS_RSH=ssh
|
cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout lwip
|
||||||
cvs -d:ext:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout lwip
|
|
||||||
|
|
||||||
(If SSH asks about authenticity of the host, you can check the key
|
|
||||||
fingerprint against http://savannah.nongnu.org/cvs/?group=lwip)
|
|
||||||
|
|
||||||
Or, obtain a stable branch (updated with bug fixes only) as follows:
|
Or, obtain a stable branch (updated with bug fixes only) as follows:
|
||||||
cvs -d:ext:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r STABLE-0_7 -d lwip-0.7 lwip
|
cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout \
|
||||||
|
-r STABLE-0_7 -d lwip-0.7 lwip
|
||||||
|
|
||||||
Or, obtain a specific (fixed) release as follows:
|
Or, obtain a specific (fixed) release as follows:
|
||||||
cvs -d:ext:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r STABLE-0_7_0 -d lwip-0.7.0 lwip
|
cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout \
|
||||||
|
-r STABLE-0_7_0 -d lwip-0.7.0 lwip
|
||||||
Or, obtain a development branch (considered unstable!) as follows:
|
|
||||||
cvs -d:ext:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r DEVEL -d lwip-DEVEL lwip
|
|
||||||
|
|
||||||
3 Committers/developers CVS access using SSH
|
3 Committers/developers CVS access using SSH
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
@@ -47,7 +42,7 @@ a while so that Savannah can update its configuration (This can take minutes).
|
|||||||
|
|
||||||
Try to login using SSH:
|
Try to login using SSH:
|
||||||
|
|
||||||
ssh -v your_login@subversions.gnu.org
|
ssh -v your_login@cvs.sv.gnu.org
|
||||||
|
|
||||||
If it tells you:
|
If it tells you:
|
||||||
|
|
||||||
@@ -58,12 +53,16 @@ then you could login; Savannah refuses to give you a shell - which is OK, as we
|
|||||||
are allowed to use SSH for CVS only. Now, you should be able to do this:
|
are allowed to use SSH for CVS only. Now, you should be able to do this:
|
||||||
|
|
||||||
export CVS_RSH=ssh
|
export CVS_RSH=ssh
|
||||||
cvs -d:ext:your_login@subversions.gnu.org:/cvsroot/lwip checkout lwip
|
cvs -z3 -d:ext:your_login@cvs.sv.gnu.org:/sources/lwip co lwip
|
||||||
|
|
||||||
after which you can edit your local files with bug fixes or new features and
|
after which you can edit your local files with bug fixes or new features and
|
||||||
commit them. Make sure you know what you are doing when using CVS to make
|
commit them. Make sure you know what you are doing when using CVS to make
|
||||||
changes on the repository. If in doubt, ask on the lwip-members mailing list.
|
changes on the repository. If in doubt, ask on the lwip-members mailing list.
|
||||||
|
|
||||||
|
(If SSH asks about authenticity of the host, you can check the key
|
||||||
|
fingerprint against http://savannah.nongnu.org/cvs/?group=lwip)
|
||||||
|
|
||||||
|
|
||||||
3 Merging from DEVEL branch to main trunk (stable)
|
3 Merging from DEVEL branch to main trunk (stable)
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
|
|
||||||
@@ -107,7 +106,8 @@ tagged tree. Export is similar to a checkout, except that the CVS metadata
|
|||||||
is not created locally.
|
is not created locally.
|
||||||
|
|
||||||
export CVS_RSH=ssh
|
export CVS_RSH=ssh
|
||||||
cvs -d:ext:anoncvs@subversions.gnu.org:/cvsroot/lwip export -r STABLE-0_6_3 -d lwip-0.6.3 lwip
|
cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout \
|
||||||
|
-r STABLE-0_6_3 -d lwip-0.6.3 lwip
|
||||||
|
|
||||||
Archive this directory using tar, gzip'd, bzip2'd and zip'd.
|
Archive this directory using tar, gzip'd, bzip2'd and zip'd.
|
||||||
|
|
||||||
|
|||||||
10
src/FILES
10
src/FILES
@@ -1,11 +1,13 @@
|
|||||||
api/ - The code for the API.
|
api/ - The code for the high-level wrapper API. Not needed if
|
||||||
|
you use the lowel-level call-back/raw API.
|
||||||
|
|
||||||
core/ - The core files including protocol implementations, memory
|
core/ - The core of the TPC/IP stack; protocol implementations,
|
||||||
and buffer management etc.
|
memory and buffer management, and the low-level raw API.
|
||||||
|
|
||||||
include/ - lwIP include files.
|
include/ - lwIP include files.
|
||||||
|
|
||||||
netif/ - Generic network interface device drivers are kept here.
|
netif/ - Generic network interface device drivers are kept here,
|
||||||
|
as well as the ARP module.
|
||||||
|
|
||||||
For more information on the various subdirectories, check the FILES
|
For more information on the various subdirectories, check the FILES
|
||||||
file in each directory.
|
file in each directory.
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t offset)
|
|||||||
offset -= p->len;
|
offset -= p->len;
|
||||||
} else {
|
} else {
|
||||||
for(i = offset; i < p->len; ++i) {
|
for(i = offset; i < p->len; ++i) {
|
||||||
((char *)dataptr)[left] = ((char *)p->payload)[i];
|
((u8_t *)dataptr)[left] = ((u8_t *)p->payload)[i];
|
||||||
if (++left >= len) {
|
if (++left >= len) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -673,7 +673,7 @@ netconn_write(struct netconn *conn, void *dataptr, u16_t size, u8_t copy)
|
|||||||
api_msg_post(msg);
|
api_msg_post(msg);
|
||||||
sys_mbox_fetch(conn->mbox, NULL);
|
sys_mbox_fetch(conn->mbox, NULL);
|
||||||
if (conn->err == ERR_OK) {
|
if (conn->err == ERR_OK) {
|
||||||
dataptr = (void *)((char *)dataptr + len);
|
dataptr = (void *)((u8_t *)dataptr + len);
|
||||||
size -= len;
|
size -= len;
|
||||||
} else if (conn->err == ERR_MEM) {
|
} else if (conn->err == ERR_MEM) {
|
||||||
conn->err = ERR_OK;
|
conn->err = ERR_OK;
|
||||||
|
|||||||
@@ -87,9 +87,12 @@ static int err_to_errno_table[11] = {
|
|||||||
EADDRINUSE /* ERR_USE -10 Address in use. */
|
EADDRINUSE /* ERR_USE -10 Address in use. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define ERR_TO_ERRNO_TABLE_SIZE \
|
||||||
|
(sizeof(err_to_errno_table)/sizeof(err_to_errno_table[0]))
|
||||||
|
|
||||||
#define err_to_errno(err) \
|
#define err_to_errno(err) \
|
||||||
((err) < (sizeof(err_to_errno_table)/sizeof(int))) ? \
|
(-(err) >= 0 && -(err) < ERR_TO_ERRNO_TABLE_SIZE ? \
|
||||||
err_to_errno_table[-(err)] : EIO
|
err_to_errno_table[-(err)] : EIO)
|
||||||
|
|
||||||
#ifdef ERRNO
|
#ifdef ERRNO
|
||||||
#define set_errno(err) errno = (err)
|
#define set_errno(err) errno = (err)
|
||||||
@@ -418,7 +421,7 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
|
|||||||
ip_addr_debug_print(SOCKETS_DEBUG, addr);
|
ip_addr_debug_print(SOCKETS_DEBUG, addr);
|
||||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen));
|
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen));
|
||||||
} else {
|
} else {
|
||||||
#if SOCKETS_DEBUG != 0
|
#if SOCKETS_DEBUG
|
||||||
addr = netbuf_fromaddr(buf);
|
addr = netbuf_fromaddr(buf);
|
||||||
port = netbuf_fromport(buf);
|
port = netbuf_fromport(buf);
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
#include "lwip/pbuf.h"
|
#include "lwip/pbuf.h"
|
||||||
|
|
||||||
#include "lwip/ip.h"
|
#include "lwip/ip.h"
|
||||||
|
#include "lwip/ip_frag.h"
|
||||||
#include "lwip/udp.h"
|
#include "lwip/udp.h"
|
||||||
#include "lwip/tcp.h"
|
#include "lwip/tcp.h"
|
||||||
|
|
||||||
@@ -46,11 +47,10 @@
|
|||||||
static void (* tcpip_init_done)(void *arg) = NULL;
|
static void (* tcpip_init_done)(void *arg) = NULL;
|
||||||
static void *tcpip_init_done_arg;
|
static void *tcpip_init_done_arg;
|
||||||
static sys_mbox_t mbox;
|
static sys_mbox_t mbox;
|
||||||
|
|
||||||
#if LWIP_TCP
|
#if LWIP_TCP
|
||||||
static int tcpip_tcp_timer_active = 0;
|
static int tcpip_tcp_timer_active = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
tcpip_tcp_timer(void *arg)
|
tcpip_tcp_timer(void *arg)
|
||||||
{
|
{
|
||||||
@@ -68,6 +68,7 @@ tcpip_tcp_timer(void *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !NO_SYS
|
||||||
void
|
void
|
||||||
tcp_timer_needed(void)
|
tcp_timer_needed(void)
|
||||||
{
|
{
|
||||||
@@ -78,8 +79,19 @@ tcp_timer_needed(void)
|
|||||||
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
|
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif /* !NO_SYS */
|
||||||
#endif /* LWIP_TCP */
|
#endif /* LWIP_TCP */
|
||||||
|
|
||||||
|
#if IP_REASSEMBLY
|
||||||
|
static void
|
||||||
|
ip_timer(void *data)
|
||||||
|
{
|
||||||
|
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: ip_reass_tmr()\n"));
|
||||||
|
ip_reass_tmr();
|
||||||
|
sys_timeout(1000, ip_timer, NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
tcpip_thread(void *arg)
|
tcpip_thread(void *arg)
|
||||||
{
|
{
|
||||||
@@ -93,6 +105,9 @@ tcpip_thread(void *arg)
|
|||||||
#endif
|
#endif
|
||||||
#if LWIP_TCP
|
#if LWIP_TCP
|
||||||
tcp_init();
|
tcp_init();
|
||||||
|
#endif
|
||||||
|
#if IP_REASSEMBLY
|
||||||
|
sys_timeout(1000, ip_timer, NULL);
|
||||||
#endif
|
#endif
|
||||||
if (tcpip_init_done != NULL) {
|
if (tcpip_init_done != NULL) {
|
||||||
tcpip_init_done(tcpip_init_done_arg);
|
tcpip_init_done(tcpip_init_done_arg);
|
||||||
|
|||||||
108
src/core/dhcp.c
108
src/core/dhcp.c
@@ -100,8 +100,7 @@ static void dhcp_check(struct netif *netif);
|
|||||||
static void dhcp_bind(struct netif *netif);
|
static void dhcp_bind(struct netif *netif);
|
||||||
static err_t dhcp_decline(struct netif *netif);
|
static err_t dhcp_decline(struct netif *netif);
|
||||||
static err_t dhcp_rebind(struct netif *netif);
|
static err_t dhcp_rebind(struct netif *netif);
|
||||||
static err_t dhcp_release(struct netif *netif);
|
static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state);
|
||||||
static void dhcp_set_state(struct dhcp *dhcp, unsigned char new_state);
|
|
||||||
|
|
||||||
/** receive, unfold, parse and free incoming messages */
|
/** receive, unfold, parse and free incoming messages */
|
||||||
static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port);
|
static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port);
|
||||||
@@ -145,10 +144,10 @@ static void dhcp_option_trailer(struct dhcp *dhcp);
|
|||||||
static void dhcp_handle_nak(struct netif *netif) {
|
static void dhcp_handle_nak(struct netif *netif) {
|
||||||
struct dhcp *dhcp = netif->dhcp;
|
struct dhcp *dhcp = netif->dhcp;
|
||||||
u16_t msecs = 10 * 1000;
|
u16_t msecs = 10 * 1000;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_handle_nak(netif=%p) %c%c%u\n", netif,
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n",
|
||||||
netif->name[0], netif->name[1], (unsigned int)netif->num));
|
(void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
|
||||||
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_handle_nak(): set request timeout %u msecs\n", msecs));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_handle_nak(): set request timeout %"U16_F" msecs\n", msecs));
|
||||||
dhcp_set_state(dhcp, DHCP_BACKING_OFF);
|
dhcp_set_state(dhcp, DHCP_BACKING_OFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,8 +163,8 @@ static void dhcp_check(struct netif *netif)
|
|||||||
struct dhcp *dhcp = netif->dhcp;
|
struct dhcp *dhcp = netif->dhcp;
|
||||||
err_t result;
|
err_t result;
|
||||||
u16_t msecs;
|
u16_t msecs;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (unsigned int)netif->name[0],
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0],
|
||||||
(unsigned int)netif->name[1]));
|
(s16_t)netif->name[1]));
|
||||||
/* create an ARP query for the offered IP address, expecting that no host
|
/* create an ARP query for the offered IP address, expecting that no host
|
||||||
responds, as the IP address should not be in use. */
|
responds, as the IP address should not be in use. */
|
||||||
result = etharp_query(netif, &dhcp->offered_ip_addr, NULL);
|
result = etharp_query(netif, &dhcp->offered_ip_addr, NULL);
|
||||||
@@ -175,7 +174,7 @@ static void dhcp_check(struct netif *netif)
|
|||||||
dhcp->tries++;
|
dhcp->tries++;
|
||||||
msecs = 500;
|
msecs = 500;
|
||||||
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_check(): set request timeout %u msecs\n", msecs));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_check(): set request timeout %"U16_F" msecs\n", msecs));
|
||||||
dhcp_set_state(dhcp, DHCP_CHECKING);
|
dhcp_set_state(dhcp, DHCP_CHECKING);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,15 +188,15 @@ static void dhcp_handle_offer(struct netif *netif)
|
|||||||
struct dhcp *dhcp = netif->dhcp;
|
struct dhcp *dhcp = netif->dhcp;
|
||||||
/* obtain the server address */
|
/* obtain the server address */
|
||||||
u8_t *option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_SERVER_ID);
|
u8_t *option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_SERVER_ID);
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_handle_offer(netif=%p) %c%c%u\n", netif,
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n",
|
||||||
netif->name[0], netif->name[1], netif->num));
|
(void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
|
||||||
if (option_ptr != NULL)
|
if (option_ptr != NULL)
|
||||||
{
|
{
|
||||||
dhcp->server_ip_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
|
dhcp->server_ip_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_handle_offer(): server 0x%08lx\n", dhcp->server_ip_addr.addr));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_handle_offer(): server 0x%08"X32_F"\n", dhcp->server_ip_addr.addr));
|
||||||
/* remember offered address */
|
/* remember offered address */
|
||||||
ip_addr_set(&dhcp->offered_ip_addr, (struct ip_addr *)&dhcp->msg_in->yiaddr);
|
ip_addr_set(&dhcp->offered_ip_addr, (struct ip_addr *)&dhcp->msg_in->yiaddr);
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08lx\n", dhcp->offered_ip_addr.addr));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08"X32_F"\n", dhcp->offered_ip_addr.addr));
|
||||||
|
|
||||||
dhcp_select(netif);
|
dhcp_select(netif);
|
||||||
}
|
}
|
||||||
@@ -216,7 +215,7 @@ static err_t dhcp_select(struct netif *netif)
|
|||||||
struct dhcp *dhcp = netif->dhcp;
|
struct dhcp *dhcp = netif->dhcp;
|
||||||
err_t result;
|
err_t result;
|
||||||
u32_t msecs;
|
u32_t msecs;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_select(netif=%p) %c%c%u\n", netif, netif->name[0], netif->name[1], netif->num));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_select(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
|
||||||
|
|
||||||
/* create and initialize the DHCP message header */
|
/* create and initialize the DHCP message header */
|
||||||
result = dhcp_create_request(netif);
|
result = dhcp_create_request(netif);
|
||||||
@@ -262,7 +261,7 @@ static err_t dhcp_select(struct netif *netif)
|
|||||||
dhcp->tries++;
|
dhcp->tries++;
|
||||||
msecs = dhcp->tries < 4 ? dhcp->tries * 1000 : 4 * 1000;
|
msecs = dhcp->tries < 4 ? dhcp->tries * 1000 : 4 * 1000;
|
||||||
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_select(): set request timeout %u msecs\n", msecs));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_select(): set request timeout %"U32_F" msecs\n", msecs));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -520,7 +519,7 @@ err_t dhcp_start(struct netif *netif)
|
|||||||
err_t result = ERR_OK;
|
err_t result = ERR_OK;
|
||||||
|
|
||||||
LWIP_ASSERT("netif != NULL", netif != NULL);
|
LWIP_ASSERT("netif != NULL", netif != NULL);
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_start(netif=%p) %c%c%u\n", netif, netif->name[0], netif->name[1], netif->num));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
|
||||||
netif->flags &= ~NETIF_FLAG_DHCP;
|
netif->flags &= ~NETIF_FLAG_DHCP;
|
||||||
|
|
||||||
/* no DHCP client attached yet? */
|
/* no DHCP client attached yet? */
|
||||||
@@ -634,10 +633,11 @@ void dhcp_inform(struct netif *netif)
|
|||||||
*/
|
*/
|
||||||
void dhcp_arp_reply(struct netif *netif, struct ip_addr *addr)
|
void dhcp_arp_reply(struct netif *netif, struct ip_addr *addr)
|
||||||
{
|
{
|
||||||
|
LWIP_ASSERT("netif != NULL", netif != NULL);
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_arp_reply()\n"));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_arp_reply()\n"));
|
||||||
/* is this DHCP client doing an ARP check? */
|
/* is a DHCP client doing an ARP check? */
|
||||||
if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_CHECKING)) {
|
if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_CHECKING)) {
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08lx\n", addr->addr));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n", addr->addr));
|
||||||
/* did a host respond with the address we
|
/* did a host respond with the address we
|
||||||
were offered by the DHCP server? */
|
were offered by the DHCP server? */
|
||||||
if (ip_addr_cmp(addr, &netif->dhcp->offered_ip_addr)) {
|
if (ip_addr_cmp(addr, &netif->dhcp->offered_ip_addr)) {
|
||||||
@@ -680,8 +680,10 @@ static err_t dhcp_decline(struct netif *netif)
|
|||||||
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
|
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
|
||||||
|
|
||||||
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
|
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
|
||||||
udp_connect(dhcp->pcb, &dhcp->server_ip_addr, DHCP_SERVER_PORT);
|
/* @todo: should we really connect here? we are performing sendto() */
|
||||||
udp_send(dhcp->pcb, dhcp->p_out);
|
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
|
||||||
|
/* per section 4.4.4, broadcast DECLINE messages */
|
||||||
|
udp_sendto(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
|
||||||
dhcp_delete_request(netif);
|
dhcp_delete_request(netif);
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_decline: BACKING OFF\n"));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_decline: BACKING OFF\n"));
|
||||||
} else {
|
} else {
|
||||||
@@ -690,7 +692,7 @@ static err_t dhcp_decline(struct netif *netif)
|
|||||||
dhcp->tries++;
|
dhcp->tries++;
|
||||||
msecs = 10*1000;
|
msecs = 10*1000;
|
||||||
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_decline(): set request timeout %u msecs\n", msecs));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_decline(): set request timeout %"U16_F" msecs\n", msecs));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -745,7 +747,7 @@ static err_t dhcp_discover(struct netif *netif)
|
|||||||
dhcp->tries++;
|
dhcp->tries++;
|
||||||
msecs = dhcp->tries < 4 ? (dhcp->tries + 1) * 1000 : 10 * 1000;
|
msecs = dhcp->tries < 4 ? (dhcp->tries + 1) * 1000 : 10 * 1000;
|
||||||
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_discover(): set request timeout %u msecs\n", msecs));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_discover(): set request timeout %"U16_F" msecs\n", msecs));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -761,22 +763,22 @@ static void dhcp_bind(struct netif *netif)
|
|||||||
struct ip_addr sn_mask, gw_addr;
|
struct ip_addr sn_mask, gw_addr;
|
||||||
LWIP_ASSERT("dhcp_bind: netif != NULL", netif != NULL);
|
LWIP_ASSERT("dhcp_bind: netif != NULL", netif != NULL);
|
||||||
LWIP_ASSERT("dhcp_bind: dhcp != NULL", dhcp != NULL);
|
LWIP_ASSERT("dhcp_bind: dhcp != NULL", dhcp != NULL);
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_bind(netif=%p) %c%c%u\n", netif, netif->name[0], netif->name[1], netif->num));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_bind(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
|
||||||
|
|
||||||
/* temporary DHCP lease? */
|
/* temporary DHCP lease? */
|
||||||
if (dhcp->offered_t1_renew != 0xffffffffUL) {
|
if (dhcp->offered_t1_renew != 0xffffffffUL) {
|
||||||
/* set renewal period timer */
|
/* set renewal period timer */
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_bind(): t1 renewal timer %lu secs\n", dhcp->offered_t1_renew));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_bind(): t1 renewal timer %"U32_F" secs\n", dhcp->offered_t1_renew));
|
||||||
dhcp->t1_timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
|
dhcp->t1_timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
|
||||||
if (dhcp->t1_timeout == 0) dhcp->t1_timeout = 1;
|
if (dhcp->t1_timeout == 0) dhcp->t1_timeout = 1;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_bind(): set request timeout %u msecs\n", dhcp->offered_t1_renew*1000));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t1_renew*1000));
|
||||||
}
|
}
|
||||||
/* set renewal period timer */
|
/* set renewal period timer */
|
||||||
if (dhcp->offered_t2_rebind != 0xffffffffUL) {
|
if (dhcp->offered_t2_rebind != 0xffffffffUL) {
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_bind(): t2 rebind timer %lu secs\n", dhcp->offered_t2_rebind));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_bind(): t2 rebind timer %"U32_F" secs\n", dhcp->offered_t2_rebind));
|
||||||
dhcp->t2_timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
|
dhcp->t2_timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
|
||||||
if (dhcp->t2_timeout == 0) dhcp->t2_timeout = 1;
|
if (dhcp->t2_timeout == 0) dhcp->t2_timeout = 1;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_bind(): set request timeout %u msecs\n", dhcp->offered_t2_rebind*1000));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t2_rebind*1000));
|
||||||
}
|
}
|
||||||
/* copy offered network mask */
|
/* copy offered network mask */
|
||||||
ip_addr_set(&sn_mask, &dhcp->offered_sn_mask);
|
ip_addr_set(&sn_mask, &dhcp->offered_sn_mask);
|
||||||
@@ -800,11 +802,11 @@ static void dhcp_bind(struct netif *netif)
|
|||||||
gw_addr.addr |= htonl(0x00000001);
|
gw_addr.addr |= htonl(0x00000001);
|
||||||
}
|
}
|
||||||
|
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): IP: 0x%08lx\n", dhcp->offered_ip_addr.addr));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): IP: 0x%08"X32_F"\n", dhcp->offered_ip_addr.addr));
|
||||||
netif_set_ipaddr(netif, &dhcp->offered_ip_addr);
|
netif_set_ipaddr(netif, &dhcp->offered_ip_addr);
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): SN: 0x%08lx\n", sn_mask.addr));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): SN: 0x%08"X32_F"\n", sn_mask.addr));
|
||||||
netif_set_netmask(netif, &sn_mask);
|
netif_set_netmask(netif, &sn_mask);
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): GW: 0x%08lx\n", gw_addr.addr));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): GW: 0x%08"X32_F"\n", gw_addr.addr));
|
||||||
netif_set_gw(netif, &gw_addr);
|
netif_set_gw(netif, &gw_addr);
|
||||||
/* bring the interface up */
|
/* bring the interface up */
|
||||||
netif_set_up(netif);
|
netif_set_up(netif);
|
||||||
@@ -863,7 +865,7 @@ err_t dhcp_renew(struct netif *netif)
|
|||||||
/* back-off on retries, but to a maximum of 20 seconds */
|
/* back-off on retries, but to a maximum of 20 seconds */
|
||||||
msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000;
|
msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000;
|
||||||
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_renew(): set request timeout %u msecs\n", msecs));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_renew(): set request timeout %"U16_F" msecs\n", msecs));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -916,7 +918,7 @@ static err_t dhcp_rebind(struct netif *netif)
|
|||||||
dhcp->tries++;
|
dhcp->tries++;
|
||||||
msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
|
msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
|
||||||
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_rebind(): set request timeout %u msecs\n", msecs));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_rebind(): set request timeout %"U16_F" msecs\n", msecs));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -925,7 +927,7 @@ static err_t dhcp_rebind(struct netif *netif)
|
|||||||
*
|
*
|
||||||
* @param netif network interface which must release its lease
|
* @param netif network interface which must release its lease
|
||||||
*/
|
*/
|
||||||
static err_t dhcp_release(struct netif *netif)
|
err_t dhcp_release(struct netif *netif)
|
||||||
{
|
{
|
||||||
struct dhcp *dhcp = netif->dhcp;
|
struct dhcp *dhcp = netif->dhcp;
|
||||||
err_t result;
|
err_t result;
|
||||||
@@ -962,7 +964,7 @@ static err_t dhcp_release(struct netif *netif)
|
|||||||
dhcp->tries++;
|
dhcp->tries++;
|
||||||
msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
|
msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
|
||||||
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_release(): set request timeout %u msecs\n", msecs));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_release(): set request timeout %"U16_F" msecs\n", msecs));
|
||||||
/* bring the interface down */
|
/* bring the interface down */
|
||||||
netif_set_down(netif);
|
netif_set_down(netif);
|
||||||
/* remove IP address from interface */
|
/* remove IP address from interface */
|
||||||
@@ -1011,7 +1013,7 @@ void dhcp_stop(struct netif *netif)
|
|||||||
*
|
*
|
||||||
* TODO: we might also want to reset the timeout here?
|
* TODO: we might also want to reset the timeout here?
|
||||||
*/
|
*/
|
||||||
static void dhcp_set_state(struct dhcp *dhcp, unsigned char new_state)
|
static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state)
|
||||||
{
|
{
|
||||||
if (new_state != dhcp->state)
|
if (new_state != dhcp->state)
|
||||||
{
|
{
|
||||||
@@ -1107,7 +1109,7 @@ static err_t dhcp_unfold_reply(struct dhcp *dhcp)
|
|||||||
j = 0;
|
j = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_unfold_reply(): copied %u bytes into dhcp->msg_in[]\n", i));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_unfold_reply(): copied %"U16_F" bytes into dhcp->msg_in[]\n", i));
|
||||||
if (dhcp->options_in != NULL) {
|
if (dhcp->options_in != NULL) {
|
||||||
ptr = (u8_t *)dhcp->options_in;
|
ptr = (u8_t *)dhcp->options_in;
|
||||||
/* proceed through options */
|
/* proceed through options */
|
||||||
@@ -1120,7 +1122,7 @@ static err_t dhcp_unfold_reply(struct dhcp *dhcp)
|
|||||||
j = 0;
|
j = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_unfold_reply(): copied %u bytes to dhcp->options_in[]\n", i));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_unfold_reply(): copied %"U16_F" bytes to dhcp->options_in[]\n", i));
|
||||||
}
|
}
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
@@ -1156,17 +1158,17 @@ static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_
|
|||||||
u8_t *options_ptr;
|
u8_t *options_ptr;
|
||||||
u8_t msg_type;
|
u8_t msg_type;
|
||||||
u8_t i;
|
u8_t i;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_recv(pbuf = %p) from DHCP server %u.%u.%u.%u port %u\n", p,
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_recv(pbuf = %p) from DHCP server %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void*)p,
|
||||||
(unsigned int)(ntohl(addr->addr) >> 24 & 0xff), (unsigned int)(ntohl(addr->addr) >> 16 & 0xff),
|
(u16_t)(ntohl(addr->addr) >> 24 & 0xff), (u16_t)(ntohl(addr->addr) >> 16 & 0xff),
|
||||||
(unsigned int)(ntohl(addr->addr) >> 8 & 0xff), (unsigned int)(ntohl(addr->addr) & 0xff), port));
|
(u16_t)(ntohl(addr->addr) >> 8 & 0xff), (u16_t)(ntohl(addr->addr) & 0xff), port));
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("pbuf->len = %u\n", p->len));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len));
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("pbuf->tot_len = %u\n", p->tot_len));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("pbuf->tot_len = %"U16_F"\n", p->tot_len));
|
||||||
/* prevent warnings about unused arguments */
|
/* prevent warnings about unused arguments */
|
||||||
(void)pcb; (void)addr; (void)port;
|
(void)pcb; (void)addr; (void)port;
|
||||||
dhcp->p = p;
|
dhcp->p = p;
|
||||||
/* TODO: check packet length before reading them */
|
/* TODO: check packet length before reading them */
|
||||||
if (reply_msg->op != DHCP_BOOTREPLY) {
|
if (reply_msg->op != DHCP_BOOTREPLY) {
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("not a DHCP reply message, but type %u\n", reply_msg->op));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("not a DHCP reply message, but type %"U16_F"\n", (u16_t)reply_msg->op));
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
dhcp->p = NULL;
|
dhcp->p = NULL;
|
||||||
return;
|
return;
|
||||||
@@ -1174,8 +1176,8 @@ static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_
|
|||||||
/* iterate through hardware address and match against DHCP message */
|
/* iterate through hardware address and match against DHCP message */
|
||||||
for (i = 0; i < netif->hwaddr_len; i++) {
|
for (i = 0; i < netif->hwaddr_len; i++) {
|
||||||
if (netif->hwaddr[i] != reply_msg->chaddr[i]) {
|
if (netif->hwaddr[i] != reply_msg->chaddr[i]) {
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("netif->hwaddr[%u]==%02x != reply_msg->chaddr[%u]==%02x\n",
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n",
|
||||||
i, netif->hwaddr[i], i, reply_msg->chaddr[i]));
|
(u16_t)i, (u16_t)netif->hwaddr[i], (u16_t)i, (u16_t)reply_msg->chaddr[i]));
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
dhcp->p = NULL;
|
dhcp->p = NULL;
|
||||||
return;
|
return;
|
||||||
@@ -1315,7 +1317,7 @@ static void dhcp_option_trailer(struct dhcp *dhcp)
|
|||||||
dhcp->msg_out->options[dhcp->options_out_len++] = DHCP_OPTION_END;
|
dhcp->msg_out->options[dhcp->options_out_len++] = DHCP_OPTION_END;
|
||||||
/* packet is too small, or not 4 byte aligned? */
|
/* packet is too small, or not 4 byte aligned? */
|
||||||
while ((dhcp->options_out_len < DHCP_MIN_OPTIONS_LEN) || (dhcp->options_out_len & 3)) {
|
while ((dhcp->options_out_len < DHCP_MIN_OPTIONS_LEN) || (dhcp->options_out_len & 3)) {
|
||||||
/* LWIP_DEBUGF(DHCP_DEBUG, ("dhcp_option_trailer: dhcp->options_out_len=%u, DHCP_OPTIONS_LEN=%u", dhcp->options_out_len, DHCP_OPTIONS_LEN)); */
|
/* LWIP_DEBUGF(DHCP_DEBUG,("dhcp_option_trailer:dhcp->options_out_len=%"U16_F", DHCP_OPTIONS_LEN=%"U16_F, dhcp->options_out_len, DHCP_OPTIONS_LEN)); */
|
||||||
LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN);
|
LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN);
|
||||||
/* add a fill/padding byte */
|
/* add a fill/padding byte */
|
||||||
dhcp->msg_out->options[dhcp->options_out_len++] = 0;
|
dhcp->msg_out->options[dhcp->options_out_len++] = 0;
|
||||||
@@ -1342,7 +1344,7 @@ static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type)
|
|||||||
u16_t offset = 0;
|
u16_t offset = 0;
|
||||||
/* at least 1 byte to read and no end marker, then at least 3 bytes to read? */
|
/* at least 1 byte to read and no end marker, then at least 3 bytes to read? */
|
||||||
while ((offset < dhcp->options_in_len) && (options[offset] != DHCP_OPTION_END)) {
|
while ((offset < dhcp->options_in_len) && (options[offset] != DHCP_OPTION_END)) {
|
||||||
/* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%u, q->len=%u", msg_offset, q->len)); */
|
/* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */
|
||||||
/* are the sname and/or file field overloaded with options? */
|
/* are the sname and/or file field overloaded with options? */
|
||||||
if (options[offset] == DHCP_OPTION_OVERLOAD) {
|
if (options[offset] == DHCP_OPTION_OVERLOAD) {
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("overloaded message detected\n"));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("overloaded message detected\n"));
|
||||||
@@ -1352,11 +1354,11 @@ static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type)
|
|||||||
}
|
}
|
||||||
/* requested option found */
|
/* requested option found */
|
||||||
else if (options[offset] == option_type) {
|
else if (options[offset] == option_type) {
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("option found at offset %u in options\n", offset));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("option found at offset %"U16_F" in options\n", offset));
|
||||||
return &options[offset];
|
return &options[offset];
|
||||||
/* skip option */
|
/* skip option */
|
||||||
} else {
|
} else {
|
||||||
LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %u in options\n", options[offset]));
|
LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %"U16_F" in options\n", options[offset]));
|
||||||
/* skip option type */
|
/* skip option type */
|
||||||
offset++;
|
offset++;
|
||||||
/* skip option length, and then length bytes */
|
/* skip option length, and then length bytes */
|
||||||
@@ -1385,11 +1387,11 @@ static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type)
|
|||||||
/* at least 1 byte to read and no end marker */
|
/* at least 1 byte to read and no end marker */
|
||||||
while ((offset < field_len) && (options[offset] != DHCP_OPTION_END)) {
|
while ((offset < field_len) && (options[offset] != DHCP_OPTION_END)) {
|
||||||
if (options[offset] == option_type) {
|
if (options[offset] == option_type) {
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("option found at offset=%u\n", offset));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("option found at offset=%"U16_F"\n", offset));
|
||||||
return &options[offset];
|
return &options[offset];
|
||||||
/* skip option */
|
/* skip option */
|
||||||
} else {
|
} else {
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("skipping option %u\n", options[offset]));
|
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("skipping option %"U16_F"\n", options[offset]));
|
||||||
/* skip option type */
|
/* skip option type */
|
||||||
offset++;
|
offset++;
|
||||||
offset += 1 + options[offset];
|
offset += 1 + options[offset];
|
||||||
@@ -1410,7 +1412,7 @@ static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type)
|
|||||||
*/
|
*/
|
||||||
static u8_t dhcp_get_option_byte(u8_t *ptr)
|
static u8_t dhcp_get_option_byte(u8_t *ptr)
|
||||||
{
|
{
|
||||||
LWIP_DEBUGF(DHCP_DEBUG, ("option byte value=%u\n", *ptr));
|
LWIP_DEBUGF(DHCP_DEBUG, ("option byte value=%"U16_F"\n", (u16_t)(*ptr)));
|
||||||
return *ptr;
|
return *ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1427,7 +1429,7 @@ static u16_t dhcp_get_option_short(u8_t *ptr)
|
|||||||
u16_t value;
|
u16_t value;
|
||||||
value = *ptr++ << 8;
|
value = *ptr++ << 8;
|
||||||
value |= *ptr;
|
value |= *ptr;
|
||||||
LWIP_DEBUGF(DHCP_DEBUG, ("option short value=%u\n", value));
|
LWIP_DEBUGF(DHCP_DEBUG, ("option short value=%"U16_F"\n", value));
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1446,7 +1448,7 @@ static u32_t dhcp_get_option_long(u8_t *ptr)
|
|||||||
value |= (u32_t)(*ptr++) << 16;
|
value |= (u32_t)(*ptr++) << 16;
|
||||||
value |= (u32_t)(*ptr++) << 8;
|
value |= (u32_t)(*ptr++) << 8;
|
||||||
value |= (u32_t)(*ptr++);
|
value |= (u32_t)(*ptr++);
|
||||||
LWIP_DEBUGF(DHCP_DEBUG, ("option long value=%lu\n", value));
|
LWIP_DEBUGF(DHCP_DEBUG, ("option long value=%"U32_F"\n", value));
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
212
src/core/inet.c
212
src/core/inet.c
@@ -48,43 +48,190 @@
|
|||||||
|
|
||||||
#include "lwip/sys.h"
|
#include "lwip/sys.h"
|
||||||
|
|
||||||
/* This is a reference implementation of the checksum algorithm
|
/* This is a reference implementation of the checksum algorithm, with the
|
||||||
|
* aim of being simple, correct and fully portable. Checksumming is the
|
||||||
- it may not work on all architectures, and all processors, particularly
|
* first thing you would want to optimize for your platform. You will
|
||||||
if they have issues with alignment and 16 bit access.
|
* need to port it to your architecture and in your sys_arch.h:
|
||||||
|
*
|
||||||
- in this case you will need to port it to your architecture and
|
* #define LWIP_CHKSUM <your_checksum_routine>
|
||||||
#define LWIP_CHKSUM <your_checksum_routine>
|
|
||||||
in your sys_arch.h
|
|
||||||
*/
|
*/
|
||||||
#ifndef LWIP_CHKSUM
|
#ifndef LWIP_CHKSUM
|
||||||
#define LWIP_CHKSUM lwip_standard_chksum
|
#define LWIP_CHKSUM lwip_standard_chksum
|
||||||
|
|
||||||
|
/**
|
||||||
|
* lwip checksum
|
||||||
|
*
|
||||||
|
* @param dataptr points to start of data to be summed at any boundary
|
||||||
|
* @param len length of data to be summed
|
||||||
|
* @return host order (!) lwip checksum (non-inverted Internet sum)
|
||||||
|
*
|
||||||
|
* @note accumulator size limits summable lenght to 64k
|
||||||
|
* @note host endianess is irrelevant (p3 RFC1071)
|
||||||
|
*/
|
||||||
static u16_t
|
static u16_t
|
||||||
lwip_standard_chksum(void *dataptr, int len)
|
lwip_standard_chksum(void *dataptr, u16_t len)
|
||||||
{
|
{
|
||||||
u32_t acc;
|
u32_t acc;
|
||||||
|
u16_t src;
|
||||||
|
u8_t *octetptr;
|
||||||
|
|
||||||
LWIP_DEBUGF(INET_DEBUG, ("lwip_chksum(%p, %d)\n", (void *)dataptr, len));
|
acc = 0;
|
||||||
for(acc = 0; len > 1; len -= 2) {
|
/* dataptr may be at odd or even addresses */
|
||||||
/* acc = acc + *((u16_t *)dataptr)++;*/
|
octetptr = (u8_t*)dataptr;
|
||||||
acc += *(u16_t *)dataptr;
|
while (len > 1)
|
||||||
dataptr = (void *)((u16_t *)dataptr + 1);
|
{
|
||||||
|
/* declare first octet as most significant
|
||||||
|
thus assume network order, ignoring host order */
|
||||||
|
src = (*octetptr) << 8;
|
||||||
|
octetptr++;
|
||||||
|
/* declare second octet as least significant */
|
||||||
|
src |= (*octetptr);
|
||||||
|
octetptr++;
|
||||||
|
acc += src;
|
||||||
|
len -= 2;
|
||||||
}
|
}
|
||||||
|
if (len > 0)
|
||||||
/* add up any odd byte */
|
{
|
||||||
if (len == 1) {
|
/* accumulate remaining octet */
|
||||||
acc += htons((u16_t)((*(u8_t *)dataptr) & 0xff) << 8);
|
src = (*octetptr) << 8;
|
||||||
LWIP_DEBUGF(INET_DEBUG, ("inet: chksum: odd byte %d\n", (unsigned int)(*(u8_t *)dataptr)));
|
acc += src;
|
||||||
} else {
|
|
||||||
LWIP_DEBUGF(INET_DEBUG, ("inet: chksum: no odd byte\n"));
|
|
||||||
}
|
}
|
||||||
acc = (acc >> 16) + (acc & 0xffffUL);
|
/* add deferred carry bits */
|
||||||
|
acc = (acc >> 16) + (acc & 0x0000ffffUL);
|
||||||
if ((acc & 0xffff0000) != 0) {
|
if ((acc & 0xffff0000) != 0) {
|
||||||
acc = (acc >> 16) + (acc & 0xffffUL);
|
acc = (acc >> 16) + (acc & 0x0000ffffUL);
|
||||||
|
}
|
||||||
|
/* This maybe a little confusing: reorder sum using htons()
|
||||||
|
instead of ntohs() since it has a little less call overhead.
|
||||||
|
The caller must invert bits for Internet sum ! */
|
||||||
|
return htons((u16_t)acc);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* Curt McDowell
|
||||||
|
* Broadcom Corp.
|
||||||
|
* csm@broadcom.com
|
||||||
|
*
|
||||||
|
* IP checksum two bytes at a time with support for
|
||||||
|
* unaligned buffer.
|
||||||
|
* Works for len up to and including 0x20000.
|
||||||
|
* by Curt McDowell, Broadcom Corp. 12/08/2005
|
||||||
|
*/
|
||||||
|
|
||||||
|
static u16_t
|
||||||
|
lwip_standard_chksum2(void *dataptr, int len)
|
||||||
|
{
|
||||||
|
u8_t *pb = dataptr;
|
||||||
|
u16_t *ps, t = 0;
|
||||||
|
u32_t sum = 0;
|
||||||
|
int odd = ((u32_t)pb & 1);
|
||||||
|
|
||||||
|
/* Get aligned to u16_t */
|
||||||
|
if (odd && len > 0) {
|
||||||
|
((u8_t *)&t)[1] = *pb++;
|
||||||
|
len--;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (u16_t)acc;
|
/* Add the bulk of the data */
|
||||||
|
ps = (u16_t *)pb;
|
||||||
|
while (len > 1) {
|
||||||
|
sum += *ps++;
|
||||||
|
len -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Consume left-over byte, if any */
|
||||||
|
if (len > 0)
|
||||||
|
((u8_t *)&t)[0] = *(u8_t *)ps;;
|
||||||
|
|
||||||
|
/* Add end bytes */
|
||||||
|
sum += t;
|
||||||
|
|
||||||
|
/* Fold 32-bit sum to 16 bits */
|
||||||
|
while (sum >> 16)
|
||||||
|
sum = (sum & 0xffff) + (sum >> 16);
|
||||||
|
|
||||||
|
/* Swap if alignment was odd */
|
||||||
|
if (odd)
|
||||||
|
sum = ((sum & 0xff) << 8) | ((sum & 0xff00) >> 8);
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An optimized checksum routine. Basically, it uses loop-unrolling on
|
||||||
|
* the checksum loop, treating the head and tail bytes specially, whereas
|
||||||
|
* the inner loop acts on 8 bytes at a time.
|
||||||
|
*
|
||||||
|
* @arg start of buffer to be checksummed. May be an odd byte address.
|
||||||
|
* @len number of bytes in the buffer to be checksummed.
|
||||||
|
*
|
||||||
|
* @todo First argument type conflicts with generic checksum routine.
|
||||||
|
*
|
||||||
|
* by Curt McDowell, Broadcom Corp. December 8th, 2005
|
||||||
|
*/
|
||||||
|
|
||||||
|
static u16_t
|
||||||
|
lwip_standard_chksum4(u8_t *pb, int len)
|
||||||
|
{
|
||||||
|
u16_t *ps, t = 0;
|
||||||
|
u32_t *pl;
|
||||||
|
u32_t sum = 0, tmp;
|
||||||
|
/* starts at odd byte address? */
|
||||||
|
int odd = ((u32_t)pb & 1);
|
||||||
|
|
||||||
|
if (odd && len > 0) {
|
||||||
|
((u8_t *)&t)[1] = *pb++;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
ps = (u16_t *)pb;
|
||||||
|
|
||||||
|
if (((u32_t)ps & 3) && len > 1) {
|
||||||
|
sum += *ps++;
|
||||||
|
len -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
pl = (u32_t *)ps;
|
||||||
|
|
||||||
|
while (len > 7) {
|
||||||
|
tmp = sum + *pl++; /* ping */
|
||||||
|
if (tmp < sum)
|
||||||
|
tmp++; /* add back carry */
|
||||||
|
|
||||||
|
sum = tmp + *pl++; /* pong */
|
||||||
|
if (sum < tmp)
|
||||||
|
sum++; /* add back carry */
|
||||||
|
|
||||||
|
len -= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make room in upper bits */
|
||||||
|
sum = (sum >> 16) + (sum & 0xffff);
|
||||||
|
|
||||||
|
ps = (u16_t *)pl;
|
||||||
|
|
||||||
|
/* 16-bit aligned word remaining? */
|
||||||
|
while (len > 1) {
|
||||||
|
sum += *ps++;
|
||||||
|
len -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dangling tail byte remaining? */
|
||||||
|
if (len > 0) /* include odd byte */
|
||||||
|
((u8_t *)&t)[0] = *(u8_t *)ps;
|
||||||
|
|
||||||
|
sum += t; /* add end bytes */
|
||||||
|
|
||||||
|
while (sum >> 16) /* combine halves */
|
||||||
|
sum = (sum >> 16) + (sum & 0xffff);
|
||||||
|
|
||||||
|
if (odd)
|
||||||
|
sum = ((sum & 0xff) << 8) | ((sum & 0xff00) >> 8);
|
||||||
|
|
||||||
|
return sum;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -109,7 +256,7 @@ inet_chksum_pseudo(struct pbuf *p,
|
|||||||
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
|
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
|
||||||
(void *)q, (void *)q->next));
|
(void *)q, (void *)q->next));
|
||||||
acc += LWIP_CHKSUM(q->payload, q->len);
|
acc += LWIP_CHKSUM(q->payload, q->len);
|
||||||
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%lx \n", acc));*/
|
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/
|
||||||
while (acc >> 16) {
|
while (acc >> 16) {
|
||||||
acc = (acc & 0xffffUL) + (acc >> 16);
|
acc = (acc & 0xffffUL) + (acc >> 16);
|
||||||
}
|
}
|
||||||
@@ -117,7 +264,7 @@ inet_chksum_pseudo(struct pbuf *p,
|
|||||||
swapped = 1 - swapped;
|
swapped = 1 - swapped;
|
||||||
acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
|
acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
|
||||||
}
|
}
|
||||||
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%lx \n", acc));*/
|
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/
|
||||||
}
|
}
|
||||||
|
|
||||||
if (swapped) {
|
if (swapped) {
|
||||||
@@ -133,7 +280,7 @@ inet_chksum_pseudo(struct pbuf *p,
|
|||||||
while (acc >> 16) {
|
while (acc >> 16) {
|
||||||
acc = (acc & 0xffffUL) + (acc >> 16);
|
acc = (acc & 0xffffUL) + (acc >> 16);
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%lx\n", acc));
|
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
|
||||||
return (u16_t)~(acc & 0xffffUL);
|
return (u16_t)~(acc & 0xffffUL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,10 +365,11 @@ inet_chksum_pbuf(struct pbuf *p)
|
|||||||
*/
|
*/
|
||||||
/* */
|
/* */
|
||||||
/* inet_aton */
|
/* inet_aton */
|
||||||
int inet_aton(const char *cp, struct in_addr *addr)
|
s8_t
|
||||||
|
inet_aton(const char *cp, struct in_addr *addr)
|
||||||
{
|
{
|
||||||
u32_t val;
|
u32_t val;
|
||||||
int base, n;
|
s32_t base, n;
|
||||||
char c;
|
char c;
|
||||||
u32_t parts[4];
|
u32_t parts[4];
|
||||||
u32_t* pp = parts;
|
u32_t* pp = parts;
|
||||||
@@ -245,11 +393,11 @@ inet_chksum_pbuf(struct pbuf *p)
|
|||||||
}
|
}
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (isdigit(c)) {
|
if (isdigit(c)) {
|
||||||
val = (val * base) + (int)(c - '0');
|
val = (val * base) + (s16_t)(c - '0');
|
||||||
c = *++cp;
|
c = *++cp;
|
||||||
} else if (base == 16 && isxdigit(c)) {
|
} else if (base == 16 && isxdigit(c)) {
|
||||||
val = (val << 4) |
|
val = (val << 4) |
|
||||||
(int)(c + 10 - (islower(c) ? 'a' : 'A'));
|
(s16_t)(c + 10 - (islower(c) ? 'a' : 'A'));
|
||||||
c = *++cp;
|
c = *++cp;
|
||||||
} else
|
} else
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -33,22 +33,21 @@
|
|||||||
/* Some ICMP messages should be passed to the transport protocols. This
|
/* Some ICMP messages should be passed to the transport protocols. This
|
||||||
is not implemented. */
|
is not implemented. */
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "lwip/opt.h"
|
||||||
#include "lwip/icmp.h"
|
#include "lwip/icmp.h"
|
||||||
#include "lwip/inet.h"
|
#include "lwip/inet.h"
|
||||||
#include "lwip/ip.h"
|
#include "lwip/ip.h"
|
||||||
#include "lwip/def.h"
|
#include "lwip/def.h"
|
||||||
|
|
||||||
#include "lwip/stats.h"
|
#include "lwip/stats.h"
|
||||||
|
|
||||||
#include "lwip/snmp.h"
|
#include "lwip/snmp.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
icmp_input(struct pbuf *p, struct netif *inp)
|
icmp_input(struct pbuf *p, struct netif *inp)
|
||||||
{
|
{
|
||||||
unsigned char type;
|
u8_t type;
|
||||||
unsigned char code;
|
u8_t code;
|
||||||
struct icmp_echo_hdr *iecho;
|
struct icmp_echo_hdr *iecho;
|
||||||
struct ip_hdr *iphdr;
|
struct ip_hdr *iphdr;
|
||||||
struct ip_addr tmpaddr;
|
struct ip_addr tmpaddr;
|
||||||
@@ -61,7 +60,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||||||
iphdr = p->payload;
|
iphdr = p->payload;
|
||||||
hlen = IPH_HL(iphdr) * 4;
|
hlen = IPH_HL(iphdr) * 4;
|
||||||
if (pbuf_header(p, -((s16_t)hlen)) || (p->tot_len < sizeof(u16_t)*2)) {
|
if (pbuf_header(p, -((s16_t)hlen)) || (p->tot_len < sizeof(u16_t)*2)) {
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%u bytes) received\n", p->tot_len));
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len));
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
ICMP_STATS_INC(icmp.lenerr);
|
ICMP_STATS_INC(icmp.lenerr);
|
||||||
snmp_inc_icmpinerrors();
|
snmp_inc_icmpinerrors();
|
||||||
@@ -74,7 +73,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||||||
case ICMP_ECHO:
|
case ICMP_ECHO:
|
||||||
/* broadcast or multicast destination address? */
|
/* broadcast or multicast destination address? */
|
||||||
if (ip_addr_isbroadcast(&iphdr->dest, inp) || ip_addr_ismulticast(&iphdr->dest)) {
|
if (ip_addr_isbroadcast(&iphdr->dest, inp) || ip_addr_ismulticast(&iphdr->dest)) {
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("Smurf.\n"));
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast or broadcast pings\n"));
|
||||||
ICMP_STATS_INC(icmp.err);
|
ICMP_STATS_INC(icmp.err);
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
return;
|
return;
|
||||||
@@ -117,7 +116,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||||||
IPH_TTL(iphdr), 0, IP_PROTO_ICMP, inp);
|
IPH_TTL(iphdr), 0, IP_PROTO_ICMP, inp);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %d code %d not supported.\n", (int)type, (int)code));
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" code %"S16_F" not supported.\n", (s16_t)type, (s16_t)code));
|
||||||
ICMP_STATS_INC(icmp.proterr);
|
ICMP_STATS_INC(icmp.proterr);
|
||||||
ICMP_STATS_INC(icmp.drop);
|
ICMP_STATS_INC(icmp.drop);
|
||||||
}
|
}
|
||||||
@@ -140,7 +139,7 @@ icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
|
|||||||
ICMPH_TYPE_SET(idur, ICMP_DUR);
|
ICMPH_TYPE_SET(idur, ICMP_DUR);
|
||||||
ICMPH_CODE_SET(idur, t);
|
ICMPH_CODE_SET(idur, t);
|
||||||
|
|
||||||
memcpy((char *)q->payload + 8, p->payload, IP_HLEN + 8);
|
memcpy((u8_t *)q->payload + 8, p->payload, IP_HLEN + 8);
|
||||||
|
|
||||||
/* calculate checksum */
|
/* calculate checksum */
|
||||||
idur->chksum = 0;
|
idur->chksum = 0;
|
||||||
@@ -178,7 +177,7 @@ icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
|
|||||||
ICMPH_CODE_SET(tehdr, t);
|
ICMPH_CODE_SET(tehdr, t);
|
||||||
|
|
||||||
/* copy fields from original packet */
|
/* copy fields from original packet */
|
||||||
memcpy((char *)q->payload + 8, (char *)p->payload, IP_HLEN + 8);
|
memcpy((u8_t *)q->payload + 8, (u8_t *)p->payload, IP_HLEN + 8);
|
||||||
|
|
||||||
/* calculate checksum */
|
/* calculate checksum */
|
||||||
tehdr->chksum = 0;
|
tehdr->chksum = 0;
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ ip_route(struct ip_addr *dest)
|
|||||||
/* iterate through netifs */
|
/* iterate through netifs */
|
||||||
for(netif = netif_list; netif != NULL; netif = netif->next) {
|
for(netif = netif_list; netif != NULL; netif = netif->next) {
|
||||||
/* network mask matches? */
|
/* network mask matches? */
|
||||||
if (ip_addr_maskcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
|
if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
|
||||||
/* return netif on which to forward IP packet */
|
/* return netif on which to forward IP packet */
|
||||||
return netif;
|
return netif;
|
||||||
}
|
}
|
||||||
@@ -110,7 +110,7 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
|
|||||||
/* Find network interface where to forward this IP packet to. */
|
/* Find network interface where to forward this IP packet to. */
|
||||||
netif = ip_route((struct ip_addr *)&(iphdr->dest));
|
netif = ip_route((struct ip_addr *)&(iphdr->dest));
|
||||||
if (netif == NULL) {
|
if (netif == NULL) {
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for 0x%lx found\n",
|
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for 0x%"X32_F" found\n",
|
||||||
iphdr->dest.addr));
|
iphdr->dest.addr));
|
||||||
snmp_inc_ipnoroutes();
|
snmp_inc_ipnoroutes();
|
||||||
return (struct netif *)NULL;
|
return (struct netif *)NULL;
|
||||||
@@ -142,7 +142,7 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
|
|||||||
IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100));
|
IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100));
|
||||||
}
|
}
|
||||||
|
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to 0x%lx\n",
|
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to 0x%"X32_F"\n",
|
||||||
iphdr->dest.addr));
|
iphdr->dest.addr));
|
||||||
|
|
||||||
IP_STATS_INC(ip.fw);
|
IP_STATS_INC(ip.fw);
|
||||||
@@ -181,7 +181,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
|||||||
/* identify the IP header */
|
/* identify the IP header */
|
||||||
iphdr = p->payload;
|
iphdr = p->payload;
|
||||||
if (IPH_V(iphdr) != 4) {
|
if (IPH_V(iphdr) != 4) {
|
||||||
LWIP_DEBUGF(IP_DEBUG | 1, ("IP packet dropped due to bad version number %u\n", IPH_V(iphdr)));
|
LWIP_DEBUGF(IP_DEBUG | 1, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr)));
|
||||||
ip_debug_print(p);
|
ip_debug_print(p);
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
IP_STATS_INC(ip.err);
|
IP_STATS_INC(ip.err);
|
||||||
@@ -196,7 +196,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
|||||||
|
|
||||||
/* header length exceeds first pbuf length? */
|
/* header length exceeds first pbuf length? */
|
||||||
if (iphdrlen > p->len) {
|
if (iphdrlen > p->len) {
|
||||||
LWIP_DEBUGF(IP_DEBUG | 2, ("IP header (len %u) does not fit in first pbuf (len %u), IP packet droppped.\n",
|
LWIP_DEBUGF(IP_DEBUG | 2, ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet droppped.\n",
|
||||||
iphdrlen, p->len));
|
iphdrlen, p->len));
|
||||||
/* free (drop) packet pbufs */
|
/* free (drop) packet pbufs */
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
@@ -210,7 +210,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
|||||||
#if CHECKSUM_CHECK_IP
|
#if CHECKSUM_CHECK_IP
|
||||||
if (inet_chksum(iphdr, iphdrlen) != 0) {
|
if (inet_chksum(iphdr, iphdrlen) != 0) {
|
||||||
|
|
||||||
LWIP_DEBUGF(IP_DEBUG | 2, ("Checksum (0x%x) failed, IP packet dropped.\n", inet_chksum(iphdr, iphdrlen)));
|
LWIP_DEBUGF(IP_DEBUG | 2, ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdrlen)));
|
||||||
ip_debug_print(p);
|
ip_debug_print(p);
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
IP_STATS_INC(ip.chkerr);
|
IP_STATS_INC(ip.chkerr);
|
||||||
@@ -227,7 +227,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
|||||||
/* match packet against an interface, i.e. is this packet for us? */
|
/* match packet against an interface, i.e. is this packet for us? */
|
||||||
for (netif = netif_list; netif != NULL; netif = netif->next) {
|
for (netif = netif_list; netif != NULL; netif = netif->next) {
|
||||||
|
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%lx netif->ip_addr 0x%lx (0x%lx, 0x%lx, 0x%lx)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%"X32_F" netif->ip_addr 0x%"X32_F" (0x%"X32_F", 0x%"X32_F", 0x%"X32_F")\n",
|
||||||
iphdr->dest.addr, netif->ip_addr.addr,
|
iphdr->dest.addr, netif->ip_addr.addr,
|
||||||
iphdr->dest.addr & netif->netmask.addr,
|
iphdr->dest.addr & netif->netmask.addr,
|
||||||
netif->ip_addr.addr & netif->netmask.addr,
|
netif->ip_addr.addr & netif->netmask.addr,
|
||||||
@@ -238,11 +238,8 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
|||||||
{
|
{
|
||||||
/* unicast to this interface address? */
|
/* unicast to this interface address? */
|
||||||
if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) ||
|
if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) ||
|
||||||
/* or broadcast matching this interface network address? */
|
/* or broadcast on this interface network address? */
|
||||||
(ip_addr_isbroadcast(&(iphdr->dest), netif) &&
|
ip_addr_isbroadcast(&(iphdr->dest), netif)) {
|
||||||
ip_addr_maskcmp(&(iphdr->dest), &(netif->ip_addr), &(netif->netmask))) ||
|
|
||||||
/* or restricted broadcast? */
|
|
||||||
ip_addr_cmp(&(iphdr->dest), IP_ADDR_BROADCAST)) {
|
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
|
LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
|
||||||
netif->name[0], netif->name[1]));
|
netif->name[0], netif->name[1]));
|
||||||
/* break out of for loop */
|
/* break out of for loop */
|
||||||
@@ -258,7 +255,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
|||||||
if (netif == NULL) {
|
if (netif == NULL) {
|
||||||
/* remote port is DHCP server? */
|
/* remote port is DHCP server? */
|
||||||
if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
|
if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
|
||||||
LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: UDP packet to DHCP client port %u\n",
|
LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: UDP packet to DHCP client port %"U16_F"\n",
|
||||||
ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdrlen))->dest)));
|
ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdrlen))->dest)));
|
||||||
if (ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdrlen))->dest) == DHCP_CLIENT_PORT) {
|
if (ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdrlen))->dest) == DHCP_CLIENT_PORT) {
|
||||||
LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: DHCP packet accepted.\n"));
|
LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: DHCP packet accepted.\n"));
|
||||||
@@ -288,7 +285,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
|||||||
/* packet consists of multiple fragments? */
|
/* packet consists of multiple fragments? */
|
||||||
if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
|
if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
|
||||||
#if IP_REASSEMBLY /* packet fragment reassembly code present? */
|
#if IP_REASSEMBLY /* packet fragment reassembly code present? */
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04x tot_len=%u len=%u MF=%u offset=%u), calling ip_reass()\n",
|
LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip_reass()\n",
|
||||||
ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & htons(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8));
|
ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & htons(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8));
|
||||||
/* reassemble the packet*/
|
/* reassemble the packet*/
|
||||||
p = ip_reass(p);
|
p = ip_reass(p);
|
||||||
@@ -299,7 +296,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
|||||||
iphdr = p->payload;
|
iphdr = p->payload;
|
||||||
#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */
|
#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%x) (while IP_REASSEMBLY == 0).\n",
|
LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n",
|
||||||
ntohs(IPH_OFFSET(iphdr))));
|
ntohs(IPH_OFFSET(iphdr))));
|
||||||
IP_STATS_INC(ip.opterr);
|
IP_STATS_INC(ip.opterr);
|
||||||
IP_STATS_INC(ip.drop);
|
IP_STATS_INC(ip.drop);
|
||||||
@@ -322,7 +319,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
|||||||
/* send to upper layers */
|
/* send to upper layers */
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n"));
|
LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n"));
|
||||||
ip_debug_print(p);
|
ip_debug_print(p);
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %d p->tot_len %d\n", p->len, p->tot_len));
|
LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len));
|
||||||
|
|
||||||
#if LWIP_RAW
|
#if LWIP_RAW
|
||||||
/* raw input did not eat the packet? */
|
/* raw input did not eat the packet? */
|
||||||
@@ -356,7 +353,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
|||||||
}
|
}
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
|
|
||||||
LWIP_DEBUGF(IP_DEBUG | 2, ("Unsupported transport protocol %d\n", IPH_PROTO(iphdr)));
|
LWIP_DEBUGF(IP_DEBUG | 2, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr)));
|
||||||
|
|
||||||
IP_STATS_INC(ip.proterr);
|
IP_STATS_INC(ip.proterr);
|
||||||
IP_STATS_INC(ip.drop);
|
IP_STATS_INC(ip.drop);
|
||||||
@@ -430,7 +427,7 @@ ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
|||||||
|
|
||||||
IP_STATS_INC(ip.xmit);
|
IP_STATS_INC(ip.xmit);
|
||||||
|
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%u\n", netif->name[0], netif->name[1], netif->num));
|
LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num));
|
||||||
ip_debug_print(p);
|
ip_debug_print(p);
|
||||||
|
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
|
LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
|
||||||
@@ -450,7 +447,7 @@ ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
|||||||
struct netif *netif;
|
struct netif *netif;
|
||||||
|
|
||||||
if ((netif = ip_route(dest)) == NULL) {
|
if ((netif = ip_route(dest)) == NULL) {
|
||||||
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: No route to 0x%lx\n", dest->addr));
|
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: No route to 0x%"X32_F"\n", dest->addr));
|
||||||
|
|
||||||
IP_STATS_INC(ip.rterr);
|
IP_STATS_INC(ip.rterr);
|
||||||
snmp_inc_ipoutdiscards();
|
snmp_inc_ipoutdiscards();
|
||||||
@@ -471,31 +468,31 @@ ip_debug_print(struct pbuf *p)
|
|||||||
|
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
|
LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("|%2d |%2d | 0x%02x | %5u | (v, hl, tos, len)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" | 0x%02"X16_F" | %5"U16_F" | (v, hl, tos, len)\n",
|
||||||
IPH_V(iphdr),
|
IPH_V(iphdr),
|
||||||
IPH_HL(iphdr),
|
IPH_HL(iphdr),
|
||||||
IPH_TOS(iphdr),
|
IPH_TOS(iphdr),
|
||||||
ntohs(IPH_LEN(iphdr))));
|
ntohs(IPH_LEN(iphdr))));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("| %5u |%u%u%u| %4u | (id, flags, offset)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n",
|
||||||
ntohs(IPH_ID(iphdr)),
|
ntohs(IPH_ID(iphdr)),
|
||||||
ntohs(IPH_OFFSET(iphdr)) >> 15 & 1,
|
ntohs(IPH_OFFSET(iphdr)) >> 15 & 1,
|
||||||
ntohs(IPH_OFFSET(iphdr)) >> 14 & 1,
|
ntohs(IPH_OFFSET(iphdr)) >> 14 & 1,
|
||||||
ntohs(IPH_OFFSET(iphdr)) >> 13 & 1,
|
ntohs(IPH_OFFSET(iphdr)) >> 13 & 1,
|
||||||
ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK));
|
ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("| %3u | %3u | 0x%04x | (ttl, proto, chksum)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n",
|
||||||
IPH_TTL(iphdr),
|
IPH_TTL(iphdr),
|
||||||
IPH_PROTO(iphdr),
|
IPH_PROTO(iphdr),
|
||||||
ntohs(IPH_CHKSUM(iphdr))));
|
ntohs(IPH_CHKSUM(iphdr))));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("| %3u | %3u | %3u | %3u | (src)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n",
|
||||||
ip4_addr1(&iphdr->src),
|
ip4_addr1(&iphdr->src),
|
||||||
ip4_addr2(&iphdr->src),
|
ip4_addr2(&iphdr->src),
|
||||||
ip4_addr3(&iphdr->src),
|
ip4_addr3(&iphdr->src),
|
||||||
ip4_addr4(&iphdr->src)));
|
ip4_addr4(&iphdr->src)));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("| %3u | %3u | %3u | %3u | (dest)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n",
|
||||||
ip4_addr1(&iphdr->dest),
|
ip4_addr1(&iphdr->dest),
|
||||||
ip4_addr2(&iphdr->dest),
|
ip4_addr2(&iphdr->dest),
|
||||||
ip4_addr3(&iphdr->dest),
|
ip4_addr3(&iphdr->dest),
|
||||||
|
|||||||
@@ -60,9 +60,12 @@ u8_t ip_addr_isbroadcast(struct ip_addr *addr, struct netif *netif)
|
|||||||
/* address matches network interface address exactly? => no broadcast */
|
/* address matches network interface address exactly? => no broadcast */
|
||||||
else if (addr->addr == netif->ip_addr.addr)
|
else if (addr->addr == netif->ip_addr.addr)
|
||||||
return 0;
|
return 0;
|
||||||
/* host identifier bits are all ones? => network broadcast address */
|
/* on the same (sub) network... */
|
||||||
else if ((addr->addr & ~netif->netmask.addr) ==
|
else if (ip_addr_netcmp(addr, &(netif->ip_addr), &(netif->netmask))
|
||||||
(ip_addr_broadcast.addr & ~netif->netmask.addr))
|
/* ...and host identifier bits are all ones? =>... */
|
||||||
|
&& ((addr->addr & ~netif->netmask.addr) ==
|
||||||
|
(ip_addr_broadcast.addr & ~netif->netmask.addr)))
|
||||||
|
/* => network broadcast address */
|
||||||
return 1;
|
return 1;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -37,12 +37,13 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
#include "lwip/sys.h"
|
/* #include "lwip/sys.h" */
|
||||||
#include "lwip/ip.h"
|
#include "lwip/ip.h"
|
||||||
#include "lwip/ip_frag.h"
|
#include "lwip/ip_frag.h"
|
||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
|
|
||||||
#include "lwip/stats.h"
|
#include "lwip/stats.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -77,7 +78,7 @@ copy_from_pbuf(struct pbuf *p, u16_t * offset,
|
|||||||
#define IP_REASS_TMO 1000
|
#define IP_REASS_TMO 1000
|
||||||
|
|
||||||
static u8_t ip_reassbuf[IP_HLEN + IP_REASS_BUFSIZE];
|
static u8_t ip_reassbuf[IP_HLEN + IP_REASS_BUFSIZE];
|
||||||
static u8_t ip_reassbitmap[IP_REASS_BUFSIZE / (8 * 8)];
|
static u8_t ip_reassbitmap[IP_REASS_BUFSIZE / (8 * 8) + 1];
|
||||||
static const u8_t bitmap_bits[8] = { 0xff, 0x7f, 0x3f, 0x1f,
|
static const u8_t bitmap_bits[8] = { 0xff, 0x7f, 0x3f, 0x1f,
|
||||||
0x0f, 0x07, 0x03, 0x01
|
0x0f, 0x07, 0x03, 0x01
|
||||||
};
|
};
|
||||||
@@ -87,18 +88,26 @@ static u8_t ip_reassflags;
|
|||||||
|
|
||||||
static u8_t ip_reasstmr;
|
static u8_t ip_reasstmr;
|
||||||
|
|
||||||
/* Reassembly timer */
|
/**
|
||||||
static void
|
* Reassembly timer base function
|
||||||
ip_reass_timer(void *arg)
|
* for both NO_SYS == 0 and 1 (!).
|
||||||
|
*
|
||||||
|
* Should be called every 1000 msec.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ip_reass_tmr(void)
|
||||||
{
|
{
|
||||||
(void)arg;
|
if (ip_reasstmr > 0) {
|
||||||
if (ip_reasstmr > 1) {
|
|
||||||
ip_reasstmr--;
|
ip_reasstmr--;
|
||||||
sys_timeout(IP_REASS_TMO, ip_reass_timer, NULL);
|
}
|
||||||
} else if (ip_reasstmr == 1)
|
|
||||||
ip_reasstmr = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reassembles incoming IP fragments into an IP datagram.
|
||||||
|
*
|
||||||
|
* @param p points to a pbuf chain of the fragment
|
||||||
|
* @return NULL if reassembly is incomplete, ? otherwise
|
||||||
|
*/
|
||||||
struct pbuf *
|
struct pbuf *
|
||||||
ip_reass(struct pbuf *p)
|
ip_reass(struct pbuf *p)
|
||||||
{
|
{
|
||||||
@@ -118,7 +127,6 @@ ip_reass(struct pbuf *p)
|
|||||||
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: new packet\n"));
|
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: new packet\n"));
|
||||||
memcpy(iphdr, fraghdr, IP_HLEN);
|
memcpy(iphdr, fraghdr, IP_HLEN);
|
||||||
ip_reasstmr = IP_REASS_MAXAGE;
|
ip_reasstmr = IP_REASS_MAXAGE;
|
||||||
sys_timeout(IP_REASS_TMO, ip_reass_timer, NULL);
|
|
||||||
ip_reassflags = 0;
|
ip_reassflags = 0;
|
||||||
/* Clear the bitmap. */
|
/* Clear the bitmap. */
|
||||||
memset(ip_reassbitmap, 0, sizeof(ip_reassbitmap));
|
memset(ip_reassbitmap, 0, sizeof(ip_reassbitmap));
|
||||||
@@ -130,7 +138,8 @@ ip_reass(struct pbuf *p)
|
|||||||
if (ip_addr_cmp(&iphdr->src, &fraghdr->src) &&
|
if (ip_addr_cmp(&iphdr->src, &fraghdr->src) &&
|
||||||
ip_addr_cmp(&iphdr->dest, &fraghdr->dest) &&
|
ip_addr_cmp(&iphdr->dest, &fraghdr->dest) &&
|
||||||
IPH_ID(iphdr) == IPH_ID(fraghdr)) {
|
IPH_ID(iphdr) == IPH_ID(fraghdr)) {
|
||||||
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: matching old packet\n"));
|
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: matching previous fragment ID=%"X16_F"\n",
|
||||||
|
ntohs(IPH_ID(fraghdr))));
|
||||||
IPFRAG_STATS_INC(ip_frag.cachehit);
|
IPFRAG_STATS_INC(ip_frag.cachehit);
|
||||||
/* Find out the offset in the reassembly buffer where we should
|
/* Find out the offset in the reassembly buffer where we should
|
||||||
copy the fragment. */
|
copy the fragment. */
|
||||||
@@ -141,9 +150,8 @@ ip_reass(struct pbuf *p)
|
|||||||
reassembly buffer, we discard the entire packet. */
|
reassembly buffer, we discard the entire packet. */
|
||||||
if (offset > IP_REASS_BUFSIZE || offset + len > IP_REASS_BUFSIZE) {
|
if (offset > IP_REASS_BUFSIZE || offset + len > IP_REASS_BUFSIZE) {
|
||||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||||
("ip_reass: fragment outside of buffer (%d:%d/%d).\n", offset,
|
("ip_reass: fragment outside of buffer (%"S16_F":%"S16_F"/%"S16_F").\n", offset,
|
||||||
offset + len, IP_REASS_BUFSIZE));
|
offset + len, IP_REASS_BUFSIZE));
|
||||||
sys_untimeout(ip_reass_timer, NULL);
|
|
||||||
ip_reasstmr = 0;
|
ip_reasstmr = 0;
|
||||||
goto nullreturn;
|
goto nullreturn;
|
||||||
}
|
}
|
||||||
@@ -151,7 +159,7 @@ ip_reass(struct pbuf *p)
|
|||||||
/* Copy the fragment into the reassembly buffer, at the right
|
/* Copy the fragment into the reassembly buffer, at the right
|
||||||
offset. */
|
offset. */
|
||||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||||
("ip_reass: copying with offset %d into %d:%d\n", offset,
|
("ip_reass: copying with offset %"S16_F" into %"S16_F":%"S16_F"\n", offset,
|
||||||
IP_HLEN + offset, IP_HLEN + offset + len));
|
IP_HLEN + offset, IP_HLEN + offset + len));
|
||||||
i = IPH_HL(fraghdr) * 4;
|
i = IPH_HL(fraghdr) * 4;
|
||||||
copy_from_pbuf(p, &i, &ip_reassbuf[IP_HLEN + offset], len);
|
copy_from_pbuf(p, &i, &ip_reassbuf[IP_HLEN + offset], len);
|
||||||
@@ -160,24 +168,29 @@ ip_reass(struct pbuf *p)
|
|||||||
if (offset / (8 * 8) == (offset + len) / (8 * 8)) {
|
if (offset / (8 * 8) == (offset + len) / (8 * 8)) {
|
||||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||||
("ip_reass: updating single byte in bitmap.\n"));
|
("ip_reass: updating single byte in bitmap.\n"));
|
||||||
/* If the two endpoints are in the same byte, we only update
|
/* If the two endpoints are in the same byte, we only update that byte. */
|
||||||
that byte. */
|
LWIP_ASSERT("offset / (8 * 8) < sizeof(ip_reassbitmap)",
|
||||||
|
offset / (8 * 8) < sizeof(ip_reassbitmap));
|
||||||
ip_reassbitmap[offset / (8 * 8)] |=
|
ip_reassbitmap[offset / (8 * 8)] |=
|
||||||
bitmap_bits[(offset / 8) & 7] &
|
bitmap_bits[(offset / 8) & 7] &
|
||||||
~bitmap_bits[((offset + len) / 8) & 7];
|
~bitmap_bits[((offset + len) / 8) & 7];
|
||||||
} else {
|
} else {
|
||||||
/* If the two endpoints are in different bytes, we update the
|
/* If the two endpoints are in different bytes, we update the
|
||||||
bytes in the endpoints and fill the stuff inbetween with
|
bytes in the endpoints and fill the stuff inbetween with
|
||||||
0xff. */
|
0xff. */
|
||||||
|
LWIP_ASSERT("offset / (8 * 8) < sizeof(ip_reassbitmap)",
|
||||||
|
offset / (8 * 8) < sizeof(ip_reassbitmap));
|
||||||
ip_reassbitmap[offset / (8 * 8)] |= bitmap_bits[(offset / 8) & 7];
|
ip_reassbitmap[offset / (8 * 8)] |= bitmap_bits[(offset / 8) & 7];
|
||||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||||
("ip_reass: updating many bytes in bitmap (%d:%d).\n",
|
("ip_reass: updating many bytes in bitmap (%"S16_F":%"S16_F").\n",
|
||||||
1 + offset / (8 * 8), (offset + len) / (8 * 8)));
|
1 + offset / (8 * 8), (offset + len) / (8 * 8)));
|
||||||
for (i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) {
|
for (i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) {
|
||||||
ip_reassbitmap[i] = 0xff;
|
ip_reassbitmap[i] = 0xff;
|
||||||
}
|
}
|
||||||
|
LWIP_ASSERT("(offset + len) / (8 * 8) < sizeof(ip_reassbitmap)",
|
||||||
|
(offset + len) / (8 * 8) < sizeof(ip_reassbitmap));
|
||||||
ip_reassbitmap[(offset + len) / (8 * 8)] |=
|
ip_reassbitmap[(offset + len) / (8 * 8)] |=
|
||||||
~bitmap_bits[((offset + len) / 8) & 7];
|
~bitmap_bits[((offset + len) / 8) & 7];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If this fragment has the More Fragments flag set to zero, we
|
/* If this fragment has the More Fragments flag set to zero, we
|
||||||
@@ -190,7 +203,7 @@ ip_reass(struct pbuf *p)
|
|||||||
ip_reassflags |= IP_REASS_FLAG_LASTFRAG;
|
ip_reassflags |= IP_REASS_FLAG_LASTFRAG;
|
||||||
ip_reasslen = offset + len;
|
ip_reasslen = offset + len;
|
||||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||||
("ip_reass: last fragment seen, total len %d\n",
|
("ip_reass: last fragment seen, total len %"S16_F"\n",
|
||||||
ip_reasslen));
|
ip_reasslen));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,23 +213,27 @@ ip_reass(struct pbuf *p)
|
|||||||
if (ip_reassflags & IP_REASS_FLAG_LASTFRAG) {
|
if (ip_reassflags & IP_REASS_FLAG_LASTFRAG) {
|
||||||
/* Check all bytes up to and including all but the last byte in
|
/* Check all bytes up to and including all but the last byte in
|
||||||
the bitmap. */
|
the bitmap. */
|
||||||
|
LWIP_ASSERT("ip_reasslen / (8 * 8) - 1 < sizeof(ip_reassbitmap)",
|
||||||
|
ip_reasslen / (8 * 8) - 1 < sizeof(ip_reassbitmap));
|
||||||
for (i = 0; i < ip_reasslen / (8 * 8) - 1; ++i) {
|
for (i = 0; i < ip_reasslen / (8 * 8) - 1; ++i) {
|
||||||
if (ip_reassbitmap[i] != 0xff) {
|
if (ip_reassbitmap[i] != 0xff) {
|
||||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||||
("ip_reass: last fragment seen, bitmap %d/%d failed (%x)\n",
|
("ip_reass: last fragment seen, bitmap %"S16_F"/%"S16_F" failed (%"X16_F")\n",
|
||||||
i, ip_reasslen / (8 * 8) - 1, ip_reassbitmap[i]));
|
i, ip_reasslen / (8 * 8) - 1, ip_reassbitmap[i]));
|
||||||
goto nullreturn;
|
goto nullreturn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Check the last byte in the bitmap. It should contain just the
|
/* Check the last byte in the bitmap. It should contain just the
|
||||||
right amount of bits. */
|
right amount of bits. */
|
||||||
|
LWIP_ASSERT("ip_reasslen / (8 * 8) < sizeof(ip_reassbitmap)",
|
||||||
|
ip_reasslen / (8 * 8) < sizeof(ip_reassbitmap));
|
||||||
if (ip_reassbitmap[ip_reasslen / (8 * 8)] !=
|
if (ip_reassbitmap[ip_reasslen / (8 * 8)] !=
|
||||||
(u8_t) ~ bitmap_bits[ip_reasslen / 8 & 7]) {
|
(u8_t) ~ bitmap_bits[ip_reasslen / 8 & 7]) {
|
||||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||||
("ip_reass: last fragment seen, bitmap %d didn't contain %x (%x)\n",
|
("ip_reass: last fragment seen, bitmap %"S16_F" didn't contain %"X16_F" (%"X16_F")\n",
|
||||||
ip_reasslen / (8 * 8), ~bitmap_bits[ip_reasslen / 8 & 7],
|
ip_reasslen / (8 * 8), ~bitmap_bits[ip_reasslen / 8 & 7],
|
||||||
ip_reassbitmap[ip_reasslen / (8 * 8)]));
|
ip_reassbitmap[ip_reasslen / (8 * 8)]));
|
||||||
goto nullreturn;
|
goto nullreturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pretend to be a "normal" (i.e., not fragmented) IP packet
|
/* Pretend to be a "normal" (i.e., not fragmented) IP packet
|
||||||
@@ -231,27 +248,25 @@ ip_reass(struct pbuf *p)
|
|||||||
/* If we have come this far, we have a full packet in the
|
/* If we have come this far, we have a full packet in the
|
||||||
buffer, so we allocate a pbuf and copy the packet into it. We
|
buffer, so we allocate a pbuf and copy the packet into it. We
|
||||||
also reset the timer. */
|
also reset the timer. */
|
||||||
sys_untimeout(ip_reass_timer, NULL);
|
|
||||||
ip_reasstmr = 0;
|
ip_reasstmr = 0;
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
p = pbuf_alloc(PBUF_LINK, ip_reasslen, PBUF_POOL);
|
p = pbuf_alloc(PBUF_LINK, ip_reasslen, PBUF_POOL);
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
i = 0;
|
i = 0;
|
||||||
for (q = p; q != NULL; q = q->next) {
|
for (q = p; q != NULL; q = q->next) {
|
||||||
/* Copy enough bytes to fill this pbuf in the chain. The
|
/* Copy enough bytes to fill this pbuf in the chain. The
|
||||||
available data in the pbuf is given by the q->len
|
available data in the pbuf is given by the q->len variable. */
|
||||||
variable. */
|
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
("ip_reass: memcpy from %p (%"S16_F") to %p, %"S16_F" bytes\n",
|
||||||
("ip_reass: memcpy from %p (%d) to %p, %d bytes\n",
|
(void *)&ip_reassbuf[i], i, q->payload,
|
||||||
(void *)&ip_reassbuf[i], i, q->payload,
|
q->len > ip_reasslen - i ? ip_reasslen - i : q->len));
|
||||||
q->len > ip_reasslen - i ? ip_reasslen - i : q->len));
|
memcpy(q->payload, &ip_reassbuf[i],
|
||||||
memcpy(q->payload, &ip_reassbuf[i],
|
q->len > ip_reasslen - i ? ip_reasslen - i : q->len);
|
||||||
q->len > ip_reasslen - i ? ip_reasslen - i : q->len);
|
i += q->len;
|
||||||
i += q->len;
|
}
|
||||||
}
|
IPFRAG_STATS_INC(ip_frag.fw);
|
||||||
IPFRAG_STATS_INC(ip_frag.fw);
|
|
||||||
} else {
|
} else {
|
||||||
IPFRAG_STATS_INC(ip_frag.memerr);
|
IPFRAG_STATS_INC(ip_frag.memerr);
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: p %p\n", (void*)p));
|
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: p %p\n", (void*)p));
|
||||||
return p;
|
return p;
|
||||||
@@ -268,9 +283,9 @@ nullreturn:
|
|||||||
static u8_t buf[MEM_ALIGN_SIZE(MAX_MTU)];
|
static u8_t buf[MEM_ALIGN_SIZE(MAX_MTU)];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fragment an IP packet if too large
|
* Fragment an IP datagram if too large for the netif.
|
||||||
*
|
*
|
||||||
* Chop the packet in mtu sized chunks and send them in order
|
* Chop the datagram in MTU sized chunks and send them in order
|
||||||
* by using a fixed size static memory buffer (PBUF_ROM)
|
* by using a fixed size static memory buffer (PBUF_ROM)
|
||||||
*/
|
*/
|
||||||
err_t
|
err_t
|
||||||
@@ -289,6 +304,9 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
|
|||||||
|
|
||||||
/* Get a RAM based MTU sized pbuf */
|
/* Get a RAM based MTU sized pbuf */
|
||||||
rambuf = pbuf_alloc(PBUF_LINK, 0, PBUF_REF);
|
rambuf = pbuf_alloc(PBUF_LINK, 0, PBUF_REF);
|
||||||
|
if (rambuf == NULL) {
|
||||||
|
return ERR_MEM;
|
||||||
|
}
|
||||||
rambuf->tot_len = rambuf->len = mtu;
|
rambuf->tot_len = rambuf->len = mtu;
|
||||||
rambuf->payload = MEM_ALIGN((void *)buf);
|
rambuf->payload = MEM_ALIGN((void *)buf);
|
||||||
|
|
||||||
@@ -332,11 +350,15 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
|
|||||||
* worked would make things simpler.
|
* worked would make things simpler.
|
||||||
*/
|
*/
|
||||||
header = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM);
|
header = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM);
|
||||||
pbuf_chain(header, rambuf);
|
if (header != NULL) {
|
||||||
netif->output(netif, header, dest);
|
pbuf_chain(header, rambuf);
|
||||||
IPFRAG_STATS_INC(ip_frag.xmit);
|
netif->output(netif, header, dest);
|
||||||
pbuf_free(header);
|
IPFRAG_STATS_INC(ip_frag.xmit);
|
||||||
|
pbuf_free(header);
|
||||||
|
} else {
|
||||||
|
pbuf_free(rambuf);
|
||||||
|
return ERR_MEM;
|
||||||
|
}
|
||||||
left -= cop;
|
left -= cop;
|
||||||
}
|
}
|
||||||
pbuf_free(rambuf);
|
pbuf_free(rambuf);
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
void
|
void
|
||||||
icmp_input(struct pbuf *p, struct netif *inp)
|
icmp_input(struct pbuf *p, struct netif *inp)
|
||||||
{
|
{
|
||||||
unsigned char type;
|
u8_t type;
|
||||||
struct icmp_echo_hdr *iecho;
|
struct icmp_echo_hdr *iecho;
|
||||||
struct ip_hdr *iphdr;
|
struct ip_hdr *iphdr;
|
||||||
struct ip_addr tmpaddr;
|
struct ip_addr tmpaddr;
|
||||||
@@ -57,7 +57,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||||||
|
|
||||||
/* TODO: check length before accessing payload! */
|
/* TODO: check length before accessing payload! */
|
||||||
|
|
||||||
type = ((char *)p->payload)[0];
|
type = ((u8_t *)p->payload)[0];
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ICMP6_ECHO:
|
case ICMP6_ECHO:
|
||||||
@@ -74,16 +74,16 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
iecho = p->payload;
|
iecho = p->payload;
|
||||||
iphdr = (struct ip_hdr *)((char *)p->payload - IP_HLEN);
|
iphdr = (struct ip_hdr *)((u8_t *)p->payload - IP_HLEN);
|
||||||
if (inet_chksum_pbuf(p) != 0) {
|
if (inet_chksum_pbuf(p) != 0) {
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%x)\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len)));
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%"X16_F")\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len)));
|
||||||
|
|
||||||
#ifdef ICMP_STATS
|
#ifdef ICMP_STATS
|
||||||
++lwip_stats.icmp.chkerr;
|
++lwip_stats.icmp.chkerr;
|
||||||
#endif /* ICMP_STATS */
|
#endif /* ICMP_STATS */
|
||||||
/* return;*/
|
/* return;*/
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp: p->len %d p->tot_len %d\n", p->len, p->tot_len));
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp: p->len %"S16_F" p->tot_len %"S16_F"\n", p->len, p->tot_len));
|
||||||
ip_addr_set(&tmpaddr, &(iphdr->src));
|
ip_addr_set(&tmpaddr, &(iphdr->src));
|
||||||
ip_addr_set(&(iphdr->src), &(iphdr->dest));
|
ip_addr_set(&(iphdr->src), &(iphdr->dest));
|
||||||
ip_addr_set(&(iphdr->dest), &tmpaddr);
|
ip_addr_set(&(iphdr->dest), &tmpaddr);
|
||||||
@@ -94,17 +94,17 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||||||
} else {
|
} else {
|
||||||
iecho->chksum += htons(ICMP6_ECHO << 8);
|
iecho->chksum += htons(ICMP6_ECHO << 8);
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%x)\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len)));
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%"X16_F")\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len)));
|
||||||
#ifdef ICMP_STATS
|
#ifdef ICMP_STATS
|
||||||
++lwip_stats.icmp.xmit;
|
++lwip_stats.icmp.xmit;
|
||||||
#endif /* ICMP_STATS */
|
#endif /* ICMP_STATS */
|
||||||
|
|
||||||
/* LWIP_DEBUGF("icmp: p->len %u p->tot_len %u\n", p->len, p->tot_len);*/
|
/* LWIP_DEBUGF("icmp: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len);*/
|
||||||
ip_output_if (p, &(iphdr->src), IP_HDRINCL,
|
ip_output_if (p, &(iphdr->src), IP_HDRINCL,
|
||||||
iphdr->hoplim, IP_PROTO_ICMP, inp);
|
iphdr->hoplim, IP_PROTO_ICMP, inp);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %d not supported.\n", (int)type));
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" not supported.\n", (s16_t)type));
|
||||||
#ifdef ICMP_STATS
|
#ifdef ICMP_STATS
|
||||||
++lwip_stats.icmp.proterr;
|
++lwip_stats.icmp.proterr;
|
||||||
++lwip_stats.icmp.drop;
|
++lwip_stats.icmp.drop;
|
||||||
@@ -127,10 +127,10 @@ icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
|
|||||||
iphdr = p->payload;
|
iphdr = p->payload;
|
||||||
|
|
||||||
idur = q->payload;
|
idur = q->payload;
|
||||||
idur->type = (char)ICMP6_DUR;
|
idur->type = (u8_t)ICMP6_DUR;
|
||||||
idur->icode = (char)t;
|
idur->icode = (u8_t)t;
|
||||||
|
|
||||||
memcpy((char *)q->payload + 8, p->payload, IP_HLEN + 8);
|
memcpy((u8_t *)q->payload + 8, p->payload, IP_HLEN + 8);
|
||||||
|
|
||||||
/* calculate checksum */
|
/* calculate checksum */
|
||||||
idur->chksum = 0;
|
idur->chksum = 0;
|
||||||
@@ -158,11 +158,11 @@ icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
|
|||||||
iphdr = p->payload;
|
iphdr = p->payload;
|
||||||
|
|
||||||
tehdr = q->payload;
|
tehdr = q->payload;
|
||||||
tehdr->type = (char)ICMP6_TE;
|
tehdr->type = (u8_t)ICMP6_TE;
|
||||||
tehdr->icode = (char)t;
|
tehdr->icode = (u8_t)t;
|
||||||
|
|
||||||
/* copy fields from original packet */
|
/* copy fields from original packet */
|
||||||
memcpy((char *)q->payload + 8, (char *)p->payload, IP_HLEN + 8);
|
memcpy((u8_t *)q->payload + 8, (u8_t *)p->payload, IP_HLEN + 8);
|
||||||
|
|
||||||
/* calculate checksum */
|
/* calculate checksum */
|
||||||
tehdr->chksum = 0;
|
tehdr->chksum = 0;
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ ip_route(struct ip_addr *dest)
|
|||||||
struct netif *netif;
|
struct netif *netif;
|
||||||
|
|
||||||
for(netif = netif_list; netif != NULL; netif = netif->next) {
|
for(netif = netif_list; netif != NULL; netif = netif->next) {
|
||||||
if (ip_addr_maskcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
|
if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
|
||||||
return netif;
|
return netif;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -217,7 +217,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
|||||||
#if IP_DEBUG
|
#if IP_DEBUG
|
||||||
/* LWIP_DEBUGF("ip_input: \n");
|
/* LWIP_DEBUGF("ip_input: \n");
|
||||||
ip_debug_print(p);
|
ip_debug_print(p);
|
||||||
LWIP_DEBUGF("ip_input: p->len %u p->tot_len %u\n", p->len, p->tot_len);*/
|
LWIP_DEBUGF("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len);*/
|
||||||
#endif /* IP_DEBUG */
|
#endif /* IP_DEBUG */
|
||||||
|
|
||||||
|
|
||||||
@@ -237,7 +237,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
|||||||
/* send ICMP destination protocol unreachable */
|
/* send ICMP destination protocol unreachable */
|
||||||
icmp_dest_unreach(p, ICMP_DUR_PROTO);
|
icmp_dest_unreach(p, ICMP_DUR_PROTO);
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("Unsupported transport protocol %u\n",
|
LWIP_DEBUGF(IP_DEBUG, ("Unsupported transport protocol %"U16_F"\n",
|
||||||
iphdr->nexthdr));
|
iphdr->nexthdr));
|
||||||
|
|
||||||
#ifdef IP_STATS
|
#ifdef IP_STATS
|
||||||
@@ -266,7 +266,7 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
|||||||
|
|
||||||
PERF_START;
|
PERF_START;
|
||||||
|
|
||||||
printf("len %u tot_len %u\n", p->len, p->tot_len);
|
printf("len %"U16_F" tot_len %"U16_F"\n", p->len, p->tot_len);
|
||||||
if (pbuf_header(p, IP_HLEN)) {
|
if (pbuf_header(p, IP_HLEN)) {
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("ip_output: not enough room for IP header in pbuf\n"));
|
LWIP_DEBUGF(IP_DEBUG, ("ip_output: not enough room for IP header in pbuf\n"));
|
||||||
#ifdef IP_STATS
|
#ifdef IP_STATS
|
||||||
@@ -275,7 +275,7 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
|||||||
|
|
||||||
return ERR_BUF;
|
return ERR_BUF;
|
||||||
}
|
}
|
||||||
printf("len %u tot_len %u\n", p->len, p->tot_len);
|
printf("len %"U16_F" tot_len %"U16_F"\n", p->len, p->tot_len);
|
||||||
|
|
||||||
iphdr = p->payload;
|
iphdr = p->payload;
|
||||||
|
|
||||||
@@ -303,7 +303,7 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
|||||||
++lwip_stats.ip.xmit;
|
++lwip_stats.ip.xmit;
|
||||||
#endif /* IP_STATS */
|
#endif /* IP_STATS */
|
||||||
|
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c (len %u)\n", netif->name[0], netif->name[1], p->tot_len));
|
LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c (len %"U16_F")\n", netif->name[0], netif->name[1], p->tot_len));
|
||||||
#if IP_DEBUG
|
#if IP_DEBUG
|
||||||
ip_debug_print(p);
|
ip_debug_print(p);
|
||||||
#endif /* IP_DEBUG */
|
#endif /* IP_DEBUG */
|
||||||
@@ -324,7 +324,7 @@ ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
|||||||
{
|
{
|
||||||
struct netif *netif;
|
struct netif *netif;
|
||||||
if ((netif = ip_route(dest)) == NULL) {
|
if ((netif = ip_route(dest)) == NULL) {
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%lx\n", dest->addr));
|
LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%"X32_F"\n", dest->addr));
|
||||||
#ifdef IP_STATS
|
#ifdef IP_STATS
|
||||||
++lwip_stats.ip.rterr;
|
++lwip_stats.ip.rterr;
|
||||||
#endif /* IP_STATS */
|
#endif /* IP_STATS */
|
||||||
@@ -339,45 +339,45 @@ void
|
|||||||
ip_debug_print(struct pbuf *p)
|
ip_debug_print(struct pbuf *p)
|
||||||
{
|
{
|
||||||
struct ip_hdr *iphdr = p->payload;
|
struct ip_hdr *iphdr = p->payload;
|
||||||
char *payload;
|
u8_t *payload;
|
||||||
|
|
||||||
payload = (char *)iphdr + IP_HLEN;
|
payload = (u8_t *)iphdr + IP_HLEN;
|
||||||
|
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
|
LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("|%2d | %x%x | %x%x | (v, traffic class, flow label)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" | %"X16_F"%"X16_F" | %"X16_F"%"X16_F" | (v, traffic class, flow label)\n",
|
||||||
iphdr->v,
|
iphdr->v,
|
||||||
iphdr->tclass1, iphdr->tclass2,
|
iphdr->tclass1, iphdr->tclass2,
|
||||||
iphdr->flow1, iphdr->flow2));
|
iphdr->flow1, iphdr->flow2));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("| %5u | %2u | %2u | (len, nexthdr, hoplim)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" | %2"U16_F" | %2"U16_F" | (len, nexthdr, hoplim)\n",
|
||||||
ntohs(iphdr->len),
|
ntohs(iphdr->len),
|
||||||
iphdr->nexthdr,
|
iphdr->nexthdr,
|
||||||
iphdr->hoplim));
|
iphdr->hoplim));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (src)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (src)\n",
|
||||||
ntohl(iphdr->src.addr[0]) >> 16 & 0xffff,
|
ntohl(iphdr->src.addr[0]) >> 16 & 0xffff,
|
||||||
ntohl(iphdr->src.addr[0]) & 0xffff));
|
ntohl(iphdr->src.addr[0]) & 0xffff));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (src)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (src)\n",
|
||||||
ntohl(iphdr->src.addr[1]) >> 16 & 0xffff,
|
ntohl(iphdr->src.addr[1]) >> 16 & 0xffff,
|
||||||
ntohl(iphdr->src.addr[1]) & 0xffff));
|
ntohl(iphdr->src.addr[1]) & 0xffff));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (src)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (src)\n",
|
||||||
ntohl(iphdr->src.addr[2]) >> 16 & 0xffff,
|
ntohl(iphdr->src.addr[2]) >> 16 & 0xffff,
|
||||||
ntohl(iphdr->src.addr[2]) & 0xffff));
|
ntohl(iphdr->src.addr[2]) & 0xffff));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (src)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (src)\n",
|
||||||
ntohl(iphdr->src.addr[3]) >> 16 & 0xffff,
|
ntohl(iphdr->src.addr[3]) >> 16 & 0xffff,
|
||||||
ntohl(iphdr->src.addr[3]) & 0xffff));
|
ntohl(iphdr->src.addr[3]) & 0xffff));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (dest)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (dest)\n",
|
||||||
ntohl(iphdr->dest.addr[0]) >> 16 & 0xffff,
|
ntohl(iphdr->dest.addr[0]) >> 16 & 0xffff,
|
||||||
ntohl(iphdr->dest.addr[0]) & 0xffff));
|
ntohl(iphdr->dest.addr[0]) & 0xffff));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (dest)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (dest)\n",
|
||||||
ntohl(iphdr->dest.addr[1]) >> 16 & 0xffff,
|
ntohl(iphdr->dest.addr[1]) >> 16 & 0xffff,
|
||||||
ntohl(iphdr->dest.addr[1]) & 0xffff));
|
ntohl(iphdr->dest.addr[1]) & 0xffff));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (dest)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (dest)\n",
|
||||||
ntohl(iphdr->dest.addr[2]) >> 16 & 0xffff,
|
ntohl(iphdr->dest.addr[2]) >> 16 & 0xffff,
|
||||||
ntohl(iphdr->dest.addr[2]) & 0xffff));
|
ntohl(iphdr->dest.addr[2]) & 0xffff));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (dest)\n",
|
LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (dest)\n",
|
||||||
ntohl(iphdr->dest.addr[3]) >> 16 & 0xffff,
|
ntohl(iphdr->dest.addr[3]) >> 16 & 0xffff,
|
||||||
ntohl(iphdr->dest.addr[3]) & 0xffff));
|
ntohl(iphdr->dest.addr[3]) & 0xffff));
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||||
|
|||||||
@@ -34,8 +34,8 @@
|
|||||||
#include "lwip/inet.h"
|
#include "lwip/inet.h"
|
||||||
|
|
||||||
|
|
||||||
int
|
u8_t
|
||||||
ip_addr_maskcmp(struct ip_addr *addr1, struct ip_addr *addr2,
|
ip_addr_netcmp(struct ip_addr *addr1, struct ip_addr *addr2,
|
||||||
struct ip_addr *mask)
|
struct ip_addr *mask)
|
||||||
{
|
{
|
||||||
return((addr1->addr[0] & mask->addr[0]) == (addr2->addr[0] & mask->addr[0]) &&
|
return((addr1->addr[0] & mask->addr[0]) == (addr2->addr[0] & mask->addr[0]) &&
|
||||||
@@ -45,7 +45,7 @@ ip_addr_maskcmp(struct ip_addr *addr1, struct ip_addr *addr2,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
u8_t
|
||||||
ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2)
|
ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2)
|
||||||
{
|
{
|
||||||
return(addr1->addr[0] == addr2->addr[0] &&
|
return(addr1->addr[0] == addr2->addr[0] &&
|
||||||
@@ -64,7 +64,7 @@ ip_addr_set(struct ip_addr *dest, struct ip_addr *src)
|
|||||||
dest->addr[3] = src->addr[3];*/
|
dest->addr[3] = src->addr[3];*/
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
u8_t
|
||||||
ip_addr_isany(struct ip_addr *addr)
|
ip_addr_isany(struct ip_addr *addr)
|
||||||
{
|
{
|
||||||
if (addr == NULL) return 1;
|
if (addr == NULL) return 1;
|
||||||
@@ -76,7 +76,7 @@ ip_addr_isany(struct ip_addr *addr)
|
|||||||
void
|
void
|
||||||
ip_addr_debug_print(struct ip_addr *addr)
|
ip_addr_debug_print(struct ip_addr *addr)
|
||||||
{
|
{
|
||||||
printf("%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx",
|
printf("%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F",
|
||||||
ntohl(addr->addr[0]) >> 16 & 0xffff,
|
ntohl(addr->addr[0]) >> 16 & 0xffff,
|
||||||
ntohl(addr->addr[0]) & 0xffff,
|
ntohl(addr->addr[0]) & 0xffff,
|
||||||
ntohl(addr->addr[1]) >> 16 & 0xffff,
|
ntohl(addr->addr[1]) >> 16 & 0xffff,
|
||||||
|
|||||||
@@ -301,7 +301,7 @@ mem_malloc(mem_size_t size)
|
|||||||
return (u8_t *)mem + SIZEOF_STRUCT_MEM;
|
return (u8_t *)mem + SIZEOF_STRUCT_MEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(MEM_DEBUG | 2, ("mem_malloc: could not allocate %d bytes\n", (int)size));
|
LWIP_DEBUGF(MEM_DEBUG | 2, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size));
|
||||||
#if MEM_STATS
|
#if MEM_STATS
|
||||||
++lwip_stats.mem.err;
|
++lwip_stats.mem.err;
|
||||||
#endif /* MEM_STATS */
|
#endif /* MEM_STATS */
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ static sys_sem_t mutex;
|
|||||||
static int
|
static int
|
||||||
memp_sanity(void)
|
memp_sanity(void)
|
||||||
{
|
{
|
||||||
int i, c;
|
s16_t i, c;
|
||||||
struct memp *m, *n;
|
struct memp *m, *n;
|
||||||
|
|
||||||
for(i = 0; i < MEMP_MAX; i++) {
|
for(i = 0; i < MEMP_MAX; i++) {
|
||||||
@@ -222,7 +222,7 @@ memp_malloc(memp_t type)
|
|||||||
mem = MEM_ALIGN((u8_t *)memp + sizeof(struct memp));
|
mem = MEM_ALIGN((u8_t *)memp + sizeof(struct memp));
|
||||||
return mem;
|
return mem;
|
||||||
} else {
|
} else {
|
||||||
LWIP_DEBUGF(MEMP_DEBUG | 2, ("memp_malloc: out of memory in pool %d\n", type));
|
LWIP_DEBUGF(MEMP_DEBUG | 2, ("memp_malloc: out of memory in pool %"S16_F"\n", type));
|
||||||
#if MEMP_STATS
|
#if MEMP_STATS
|
||||||
++lwip_stats.memp[type].err;
|
++lwip_stats.memp[type].err;
|
||||||
#endif /* MEMP_STATS */
|
#endif /* MEMP_STATS */
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
|
|||||||
err_t (* init)(struct netif *netif),
|
err_t (* init)(struct netif *netif),
|
||||||
err_t (* input)(struct pbuf *p, struct netif *netif))
|
err_t (* input)(struct pbuf *p, struct netif *netif))
|
||||||
{
|
{
|
||||||
static int netifnum = 0;
|
static s16_t netifnum = 0;
|
||||||
|
|
||||||
#if LWIP_DHCP
|
#if LWIP_DHCP
|
||||||
/* netif not under DHCP control by default */
|
/* netif not under DHCP control by default */
|
||||||
@@ -205,7 +205,7 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
|
|||||||
*/
|
*/
|
||||||
etharp_query(netif, ipaddr, NULL);
|
etharp_query(netif, ipaddr, NULL);
|
||||||
#endif
|
#endif
|
||||||
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: IP address of interface %c%c set to %u.%u.%u.%u\n",
|
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||||
netif->name[0], netif->name[1],
|
netif->name[0], netif->name[1],
|
||||||
ip4_addr1(&netif->ip_addr),
|
ip4_addr1(&netif->ip_addr),
|
||||||
ip4_addr2(&netif->ip_addr),
|
ip4_addr2(&netif->ip_addr),
|
||||||
@@ -217,7 +217,7 @@ void
|
|||||||
netif_set_gw(struct netif *netif, struct ip_addr *gw)
|
netif_set_gw(struct netif *netif, struct ip_addr *gw)
|
||||||
{
|
{
|
||||||
ip_addr_set(&(netif->gw), gw);
|
ip_addr_set(&(netif->gw), gw);
|
||||||
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: GW address of interface %c%c set to %u.%u.%u.%u\n",
|
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||||
netif->name[0], netif->name[1],
|
netif->name[0], netif->name[1],
|
||||||
ip4_addr1(&netif->gw),
|
ip4_addr1(&netif->gw),
|
||||||
ip4_addr2(&netif->gw),
|
ip4_addr2(&netif->gw),
|
||||||
@@ -229,7 +229,7 @@ void
|
|||||||
netif_set_netmask(struct netif *netif, struct ip_addr *netmask)
|
netif_set_netmask(struct netif *netif, struct ip_addr *netmask)
|
||||||
{
|
{
|
||||||
ip_addr_set(&(netif->netmask), netmask);
|
ip_addr_set(&(netif->netmask), netmask);
|
||||||
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: netmask of interface %c%c set to %u.%u.%u.%u\n",
|
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||||
netif->name[0], netif->name[1],
|
netif->name[0], netif->name[1],
|
||||||
ip4_addr1(&netif->netmask),
|
ip4_addr1(&netif->netmask),
|
||||||
ip4_addr2(&netif->netmask),
|
ip4_addr2(&netif->netmask),
|
||||||
|
|||||||
@@ -62,20 +62,18 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
#include "lwip/stats.h"
|
#include "lwip/stats.h"
|
||||||
|
|
||||||
#include "lwip/def.h"
|
#include "lwip/def.h"
|
||||||
#include "lwip/mem.h"
|
#include "lwip/mem.h"
|
||||||
#include "lwip/memp.h"
|
#include "lwip/memp.h"
|
||||||
#include "lwip/pbuf.h"
|
#include "lwip/pbuf.h"
|
||||||
|
|
||||||
#include "lwip/sys.h"
|
#include "lwip/sys.h"
|
||||||
|
|
||||||
#include "arch/perf.h"
|
#include "arch/perf.h"
|
||||||
|
|
||||||
static u8_t pbuf_pool_memory[(PBUF_POOL_SIZE * MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE + sizeof(struct pbuf)))];
|
static u8_t pbuf_pool_memory[MEM_ALIGNMENT - 1 + PBUF_POOL_SIZE * MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE + sizeof(struct pbuf))];
|
||||||
|
|
||||||
#if !SYS_LIGHTWEIGHT_PROT
|
#if !SYS_LIGHTWEIGHT_PROT
|
||||||
static volatile u8_t pbuf_pool_free_lock, pbuf_pool_alloc_lock;
|
static volatile u8_t pbuf_pool_free_lock, pbuf_pool_alloc_lock;
|
||||||
@@ -102,8 +100,7 @@ pbuf_init(void)
|
|||||||
struct pbuf *p, *q = NULL;
|
struct pbuf *p, *q = NULL;
|
||||||
u16_t i;
|
u16_t i;
|
||||||
|
|
||||||
pbuf_pool = (struct pbuf *)&pbuf_pool_memory[0];
|
pbuf_pool = (struct pbuf *)MEM_ALIGN(pbuf_pool_memory);
|
||||||
LWIP_ASSERT("pbuf_init: pool aligned", (mem_ptr_t)pbuf_pool % MEM_ALIGNMENT == 0);
|
|
||||||
|
|
||||||
#if PBUF_STATS
|
#if PBUF_STATS
|
||||||
lwip_stats.pbuf.avail = PBUF_POOL_SIZE;
|
lwip_stats.pbuf.avail = PBUF_POOL_SIZE;
|
||||||
@@ -183,7 +180,7 @@ pbuf_pool_alloc(void)
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocates a pbuf.
|
* Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type).
|
||||||
*
|
*
|
||||||
* The actual memory allocated for the pbuf is determined by the
|
* The actual memory allocated for the pbuf is determined by the
|
||||||
* layer at which the pbuf is allocated and the requested size
|
* layer at which the pbuf is allocated and the requested size
|
||||||
@@ -217,7 +214,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
|
|||||||
struct pbuf *p, *q, *r;
|
struct pbuf *p, *q, *r;
|
||||||
u16_t offset;
|
u16_t offset;
|
||||||
s32_t rem_len; /* remaining length */
|
s32_t rem_len; /* remaining length */
|
||||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc(length=%u)\n", length));
|
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc(length=%"U16_F")\n", length));
|
||||||
|
|
||||||
/* determine header offset */
|
/* determine header offset */
|
||||||
offset = 0;
|
offset = 0;
|
||||||
@@ -319,7 +316,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
|
|||||||
LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned",
|
LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned",
|
||||||
((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0);
|
((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0);
|
||||||
break;
|
break;
|
||||||
/* pbuf references existing (static constant) ROM payload? */
|
/* pbuf references existing (non-volatile static constant) ROM payload? */
|
||||||
case PBUF_ROM:
|
case PBUF_ROM:
|
||||||
/* pbuf references existing (externally allocated) RAM payload? */
|
/* pbuf references existing (externally allocated) RAM payload? */
|
||||||
case PBUF_REF:
|
case PBUF_REF:
|
||||||
@@ -341,7 +338,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
|
|||||||
}
|
}
|
||||||
/* set reference count */
|
/* set reference count */
|
||||||
p->ref = 1;
|
p->ref = 1;
|
||||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc(length=%u) == %p\n", length, (void *)p));
|
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p));
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -505,7 +502,7 @@ pbuf_header(struct pbuf *p, s16_t header_size_increment)
|
|||||||
p->len += header_size_increment;
|
p->len += header_size_increment;
|
||||||
p->tot_len += header_size_increment;
|
p->tot_len += header_size_increment;
|
||||||
|
|
||||||
LWIP_DEBUGF( PBUF_DEBUG, ("pbuf_header: old %p new %p (%d)\n",
|
LWIP_DEBUGF( PBUF_DEBUG, ("pbuf_header: old %p new %p (%"S16_F")\n",
|
||||||
(void *)payload, (void *)p->payload, header_size_increment));
|
(void *)payload, (void *)p->payload, header_size_increment));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -600,7 +597,7 @@ pbuf_free(struct pbuf *p)
|
|||||||
/* p->ref > 0, this pbuf is still referenced to */
|
/* p->ref > 0, this pbuf is still referenced to */
|
||||||
/* (and so the remaining pbufs in chain as well) */
|
/* (and so the remaining pbufs in chain as well) */
|
||||||
} else {
|
} else {
|
||||||
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: %p has ref %u, ending here.\n", (void *)p, (unsigned int)p->ref));
|
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, (u16_t)p->ref));
|
||||||
/* stop walking through the chain */
|
/* stop walking through the chain */
|
||||||
p = NULL;
|
p = NULL;
|
||||||
}
|
}
|
||||||
@@ -664,8 +661,8 @@ pbuf_cat(struct pbuf *h, struct pbuf *t)
|
|||||||
{
|
{
|
||||||
struct pbuf *p;
|
struct pbuf *p;
|
||||||
|
|
||||||
LWIP_ASSERT("h != NULL", h != NULL);
|
LWIP_ASSERT("h != NULL (programmer violates API)", h != NULL);
|
||||||
LWIP_ASSERT("t != NULL", t != NULL);
|
LWIP_ASSERT("t != NULL (programmer violates API)", t != NULL);
|
||||||
if ((h == NULL) || (t == NULL)) return;
|
if ((h == NULL) || (t == NULL)) return;
|
||||||
|
|
||||||
/* proceed to last pbuf of chain */
|
/* proceed to last pbuf of chain */
|
||||||
@@ -675,10 +672,14 @@ pbuf_cat(struct pbuf *h, struct pbuf *t)
|
|||||||
}
|
}
|
||||||
/* { p is last pbuf of first h chain, p->next == NULL } */
|
/* { p is last pbuf of first h chain, p->next == NULL } */
|
||||||
LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len);
|
LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len);
|
||||||
|
LWIP_ASSERT("p->next == NULL", p->next == NULL);
|
||||||
/* add total length of second chain to last pbuf total of first chain */
|
/* add total length of second chain to last pbuf total of first chain */
|
||||||
p->tot_len += t->tot_len;
|
p->tot_len += t->tot_len;
|
||||||
/* chain last pbuf of head (p) with first of tail (t) */
|
/* chain last pbuf of head (p) with first of tail (t) */
|
||||||
p->next = t;
|
p->next = t;
|
||||||
|
/* p->next now references t, but the caller will drop its reference to t,
|
||||||
|
* so netto there is no change to the reference count of t.
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -706,8 +707,8 @@ pbuf_chain(struct pbuf *h, struct pbuf *t)
|
|||||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t));
|
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For packet queueing. Note that queued packets must be dequeued first
|
/* For packet queueing. Note that queued packets MUST be dequeued first
|
||||||
* before calling any pbuf functions. */
|
* using pbuf_dequeue() before calling other pbuf_() functions. */
|
||||||
#if ARP_QUEUEING
|
#if ARP_QUEUEING
|
||||||
/**
|
/**
|
||||||
* Add a packet to the end of a queue.
|
* Add a packet to the end of a queue.
|
||||||
@@ -715,6 +716,7 @@ pbuf_chain(struct pbuf *h, struct pbuf *t)
|
|||||||
* @param q pointer to first packet on the queue
|
* @param q pointer to first packet on the queue
|
||||||
* @param n packet to be queued
|
* @param n packet to be queued
|
||||||
*
|
*
|
||||||
|
* Both packets MUST be given, and must be different.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
pbuf_queue(struct pbuf *p, struct pbuf *n)
|
pbuf_queue(struct pbuf *p, struct pbuf *n)
|
||||||
@@ -723,9 +725,13 @@ pbuf_queue(struct pbuf *p, struct pbuf *n)
|
|||||||
struct pbuf *q = p;
|
struct pbuf *q = p;
|
||||||
#endif
|
#endif
|
||||||
/* programmer stupidity checks */
|
/* programmer stupidity checks */
|
||||||
LWIP_ASSERT("p != NULL", p != NULL);
|
LWIP_ASSERT("p == NULL in pbuf_queue: this indicates a programmer error\n", p != NULL);
|
||||||
LWIP_ASSERT("n != NULL", n != NULL);
|
LWIP_ASSERT("n == NULL in pbuf_queue: this indicates a programmer error\n", n != NULL);
|
||||||
if ((p == NULL) || (n == NULL)) return;
|
LWIP_ASSERT("p == n in pbuf_queue: this indicates a programmer error\n", p != n);
|
||||||
|
if ((p == NULL) || (n == NULL) || (p == n)){
|
||||||
|
LWIP_DEBUGF(PBUF_DEBUG | DBG_HALT | 3, ("pbuf_queue: programmer argument error\n"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* iterate through all packets on queue */
|
/* iterate through all packets on queue */
|
||||||
while (p->next != NULL) {
|
while (p->next != NULL) {
|
||||||
@@ -787,7 +793,7 @@ pbuf_dequeue(struct pbuf *p)
|
|||||||
/* { p->tot_len == p->len } => p is the last pbuf of the first packet */
|
/* { p->tot_len == p->len } => p is the last pbuf of the first packet */
|
||||||
/* remember next packet on queue in q */
|
/* remember next packet on queue in q */
|
||||||
q = p->next;
|
q = p->next;
|
||||||
/* dequeue p from queue */
|
/* dequeue packet p from queue */
|
||||||
p->next = NULL;
|
p->next = NULL;
|
||||||
/* any next packet on queue? */
|
/* any next packet on queue? */
|
||||||
if (q != NULL) {
|
if (q != NULL) {
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ raw_input(struct pbuf *p, struct netif *inp)
|
|||||||
{
|
{
|
||||||
struct raw_pcb *pcb;
|
struct raw_pcb *pcb;
|
||||||
struct ip_hdr *iphdr;
|
struct ip_hdr *iphdr;
|
||||||
int proto;
|
s16_t proto;
|
||||||
u8_t eaten = 0;
|
u8_t eaten = 0;
|
||||||
|
|
||||||
iphdr = p->payload;
|
iphdr = p->payload;
|
||||||
@@ -224,7 +224,7 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((netif = ip_route(ipaddr)) == NULL) {
|
if ((netif = ip_route(ipaddr)) == NULL) {
|
||||||
LWIP_DEBUGF(RAW_DEBUG | 1, ("raw_sendto: No route to 0x%lx\n", ipaddr->addr));
|
LWIP_DEBUGF(RAW_DEBUG | 1, ("raw_sendto: No route to 0x%"X32_F"\n", ipaddr->addr));
|
||||||
#if RAW_STATS
|
#if RAW_STATS
|
||||||
/* ++lwip_stats.raw.rterr;*/
|
/* ++lwip_stats.raw.rterr;*/
|
||||||
#endif /* RAW_STATS */
|
#endif /* RAW_STATS */
|
||||||
|
|||||||
@@ -53,48 +53,48 @@ void
|
|||||||
stats_display_proto(struct stats_proto *proto, char *name)
|
stats_display_proto(struct stats_proto *proto, char *name)
|
||||||
{
|
{
|
||||||
LWIP_PLATFORM_DIAG(("\n%s\n\t", name));
|
LWIP_PLATFORM_DIAG(("\n%s\n\t", name));
|
||||||
LWIP_PLATFORM_DIAG(("xmit: %d\n\t", proto->xmit));
|
LWIP_PLATFORM_DIAG(("xmit: %"S16_F"\n\t", proto->xmit));
|
||||||
LWIP_PLATFORM_DIAG(("rexmit: %d\n\t", proto->rexmit));
|
LWIP_PLATFORM_DIAG(("rexmit: %"S16_F"\n\t", proto->rexmit));
|
||||||
LWIP_PLATFORM_DIAG(("recv: %d\n\t", proto->recv));
|
LWIP_PLATFORM_DIAG(("recv: %"S16_F"\n\t", proto->recv));
|
||||||
LWIP_PLATFORM_DIAG(("fw: %d\n\t", proto->fw));
|
LWIP_PLATFORM_DIAG(("fw: %"S16_F"\n\t", proto->fw));
|
||||||
LWIP_PLATFORM_DIAG(("drop: %d\n\t", proto->drop));
|
LWIP_PLATFORM_DIAG(("drop: %"S16_F"\n\t", proto->drop));
|
||||||
LWIP_PLATFORM_DIAG(("chkerr: %d\n\t", proto->chkerr));
|
LWIP_PLATFORM_DIAG(("chkerr: %"S16_F"\n\t", proto->chkerr));
|
||||||
LWIP_PLATFORM_DIAG(("lenerr: %d\n\t", proto->lenerr));
|
LWIP_PLATFORM_DIAG(("lenerr: %"S16_F"\n\t", proto->lenerr));
|
||||||
LWIP_PLATFORM_DIAG(("memerr: %d\n\t", proto->memerr));
|
LWIP_PLATFORM_DIAG(("memerr: %"S16_F"\n\t", proto->memerr));
|
||||||
LWIP_PLATFORM_DIAG(("rterr: %d\n\t", proto->rterr));
|
LWIP_PLATFORM_DIAG(("rterr: %"S16_F"\n\t", proto->rterr));
|
||||||
LWIP_PLATFORM_DIAG(("proterr: %d\n\t", proto->proterr));
|
LWIP_PLATFORM_DIAG(("proterr: %"S16_F"\n\t", proto->proterr));
|
||||||
LWIP_PLATFORM_DIAG(("opterr: %d\n\t", proto->opterr));
|
LWIP_PLATFORM_DIAG(("opterr: %"S16_F"\n\t", proto->opterr));
|
||||||
LWIP_PLATFORM_DIAG(("err: %d\n\t", proto->err));
|
LWIP_PLATFORM_DIAG(("err: %"S16_F"\n\t", proto->err));
|
||||||
LWIP_PLATFORM_DIAG(("cachehit: %d\n", proto->cachehit));
|
LWIP_PLATFORM_DIAG(("cachehit: %"S16_F"\n", proto->cachehit));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stats_display_pbuf(struct stats_pbuf *pbuf)
|
stats_display_pbuf(struct stats_pbuf *pbuf)
|
||||||
{
|
{
|
||||||
LWIP_PLATFORM_DIAG(("\nPBUF\n\t"));
|
LWIP_PLATFORM_DIAG(("\nPBUF\n\t"));
|
||||||
LWIP_PLATFORM_DIAG(("avail: %d\n\t", pbuf->avail));
|
LWIP_PLATFORM_DIAG(("avail: %"S16_F"\n\t", pbuf->avail));
|
||||||
LWIP_PLATFORM_DIAG(("used: %d\n\t", pbuf->used));
|
LWIP_PLATFORM_DIAG(("used: %"S16_F"\n\t", pbuf->used));
|
||||||
LWIP_PLATFORM_DIAG(("max: %d\n\t", pbuf->max));
|
LWIP_PLATFORM_DIAG(("max: %"S16_F"\n\t", pbuf->max));
|
||||||
LWIP_PLATFORM_DIAG(("err: %d\n\t", pbuf->err));
|
LWIP_PLATFORM_DIAG(("err: %"S16_F"\n\t", pbuf->err));
|
||||||
LWIP_PLATFORM_DIAG(("alloc_locked: %d\n\t", pbuf->alloc_locked));
|
LWIP_PLATFORM_DIAG(("alloc_locked: %"S16_F"\n\t", pbuf->alloc_locked));
|
||||||
LWIP_PLATFORM_DIAG(("refresh_locked: %d\n", pbuf->refresh_locked));
|
LWIP_PLATFORM_DIAG(("refresh_locked: %"S16_F"\n", pbuf->refresh_locked));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stats_display_mem(struct stats_mem *mem, char *name)
|
stats_display_mem(struct stats_mem *mem, char *name)
|
||||||
{
|
{
|
||||||
LWIP_PLATFORM_DIAG(("\n MEM %s\n\t", name));
|
LWIP_PLATFORM_DIAG(("\n MEM %s\n\t", name));
|
||||||
LWIP_PLATFORM_DIAG(("avail: %d\n\t", mem->avail));
|
LWIP_PLATFORM_DIAG(("avail: %"S16_F"\n\t", mem->avail));
|
||||||
LWIP_PLATFORM_DIAG(("used: %d\n\t", mem->used));
|
LWIP_PLATFORM_DIAG(("used: %"S16_F"\n\t", mem->used));
|
||||||
LWIP_PLATFORM_DIAG(("max: %d\n\t", mem->max));
|
LWIP_PLATFORM_DIAG(("max: %"S16_F"\n\t", mem->max));
|
||||||
LWIP_PLATFORM_DIAG(("err: %d\n", mem->err));
|
LWIP_PLATFORM_DIAG(("err: %"S16_F"\n", mem->err));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stats_display(void)
|
stats_display(void)
|
||||||
{
|
{
|
||||||
int i;
|
s16_t i;
|
||||||
char * memp_names[] = {"PBUF", "RAW_PCB", "UDP_PCB", "TCP_PCB", "TCP_PCB_LISTEN",
|
char * memp_names[] = {"PBUF", "RAW_PCB", "UDP_PCB", "TCP_PCB", "TCP_PCB_LISTEN",
|
||||||
"TCP_SEG", "NETBUF", "NETCONN", "API_MSG", "TCP_MSG", "TIMEOUT"};
|
"TCP_SEG", "NETBUF", "NETCONN", "API_MSG", "TCP_MSG", "TIMEOUT"};
|
||||||
stats_display_proto(&lwip_stats.link, "LINK");
|
stats_display_proto(&lwip_stats.link, "LINK");
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
struct sswt_cb
|
struct sswt_cb
|
||||||
{
|
{
|
||||||
int timeflag;
|
s16_t timeflag;
|
||||||
sys_sem_t *psem;
|
sys_sem_t *psem;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -170,7 +170,7 @@ sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
|
|||||||
|
|
||||||
timeouts = sys_arch_timeouts();
|
timeouts = sys_arch_timeouts();
|
||||||
|
|
||||||
LWIP_DEBUGF(SYS_DEBUG, ("sys_timeout: %p msecs=%lu h=%p arg=%p\n",
|
LWIP_DEBUGF(SYS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" h=%p arg=%p\n",
|
||||||
(void *)timeout, msecs, (void *)h, (void *)arg));
|
(void *)timeout, msecs, (void *)h, (void *)arg));
|
||||||
|
|
||||||
LWIP_ASSERT("sys_timeout: timeouts != NULL", timeouts != NULL);
|
LWIP_ASSERT("sys_timeout: timeouts != NULL", timeouts != NULL);
|
||||||
|
|||||||
144
src/core/tcp.c
144
src/core/tcp.c
@@ -237,14 +237,10 @@ err_t
|
|||||||
tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
||||||
{
|
{
|
||||||
struct tcp_pcb *cpcb;
|
struct tcp_pcb *cpcb;
|
||||||
#if SO_REUSE
|
|
||||||
int reuse_port_all_set = 1;
|
|
||||||
#endif /* SO_REUSE */
|
|
||||||
|
|
||||||
if (port == 0) {
|
if (port == 0) {
|
||||||
port = tcp_new_port();
|
port = tcp_new_port();
|
||||||
}
|
}
|
||||||
#if SO_REUSE == 0
|
|
||||||
/* Check if the address already is in use. */
|
/* Check if the address already is in use. */
|
||||||
for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs;
|
for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs;
|
||||||
cpcb != NULL; cpcb = cpcb->next) {
|
cpcb != NULL; cpcb = cpcb->next) {
|
||||||
@@ -266,107 +262,12 @@ tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else /* SO_REUSE */
|
|
||||||
/* Search through list of PCB's in LISTEN state.
|
|
||||||
|
|
||||||
If there is a PCB bound to specified port and IP_ADDR_ANY another PCB can be bound to the interface IP
|
|
||||||
or to the loopback address on the same port if SOF_REUSEADDR is set. Any combination of PCB's bound to
|
|
||||||
the same local port, but to one address out of {IP_ADDR_ANY, 127.0.0.1, interface IP} at a time is valid.
|
|
||||||
But no two PCB's bound to same local port and same local address is valid.
|
|
||||||
|
|
||||||
If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then
|
|
||||||
all PCB's must have the SOF_REUSEPORT option set.
|
|
||||||
|
|
||||||
When the two options aren't set and specified port is already bound, ERR_USE is returned saying that
|
|
||||||
address is already in use. */
|
|
||||||
for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; cpcb != NULL; cpcb = cpcb->next) {
|
|
||||||
if(cpcb->local_port == port) {
|
|
||||||
if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
|
|
||||||
if(pcb->so_options & SOF_REUSEPORT) {
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's: SO_REUSEPORT set and same address.\n"));
|
|
||||||
reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's: SO_REUSEPORT not set and same address.\n"));
|
|
||||||
return ERR_USE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(cpcb->local_ip))) ||
|
|
||||||
(!ip_addr_isany(ipaddr) && ip_addr_isany(&(cpcb->local_ip)))) {
|
|
||||||
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
|
|
||||||
return ERR_USE;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's SO_REUSEPORT or SO_REUSEADDR set and not the same address.\n"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Search through list of PCB's in a state in which they can accept or send data. Same decription as for
|
|
||||||
PCB's in state LISTEN applies to this PCB's regarding the options SOF_REUSEADDR and SOF_REUSEPORT. */
|
|
||||||
for(cpcb = tcp_active_pcbs; cpcb != NULL; cpcb = cpcb->next) {
|
|
||||||
if(cpcb->local_port == port) {
|
|
||||||
if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
|
|
||||||
if(pcb->so_options & SOF_REUSEPORT) {
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT set and same address.\n"));
|
|
||||||
reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT not set and same address.\n"));
|
|
||||||
return ERR_USE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(cpcb->local_ip))) ||
|
|
||||||
(!ip_addr_isany(ipaddr) && ip_addr_isany(&(cpcb->local_ip)))) {
|
|
||||||
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
|
|
||||||
return ERR_USE;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT or SO_REUSEADDR set and not the same address.\n"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Search through list of PCB's in TIME_WAIT state. If SO_REUSEADDR is set a bound combination [IP, port}
|
|
||||||
can be rebound. The same applies when SOF_REUSEPORT is set.
|
|
||||||
|
|
||||||
If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then
|
|
||||||
all PCB's must have the SOF_REUSEPORT option set.
|
|
||||||
|
|
||||||
When the two options aren't set and specified port is already bound, ERR_USE is returned saying that
|
|
||||||
address is already in use. */
|
|
||||||
for(cpcb = tcp_tw_pcbs; cpcb != NULL; cpcb = cpcb->next) {
|
|
||||||
if(cpcb->local_port == port) {
|
|
||||||
if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
|
|
||||||
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in TIME_WAIT PCB's SO_REUSEPORT or SO_REUSEADDR not set and same address.\n"));
|
|
||||||
return ERR_USE;
|
|
||||||
}
|
|
||||||
else if(pcb->so_options & SOF_REUSEPORT) {
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in TIME_WAIT PCB's SO_REUSEPORT set and same address.\n"));
|
|
||||||
reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If SOF_REUSEPORT isn't set in all PCB's bound to specified port and local address specified then
|
|
||||||
{IP, port} can't be reused. */
|
|
||||||
if(!reuse_port_all_set) {
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: not all sockets have SO_REUSEPORT set.\n"));
|
|
||||||
return ERR_USE;
|
|
||||||
}
|
|
||||||
#endif /* SO_REUSE */
|
|
||||||
|
|
||||||
if (!ip_addr_isany(ipaddr)) {
|
if (!ip_addr_isany(ipaddr)) {
|
||||||
pcb->local_ip = *ipaddr;
|
pcb->local_ip = *ipaddr;
|
||||||
}
|
}
|
||||||
pcb->local_port = port;
|
pcb->local_port = port;
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %u\n", port));
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"\n", port));
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
#if LWIP_CALLBACK_API
|
#if LWIP_CALLBACK_API
|
||||||
@@ -456,7 +357,7 @@ tcp_recved(struct tcp_pcb *pcb, u16_t len)
|
|||||||
tcp_ack_now(pcb);
|
tcp_ack_now(pcb);
|
||||||
}
|
}
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %u bytes, wnd %u (%u).\n",
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %"U16_F" bytes, wnd %"U16_F" (%"U16_F").\n",
|
||||||
len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd));
|
len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -510,7 +411,7 @@ tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
|
|||||||
err_t ret;
|
err_t ret;
|
||||||
u32_t iss;
|
u32_t iss;
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %u\n", port));
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port));
|
||||||
if (ipaddr != NULL) {
|
if (ipaddr != NULL) {
|
||||||
pcb->remote_ip = *ipaddr;
|
pcb->remote_ip = *ipaddr;
|
||||||
} else {
|
} else {
|
||||||
@@ -592,7 +493,7 @@ tcp_slowtmr(void)
|
|||||||
if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) {
|
if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) {
|
||||||
|
|
||||||
/* Time for a retransmission. */
|
/* Time for a retransmission. */
|
||||||
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %u pcb->rto %u\n",
|
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"U16_F" pcb->rto %"U16_F"\n",
|
||||||
pcb->rtime, pcb->rto));
|
pcb->rtime, pcb->rto));
|
||||||
|
|
||||||
/* Double retransmission time-out unless we are trying to
|
/* Double retransmission time-out unless we are trying to
|
||||||
@@ -607,7 +508,7 @@ tcp_slowtmr(void)
|
|||||||
pcb->ssthresh = pcb->mss * 2;
|
pcb->ssthresh = pcb->mss * 2;
|
||||||
}
|
}
|
||||||
pcb->cwnd = pcb->mss;
|
pcb->cwnd = pcb->mss;
|
||||||
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %u ssthresh %u\n",
|
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"U16_F" ssthresh %"U16_F"\n",
|
||||||
pcb->cwnd, pcb->ssthresh));
|
pcb->cwnd, pcb->ssthresh));
|
||||||
|
|
||||||
/* The following needs to be called AFTER cwnd is set to one mss - STJ */
|
/* The following needs to be called AFTER cwnd is set to one mss - STJ */
|
||||||
@@ -626,7 +527,7 @@ tcp_slowtmr(void)
|
|||||||
/* Check if KEEPALIVE should be sent */
|
/* Check if KEEPALIVE should be sent */
|
||||||
if((pcb->so_options & SOF_KEEPALIVE) && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) {
|
if((pcb->so_options & SOF_KEEPALIVE) && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) {
|
||||||
if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + TCP_MAXIDLE) / TCP_SLOW_INTERVAL) {
|
if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + TCP_MAXIDLE) / TCP_SLOW_INTERVAL) {
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %u.%u.%u.%u.\n",
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %"U16_F".%"U16_F".%"U16_F".%"U16_F".\n",
|
||||||
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
|
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
|
||||||
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
|
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
|
||||||
|
|
||||||
@@ -654,12 +555,19 @@ tcp_slowtmr(void)
|
|||||||
/* Check if this PCB has stayed too long in SYN-RCVD */
|
/* Check if this PCB has stayed too long in SYN-RCVD */
|
||||||
if (pcb->state == SYN_RCVD) {
|
if (pcb->state == SYN_RCVD) {
|
||||||
if ((u32_t)(tcp_ticks - pcb->tmr) >
|
if ((u32_t)(tcp_ticks - pcb->tmr) >
|
||||||
TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) {
|
TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) {
|
||||||
++pcb_remove;
|
++pcb_remove;
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check if this PCB has stayed too long in LAST-ACK */
|
||||||
|
if (pcb->state == LAST_ACK) {
|
||||||
|
if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) {
|
||||||
|
++pcb_remove;
|
||||||
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in LAST-ACK\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* If the PCB should be removed, do it. */
|
/* If the PCB should be removed, do it. */
|
||||||
if (pcb_remove) {
|
if (pcb_remove) {
|
||||||
@@ -814,7 +722,7 @@ tcp_seg_copy(struct tcp_seg *seg)
|
|||||||
if (cseg == NULL) {
|
if (cseg == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
memcpy((char *)cseg, (const char *)seg, sizeof(struct tcp_seg));
|
memcpy((u8_t *)cseg, (const u8_t *)seg, sizeof(struct tcp_seg));
|
||||||
pbuf_ref(cseg->p);
|
pbuf_ref(cseg->p);
|
||||||
return cseg;
|
return cseg;
|
||||||
}
|
}
|
||||||
@@ -858,7 +766,7 @@ tcp_kill_prio(u8_t prio)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (inactive != NULL) {
|
if (inactive != NULL) {
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB 0x%p (%ld)\n",
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n",
|
||||||
(void *)inactive, inactivity));
|
(void *)inactive, inactivity));
|
||||||
tcp_abort(inactive);
|
tcp_abort(inactive);
|
||||||
}
|
}
|
||||||
@@ -880,7 +788,7 @@ tcp_kill_timewait(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (inactive != NULL) {
|
if (inactive != NULL) {
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB 0x%p (%ld)\n",
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F")\n",
|
||||||
(void *)inactive, inactivity));
|
(void *)inactive, inactivity));
|
||||||
tcp_abort(inactive);
|
tcp_abort(inactive);
|
||||||
}
|
}
|
||||||
@@ -1112,16 +1020,16 @@ tcp_debug_print(struct tcp_hdr *tcphdr)
|
|||||||
{
|
{
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n"));
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("| %5u | %5u | (src port, dest port)\n",
|
LWIP_DEBUGF(TCP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n",
|
||||||
ntohs(tcphdr->src), ntohs(tcphdr->dest)));
|
ntohs(tcphdr->src), ntohs(tcphdr->dest)));
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("| %010lu | (seq no)\n",
|
LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (seq no)\n",
|
||||||
ntohl(tcphdr->seqno)));
|
ntohl(tcphdr->seqno)));
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("| %010lu | (ack no)\n",
|
LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (ack no)\n",
|
||||||
ntohl(tcphdr->ackno)));
|
ntohl(tcphdr->ackno)));
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("| %2u | |%u%u%u%u%u%u| %5u | (hdrlen, flags (",
|
LWIP_DEBUGF(TCP_DEBUG, ("| %2"U16_F" | |%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"| %5"U16_F" | (hdrlen, flags (",
|
||||||
TCPH_HDRLEN(tcphdr),
|
TCPH_HDRLEN(tcphdr),
|
||||||
TCPH_FLAGS(tcphdr) >> 5 & 1,
|
TCPH_FLAGS(tcphdr) >> 5 & 1,
|
||||||
TCPH_FLAGS(tcphdr) >> 4 & 1,
|
TCPH_FLAGS(tcphdr) >> 4 & 1,
|
||||||
@@ -1133,7 +1041,7 @@ tcp_debug_print(struct tcp_hdr *tcphdr)
|
|||||||
tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
|
tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("), win)\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("), win)\n"));
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04x | %5u | (chksum, urgp)\n",
|
LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04"X16_F" | %5"U16_F" | (chksum, urgp)\n",
|
||||||
ntohs(tcphdr->chksum), ntohs(tcphdr->urgp)));
|
ntohs(tcphdr->chksum), ntohs(tcphdr->urgp)));
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
|
||||||
}
|
}
|
||||||
@@ -1214,28 +1122,28 @@ tcp_debug_print_pcbs(void)
|
|||||||
struct tcp_pcb *pcb;
|
struct tcp_pcb *pcb;
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n"));
|
||||||
for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
|
for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("Local port %u, foreign port %u snd_nxt %lu rcv_nxt %lu ",
|
LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ",
|
||||||
pcb->local_port, pcb->remote_port,
|
pcb->local_port, pcb->remote_port,
|
||||||
pcb->snd_nxt, pcb->rcv_nxt));
|
pcb->snd_nxt, pcb->rcv_nxt));
|
||||||
tcp_debug_print_state(pcb->state);
|
tcp_debug_print_state(pcb->state);
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n"));
|
||||||
for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {
|
for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("Local port %u, foreign port %u snd_nxt %lu rcv_nxt %lu ",
|
LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ",
|
||||||
pcb->local_port, pcb->remote_port,
|
pcb->local_port, pcb->remote_port,
|
||||||
pcb->snd_nxt, pcb->rcv_nxt));
|
pcb->snd_nxt, pcb->rcv_nxt));
|
||||||
tcp_debug_print_state(pcb->state);
|
tcp_debug_print_state(pcb->state);
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n"));
|
LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n"));
|
||||||
for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
|
for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("Local port %u, foreign port %u snd_nxt %lu rcv_nxt %lu ",
|
LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ",
|
||||||
pcb->local_port, pcb->remote_port,
|
pcb->local_port, pcb->remote_port,
|
||||||
pcb->snd_nxt, pcb->rcv_nxt));
|
pcb->snd_nxt, pcb->rcv_nxt));
|
||||||
tcp_debug_print_state(pcb->state);
|
tcp_debug_print_state(pcb->state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
s16_t
|
||||||
tcp_pcbs_sane(void)
|
tcp_pcbs_sane(void)
|
||||||
{
|
{
|
||||||
struct tcp_pcb *pcb;
|
struct tcp_pcb *pcb;
|
||||||
|
|||||||
@@ -97,12 +97,6 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|||||||
u8_t hdrlen;
|
u8_t hdrlen;
|
||||||
err_t err;
|
err_t err;
|
||||||
|
|
||||||
#if SO_REUSE
|
|
||||||
struct tcp_pcb *pcb_temp;
|
|
||||||
int reuse = 0;
|
|
||||||
int reuse_port = 0;
|
|
||||||
#endif /* SO_REUSE */
|
|
||||||
|
|
||||||
PERF_START;
|
PERF_START;
|
||||||
|
|
||||||
TCP_STATS_INC(tcp.recv);
|
TCP_STATS_INC(tcp.recv);
|
||||||
@@ -117,7 +111,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|||||||
/* remove header from payload */
|
/* remove header from payload */
|
||||||
if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) {
|
if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) {
|
||||||
/* drop short packets */
|
/* drop short packets */
|
||||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%u bytes) discarded\n", p->tot_len));
|
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len));
|
||||||
TCP_STATS_INC(tcp.lenerr);
|
TCP_STATS_INC(tcp.lenerr);
|
||||||
TCP_STATS_INC(tcp.drop);
|
TCP_STATS_INC(tcp.drop);
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
@@ -136,7 +130,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|||||||
if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
|
if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
|
||||||
(struct ip_addr *)&(iphdr->dest),
|
(struct ip_addr *)&(iphdr->dest),
|
||||||
IP_PROTO_TCP, p->tot_len) != 0) {
|
IP_PROTO_TCP, p->tot_len) != 0) {
|
||||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04x\n",
|
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n",
|
||||||
inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src), (struct ip_addr *)&(iphdr->dest),
|
inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src), (struct ip_addr *)&(iphdr->dest),
|
||||||
IP_PROTO_TCP, p->tot_len)));
|
IP_PROTO_TCP, p->tot_len)));
|
||||||
#if TCP_DEBUG
|
#if TCP_DEBUG
|
||||||
@@ -169,16 +163,8 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|||||||
for an active connection. */
|
for an active connection. */
|
||||||
prev = NULL;
|
prev = NULL;
|
||||||
|
|
||||||
#if SO_REUSE
|
|
||||||
pcb_temp = tcp_active_pcbs;
|
|
||||||
|
|
||||||
again_1:
|
|
||||||
|
|
||||||
/* Iterate through the TCP pcb list for a fully matching pcb */
|
|
||||||
for(pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
|
|
||||||
#else /* SO_REUSE */
|
|
||||||
for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
|
for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
|
||||||
#endif /* SO_REUSE */
|
|
||||||
LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);
|
LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);
|
||||||
LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
|
LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
|
||||||
LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
|
LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
|
||||||
@@ -187,32 +173,6 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|||||||
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
|
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
|
||||||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
|
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
|
||||||
|
|
||||||
#if SO_REUSE
|
|
||||||
if(pcb->so_options & SOF_REUSEPORT) {
|
|
||||||
if(reuse) {
|
|
||||||
/* We processed one PCB already */
|
|
||||||
LWIP_DEBUGF(TCP_INPUT_DEBUG,("tcp_input: second or later PCB and SOF_REUSEPORT set.\n"));
|
|
||||||
} else {
|
|
||||||
/* First PCB with this address */
|
|
||||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: first PCB and SOF_REUSEPORT set.\n"));
|
|
||||||
reuse = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
reuse_port = 1;
|
|
||||||
p->ref++;
|
|
||||||
|
|
||||||
/* We want to search on next socket after receiving */
|
|
||||||
pcb_temp = pcb->next;
|
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: reference counter on PBUF set to %i\n", p->ref));
|
|
||||||
} else {
|
|
||||||
if(reuse) {
|
|
||||||
/* We processed one PCB already */
|
|
||||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* SO_REUSE */
|
|
||||||
|
|
||||||
/* Move this PCB to the front of the list so that subsequent
|
/* Move this PCB to the front of the list so that subsequent
|
||||||
lookups will be faster (we exploit locality in TCP segment
|
lookups will be faster (we exploit locality in TCP segment
|
||||||
arrivals). */
|
arrivals). */
|
||||||
@@ -357,25 +317,9 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|||||||
tcp_debug_print_state(pcb->state);
|
tcp_debug_print_state(pcb->state);
|
||||||
#endif /* TCP_DEBUG */
|
#endif /* TCP_DEBUG */
|
||||||
#endif /* TCP_INPUT_DEBUG */
|
#endif /* TCP_INPUT_DEBUG */
|
||||||
#if SO_REUSE
|
|
||||||
/* First socket should receive now */
|
|
||||||
if(reuse_port) {
|
|
||||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: searching next PCB.\n"));
|
|
||||||
reuse_port = 0;
|
|
||||||
|
|
||||||
/* We are searching connected sockets */
|
|
||||||
goto again_1;
|
|
||||||
}
|
|
||||||
#endif /* SO_REUSE */
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
#if SO_REUSE
|
|
||||||
if(reuse) {
|
|
||||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: freeing PBUF with reference counter set to %i\n", p->ref));
|
|
||||||
pbuf_free(p);
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
#endif /* SO_REUSE */
|
|
||||||
/* If no matching PCB was found, send a TCP RST (reset) to the
|
/* If no matching PCB was found, send a TCP RST (reset) to the
|
||||||
sender. */
|
sender. */
|
||||||
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n"));
|
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n"));
|
||||||
@@ -388,9 +332,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|||||||
}
|
}
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
}
|
}
|
||||||
#if SO_REUSE
|
|
||||||
end:
|
|
||||||
#endif /* SO_REUSE */
|
|
||||||
LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
|
LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
|
||||||
PERF_STOP("tcp_input");
|
PERF_STOP("tcp_input");
|
||||||
}
|
}
|
||||||
@@ -417,7 +359,7 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
|
|||||||
&(iphdr->dest), &(iphdr->src),
|
&(iphdr->dest), &(iphdr->src),
|
||||||
tcphdr->dest, tcphdr->src);
|
tcphdr->dest, tcphdr->src);
|
||||||
} else if (flags & TCP_SYN) {
|
} else if (flags & TCP_SYN) {
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %u -> %u.\n", tcphdr->src, tcphdr->dest));
|
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));
|
||||||
npcb = tcp_alloc(pcb->prio);
|
npcb = tcp_alloc(pcb->prio);
|
||||||
/* If a new PCB could not be created (probably due to lack of memory),
|
/* If a new PCB could not be created (probably due to lack of memory),
|
||||||
we don't do anything, but rely on the sender will retransmit the
|
we don't do anything, but rely on the sender will retransmit the
|
||||||
@@ -503,13 +445,13 @@ tcp_process(struct tcp_pcb *pcb)
|
|||||||
/* First, determine if the reset is acceptable. */
|
/* First, determine if the reset is acceptable. */
|
||||||
if (pcb->state == SYN_SENT) {
|
if (pcb->state == SYN_SENT) {
|
||||||
if (ackno == pcb->snd_nxt) {
|
if (ackno == pcb->snd_nxt) {
|
||||||
acceptable = 1;
|
acceptable = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/*if (TCP_SEQ_GEQ(seqno, pcb->rcv_nxt) &&
|
/*if (TCP_SEQ_GEQ(seqno, pcb->rcv_nxt) &&
|
||||||
TCP_SEQ_LEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {
|
TCP_SEQ_LEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {
|
||||||
*/
|
*/
|
||||||
if(TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)){
|
if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) {
|
||||||
acceptable = 1;
|
acceptable = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -521,9 +463,9 @@ tcp_process(struct tcp_pcb *pcb)
|
|||||||
pcb->flags &= ~TF_ACK_DELAY;
|
pcb->flags &= ~TF_ACK_DELAY;
|
||||||
return ERR_RST;
|
return ERR_RST;
|
||||||
} else {
|
} else {
|
||||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %lu rcv_nxt %lu\n",
|
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n",
|
||||||
seqno, pcb->rcv_nxt));
|
seqno, pcb->rcv_nxt));
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %lu rcv_nxt %lu\n",
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n",
|
||||||
seqno, pcb->rcv_nxt));
|
seqno, pcb->rcv_nxt));
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
@@ -536,10 +478,12 @@ tcp_process(struct tcp_pcb *pcb)
|
|||||||
/* Do different things depending on the TCP state. */
|
/* Do different things depending on the TCP state. */
|
||||||
switch (pcb->state) {
|
switch (pcb->state) {
|
||||||
case SYN_SENT:
|
case SYN_SENT:
|
||||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %lu pcb->snd_nxt %lu unacked %lu\n", ackno,
|
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno,
|
||||||
pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno)));
|
pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno)));
|
||||||
|
/* received SYN ACK with expected sequence number? */
|
||||||
if ((flags & TCP_ACK) && (flags & TCP_SYN)
|
if ((flags & TCP_ACK) && (flags & TCP_SYN)
|
||||||
&& ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) {
|
&& ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) {
|
||||||
|
pcb->snd_buf++;
|
||||||
pcb->rcv_nxt = seqno + 1;
|
pcb->rcv_nxt = seqno + 1;
|
||||||
pcb->lastack = ackno;
|
pcb->lastack = ackno;
|
||||||
pcb->snd_wnd = tcphdr->wnd;
|
pcb->snd_wnd = tcphdr->wnd;
|
||||||
@@ -547,7 +491,7 @@ tcp_process(struct tcp_pcb *pcb)
|
|||||||
pcb->state = ESTABLISHED;
|
pcb->state = ESTABLISHED;
|
||||||
pcb->cwnd = pcb->mss;
|
pcb->cwnd = pcb->mss;
|
||||||
--pcb->snd_queuelen;
|
--pcb->snd_queuelen;
|
||||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %u\n", (unsigned int)pcb->snd_queuelen));
|
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"U16_F"\n", (u16_t)pcb->snd_queuelen));
|
||||||
rseg = pcb->unacked;
|
rseg = pcb->unacked;
|
||||||
pcb->unacked = rseg->next;
|
pcb->unacked = rseg->next;
|
||||||
tcp_seg_free(rseg);
|
tcp_seg_free(rseg);
|
||||||
@@ -560,15 +504,20 @@ tcp_process(struct tcp_pcb *pcb)
|
|||||||
TCP_EVENT_CONNECTED(pcb, ERR_OK, err);
|
TCP_EVENT_CONNECTED(pcb, ERR_OK, err);
|
||||||
tcp_ack(pcb);
|
tcp_ack(pcb);
|
||||||
}
|
}
|
||||||
|
/* received ACK? possibly a half-open connection */
|
||||||
|
else if (flags & TCP_ACK) {
|
||||||
|
/* send a RST to bring the other side in a non-synchronized state. */
|
||||||
|
tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
|
||||||
|
tcphdr->dest, tcphdr->src);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SYN_RCVD:
|
case SYN_RCVD:
|
||||||
if (flags & TCP_ACK &&
|
if (flags & TCP_ACK &&
|
||||||
!(flags & TCP_RST)) {
|
!(flags & TCP_RST)) {
|
||||||
/*if (TCP_SEQ_LT(pcb->lastack, ackno) &&
|
/* expected ACK number? */
|
||||||
TCP_SEQ_LEQ(ackno, pcb->snd_nxt)) { */
|
if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) {
|
||||||
if(TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){
|
|
||||||
pcb->state = ESTABLISHED;
|
pcb->state = ESTABLISHED;
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %u -> %u.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
||||||
#if LWIP_CALLBACK_API
|
#if LWIP_CALLBACK_API
|
||||||
LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL);
|
LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL);
|
||||||
#endif
|
#endif
|
||||||
@@ -585,6 +534,12 @@ tcp_process(struct tcp_pcb *pcb)
|
|||||||
tcp_receive(pcb);
|
tcp_receive(pcb);
|
||||||
pcb->cwnd = pcb->mss;
|
pcb->cwnd = pcb->mss;
|
||||||
}
|
}
|
||||||
|
/* incorrect ACK number */
|
||||||
|
else {
|
||||||
|
/* send RST */
|
||||||
|
tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
|
||||||
|
tcphdr->dest, tcphdr->src);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CLOSE_WAIT:
|
case CLOSE_WAIT:
|
||||||
@@ -601,15 +556,15 @@ tcp_process(struct tcp_pcb *pcb)
|
|||||||
if (flags & TCP_FIN) {
|
if (flags & TCP_FIN) {
|
||||||
if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
|
if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
|
||||||
LWIP_DEBUGF(TCP_DEBUG,
|
LWIP_DEBUGF(TCP_DEBUG,
|
||||||
("TCP connection closed %d -> %d.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
||||||
tcp_ack_now(pcb);
|
tcp_ack_now(pcb);
|
||||||
tcp_pcb_purge(pcb);
|
tcp_pcb_purge(pcb);
|
||||||
TCP_RMV(&tcp_active_pcbs, pcb);
|
TCP_RMV(&tcp_active_pcbs, pcb);
|
||||||
pcb->state = TIME_WAIT;
|
pcb->state = TIME_WAIT;
|
||||||
TCP_REG(&tcp_tw_pcbs, pcb);
|
TCP_REG(&tcp_tw_pcbs, pcb);
|
||||||
} else {
|
} else {
|
||||||
tcp_ack_now(pcb);
|
tcp_ack_now(pcb);
|
||||||
pcb->state = CLOSING;
|
pcb->state = CLOSING;
|
||||||
}
|
}
|
||||||
} else if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
|
} else if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
|
||||||
pcb->state = FIN_WAIT_2;
|
pcb->state = FIN_WAIT_2;
|
||||||
@@ -618,7 +573,7 @@ tcp_process(struct tcp_pcb *pcb)
|
|||||||
case FIN_WAIT_2:
|
case FIN_WAIT_2:
|
||||||
tcp_receive(pcb);
|
tcp_receive(pcb);
|
||||||
if (flags & TCP_FIN) {
|
if (flags & TCP_FIN) {
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %u -> %u.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
||||||
tcp_ack_now(pcb);
|
tcp_ack_now(pcb);
|
||||||
tcp_pcb_purge(pcb);
|
tcp_pcb_purge(pcb);
|
||||||
TCP_RMV(&tcp_active_pcbs, pcb);
|
TCP_RMV(&tcp_active_pcbs, pcb);
|
||||||
@@ -629,7 +584,7 @@ tcp_process(struct tcp_pcb *pcb)
|
|||||||
case CLOSING:
|
case CLOSING:
|
||||||
tcp_receive(pcb);
|
tcp_receive(pcb);
|
||||||
if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
|
if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %u -> %u.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
||||||
tcp_ack_now(pcb);
|
tcp_ack_now(pcb);
|
||||||
tcp_pcb_purge(pcb);
|
tcp_pcb_purge(pcb);
|
||||||
TCP_RMV(&tcp_active_pcbs, pcb);
|
TCP_RMV(&tcp_active_pcbs, pcb);
|
||||||
@@ -640,7 +595,7 @@ tcp_process(struct tcp_pcb *pcb)
|
|||||||
case LAST_ACK:
|
case LAST_ACK:
|
||||||
tcp_receive(pcb);
|
tcp_receive(pcb);
|
||||||
if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
|
if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %u -> %u.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
||||||
pcb->state = CLOSED;
|
pcb->state = CLOSED;
|
||||||
recv_flags = TF_CLOSED;
|
recv_flags = TF_CLOSED;
|
||||||
}
|
}
|
||||||
@@ -648,7 +603,6 @@ tcp_process(struct tcp_pcb *pcb)
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -673,7 +627,7 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||||||
#endif
|
#endif
|
||||||
struct pbuf *p;
|
struct pbuf *p;
|
||||||
s32_t off;
|
s32_t off;
|
||||||
int m;
|
s16_t m;
|
||||||
u32_t right_wnd_edge;
|
u32_t right_wnd_edge;
|
||||||
u16_t new_tot_len;
|
u16_t new_tot_len;
|
||||||
|
|
||||||
@@ -688,11 +642,11 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||||||
pcb->snd_wnd = tcphdr->wnd;
|
pcb->snd_wnd = tcphdr->wnd;
|
||||||
pcb->snd_wl1 = seqno;
|
pcb->snd_wl1 = seqno;
|
||||||
pcb->snd_wl2 = ackno;
|
pcb->snd_wl2 = ackno;
|
||||||
LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %lu\n", pcb->snd_wnd));
|
LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"U32_F"\n", pcb->snd_wnd));
|
||||||
#if TCP_WND_DEBUG
|
#if TCP_WND_DEBUG
|
||||||
} else {
|
} else {
|
||||||
if (pcb->snd_wnd != tcphdr->wnd) {
|
if (pcb->snd_wnd != tcphdr->wnd) {
|
||||||
LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: no window update lastack %lu snd_max %lu ackno %lu wl1 %lu seqno %lu wl2 %lu\n",
|
LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: no window update lastack %"U32_F" snd_max %"U32_F" ackno %"U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n",
|
||||||
pcb->lastack, pcb->snd_max, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2));
|
pcb->lastack, pcb->snd_max, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2));
|
||||||
}
|
}
|
||||||
#endif /* TCP_WND_DEBUG */
|
#endif /* TCP_WND_DEBUG */
|
||||||
@@ -707,8 +661,8 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||||||
if (pcb->dupacks >= 3 && pcb->unacked != NULL) {
|
if (pcb->dupacks >= 3 && pcb->unacked != NULL) {
|
||||||
if (!(pcb->flags & TF_INFR)) {
|
if (!(pcb->flags & TF_INFR)) {
|
||||||
/* This is fast retransmit. Retransmit the first unacked segment. */
|
/* This is fast retransmit. Retransmit the first unacked segment. */
|
||||||
LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupacks %u (%lu), fast retransmit %lu\n",
|
LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupacks %"U16_F" (%"U32_F"), fast retransmit %"U32_F"\n",
|
||||||
(unsigned int)pcb->dupacks, pcb->lastack,
|
(u16_t)pcb->dupacks, pcb->lastack,
|
||||||
ntohl(pcb->unacked->tcphdr->seqno)));
|
ntohl(pcb->unacked->tcphdr->seqno)));
|
||||||
tcp_rexmit(pcb);
|
tcp_rexmit(pcb);
|
||||||
/* Set ssthresh to max (FlightSize / 2, 2*SMSS) */
|
/* Set ssthresh to max (FlightSize / 2, 2*SMSS) */
|
||||||
@@ -732,7 +686,7 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupack averted %lu %lu\n",
|
LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupack averted %"U32_F" %"U32_F"\n",
|
||||||
pcb->snd_wl1 + pcb->snd_wnd, right_wnd_edge));
|
pcb->snd_wl1 + pcb->snd_wnd, right_wnd_edge));
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
@@ -757,6 +711,7 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||||||
|
|
||||||
/* Update the send buffer space. */
|
/* Update the send buffer space. */
|
||||||
pcb->acked = ackno - pcb->lastack;
|
pcb->acked = ackno - pcb->lastack;
|
||||||
|
|
||||||
pcb->snd_buf += pcb->acked;
|
pcb->snd_buf += pcb->acked;
|
||||||
|
|
||||||
/* Reset the fast retransmit variables. */
|
/* Reset the fast retransmit variables. */
|
||||||
@@ -770,16 +725,16 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||||||
if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
|
if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
|
||||||
pcb->cwnd += pcb->mss;
|
pcb->cwnd += pcb->mss;
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %u\n", pcb->cwnd));
|
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"U16_F"\n", pcb->cwnd));
|
||||||
} else {
|
} else {
|
||||||
u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd);
|
u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd);
|
||||||
if (new_cwnd > pcb->cwnd) {
|
if (new_cwnd > pcb->cwnd) {
|
||||||
pcb->cwnd = new_cwnd;
|
pcb->cwnd = new_cwnd;
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %u\n", pcb->cwnd));
|
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"U16_F"\n", pcb->cwnd));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %lu, unacked->seqno %lu:%lu\n",
|
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n",
|
||||||
ackno,
|
ackno,
|
||||||
pcb->unacked != NULL?
|
pcb->unacked != NULL?
|
||||||
ntohl(pcb->unacked->tcphdr->seqno): 0,
|
ntohl(pcb->unacked->tcphdr->seqno): 0,
|
||||||
@@ -791,7 +746,7 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||||||
while (pcb->unacked != NULL &&
|
while (pcb->unacked != NULL &&
|
||||||
TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) +
|
TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) +
|
||||||
TCP_TCPLEN(pcb->unacked), ackno)) {
|
TCP_TCPLEN(pcb->unacked), ackno)) {
|
||||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %lu:%lu from pcb->unacked\n",
|
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n",
|
||||||
ntohl(pcb->unacked->tcphdr->seqno),
|
ntohl(pcb->unacked->tcphdr->seqno),
|
||||||
ntohl(pcb->unacked->tcphdr->seqno) +
|
ntohl(pcb->unacked->tcphdr->seqno) +
|
||||||
TCP_TCPLEN(pcb->unacked)));
|
TCP_TCPLEN(pcb->unacked)));
|
||||||
@@ -799,11 +754,11 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||||||
next = pcb->unacked;
|
next = pcb->unacked;
|
||||||
pcb->unacked = pcb->unacked->next;
|
pcb->unacked = pcb->unacked->next;
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %u ... ", (unsigned int)pcb->snd_queuelen));
|
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
|
||||||
pcb->snd_queuelen -= pbuf_clen(next->p);
|
pcb->snd_queuelen -= pbuf_clen(next->p);
|
||||||
tcp_seg_free(next);
|
tcp_seg_free(next);
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%u (after freeing unacked)\n", (unsigned int)pcb->snd_queuelen));
|
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unacked)\n", (u16_t)pcb->snd_queuelen));
|
||||||
if (pcb->snd_queuelen != 0) {
|
if (pcb->snd_queuelen != 0) {
|
||||||
LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||
|
LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||
|
||||||
pcb->unsent != NULL);
|
pcb->unsent != NULL);
|
||||||
@@ -823,16 +778,16 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||||||
TCP_SEQ_LEQ(ackno, pcb->snd_max)*/
|
TCP_SEQ_LEQ(ackno, pcb->snd_max)*/
|
||||||
TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent), pcb->snd_max)
|
TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent), pcb->snd_max)
|
||||||
) {
|
) {
|
||||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %lu:%lu from pcb->unsent\n",
|
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n",
|
||||||
ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) +
|
ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) +
|
||||||
TCP_TCPLEN(pcb->unsent)));
|
TCP_TCPLEN(pcb->unsent)));
|
||||||
|
|
||||||
next = pcb->unsent;
|
next = pcb->unsent;
|
||||||
pcb->unsent = pcb->unsent->next;
|
pcb->unsent = pcb->unsent->next;
|
||||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %u ... ", (unsigned int)pcb->snd_queuelen));
|
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
|
||||||
pcb->snd_queuelen -= pbuf_clen(next->p);
|
pcb->snd_queuelen -= pbuf_clen(next->p);
|
||||||
tcp_seg_free(next);
|
tcp_seg_free(next);
|
||||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%u (after freeing unsent)\n", (unsigned int)pcb->snd_queuelen));
|
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unsent)\n", (u16_t)pcb->snd_queuelen));
|
||||||
if (pcb->snd_queuelen != 0) {
|
if (pcb->snd_queuelen != 0) {
|
||||||
LWIP_ASSERT("tcp_receive: valid queue length",
|
LWIP_ASSERT("tcp_receive: valid queue length",
|
||||||
pcb->unacked != NULL || pcb->unsent != NULL);
|
pcb->unacked != NULL || pcb->unsent != NULL);
|
||||||
@@ -844,7 +799,7 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||||||
}
|
}
|
||||||
/* End of ACK for new data processing. */
|
/* End of ACK for new data processing. */
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %u rtseq %lu ackno %lu\n",
|
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n",
|
||||||
pcb->rttest, pcb->rtseq, ackno));
|
pcb->rttest, pcb->rtseq, ackno));
|
||||||
|
|
||||||
/* RTT estimation calculations. This is done by checking if the
|
/* RTT estimation calculations. This is done by checking if the
|
||||||
@@ -853,7 +808,7 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||||||
if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) {
|
if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) {
|
||||||
m = tcp_ticks - pcb->rttest;
|
m = tcp_ticks - pcb->rttest;
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %u ticks (%u msec).\n",
|
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n",
|
||||||
m, m * TCP_SLOW_INTERVAL));
|
m, m * TCP_SLOW_INTERVAL));
|
||||||
|
|
||||||
/* This is taken directly from VJs original code in his paper */
|
/* This is taken directly from VJs original code in his paper */
|
||||||
@@ -866,7 +821,7 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||||||
pcb->sv += m;
|
pcb->sv += m;
|
||||||
pcb->rto = (pcb->sa >> 3) + pcb->sv;
|
pcb->rto = (pcb->sa >> 3) + pcb->sv;
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %u (%u miliseconds)\n",
|
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" miliseconds)\n",
|
||||||
pcb->rto, pcb->rto * TCP_SLOW_INTERVAL));
|
pcb->rto, pcb->rto * TCP_SLOW_INTERVAL));
|
||||||
|
|
||||||
pcb->rttest = 0;
|
pcb->rttest = 0;
|
||||||
@@ -955,7 +910,7 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||||||
/* the whole segment is < rcv_nxt */
|
/* the whole segment is < rcv_nxt */
|
||||||
/* must be a duplicate of a packet that has already been correctly handled */
|
/* must be a duplicate of a packet that has already been correctly handled */
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %lu\n", seqno));
|
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno));
|
||||||
tcp_ack_now(pcb);
|
tcp_ack_now(pcb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -982,7 +937,12 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||||||
|
|
||||||
tcplen = TCP_TCPLEN(&inseg);
|
tcplen = TCP_TCPLEN(&inseg);
|
||||||
|
|
||||||
pcb->rcv_nxt += tcplen;
|
/* First received FIN will be ACKed +1, on any successive (duplicate)
|
||||||
|
* FINs we are already in CLOSE_WAIT and have already done +1.
|
||||||
|
*/
|
||||||
|
if (pcb->state != CLOSE_WAIT) {
|
||||||
|
pcb->rcv_nxt += tcplen;
|
||||||
|
}
|
||||||
|
|
||||||
/* Update the receiver's (our) window. */
|
/* Update the receiver's (our) window. */
|
||||||
if (pcb->rcv_wnd < tcplen) {
|
if (pcb->rcv_wnd < tcplen) {
|
||||||
|
|||||||
@@ -39,19 +39,17 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "lwip/def.h"
|
#include "lwip/def.h"
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
#include "lwip/mem.h"
|
#include "lwip/mem.h"
|
||||||
#include "lwip/memp.h"
|
#include "lwip/memp.h"
|
||||||
#include "lwip/sys.h"
|
#include "lwip/sys.h"
|
||||||
|
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
|
|
||||||
#include "lwip/inet.h"
|
#include "lwip/inet.h"
|
||||||
#include "lwip/tcp.h"
|
#include "lwip/tcp.h"
|
||||||
|
|
||||||
#include "lwip/stats.h"
|
#include "lwip/stats.h"
|
||||||
|
|
||||||
#if LWIP_TCP
|
#if LWIP_TCP
|
||||||
@@ -62,27 +60,33 @@ static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
|
|||||||
err_t
|
err_t
|
||||||
tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
|
tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
|
||||||
{
|
{
|
||||||
|
/* no data, no length, flags, copy=1, no optdata, no optdatalen */
|
||||||
return tcp_enqueue(pcb, NULL, 0, flags, 1, NULL, 0);
|
return tcp_enqueue(pcb, NULL, 0, flags, 1, NULL, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* NB. tcp_write() enqueues data for sending, but does not send it
|
* Write data for sending (but does not send it immediately).
|
||||||
* straight away. It waits in the expectation of more data being sent
|
*
|
||||||
* soon (as it can send them more efficiently by combining them
|
* It waits in the expectation of more data being sent soon (as
|
||||||
* together). To prompt the system to send data now, call
|
* it can send them more efficiently by combining them together).
|
||||||
* tcp_output() after calling tcp_write().
|
* To prompt the system to send data now, call tcp_output() after
|
||||||
|
* calling tcp_write().
|
||||||
|
*
|
||||||
|
* @arg pcb Protocol control block of the TCP connection to enqueue data for.
|
||||||
|
*
|
||||||
|
* @see tcp_write()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
err_t
|
err_t
|
||||||
tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
|
tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
|
||||||
{
|
{
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, arg=%p, len=%u, copy=%d)\n", (void *)pcb,
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, arg=%p, len=%"U16_F", copy=%"U16_F")\n", (void *)pcb,
|
||||||
arg, len, (unsigned int)copy));
|
arg, len, (u16_t)copy));
|
||||||
if (pcb->state == SYN_SENT ||
|
/* connection is in valid state for data transmission? */
|
||||||
pcb->state == SYN_RCVD ||
|
if (pcb->state == ESTABLISHED ||
|
||||||
pcb->state == ESTABLISHED ||
|
pcb->state == CLOSE_WAIT ||
|
||||||
pcb->state == CLOSE_WAIT) {
|
pcb->state == SYN_SENT ||
|
||||||
|
pcb->state == SYN_RCVD) {
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
return tcp_enqueue(pcb, (void *)arg, len, 0, copy, NULL, 0);
|
return tcp_enqueue(pcb, (void *)arg, len, 0, copy, NULL, 0);
|
||||||
}
|
}
|
||||||
@@ -93,10 +97,24 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enqueue either data or TCP options (but not both) for tranmission
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @arg pcb Protocol control block for the TCP connection to enqueue data for.
|
||||||
|
* @arg arg Pointer to the data to be enqueued for sending.
|
||||||
|
* @arg len Data length in bytes
|
||||||
|
* @arg flags
|
||||||
|
* @arg copy 1 if data must be copied, 0 if data is non-volatile and can be
|
||||||
|
* referenced.
|
||||||
|
* @arg optdata
|
||||||
|
* @arg optlen
|
||||||
|
*/
|
||||||
err_t
|
err_t
|
||||||
tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
||||||
u8_t flags, u8_t copy,
|
u8_t flags, u8_t copy,
|
||||||
u8_t *optdata, u8_t optlen)
|
u8_t *optdata, u8_t optlen)
|
||||||
{
|
{
|
||||||
struct pbuf *p;
|
struct pbuf *p;
|
||||||
struct tcp_seg *seg, *useg, *queue;
|
struct tcp_seg *seg, *useg, *queue;
|
||||||
@@ -105,41 +123,46 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||||||
void *ptr;
|
void *ptr;
|
||||||
u8_t queuelen;
|
u8_t queuelen;
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue(pcb=%p, arg=%p, len=%u, flags=%x, copy=%u)\n",
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue(pcb=%p, arg=%p, len=%"U16_F", flags=%"X16_F", copy=%"U16_F")\n",
|
||||||
(void *)pcb, arg, len, (unsigned int)flags, (unsigned int)copy));
|
(void *)pcb, arg, len, (u16_t)flags, (u16_t)copy));
|
||||||
left = len;
|
LWIP_ASSERT("tcp_enqueue: len == 0 || optlen == 0 (programmer violates API)",
|
||||||
ptr = arg;
|
len == 0 || optlen == 0);
|
||||||
|
LWIP_ASSERT("tcp_enqueue: arg == NULL || optdata == NULL (programmer violates API)",
|
||||||
|
arg == NULL || optdata == NULL);
|
||||||
/* fail on too much data */
|
/* fail on too much data */
|
||||||
if (len > pcb->snd_buf) {
|
if (len > pcb->snd_buf) {
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too much data (len=%u > snd_buf=%u)\n", len, pcb->snd_buf));
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n", len, pcb->snd_buf));
|
||||||
return ERR_MEM;
|
return ERR_MEM;
|
||||||
}
|
}
|
||||||
|
left = len;
|
||||||
|
ptr = arg;
|
||||||
|
|
||||||
/* seqno will be the sequence number of the first segment enqueued
|
/* seqno will be the sequence number of the first segment enqueued
|
||||||
* by the call to this function. */
|
* by the call to this function. */
|
||||||
seqno = pcb->snd_lbb;
|
seqno = pcb->snd_lbb;
|
||||||
|
|
||||||
queue = NULL;
|
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen));
|
||||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %u\n", (unsigned int)pcb->snd_queuelen));
|
|
||||||
|
|
||||||
/* Check if the queue length exceeds the configured maximum queue
|
/* If total number of pbufs on the unsent/unacked queues exceeds the
|
||||||
* length. If so, we return an error. */
|
* configured maximum, return an error */
|
||||||
queuelen = pcb->snd_queuelen;
|
queuelen = pcb->snd_queuelen;
|
||||||
if (queuelen >= TCP_SND_QUEUELEN) {
|
if (queuelen >= TCP_SND_QUEUELEN) {
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too long queue %u (max %u)\n", queuelen, TCP_SND_QUEUELEN));
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too long queue %"U16_F" (max %"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
|
||||||
goto memerr;
|
TCP_STATS_INC(tcp.memerr);
|
||||||
|
return ERR_MEM;
|
||||||
}
|
}
|
||||||
|
if (queuelen != 0) {
|
||||||
if (pcb->snd_queuelen != 0) {
|
LWIP_ASSERT("tcp_enqueue: pbufs on queue => at least one queue non-empty",
|
||||||
LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
|
pcb->unacked != NULL || pcb->unsent != NULL);
|
||||||
pcb->unsent != NULL);
|
} else {
|
||||||
|
LWIP_ASSERT("tcp_enqueue: no pbufs on queue => both queues empty",
|
||||||
|
pcb->unacked == NULL && pcb->unsent == NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
seg = useg = NULL;
|
|
||||||
seglen = 0;
|
|
||||||
|
|
||||||
/* First, break up the data into segments and tuck them together in
|
/* First, break up the data into segments and tuck them together in
|
||||||
* the local "queue" variable. */
|
* the local "queue" variable. */
|
||||||
|
useg = queue = seg = NULL;
|
||||||
|
seglen = 0;
|
||||||
while (queue == NULL || left > 0) {
|
while (queue == NULL || left > 0) {
|
||||||
|
|
||||||
/* The segment length should be the MSS if the data to be enqueued
|
/* The segment length should be the MSS if the data to be enqueued
|
||||||
@@ -155,20 +178,25 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||||||
seg->next = NULL;
|
seg->next = NULL;
|
||||||
seg->p = NULL;
|
seg->p = NULL;
|
||||||
|
|
||||||
|
/* first segment of to-be-queued data? */
|
||||||
if (queue == NULL) {
|
if (queue == NULL) {
|
||||||
useg = queue = seg;
|
queue = seg;
|
||||||
}
|
}
|
||||||
|
/* subsequent segments of to-be-queued data */
|
||||||
else {
|
else {
|
||||||
/* Attach the segment to the end of the queued segments. */
|
/* Attach the segment to the end of the queued segments */
|
||||||
LWIP_ASSERT("useg != NULL", useg != NULL);
|
LWIP_ASSERT("useg != NULL", useg != NULL);
|
||||||
useg->next = seg;
|
useg->next = seg;
|
||||||
useg = seg;
|
|
||||||
}
|
}
|
||||||
|
/* remember last segment of to-be-queued data for next iteration */
|
||||||
|
useg = seg;
|
||||||
|
|
||||||
/* If copy is set, memory should be allocated
|
/* If copy is set, memory should be allocated
|
||||||
* and data copied into pbuf, otherwise data comes from
|
* and data copied into pbuf, otherwise data comes from
|
||||||
* ROM or other static memory, and need not be copied. If
|
* ROM or other static memory, and need not be copied. If
|
||||||
* optdata is != NULL, we have options instead of data. */
|
* optdata is != NULL, we have options instead of data. */
|
||||||
|
|
||||||
|
/* options? */
|
||||||
if (optdata != NULL) {
|
if (optdata != NULL) {
|
||||||
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
|
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
|
||||||
goto memerr;
|
goto memerr;
|
||||||
@@ -176,9 +204,10 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||||||
++queuelen;
|
++queuelen;
|
||||||
seg->dataptr = seg->p->payload;
|
seg->dataptr = seg->p->payload;
|
||||||
}
|
}
|
||||||
|
/* copy from volatile memory? */
|
||||||
else if (copy) {
|
else if (copy) {
|
||||||
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_RAM)) == NULL) {
|
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_RAM)) == NULL) {
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue : could not allocate memory for pbuf copy size %u\n", seglen));
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue : could not allocate memory for pbuf copy size %"U16_F"\n", seglen));
|
||||||
goto memerr;
|
goto memerr;
|
||||||
}
|
}
|
||||||
++queuelen;
|
++queuelen;
|
||||||
@@ -189,8 +218,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||||||
}
|
}
|
||||||
/* do not copy data */
|
/* do not copy data */
|
||||||
else {
|
else {
|
||||||
|
/* First, allocate a pbuf for holding the data.
|
||||||
/* first, allocate a pbuf for holding the data.
|
|
||||||
* since the referenced data is available at least until it is sent out on the
|
* since the referenced data is available at least until it is sent out on the
|
||||||
* link (as it has to be ACKed by the remote party) we can safely use PBUF_ROM
|
* link (as it has to be ACKed by the remote party) we can safely use PBUF_ROM
|
||||||
* instead of PBUF_REF here.
|
* instead of PBUF_REF here.
|
||||||
@@ -200,6 +228,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||||||
goto memerr;
|
goto memerr;
|
||||||
}
|
}
|
||||||
++queuelen;
|
++queuelen;
|
||||||
|
/* reference the non-volatile payload data */
|
||||||
p->payload = ptr;
|
p->payload = ptr;
|
||||||
seg->dataptr = ptr;
|
seg->dataptr = ptr;
|
||||||
|
|
||||||
@@ -214,28 +243,22 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||||||
++queuelen;
|
++queuelen;
|
||||||
|
|
||||||
/* Concatenate the headers and data pbufs together. */
|
/* Concatenate the headers and data pbufs together. */
|
||||||
pbuf_cat(seg->p, p);
|
pbuf_cat(seg->p/*header*/, p/*data*/);
|
||||||
p = NULL;
|
p = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now that there are more segments queued, we check again if the
|
/* Now that there are more segments queued, we check again if the
|
||||||
length of the queue exceeds the configured maximum. */
|
length of the queue exceeds the configured maximum. */
|
||||||
if (queuelen > TCP_SND_QUEUELEN) {
|
if (queuelen > TCP_SND_QUEUELEN) {
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: queue too long %u (%u)\n", queuelen, TCP_SND_QUEUELEN));
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
|
||||||
goto memerr;
|
goto memerr;
|
||||||
}
|
}
|
||||||
|
|
||||||
seg->len = seglen;
|
seg->len = seglen;
|
||||||
#if 0 /* Was commented out. TODO: can someone say why this is here? */
|
|
||||||
if ((flags & TCP_SYN) || (flags & TCP_FIN)) {
|
/* build TCP header */
|
||||||
++seg->len;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* Build TCP header. */
|
|
||||||
if (pbuf_header(seg->p, TCP_HLEN)) {
|
if (pbuf_header(seg->p, TCP_HLEN)) {
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
|
||||||
|
|
||||||
TCP_STATS_INC(tcp.err);
|
TCP_STATS_INC(tcp.err);
|
||||||
goto memerr;
|
goto memerr;
|
||||||
}
|
}
|
||||||
@@ -258,17 +281,16 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||||||
segments such as SYN|ACK. */
|
segments such as SYN|ACK. */
|
||||||
memcpy(seg->dataptr, optdata, optlen);
|
memcpy(seg->dataptr, optdata, optlen);
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE, ("tcp_enqueue: queueing %lu:%lu (0x%x)\n",
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE, ("tcp_enqueue: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n",
|
||||||
ntohl(seg->tcphdr->seqno),
|
ntohl(seg->tcphdr->seqno),
|
||||||
ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
|
ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
|
||||||
flags));
|
(u16_t)flags));
|
||||||
|
|
||||||
left -= seglen;
|
left -= seglen;
|
||||||
seqno += seglen;
|
seqno += seglen;
|
||||||
ptr = (void *)((char *)ptr + seglen);
|
ptr = (void *)((u8_t *)ptr + seglen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Now that the data to be enqueued has been broken up into TCP
|
/* Now that the data to be enqueued has been broken up into TCP
|
||||||
segments in the queue variable, we add them to the end of the
|
segments in the queue variable, we add them to the end of the
|
||||||
pcb->unsent queue. */
|
pcb->unsent queue. */
|
||||||
@@ -278,6 +300,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||||||
else {
|
else {
|
||||||
for (useg = pcb->unsent; useg->next != NULL; useg = useg->next);
|
for (useg = pcb->unsent; useg->next != NULL; useg = useg->next);
|
||||||
}
|
}
|
||||||
|
/* { useg is last segment on the unsent queue, NULL if list is empty } */
|
||||||
|
|
||||||
/* If there is room in the last pbuf on the unsent queue,
|
/* If there is room in the last pbuf on the unsent queue,
|
||||||
chain the first pbuf on the queue together with that. */
|
chain the first pbuf on the queue together with that. */
|
||||||
@@ -285,24 +308,27 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||||||
TCP_TCPLEN(useg) != 0 &&
|
TCP_TCPLEN(useg) != 0 &&
|
||||||
!(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) &&
|
!(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) &&
|
||||||
!(flags & (TCP_SYN | TCP_FIN)) &&
|
!(flags & (TCP_SYN | TCP_FIN)) &&
|
||||||
|
/* fit within max seg size */
|
||||||
useg->len + queue->len <= pcb->mss) {
|
useg->len + queue->len <= pcb->mss) {
|
||||||
/* Remove TCP header from first segment. */
|
/* Remove TCP header from first segment of our to-be-queued list */
|
||||||
pbuf_header(queue->p, -TCP_HLEN);
|
pbuf_header(queue->p, -TCP_HLEN);
|
||||||
pbuf_cat(useg->p, queue->p);
|
pbuf_cat(useg->p, queue->p);
|
||||||
useg->len += queue->len;
|
useg->len += queue->len;
|
||||||
useg->next = queue->next;
|
useg->next = queue->next;
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE | DBG_STATE, ("tcp_enqueue: chaining, new len %u\n", useg->len));
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE | DBG_STATE, ("tcp_enqueue: chaining segments, new len %"U16_F"\n", useg->len));
|
||||||
if (seg == queue) {
|
if (seg == queue) {
|
||||||
seg = NULL;
|
seg = NULL;
|
||||||
}
|
}
|
||||||
memp_free(MEMP_TCP_SEG, queue);
|
memp_free(MEMP_TCP_SEG, queue);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
/* empty list */
|
||||||
if (useg == NULL) {
|
if (useg == NULL) {
|
||||||
|
/* initialize list with this segment */
|
||||||
pcb->unsent = queue;
|
pcb->unsent = queue;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
/* enqueue segment */
|
||||||
else {
|
else {
|
||||||
useg->next = queue;
|
useg->next = queue;
|
||||||
}
|
}
|
||||||
@@ -311,13 +337,15 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||||||
++len;
|
++len;
|
||||||
}
|
}
|
||||||
pcb->snd_lbb += len;
|
pcb->snd_lbb += len;
|
||||||
pcb->snd_buf -= len;
|
|
||||||
pcb->snd_queuelen = queuelen;
|
|
||||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %d (after enqueued)\n", pcb->snd_queuelen));
|
|
||||||
if (pcb->snd_queuelen != 0) {
|
|
||||||
LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
|
|
||||||
pcb->unsent != NULL);
|
|
||||||
|
|
||||||
|
pcb->snd_buf -= len;
|
||||||
|
|
||||||
|
/* update number of segments on the queues */
|
||||||
|
pcb->snd_queuelen = queuelen;
|
||||||
|
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %"S16_F" (after enqueued)\n", pcb->snd_queuelen));
|
||||||
|
if (pcb->snd_queuelen != 0) {
|
||||||
|
LWIP_ASSERT("tcp_enqueue: valid queue length",
|
||||||
|
pcb->unacked != NULL || pcb->unsent != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the PSH flag in the last segment that we enqueued, but only
|
/* Set the PSH flag in the last segment that we enqueued, but only
|
||||||
@@ -327,7 +355,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
memerr:
|
memerr:
|
||||||
TCP_STATS_INC(tcp.memerr);
|
TCP_STATS_INC(tcp.memerr);
|
||||||
|
|
||||||
if (queue != NULL) {
|
if (queue != NULL) {
|
||||||
@@ -336,9 +364,8 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
|||||||
if (pcb->snd_queuelen != 0) {
|
if (pcb->snd_queuelen != 0) {
|
||||||
LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
|
LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
|
||||||
pcb->unsent != NULL);
|
pcb->unsent != NULL);
|
||||||
|
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(TCP_QLEN_DEBUG | DBG_STATE, ("tcp_enqueue: %d (with mem err)\n", pcb->snd_queuelen));
|
LWIP_DEBUGF(TCP_QLEN_DEBUG | DBG_STATE, ("tcp_enqueue: %"S16_F" (with mem err)\n", pcb->snd_queuelen));
|
||||||
return ERR_MEM;
|
return ERR_MEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,7 +378,7 @@ tcp_output(struct tcp_pcb *pcb)
|
|||||||
struct tcp_seg *seg, *useg;
|
struct tcp_seg *seg, *useg;
|
||||||
u32_t wnd;
|
u32_t wnd;
|
||||||
#if TCP_CWND_DEBUG
|
#if TCP_CWND_DEBUG
|
||||||
int i = 0;
|
s16_t i = 0;
|
||||||
#endif /* TCP_CWND_DEBUG */
|
#endif /* TCP_CWND_DEBUG */
|
||||||
|
|
||||||
/* First, check if we are invoked by the TCP input processing
|
/* First, check if we are invoked by the TCP input processing
|
||||||
@@ -364,7 +391,6 @@ tcp_output(struct tcp_pcb *pcb)
|
|||||||
|
|
||||||
wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
|
wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
|
||||||
|
|
||||||
|
|
||||||
seg = pcb->unsent;
|
seg = pcb->unsent;
|
||||||
|
|
||||||
/* useg should point to last segment on unacked queue */
|
/* useg should point to last segment on unacked queue */
|
||||||
@@ -372,24 +398,24 @@ tcp_output(struct tcp_pcb *pcb)
|
|||||||
if (useg != NULL) {
|
if (useg != NULL) {
|
||||||
for (; useg->next != NULL; useg = useg->next);
|
for (; useg->next != NULL; useg = useg->next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* If the TF_ACK_NOW flag is set, we check if there is data that is
|
/* If the TF_ACK_NOW flag is set and no data will be sent (either
|
||||||
to be sent. If data is to be sent out, we'll just piggyback our
|
* because the ->unsent queue is empty or because the window does
|
||||||
acknowledgement with the outgoing segment. If no data will be
|
* not allow it), construct an empty ACK segment and send it.
|
||||||
sent (either because the ->unsent queue is empty or because the
|
*
|
||||||
window doesn't allow it) we'll have to construct an empty ACK
|
* If data is to be sent, we will just piggyback the ACK (see below).
|
||||||
segment and send it. */
|
*/
|
||||||
if (pcb->flags & TF_ACK_NOW &&
|
if (pcb->flags & TF_ACK_NOW &&
|
||||||
(seg == NULL ||
|
(seg == NULL ||
|
||||||
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
|
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
|
||||||
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
|
|
||||||
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
|
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
|
||||||
return ERR_BUF;
|
return ERR_BUF;
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: sending ACK for %lu\n", pcb->rcv_nxt));
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt));
|
||||||
|
/* remove ACK flags from the PCB, as we send an empty ACK now */
|
||||||
|
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
|
||||||
|
|
||||||
tcphdr = p->payload;
|
tcphdr = p->payload;
|
||||||
tcphdr->src = htons(pcb->local_port);
|
tcphdr->src = htons(pcb->local_port);
|
||||||
@@ -406,7 +432,6 @@ tcp_output(struct tcp_pcb *pcb)
|
|||||||
tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
|
tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
|
||||||
IP_PROTO_TCP, p->tot_len);
|
IP_PROTO_TCP, p->tot_len);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
|
ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
|
||||||
IP_PROTO_TCP);
|
IP_PROTO_TCP);
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
@@ -416,26 +441,26 @@ tcp_output(struct tcp_pcb *pcb)
|
|||||||
|
|
||||||
#if TCP_OUTPUT_DEBUG
|
#if TCP_OUTPUT_DEBUG
|
||||||
if (seg == NULL) {
|
if (seg == NULL) {
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", pcb->unsent));
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", (void*)pcb->unsent));
|
||||||
}
|
}
|
||||||
#endif /* TCP_OUTPUT_DEBUG */
|
#endif /* TCP_OUTPUT_DEBUG */
|
||||||
#if TCP_CWND_DEBUG
|
#if TCP_CWND_DEBUG
|
||||||
if (seg == NULL) {
|
if (seg == NULL) {
|
||||||
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, seg == NULL, ack %lu\n",
|
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", seg == NULL, ack %"U32_F"\n",
|
||||||
pcb->snd_wnd, pcb->cwnd, wnd,
|
pcb->snd_wnd, pcb->cwnd, wnd,
|
||||||
pcb->lastack));
|
pcb->lastack));
|
||||||
} else {
|
} else {
|
||||||
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, effwnd %lu, seq %lu, ack %lu\n",
|
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n",
|
||||||
pcb->snd_wnd, pcb->cwnd, wnd,
|
pcb->snd_wnd, pcb->cwnd, wnd,
|
||||||
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
|
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
|
||||||
ntohl(seg->tcphdr->seqno), pcb->lastack));
|
ntohl(seg->tcphdr->seqno), pcb->lastack));
|
||||||
}
|
}
|
||||||
#endif /* TCP_CWND_DEBUG */
|
#endif /* TCP_CWND_DEBUG */
|
||||||
|
/* data available and window allows it to be sent? */
|
||||||
while (seg != NULL &&
|
while (seg != NULL &&
|
||||||
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
|
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
|
||||||
#if TCP_CWND_DEBUG
|
#if TCP_CWND_DEBUG
|
||||||
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, effwnd %lu, seq %lu, ack %lu, i%d\n",
|
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n",
|
||||||
pcb->snd_wnd, pcb->cwnd, wnd,
|
pcb->snd_wnd, pcb->cwnd, wnd,
|
||||||
ntohl(seg->tcphdr->seqno) + seg->len -
|
ntohl(seg->tcphdr->seqno) + seg->len -
|
||||||
pcb->lastack,
|
pcb->lastack,
|
||||||
@@ -458,21 +483,26 @@ tcp_output(struct tcp_pcb *pcb)
|
|||||||
/* put segment on unacknowledged list if length > 0 */
|
/* put segment on unacknowledged list if length > 0 */
|
||||||
if (TCP_TCPLEN(seg) > 0) {
|
if (TCP_TCPLEN(seg) > 0) {
|
||||||
seg->next = NULL;
|
seg->next = NULL;
|
||||||
|
/* unacked list is empty? */
|
||||||
if (pcb->unacked == NULL) {
|
if (pcb->unacked == NULL) {
|
||||||
pcb->unacked = seg;
|
pcb->unacked = seg;
|
||||||
useg = seg;
|
useg = seg;
|
||||||
|
/* unacked list is not empty? */
|
||||||
} else {
|
} else {
|
||||||
/* In the case of fast retransmit, the packet should not go to the end
|
/* In the case of fast retransmit, the packet should not go to the tail
|
||||||
* of the unacked queue, but rather at the start. We need to check for
|
* of the unacked queue, but rather at the head. We need to check for
|
||||||
* this case. -STJ Jul 27, 2004 */
|
* this case. -STJ Jul 27, 2004 */
|
||||||
if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))){
|
if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))){
|
||||||
|
/* add segment to head of unacked list */
|
||||||
seg->next = pcb->unacked;
|
seg->next = pcb->unacked;
|
||||||
pcb->unacked = seg;
|
pcb->unacked = seg;
|
||||||
} else {
|
} else {
|
||||||
|
/* add segment to tail of unacked list */
|
||||||
useg->next = seg;
|
useg->next = seg;
|
||||||
useg = useg->next;
|
useg = useg->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* do not queue empty segments on the unacked list */
|
||||||
} else {
|
} else {
|
||||||
tcp_seg_free(seg);
|
tcp_seg_free(seg);
|
||||||
}
|
}
|
||||||
@@ -481,6 +511,9 @@ tcp_output(struct tcp_pcb *pcb)
|
|||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actually send a TCP segment over IP
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
||||||
{
|
{
|
||||||
@@ -515,9 +548,9 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
|||||||
pcb->rttest = tcp_ticks;
|
pcb->rttest = tcp_ticks;
|
||||||
pcb->rtseq = ntohl(seg->tcphdr->seqno);
|
pcb->rtseq = ntohl(seg->tcphdr->seqno);
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %lu\n", pcb->rtseq));
|
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq));
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %lu:%lu\n",
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n",
|
||||||
htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) +
|
htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) +
|
||||||
seg->len));
|
seg->len));
|
||||||
|
|
||||||
@@ -573,9 +606,10 @@ tcp_rst(u32_t seqno, u32_t ackno,
|
|||||||
/* Send output with hardcoded TTL since we have no access to the pcb */
|
/* Send output with hardcoded TTL since we have no access to the pcb */
|
||||||
ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
|
ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %lu ackno %lu.\n", seqno, ackno));
|
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* requeue all unacked segments for retransmission */
|
||||||
void
|
void
|
||||||
tcp_rexmit_rto(struct tcp_pcb *pcb)
|
tcp_rexmit_rto(struct tcp_pcb *pcb)
|
||||||
{
|
{
|
||||||
@@ -585,22 +619,24 @@ tcp_rexmit_rto(struct tcp_pcb *pcb)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Move all unacked segments to the unsent queue. */
|
/* Move all unacked segments to the head of the unsent queue */
|
||||||
for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
|
for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
|
||||||
|
/* concatenate unsent queue after unacked queue */
|
||||||
seg->next = pcb->unsent;
|
seg->next = pcb->unsent;
|
||||||
|
/* unsent queue is the concatenated queue (of unacked, unsent) */
|
||||||
pcb->unsent = pcb->unacked;
|
pcb->unsent = pcb->unacked;
|
||||||
|
/* unacked queue is now empty */
|
||||||
pcb->unacked = NULL;
|
pcb->unacked = NULL;
|
||||||
|
|
||||||
pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
|
pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
|
||||||
|
/* increment number of retransmissions */
|
||||||
++pcb->nrtx;
|
++pcb->nrtx;
|
||||||
|
|
||||||
/* Don't take any rtt measurements after retransmitting. */
|
/* Don't take any RTT measurements after retransmitting. */
|
||||||
pcb->rttest = 0;
|
pcb->rttest = 0;
|
||||||
|
|
||||||
/* Do the actual retransmission. */
|
/* Do the actual retransmission */
|
||||||
tcp_output(pcb);
|
tcp_output(pcb);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -637,11 +673,11 @@ tcp_keepalive(struct tcp_pcb *pcb)
|
|||||||
struct pbuf *p;
|
struct pbuf *p;
|
||||||
struct tcp_hdr *tcphdr;
|
struct tcp_hdr *tcphdr;
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %u.%u.%u.%u\n",
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||||
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
|
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
|
||||||
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
|
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %lu pcb->tmr %lu pcb->keep_cnt %u\n", tcp_ticks, pcb->tmr, pcb->keep_cnt));
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt %"U16_F"\n", tcp_ticks, pcb->tmr, pcb->keep_cnt));
|
||||||
|
|
||||||
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
|
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
|
||||||
|
|
||||||
@@ -670,7 +706,7 @@ tcp_keepalive(struct tcp_pcb *pcb)
|
|||||||
|
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
|
|
||||||
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_keepalive: seqno %lu ackno %lu.\n", pcb->snd_nxt - 1, pcb->rcv_nxt));
|
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F".\n", pcb->snd_nxt - 1, pcb->rcv_nxt));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* LWIP_TCP */
|
#endif /* LWIP_TCP */
|
||||||
|
|||||||
265
src/core/udp.c
265
src/core/udp.c
@@ -66,7 +66,6 @@ struct udp_pcb *udp_pcbs = NULL;
|
|||||||
|
|
||||||
static struct udp_pcb *pcb_cache = NULL;
|
static struct udp_pcb *pcb_cache = NULL;
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
udp_init(void)
|
udp_init(void)
|
||||||
{
|
{
|
||||||
@@ -88,16 +87,11 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||||||
{
|
{
|
||||||
struct udp_hdr *udphdr;
|
struct udp_hdr *udphdr;
|
||||||
struct udp_pcb *pcb;
|
struct udp_pcb *pcb;
|
||||||
|
struct udp_pcb *uncon_pcb;
|
||||||
struct ip_hdr *iphdr;
|
struct ip_hdr *iphdr;
|
||||||
u16_t src, dest;
|
u16_t src, dest;
|
||||||
|
u8_t local_match;
|
||||||
|
|
||||||
#if SO_REUSE
|
|
||||||
struct udp_pcb *pcb_temp;
|
|
||||||
int reuse = 0;
|
|
||||||
int reuse_port_1 = 0;
|
|
||||||
int reuse_port_2 = 0;
|
|
||||||
#endif /* SO_REUSE */
|
|
||||||
|
|
||||||
PERF_START;
|
PERF_START;
|
||||||
|
|
||||||
UDP_STATS_INC(udp.recv);
|
UDP_STATS_INC(udp.recv);
|
||||||
@@ -106,7 +100,7 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||||||
|
|
||||||
if (pbuf_header(p, -((s16_t)(UDP_HLEN + IPH_HL(iphdr) * 4)))) {
|
if (pbuf_header(p, -((s16_t)(UDP_HLEN + IPH_HL(iphdr) * 4)))) {
|
||||||
/* drop short packets */
|
/* drop short packets */
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: short UDP datagram (%u bytes) discarded\n", p->tot_len));
|
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: short UDP datagram (%"U16_F" bytes) discarded\n", p->tot_len));
|
||||||
UDP_STATS_INC(udp.lenerr);
|
UDP_STATS_INC(udp.lenerr);
|
||||||
UDP_STATS_INC(udp.drop);
|
UDP_STATS_INC(udp.drop);
|
||||||
snmp_inc_udpinerrors();
|
snmp_inc_udpinerrors();
|
||||||
@@ -116,7 +110,7 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||||||
|
|
||||||
udphdr = (struct udp_hdr *)((u8_t *)p->payload - UDP_HLEN);
|
udphdr = (struct udp_hdr *)((u8_t *)p->payload - UDP_HLEN);
|
||||||
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %u\n", p->tot_len));
|
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len));
|
||||||
|
|
||||||
src = ntohs(udphdr->src);
|
src = ntohs(udphdr->src);
|
||||||
dest = ntohs(udphdr->dest);
|
dest = ntohs(udphdr->dest);
|
||||||
@@ -124,117 +118,46 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||||||
udp_debug_print(udphdr);
|
udp_debug_print(udphdr);
|
||||||
|
|
||||||
/* print the UDP source and destination */
|
/* print the UDP source and destination */
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp (%u.%u.%u.%u, %u) <-- (%u.%u.%u.%u, %u)\n",
|
LWIP_DEBUGF(UDP_DEBUG, ("udp (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") <-- (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n",
|
||||||
ip4_addr1(&iphdr->dest), ip4_addr2(&iphdr->dest),
|
ip4_addr1(&iphdr->dest), ip4_addr2(&iphdr->dest),
|
||||||
ip4_addr3(&iphdr->dest), ip4_addr4(&iphdr->dest), ntohs(udphdr->dest),
|
ip4_addr3(&iphdr->dest), ip4_addr4(&iphdr->dest), ntohs(udphdr->dest),
|
||||||
ip4_addr1(&iphdr->src), ip4_addr2(&iphdr->src),
|
ip4_addr1(&iphdr->src), ip4_addr2(&iphdr->src),
|
||||||
ip4_addr3(&iphdr->src), ip4_addr4(&iphdr->src), ntohs(udphdr->src)));
|
ip4_addr3(&iphdr->src), ip4_addr4(&iphdr->src), ntohs(udphdr->src)));
|
||||||
|
|
||||||
#if SO_REUSE
|
local_match = 0;
|
||||||
pcb_temp = udp_pcbs;
|
uncon_pcb = NULL;
|
||||||
|
/* Iterate through the UDP pcb list for a matching pcb */
|
||||||
again_1:
|
|
||||||
|
|
||||||
/* Iterate through the UDP pcb list for a fully matching pcb */
|
|
||||||
for (pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
|
|
||||||
#else /* SO_REUSE */
|
|
||||||
/* Iterate through the UDP pcb list for a fully matching pcb */
|
|
||||||
for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
|
for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
|
||||||
#endif /* SO_REUSE */
|
|
||||||
/* print the PCB local and remote address */
|
/* print the PCB local and remote address */
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n",
|
LWIP_DEBUGF(UDP_DEBUG, ("pcb (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") --- (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n",
|
||||||
ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
|
ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
|
||||||
ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port,
|
ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port,
|
||||||
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
|
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
|
||||||
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip), pcb->remote_port));
|
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip), pcb->remote_port));
|
||||||
|
|
||||||
/* PCB remote port matches UDP source port? */
|
/* compare PCB local addr+port to UDP destination addr+port */
|
||||||
if ((pcb->remote_port == src) &&
|
if ((pcb->local_port == dest) &&
|
||||||
/* PCB local port matches UDP destination port? */
|
|
||||||
(pcb->local_port == dest) &&
|
|
||||||
/* accepting from any remote (source) IP address? or... */
|
|
||||||
(ip_addr_isany(&pcb->remote_ip) ||
|
|
||||||
/* PCB remote IP address matches UDP source IP address? */
|
|
||||||
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&
|
|
||||||
/* accepting on any local (netif) IP address? or... */
|
|
||||||
(ip_addr_isany(&pcb->local_ip) ||
|
(ip_addr_isany(&pcb->local_ip) ||
|
||||||
/* PCB local IP address matches UDP destination IP address? */
|
|
||||||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
|
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
|
||||||
#if SO_REUSE
|
local_match = 1;
|
||||||
if (pcb->so_options & SOF_REUSEPORT) {
|
if ((uncon_pcb == NULL) &&
|
||||||
if(reuse) {
|
((pcb->flags & UDP_FLAGS_CONNECTED) == 0)) {
|
||||||
/* We processed one PCB already */
|
/* the first unconnected matching PCB */
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB and SOF_REUSEPORT set.\n"));
|
uncon_pcb = pcb;
|
||||||
} else {
|
}
|
||||||
/* First PCB with this address */
|
}
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: first PCB and SOF_REUSEPORT set.\n"));
|
/* compare PCB remote addr+port to UDP source addr+port */
|
||||||
reuse = 1;
|
if ((local_match != 0) &&
|
||||||
}
|
(pcb->remote_port == src) &&
|
||||||
|
(ip_addr_isany(&pcb->remote_ip) ||
|
||||||
reuse_port_1 = 1;
|
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)))) {
|
||||||
p->ref++;
|
/* the first fully matching PCB */
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: reference counter on PBUF set to %i\n", p->ref));
|
|
||||||
} else {
|
|
||||||
if (reuse) {
|
|
||||||
/* We processed one PCB already */
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* SO_REUSE */
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* no fully matching pcb found? then look for an unconnected pcb */
|
/* no fully matching pcb found? then look for an unconnected pcb */
|
||||||
if (pcb == NULL) {
|
if (pcb == NULL) {
|
||||||
/* Iterate through the UDP PCB list for a pcb that matches
|
pcb = uncon_pcb;
|
||||||
the local address. */
|
|
||||||
|
|
||||||
#if SO_REUSE
|
|
||||||
pcb_temp = udp_pcbs;
|
|
||||||
|
|
||||||
again_2:
|
|
||||||
|
|
||||||
for (pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
|
|
||||||
#else /* SO_REUSE */
|
|
||||||
for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
|
|
||||||
#endif /* SO_REUSE */
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n",
|
|
||||||
ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
|
|
||||||
ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port,
|
|
||||||
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
|
|
||||||
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip), pcb->remote_port));
|
|
||||||
/* unconnected? */
|
|
||||||
if (((pcb->flags & UDP_FLAGS_CONNECTED) == 0) &&
|
|
||||||
/* destination port matches? */
|
|
||||||
(pcb->local_port == dest) &&
|
|
||||||
/* not bound to a specific (local) interface address? or... */
|
|
||||||
(ip_addr_isany(&pcb->local_ip) ||
|
|
||||||
/* ...matching interface address? */
|
|
||||||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
|
|
||||||
#if SO_REUSE
|
|
||||||
if (pcb->so_options & SOF_REUSEPORT) {
|
|
||||||
if (reuse) {
|
|
||||||
/* We processed one PCB already */
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB and SOF_REUSEPORT set.\n"));
|
|
||||||
} else {
|
|
||||||
/* First PCB with this address */
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: first PCB and SOF_REUSEPORT set.\n"));
|
|
||||||
reuse = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
reuse_port_2 = 1;
|
|
||||||
p->ref++;
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: reference counter on PBUF set to %i\n", p->ref));
|
|
||||||
} else {
|
|
||||||
if (reuse) {
|
|
||||||
/* We processed one PCB already */
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* SO_REUSE */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check checksum if this is a match or if it was directed at us. */
|
/* Check checksum if this is a match or if it was directed at us. */
|
||||||
@@ -280,34 +203,12 @@ udp_input(struct pbuf *p, struct netif *inp)
|
|||||||
pbuf_header(p, -UDP_HLEN);
|
pbuf_header(p, -UDP_HLEN);
|
||||||
if (pcb != NULL) {
|
if (pcb != NULL) {
|
||||||
snmp_inc_udpindatagrams();
|
snmp_inc_udpindatagrams();
|
||||||
pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src), src);
|
/* callback */
|
||||||
#if SO_REUSE
|
if (pcb->recv != NULL)
|
||||||
/* First socket should receive now */
|
{
|
||||||
if(reuse_port_1 || reuse_port_2) {
|
pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src), src);
|
||||||
/* We want to search on next socket after receiving */
|
}
|
||||||
pcb_temp = pcb->next;
|
|
||||||
|
|
||||||
if(reuse_port_1) {
|
|
||||||
/* We are searching connected sockets */
|
|
||||||
reuse_port_1 = 0;
|
|
||||||
reuse_port_2 = 0;
|
|
||||||
goto again_1;
|
|
||||||
} else {
|
} else {
|
||||||
/* We are searching unconnected sockets */
|
|
||||||
reuse_port_1 = 0;
|
|
||||||
reuse_port_2 = 0;
|
|
||||||
goto again_2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* SO_REUSE */
|
|
||||||
} else {
|
|
||||||
#if SO_REUSE
|
|
||||||
if(reuse) {
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: freeing PBUF with reference counter set to %i\n", p->ref));
|
|
||||||
pbuf_free(p);
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
#endif /* SO_REUSE */
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE, ("udp_input: not for us.\n"));
|
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE, ("udp_input: not for us.\n"));
|
||||||
|
|
||||||
/* No match was found, send ICMP destination port unreachable unless
|
/* No match was found, send ICMP destination port unreachable unless
|
||||||
@@ -356,9 +257,10 @@ udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
|
|||||||
struct ip_addr *dst_ip, u16_t dst_port)
|
struct ip_addr *dst_ip, u16_t dst_port)
|
||||||
{
|
{
|
||||||
err_t err;
|
err_t err;
|
||||||
|
/* temporary space for current PCB remote address */
|
||||||
struct ip_addr pcb_remote_ip;
|
struct ip_addr pcb_remote_ip;
|
||||||
u16_t pcb_remote_port;
|
u16_t pcb_remote_port;
|
||||||
/* remember remote peer address of PCB */
|
/* remember current remote peer address of PCB */
|
||||||
pcb_remote_ip.addr = pcb->remote_ip.addr;
|
pcb_remote_ip.addr = pcb->remote_ip.addr;
|
||||||
pcb_remote_port = pcb->remote_port;
|
pcb_remote_port = pcb->remote_port;
|
||||||
/* copy packet destination address to PCB remote peer address */
|
/* copy packet destination address to PCB remote peer address */
|
||||||
@@ -366,7 +268,7 @@ udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
|
|||||||
pcb->remote_port = dst_port;
|
pcb->remote_port = dst_port;
|
||||||
/* send to the packet destination address */
|
/* send to the packet destination address */
|
||||||
err = udp_send(pcb, p);
|
err = udp_send(pcb, p);
|
||||||
/* reset PCB remote peer address */
|
/* restore PCB remote peer address */
|
||||||
pcb->remote_ip.addr = pcb_remote_ip.addr;
|
pcb->remote_ip.addr = pcb_remote_ip.addr;
|
||||||
pcb->remote_port = pcb_remote_port;
|
pcb->remote_port = pcb_remote_port;
|
||||||
return err;
|
return err;
|
||||||
@@ -405,6 +307,14 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* find the outgoing network interface for this packet */
|
||||||
|
netif = ip_route(&(pcb->remote_ip));
|
||||||
|
/* no outgoing network interface could be found? */
|
||||||
|
if (netif == NULL) {
|
||||||
|
LWIP_DEBUGF(UDP_DEBUG | 1, ("udp_send: No route to 0x%"X32_F"\n", pcb->remote_ip.addr));
|
||||||
|
UDP_STATS_INC(udp.rterr);
|
||||||
|
return ERR_RTE;
|
||||||
|
}
|
||||||
|
|
||||||
/* not enough space to add an UDP header to first pbuf in given p chain? */
|
/* not enough space to add an UDP header to first pbuf in given p chain? */
|
||||||
if (pbuf_header(p, UDP_HLEN)) {
|
if (pbuf_header(p, UDP_HLEN)) {
|
||||||
@@ -432,12 +342,6 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
|||||||
/* in UDP, 0 checksum means 'no checksum' */
|
/* in UDP, 0 checksum means 'no checksum' */
|
||||||
udphdr->chksum = 0x0000;
|
udphdr->chksum = 0x0000;
|
||||||
|
|
||||||
/* find the outgoing network interface for this packet */
|
|
||||||
if ((netif = ip_route(&(pcb->remote_ip))) == NULL) {
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG | 1, ("udp_send: No route to 0x%lx\n", pcb->remote_ip.addr));
|
|
||||||
UDP_STATS_INC(udp.rterr);
|
|
||||||
return ERR_RTE;
|
|
||||||
}
|
|
||||||
/* PCB local address is IP_ANY_ADDR? */
|
/* PCB local address is IP_ANY_ADDR? */
|
||||||
if (ip_addr_isany(&pcb->local_ip)) {
|
if (ip_addr_isany(&pcb->local_ip)) {
|
||||||
/* use outgoing network interface IP address as source address */
|
/* use outgoing network interface IP address as source address */
|
||||||
@@ -447,11 +351,11 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
|||||||
src_ip = &(pcb->local_ip);
|
src_ip = &(pcb->local_ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %u\n", q->tot_len));
|
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %"U16_F"\n", q->tot_len));
|
||||||
|
|
||||||
/* UDP Lite protocol? */
|
/* UDP Lite protocol? */
|
||||||
if (pcb->flags & UDP_FLAGS_UDPLITE) {
|
if (pcb->flags & UDP_FLAGS_UDPLITE) {
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %u\n", q->tot_len));
|
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %"U16_F"\n", q->tot_len));
|
||||||
/* set UDP message length in UDP header */
|
/* set UDP message length in UDP header */
|
||||||
udphdr->len = htons(pcb->chksum_len);
|
udphdr->len = htons(pcb->chksum_len);
|
||||||
/* calculate checksum */
|
/* calculate checksum */
|
||||||
@@ -468,7 +372,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
|||||||
err = ip_output_if (q, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif);
|
err = ip_output_if (q, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif);
|
||||||
/* UDP */
|
/* UDP */
|
||||||
} else {
|
} else {
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %u\n", q->tot_len));
|
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %"U16_F"\n", q->tot_len));
|
||||||
udphdr->len = htons(q->tot_len);
|
udphdr->len = htons(q->tot_len);
|
||||||
/* calculate checksum */
|
/* calculate checksum */
|
||||||
#if CHECKSUM_GEN_UDP
|
#if CHECKSUM_GEN_UDP
|
||||||
@@ -480,7 +384,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
|||||||
#else
|
#else
|
||||||
udphdr->chksum = 0x0000;
|
udphdr->chksum = 0x0000;
|
||||||
#endif
|
#endif
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04x\n", udphdr->chksum));
|
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum));
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n"));
|
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n"));
|
||||||
/* output to IP */
|
/* output to IP */
|
||||||
err = ip_output_if(q, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);
|
err = ip_output_if(q, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);
|
||||||
@@ -519,12 +423,10 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
|||||||
{
|
{
|
||||||
struct udp_pcb *ipcb;
|
struct udp_pcb *ipcb;
|
||||||
u8_t rebind;
|
u8_t rebind;
|
||||||
#if SO_REUSE
|
|
||||||
int reuse_port_all_set = 1;
|
|
||||||
#endif /* SO_REUSE */
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, ("udp_bind(ipaddr = "));
|
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, ("udp_bind(ipaddr = "));
|
||||||
ip_addr_debug_print(UDP_DEBUG, ipaddr);
|
ip_addr_debug_print(UDP_DEBUG, ipaddr);
|
||||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, (", port = %u)\n", port));
|
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, (", port = %"U16_F")\n", port));
|
||||||
|
|
||||||
rebind = 0;
|
rebind = 0;
|
||||||
/* Check for double bind and rebind of the same pcb */
|
/* Check for double bind and rebind of the same pcb */
|
||||||
@@ -537,7 +439,6 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
|||||||
rebind = 1;
|
rebind = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SO_REUSE == 0
|
|
||||||
/* this code does not allow upper layer to share a UDP port for
|
/* this code does not allow upper layer to share a UDP port for
|
||||||
listening to broadcast or multicast traffic (See SO_REUSE_ADDR and
|
listening to broadcast or multicast traffic (See SO_REUSE_ADDR and
|
||||||
SO_REUSE_PORT under *BSD). TODO: See where it fits instead, OR
|
SO_REUSE_PORT under *BSD). TODO: See where it fits instead, OR
|
||||||
@@ -550,56 +451,13 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
|||||||
ip_addr_isany(ipaddr) ||
|
ip_addr_isany(ipaddr) ||
|
||||||
ip_addr_cmp(&(ipcb->local_ip), ipaddr))) {
|
ip_addr_cmp(&(ipcb->local_ip), ipaddr))) {
|
||||||
/* other PCB already binds to this local IP and port */
|
/* other PCB already binds to this local IP and port */
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: local port %u already bound by another pcb\n", port));
|
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: local port %"U16_F" already bound by another pcb\n", port));
|
||||||
return ERR_USE;
|
return ERR_USE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else /* SO_REUSE */
|
|
||||||
/* Search through list of PCB's.
|
|
||||||
|
|
||||||
If there is a PCB bound to specified port and IP_ADDR_ANY another PCB can be bound to the interface IP
|
|
||||||
or to the loopback address on the same port if SOF_REUSEADDR is set. Any combination of PCB's bound to
|
|
||||||
the same local port, but to one address out of {IP_ADDR_ANY, 127.0.0.1, interface IP} at a time is valid.
|
|
||||||
But no two PCB's bound to same local port and same local address is valid.
|
|
||||||
|
|
||||||
If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then
|
|
||||||
all PCB's must have the SOF_REUSEPORT option set.
|
|
||||||
|
|
||||||
When the two options aren't set and specified port is already bound, ERR_USE is returned saying that
|
|
||||||
address is already in use. */
|
|
||||||
else if (ipcb->local_port == port) {
|
|
||||||
if(ip_addr_cmp(&(ipcb->local_ip), ipaddr)) {
|
|
||||||
if(pcb->so_options & SOF_REUSEPORT) {
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT set and same address.\n"));
|
|
||||||
reuse_port_all_set = (reuse_port_all_set && (ipcb->so_options & SOF_REUSEPORT));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT not set and same address.\n"));
|
|
||||||
return ERR_USE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(ipcb->local_ip))) ||
|
|
||||||
(!ip_addr_isany(ipaddr) && ip_addr_isany(&(ipcb->local_ip)))) {
|
|
||||||
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
|
|
||||||
return ERR_USE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* SO_REUSE */
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SO_REUSE
|
|
||||||
/* If SOF_REUSEPORT isn't set in all PCB's bound to specified port and local address specified then
|
|
||||||
{IP, port} can't be reused. */
|
|
||||||
if(!reuse_port_all_set) {
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: not all sockets have SO_REUSEPORT set.\n"));
|
|
||||||
return ERR_USE;
|
|
||||||
}
|
|
||||||
#endif /* SO_REUSE */
|
|
||||||
|
|
||||||
ip_addr_set(&pcb->local_ip, ipaddr);
|
ip_addr_set(&pcb->local_ip, ipaddr);
|
||||||
/* no port specified? */
|
/* no port specified? */
|
||||||
if (port == 0) {
|
if (port == 0) {
|
||||||
@@ -629,11 +487,11 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
|||||||
pcb->next = udp_pcbs;
|
pcb->next = udp_pcbs;
|
||||||
udp_pcbs = pcb;
|
udp_pcbs = pcb;
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | DBG_STATE, ("udp_bind: bound to %u.%u.%u.%u, port %u\n",
|
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | DBG_STATE, ("udp_bind: bound to %"U16_F".%"U16_F".%"U16_F".%"U16_F", port %"U16_F"\n",
|
||||||
(unsigned int)(ntohl(pcb->local_ip.addr) >> 24 & 0xff),
|
(u16_t)(ntohl(pcb->local_ip.addr) >> 24 & 0xff),
|
||||||
(unsigned int)(ntohl(pcb->local_ip.addr) >> 16 & 0xff),
|
(u16_t)(ntohl(pcb->local_ip.addr) >> 16 & 0xff),
|
||||||
(unsigned int)(ntohl(pcb->local_ip.addr) >> 8 & 0xff),
|
(u16_t)(ntohl(pcb->local_ip.addr) >> 8 & 0xff),
|
||||||
(unsigned int)(ntohl(pcb->local_ip.addr) & 0xff), pcb->local_port));
|
(u16_t)(ntohl(pcb->local_ip.addr) & 0xff), pcb->local_port));
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -682,11 +540,11 @@ udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
|||||||
pcb->local_ip.addr = 0;
|
pcb->local_ip.addr = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | DBG_STATE, ("udp_connect: connected to %u.%u.%u.%u, port %u\n",
|
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | DBG_STATE, ("udp_connect: connected to %"U16_F".%"U16_F".%"U16_F".%"U16_F",port %"U16_F"\n",
|
||||||
(unsigned int)(ntohl(pcb->remote_ip.addr) >> 24 & 0xff),
|
(u16_t)(ntohl(pcb->remote_ip.addr) >> 24 & 0xff),
|
||||||
(unsigned int)(ntohl(pcb->remote_ip.addr) >> 16 & 0xff),
|
(u16_t)(ntohl(pcb->remote_ip.addr) >> 16 & 0xff),
|
||||||
(unsigned int)(ntohl(pcb->remote_ip.addr) >> 8 & 0xff),
|
(u16_t)(ntohl(pcb->remote_ip.addr) >> 8 & 0xff),
|
||||||
(unsigned int)(ntohl(pcb->remote_ip.addr) & 0xff), pcb->remote_port));
|
(u16_t)(ntohl(pcb->remote_ip.addr) & 0xff), pcb->remote_port));
|
||||||
|
|
||||||
/* Insert UDP PCB into the list of active UDP PCBs. */
|
/* Insert UDP PCB into the list of active UDP PCBs. */
|
||||||
for(ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
|
for(ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
|
||||||
@@ -771,18 +629,17 @@ udp_new(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if UDP_DEBUG
|
#if UDP_DEBUG
|
||||||
int
|
void
|
||||||
udp_debug_print(struct udp_hdr *udphdr)
|
udp_debug_print(struct udp_hdr *udphdr)
|
||||||
{
|
{
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\n"));
|
LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\n"));
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("| %5u | %5u | (src port, dest port)\n",
|
LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n",
|
||||||
ntohs(udphdr->src), ntohs(udphdr->dest)));
|
ntohs(udphdr->src), ntohs(udphdr->dest)));
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("| %5u | 0x%04x | (len, chksum)\n",
|
LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | 0x%04"X16_F" | (len, chksum)\n",
|
||||||
ntohs(udphdr->len), ntohs(udphdr->chksum)));
|
ntohs(udphdr->len), ntohs(udphdr->chksum)));
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
|
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
#endif /* UDP_DEBUG */
|
#endif /* UDP_DEBUG */
|
||||||
|
|
||||||
|
|||||||
@@ -39,13 +39,16 @@
|
|||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
|
|
||||||
u16_t inet_chksum(void *dataptr, u16_t len);
|
u16_t inet_chksum(void *dataptr, u16_t len);
|
||||||
|
#if 0 /* optimized routine */
|
||||||
|
u16_t inet_chksum4(u8_t *dataptr, u16_t len);
|
||||||
|
#endif
|
||||||
u16_t inet_chksum_pbuf(struct pbuf *p);
|
u16_t inet_chksum_pbuf(struct pbuf *p);
|
||||||
u16_t inet_chksum_pseudo(struct pbuf *p,
|
u16_t inet_chksum_pseudo(struct pbuf *p,
|
||||||
struct ip_addr *src, struct ip_addr *dest,
|
struct ip_addr *src, struct ip_addr *dest,
|
||||||
u8_t proto, u16_t proto_len);
|
u8_t proto, u16_t proto_len);
|
||||||
|
|
||||||
u32_t inet_addr(const char *cp);
|
u32_t inet_addr(const char *cp);
|
||||||
int inet_aton(const char *cp, struct in_addr *addr);
|
s8_t inet_aton(const char *cp, struct in_addr *addr);
|
||||||
char *inet_ntoa(struct in_addr addr); /* returns ptr to static buffer; not reentrant! */
|
char *inet_ntoa(struct in_addr addr); /* returns ptr to static buffer; not reentrant! */
|
||||||
|
|
||||||
#ifdef htons
|
#ifdef htons
|
||||||
|
|||||||
@@ -40,7 +40,6 @@
|
|||||||
|
|
||||||
#include "lwip/err.h"
|
#include "lwip/err.h"
|
||||||
|
|
||||||
struct netif;
|
|
||||||
|
|
||||||
void ip_init(void);
|
void ip_init(void);
|
||||||
struct netif *ip_route(struct ip_addr *dest);
|
struct netif *ip_route(struct ip_addr *dest);
|
||||||
|
|||||||
@@ -117,7 +117,15 @@ extern const struct ip_addr ip_addr_broadcast;
|
|||||||
#define ip_addr_set(dest, src) (dest)->addr = \
|
#define ip_addr_set(dest, src) (dest)->addr = \
|
||||||
((src) == NULL? 0:\
|
((src) == NULL? 0:\
|
||||||
(src)->addr)
|
(src)->addr)
|
||||||
#define ip_addr_maskcmp(addr1, addr2, mask) (((addr1)->addr & \
|
/**
|
||||||
|
* Determine if two address are on the same network.
|
||||||
|
*
|
||||||
|
* @arg addr1 IP address 1
|
||||||
|
* @arg addr2 IP address 2
|
||||||
|
* @arg mask network identifier mask
|
||||||
|
* @return !0 if the network identifiers of both address match
|
||||||
|
*/
|
||||||
|
#define ip_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \
|
||||||
(mask)->addr) == \
|
(mask)->addr) == \
|
||||||
((addr2)->addr & \
|
((addr2)->addr & \
|
||||||
(mask)->addr))
|
(mask)->addr))
|
||||||
@@ -130,18 +138,18 @@ u8_t ip_addr_isbroadcast(struct ip_addr *, struct netif *);
|
|||||||
#define ip_addr_ismulticast(addr1) (((addr1)->addr & ntohl(0xf0000000)) == ntohl(0xe0000000))
|
#define ip_addr_ismulticast(addr1) (((addr1)->addr & ntohl(0xf0000000)) == ntohl(0xe0000000))
|
||||||
|
|
||||||
|
|
||||||
#define ip_addr_debug_print(debug, ipaddr) LWIP_DEBUGF(debug, ("%u.%u.%u.%u", \
|
#define ip_addr_debug_print(debug, ipaddr) LWIP_DEBUGF(debug, ("%"U16_F".%"U16_F".%"U16_F".%"U16_F, \
|
||||||
ipaddr?(unsigned int)(ntohl((ipaddr)->addr) >> 24) & 0xff:0, \
|
ipaddr?(u16_t)(ntohl((ipaddr)->addr) >> 24) & 0xff:0, \
|
||||||
ipaddr?(unsigned int)(ntohl((ipaddr)->addr) >> 16) & 0xff:0, \
|
ipaddr?(u16_t)(ntohl((ipaddr)->addr) >> 16) & 0xff:0, \
|
||||||
ipaddr?(unsigned int)(ntohl((ipaddr)->addr) >> 8) & 0xff:0, \
|
ipaddr?(u16_t)(ntohl((ipaddr)->addr) >> 8) & 0xff:0, \
|
||||||
ipaddr?(unsigned int)ntohl((ipaddr)->addr) & 0xff:0U))
|
ipaddr?(u16_t)ntohl((ipaddr)->addr) & 0xff:0U))
|
||||||
|
|
||||||
/* cast to unsigned int, as it is used as argument to printf functions
|
/* cast to unsigned int, as it is used as argument to printf functions
|
||||||
* which expect integer arguments */
|
* which expect integer arguments. CSi: use cc.h formatters (conversion chars)! */
|
||||||
#define ip4_addr1(ipaddr) ((unsigned int)(ntohl((ipaddr)->addr) >> 24) & 0xff)
|
#define ip4_addr1(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 24) & 0xff)
|
||||||
#define ip4_addr2(ipaddr) ((unsigned int)(ntohl((ipaddr)->addr) >> 16) & 0xff)
|
#define ip4_addr2(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 16) & 0xff)
|
||||||
#define ip4_addr3(ipaddr) ((unsigned int)(ntohl((ipaddr)->addr) >> 8) & 0xff)
|
#define ip4_addr3(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 8) & 0xff)
|
||||||
#define ip4_addr4(ipaddr) ((unsigned int)(ntohl((ipaddr)->addr)) & 0xff)
|
#define ip4_addr4(ipaddr) ((u16_t)(ntohl((ipaddr)->addr)) & 0xff)
|
||||||
#endif /* __LWIP_IP_ADDR_H__ */
|
#endif /* __LWIP_IP_ADDR_H__ */
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -38,8 +38,9 @@
|
|||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
|
|
||||||
struct pbuf * ip_reass(struct pbuf *);
|
void ip_reass_tmr(void);
|
||||||
err_t ip_frag(struct pbuf *, struct netif *, struct ip_addr *);
|
struct pbuf * ip_reass(struct pbuf *p);
|
||||||
|
err_t ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest);
|
||||||
|
|
||||||
#endif /* __LWIP_IP_FRAG_H__ */
|
#endif /* __LWIP_IP_FRAG_H__ */
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ u16_t inet_chksum_pseudo(struct pbuf *p,
|
|||||||
u8_t proto, u32_t proto_len);
|
u8_t proto, u32_t proto_len);
|
||||||
|
|
||||||
u32_t inet_addr(const char *cp);
|
u32_t inet_addr(const char *cp);
|
||||||
int inet_aton(const char *cp, struct in_addr *addr);
|
s8_t inet_aton(const char *cp, struct in_addr *addr);
|
||||||
|
|
||||||
#ifndef _MACHINE_ENDIAN_H_
|
#ifndef _MACHINE_ENDIAN_H_
|
||||||
#ifndef _NETINET_IN_H
|
#ifndef _NETINET_IN_H
|
||||||
|
|||||||
@@ -81,10 +81,10 @@ void ip_input(struct pbuf *p, struct netif *inp);
|
|||||||
|
|
||||||
/* source and destination addresses in network byte order, please */
|
/* source and destination addresses in network byte order, please */
|
||||||
err_t ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
err_t ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||||
unsigned char ttl, unsigned char proto);
|
u8_t ttl, u8_t proto);
|
||||||
|
|
||||||
err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||||
unsigned char ttl, unsigned char proto,
|
u8_t ttl, u8_t proto,
|
||||||
struct netif *netif);
|
struct netif *netif);
|
||||||
|
|
||||||
#if IP_DEBUG
|
#if IP_DEBUG
|
||||||
|
|||||||
@@ -45,11 +45,11 @@ struct ip_addr {
|
|||||||
(ipaddr)->addr[2] = htonl(((e & 0xffff) << 16) | (f & 0xffff)); \
|
(ipaddr)->addr[2] = htonl(((e & 0xffff) << 16) | (f & 0xffff)); \
|
||||||
(ipaddr)->addr[3] = htonl(((g & 0xffff) << 16) | (h & 0xffff)); } while(0)
|
(ipaddr)->addr[3] = htonl(((g & 0xffff) << 16) | (h & 0xffff)); } while(0)
|
||||||
|
|
||||||
int ip_addr_maskcmp(struct ip_addr *addr1, struct ip_addr *addr2,
|
u8_t ip_addr_netcmp(struct ip_addr *addr1, struct ip_addr *addr2,
|
||||||
struct ip_addr *mask);
|
struct ip_addr *mask);
|
||||||
int ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2);
|
u8_t ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2);
|
||||||
void ip_addr_set(struct ip_addr *dest, struct ip_addr *src);
|
void ip_addr_set(struct ip_addr *dest, struct ip_addr *src);
|
||||||
int ip_addr_isany(struct ip_addr *addr);
|
u8_t ip_addr_isany(struct ip_addr *addr);
|
||||||
|
|
||||||
|
|
||||||
#if IP_DEBUG
|
#if IP_DEBUG
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ struct api_msg_msg {
|
|||||||
struct {
|
struct {
|
||||||
void *dataptr;
|
void *dataptr;
|
||||||
u16_t len;
|
u16_t len;
|
||||||
unsigned char copy;
|
u8_t copy;
|
||||||
} w;
|
} w;
|
||||||
sys_mbox_t mbox;
|
sys_mbox_t mbox;
|
||||||
u16_t len;
|
u16_t len;
|
||||||
|
|||||||
@@ -71,7 +71,7 @@
|
|||||||
/** print debug message only if debug message type is enabled...
|
/** print debug message only if debug message type is enabled...
|
||||||
* AND is of correct type AND is at least DBG_LEVEL
|
* AND is of correct type AND is at least DBG_LEVEL
|
||||||
*/
|
*/
|
||||||
# define LWIP_DEBUGF(debug,x) do { if (((debug) & DBG_ON) && ((debug) & DBG_TYPES_ON) && ((int)((debug) & DBG_MASK_LEVEL) >= DBG_MIN_LEVEL)) { LWIP_PLATFORM_DIAG(x); if ((debug) & DBG_HALT) while(1); } } while(0)
|
# define LWIP_DEBUGF(debug,x) do { if (((debug) & DBG_ON) && ((debug) & DBG_TYPES_ON) && ((s16_t)((debug) & DBG_MASK_LEVEL) >= DBG_MIN_LEVEL)) { LWIP_PLATFORM_DIAG(x); if ((debug) & DBG_HALT) while(1); } } while(0)
|
||||||
# define LWIP_ERROR(x) do { LWIP_PLATFORM_DIAG(x); } while(0)
|
# define LWIP_ERROR(x) do { LWIP_PLATFORM_DIAG(x); } while(0)
|
||||||
#else /* LWIP_DEBUG */
|
#else /* LWIP_DEBUG */
|
||||||
# define LWIP_DEBUGF(debug,x)
|
# define LWIP_DEBUGF(debug,x)
|
||||||
|
|||||||
@@ -86,8 +86,12 @@ struct dhcp_msg
|
|||||||
PACK_STRUCT_FIELD(u8_t file[DHCP_FILE_LEN]);
|
PACK_STRUCT_FIELD(u8_t file[DHCP_FILE_LEN]);
|
||||||
PACK_STRUCT_FIELD(u32_t cookie);
|
PACK_STRUCT_FIELD(u32_t cookie);
|
||||||
#define DHCP_MIN_OPTIONS_LEN 68U
|
#define DHCP_MIN_OPTIONS_LEN 68U
|
||||||
|
/** make sure user does not configure this too small */
|
||||||
|
#if ((defined(DHCP_OPTIONS_LEN)) && (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN))
|
||||||
|
# undef DHCP_OPTIONS_LEN
|
||||||
|
#endif
|
||||||
/** allow this to be configured in lwipopts.h, but not too small */
|
/** allow this to be configured in lwipopts.h, but not too small */
|
||||||
#if ((!defined(DHCP_OPTIONS_LEN)) || (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN))
|
#if (!defined(DHCP_OPTIONS_LEN))
|
||||||
/** set this to be sufficient for your options in outgoing DHCP msgs */
|
/** set this to be sufficient for your options in outgoing DHCP msgs */
|
||||||
# define DHCP_OPTIONS_LEN DHCP_MIN_OPTIONS_LEN
|
# define DHCP_OPTIONS_LEN DHCP_MIN_OPTIONS_LEN
|
||||||
#endif
|
#endif
|
||||||
@@ -100,11 +104,13 @@ PACK_STRUCT_END
|
|||||||
|
|
||||||
/** start DHCP configuration */
|
/** start DHCP configuration */
|
||||||
err_t dhcp_start(struct netif *netif);
|
err_t dhcp_start(struct netif *netif);
|
||||||
|
/** enforce early lease renewal (not needed normally)*/
|
||||||
|
err_t dhcp_renew(struct netif *netif);
|
||||||
|
/** release the DHCP lease, usually called before dhcp_stop()*/
|
||||||
|
err_t dhcp_release(struct netif *netif);
|
||||||
/** stop DHCP configuration */
|
/** stop DHCP configuration */
|
||||||
void dhcp_stop(struct netif *netif);
|
void dhcp_stop(struct netif *netif);
|
||||||
/** enforce lease renewal */
|
/** inform server of our manual IP address */
|
||||||
err_t dhcp_renew(struct netif *netif);
|
|
||||||
/** inform server of our IP address */
|
|
||||||
void dhcp_inform(struct netif *netif);
|
void dhcp_inform(struct netif *netif);
|
||||||
|
|
||||||
/** if enabled, check whether the offered IP address is not in use, using ARP */
|
/** if enabled, check whether the offered IP address is not in use, using ARP */
|
||||||
|
|||||||
@@ -98,9 +98,9 @@ struct netif {
|
|||||||
struct dhcp *dhcp;
|
struct dhcp *dhcp;
|
||||||
#endif
|
#endif
|
||||||
/** number of bytes used in hwaddr */
|
/** number of bytes used in hwaddr */
|
||||||
unsigned char hwaddr_len;
|
u8_t hwaddr_len;
|
||||||
/** link level hardware address of this interface */
|
/** link level hardware address of this interface */
|
||||||
unsigned char hwaddr[NETIF_MAX_HWADDR_LEN];
|
u8_t hwaddr[NETIF_MAX_HWADDR_LEN];
|
||||||
/** maximum transfer unit (in bytes) */
|
/** maximum transfer unit (in bytes) */
|
||||||
u16_t mtu;
|
u16_t mtu;
|
||||||
/** flags (see NETIF_FLAG_ above) */
|
/** flags (see NETIF_FLAG_ above) */
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ a lot of data that needs to be copied, this should be set high. */
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MEMP_SANITY_CHECK
|
#ifndef MEMP_SANITY_CHECK
|
||||||
#define MEMP_SANITY_CHECK 0
|
#define MEMP_SANITY_CHECK 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
|
/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
|
||||||
@@ -163,7 +163,15 @@ a lot of data that needs to be copied, this should be set high. */
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* If enabled, outgoing packets are queued during hardware address
|
* If enabled, outgoing packets are queued during hardware address
|
||||||
* resolution. The etharp.c implementation queues 1 packet only.
|
* resolution.
|
||||||
|
*
|
||||||
|
* This feature has not stabilized yet. Single-packet queueing is
|
||||||
|
* believed to be stable, multi-packet queueing is believed to
|
||||||
|
* clash with the TCP segment queueing.
|
||||||
|
*
|
||||||
|
* As multi-packet-queueing is currently disabled, enabling this
|
||||||
|
* _should_ work, but we need your testing feedback on lwip-users.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef ARP_QUEUEING
|
#ifndef ARP_QUEUEING
|
||||||
#define ARP_QUEUEING 1
|
#define ARP_QUEUEING 1
|
||||||
@@ -303,7 +311,7 @@ a lot of data that needs to be copied, this should be set high. */
|
|||||||
|
|
||||||
/* Support loop interface (127.0.0.1) */
|
/* Support loop interface (127.0.0.1) */
|
||||||
#ifndef LWIP_HAVE_LOOPIF
|
#ifndef LWIP_HAVE_LOOPIF
|
||||||
#define LWIP_HAVE_LOOPIF 1
|
#define LWIP_HAVE_LOOPIF 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef LWIP_EVENT_API
|
#ifndef LWIP_EVENT_API
|
||||||
@@ -338,8 +346,10 @@ a lot of data that needs to be copied, this should be set high. */
|
|||||||
|
|
||||||
/* ---------- Socket Options ---------- */
|
/* ---------- Socket Options ---------- */
|
||||||
/* Enable SO_REUSEADDR and SO_REUSEPORT options */
|
/* Enable SO_REUSEADDR and SO_REUSEPORT options */
|
||||||
#ifndef SO_REUSE
|
#ifdef SO_REUSE
|
||||||
# define SO_REUSE 1
|
/* I removed the lot since this was an ugly hack. It broke the raw-API.
|
||||||
|
It also came with many ugly goto's, Christiaan Simons. */
|
||||||
|
#error "SO_REUSE currently unavailable, this was a hack"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -355,63 +365,63 @@ a lot of data that needs to be copied, this should be set high. */
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef LINK_STATS
|
#ifndef LINK_STATS
|
||||||
#define LINK_STATS 1
|
#define LINK_STATS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef IP_STATS
|
#ifndef IP_STATS
|
||||||
#define IP_STATS 1
|
#define IP_STATS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef IPFRAG_STATS
|
#ifndef IPFRAG_STATS
|
||||||
#define IPFRAG_STATS 1
|
#define IPFRAG_STATS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef ICMP_STATS
|
#ifndef ICMP_STATS
|
||||||
#define ICMP_STATS 1
|
#define ICMP_STATS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef UDP_STATS
|
#ifndef UDP_STATS
|
||||||
#define UDP_STATS 1
|
#define UDP_STATS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef TCP_STATS
|
#ifndef TCP_STATS
|
||||||
#define TCP_STATS 1
|
#define TCP_STATS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MEM_STATS
|
#ifndef MEM_STATS
|
||||||
#define MEM_STATS 1
|
#define MEM_STATS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MEMP_STATS
|
#ifndef MEMP_STATS
|
||||||
#define MEMP_STATS 1
|
#define MEMP_STATS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PBUF_STATS
|
#ifndef PBUF_STATS
|
||||||
#define PBUF_STATS 1
|
#define PBUF_STATS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef SYS_STATS
|
#ifndef SYS_STATS
|
||||||
#define SYS_STATS 1
|
#define SYS_STATS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef RAW_STATS
|
#ifndef RAW_STATS
|
||||||
#define RAW_STATS 0
|
#define RAW_STATS 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define LINK_STATS 0
|
#define LINK_STATS 0
|
||||||
#define IP_STATS 0
|
#define IP_STATS 0
|
||||||
#define IPFRAG_STATS 0
|
#define IPFRAG_STATS 0
|
||||||
#define ICMP_STATS 0
|
#define ICMP_STATS 0
|
||||||
#define UDP_STATS 0
|
#define UDP_STATS 0
|
||||||
#define TCP_STATS 0
|
#define TCP_STATS 0
|
||||||
#define MEM_STATS 0
|
#define MEM_STATS 0
|
||||||
#define MEMP_STATS 0
|
#define MEMP_STATS 0
|
||||||
#define PBUF_STATS 0
|
#define PBUF_STATS 0
|
||||||
#define SYS_STATS 0
|
#define SYS_STATS 0
|
||||||
#define RAW_STATS 0
|
#define RAW_STATS 0
|
||||||
#define LWIP_STATS_DISPLAY 0
|
#define LWIP_STATS_DISPLAY 0
|
||||||
|
|
||||||
#endif /* LWIP_STATS */
|
#endif /* LWIP_STATS */
|
||||||
|
|
||||||
|
|||||||
@@ -213,18 +213,13 @@ enum tcp_state {
|
|||||||
TIME_WAIT = 10
|
TIME_WAIT = 10
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* the TCP protocol control block */
|
/* the TCP protocol control block */
|
||||||
struct tcp_pcb {
|
struct tcp_pcb {
|
||||||
/* Common members of all PCB types */
|
/** common PCB members */
|
||||||
IP_PCB;
|
IP_PCB;
|
||||||
|
/** protocol specific PCB members */
|
||||||
/* Protocol specific PCB members */
|
struct tcp_pcb *next; /* for the linked list */
|
||||||
|
enum tcp_state state; /* TCP state */
|
||||||
struct tcp_pcb *next; /* for the linked list */
|
|
||||||
|
|
||||||
enum tcp_state state; /* TCP state */
|
|
||||||
|
|
||||||
u8_t prio;
|
u8_t prio;
|
||||||
void *callback_arg;
|
void *callback_arg;
|
||||||
|
|
||||||
@@ -240,7 +235,7 @@ struct tcp_pcb {
|
|||||||
#define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */
|
#define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */
|
||||||
#define TF_NODELAY (u8_t)0x40U /* Disable Nagle algorithm */
|
#define TF_NODELAY (u8_t)0x40U /* Disable Nagle algorithm */
|
||||||
|
|
||||||
/* receiver varables */
|
/* receiver variables */
|
||||||
u32_t rcv_nxt; /* next seqno expected */
|
u32_t rcv_nxt; /* next seqno expected */
|
||||||
u16_t rcv_wnd; /* receiver window */
|
u16_t rcv_wnd; /* receiver window */
|
||||||
|
|
||||||
@@ -253,10 +248,10 @@ struct tcp_pcb {
|
|||||||
|
|
||||||
u16_t mss; /* maximum segment size */
|
u16_t mss; /* maximum segment size */
|
||||||
|
|
||||||
/* RTT estimation variables. */
|
/* RTT (round trip time) estimation variables */
|
||||||
u16_t rttest; /* RTT estimate in 500ms ticks */
|
u32_t rttest; /* RTT estimate in 500ms ticks */
|
||||||
u32_t rtseq; /* sequence number being timed */
|
u32_t rtseq; /* sequence number being timed */
|
||||||
s16_t sa, sv;
|
s16_t sa, sv; /* @todo document this */
|
||||||
|
|
||||||
u16_t rto; /* retransmission time-out */
|
u16_t rto; /* retransmission time-out */
|
||||||
u8_t nrtx; /* number of retransmissions */
|
u8_t nrtx; /* number of retransmissions */
|
||||||
@@ -392,7 +387,7 @@ err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb,
|
|||||||
(errf)((arg),(err))
|
(errf)((arg),(err))
|
||||||
#endif /* LWIP_EVENT_API */
|
#endif /* LWIP_EVENT_API */
|
||||||
|
|
||||||
/* This structure is used to repressent TCP segments when queued. */
|
/* This structure represents a TCP segment on the unsent and unacked queues */
|
||||||
struct tcp_seg {
|
struct tcp_seg {
|
||||||
struct tcp_seg *next; /* used when putting segements on a queue */
|
struct tcp_seg *next; /* used when putting segements on a queue */
|
||||||
struct pbuf *p; /* buffer containing data + TCP header */
|
struct pbuf *p; /* buffer containing data + TCP header */
|
||||||
@@ -444,7 +439,7 @@ void tcp_debug_print(struct tcp_hdr *tcphdr);
|
|||||||
void tcp_debug_print_flags(u8_t flags);
|
void tcp_debug_print_flags(u8_t flags);
|
||||||
void tcp_debug_print_state(enum tcp_state s);
|
void tcp_debug_print_state(enum tcp_state s);
|
||||||
void tcp_debug_print_pcbs(void);
|
void tcp_debug_print_pcbs(void);
|
||||||
int tcp_pcbs_sane(void);
|
s16_t tcp_pcbs_sane(void);
|
||||||
#else
|
#else
|
||||||
# define tcp_debug_print(tcphdr)
|
# define tcp_debug_print(tcphdr)
|
||||||
# define tcp_debug_print_flags(flags)
|
# define tcp_debug_print_flags(flags)
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ void udp_input (struct pbuf *p, struct netif *inp);
|
|||||||
void udp_init (void);
|
void udp_init (void);
|
||||||
|
|
||||||
#if UDP_DEBUG
|
#if UDP_DEBUG
|
||||||
int udp_debug_print(struct udp_hdr *udphdr);
|
void udp_debug_print(struct udp_hdr *udphdr);
|
||||||
#else
|
#else
|
||||||
#define udp_debug_print(udphdr)
|
#define udp_debug_print(udphdr)
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -107,7 +107,8 @@ PACK_STRUCT_END
|
|||||||
# include "arch/epstruct.h"
|
# include "arch/epstruct.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ARP_TMR_INTERVAL 10000
|
/** 5 seconds period */
|
||||||
|
#define ARP_TMR_INTERVAL 5000
|
||||||
|
|
||||||
#define ETHTYPE_ARP 0x0806
|
#define ETHTYPE_ARP 0x0806
|
||||||
#define ETHTYPE_IP 0x0800
|
#define ETHTYPE_IP 0x0800
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
This directory contains generic network interface device drivers that
|
This directory contains generic network interface device drivers that
|
||||||
don't contain any hardware or architecture specific code. The files
|
do not contain any hardware or architecture specific code. The files
|
||||||
are:
|
are:
|
||||||
|
|
||||||
etharp.c
|
etharp.c
|
||||||
Implements the ARP (Address Resolution Protocol) over
|
Implements the ARP (Address Resolution Protocol) over
|
||||||
Ethernet. The code in this file should be used together with
|
Ethernet. The code in this file should be used together with
|
||||||
Ethernet device drivers.
|
Ethernet device drivers. Note that this module has been
|
||||||
|
largely made Ethernet independent so you should be able to
|
||||||
|
adapt this for other link layers (such as Firewire).
|
||||||
|
|
||||||
ethernetif.c
|
ethernetif.c
|
||||||
An example of how an Ethernet device driver could look. This
|
An example of how an Ethernet device driver could look. This
|
||||||
file can be used as a "skeleton" for developing new Ethernet
|
file can be used as a "skeleton" for developing new Ethernet
|
||||||
network device drivers. It uses the etharp.c ARP code.
|
network device drivers. It uses the etharp.c ARP code.
|
||||||
!!!THIS FILE IS NOT IN SYNC WITH CURRENT CODE !!!!
|
|
||||||
|
|
||||||
loopif.c
|
loopif.c
|
||||||
An example network interface that shows how a "loopback"
|
An example network interface that shows how a "loopback"
|
||||||
|
|||||||
@@ -55,10 +55,17 @@
|
|||||||
# include "lwip/dhcp.h"
|
# include "lwip/dhcp.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** the time an ARP entry stays valid after its last update, (120 * 10) seconds = 20 minutes. */
|
/** the time an ARP entry stays valid after its last update,
|
||||||
#define ARP_MAXAGE 120
|
* (240 * 5) seconds = 20 minutes.
|
||||||
/** the time an ARP entry stays pending after first request, (1 * 10) seconds = 10 seconds. */
|
*/
|
||||||
#define ARP_MAXPENDING 1
|
#define ARP_MAXAGE 240
|
||||||
|
/** the time an ARP entry stays pending after first request,
|
||||||
|
* (2 * 5) seconds = 10 seconds.
|
||||||
|
*
|
||||||
|
* @internal Keep this number at least 2, otherwise it might
|
||||||
|
* run out instantly if the timeout occurs directly after a request.
|
||||||
|
*/
|
||||||
|
#define ARP_MAXPENDING 2
|
||||||
|
|
||||||
#define HWTYPE_ETHERNET 1
|
#define HWTYPE_ETHERNET 1
|
||||||
|
|
||||||
@@ -96,9 +103,11 @@ struct etharp_entry {
|
|||||||
static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
|
static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
|
||||||
static struct etharp_entry arp_table[ARP_TABLE_SIZE];
|
static struct etharp_entry arp_table[ARP_TABLE_SIZE];
|
||||||
|
|
||||||
/** ask update_arp_entry() to create new entry instead of merely update existing */
|
/**
|
||||||
/** ask find_entry() to create new entry instead of merely finding existing */
|
* Try hard to create a new entry - we want the IP address to appear in
|
||||||
#define ETHARP_CREATE 1
|
* the cache (even if this means removing an active entry or so). */
|
||||||
|
#define ETHARP_TRY_HARD 1
|
||||||
|
|
||||||
static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags);
|
static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags);
|
||||||
static err_t update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags);
|
static err_t update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags);
|
||||||
/**
|
/**
|
||||||
@@ -121,7 +130,7 @@ etharp_init(void)
|
|||||||
/**
|
/**
|
||||||
* Clears expired entries in the ARP table.
|
* Clears expired entries in the ARP table.
|
||||||
*
|
*
|
||||||
* This function should be called every ETHARP_TMR_INTERVAL microseconds (10 seconds),
|
* This function should be called every ETHARP_TMR_INTERVAL microseconds (5 seconds),
|
||||||
* in order to expire entries in the ARP table.
|
* in order to expire entries in the ARP table.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
@@ -137,13 +146,13 @@ etharp_tmr(void)
|
|||||||
if ((arp_table[i].state == ETHARP_STATE_STABLE) &&
|
if ((arp_table[i].state == ETHARP_STATE_STABLE) &&
|
||||||
/* entry has become old? */
|
/* entry has become old? */
|
||||||
(arp_table[i].ctime >= ARP_MAXAGE)) {
|
(arp_table[i].ctime >= ARP_MAXAGE)) {
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired stable entry %u.\n", i));
|
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired stable entry %"U16_F".\n", (u16_t)i));
|
||||||
arp_table[i].state = ETHARP_STATE_EXPIRED;
|
arp_table[i].state = ETHARP_STATE_EXPIRED;
|
||||||
/* pending entry? */
|
/* pending entry? */
|
||||||
} else if (arp_table[i].state == ETHARP_STATE_PENDING) {
|
} else if (arp_table[i].state == ETHARP_STATE_PENDING) {
|
||||||
/* entry unresolved/pending for too long? */
|
/* entry unresolved/pending for too long? */
|
||||||
if (arp_table[i].ctime >= ARP_MAXPENDING) {
|
if (arp_table[i].ctime >= ARP_MAXPENDING) {
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %u.\n", i));
|
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %"U16_F".\n", (u16_t)i));
|
||||||
arp_table[i].state = ETHARP_STATE_EXPIRED;
|
arp_table[i].state = ETHARP_STATE_EXPIRED;
|
||||||
#if ARP_QUEUEING
|
#if ARP_QUEUEING
|
||||||
} else if (arp_table[i].p != NULL) {
|
} else if (arp_table[i].p != NULL) {
|
||||||
@@ -157,7 +166,7 @@ etharp_tmr(void)
|
|||||||
/* and empty packet queue */
|
/* and empty packet queue */
|
||||||
if (arp_table[i].p != NULL) {
|
if (arp_table[i].p != NULL) {
|
||||||
/* remove all queued packets */
|
/* remove all queued packets */
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing entry %u, packet queue %p.\n", i, (void *)(arp_table[i].p)));
|
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].p)));
|
||||||
pbuf_free(arp_table[i].p);
|
pbuf_free(arp_table[i].p);
|
||||||
arp_table[i].p = NULL;
|
arp_table[i].p = NULL;
|
||||||
}
|
}
|
||||||
@@ -169,7 +178,7 @@ etharp_tmr(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search the ARP table for a specific entry.
|
* Search the ARP table for a matching or new entry.
|
||||||
*
|
*
|
||||||
* If an IP address is given, return a pending or stable ARP entry that matches
|
* If an IP address is given, return a pending or stable ARP entry that matches
|
||||||
* the address. If no match is found, create a new entry with this address set,
|
* the address. If no match is found, create a new entry with this address set,
|
||||||
@@ -179,28 +188,29 @@ etharp_tmr(void)
|
|||||||
* If ipaddr is NULL, return a initialized new entry in state ETHARP_EMPTY.
|
* If ipaddr is NULL, return a initialized new entry in state ETHARP_EMPTY.
|
||||||
*
|
*
|
||||||
* In all cases, attempt to create new entries from an empty entry. If no
|
* In all cases, attempt to create new entries from an empty entry. If no
|
||||||
* empty entries are available and ETHARP_CREATE flag is set, recycle
|
* empty entries are available and ETHARP_TRY_HARD flag is set, recycle
|
||||||
* old entries. Heuristic choose the least important entry for recycling.
|
* old entries. Heuristic choose the least important entry for recycling.
|
||||||
*
|
*
|
||||||
* @param ipaddr IP address to find in ARP cache, or to add if not found.
|
* @param ipaddr IP address to find in ARP cache, or to add if not found.
|
||||||
* @param flags
|
* @param flags
|
||||||
* - ETHARP_CREATE: Try hard to create a entry by allowing recycling.
|
* - ETHARP_TRY_HARD: Try hard to create a entry by allowing recycling of
|
||||||
|
* active (stable or pending) entries.
|
||||||
*
|
*
|
||||||
* @return The ARP entry index that matched or is created, ERR_MEM if no
|
* @return The ARP entry index that matched or is created, ERR_MEM if no
|
||||||
* entry is found or could be recycled.
|
* entry is found or could be recycled.
|
||||||
*/
|
*/
|
||||||
static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags)
|
static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags)
|
||||||
{
|
{
|
||||||
s8_t old_pending, old_stable, empty, i;
|
s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE;
|
||||||
u8_t age_pending, age_stable;
|
s8_t empty = ARP_TABLE_SIZE;
|
||||||
|
u8_t i = 0, age_pending = 0, age_stable = 0;
|
||||||
#if ARP_QUEUEING
|
#if ARP_QUEUEING
|
||||||
|
/* oldest entry with packets on queue */
|
||||||
s8_t old_queue = ARP_TABLE_SIZE;
|
s8_t old_queue = ARP_TABLE_SIZE;
|
||||||
|
/* its age */
|
||||||
u8_t age_queue = 0;
|
u8_t age_queue = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
old_pending = old_stable = empty = ARP_TABLE_SIZE;
|
|
||||||
age_pending = age_stable = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* a) do a search through the cache, remember candidates
|
* a) do a search through the cache, remember candidates
|
||||||
* b) select candidate entry
|
* b) select candidate entry
|
||||||
@@ -219,7 +229,7 @@ static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags)
|
|||||||
for (i = 0; i < ARP_TABLE_SIZE; ++i) {
|
for (i = 0; i < ARP_TABLE_SIZE; ++i) {
|
||||||
/* no empty entry found yet and now we do find one? */
|
/* no empty entry found yet and now we do find one? */
|
||||||
if ((empty == ARP_TABLE_SIZE) && (arp_table[i].state == ETHARP_STATE_EMPTY)) {
|
if ((empty == ARP_TABLE_SIZE) && (arp_table[i].state == ETHARP_STATE_EMPTY)) {
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG, ("find_entry: found empty entry %d\n", i));
|
LWIP_DEBUGF(ETHARP_DEBUG, ("find_entry: found empty entry %"U16_F"\n", (u16_t)i));
|
||||||
/* remember first empty entry */
|
/* remember first empty entry */
|
||||||
empty = i;
|
empty = i;
|
||||||
}
|
}
|
||||||
@@ -227,8 +237,8 @@ static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags)
|
|||||||
else if (arp_table[i].state == ETHARP_STATE_PENDING) {
|
else if (arp_table[i].state == ETHARP_STATE_PENDING) {
|
||||||
/* if given, does IP address match IP address in ARP entry? */
|
/* if given, does IP address match IP address in ARP entry? */
|
||||||
if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
|
if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: found matching pending entry %d\n", i));
|
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: found matching pending entry %"U16_F"\n", (u16_t)i));
|
||||||
/* found match, simply bail out */
|
/* found exact IP address match, simply bail out */
|
||||||
return i;
|
return i;
|
||||||
#if ARP_QUEUEING
|
#if ARP_QUEUEING
|
||||||
/* pending with queued packets? */
|
/* pending with queued packets? */
|
||||||
@@ -250,8 +260,8 @@ static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags)
|
|||||||
else if (arp_table[i].state == ETHARP_STATE_STABLE) {
|
else if (arp_table[i].state == ETHARP_STATE_STABLE) {
|
||||||
/* if given, does IP address match IP address in ARP entry? */
|
/* if given, does IP address match IP address in ARP entry? */
|
||||||
if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
|
if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: found matching stable entry %d\n", i));
|
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: found matching stable entry %"U16_F"\n", (u16_t)i));
|
||||||
/* found match, simply bail out */
|
/* found exact IP address match, simply bail out */
|
||||||
return i;
|
return i;
|
||||||
/* remember entry with oldest stable entry in oldest, its age in maxtime */
|
/* remember entry with oldest stable entry in oldest, its age in maxtime */
|
||||||
} else if (arp_table[i].ctime >= age_stable) {
|
} else if (arp_table[i].ctime >= age_stable) {
|
||||||
@@ -260,24 +270,33 @@ static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* { we have no match } => try to create a new entry */
|
||||||
|
|
||||||
|
/* no empty entry found and not allowed to recycle? */
|
||||||
|
if ((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_TRY_HARD) == 0))
|
||||||
|
{
|
||||||
|
return (s8_t)ERR_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
/* b) choose the least destructive entry to recycle:
|
/* b) choose the least destructive entry to recycle:
|
||||||
* 1) empty entry
|
* 1) empty entry
|
||||||
* 2) oldest stable entry
|
* 2) oldest stable entry
|
||||||
* 3) oldest pending entry without queued packets
|
* 3) oldest pending entry without queued packets
|
||||||
* 4) oldest pending entry without queued packets
|
* 4) oldest pending entry without queued packets
|
||||||
|
*
|
||||||
|
* { ETHARP_TRY_HARD is set at this point }
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* 1) empty entry available? */
|
/* 1) empty entry available? */
|
||||||
if (empty < ARP_TABLE_SIZE) {
|
if (empty < ARP_TABLE_SIZE) {
|
||||||
i = empty;
|
i = empty;
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: selecting empty entry %d\n", i));
|
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: selecting empty entry %"U16_F"\n", (u16_t)i));
|
||||||
}
|
}
|
||||||
/* 2) found recyclable stable entry? */
|
/* 2) found recyclable stable entry? */
|
||||||
else if (old_stable < ARP_TABLE_SIZE) {
|
else if (old_stable < ARP_TABLE_SIZE) {
|
||||||
/* recycle oldest stable*/
|
/* recycle oldest stable*/
|
||||||
i = old_stable;
|
i = old_stable;
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: selecting oldest stable entry %d\n", i));
|
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i));
|
||||||
#if ARP_QUEUEING
|
#if ARP_QUEUEING
|
||||||
/* no queued packets should exist on stable entries */
|
/* no queued packets should exist on stable entries */
|
||||||
LWIP_ASSERT("arp_table[i].p == NULL", arp_table[i].p == NULL);
|
LWIP_ASSERT("arp_table[i].p == NULL", arp_table[i].p == NULL);
|
||||||
@@ -286,48 +305,33 @@ static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags)
|
|||||||
} else if (old_pending < ARP_TABLE_SIZE) {
|
} else if (old_pending < ARP_TABLE_SIZE) {
|
||||||
/* recycle oldest pending */
|
/* recycle oldest pending */
|
||||||
i = old_pending;
|
i = old_pending;
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: selecting oldest pending entry %d (without queue)\n", i));
|
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i));
|
||||||
#if ARP_QUEUEING
|
#if ARP_QUEUEING
|
||||||
/* 4) found recyclable pending entry with queued packets? */
|
/* 4) found recyclable pending entry with queued packets? */
|
||||||
} else if (old_queue < ARP_TABLE_SIZE) {
|
} else if (old_queue < ARP_TABLE_SIZE) {
|
||||||
/* recycle oldest pending */
|
/* recycle oldest pending */
|
||||||
i = old_queue;
|
i = old_queue;
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: selecting oldest pending entry %d, freeing packet queue %p\n", i, (void *)(arp_table[i].p)));
|
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].p)));
|
||||||
/* no empty or recyclable entries found */
|
pbuf_free(arp_table[i].p);
|
||||||
|
arp_table[i].p = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
/* no empty or recyclable entries found */
|
||||||
} else {
|
} else {
|
||||||
return ERR_MEM;
|
return (s8_t)ERR_MEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* { empty or recyclable entry found } */
|
/* { empty or recyclable entry found } */
|
||||||
LWIP_ASSERT("i >= 0", i >= 0);
|
|
||||||
LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE);
|
LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE);
|
||||||
|
|
||||||
/* allowed to recycle a entry? */
|
/* recycle entry (no-op for an already empty entry) */
|
||||||
if (flags & ETHARP_CREATE) {
|
arp_table[i].state = ETHARP_STATE_EMPTY;
|
||||||
/* recycle (no-op for an already empty entry) */
|
|
||||||
arp_table[i].state = ETHARP_STATE_EMPTY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* empty entry found or created? */
|
/* IP address given? */
|
||||||
if (arp_table[i].state == ETHARP_STATE_EMPTY) {
|
if (ipaddr != NULL) {
|
||||||
/* IP address given? */
|
/* set IP address */
|
||||||
if (ipaddr != NULL) {
|
ip_addr_set(&arp_table[i].ipaddr, ipaddr);
|
||||||
/* set IP address */
|
|
||||||
ip_addr_set(&arp_table[i].ipaddr, ipaddr);
|
|
||||||
}
|
|
||||||
arp_table[i].ctime = 0;
|
|
||||||
#if ARP_QUEUEING
|
|
||||||
/* remove any queued packets */
|
|
||||||
if (arp_table[i].p != NULL) pbuf_free(arp_table[i].p);
|
|
||||||
arp_table[i].p = NULL;
|
|
||||||
#endif
|
|
||||||
/* no entry available */
|
|
||||||
} else {
|
|
||||||
/* return failure */
|
|
||||||
i = (s8_t)ERR_MEM;
|
|
||||||
}
|
}
|
||||||
|
arp_table[i].ctime = 0;
|
||||||
return (err_t)i;
|
return (err_t)i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,23 +344,23 @@ static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags)
|
|||||||
* @param ipaddr IP address of the inserted ARP entry.
|
* @param ipaddr IP address of the inserted ARP entry.
|
||||||
* @param ethaddr Ethernet address of the inserted ARP entry.
|
* @param ethaddr Ethernet address of the inserted ARP entry.
|
||||||
* @param flags Defines behaviour:
|
* @param flags Defines behaviour:
|
||||||
* - ETHARP_CREATE Allows ARP to insert this as a new item. If not specified,
|
* - ETHARP_TRY_HARD Allows ARP to insert this as a new item. If not specified,
|
||||||
* only existing ARP entries will be updated.
|
* only existing ARP entries will be updated.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* - ERR_OK Succesfully updated ARP cache.
|
* - ERR_OK Succesfully updated ARP cache.
|
||||||
* - ERR_MEM If we could not add a new ARP entry when ETHARP_CREATE was set.
|
* - ERR_MEM If we could not add a new ARP entry when ETHARP_TRY_HARD was set.
|
||||||
* - ERR_ARG Non-unicast address given, those will not appear in ARP cache.
|
* - ERR_ARG Non-unicast address given, those will not appear in ARP cache.
|
||||||
*
|
*
|
||||||
* @see pbuf_free()
|
* @see pbuf_free()
|
||||||
*/
|
*/
|
||||||
err_t
|
static err_t
|
||||||
update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags)
|
update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags)
|
||||||
{
|
{
|
||||||
s8_t i, k;
|
s8_t i, k;
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("update_arp_entry()\n"));
|
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("update_arp_entry()\n"));
|
||||||
LWIP_ASSERT("netif->hwaddr_len != 0", netif->hwaddr_len != 0);
|
LWIP_ASSERT("netif->hwaddr_len != 0", netif->hwaddr_len != 0);
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: %u.%u.%u.%u - %02x:%02x:%02x:%02x:%02x:%02x\n",
|
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n",
|
||||||
ip4_addr1(ipaddr), ip4_addr2(ipaddr), ip4_addr3(ipaddr), ip4_addr4(ipaddr),
|
ip4_addr1(ipaddr), ip4_addr2(ipaddr), ip4_addr3(ipaddr), ip4_addr4(ipaddr),
|
||||||
ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2],
|
ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2],
|
||||||
ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5]));
|
ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5]));
|
||||||
@@ -375,7 +379,7 @@ update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *e
|
|||||||
/* mark it stable */
|
/* mark it stable */
|
||||||
arp_table[i].state = ETHARP_STATE_STABLE;
|
arp_table[i].state = ETHARP_STATE_STABLE;
|
||||||
|
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: updating stable entry %u\n", i));
|
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i));
|
||||||
/* update address */
|
/* update address */
|
||||||
for (k = 0; k < netif->hwaddr_len; ++k) {
|
for (k = 0; k < netif->hwaddr_len; ++k) {
|
||||||
arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
|
arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
|
||||||
@@ -385,10 +389,10 @@ update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *e
|
|||||||
/* this is where we will send out queued packets! */
|
/* this is where we will send out queued packets! */
|
||||||
#if ARP_QUEUEING
|
#if ARP_QUEUEING
|
||||||
while (arp_table[i].p != NULL) {
|
while (arp_table[i].p != NULL) {
|
||||||
/* get the first packet on the queue (if any) */
|
/* get the first packet on the queue */
|
||||||
struct pbuf *p = arp_table[i].p;
|
struct pbuf *p = arp_table[i].p;
|
||||||
/* Ethernet header */
|
/* Ethernet header */
|
||||||
struct eth_hdr *ethhdr = p->payload;;
|
struct eth_hdr *ethhdr = p->payload;
|
||||||
/* remember (and reference) remainder of queue */
|
/* remember (and reference) remainder of queue */
|
||||||
/* note: this will also terminate the p pbuf chain */
|
/* note: this will also terminate the p pbuf chain */
|
||||||
arp_table[i].p = pbuf_dequeue(p);
|
arp_table[i].p = pbuf_dequeue(p);
|
||||||
@@ -427,19 +431,21 @@ void
|
|||||||
etharp_ip_input(struct netif *netif, struct pbuf *p)
|
etharp_ip_input(struct netif *netif, struct pbuf *p)
|
||||||
{
|
{
|
||||||
struct ethip_hdr *hdr;
|
struct ethip_hdr *hdr;
|
||||||
|
LWIP_ASSERT("netif != NULL", netif != NULL);
|
||||||
/* Only insert an entry if the source IP address of the
|
/* Only insert an entry if the source IP address of the
|
||||||
incoming IP packet comes from a host on the local network. */
|
incoming IP packet comes from a host on the local network. */
|
||||||
hdr = p->payload;
|
hdr = p->payload;
|
||||||
/* source is on local network? */
|
/* source is not on the local network? */
|
||||||
if (!ip_addr_maskcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask))) {
|
if (!ip_addr_netcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask))) {
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n"));
|
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n"));
|
||||||
/* update ARP table, ask to insert entry */
|
/* update ARP table */
|
||||||
update_arp_entry(netif, &(hdr->ip.src), &(hdr->eth.src), ETHARP_CREATE);
|
/* @todo We could use ETHARP_TRY_HARD if we think we are going to talk
|
||||||
|
* back soon (for example, if the destination IP address is ours. */
|
||||||
|
update_arp_entry(netif, &(hdr->ip.src), &(hdr->eth.src), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -467,9 +473,11 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
|
|||||||
u8_t i;
|
u8_t i;
|
||||||
u8_t for_us;
|
u8_t for_us;
|
||||||
|
|
||||||
|
LWIP_ASSERT("netif != NULL", netif != NULL);
|
||||||
|
|
||||||
/* drop short ARP packets */
|
/* drop short ARP packets */
|
||||||
if (p->tot_len < sizeof(struct etharp_hdr)) {
|
if (p->tot_len < sizeof(struct etharp_hdr)) {
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 1, ("etharp_arp_input: packet dropped, too short (%d/%d)\n", p->tot_len, sizeof(struct etharp_hdr)));
|
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 1, ("etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len, sizeof(struct etharp_hdr)));
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -492,7 +500,7 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
|
|||||||
if (for_us) {
|
if (for_us) {
|
||||||
/* add IP address in ARP cache; assume requester wants to talk to us.
|
/* add IP address in ARP cache; assume requester wants to talk to us.
|
||||||
* can result in directly sending the queued packets for this host. */
|
* can result in directly sending the queued packets for this host. */
|
||||||
update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), ETHARP_CREATE);
|
update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), ETHARP_TRY_HARD);
|
||||||
/* ARP message not directed to us? */
|
/* ARP message not directed to us? */
|
||||||
} else {
|
} else {
|
||||||
/* update the source IP address in the cache, if present */
|
/* update the source IP address in the cache, if present */
|
||||||
@@ -548,12 +556,16 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
|
|||||||
/* ARP reply. We already updated the ARP cache earlier. */
|
/* ARP reply. We already updated the ARP cache earlier. */
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n"));
|
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n"));
|
||||||
#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
|
#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
|
||||||
/* DHCP wants to know about ARP replies to our wanna-have-address */
|
/* DHCP wants to know about ARP replies from any host with an
|
||||||
if (for_us) dhcp_arp_reply(netif, &sipaddr);
|
* IP address also offered to us by the DHCP server. We do not
|
||||||
|
* want to take a duplicate IP address on a single network.
|
||||||
|
* @todo How should we handle redundant (fail-over) interfaces?
|
||||||
|
* */
|
||||||
|
dhcp_arp_reply(netif, &sipaddr);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %d\n", htons(hdr->opcode)));
|
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %"S16_F"\n", htons(hdr->opcode)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* free ARP packet */
|
/* free ARP packet */
|
||||||
@@ -563,36 +575,27 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
|
|||||||
/**
|
/**
|
||||||
* Resolve and fill-in Ethernet address header for outgoing packet.
|
* Resolve and fill-in Ethernet address header for outgoing packet.
|
||||||
*
|
*
|
||||||
* If ARP has the Ethernet address in cache, the given packet is
|
* For IP multicast and broadcast, corresponding Ethernet addresses
|
||||||
* returned, ready to be sent.
|
* are selected and the packet is transmitted on the link.
|
||||||
*
|
*
|
||||||
* If ARP does not have the Ethernet address in cache the packet is
|
* For unicast addresses, the packet is submitted to etharp_query(). In
|
||||||
* queued (if enabled and space available) and a ARP request is sent.
|
* case the IP address is outside the local network, the IP address of
|
||||||
* This ARP request is returned as a pbuf, which should be sent by
|
* the gateway is used.
|
||||||
* the caller.
|
|
||||||
*
|
|
||||||
* A returned non-NULL packet should be sent by the caller.
|
|
||||||
*
|
|
||||||
* If ARP failed to allocate resources, NULL is returned.
|
|
||||||
*
|
*
|
||||||
* @param netif The lwIP network interface which the IP packet will be sent on.
|
* @param netif The lwIP network interface which the IP packet will be sent on.
|
||||||
* @param ipaddr The IP address of the packet destination.
|
* @param ipaddr The IP address of the packet destination.
|
||||||
* @param pbuf The pbuf(s) containing the IP packet to be sent.
|
* @param pbuf The pbuf(s) containing the IP packet to be sent.
|
||||||
*
|
*
|
||||||
* @return If non-NULL, a packet ready to be sent by caller.
|
|
||||||
*
|
|
||||||
* @return
|
* @return
|
||||||
* - ERR_BUF Could not make room for Ethernet header.
|
* - ERR_RTE No route to destination (no gateway to external networks),
|
||||||
* - ERR_MEM Hardware address unknown, and no more ARP entries available
|
* or the return type of either etharp_query() or netif->linkoutput().
|
||||||
* to query for address or queue the packet.
|
|
||||||
* - ERR_RTE No route to destination (no gateway to external networks).
|
|
||||||
*/
|
*/
|
||||||
err_t
|
err_t
|
||||||
etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
|
etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
|
||||||
{
|
{
|
||||||
struct eth_addr *dest, *srcaddr, mcastaddr;
|
struct eth_addr *dest, *srcaddr, mcastaddr;
|
||||||
struct eth_hdr *ethhdr;
|
struct eth_hdr *ethhdr;
|
||||||
err_t result = ERR_OK;
|
u8_t i;
|
||||||
|
|
||||||
/* make room for Ethernet header - should not fail */
|
/* make room for Ethernet header - should not fail */
|
||||||
if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
|
if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
|
||||||
@@ -607,13 +610,13 @@ etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
|
|||||||
/* Determine on destination hardware address. Broadcasts and multicasts
|
/* Determine on destination hardware address. Broadcasts and multicasts
|
||||||
* are special, other IP addresses are looked up in the ARP table. */
|
* are special, other IP addresses are looked up in the ARP table. */
|
||||||
|
|
||||||
/* destination IP address is an IP broadcast address? */
|
/* broadcast destination IP address? */
|
||||||
if (ip_addr_isany(ipaddr) || ip_addr_isbroadcast(ipaddr, netif)) {
|
if (ip_addr_isbroadcast(ipaddr, netif)) {
|
||||||
/* broadcast on Ethernet also */
|
/* broadcast on Ethernet also */
|
||||||
dest = (struct eth_addr *)ðbroadcast;
|
dest = (struct eth_addr *)ðbroadcast;
|
||||||
/* destination IP address is an IP multicast address? */
|
/* multicast destination IP address? */
|
||||||
} else if (ip_addr_ismulticast(ipaddr)) {
|
} else if (ip_addr_ismulticast(ipaddr)) {
|
||||||
/* Hash IP multicast address to MAC address. */
|
/* Hash IP multicast address to MAC address.*/
|
||||||
mcastaddr.addr[0] = 0x01;
|
mcastaddr.addr[0] = 0x01;
|
||||||
mcastaddr.addr[1] = 0x00;
|
mcastaddr.addr[1] = 0x00;
|
||||||
mcastaddr.addr[2] = 0x5e;
|
mcastaddr.addr[2] = 0x5e;
|
||||||
@@ -622,17 +625,17 @@ etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
|
|||||||
mcastaddr.addr[5] = ip4_addr4(ipaddr);
|
mcastaddr.addr[5] = ip4_addr4(ipaddr);
|
||||||
/* destination Ethernet address is multicast */
|
/* destination Ethernet address is multicast */
|
||||||
dest = &mcastaddr;
|
dest = &mcastaddr;
|
||||||
/* destination IP address is an IP unicast address */
|
/* unicast destination IP address? */
|
||||||
} else {
|
} else {
|
||||||
/* outside local network? */
|
/* outside local network? */
|
||||||
if (!ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {
|
if (!ip_addr_netcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {
|
||||||
/* interface has default gateway? */
|
/* interface has default gateway? */
|
||||||
if (netif->gw.addr != 0) {
|
if (netif->gw.addr != 0) {
|
||||||
/* send to hardware address of default gateway IP address */
|
/* send to hardware address of default gateway IP address */
|
||||||
ipaddr = &(netif->gw);
|
ipaddr = &(netif->gw);
|
||||||
/* no default gateway available */
|
/* no default gateway available */
|
||||||
} else {
|
} else {
|
||||||
/* no route to destination error */
|
/* no route to destination error (default gateway missing) */
|
||||||
return ERR_RTE;
|
return ERR_RTE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -640,23 +643,17 @@ etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
|
|||||||
return etharp_query(netif, ipaddr, q);
|
return etharp_query(netif, ipaddr, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* destination Ethernet address known */
|
/* continuation for multicast/broadcast destinations */
|
||||||
if (dest != NULL) {
|
/* obtain source Ethernet address of the given interface */
|
||||||
u8_t i;
|
srcaddr = (struct eth_addr *)netif->hwaddr;
|
||||||
/* obtain source Ethernet address of the given interface */
|
ethhdr = q->payload;
|
||||||
srcaddr = (struct eth_addr *)netif->hwaddr;
|
for (i = 0; i < netif->hwaddr_len; i++) {
|
||||||
/* A valid IP->MAC address mapping was found, fill in the
|
ethhdr->dest.addr[i] = dest->addr[i];
|
||||||
* Ethernet header for the outgoing packet */
|
ethhdr->src.addr[i] = srcaddr->addr[i];
|
||||||
ethhdr = q->payload;
|
|
||||||
for (i = 0; i < netif->hwaddr_len; i++) {
|
|
||||||
ethhdr->dest.addr[i] = dest->addr[i];
|
|
||||||
ethhdr->src.addr[i] = srcaddr->addr[i];
|
|
||||||
}
|
|
||||||
ethhdr->type = htons(ETHTYPE_IP);
|
|
||||||
/* send packet */
|
|
||||||
result = netif->linkoutput(netif, q);
|
|
||||||
}
|
}
|
||||||
return result;
|
ethhdr->type = htons(ETHTYPE_IP);
|
||||||
|
/* send packet directly on the link */
|
||||||
|
return netif->linkoutput(netif, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -692,25 +689,29 @@ etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
|
|||||||
*/
|
*/
|
||||||
err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
|
err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
|
||||||
{
|
{
|
||||||
struct pbuf *p;
|
|
||||||
struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr;
|
struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr;
|
||||||
err_t result = ERR_MEM;
|
err_t result = ERR_MEM;
|
||||||
s8_t i; /* ARP entry index */
|
s8_t i; /* ARP entry index */
|
||||||
u8_t k; /* Ethernet address octet index */
|
u8_t k; /* Ethernet address octet index */
|
||||||
|
|
||||||
/* non-unicast address? */
|
/* non-unicast address? */
|
||||||
if (ip_addr_isany(ipaddr) ||
|
if (ip_addr_isbroadcast(ipaddr, netif) ||
|
||||||
ip_addr_isbroadcast(ipaddr, netif) ||
|
ip_addr_ismulticast(ipaddr) ||
|
||||||
ip_addr_ismulticast(ipaddr)) {
|
ip_addr_isany(ipaddr)) {
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n"));
|
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n"));
|
||||||
return ERR_ARG;
|
return ERR_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find entry in ARP cache, ask to create entry if queueing packet */
|
/* find entry in ARP cache, ask to create entry if queueing packet */
|
||||||
i = find_entry(ipaddr, (q != NULL) ? ETHARP_CREATE : 0);
|
i = find_entry(ipaddr, ETHARP_TRY_HARD);
|
||||||
|
|
||||||
/* could not find or create entry? */
|
/* could not find or create entry? */
|
||||||
if (i < 0) return (err_t)i;
|
if (i < 0)
|
||||||
|
{
|
||||||
|
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: could not create ARP entry\n"));
|
||||||
|
if (q) LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: packet dropped\n"));
|
||||||
|
return (err_t)i;
|
||||||
|
}
|
||||||
|
|
||||||
/* mark a fresh entry as pending (we just sent a request) */
|
/* mark a fresh entry as pending (we just sent a request) */
|
||||||
if (arp_table[i].state == ETHARP_STATE_EMPTY) {
|
if (arp_table[i].state == ETHARP_STATE_EMPTY) {
|
||||||
@@ -722,7 +723,7 @@ err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
|
|||||||
((arp_table[i].state == ETHARP_STATE_PENDING) ||
|
((arp_table[i].state == ETHARP_STATE_PENDING) ||
|
||||||
(arp_table[i].state == ETHARP_STATE_STABLE)));
|
(arp_table[i].state == ETHARP_STATE_STABLE)));
|
||||||
|
|
||||||
/* do we have a pending entry? */
|
/* do we have a pending entry? or an implicit query request? */
|
||||||
if ((arp_table[i].state == ETHARP_STATE_PENDING) || (q == NULL)) {
|
if ((arp_table[i].state == ETHARP_STATE_PENDING) || (q == NULL)) {
|
||||||
/* try to resolve it; send out ARP request */
|
/* try to resolve it; send out ARP request */
|
||||||
result = etharp_request(netif, ipaddr);
|
result = etharp_request(netif, ipaddr);
|
||||||
@@ -746,6 +747,7 @@ err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
|
|||||||
/* pending entry? (either just created or already pending */
|
/* pending entry? (either just created or already pending */
|
||||||
} else if (arp_table[i].state == ETHARP_STATE_PENDING) {
|
} else if (arp_table[i].state == ETHARP_STATE_PENDING) {
|
||||||
#if ARP_QUEUEING /* queue the given q packet */
|
#if ARP_QUEUEING /* queue the given q packet */
|
||||||
|
struct pbuf *p;
|
||||||
/* copy any PBUF_REF referenced payloads into PBUF_RAM */
|
/* copy any PBUF_REF referenced payloads into PBUF_RAM */
|
||||||
/* (the caller of lwIP assumes the referenced payload can be
|
/* (the caller of lwIP assumes the referenced payload can be
|
||||||
* freed after it returns from the lwIP call that brought us here) */
|
* freed after it returns from the lwIP call that brought us here) */
|
||||||
@@ -757,11 +759,13 @@ err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
|
|||||||
/* ... in the empty queue */
|
/* ... in the empty queue */
|
||||||
pbuf_ref(p);
|
pbuf_ref(p);
|
||||||
arp_table[i].p = p;
|
arp_table[i].p = p;
|
||||||
|
#if 0 /* multi-packet-queueing disabled, see bug #11400 */
|
||||||
} else {
|
} else {
|
||||||
/* ... at tail of non-empty queue */
|
/* ... at tail of non-empty queue */
|
||||||
pbuf_queue(arp_table[i].p, p);
|
pbuf_queue(arp_table[i].p, p);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %d\n", (void *)q, i));
|
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
|
||||||
result = ERR_OK;
|
result = ERR_OK;
|
||||||
} else {
|
} else {
|
||||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
|
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
#include "lwip/mem.h"
|
#include "lwip/mem.h"
|
||||||
#include "lwip/pbuf.h"
|
#include "lwip/pbuf.h"
|
||||||
#include "lwip/sys.h"
|
#include "lwip/sys.h"
|
||||||
|
#include <lwip/stats.h>
|
||||||
|
|
||||||
#include "netif/etharp.h"
|
#include "netif/etharp.h"
|
||||||
|
|
||||||
@@ -117,7 +118,7 @@ low_level_output(struct netif *netif, struct pbuf *p)
|
|||||||
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
|
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef LINK_STATS
|
#if LINK_STATS
|
||||||
lwip_stats.link.xmit++;
|
lwip_stats.link.xmit++;
|
||||||
#endif /* LINK_STATS */
|
#endif /* LINK_STATS */
|
||||||
|
|
||||||
@@ -170,12 +171,12 @@ low_level_input(struct netif *netif)
|
|||||||
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
|
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef LINK_STATS
|
#if LINK_STATS
|
||||||
lwip_stats.link.recv++;
|
lwip_stats.link.recv++;
|
||||||
#endif /* LINK_STATS */
|
#endif /* LINK_STATS */
|
||||||
} else {
|
} else {
|
||||||
drop packet();
|
drop packet();
|
||||||
#ifdef LINK_STATS
|
#if LINK_STATS
|
||||||
lwip_stats.link.memerr++;
|
lwip_stats.link.memerr++;
|
||||||
lwip_stats.link.drop++;
|
lwip_stats.link.drop++;
|
||||||
#endif /* LINK_STATS */
|
#endif /* LINK_STATS */
|
||||||
@@ -229,7 +230,7 @@ ethernetif_input(struct netif *netif)
|
|||||||
/* points to packet payload, which starts with an Ethernet header */
|
/* points to packet payload, which starts with an Ethernet header */
|
||||||
ethhdr = p->payload;
|
ethhdr = p->payload;
|
||||||
|
|
||||||
#ifdef LINK_STATS
|
#if LINK_STATS
|
||||||
lwip_stats.link.recv++;
|
lwip_stats.link.recv++;
|
||||||
#endif /* LINK_STATS */
|
#endif /* LINK_STATS */
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ loopif_output(struct netif *netif, struct pbuf *p,
|
|||||||
struct ip_addr *ipaddr)
|
struct ip_addr *ipaddr)
|
||||||
{
|
{
|
||||||
struct pbuf *q, *r;
|
struct pbuf *q, *r;
|
||||||
char *ptr;
|
u8_t *ptr;
|
||||||
void **arg;
|
void **arg;
|
||||||
|
|
||||||
#if defined(LWIP_DEBUG) && defined(LWIP_TCPDUMP)
|
#if defined(LWIP_DEBUG) && defined(LWIP_TCPDUMP)
|
||||||
|
|||||||
@@ -1235,7 +1235,7 @@ static int lcp_reqci(fsm *f,
|
|||||||
ho->neg_mru = 1; /* Remember he sent MRU */
|
ho->neg_mru = 1; /* Remember he sent MRU */
|
||||||
ho->mru = cishort; /* And remember value */
|
ho->mru = cishort; /* And remember value */
|
||||||
#if TRACELCP > 0
|
#if TRACELCP > 0
|
||||||
sprintf(&traceBuf[traceNdx], " MRU %d", cishort);
|
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " MRU %d", cishort);
|
||||||
traceNdx = strlen(traceBuf);
|
traceNdx = strlen(traceBuf);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
@@ -1268,7 +1268,7 @@ static int lcp_reqci(fsm *f,
|
|||||||
ho->neg_asyncmap = 1;
|
ho->neg_asyncmap = 1;
|
||||||
ho->asyncmap = cilong;
|
ho->asyncmap = cilong;
|
||||||
#if TRACELCP > 0
|
#if TRACELCP > 0
|
||||||
sprintf(&traceBuf[traceNdx], " ASYNCMAP=%lX", cilong);
|
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " ASYNCMAP=%lX", cilong);
|
||||||
traceNdx = strlen(traceBuf);
|
traceNdx = strlen(traceBuf);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
@@ -1320,7 +1320,7 @@ static int lcp_reqci(fsm *f,
|
|||||||
}
|
}
|
||||||
ho->neg_upap = 1;
|
ho->neg_upap = 1;
|
||||||
#if TRACELCP > 0
|
#if TRACELCP > 0
|
||||||
sprintf(&traceBuf[traceNdx], " PAP (%X)", cishort);
|
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " PAP (%X)", cishort);
|
||||||
traceNdx = strlen(traceBuf);
|
traceNdx = strlen(traceBuf);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
@@ -1358,7 +1358,7 @@ static int lcp_reqci(fsm *f,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if TRACELCP > 0
|
#if TRACELCP > 0
|
||||||
sprintf(&traceBuf[traceNdx], " CHAP %X,%d", cishort, cichar);
|
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CHAP %X,%d", cishort, cichar);
|
||||||
traceNdx = strlen(traceBuf);
|
traceNdx = strlen(traceBuf);
|
||||||
#endif
|
#endif
|
||||||
ho->chap_mdtype = cichar; /* save md type */
|
ho->chap_mdtype = cichar; /* save md type */
|
||||||
@@ -1390,7 +1390,7 @@ static int lcp_reqci(fsm *f,
|
|||||||
GETSHORT(cishort, p);
|
GETSHORT(cishort, p);
|
||||||
GETLONG(cilong, p);
|
GETLONG(cilong, p);
|
||||||
#if TRACELCP > 0
|
#if TRACELCP > 0
|
||||||
sprintf(&traceBuf[traceNdx], " QUALITY (%x %x)", cishort, (unsigned int) cilong);
|
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " QUALITY (%x %x)", cishort, (unsigned int) cilong);
|
||||||
traceNdx = strlen(traceBuf);
|
traceNdx = strlen(traceBuf);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1422,7 +1422,7 @@ static int lcp_reqci(fsm *f,
|
|||||||
}
|
}
|
||||||
GETLONG(cilong, p);
|
GETLONG(cilong, p);
|
||||||
#if TRACELCP > 0
|
#if TRACELCP > 0
|
||||||
sprintf(&traceBuf[traceNdx], " MAGICNUMBER (%lX)", cilong);
|
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " MAGICNUMBER (%lX)", cilong);
|
||||||
traceNdx = strlen(traceBuf);
|
traceNdx = strlen(traceBuf);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1445,7 +1445,7 @@ static int lcp_reqci(fsm *f,
|
|||||||
|
|
||||||
case CI_PCOMPRESSION:
|
case CI_PCOMPRESSION:
|
||||||
#if TRACELCP > 0
|
#if TRACELCP > 0
|
||||||
sprintf(&traceBuf[traceNdx], " PCOMPRESSION");
|
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " PCOMPRESSION");
|
||||||
traceNdx = strlen(traceBuf);
|
traceNdx = strlen(traceBuf);
|
||||||
#endif
|
#endif
|
||||||
if (!ao->neg_pcompression ||
|
if (!ao->neg_pcompression ||
|
||||||
@@ -1458,7 +1458,7 @@ static int lcp_reqci(fsm *f,
|
|||||||
|
|
||||||
case CI_ACCOMPRESSION:
|
case CI_ACCOMPRESSION:
|
||||||
#if TRACELCP > 0
|
#if TRACELCP > 0
|
||||||
sprintf(&traceBuf[traceNdx], " ACCOMPRESSION");
|
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " ACCOMPRESSION");
|
||||||
traceNdx = strlen(traceBuf);
|
traceNdx = strlen(traceBuf);
|
||||||
#endif
|
#endif
|
||||||
if (!ao->neg_accompression ||
|
if (!ao->neg_accompression ||
|
||||||
@@ -1471,7 +1471,7 @@ static int lcp_reqci(fsm *f,
|
|||||||
|
|
||||||
case CI_MRRU:
|
case CI_MRRU:
|
||||||
#if TRACELCP > 0
|
#if TRACELCP > 0
|
||||||
sprintf(&traceBuf[traceNdx], " CI_MRRU");
|
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_MRRU");
|
||||||
traceNdx = strlen(traceBuf);
|
traceNdx = strlen(traceBuf);
|
||||||
#endif
|
#endif
|
||||||
orc = CONFREJ;
|
orc = CONFREJ;
|
||||||
@@ -1479,7 +1479,7 @@ static int lcp_reqci(fsm *f,
|
|||||||
|
|
||||||
case CI_SSNHF:
|
case CI_SSNHF:
|
||||||
#if TRACELCP > 0
|
#if TRACELCP > 0
|
||||||
sprintf(&traceBuf[traceNdx], " CI_SSNHF");
|
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_SSNHF");
|
||||||
traceNdx = strlen(traceBuf);
|
traceNdx = strlen(traceBuf);
|
||||||
#endif
|
#endif
|
||||||
orc = CONFREJ;
|
orc = CONFREJ;
|
||||||
@@ -1487,7 +1487,7 @@ static int lcp_reqci(fsm *f,
|
|||||||
|
|
||||||
case CI_EPDISC:
|
case CI_EPDISC:
|
||||||
#if TRACELCP > 0
|
#if TRACELCP > 0
|
||||||
sprintf(&traceBuf[traceNdx], " CI_EPDISC");
|
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_EPDISC");
|
||||||
traceNdx = strlen(traceBuf);
|
traceNdx = strlen(traceBuf);
|
||||||
#endif
|
#endif
|
||||||
orc = CONFREJ;
|
orc = CONFREJ;
|
||||||
@@ -1495,7 +1495,7 @@ static int lcp_reqci(fsm *f,
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
#if TRACELCP
|
#if TRACELCP
|
||||||
sprintf(&traceBuf[traceNdx], " unknown %d", citype);
|
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " unknown %d", citype);
|
||||||
traceNdx = strlen(traceBuf);
|
traceNdx = strlen(traceBuf);
|
||||||
#endif
|
#endif
|
||||||
orc = CONFREJ;
|
orc = CONFREJ;
|
||||||
|
|||||||
@@ -1236,7 +1236,7 @@ static void pppMain(void *arg)
|
|||||||
pppInProc(pd, p->payload, c);
|
pppInProc(pd, p->payload, c);
|
||||||
} else {
|
} else {
|
||||||
PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d sio_read len=%d returned %d\n", pd, p->len, c));
|
PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d sio_read len=%d returned %d\n", pd, p->len, c));
|
||||||
sys_msleep(250); /* give other tasks a chance to run */
|
sys_msleep(1); /* give other tasks a chance to run */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,9 +32,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is an arch independent SLIP netif. The specific serial hooks must be provided
|
* This is an arch independent SLIP netif. The specific serial hooks must be
|
||||||
* by another file.They are sio_open, sio_recv and sio_send
|
* provided by another file. They are sio_open, sio_recv and sio_send
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "netif/slipif.h"
|
#include "netif/slipif.h"
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
@@ -55,32 +55,32 @@
|
|||||||
* Send a pbuf doing the necessary SLIP encapsulation
|
* Send a pbuf doing the necessary SLIP encapsulation
|
||||||
*
|
*
|
||||||
* Uses the serial layer's sio_send()
|
* Uses the serial layer's sio_send()
|
||||||
*/
|
*/
|
||||||
err_t
|
err_t
|
||||||
slipif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
|
slipif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
|
||||||
{
|
{
|
||||||
struct pbuf *q;
|
struct pbuf *q;
|
||||||
int i;
|
u16_t i;
|
||||||
u8_t c;
|
u8_t c;
|
||||||
|
|
||||||
/* Send pbuf out on the serial I/O device. */
|
/* Send pbuf out on the serial I/O device. */
|
||||||
sio_send(SLIP_END, netif->state);
|
sio_send(SLIP_END, netif->state);
|
||||||
|
|
||||||
for(q = p; q != NULL; q = q->next) {
|
for (q = p; q != NULL; q = q->next) {
|
||||||
for(i = 0; i < q->len; i++) {
|
for (i = 0; i < q->len; i++) {
|
||||||
c = ((u8_t *)q->payload)[i];
|
c = ((u8_t *)q->payload)[i];
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case SLIP_END:
|
case SLIP_END:
|
||||||
sio_send(SLIP_ESC, netif->state);
|
sio_send(SLIP_ESC, netif->state);
|
||||||
sio_send(SLIP_ESC_END, netif->state);
|
sio_send(SLIP_ESC_END, netif->state);
|
||||||
break;
|
break;
|
||||||
case SLIP_ESC:
|
case SLIP_ESC:
|
||||||
sio_send(SLIP_ESC, netif->state);
|
sio_send(SLIP_ESC, netif->state);
|
||||||
sio_send(SLIP_ESC_ESC, netif->state);
|
sio_send(SLIP_ESC_ESC, netif->state);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sio_send(c, netif->state);
|
sio_send(c, netif->state);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,14 +94,14 @@ slipif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
|
|||||||
* Poll the serial layer by calling sio_recv()
|
* Poll the serial layer by calling sio_recv()
|
||||||
*
|
*
|
||||||
* @return The IP packet when SLIP_END is received
|
* @return The IP packet when SLIP_END is received
|
||||||
*/
|
*/
|
||||||
static struct pbuf *
|
static struct pbuf *
|
||||||
slipif_input( struct netif * netif )
|
slipif_input(struct netif *netif)
|
||||||
{
|
{
|
||||||
u8_t c;
|
u8_t c;
|
||||||
struct pbuf *p, *q;
|
struct pbuf *p, *q;
|
||||||
int recved;
|
u16_t recved;
|
||||||
int i;
|
u16_t i;
|
||||||
|
|
||||||
q = p = NULL;
|
q = p = NULL;
|
||||||
recved = i = 0;
|
recved = i = 0;
|
||||||
@@ -112,13 +112,13 @@ slipif_input( struct netif * netif )
|
|||||||
switch (c) {
|
switch (c) {
|
||||||
case SLIP_END:
|
case SLIP_END:
|
||||||
if (recved > 0) {
|
if (recved > 0) {
|
||||||
/* Received whole packet. */
|
/* Received whole packet. */
|
||||||
pbuf_realloc(q, recved);
|
pbuf_realloc(q, recved);
|
||||||
|
|
||||||
LINK_STATS_INC(link.recv);
|
LINK_STATS_INC(link.recv);
|
||||||
|
|
||||||
LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet\n"));
|
LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet\n"));
|
||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -126,51 +126,54 @@ slipif_input( struct netif * netif )
|
|||||||
c = sio_recv(netif->state);
|
c = sio_recv(netif->state);
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case SLIP_ESC_END:
|
case SLIP_ESC_END:
|
||||||
c = SLIP_END;
|
c = SLIP_END;
|
||||||
break;
|
break;
|
||||||
case SLIP_ESC_ESC:
|
case SLIP_ESC_ESC:
|
||||||
c = SLIP_ESC;
|
c = SLIP_ESC;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n"));
|
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n"));
|
||||||
p = pbuf_alloc(PBUF_LINK, PBUF_POOL_BUFSIZE, PBUF_POOL);
|
p = pbuf_alloc(PBUF_LINK, PBUF_POOL_BUFSIZE, PBUF_POOL);
|
||||||
|
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
LINK_STATS_INC(link.drop);
|
LINK_STATS_INC(link.drop);
|
||||||
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n"));
|
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (q != NULL) {
|
if (q != NULL) {
|
||||||
pbuf_cat(q, p);
|
pbuf_cat(q, p);
|
||||||
} else {
|
} else {
|
||||||
q = p;
|
q = p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (p != NULL && recved < MAX_SIZE) {
|
if (p != NULL && recved < MAX_SIZE) {
|
||||||
((u8_t *)p->payload)[i] = c;
|
((u8_t *)p->payload)[i] = c;
|
||||||
recved++;
|
recved++;
|
||||||
i++;
|
i++;
|
||||||
if (i >= p->len) {
|
if (i >= p->len) {
|
||||||
i = 0;
|
i = 0;
|
||||||
p = NULL;
|
if (p->next != NULL && p->next->len > 0)
|
||||||
}
|
p = p->next;
|
||||||
|
else
|
||||||
|
p = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The SLIP input thread
|
* The SLIP input thread.
|
||||||
*
|
*
|
||||||
* Feed the IP layer with incoming packets
|
* Feed the IP layer with incoming packets
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
slipif_loop(void *nf)
|
slipif_loop(void *nf)
|
||||||
{
|
{
|
||||||
@@ -188,22 +191,22 @@ slipif_loop(void *nf)
|
|||||||
*
|
*
|
||||||
* Call the arch specific sio_open and remember
|
* Call the arch specific sio_open and remember
|
||||||
* the opened device in the state field of the netif.
|
* the opened device in the state field of the netif.
|
||||||
*/
|
*/
|
||||||
err_t
|
err_t
|
||||||
slipif_init(struct netif *netif)
|
slipif_init(struct netif *netif)
|
||||||
{
|
{
|
||||||
|
|
||||||
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%x\n", (int)netif->num));
|
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%"U16_F"\n", (u16_t)netif->num));
|
||||||
|
|
||||||
netif->name[0] = 's';
|
netif->name[0] = 's';
|
||||||
netif->name[1] = 'l';
|
netif->name[1] = 'l';
|
||||||
netif->output = slipif_output;
|
netif->output = slipif_output;
|
||||||
netif->mtu = 1500;
|
netif->mtu = 1500;
|
||||||
netif->flags = NETIF_FLAG_POINTTOPOINT;
|
netif->flags = NETIF_FLAG_POINTTOPOINT;
|
||||||
|
|
||||||
netif->state = sio_open(netif->num);
|
netif->state = sio_open(netif->num);
|
||||||
if (!netif->state)
|
if (!netif->state)
|
||||||
return ERR_IF;
|
return ERR_IF;
|
||||||
|
|
||||||
sys_thread_new(slipif_loop, netif, SLIPIF_THREAD_PRIO);
|
sys_thread_new(slipif_loop, netif, SLIPIF_THREAD_PRIO);
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
|
|||||||
Reference in New Issue
Block a user