summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorbernard.xiong <[email protected]>2010-01-13 03:22:23 +0000
committerbernard.xiong <[email protected]>2010-01-13 03:22:23 +0000
commita27f7c67bd51c93dfed233adc371d6f178ff7b73 (patch)
tree746823bd3b601ce9fe738a7b97875cd0ad7481d9 /net
parentce10330d8044964445c9bb0876dd8553a934da2c (diff)
update lwip to 1.3.2
git-svn-id: https://rt-thread.googlecode.com/svn/trunk@297 bbd45198-f89e-11dd-88c7-29a3b14d5316
Diffstat (limited to 'net')
-rw-r--r--net/lwip/CHANGELOG171
-rw-r--r--net/lwip/README2
-rw-r--r--net/lwip/SConscript2
-rw-r--r--net/lwip/src/api/api_lib.c3
-rw-r--r--net/lwip/src/api/api_msg.c13
-rw-r--r--net/lwip/src/api/netbuf.c5
-rw-r--r--net/lwip/src/api/netdb.c40
-rw-r--r--net/lwip/src/api/netifapi.c36
-rw-r--r--net/lwip/src/api/sockets.c85
-rw-r--r--net/lwip/src/core/dhcp.c263
-rw-r--r--net/lwip/src/core/dns.c2
-rw-r--r--net/lwip/src/core/init.c5
-rw-r--r--net/lwip/src/core/ipv4/autoip.c106
-rw-r--r--net/lwip/src/core/ipv4/ip.c102
-rw-r--r--net/lwip/src/core/mem.c8
-rw-r--r--net/lwip/src/core/memp.c59
-rw-r--r--net/lwip/src/core/memp_tiny.c116
-rw-r--r--net/lwip/src/core/netif.c48
-rw-r--r--net/lwip/src/core/pbuf.c118
-rw-r--r--net/lwip/src/core/raw.c10
-rw-r--r--net/lwip/src/core/snmp/mib2.c52
-rw-r--r--net/lwip/src/core/snmp/mib_structs.c2
-rw-r--r--net/lwip/src/core/sys.c14
-rw-r--r--net/lwip/src/core/tcp.c85
-rw-r--r--net/lwip/src/core/tcp_in.c335
-rw-r--r--net/lwip/src/core/tcp_out.c205
-rw-r--r--net/lwip/src/core/udp.c25
-rw-r--r--net/lwip/src/include/ipv4/lwip/autoip.h11
-rw-r--r--net/lwip/src/include/ipv4/lwip/icmp.h19
-rw-r--r--net/lwip/src/include/ipv4/lwip/ip.h15
-rw-r--r--net/lwip/src/include/ipv4/lwip/ip_addr.h5
-rw-r--r--net/lwip/src/include/lwip/api_msg.h2
-rw-r--r--net/lwip/src/include/lwip/debug.h5
-rw-r--r--net/lwip/src/include/lwip/dhcp.h14
-rw-r--r--net/lwip/src/include/lwip/init.h2
-rw-r--r--net/lwip/src/include/lwip/memp.h5
-rw-r--r--net/lwip/src/include/lwip/netbuf.h9
-rw-r--r--net/lwip/src/include/lwip/netdb.h2
-rw-r--r--net/lwip/src/include/lwip/netif.h4
-rw-r--r--net/lwip/src/include/lwip/netifapi.h5
-rw-r--r--net/lwip/src/include/lwip/opt.h42
-rw-r--r--net/lwip/src/include/lwip/sio.h72
-rw-r--r--net/lwip/src/include/lwip/tcp.h28
-rw-r--r--net/lwip/src/include/lwip/udp.h3
-rw-r--r--net/lwip/src/include/netif/etharp.h38
-rw-r--r--net/lwip/src/include/netif/slipif.h1
-rw-r--r--net/lwip/src/lwipopts.h8
-rw-r--r--net/lwip/src/netif/FILES4
-rw-r--r--net/lwip/src/netif/etharp.c87
-rw-r--r--net/lwip/src/netif/ethernetif.c26
-rw-r--r--net/lwip/src/netif/ppp/auth.c2
-rw-r--r--net/lwip/src/netif/ppp/chap.c1
-rw-r--r--net/lwip/src/netif/ppp/chpms.c3
-rw-r--r--net/lwip/src/netif/ppp/fsm.c4
-rw-r--r--net/lwip/src/netif/ppp/ipcp.c15
-rw-r--r--net/lwip/src/netif/ppp/md5.c2
-rw-r--r--net/lwip/src/netif/ppp/pap.c3
-rw-r--r--net/lwip/src/netif/ppp/ppp.c66
-rw-r--r--net/lwip/src/netif/ppp/ppp.h4
-rw-r--r--net/lwip/src/netif/ppp/ppp_oe.c6
-rw-r--r--net/lwip/src/netif/ppp/randm.c1
-rw-r--r--net/lwip/src/netif/ppp/vj.c2
-rw-r--r--net/lwip/src/netif/slipif.c244
-rw-r--r--net/lwip/test/unit/lwip_check.h37
-rw-r--r--net/lwip/test/unit/lwip_unittests.c42
-rw-r--r--net/lwip/test/unit/tcp/tcp_helper.c196
-rw-r--r--net/lwip/test/unit/tcp/tcp_helper.h36
-rw-r--r--net/lwip/test/unit/tcp/test_tcp.c104
-rw-r--r--net/lwip/test/unit/tcp/test_tcp.h8
-rw-r--r--net/lwip/test/unit/tcp/test_tcp_oos.c433
-rw-r--r--net/lwip/test/unit/tcp/test_tcp_oos.h8
-rw-r--r--net/lwip/test/unit/udp/test_udp.c80
-rw-r--r--net/lwip/test/unit/udp/test_udp.h8
73 files changed, 2661 insertions, 963 deletions
diff --git a/net/lwip/CHANGELOG b/net/lwip/CHANGELOG
index a45765010d..860d1c470e 100644
--- a/net/lwip/CHANGELOG
+++ b/net/lwip/CHANGELOG
@@ -19,8 +19,179 @@ HISTORY
++ New features:
+
+ ++ Bugfixes:
+
+
+(STABLE-1.3.2)
+
+ ++ New features:
+
+ 2009-10-27 Simon Goldschmidt/Stephan Lesage
+ * netifapi.c/.h: Added netifapi_netif_set_addr()
+
+ 2009-10-07 Simon Goldschmidt/Fabian Koch
+ * api_msg.c, netbuf.c/.h, opt.h: patch #6888: Patch for UDP Netbufs to
+ support dest-addr and dest-port (optional: LWIP_NETBUF_RECVINFO)
+
+ 2009-08-26 Simon Goldschmidt/Simon Kallweit
+ * slipif.c/.h: bug #26397: SLIP polling support
+
+ 2009-08-25 Simon Goldschmidt
+ * opt.h, etharp.h/.c: task #9033: Support IEEE 802.1q tagged frame (VLAN),
+ New configuration options ETHARP_SUPPORT_VLAN and ETHARP_VLAN_CHECK.
+
+ 2009-08-25 Simon Goldschmidt
+ * ip_addr.h, netdb.c: patch #6900: added define ip_ntoa(struct ip_addr*)
+
+ 2009-08-24 Jakob Stoklund Olesen
+ * autoip.c, dhcp.c, netif.c: patch #6725: Teach AutoIP and DHCP to respond
+ to netif_set_link_up().
+
+ 2009-08-23 Simon Goldschmidt
+ * tcp.h/.c: Added function tcp_debug_state_str() to convert a tcp state
+ to a human-readable string.
+
++ Bugfixes:
+ 2009-12-24: Kieran Mansley
+ * tcp_in.c Apply patches from Oleg Tyshev to improve OOS processing
+ (BUG#28241)
+
+ 2009-12-06: Simon Goldschmidt
+ * ppp.h/.c: Fixed bug #27079 (Yet another leak in PPP): outpacket_buf can
+ be statically allocated (like in ucip)
+
+ 2009-12-04: Simon Goldschmidt (patch by Ioardan Neshev)
+ * pap.c: patch #6969: PPP: missing PAP authentication UNTIMEOUT
+
+ 2009-12-03: Simon Goldschmidt
+ * tcp.h, tcp_in.c, tcp_out.c: Fixed bug #28106: dup ack for fast retransmit
+ could have non-zero length
+
+ 2009-12-02: Simon Goldschmidt
+ * tcp_in.c: Fixed bug #27904: TCP sends too many ACKs: delay resetting
+ tcp_input_pcb until after calling the pcb's callbacks
+
+ 2009-11-29: Simon Goldschmidt
+ * tcp_in.c: Fixed bug #28054: Two segments with FIN flag on the out-of-
+ sequence queue, also fixed PBUF_POOL leak in the out-of-sequence code
+
+ 2009-11-29: Simon Goldschmidt
+ * pbuf.c: Fixed bug #28064: pbuf_alloc(PBUF_POOL) is not thread-safe by
+ queueing a call into tcpip_thread to free ooseq-bufs if the pool is empty
+
+ 2009-11-26: Simon Goldschmidt
+ * tcp.h: Fixed bug #28098: Nagle can prevent fast retransmit from sending
+ segment
+
+ 2009-11-26: Simon Goldschmidt
+ * tcp.h, sockets.c: Fixed bug #28099: API required to disable Nagle
+ algorithm at PCB level
+
+ 2009-11-22: Simon Goldschmidt
+ * tcp_out.c: Fixed bug #27905: FIN isn't combined with data on unsent
+
+ 2009-11-22: Simon Goldschmidt (suggested by Bill Auerbach)
+ * tcp.c: tcp_alloc: prevent increasing stats.err for MEMP_TCP_PCB when
+ reusing time-wait pcb
+
+ 2009-11-20: Simon Goldschmidt (patch by Albert Bartel)
+ * sockets.c: Fixed bug #28062: Data received directly after accepting
+ does not wake up select
+
+ 2009-11-11: Simon Goldschmidt
+ * netdb.h: Fixed bug #27994: incorrect define for freeaddrinfo(addrinfo)
+
+ 2009-10-30: Simon Goldschmidt
+ * opt.h: Increased default value for TCP_MSS to 536, updated default
+ value for TCP_WND to 4*TCP_MSS to keep delayed ACK working.
+
+ 2009-10-28: Kieran Mansley
+ * tcp_in.c, tcp_out.c, tcp.h: re-work the fast retransmission code
+ to follow algorithm from TCP/IP Illustrated
+
+ 2009-10-27: Kieran Mansley
+ * tcp_in.c: fix BUG#27445: grow cwnd with every duplicate ACK
+
+ 2009-10-25: Simon Goldschmidt
+ * tcp.h: bug-fix in the TCP_EVENT_RECV macro (has to call tcp_recved if
+ pcb->recv is NULL to keep rcv_wnd correct)
+
+ 2009-10-25: Simon Goldschmidt
+ * tcp_in.c: Fixed bug #26251: RST process in TIME_WAIT TCP state
+
+ 2009-10-23: Simon Goldschmidt (David Empson)
+ * tcp.c: Fixed bug #27783: Silly window avoidance for small window sizes
+
+ 2009-10-21: Simon Goldschmidt
+ * tcp_in.c: Fixed bug #27215: TCP sent() callback gives leading and
+ trailing 1 byte len (SYN/FIN)
+
+ 2009-10-21: Simon Goldschmidt
+ * tcp_out.c: Fixed bug #27315: zero window probe and FIN
+
+ 2009-10-19: Simon Goldschmidt
+ * dhcp.c/.h: Minor code simplification (don't store received pbuf, change
+ conditional code to assert where applicable), check pbuf length before
+ testing for valid reply
+
+ 2009-10-19: Simon Goldschmidt
+ * dhcp.c: Removed most calls to udp_connect since they aren't necessary
+ when using udp_sendto_if() - always stay connected to IP_ADDR_ANY.
+
+ 2009-10-16: Simon Goldschmidt
+ * ip.c: Fixed bug #27390: Source IP check in ip_input() causes it to drop
+ valid DHCP packets -> allow 0.0.0.0 as source address when LWIP_DHCP is
+ enabled
+
+ 2009-10-15: Simon Goldschmidt (Oleg Tyshev)
+ * tcp_in.c: Fixed bug #27329: dupacks by unidirectional data transmit
+
+ 2009-10-15: Simon Goldschmidt
+ * api_lib.c: Fixed bug #27709: conn->err race condition on netconn_recv()
+ timeout
+
+ 2009-10-15: Simon Goldschmidt
+ * autoip.c: Fixed bug #27704: autoip starts with wrong address
+ LWIP_AUTOIP_CREATE_SEED_ADDR() returned address in host byte order instead
+ of network byte order
+
+ 2009-10-11 Simon Goldschmidt (J�rg Kesten)
+ * tcp_out.c: Fixed bug #27504: tcp_enqueue wrongly concatenates segments
+ which are not consecutive when retransmitting unacked segments
+
+ 2009-10-09 Simon Goldschmidt
+ * opt.h: Fixed default values of some stats to only be enabled if used
+ Fixes bug #27338: sys_stats is defined when NO_SYS = 1
+
+ 2009-08-30 Simon Goldschmidt
+ * ip.c: Fixed bug bug #27345: "ip_frag() does not use the LWIP_NETIF_LOOPBACK
+ function" by checking for loopback before calling ip_frag
+
+ 2009-08-25 Simon Goldschmidt
+ * dhcp.c: fixed invalid dependency to etharp_query if DHCP_DOES_ARP_CHECK==0
+
+ 2009-08-23 Simon Goldschmidt
+ * ppp.c: bug #27078: Possible memory leak in pppInit()
+
+ 2009-08-23 Simon Goldschmidt
+ * netdb.c, dns.c: bug #26657: DNS, if host name is "localhost", result
+ is error.
+
+ 2009-08-23 Simon Goldschmidt
+ * opt.h, init.c: bug #26649: TCP fails when TCP_MSS > TCP_SND_BUF
+ Fixed wrong parenthesis, added check in init.c
+
+ 2009-08-23 Simon Goldschmidt
+ * ppp.c: bug #27266: wait-state debug message in pppMain occurs every ms
+
+ 2009-08-23 Simon Goldschmidt
+ * many ppp files: bug #27267: Added include to string.h where needed
+
+ 2009-08-23 Simon Goldschmidt
+ * tcp.h: patch #6843: tcp.h macro optimization patch (for little endian)
+
(STABLE-1.3.1)
diff --git a/net/lwip/README b/net/lwip/README
index 8dda4b468a..a62cc4f38c 100644
--- a/net/lwip/README
+++ b/net/lwip/README
@@ -72,7 +72,7 @@ current CVS sources and is available from this web page:
http://www.nongnu.org/lwip/
There is now a constantly growin wiki about lwIP at
- http://lwip.scribblewiki.com/
+ http://lwip.wikia.com/wiki/LwIP_Wiki
Also, there are mailing lists you can subscribe at
http://savannah.nongnu.org/mail/?group=lwip
diff --git a/net/lwip/SConscript b/net/lwip/SConscript
index fb10db37f2..de08af6688 100644
--- a/net/lwip/SConscript
+++ b/net/lwip/SConscript
@@ -16,7 +16,7 @@ src/arch/sys_arch_init.c
src/core/dhcp.c
src/core/dns.c
src/core/init.c
-src/core/memp_tiny.c
+src/core/memp.c
src/core/netif.c
src/core/pbuf.c
src/core/raw.c
diff --git a/net/lwip/src/api/api_lib.c b/net/lwip/src/api/api_lib.c
index 86df911ea3..195a9a525e 100644
--- a/net/lwip/src/api/api_lib.c
+++ b/net/lwip/src/api/api_lib.c
@@ -327,8 +327,9 @@ netconn_recv(struct netconn *conn)
#if LWIP_SO_RCVTIMEO
if (sys_arch_mbox_fetch(conn->recvmbox, (void *)&p, conn->recv_timeout)==SYS_ARCH_TIMEOUT) {
+ memp_free(MEMP_NETBUF, buf);
conn->err = ERR_TIMEOUT;
- p = NULL;
+ return NULL;
}
#else
sys_arch_mbox_fetch(conn->recvmbox, (void *)&p, 0);
diff --git a/net/lwip/src/api/api_msg.c b/net/lwip/src/api/api_msg.c
index 28d1010193..46c9abf297 100644
--- a/net/lwip/src/api/api_msg.c
+++ b/net/lwip/src/api/api_msg.c
@@ -168,6 +168,15 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
buf->ptr = p;
buf->addr = addr;
buf->port = port;
+#if LWIP_NETBUF_RECVINFO
+ {
+ const struct ip_hdr* iphdr = ip_current_header();
+ /* get the UDP header - always in the first pbuf, ensured by udp_input */
+ const struct udp_hdr* udphdr = (void*)(((char*)iphdr) + IPH_LEN(iphdr));
+ buf->toaddr = (struct ip_addr*)&iphdr->dest;
+ buf->toport = udphdr->dest;
+ }
+#endif /* LWIP_NETBUF_RECVINFO */
}
if (sys_mbox_trypost(conn->recvmbox, buf) != ERR_OK) {
@@ -807,6 +816,8 @@ do_connect(struct api_msg_msg *msg)
break;
#endif /* LWIP_TCP */
default:
+ LWIP_ERROR("Invalid netconn type", 0, do{ msg->conn->err = ERR_VAL;
+ sys_sem_signal(msg->conn->op_completed); }while(0));
break;
}
}
@@ -1149,7 +1160,7 @@ do_close(struct api_msg_msg *msg)
#endif /* LWIP_TCP */
{
msg->conn->err = ERR_VAL;
- TCPIP_APIMSG_ACK(msg);
+ sys_sem_signal(msg->conn->op_completed);
}
}
diff --git a/net/lwip/src/api/netbuf.c b/net/lwip/src/api/netbuf.c
index af44eefc7e..57efc4f9f8 100644
--- a/net/lwip/src/api/netbuf.c
+++ b/net/lwip/src/api/netbuf.c
@@ -62,6 +62,11 @@ netbuf *netbuf_new(void)
buf->p = NULL;
buf->ptr = NULL;
buf->addr = NULL;
+ buf->port = 0;
+#if LWIP_NETBUF_RECVINFO
+ buf->toaddr = NULL;
+ buf->toport = 0;
+#endif /* LWIP_NETBUF_RECVINFO */
return buf;
} else {
return NULL;
diff --git a/net/lwip/src/api/netdb.c b/net/lwip/src/api/netdb.c
index 8aa237f4c1..69a331be7b 100644
--- a/net/lwip/src/api/netdb.c
+++ b/net/lwip/src/api/netdb.c
@@ -116,7 +116,7 @@ lwip_gethostbyname(const char *name)
u8_t idx;
for ( idx=0; s_hostent.h_aliases[idx]; idx++) {
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases[%i]-> == %p\n", idx, s_hostent.h_aliases[idx]));
- LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases[%i]-> == %s\n", idx, s_hostent.h_aliases[idx]));
+ LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases[%i]-> == %s\n", idx, s_hostent.h_aliases[idx]));
}
}
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addrtype == %d\n", s_hostent.h_addrtype));
@@ -126,7 +126,7 @@ lwip_gethostbyname(const char *name)
u8_t idx;
for ( idx=0; s_hostent.h_addr_list[idx]; idx++) {
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i] == %p\n", idx, s_hostent.h_addr_list[idx]));
- LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, inet_ntoa(*((struct in_addr*)(s_hostent.h_addr_list[idx])))));
+ LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, ip_ntoa(s_hostent.h_addr_list[idx])));
}
}
#endif /* DNS_DEBUG */
@@ -234,12 +234,6 @@ lwip_freeaddrinfo(struct addrinfo *ai)
struct addrinfo *next;
while (ai != NULL) {
- if (ai->ai_addr != NULL) {
- mem_free(ai->ai_addr);
- }
- if (ai->ai_canonname != NULL) {
- mem_free(ai->ai_canonname);
- }
next = ai->ai_next;
mem_free(ai);
ai = next;
@@ -274,6 +268,8 @@ lwip_getaddrinfo(const char *nodename, const char *servname,
struct addrinfo *ai;
struct sockaddr_in *sa = NULL;
int port_nr = 0;
+ size_t total_size;
+ size_t namelen = 0;
if (res == NULL) {
return EAI_FAIL;
@@ -300,19 +296,21 @@ lwip_getaddrinfo(const char *nodename, const char *servname,
}
} else {
/* service location specified, use loopback address */
- addr.addr = INADDR_LOOPBACK;
+ addr.addr = htonl(INADDR_LOOPBACK);
}
- ai = mem_malloc(sizeof(struct addrinfo));
- if (ai == NULL) {
- goto memerr;
+ total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_in);
+ if (nodename != NULL) {
+ namelen = strlen(nodename);
+ LWIP_ASSERT("namelen is too long", (namelen + 1) <= (mem_size_t)-1);
+ total_size += namelen + 1;
}
- memset(ai, 0, sizeof(struct addrinfo));
- sa = mem_malloc(sizeof(struct sockaddr_in));
- if (sa == NULL) {
+ ai = mem_malloc(total_size);
+ if (ai == NULL) {
goto memerr;
}
- memset(sa, 0, sizeof(struct sockaddr_in));
+ memset(ai, 0, total_size);
+ sa = (struct sockaddr_in*)((u8_t*)ai + sizeof(struct addrinfo));
/* set up sockaddr */
sa->sin_addr.s_addr = addr.addr;
sa->sin_family = AF_INET;
@@ -328,12 +326,7 @@ lwip_getaddrinfo(const char *nodename, const char *servname,
}
if (nodename != NULL) {
/* copy nodename to canonname if specified */
- size_t namelen = strlen(nodename);
- LWIP_ASSERT("namelen is too long", (namelen + 1) <= (mem_size_t)-1);
- ai->ai_canonname = mem_malloc((mem_size_t)(namelen + 1));
- if (ai->ai_canonname == NULL) {
- goto memerr;
- }
+ ai->ai_canonname = ((char*)ai + sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
MEMCPY(ai->ai_canonname, nodename, namelen);
ai->ai_canonname[namelen] = 0;
}
@@ -347,9 +340,6 @@ memerr:
if (ai != NULL) {
mem_free(ai);
}
- if (sa != NULL) {
- mem_free(sa);
- }
return EAI_MEMORY;
}
diff --git a/net/lwip/src/api/netifapi.c b/net/lwip/src/api/netifapi.c
index 491837378d..57089864ae 100644
--- a/net/lwip/src/api/netifapi.c
+++ b/net/lwip/src/api/netifapi.c
@@ -59,6 +59,20 @@ do_netifapi_netif_add( struct netifapi_msg_msg *msg)
}
/**
+ * Call netif_set_addr() inside the tcpip_thread context.
+ */
+void
+do_netifapi_netif_set_addr( struct netifapi_msg_msg *msg)
+{
+ netif_set_addr( msg->netif,
+ msg->msg.add.ipaddr,
+ msg->msg.add.netmask,
+ msg->msg.add.gw);
+ msg->err = ERR_OK;
+ TCPIP_NETIFAPI_ACK(msg);
+}
+
+/**
* Call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) inside the
* tcpip_thread context.
*/
@@ -104,6 +118,28 @@ netifapi_netif_add(struct netif *netif,
}
/**
+ * Call netif_set_addr() in a thread-safe way by running that function inside the
+ * tcpip_thread context.
+ *
+ * @note for params @see netif_set_addr()
+ */
+err_t
+netifapi_netif_set_addr(struct netif *netif,
+ struct ip_addr *ipaddr,
+ struct ip_addr *netmask,
+ struct ip_addr *gw)
+{
+ struct netifapi_msg msg;
+ msg.function = do_netifapi_netif_set_addr;
+ msg.msg.netif = netif;
+ msg.msg.msg.add.ipaddr = ipaddr;
+ msg.msg.msg.add.netmask = netmask;
+ msg.msg.msg.add.gw = gw;
+ TCPIP_NETIFAPI(&msg);
+ return msg.msg.err;
+}
+
+/**
* call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) in a thread-safe
* way by running that function inside the tcpip_thread context.
*
diff --git a/net/lwip/src/api/sockets.c b/net/lwip/src/api/sockets.c
index c02e56ef16..36df4d8960 100644
--- a/net/lwip/src/api/sockets.c
+++ b/net/lwip/src/api/sockets.c
@@ -494,7 +494,7 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
buf = sock->lastdata;
} else {
/* If this is non-blocking call, then check first */
- if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK)) &&
+ if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK)) &&
(sock->rcvevent <= 0)) {
if (off > 0) {
/* already received data, return that */
@@ -546,9 +546,9 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
if (netconn_type(sock->conn) == NETCONN_TCP) {
LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen);
len -= copylen;
- if ( (len <= 0) ||
- (buf->p->flags & PBUF_FLAG_PUSH) ||
- (sock->rcvevent <= 0) ||
+ if ( (len <= 0) ||
+ (buf->p->flags & PBUF_FLAG_PUSH) ||
+ (sock->rcvevent <= 0) ||
((flags & MSG_PEEK)!=0)) {
done = 1;
}
@@ -702,16 +702,16 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
#if LWIP_TCPIP_CORE_LOCKING
/* Should only be consider like a sample or a simple way to experiment this option (no check of "to" field...) */
{ struct pbuf* p;
-
+
p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
if (p == NULL) {
err = ERR_MEM;
} else {
p->payload = (void*)data;
p->len = p->tot_len = short_size;
-
+
remote_addr.addr = ((const struct sockaddr_in *)to)->sin_addr.s_addr;
-
+
LOCK_TCPIP_CORE();
if (sock->conn->type==NETCONN_RAW) {
err = sock->conn->err = raw_sendto(sock->conn->pcb.raw, p, &remote_addr);
@@ -719,7 +719,7 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
err = sock->conn->err = udp_sendto(sock->conn->pcb.udp, p, &remote_addr, ntohs(((const struct sockaddr_in *)to)->sin_port));
}
UNLOCK_TCPIP_CORE();
-
+
pbuf_free(p);
}
}
@@ -845,11 +845,11 @@ lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
int i, nready = 0;
fd_set lreadset, lwriteset, lexceptset;
struct lwip_socket *p_sock;
-
+
FD_ZERO(&lreadset);
FD_ZERO(&lwriteset);
FD_ZERO(&lexceptset);
-
+
/* Go through each socket in each list to count number of sockets which
currently match */
for(i = 0; i < maxfdp1; i++) {
@@ -875,7 +875,7 @@ lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
*readset = lreadset;
*writeset = lwriteset;
FD_ZERO(exceptset);
-
+
return nready;
}
@@ -935,27 +935,27 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
FD_ZERO(writeset);
if (exceptset)
FD_ZERO(exceptset);
-
+
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n"));
set_errno(0);
-
+
return 0;
}
-
+
/* add our semaphore to list */
/* We don't actually need any dynamic memory. Our entry on the
* list is only valid while we are in this function, so it's ok
* to use local variables */
-
+
select_cb.sem = sys_sem_new(0);
/* Note that we are still protected */
/* Put this select_cb on top of list */
select_cb.next = select_cb_list;
select_cb_list = &select_cb;
-
+
/* Now we can safely unprotect */
sys_sem_signal(selectsem);
-
+
/* Now just wait to be woken */
if (timeout == 0)
/* Wait forever */
@@ -965,7 +965,7 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
if(msectimeout == 0)
msectimeout = 1;
}
-
+
if (sys_arch_timeouts() == NULL){
/* it's not a lwip thread, use os semaphore with timeout to handle it */
i = sys_arch_sem_wait(select_cb.sem, msectimeout);
@@ -976,7 +976,7 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
/* it's a lwip thread, use os semaphore with timeout to handle it */
i = sys_sem_wait_timeout(select_cb.sem, msectimeout);
}
-
+
/* Take us off the list */
sys_sem_wait(selectsem);
if (select_cb_list == &select_cb)
@@ -988,9 +988,9 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
break;
}
}
-
+
sys_sem_signal(selectsem);
-
+
sys_sem_free(select_cb.sem);
if (i == 0) {
/* Timeout */
@@ -1000,13 +1000,13 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
FD_ZERO(writeset);
if (exceptset)
FD_ZERO(exceptset);
-
+
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n"));
set_errno(0);
-
+
return 0;
}
-
+
if (readset)
lreadset = *readset;
else
@@ -1019,22 +1019,22 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
lexceptset = *exceptset;
else
FD_ZERO(&lexceptset);
-
+
/* See what's set */
nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset);
} else
sys_sem_signal(selectsem);
-
+
if (readset)
*readset = lreadset;
if (writeset)
*writeset = lwriteset;
if (exceptset)
*exceptset = lexceptset;
-
+
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready));
set_errno(0);
-
+
return nready;
}
@@ -1068,6 +1068,7 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
sys_sem_signal(socksem);
return;
}
+ s = conn->socket;
sys_sem_signal(socksem);
}
@@ -1205,11 +1206,11 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
/* Do length and type checks for the various options first, to keep it readable. */
switch (level) {
-
+
/* Level: SOL_SOCKET */
case SOL_SOCKET:
switch (optname) {
-
+
case SO_ACCEPTCONN:
case SO_BROADCAST:
/* UNIMPL case SO_DEBUG: */
@@ -1258,7 +1259,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
err = ENOPROTOOPT;
} /* switch (optname) */
break;
-
+
/* Level: IPPROTO_IP */
case IPPROTO_IP:
switch (optname) {
@@ -1290,7 +1291,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
err = ENOPROTOOPT;
} /* switch (optname) */
break;
-
+
#if LWIP_TCP
/* Level: IPPROTO_TCP */
case IPPROTO_TCP:
@@ -1298,7 +1299,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
err = EINVAL;
break;
}
-
+
/* If this is no TCP socket, ignore any options. */
if (sock->conn->type != NETCONN_TCP)
return 0;
@@ -1312,7 +1313,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
case TCP_KEEPCNT:
#endif /* LWIP_TCP_KEEPALIVE */
break;
-
+
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
s, optname));
@@ -1327,7 +1328,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
err = EINVAL;
break;
}
-
+
/* If this is no UDP lite socket, ignore any options. */
if (sock->conn->type != NETCONN_UDPLITE)
return 0;
@@ -1336,7 +1337,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
case UDPLITE_SEND_CSCOV:
case UDPLITE_RECV_CSCOV:
break;
-
+
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
s, optname));
@@ -1351,7 +1352,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
err = ENOPROTOOPT;
} /* switch */
-
+
if (err != ERR_OK) {
sock_set_errno(sock, err);
return -1;
@@ -1396,7 +1397,7 @@ lwip_getsockopt_internal(void *arg)
optval = data->optval;
switch (level) {
-
+
/* Level: SOL_SOCKET */
case SOL_SOCKET:
switch (optname) {
@@ -1442,7 +1443,7 @@ lwip_getsockopt_internal(void *arg)
case SO_ERROR:
if (sock->err == 0) {
sock_set_errno(sock, err_to_errno(sock->conn->err));
- }
+ }
*(int *)optval = sock->err;
sock->err = 0;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n",
@@ -1500,7 +1501,7 @@ lwip_getsockopt_internal(void *arg)
case IPPROTO_TCP:
switch (optname) {
case TCP_NODELAY:
- *(int*)optval = (sock->conn->pcb.tcp->flags & TF_NODELAY);
+ *(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n",
s, (*(int*)optval)?"on":"off") );
break;
@@ -1861,9 +1862,9 @@ lwip_setsockopt_internal(void *arg)
switch (optname) {
case TCP_NODELAY:
if (*(int*)optval) {
- sock->conn->pcb.tcp->flags |= TF_NODELAY;
+ tcp_nagle_disable(sock->conn->pcb.tcp);
} else {
- sock->conn->pcb.tcp->flags &= ~TF_NODELAY;
+ tcp_nagle_enable(sock->conn->pcb.tcp);
}
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n",
s, (*(int *)optval)?"on":"off") );
diff --git a/net/lwip/src/core/dhcp.c b/net/lwip/src/core/dhcp.c
index df0f978819..82068bfd53 100644
--- a/net/lwip/src/core/dhcp.c
+++ b/net/lwip/src/core/dhcp.c
@@ -99,6 +99,10 @@
* MTU is checked to be big enough in dhcp_start */
#define DHCP_MAX_MSG_LEN(netif) (netif->mtu)
#define DHCP_MAX_MSG_LEN_MIN_REQUIRED 576
+/** Minimum length for reply before packet is parsed */
+#define DHCP_MIN_REPLY_LEN 44
+
+#define REBOOT_TRIES 2
/* DHCP client state machine functions */
static void dhcp_handle_ack(struct netif *netif);
@@ -107,17 +111,18 @@ static void dhcp_handle_offer(struct netif *netif);
static err_t dhcp_discover(struct netif *netif);
static err_t dhcp_select(struct netif *netif);
-static void dhcp_check(struct netif *netif);
static void dhcp_bind(struct netif *netif);
#if DHCP_DOES_ARP_CHECK
+static void dhcp_check(struct netif *netif);
static err_t dhcp_decline(struct netif *netif);
#endif /* DHCP_DOES_ARP_CHECK */
static err_t dhcp_rebind(struct netif *netif);
+static err_t dhcp_reboot(struct netif *netif);
static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state);
/* 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 err_t dhcp_unfold_reply(struct dhcp *dhcp);
+static err_t dhcp_unfold_reply(struct dhcp *dhcp, struct pbuf *p);
static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type);
static u8_t dhcp_get_option_byte(u8_t *ptr);
#if 0
@@ -161,7 +166,7 @@ static void
dhcp_handle_nak(struct netif *netif)
{
struct dhcp *dhcp = netif->dhcp;
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n",
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n",
(void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
/* Set the interface down since the address must no longer be used, as per RFC2131 */
netif_set_down(netif);
@@ -175,6 +180,7 @@ dhcp_handle_nak(struct netif *netif)
dhcp_discover(netif);
}
+#if DHCP_DOES_ARP_CHECK
/**
* Checks if the offered IP address is already in use.
*
@@ -190,20 +196,21 @@ dhcp_check(struct netif *netif)
struct dhcp *dhcp = netif->dhcp;
err_t result;
u16_t msecs;
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0],
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0],
(s16_t)netif->name[1]));
dhcp_set_state(dhcp, DHCP_CHECKING);
/* create an ARP query for the offered IP address, expecting that no host
responds, as the IP address should not be in use. */
result = etharp_query(netif, &dhcp->offered_ip_addr, NULL);
if (result != ERR_OK) {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_check: could not perform ARP query\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_check: could not perform ARP query\n"));
}
dhcp->tries++;
msecs = 500;
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_check(): set request timeout %"U16_F" msecs\n", msecs));
}
+#endif /* DHCP_DOES_ARP_CHECK */
/**
* Remember the configuration offered by a DHCP server.
@@ -216,7 +223,7 @@ dhcp_handle_offer(struct netif *netif)
struct dhcp *dhcp = netif->dhcp;
/* obtain the server address */
u8_t *option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_SERVER_ID);
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n",
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n",
(void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
if (option_ptr != NULL) {
dhcp->server_ip_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
@@ -247,7 +254,7 @@ dhcp_select(struct netif *netif)
const char *p;
#endif /* LWIP_NETIF_HOSTNAME */
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_select(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_select(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
dhcp_set_state(dhcp, DHCP_REQUESTING);
/* create and initialize the DHCP message header */
@@ -286,16 +293,12 @@ dhcp_select(struct netif *netif)
/* shrink the pbuf to the actual content length */
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
- /* TODO: we really should bind to a specific local interface here
- but we cannot specify an unconfigured netif as it is addressless */
/* send broadcast to any DHCP server */
udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
- /* reconnect to any (or to server here?!) */
- udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
dhcp_delete_request(netif);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: REQUESTING\n"));
} else {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_select: could not allocate DHCP request\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_select: could not allocate DHCP request\n"));
}
dhcp->tries++;
msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000;
@@ -378,7 +381,7 @@ static void
dhcp_timeout(struct netif *netif)
{
struct dhcp *dhcp = netif->dhcp;
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_timeout()\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout()\n"));
/* back-off period has passed, or server selection timed out */
if ((dhcp->state == DHCP_BACKING_OFF) || (dhcp->state == DHCP_SELECTING)) {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout(): restarting discovery\n"));
@@ -393,6 +396,7 @@ dhcp_timeout(struct netif *netif)
dhcp_release(netif);
dhcp_discover(netif);
}
+#if DHCP_DOES_ARP_CHECK
/* received no ARP reply for the offered address (which is good) */
} else if (dhcp->state == DHCP_CHECKING) {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): CHECKING, ARP request timed out\n"));
@@ -404,6 +408,7 @@ dhcp_timeout(struct netif *netif)
/* bind the interface to the offered address */
dhcp_bind(netif);
}
+#endif /* DHCP_DOES_ARP_CHECK */
}
/* did not get response to renew request? */
else if (dhcp->state == DHCP_RENEWING) {
@@ -421,6 +426,12 @@ dhcp_timeout(struct netif *netif)
dhcp_release(netif);
dhcp_discover(netif);
}
+ } else if (dhcp->state == DHCP_REBOOTING) {
+ if (dhcp->tries < REBOOT_TRIES) {
+ dhcp_reboot(netif);
+ } else {
+ dhcp_discover(netif);
+ }
}
}
@@ -600,13 +611,13 @@ dhcp_start(struct netif *netif)
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): allocated dhcp"));
/* already has DHCP client attached */
} else {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 3, ("dhcp_start(): restarting DHCP configuration\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(): restarting DHCP configuration\n"));
if (dhcp->pcb != NULL) {
udp_remove(dhcp->pcb);
}
- if (dhcp->p != NULL) {
- pbuf_free(dhcp->p);
- }
+ LWIP_ASSERT("pbuf p_out wasn't freed", dhcp->p_out == NULL);
+ LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL &&
+ dhcp->options_in == NULL && dhcp->options_in_len == 0);
}
/* clear data structure */
@@ -652,23 +663,23 @@ dhcp_start(struct netif *netif)
void
dhcp_inform(struct netif *netif)
{
- struct dhcp *dhcp, *old_dhcp = netif->dhcp;
+ struct dhcp *dhcp, *old_dhcp;
err_t result = ERR_OK;
dhcp = mem_malloc(sizeof(struct dhcp));
if (dhcp == NULL) {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_inform(): could not allocate dhcp\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform(): could not allocate dhcp\n"));
return;
}
- netif->dhcp = dhcp;
memset(dhcp, 0, sizeof(struct dhcp));
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_inform(): allocated dhcp\n"));
dhcp->pcb = udp_new();
if (dhcp->pcb == NULL) {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_inform(): could not obtain pcb"));
- mem_free((void *)dhcp);
- return;
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform(): could not obtain pcb"));
+ goto free_dhcp_and_return;
}
+ old_dhcp = netif->dhcp;
+ netif->dhcp = dhcp;
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_inform(): created new udp pcb\n"));
/* create and initialize the DHCP message header */
result = dhcp_create_request(netif);
@@ -688,21 +699,48 @@ dhcp_inform(struct netif *netif)
dhcp->pcb->so_options|=SOF_BROADCAST;
#endif /* IP_SOF_BROADCAST */
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
- udp_connect(dhcp->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_inform: INFORMING\n"));
udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
- udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
dhcp_delete_request(netif);
} else {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_inform: could not allocate DHCP request\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform: could not allocate DHCP request\n"));
}
- if (dhcp->pcb != NULL) {
- udp_remove(dhcp->pcb);
- }
+ udp_remove(dhcp->pcb);
dhcp->pcb = NULL;
- mem_free((void *)dhcp);
netif->dhcp = old_dhcp;
+free_dhcp_and_return:
+ mem_free((void *)dhcp);
+}
+
+/** Handle a possible change in the network configuration.
+ *
+ * This enters the REBOOTING state to verify that the currently bound
+ * address is still valid.
+ */
+void
+dhcp_network_changed(struct netif *netif)
+{
+ struct dhcp *dhcp = netif->dhcp;
+ if (!dhcp)
+ return;
+ switch (dhcp->state) {
+ case DHCP_REBINDING:
+ case DHCP_RENEWING:
+ case DHCP_BOUND:
+ case DHCP_REBOOTING:
+ netif_set_down(netif);
+ dhcp->tries = 0;
+ dhcp_reboot(netif);
+ break;
+ case DHCP_OFF:
+ /* stay off */
+ break;
+ default:
+ dhcp->tries = 0;
+ dhcp_discover(netif);
+ break;
+ }
}
#if DHCP_DOES_ARP_CHECK
@@ -715,7 +753,7 @@ dhcp_inform(struct netif *netif)
void dhcp_arp_reply(struct netif *netif, struct ip_addr *addr)
{
LWIP_ERROR("netif != NULL", (netif != NULL), return;);
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_arp_reply()\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_arp_reply()\n"));
/* is a DHCP client doing an ARP check? */
if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_CHECKING)) {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n", addr->addr));
@@ -723,7 +761,8 @@ void dhcp_arp_reply(struct netif *netif, struct ip_addr *addr)
were offered by the DHCP server? */
if (ip_addr_cmp(addr, &netif->dhcp->offered_ip_addr)) {
/* we will not accept the offered address */
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 1, ("dhcp_arp_reply(): arp reply matched with offered address, declining\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
+ ("dhcp_arp_reply(): arp reply matched with offered address, declining\n"));
dhcp_decline(netif);
}
}
@@ -744,7 +783,7 @@ dhcp_decline(struct netif *netif)
struct dhcp *dhcp = netif->dhcp;
err_t result = ERR_OK;
u16_t msecs;
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_decline()\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline()\n"));
dhcp_set_state(dhcp, DHCP_BACKING_OFF);
/* create and initialize the DHCP message header */
result = dhcp_create_request(netif);
@@ -759,14 +798,13 @@ dhcp_decline(struct netif *netif)
/* resize pbuf to reflect true size of options */
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
- /* @todo: should we really connect here? we are performing sendto() */
- udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
/* per section 4.4.4, broadcast DECLINE messages */
udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
dhcp_delete_request(netif);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n"));
} else {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_decline: could not allocate DHCP request\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
+ ("dhcp_decline: could not allocate DHCP request\n"));
}
dhcp->tries++;
msecs = 10*1000;
@@ -788,7 +826,7 @@ dhcp_discover(struct netif *netif)
struct dhcp *dhcp = netif->dhcp;
err_t result = ERR_OK;
u16_t msecs;
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_discover()\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover()\n"));
ip_addr_set(&dhcp->offered_ip_addr, IP_ADDR_ANY);
dhcp_set_state(dhcp, DHCP_SELECTING);
/* create and initialize the DHCP message header */
@@ -812,14 +850,13 @@ dhcp_discover(struct netif *netif)
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: realloc()ing\n"));
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
- udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n"));
udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n"));
dhcp_delete_request(netif);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n"));
} else {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_discover: could not allocate DHCP request\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_discover: could not allocate DHCP request\n"));
}
dhcp->tries++;
#if LWIP_DHCP_AUTOIP_COOP
@@ -849,7 +886,7 @@ dhcp_bind(struct netif *netif)
LWIP_ERROR("dhcp_bind: netif != NULL", (netif != NULL), return;);
dhcp = netif->dhcp;
LWIP_ERROR("dhcp_bind: dhcp != NULL", (dhcp != NULL), return;);
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_bind(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
/* temporary DHCP lease? */
if (dhcp->offered_t1_renew != 0xffffffffUL) {
@@ -937,7 +974,7 @@ dhcp_renew(struct netif *netif)
#if LWIP_NETIF_HOSTNAME
const char *p;
#endif /* LWIP_NETIF_HOSTNAME */
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_renew()\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_renew()\n"));
dhcp_set_state(dhcp, DHCP_RENEWING);
/* create and initialize the DHCP message header */
@@ -974,13 +1011,12 @@ dhcp_renew(struct netif *netif)
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
- udp_connect(dhcp->pcb, &dhcp->server_ip_addr, DHCP_SERVER_PORT);
udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif);
dhcp_delete_request(netif);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew: RENEWING\n"));
} else {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_renew: could not allocate DHCP request\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_renew: could not allocate DHCP request\n"));
}
dhcp->tries++;
/* back-off on retries, but to a maximum of 20 seconds */
@@ -1040,12 +1076,11 @@ dhcp_rebind(struct netif *netif)
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
/* broadcast to server */
- udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
dhcp_delete_request(netif);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind: REBINDING\n"));
} else {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_rebind: could not allocate DHCP request\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_rebind: could not allocate DHCP request\n"));
}
dhcp->tries++;
msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
@@ -1055,6 +1090,52 @@ dhcp_rebind(struct netif *netif)
}
/**
+ * Enter REBOOTING state to verify an existing lease
+ *
+ * @param netif network interface which must reboot
+ */
+static err_t
+dhcp_reboot(struct netif *netif)
+{
+ struct dhcp *dhcp = netif->dhcp;
+ err_t result;
+ u16_t msecs;
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot()\n"));
+ dhcp_set_state(dhcp, DHCP_REBOOTING);
+
+ /* create and initialize the DHCP message header */
+ result = dhcp_create_request(netif);
+ if (result == ERR_OK) {
+
+ dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
+ dhcp_option_byte(dhcp, DHCP_REQUEST);
+
+ dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
+ dhcp_option_short(dhcp, 576);
+
+ dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
+ dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
+
+ dhcp_option_trailer(dhcp);
+
+ pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
+
+ /* broadcast to server */
+ udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
+ dhcp_delete_request(netif);
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot: REBOOTING\n"));
+ } else {
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_reboot: could not allocate DHCP request\n"));
+ }
+ dhcp->tries++;
+ msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
+ dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot(): set request timeout %"U16_F" msecs\n", msecs));
+ return result;
+}
+
+
+/**
* Release a DHCP lease.
*
* @param netif network interface which must release its lease
@@ -1065,7 +1146,7 @@ dhcp_release(struct netif *netif)
struct dhcp *dhcp = netif->dhcp;
err_t result;
u16_t msecs;
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_release()\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_release()\n"));
/* idle DHCP client */
dhcp_set_state(dhcp, DHCP_OFF);
@@ -1086,12 +1167,11 @@ dhcp_release(struct netif *netif)
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
- udp_connect(dhcp->pcb, &dhcp->server_ip_addr, DHCP_SERVER_PORT);
udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif);
dhcp_delete_request(netif);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_OFF\n"));
} else {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_release: could not allocate DHCP request\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n"));
}
dhcp->tries++;
msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
@@ -1121,7 +1201,7 @@ dhcp_stop(struct netif *netif)
/* Remove the flag that says this netif is handled by DHCP. */
netif->flags &= ~NETIF_FLAG_DHCP;
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_stop()\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_stop()\n"));
/* netif is DHCP configured? */
if (dhcp != NULL) {
#if LWIP_DHCP_AUTOIP_COOP
@@ -1135,12 +1215,8 @@ dhcp_stop(struct netif *netif)
udp_remove(dhcp->pcb);
dhcp->pcb = NULL;
}
- if (dhcp->p != NULL) {
- pbuf_free(dhcp->p);
- dhcp->p = NULL;
- }
- /* free unfolded reply */
- dhcp_free_reply(dhcp);
+ LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL &&
+ dhcp->options_in == NULL && dhcp->options_in_len == 0);
mem_free((void *)dhcp);
netif->dhcp = NULL;
}
@@ -1214,39 +1290,44 @@ dhcp_option_long(struct dhcp *dhcp, u32_t value)
*
*/
static err_t
-dhcp_unfold_reply(struct dhcp *dhcp)
+dhcp_unfold_reply(struct dhcp *dhcp, struct pbuf *p)
{
u16_t ret;
LWIP_ERROR("dhcp != NULL", (dhcp != NULL), return ERR_ARG;);
- LWIP_ERROR("dhcp->p != NULL", (dhcp->p != NULL), return ERR_VAL;);
/* free any left-overs from previous unfolds */
dhcp_free_reply(dhcp);
/* options present? */
- if (dhcp->p->tot_len > (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN)) {
- dhcp->options_in_len = dhcp->p->tot_len - (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
+ if (p->tot_len > (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN)) {
+ dhcp->options_in_len = p->tot_len - (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
dhcp->options_in = mem_malloc(dhcp->options_in_len);
if (dhcp->options_in == NULL) {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_unfold_reply(): could not allocate dhcp->options\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
+ ("dhcp_unfold_reply(): could not allocate dhcp->options\n"));
+ dhcp->options_in_len = 0;
return ERR_MEM;
}
}
dhcp->msg_in = mem_malloc(sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
if (dhcp->msg_in == NULL) {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_unfold_reply(): could not allocate dhcp->msg_in\n"));
- mem_free((void *)dhcp->options_in);
- dhcp->options_in = NULL;
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
+ ("dhcp_unfold_reply(): could not allocate dhcp->msg_in\n"));
+ if (dhcp->options_in != NULL) {
+ mem_free(dhcp->options_in);
+ dhcp->options_in = NULL;
+ dhcp->options_in_len = 0;
+ }
return ERR_MEM;
}
/** copy the DHCP message without options */
- ret = pbuf_copy_partial(dhcp->p, dhcp->msg_in, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN, 0);
+ ret = pbuf_copy_partial(p, dhcp->msg_in, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN, 0);
LWIP_ASSERT("ret == sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN", ret == sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_unfold_reply(): copied %"U16_F" bytes into dhcp->msg_in[]\n",
sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN));
if (dhcp->options_in != NULL) {
/** copy the DHCP options */
- ret = pbuf_copy_partial(dhcp->p, dhcp->options_in, dhcp->options_in_len, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
+ ret = pbuf_copy_partial(p, dhcp->options_in, dhcp->options_in_len, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
LWIP_ASSERT("ret == dhcp->options_in_len", ret == dhcp->options_in_len);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_unfold_reply(): copied %"U16_F" bytes to dhcp->options_in[]\n",
dhcp->options_in_len));
@@ -1258,7 +1339,6 @@ dhcp_unfold_reply(struct dhcp *dhcp)
/**
* Free the incoming DHCP message including contiguous copy of
* its DHCP options.
- *
*/
static void dhcp_free_reply(struct dhcp *dhcp)
{
@@ -1267,14 +1347,13 @@ static void dhcp_free_reply(struct dhcp *dhcp)
dhcp->msg_in = NULL;
}
if (dhcp->options_in) {
- mem_free((void *)dhcp->options_in);
+ mem_free(dhcp->options_in);
dhcp->options_in = NULL;
dhcp->options_in_len = 0;
}
LWIP_DEBUGF(DHCP_DEBUG, ("dhcp_free_reply(): free'd\n"));
}
-
/**
* If an incoming DHCP message is in response to us, then trigger the state machine
*/
@@ -1286,7 +1365,7 @@ static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_
u8_t *options_ptr;
u8_t msg_type;
u8_t i;
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_recv(pbuf = %p) from DHCP server %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void*)p,
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_recv(pbuf = %p) from DHCP server %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void*)p,
(u16_t)(ntohl(addr->addr) >> 24 & 0xff), (u16_t)(ntohl(addr->addr) >> 16 & 0xff),
(u16_t)(ntohl(addr->addr) >> 8 & 0xff), (u16_t)(ntohl(addr->addr) & 0xff), port));
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len));
@@ -1295,28 +1374,38 @@ static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_
LWIP_UNUSED_ARG(pcb);
LWIP_UNUSED_ARG(addr);
LWIP_UNUSED_ARG(port);
- dhcp->p = p;
- /* TODO: check packet length before reading them */
+
+ LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL &&
+ dhcp->options_in == NULL && dhcp->options_in_len == 0);
+
+ if (p->len < DHCP_MIN_REPLY_LEN) {
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP reply message too short\n"));
+ goto free_pbuf_and_return;
+ }
+
if (reply_msg->op != DHCP_BOOTREPLY) {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1, ("not a DHCP reply message, but type %"U16_F"\n", (u16_t)reply_msg->op));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("not a DHCP reply message, but type %"U16_F"\n", (u16_t)reply_msg->op));
goto free_pbuf_and_return;
}
/* iterate through hardware address and match against DHCP message */
for (i = 0; i < netif->hwaddr_len; i++) {
if (netif->hwaddr[i] != reply_msg->chaddr[i]) {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n",
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
+ ("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n",
(u16_t)i, (u16_t)netif->hwaddr[i], (u16_t)i, (u16_t)reply_msg->chaddr[i]));
goto free_pbuf_and_return;
}
}
/* match transaction ID against what we expected */
if (ntohl(reply_msg->xid) != dhcp->xid) {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("transaction id mismatch reply_msg->xid(%"X32_F")!=dhcp->xid(%"X32_F")\n",ntohl(reply_msg->xid),dhcp->xid));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
+ ("transaction id mismatch reply_msg->xid(%"X32_F")!=dhcp->xid(%"X32_F")\n",ntohl(reply_msg->xid),dhcp->xid));
goto free_pbuf_and_return;
}
/* option fields could be unfold? */
- if (dhcp_unfold_reply(dhcp) != ERR_OK) {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("problem unfolding DHCP message - too short on memory?\n"));
+ if (dhcp_unfold_reply(dhcp, p) != ERR_OK) {
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
+ ("problem unfolding DHCP message - too short on memory?\n"));
goto free_pbuf_and_return;
}
@@ -1324,7 +1413,7 @@ static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_
/* obtain pointer to DHCP message type */
options_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_MESSAGE_TYPE);
if (options_ptr == NULL) {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1, ("DHCP_OPTION_MESSAGE_TYPE option not found\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP_OPTION_MESSAGE_TYPE option not found\n"));
goto free_pbuf_and_return;
}
@@ -1332,7 +1421,7 @@ static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_
msg_type = dhcp_get_option_byte(options_ptr + 2);
/* message type is DHCP ACK? */
if (msg_type == DHCP_ACK) {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1, ("DHCP_ACK received\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_ACK received\n"));
/* in requesting state? */
if (dhcp->state == DHCP_REQUESTING) {
dhcp_handle_ack(netif);
@@ -1355,13 +1444,13 @@ static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_
else if ((msg_type == DHCP_NAK) &&
((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REQUESTING) ||
(dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING ))) {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1, ("DHCP_NAK received\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_NAK received\n"));
dhcp->request_timeout = 0;
dhcp_handle_nak(netif);
}
/* received a DHCP_OFFER in DHCP_SELECTING state? */
else if ((msg_type == DHCP_OFFER) && (dhcp->state == DHCP_SELECTING)) {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1, ("DHCP_OFFER received in DHCP_SELECTING state\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_OFFER received in DHCP_SELECTING state\n"));
dhcp->request_timeout = 0;
/* remember offered lease */
dhcp_handle_offer(netif);
@@ -1369,7 +1458,6 @@ static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_
free_pbuf_and_return:
dhcp_free_reply(dhcp);
pbuf_free(p);
- dhcp->p = NULL;
}
/**
@@ -1403,7 +1491,8 @@ dhcp_create_request(struct netif *netif)
LWIP_ASSERT("dhcp_create_request: dhcp->msg_out == NULL", dhcp->msg_out == NULL);
dhcp->p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM);
if (dhcp->p_out == NULL) {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_create_request(): could not allocate pbuf\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
+ ("dhcp_create_request(): could not allocate pbuf\n"));
return ERR_MEM;
}
LWIP_ASSERT("dhcp_create_request: check that first pbuf can hold struct dhcp_msg",
@@ -1413,7 +1502,7 @@ dhcp_create_request(struct netif *netif)
if (dhcp->tries==0)
xid++;
dhcp->xid = xid;
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2,
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
("transaction id xid(%"X32_F")\n", xid));
dhcp->msg_out = (struct dhcp_msg *)dhcp->p_out->payload;
@@ -1521,7 +1610,7 @@ static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type)
/* 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? */
if (options[offset] == DHCP_OPTION_OVERLOAD) {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("overloaded message detected\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded message detected\n"));
/* skip option type and length */
offset += 2;
overload = options[offset++];
@@ -1543,16 +1632,16 @@ static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type)
if (overload != DHCP_OVERLOAD_NONE) {
u16_t field_len;
if (overload == DHCP_OVERLOAD_FILE) {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1, ("overloaded file field\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded file field\n"));
options = (u8_t *)&dhcp->msg_in->file;
field_len = DHCP_FILE_LEN;
} else if (overload == DHCP_OVERLOAD_SNAME) {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1, ("overloaded sname field\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname field\n"));
options = (u8_t *)&dhcp->msg_in->sname;
field_len = DHCP_SNAME_LEN;
/* TODO: check if else if () is necessary */
} else {
- LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1, ("overloaded sname and file field\n"));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname and file field\n"));
options = (u8_t *)&dhcp->msg_in->sname;
field_len = DHCP_FILE_LEN + DHCP_SNAME_LEN;
}
diff --git a/net/lwip/src/core/dns.c b/net/lwip/src/core/dns.c
index 62a2592e90..b955538c94 100644
--- a/net/lwip/src/core/dns.c
+++ b/net/lwip/src/core/dns.c
@@ -961,7 +961,7 @@ dns_gethostbyname(const char *hostname, struct ip_addr *addr, dns_found_callback
#if LWIP_HAVE_LOOPIF
if (strcmp(hostname,"localhost")==0) {
- addr->addr = INADDR_LOOPBACK;
+ addr->addr = htonl(INADDR_LOOPBACK);
return ERR_OK;
}
#endif /* LWIP_HAVE_LOOPIF */
diff --git a/net/lwip/src/core/init.c b/net/lwip/src/core/init.c
index 277811a6a1..be0e358216 100644
--- a/net/lwip/src/core/init.c
+++ b/net/lwip/src/core/init.c
@@ -168,6 +168,9 @@
#if (DNS_LOCAL_HOSTLIST && !DNS_LOCAL_HOSTLIST_IS_DYNAMIC && !(defined(DNS_LOCAL_HOSTLIST_INIT)))
#error "you have to define define DNS_LOCAL_HOSTLIST_INIT {{'host1', 0x123}, {'host2', 0x234}} to initialize DNS_LOCAL_HOSTLIST"
#endif
+#if PPP_SUPPORT && !PPPOS_SUPPORT & !PPPOE_SUPPORT
+ #error "PPP_SUPPORT needs either PPPOS_SUPPORT or PPPOE_SUPPORT turned on"
+#endif
/* Compile-time checks for deprecated options.
@@ -208,6 +211,8 @@ lwip_sanity_check(void)
#if LWIP_TCP
if (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN)
LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN\n"));
+ if (TCP_SND_BUF < 2 * TCP_MSS)
+ LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly\n"));
if (TCP_SND_QUEUELEN < (2 * (TCP_SND_BUF/TCP_MSS)))
LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_SND_QUEUELEN must be at least as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work\n"));
if (TCP_SNDLOWAT > TCP_SND_BUF)
diff --git a/net/lwip/src/core/ipv4/autoip.c b/net/lwip/src/core/ipv4/autoip.c
index 367adb0605..7aa7cea53f 100644
--- a/net/lwip/src/core/ipv4/autoip.c
+++ b/net/lwip/src/core/ipv4/autoip.c
@@ -100,7 +100,7 @@
*/
#ifndef LWIP_AUTOIP_CREATE_SEED_ADDR
#define LWIP_AUTOIP_CREATE_SEED_ADDR(netif) \
- (AUTOIP_RANGE_START + ((u32_t)(((u8_t)(netif->hwaddr[4])) | \
+ htonl(AUTOIP_RANGE_START + ((u32_t)(((u8_t)(netif->hwaddr[4])) | \
((u32_t)((u8_t)(netif->hwaddr[5]))) << 8)))
#endif /* LWIP_AUTOIP_CREATE_SEED_ADDR */
@@ -108,7 +108,10 @@
static void autoip_handle_arp_conflict(struct netif *netif);
/* creates a pseudo random LL IP-Address for a network interface */
-static void autoip_create_addr(struct netif *netif, struct ip_addr *IPAddr);
+static void autoip_create_addr(struct netif *netif, struct ip_addr *ipaddr);
+
+/* sends an ARP probe */
+static err_t autoip_arp_probe(struct netif *netif);
/* sends an ARP announce */
static err_t autoip_arp_announce(struct netif *netif);
@@ -116,13 +119,16 @@ static err_t autoip_arp_announce(struct netif *netif);
/* configure interface for use with current LL IP-Address */
static err_t autoip_bind(struct netif *netif);
+/* start sending probes for llipaddr */
+static void autoip_start_probing(struct netif *netif);
+
/**
* Initialize this module
*/
void
autoip_init(void)
{
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | 3, ("autoip_init()\n"));
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_init()\n"));
}
/**
@@ -139,19 +145,19 @@ autoip_handle_arp_conflict(struct netif *netif)
/* retreat, there was a conflicting ARP in the last
* DEFEND_INTERVAL seconds
*/
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 1,
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n"));
/* TODO: close all TCP sessions */
autoip_start(netif);
} else {
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 1,
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
("autoip_handle_arp_conflict(): we are defend, send ARP Announce\n"));
autoip_arp_announce(netif);
netif->autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND;
}
} else {
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 1,
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
("autoip_handle_arp_conflict(): we do not defend, retreating\n"));
/* TODO: close all TCP sessions */
autoip_start(netif);
@@ -162,10 +168,10 @@ autoip_handle_arp_conflict(struct netif *netif)
* Create an IP-Address out of range 169.254.1.0 to 169.254.254.255
*
* @param netif network interface on which create the IP-Address
- * @param IPAddr ip address to initialize
+ * @param ipaddr ip address to initialize
*/
static void
-autoip_create_addr(struct netif *netif, struct ip_addr *IPAddr)
+autoip_create_addr(struct netif *netif, struct ip_addr *ipaddr)
{
/* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255
* compliant to RFC 3927 Section 2.1
@@ -183,12 +189,25 @@ autoip_create_addr(struct netif *netif, struct ip_addr *IPAddr)
addr -= AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1;
}
LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) &&
- (addr <= AUTOIP_RANGE_END));
- IPAddr->addr = htonl(addr);
+ (addr <= AUTOIP_RANGE_END));
+ ipaddr->addr = htonl(addr);
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 1,
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
("autoip_create_addr(): tried_llipaddr=%"U16_F", 0x%08"X32_F"\n",
- (u16_t)(netif->autoip->tried_llipaddr), (u32_t)(IPAddr->addr)));
+ (u16_t)(netif->autoip->tried_llipaddr), (u32_t)(ipaddr->addr)));
+}
+
+/**
+ * Sends an ARP probe from a network interface
+ *
+ * @param netif network interface used to send the probe
+ */
+static err_t
+autoip_arp_probe(struct netif *netif)
+{
+ return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, &ethbroadcast,
+ (struct eth_addr *)netif->hwaddr, IP_ADDR_ANY, &ethzero,
+ &netif->autoip->llipaddr, ARP_REQUEST);
}
/**
@@ -215,7 +234,7 @@ autoip_bind(struct netif *netif)
struct autoip *autoip = netif->autoip;
struct ip_addr sn_mask, gw_addr;
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | 3,
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
("autoip_bind(netif=%p) %c%c%"U16_F" 0x%08"X32_F"\n",
(void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num, autoip->llipaddr.addr));
@@ -281,6 +300,16 @@ autoip_start(struct netif *netif)
autoip_create_addr(netif, &(autoip->llipaddr));
autoip->tried_llipaddr++;
+ autoip_start_probing(netif);
+
+ return result;
+}
+
+static void
+autoip_start_probing(struct netif *netif)
+{
+ struct autoip *autoip = netif->autoip;
+
autoip->state = AUTOIP_STATE_PROBING;
autoip->sent_num = 0;
@@ -295,12 +324,24 @@ autoip_start(struct netif *netif)
* accquiring and probing address
* compliant to RFC 3927 Section 2.2.1
*/
-
if(autoip->tried_llipaddr > MAX_CONFLICTS) {
autoip->ttw = RATE_LIMIT_INTERVAL * AUTOIP_TICKS_PER_SECOND;
}
+}
- return result;
+/**
+ * Handle a possible change in the network configuration.
+ *
+ * If there is an AutoIP address configured, take the interface down
+ * and begin probing with the same address.
+ */
+void
+autoip_network_changed(struct netif *netif)
+{
+ if (netif->autoip && netif->autoip->state != AUTOIP_STATE_OFF) {
+ netif_set_down(netif);
+ autoip_start_probing(netif);
+ }
}
/**
@@ -340,13 +381,13 @@ autoip_tmr()
if(netif->autoip->ttw > 0) {
netif->autoip->ttw--;
} else {
- if(netif->autoip->sent_num == PROBE_NUM) {
+ if(netif->autoip->sent_num >= PROBE_NUM) {
netif->autoip->state = AUTOIP_STATE_ANNOUNCING;
netif->autoip->sent_num = 0;
netif->autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND;
} else {
- etharp_request(netif, &(netif->autoip->llipaddr));
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | 3,
+ autoip_arp_probe(netif);
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
("autoip_tmr() PROBING Sent Probe\n"));
netif->autoip->sent_num++;
/* calculate time to wait to next probe */
@@ -363,21 +404,24 @@ autoip_tmr()
} else {
if(netif->autoip->sent_num == 0) {
/* We are here the first time, so we waited ANNOUNCE_WAIT seconds
- * Now we can bind to an IP address and use it
+ * Now we can bind to an IP address and use it.
+ *
+ * autoip_bind calls netif_set_up. This triggers a gratuitous ARP
+ * which counts as an announcement.
*/
autoip_bind(netif);
- }
-
- if(netif->autoip->sent_num == ANNOUNCE_NUM) {
- netif->autoip->state = AUTOIP_STATE_BOUND;
- netif->autoip->sent_num = 0;
- netif->autoip->ttw = 0;
} else {
autoip_arp_announce(netif);
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | 3,
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
("autoip_tmr() ANNOUNCING Sent Announce\n"));
- netif->autoip->sent_num++;
- netif->autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND;
+ }
+ netif->autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND;
+ netif->autoip->sent_num++;
+
+ if(netif->autoip->sent_num >= ANNOUNCE_NUM) {
+ netif->autoip->state = AUTOIP_STATE_BOUND;
+ netif->autoip->sent_num = 0;
+ netif->autoip->ttw = 0;
}
}
break;
@@ -397,7 +441,7 @@ autoip_tmr()
void
autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
{
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | 3, ("autoip_arp_reply()\n"));
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_arp_reply()\n"));
if ((netif->autoip != NULL) && (netif->autoip->state != AUTOIP_STATE_OFF)) {
/* when ip.src == llipaddr && hw.src != netif->hwaddr
*
@@ -431,7 +475,7 @@ autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
if ((ip_addr_cmp(&sipaddr, &netif->autoip->llipaddr)) ||
(ip_addr_cmp(&dipaddr, &netif->autoip->llipaddr) &&
!eth_addr_cmp(&netifaddr, &hdr->shwaddr))) {
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 1,
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
("autoip_arp_reply(): Probe Conflict detected\n"));
autoip_start(netif);
}
@@ -442,7 +486,7 @@ autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
*/
if (ip_addr_cmp(&sipaddr, &netif->autoip->llipaddr) &&
!eth_addr_cmp(&netifaddr, &hdr->shwaddr)) {
- LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 1,
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
("autoip_arp_reply(): Conflicting ARP-Packet detected\n"));
autoip_handle_arp_conflict(netif);
}
diff --git a/net/lwip/src/core/ipv4/ip.c b/net/lwip/src/core/ipv4/ip.c
index 7e404a9f36..b1e98f33ca 100644
--- a/net/lwip/src/core/ipv4/ip.c
+++ b/net/lwip/src/core/ipv4/ip.c
@@ -62,40 +62,12 @@
* The interface that provided the packet for the current callback
* invocation.
*/
-static struct netif *current_netif;
+struct netif *current_netif;
/**
* Header of the input packet currently being processed.
*/
-static const struct ip_hdr *current_header;
-
-/**
- * Get the interface that received the current packet.
- *
- * This function must only be called from a receive callback (udp_recv,
- * raw_recv, tcp_accept). It will return NULL otherwise.
- *
- * @param pcb Pointer to the pcb receiving a packet.
- */
-struct netif *
-ip_current_netif(void)
-{
- return current_netif;
-}
-
-/**
- * Get the IP header of the current packet.
- *
- * This function must only be called from a receive callback (udp_recv,
- * raw_recv, tcp_accept). It will return NULL otherwise.
- *
- * @param pcb Pointer to the pcb receiving a packet.
- */
-const struct ip_hdr *
-ip_current_header(void)
-{
- return current_header;
-}
+const struct ip_hdr *current_header;
/**
* Finds the appropriate network interface for a given IP address. It
@@ -122,7 +94,7 @@ ip_route(struct ip_addr *dest)
}
}
if ((netif_default == NULL) || (!netif_is_up(netif_default))) {
- LWIP_DEBUGF(IP_DEBUG | 2, ("ip_route: No route to 0x%"X32_F"\n", dest->addr));
+ LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_route: No route to 0x%"X32_F"\n", dest->addr));
IP_STATS_INC(ip.rterr);
snmp_inc_ipoutnoroutes();
return NULL;
@@ -230,7 +202,7 @@ ip_input(struct pbuf *p, struct netif *inp)
/* identify the IP header */
iphdr = p->payload;
if (IPH_V(iphdr) != 4) {
- LWIP_DEBUGF(IP_DEBUG | 1, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr)));
+ LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr)));
ip_debug_print(p);
pbuf_free(p);
IP_STATS_INC(ip.err);
@@ -248,13 +220,16 @@ ip_input(struct pbuf *p, struct netif *inp)
/* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */
if ((iphdr_hlen > p->len) || (iphdr_len > p->tot_len)) {
- if (iphdr_hlen > p->len)
- LWIP_DEBUGF(IP_DEBUG | 2, ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n",
- iphdr_hlen, p->len));
- if (iphdr_len > p->tot_len)
- LWIP_DEBUGF(IP_DEBUG | 2, ("IP (len %"U16_F") is longer than pbuf (len %"U16_F"), "
- "IP packet dropped.\n",
- iphdr_len, p->tot_len));
+ if (iphdr_hlen > p->len) {
+ LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
+ ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n",
+ iphdr_hlen, p->len));
+ }
+ if (iphdr_len > p->tot_len) {
+ LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
+ ("IP (len %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n",
+ iphdr_len, p->tot_len));
+ }
/* free (drop) packet pbufs */
pbuf_free(p);
IP_STATS_INC(ip.lenerr);
@@ -267,7 +242,8 @@ ip_input(struct pbuf *p, struct netif *inp)
#if CHECKSUM_CHECK_IP
if (inet_chksum(iphdr, iphdr_hlen) != 0) {
- LWIP_DEBUGF(IP_DEBUG | 2, ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdr_hlen)));
+ LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
+ ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdr_hlen)));
ip_debug_print(p);
pbuf_free(p);
IP_STATS_INC(ip.chkerr);
@@ -336,10 +312,10 @@ ip_input(struct pbuf *p, struct netif *inp)
if (netif == NULL) {
/* remote port is DHCP server? */
if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
- LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | 1, ("ip_input: UDP packet to DHCP client port %"U16_F"\n",
+ LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: UDP packet to DHCP client port %"U16_F"\n",
ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen))->dest)));
if (ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen))->dest) == DHCP_CLIENT_PORT) {
- LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | 1, ("ip_input: DHCP packet accepted.\n"));
+ LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: DHCP packet accepted.\n"));
netif = inp;
check_ip_src = 0;
}
@@ -349,12 +325,13 @@ ip_input(struct pbuf *p, struct netif *inp)
/* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */
#if LWIP_DHCP
- if (check_ip_src)
+ /* DHCP servers need 0.0.0.0 to be allowed as source address (RFC 1.1.2.2: 3.2.1.3/a) */
+ if (check_ip_src && (iphdr->src.addr != 0))
#endif /* LWIP_DHCP */
{ if ((ip_addr_isbroadcast(&(iphdr->src), inp)) ||
(ip_addr_ismulticast(&(iphdr->src)))) {
/* packet source is not valid */
- LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | 1, ("ip_input: packet source is not valid.\n"));
+ LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ip_input: packet source is not valid.\n"));
/* free (drop) packet pbufs */
pbuf_free(p);
IP_STATS_INC(ip.drop);
@@ -367,7 +344,7 @@ ip_input(struct pbuf *p, struct netif *inp)
/* packet not for us? */
if (netif == NULL) {
/* packet not for us, route or discard */
- LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | 1, ("ip_input: packet not for us.\n"));
+ LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: packet not for us.\n"));
#if IP_FORWARD
/* non-broadcast packet? */
if (!ip_addr_isbroadcast(&(iphdr->dest), inp)) {
@@ -396,7 +373,7 @@ ip_input(struct pbuf *p, struct netif *inp)
iphdr = p->payload;
#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */
pbuf_free(p);
- LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n",
+ LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n",
ntohs(IPH_OFFSET(iphdr))));
IP_STATS_INC(ip.opterr);
IP_STATS_INC(ip.drop);
@@ -414,7 +391,7 @@ ip_input(struct pbuf *p, struct netif *inp)
#else
if (iphdr_hlen > IP_HLEN) {
#endif /* LWIP_IGMP */
- LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since there were IP options (while IP_OPTIONS_ALLOWED == 0).\n"));
+ LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since there were IP options (while IP_OPTIONS_ALLOWED == 0).\n"));
pbuf_free(p);
IP_STATS_INC(ip.opterr);
IP_STATS_INC(ip.drop);
@@ -476,7 +453,7 @@ ip_input(struct pbuf *p, struct netif *inp)
#endif /* LWIP_ICMP */
pbuf_free(p);
- LWIP_DEBUGF(IP_DEBUG | 2, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr)));
+ LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr)));
IP_STATS_INC(ip.proterr);
IP_STATS_INC(ip.drop);
@@ -551,7 +528,7 @@ err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest
ip_hlen += optlen_aligned;
/* First write in the IP options */
if (pbuf_header(p, optlen_aligned)) {
- LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output_if_opt: not enough room for IP options in pbuf\n"));
+ LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output_if_opt: not enough room for IP options in pbuf\n"));
IP_STATS_INC(ip.err);
snmp_inc_ipoutdiscards();
return ERR_BUF;
@@ -565,7 +542,7 @@ err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest
#endif /* IP_OPTIONS_SEND */
/* generate IP header */
if (pbuf_header(p, IP_HLEN)) {
- LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: not enough room for IP header in pbuf\n"));
+ LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output: not enough room for IP header in pbuf\n"));
IP_STATS_INC(ip.err);
snmp_inc_ipoutdiscards();
@@ -603,30 +580,27 @@ err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest
dest = &(iphdr->dest);
}
-#if IP_FRAG
- /* don't fragment if interface has mtu set to 0 [loopif] */
- if (netif->mtu && (p->tot_len > netif->mtu))
- return ip_frag(p,netif,dest);
-#endif
-
IP_STATS_INC(ip.xmit);
LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num));
ip_debug_print(p);
-#if (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF)
+#if ENABLE_LOOPBACK
if (ip_addr_cmp(dest, &netif->ip_addr)) {
/* Packet to self, enqueue it for loopback */
LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()"));
-
return netif_loop_output(netif, p, dest);
- } else
-#endif /* (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF) */
- {
- LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
-
- return netif->output(netif, p, dest);
}
+#endif /* ENABLE_LOOPBACK */
+#if IP_FRAG
+ /* don't fragment if interface has mtu set to 0 [loopif] */
+ if (netif->mtu && (p->tot_len > netif->mtu)) {
+ return ip_frag(p,netif,dest);
+ }
+#endif
+
+ LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
+ return netif->output(netif, p, dest);
}
/**
diff --git a/net/lwip/src/core/mem.c b/net/lwip/src/core/mem.c
index b5f13ab3b0..7928e3bf0b 100644
--- a/net/lwip/src/core/mem.c
+++ b/net/lwip/src/core/mem.c
@@ -300,7 +300,7 @@ mem_free(void *rmem)
LWIP_MEM_FREE_DECL_PROTECT();
if (rmem == NULL) {
- LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | 2, ("mem_free(p == NULL) was called.\n"));
+ LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("mem_free(p == NULL) was called.\n"));
return;
}
LWIP_ASSERT("mem_free: sanity check alignment", (((mem_ptr_t)rmem) & (MEM_ALIGNMENT-1)) == 0);
@@ -310,7 +310,7 @@ mem_free(void *rmem)
if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
SYS_ARCH_DECL_PROTECT(lev);
- LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_free: illegal memory\n"));
+ LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_free: illegal memory\n"));
/* protect mem stats from concurrent access */
SYS_ARCH_PROTECT(lev);
MEM_STATS_INC(illegal);
@@ -380,7 +380,7 @@ mem_realloc(void *rmem, mem_size_t newsize)
if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
SYS_ARCH_DECL_PROTECT(lev);
- LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_realloc: illegal memory\n"));
+ LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_realloc: illegal memory\n"));
/* protect mem stats from concurrent access */
SYS_ARCH_PROTECT(lev);
MEM_STATS_INC(illegal);
@@ -599,7 +599,7 @@ mem_malloc(mem_size_t size)
/* if we got interrupted by a mem_free, try again */
} while(local_mem_free_count != 0);
#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
- LWIP_DEBUGF(MEM_DEBUG | 2, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size));
+ LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size));
MEM_STATS_INC(err);
LWIP_MEM_ALLOC_UNPROTECT();
sys_sem_signal(mem_sem);
diff --git a/net/lwip/src/core/memp.c b/net/lwip/src/core/memp.c
index dfc32213d6..dbbdc54443 100644
--- a/net/lwip/src/core/memp.c
+++ b/net/lwip/src/core/memp.c
@@ -289,7 +289,11 @@ memp_init(void)
/* check everything a first time to see if it worked */
memp_overflow_check_all();
#endif /* MEMP_OVERFLOW_CHECK */
-}
+}
+#else
+/* fix time-wait tcp pcb issue */
+static rt_uint16_t tcp_pcbs = 0;
+#endif /* MEMP_MEM_MALLOC */
/**
* Get an element from a specific pool.
@@ -308,7 +312,8 @@ memp_malloc(memp_t type)
#else
memp_malloc_fn(memp_t type, const char* file, const int line)
#endif
-{
+{
+#if !MEMP_MEM_MALLOC
struct memp *memp;
SYS_ARCH_DECL_PROTECT(old_level);
@@ -333,13 +338,41 @@ memp_malloc_fn(memp_t type, const char* file, const int line)
((mem_ptr_t)memp % MEM_ALIGNMENT) == 0);
memp = (struct memp*)((u8_t*)memp + MEMP_SIZE);
} else {
- LWIP_DEBUGF(MEMP_DEBUG | 2, ("memp_malloc: out of memory in pool %s\n", memp_desc[type]));
+ LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", memp_desc[type]));
MEMP_STATS_INC(err, type);
}
-
SYS_ARCH_UNPROTECT(old_level);
return memp;
+#else
+ void* ptr;
+ rt_uint32_t size;
+ SYS_ARCH_DECL_PROTECT(old_level);
+
+ size = memp_sizes[type];
+ LWIP_DEBUGF(MEMP_DEBUG, ("memp malloc %s, size %d, ", memp_desc[type], memp_sizes[type]));
+
+ SYS_ARCH_PROTECT(old_level);
+ if (type == MEMP_TCP_PCB)
+ {
+ if (tcp_pcbs >= MEMP_NUM_TCP_PCB)
+ {
+ SYS_ARCH_UNPROTECT(old_level);
+ return NULL;
+ }
+ else
+ {
+ /* increased tcp pcb allocated number */
+ tcp_pcbs ++;
+ }
+ }
+ SYS_ARCH_UNPROTECT(old_level);
+
+ ptr = mem_malloc(size);
+ LWIP_DEBUGF(MEMP_DEBUG, ("mem 0x%x\n", ptr));
+
+ return ptr;
+#endif /* MEMP_MEM_MALLOC */
}
/**
@@ -351,6 +384,7 @@ memp_malloc_fn(memp_t type, const char* file, const int line)
void
memp_free(memp_t type, void *mem)
{
+#if !MEMP_MEM_MALLOC
struct memp *memp;
SYS_ARCH_DECL_PROTECT(old_level);
@@ -381,6 +415,19 @@ memp_free(memp_t type, void *mem)
#endif /* MEMP_SANITY_CHECK */
SYS_ARCH_UNPROTECT(old_level);
-}
-
+#else
+ SYS_ARCH_DECL_PROTECT(old_level);
+
+ SYS_ARCH_PROTECT(old_level);
+ if (type == MEMP_TCP_PCB && mem)
+ {
+ tcp_pcbs --;
+ }
+ SYS_ARCH_UNPROTECT(old_level);
+
+ LWIP_DEBUGF(MEMP_DEBUG, ("memp free %s, mem 0x%x\n", memp_desc[type], mem));
+ /* release this memory */
+ mem_free(mem);
#endif /* MEMP_MEM_MALLOC */
+}
+
diff --git a/net/lwip/src/core/memp_tiny.c b/net/lwip/src/core/memp_tiny.c
deleted file mode 100644
index 95a4a87f46..0000000000
--- a/net/lwip/src/core/memp_tiny.c
+++ /dev/null
@@ -1,116 +0,0 @@
-#include "lwip/opt.h"
-
-#include "lwip/memp.h"
-#include "lwip/pbuf.h"
-#include "lwip/udp.h"
-#include "lwip/raw.h"
-#include "lwip/tcp.h"
-#include "lwip/igmp.h"
-#include "lwip/api.h"
-#include "lwip/api_msg.h"
-#include "lwip/tcpip.h"
-#include "lwip/sys.h"
-#include "lwip/stats.h"
-#include "netif/etharp.h"
-#include "lwip/ip_frag.h"
-
-#include <string.h>
-
-#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x))
-
-/** This array holds the element sizes of each pool. */
-static const u16_t memp_sizes[MEMP_MAX] = {
-#define LWIP_MEMPOOL(name,num,size,desc) MEMP_ALIGN_SIZE(size),
-#include "lwip/memp_std.h"
-};
-
-/** This array holds a textual description of each pool. */
-#ifdef LWIP_DEBUG
-static const char *memp_desc[MEMP_MAX] = {
-#define LWIP_MEMPOOL(name,num,size,desc) (desc),
-#include "lwip/memp_std.h"
-};
-#endif /* LWIP_DEBUG */
-
-/* fix time-wait tcp pcb issue */
-static rt_uint32_t tcp_pcbs = 0;
-
-/**
- * Initialize this module.
- *
- * Carves out memp_memory into linked lists for each pool-type.
- */
-void
-memp_init(void)
-{
- /* nothing */
-}
-
-/**
- * Get an element from a specific pool.
- *
- * @param type the pool to get an element from
- *
- * the debug version has two more parameters:
- * @param file file name calling this function
- * @param line number of line where this function is called
- *
- * @return a pointer to the allocated memory or a NULL pointer on error
- */
-void *
-#if !MEMP_OVERFLOW_CHECK
-memp_malloc(memp_t type)
-#else
-memp_malloc_fn(memp_t type, const char* file, const int line)
-#endif
-{
- void* ptr;
- rt_uint32_t size, level;
-
- size = memp_sizes[type];
- LWIP_DEBUGF(MEMP_DEBUG, ("memp malloc %s, size %d, ", memp_desc[type], memp_sizes[type]));
-
- level = rt_hw_interrupt_disable();
- if (type == MEMP_TCP_PCB)
- {
- if (tcp_pcbs >= MEMP_NUM_TCP_PCB)
- {
- rt_hw_interrupt_enable(level);
- return RT_NULL;
- }
- else
- {
- /* increased tcp pcb allocated number */
- tcp_pcbs ++;
- }
- }
- rt_hw_interrupt_enable(level);
-
- ptr = rt_malloc(size);
- LWIP_DEBUGF(MEMP_DEBUG, ("mem 0x%x\n", ptr));
-
- return ptr;
-}
-
-/**
- * Put an element back into its pool.
- *
- * @param type the pool where to put mem
- * @param mem the memp element to free
- */
-void
-memp_free(memp_t type, void *mem)
-{
- rt_uint32_t level;
-
- level = rt_hw_interrupt_disable();
- if (type == MEMP_TCP_PCB && mem)
- {
- tcp_pcbs --;
- }
- rt_hw_interrupt_enable(level);
-
- LWIP_DEBUGF(MEMP_DEBUG, ("memp free %s, mem 0x%x\n", memp_desc[type], mem));
- /* release this memory */
- rt_free(mem);
-}
diff --git a/net/lwip/src/core/netif.c b/net/lwip/src/core/netif.c
index c9b6b9b5e4..b52cd02ac8 100644
--- a/net/lwip/src/core/netif.c
+++ b/net/lwip/src/core/netif.c
@@ -52,6 +52,13 @@
#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
#endif /* ENABLE_LOOPBACK */
+#if LWIP_AUTOIP
+#include "lwip/autoip.h"
+#endif /* LWIP_AUTOIP */
+#if LWIP_DHCP
+#include "lwip/dhcp.h"
+#endif /* LWIP_DHCP */
+
#if LWIP_NETIF_STATUS_CALLBACK
#define NETIF_STATUS_CALLBACK(n) { if (n->status_callback) (n->status_callback)(n); }
#else
@@ -271,14 +278,14 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
if ((ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0)
{
/* extern struct tcp_pcb *tcp_active_pcbs; defined by tcp.h */
- LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: netif address being changed\n"));
+ LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n"));
pcb = tcp_active_pcbs;
while (pcb != NULL) {
/* PCB bound to current local interface address? */
if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) {
/* this connection must be aborted */
struct tcp_pcb *next = pcb->next;
- LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb));
+ LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb));
tcp_abort(pcb);
pcb = next;
} else {
@@ -303,7 +310,7 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
snmp_insert_ipaddridx_tree(netif);
snmp_insert_iprteidx_tree(0,netif);
- LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 3, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
+ LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
netif->name[0], netif->name[1],
ip4_addr1(&netif->ip_addr),
ip4_addr2(&netif->ip_addr),
@@ -323,7 +330,7 @@ void
netif_set_gw(struct netif *netif, struct ip_addr *gw)
{
ip_addr_set(&(netif->gw), gw);
- LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 3, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
+ LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
netif->name[0], netif->name[1],
ip4_addr1(&netif->gw),
ip4_addr2(&netif->gw),
@@ -347,7 +354,7 @@ netif_set_netmask(struct netif *netif, struct ip_addr *netmask)
/* set new netmask to netif */
ip_addr_set(&(netif->netmask), netmask);
snmp_insert_iprteidx_tree(0, netif);
- LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 3, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
+ LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
netif->name[0], netif->name[1],
ip4_addr1(&netif->netmask),
ip4_addr2(&netif->netmask),
@@ -406,7 +413,13 @@ void netif_set_up(struct netif *netif)
etharp_gratuitous(netif);
}
#endif /* LWIP_ARP */
-
+
+#if LWIP_IGMP
+ /* resend IGMP memberships */
+ if (netif->flags & NETIF_FLAG_IGMP) {
+ igmp_report_groups( netif);
+ }
+#endif /* LWIP_IGMP */
}
}
@@ -459,6 +472,19 @@ void netif_set_link_up(struct netif *netif )
{
netif->flags |= NETIF_FLAG_LINK_UP;
+#if LWIP_DHCP
+ if (netif->dhcp) {
+ dhcp_network_changed(netif);
+ }
+#endif /* LWIP_DHCP */
+
+#if LWIP_AUTOIP
+ if (netif->autoip) {
+ autoip_network_changed(netif);
+ }
+#endif /* LWIP_AUTOIP */
+
+ if (netif->flags & NETIF_FLAG_UP) {
#if LWIP_ARP
/* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */
if (netif->flags & NETIF_FLAG_ETHARP) {
@@ -467,12 +493,12 @@ void netif_set_link_up(struct netif *netif )
#endif /* LWIP_ARP */
#if LWIP_IGMP
- /* resend IGMP memberships */
- if (netif->flags & NETIF_FLAG_IGMP) {
- igmp_report_groups( netif);
- }
+ /* resend IGMP memberships */
+ if (netif->flags & NETIF_FLAG_IGMP) {
+ igmp_report_groups( netif);
+ }
#endif /* LWIP_IGMP */
-
+ }
NETIF_LINK_CALLBACK(netif);
}
diff --git a/net/lwip/src/core/pbuf.c b/net/lwip/src/core/pbuf.c
index 50b22c354c..11cc2e67fd 100644
--- a/net/lwip/src/core/pbuf.c
+++ b/net/lwip/src/core/pbuf.c
@@ -81,41 +81,71 @@
aligned there. Therefore, PBUF_POOL_BUFSIZE_ALIGNED can be used here. */
#define PBUF_POOL_BUFSIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE)
-#if TCP_QUEUE_OOSEQ
-#define ALLOC_POOL_PBUF(p) do { (p) = alloc_pool_pbuf(); } while (0)
-#else
-#define ALLOC_POOL_PBUF(p) do { (p) = memp_malloc(MEMP_PBUF_POOL); } while (0)
-#endif
-
+#if !TCP_QUEUE_OOSEQ || NO_SYS
+#define PBUF_POOL_IS_EMPTY()
+#else /* !TCP_QUEUE_OOSEQ || NO_SYS */
+/** Define this to 0 to prevent freeing ooseq pbufs when the PBUF_POOL is empty */
+#ifndef PBUF_POOL_FREE_OOSEQ
+#define PBUF_POOL_FREE_OOSEQ 1
+#endif /* PBUF_POOL_FREE_OOSEQ */
-#if TCP_QUEUE_OOSEQ
+#if PBUF_POOL_FREE_OOSEQ
+#include "lwip/tcpip.h"
+#define PBUF_POOL_IS_EMPTY() pbuf_pool_is_empty()
+static u8_t pbuf_free_ooseq_queued;
/**
* Attempt to reclaim some memory from queued out-of-sequence TCP segments
* if we run out of pool pbufs. It's better to give priority to new packets
* if we're running out.
*
- * @return the allocated pbuf.
+ * This must be done in the correct thread context therefore this function
+ * can only be used with NO_SYS=0 and through tcpip_callback.
*/
-static struct pbuf *
-alloc_pool_pbuf(void)
+static void
+pbuf_free_ooseq(void* arg)
{
- struct tcp_pcb *pcb;
- struct pbuf *p;
+ struct tcp_pcb* pcb;
+ SYS_ARCH_DECL_PROTECT(old_level);
+ LWIP_UNUSED_ARG(arg);
-retry:
- p = memp_malloc(MEMP_PBUF_POOL);
- if (NULL == p) {
- for (pcb=tcp_active_pcbs; NULL != pcb; pcb = pcb->next) {
- if (NULL != pcb->ooseq) {
- tcp_segs_free(pcb->ooseq);
- pcb->ooseq = NULL;
- goto retry;
- }
+ SYS_ARCH_PROTECT(old_level);
+ pbuf_free_ooseq_queued = 0;
+ SYS_ARCH_UNPROTECT(old_level);
+
+ for (pcb = tcp_active_pcbs; NULL != pcb; pcb = pcb->next) {
+ if (NULL != pcb->ooseq) {
+ /** Free the ooseq pbufs of one PCB only */
+ LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free_ooseq: freeing out-of-sequence pbufs\n"));
+ tcp_segs_free(pcb->ooseq);
+ pcb->ooseq = NULL;
+ return;
+ }
+ }
+}
+
+/** Queue a call to pbuf_free_ooseq if not already queued. */
+static void
+pbuf_pool_is_empty(void)
+{
+ u8_t queued;
+ SYS_ARCH_DECL_PROTECT(old_level);
+
+ SYS_ARCH_PROTECT(old_level);
+ queued = pbuf_free_ooseq_queued;
+ pbuf_free_ooseq_queued = 1;
+ SYS_ARCH_UNPROTECT(old_level);
+
+ if(!queued) {
+ /* queue a call to pbuf_free_ooseq if not already queued */
+ if(tcpip_callback_with_block(pbuf_free_ooseq, NULL, 0) != ERR_OK) {
+ SYS_ARCH_PROTECT(old_level);
+ pbuf_free_ooseq_queued = 0;
+ SYS_ARCH_UNPROTECT(old_level);
}
}
- return p;
}
-#endif /* TCP_QUEUE_OOSEQ */
+#endif /* PBUF_POOL_FREE_OOSEQ */
+#endif /* !TCP_QUEUE_OOSEQ || NO_SYS */
/**
* Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type).
@@ -154,7 +184,7 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
struct pbuf *p, *q, *r;
u16_t offset;
s32_t rem_len; /* remaining length */
- LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE | 3, ("pbuf_alloc(length=%"U16_F")\n", length));
+ LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F")\n", length));
/* determine header offset */
offset = 0;
@@ -181,9 +211,10 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
switch (type) {
case PBUF_POOL:
/* allocate head of pbuf chain into p */
- ALLOC_POOL_PBUF(p);
- LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE | 3, ("pbuf_alloc: allocated pbuf %p\n", (void *)p));
+ p = memp_malloc(MEMP_PBUF_POOL);
+ LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc: allocated pbuf %p\n", (void *)p));
if (p == NULL) {
+ PBUF_POOL_IS_EMPTY();
return NULL;
}
p->type = type;
@@ -213,8 +244,9 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
rem_len = length - p->len;
/* any remaining pbufs to be allocated? */
while (rem_len > 0) {
- ALLOC_POOL_PBUF(q);
+ q = memp_malloc(MEMP_PBUF_POOL);
if (q == NULL) {
+ PBUF_POOL_IS_EMPTY();
/* free chain so far allocated */
pbuf_free(p);
/* bail out unsuccesfully */
@@ -268,7 +300,8 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
/* only allocate memory for the pbuf structure */
p = memp_malloc(MEMP_PBUF);
if (p == NULL) {
- LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE | 2, ("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_%s.\n",
+ LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
+ ("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_%s.\n",
(type == PBUF_ROM) ? "ROM" : "REF"));
return NULL;
}
@@ -286,7 +319,7 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
p->ref = 1;
/* set flags */
p->flags = 0;
- LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE | 3, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p));
+ LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p));
return p;
}
@@ -426,9 +459,9 @@ pbuf_header(struct pbuf *p, s16_t header_size_increment)
p->payload = (u8_t *)p->payload - header_size_increment;
/* boundary check fails? */
if ((u8_t *)p->payload < (u8_t *)p + SIZEOF_STRUCT_PBUF) {
- LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_header: failed as %p < %p (not enough space for new header size)\n",
- (void *)p->payload,
- (void *)(p + 1)));\
+ LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
+ ("pbuf_header: failed as %p < %p (not enough space for new header size)\n",
+ (void *)p->payload, (void *)(p + 1)));
/* restore old payload pointer */
p->payload = payload;
/* bail out unsuccesfully */
@@ -455,7 +488,7 @@ pbuf_header(struct pbuf *p, s16_t header_size_increment)
p->len += header_size_increment;
p->tot_len += header_size_increment;
- LWIP_DEBUGF(PBUF_DEBUG, ("pbuf_header: old %p new %p (%"S16_F")\n",
+ LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_header: old %p new %p (%"S16_F")\n",
(void *)payload, (void *)p->payload, header_size_increment));
return 0;
@@ -504,10 +537,11 @@ pbuf_free(struct pbuf *p)
if (p == NULL) {
LWIP_ASSERT("p != NULL", p != NULL);
/* if assertions are disabled, proceed with debug output */
- LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE | 2, ("pbuf_free(p == NULL) was called.\n"));
+ LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
+ ("pbuf_free(p == NULL) was called.\n"));
return 0;
}
- LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE | 3, ("pbuf_free(%p)\n", (void *)p));
+ LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free(%p)\n", (void *)p));
PERF_START;
@@ -534,7 +568,7 @@ pbuf_free(struct pbuf *p)
if (ref == 0) {
/* remember next pbuf in chain for next iteration */
q = p->next;
- LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: deallocating %p\n", (void *)p));
+ LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: deallocating %p\n", (void *)p));
type = p->type;
/* is this a pbuf from the pool? */
if (type == PBUF_POOL) {
@@ -552,7 +586,7 @@ pbuf_free(struct pbuf *p)
/* p->ref > 0, this pbuf is still referenced to */
/* (and so the remaining pbufs in chain as well) */
} else {
- LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, ref));
+ LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, ref));
/* stop walking through the chain */
p = NULL;
}
@@ -657,7 +691,7 @@ pbuf_chain(struct pbuf *h, struct pbuf *t)
pbuf_cat(h, t);
/* t is now referenced by h */
pbuf_ref(t);
- LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_FRESH | 2, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t));
+ LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t));
}
/**
@@ -686,10 +720,10 @@ pbuf_dechain(struct pbuf *p)
/* total length of pbuf p is its own length only */
p->tot_len = p->len;
/* q is no longer referenced by p, free it */
- LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_STATE, ("pbuf_dechain: unreferencing %p\n", (void *)q));
+ LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_dechain: unreferencing %p\n", (void *)q));
tail_gone = pbuf_free(q);
if (tail_gone > 0) {
- LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_STATE,
+ LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE,
("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q));
}
/* return remaining tail or NULL if deallocated */
@@ -722,7 +756,7 @@ pbuf_copy(struct pbuf *p_to, struct pbuf *p_from)
{
u16_t offset_to=0, offset_from=0, len;
- LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE | 3, ("pbuf_copy(%p, %p)\n",
+ LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\n",
(void*)p_to, (void*)p_from));
/* is the target big enough to hold the source? */
@@ -768,7 +802,7 @@ pbuf_copy(struct pbuf *p_to, struct pbuf *p_from)
(p_to->next == NULL), return ERR_VAL;);
}
} while (p_from);
- LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE | 1, ("pbuf_copy: end of chain reached.\n"));
+ LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy: end of chain reached.\n"));
return ERR_OK;
}
diff --git a/net/lwip/src/core/raw.c b/net/lwip/src/core/raw.c
index 589950e751..2f105fe6bf 100644
--- a/net/lwip/src/core/raw.c
+++ b/net/lwip/src/core/raw.c
@@ -210,7 +210,7 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
struct ip_addr *src_ip;
struct pbuf *q; /* q will be sent down the stack */
- LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | 3, ("raw_sendto\n"));
+ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n"));
/* not enough space to add an IP header to first pbuf in given p chain? */
if (pbuf_header(p, IP_HLEN)) {
@@ -218,7 +218,7 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM);
/* new header pbuf could not be allocated? */
if (q == NULL) {
- LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | 2, ("raw_sendto: could not allocate header\n"));
+ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("raw_sendto: could not allocate header\n"));
return ERR_MEM;
}
/* chain header q in front of given pbuf p */
@@ -235,7 +235,7 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
}
if ((netif = ip_route(ipaddr)) == NULL) {
- LWIP_DEBUGF(RAW_DEBUG | 1, ("raw_sendto: No route to 0x%"X32_F"\n", ipaddr->addr));
+ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to 0x%"X32_F"\n", ipaddr->addr));
/* free any temporary header pbuf allocated by pbuf_header() */
if (q != p) {
pbuf_free(q);
@@ -246,7 +246,7 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
#if IP_SOF_BROADCAST
/* broadcast filter? */
if ( ((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(ipaddr, netif) ) {
- LWIP_DEBUGF(RAW_DEBUG | 1, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
+ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
/* free any temporary header pbuf allocated by pbuf_header() */
if (q != p) {
pbuf_free(q);
@@ -335,7 +335,7 @@ struct raw_pcb *
raw_new(u8_t proto) {
struct raw_pcb *pcb;
- LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | 3, ("raw_new\n"));
+ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_new\n"));
pcb = memp_malloc(MEMP_RAW_PCB);
/* could allocate RAW PCB? */
diff --git a/net/lwip/src/core/snmp/mib2.c b/net/lwip/src/core/snmp/mib2.c
index 33eeee66cc..bc5830d65d 100644
--- a/net/lwip/src/core/snmp/mib2.c
+++ b/net/lwip/src/core/snmp/mib2.c
@@ -2077,25 +2077,25 @@ void snmp_get_snmpenableauthentraps(u8_t *value)
void
noleafs_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
{
- if (ident_len){}
- if (ident){}
+ LWIP_UNUSED_ARG(ident_len);
+ LWIP_UNUSED_ARG(ident);
od->instance = MIB_OBJECT_NONE;
}
void
noleafs_get_value(struct obj_def *od, u16_t len, void *value)
{
- if (od){}
- if (len){}
- if (value){}
+ LWIP_UNUSED_ARG(od);
+ LWIP_UNUSED_ARG(len);
+ LWIP_UNUSED_ARG(value);
}
u8_t
noleafs_set_test(struct obj_def *od, u16_t len, void *value)
{
- if (od){}
- if (len){}
- if (value){}
+ LWIP_UNUSED_ARG(od);
+ LWIP_UNUSED_ARG(len);
+ LWIP_UNUSED_ARG(value);
/* can't set */
return 0;
}
@@ -2103,9 +2103,9 @@ noleafs_set_test(struct obj_def *od, u16_t len, void *value)
void
noleafs_set_value(struct obj_def *od, u16_t len, void *value)
{
- if (od){}
- if (len){}
- if (value){}
+ LWIP_UNUSED_ARG(od);
+ LWIP_UNUSED_ARG(len);
+ LWIP_UNUSED_ARG(value);
}
@@ -2238,7 +2238,7 @@ system_set_test(struct obj_def *od, u16_t len, void *value)
{
u8_t id, set_ok;
- if (value) {}
+ LWIP_UNUSED_ARG(value);
set_ok = 0;
id = od->id_inst_ptr[0];
switch (id)
@@ -2332,7 +2332,7 @@ interfaces_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
static void
interfaces_get_value(struct obj_def *od, u16_t len, void *value)
{
- if (len){}
+ LWIP_UNUSED_ARG(len);
if (od->id_inst_ptr[0] == 1)
{
s32_t *sint_ptr = value;
@@ -2724,7 +2724,8 @@ atentry_get_value(struct obj_def *od, u16_t len, void *value)
struct ip_addr ip;
struct netif *netif;
- if (len) {}
+ LWIP_UNUSED_ARG(len);
+ LWIP_UNUSED_ARG(value);/* if !LWIP_ARP */
snmp_ifindextonetif(od->id_inst_ptr[1], &netif);
snmp_oidtoip(&od->id_inst_ptr[2], &ip);
@@ -2831,7 +2832,7 @@ ip_get_value(struct obj_def *od, u16_t len, void *value)
{
u8_t id;
- if (len) {}
+ LWIP_UNUSED_ARG(len);
id = od->id_inst_ptr[0];
switch (id)
{
@@ -2985,7 +2986,7 @@ ip_set_test(struct obj_def *od, u16_t len, void *value)
u8_t id, set_ok;
s32_t *sint_ptr = value;
- if (len) {}
+ LWIP_UNUSED_ARG(len);
set_ok = 0;
id = od->id_inst_ptr[0];
switch (id)
@@ -3065,7 +3066,7 @@ ip_addrentry_get_value(struct obj_def *od, u16_t len, void *value)
struct ip_addr ip;
struct netif *netif = netif_list;
- if (len) {}
+ LWIP_UNUSED_ARG(len);
snmp_oidtoip(&od->id_inst_ptr[1], &ip);
ip.addr = htonl(ip.addr);
ifidx = 0;
@@ -3408,7 +3409,8 @@ ip_ntomentry_get_value(struct obj_def *od, u16_t len, void *value)
struct ip_addr ip;
struct netif *netif;
- if (len) {}
+ LWIP_UNUSED_ARG(len);
+ LWIP_UNUSED_ARG(value);/* if !LWIP_ARP */
snmp_ifindextonetif(od->id_inst_ptr[1], &netif);
snmp_oidtoip(&od->id_inst_ptr[2], &ip);
@@ -3482,7 +3484,7 @@ icmp_get_value(struct obj_def *od, u16_t len, void *value)
u32_t *uint_ptr = value;
u8_t id;
- if (len){}
+ LWIP_UNUSED_ARG(len);
id = od->id_inst_ptr[0];
switch (id)
{
@@ -3636,7 +3638,7 @@ tcp_get_value(struct obj_def *od, u16_t len, void *value)
s32_t *sint_ptr = value;
u8_t id;
- if (len){}
+ LWIP_UNUSED_ARG(len);
id = od->id_inst_ptr[0];
switch (id)
{
@@ -3804,7 +3806,7 @@ udp_get_value(struct obj_def *od, u16_t len, void *value)
u32_t *uint_ptr = value;
u8_t id;
- if (len){}
+ LWIP_UNUSED_ARG(len);
id = od->id_inst_ptr[0];
switch (id)
{
@@ -3870,7 +3872,7 @@ udpentry_get_value(struct obj_def *od, u16_t len, void *value)
struct ip_addr ip;
u16_t port;
- if (len){}
+ LWIP_UNUSED_ARG(len);
snmp_oidtoip(&od->id_inst_ptr[1], &ip);
ip.addr = htonl(ip.addr);
port = od->id_inst_ptr[5];
@@ -3977,7 +3979,7 @@ snmp_get_value(struct obj_def *od, u16_t len, void *value)
u32_t *uint_ptr = value;
u8_t id;
- if (len){}
+ LWIP_UNUSED_ARG(len);
id = od->id_inst_ptr[0];
switch (id)
{
@@ -4080,7 +4082,7 @@ snmp_set_test(struct obj_def *od, u16_t len, void *value)
{
u8_t id, set_ok;
- if (len) {}
+ LWIP_UNUSED_ARG(len);
set_ok = 0;
id = od->id_inst_ptr[0];
if (id == 30)
@@ -4113,7 +4115,7 @@ snmp_set_value(struct obj_def *od, u16_t len, void *value)
{
u8_t id;
- if (len) {}
+ LWIP_UNUSED_ARG(len);
id = od->id_inst_ptr[0];
if (id == 30)
{
diff --git a/net/lwip/src/core/snmp/mib_structs.c b/net/lwip/src/core/snmp/mib_structs.c
index af8994ed22..39a2949675 100644
--- a/net/lwip/src/core/snmp/mib_structs.c
+++ b/net/lwip/src/core/snmp/mib_structs.c
@@ -118,7 +118,7 @@ snmp_netiftoifindex(struct netif *netif, s32_t *ifidx)
u16_t i;
i = 0;
- while (nif != netif)
+ while ((nif != NULL) && (nif != netif))
{
nif = nif->next;
i++;
diff --git a/net/lwip/src/core/sys.c b/net/lwip/src/core/sys.c
index d1fbda4e6c..cb5e86a7e6 100644
--- a/net/lwip/src/core/sys.c
+++ b/net/lwip/src/core/sys.c
@@ -97,7 +97,7 @@ sys_mbox_fetch(sys_mbox_t mbox, void **msg)
arg = tmptimeout->arg;
memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
if (h != NULL) {
- LWIP_DEBUGF(SYS_DEBUG, ("smf calling h=%p(%p)\n", (void*)&h, arg));
+ LWIP_DEBUGF(SYS_DEBUG, ("smf calling h=%p(%p)\n", *(void**)&h, arg));
h(arg);
}
@@ -154,7 +154,7 @@ sys_sem_wait(sys_sem_t sem)
arg = tmptimeout->arg;
memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
if (h != NULL) {
- LWIP_DEBUGF(SYS_DEBUG, ("ssw h=%p(%p)\n", (void*)&h, (void *)arg));
+ LWIP_DEBUGF(SYS_DEBUG, ("ssw h=%p(%p)\n", *(void**)&h, (void *)arg));
h(arg);
}
@@ -203,7 +203,7 @@ sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
timeouts = sys_arch_timeouts();
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));
if (timeouts == NULL) {
LWIP_ASSERT("sys_timeout: timeouts != NULL", timeouts != NULL);
@@ -264,13 +264,15 @@ sys_untimeout(sys_timeout_handler h, void *arg)
if ((t->h == h) && (t->arg == arg)) {
/* We have a match */
/* Unlink from previous in list */
- if (prev_t == NULL)
+ if (prev_t == NULL) {
timeouts->next = t->next;
- else
+ } else {
prev_t->next = t->next;
+ }
/* If not the last one, add time of this one back to next */
- if (t->next != NULL)
+ if (t->next != NULL) {
t->next->time += t->time;
+ }
memp_free(MEMP_SYS_TIMEOUT, t);
return;
}
diff --git a/net/lwip/src/core/tcp.c b/net/lwip/src/core/tcp.c
index 0f3fd41c3b..29cdf185d4 100644
--- a/net/lwip/src/core/tcp.c
+++ b/net/lwip/src/core/tcp.c
@@ -50,9 +50,24 @@
#include "lwip/snmp.h"
#include "lwip/tcp.h"
#include "lwip/debug.h"
+#include "lwip/stats.h"
#include <string.h>
+const char *tcp_state_str[] = {
+ "CLOSED",
+ "LISTEN",
+ "SYN_SENT",
+ "SYN_RCVD",
+ "ESTABLISHED",
+ "FIN_WAIT_1",
+ "FIN_WAIT_2",
+ "CLOSE_WAIT",
+ "CLOSING",
+ "LAST_ACK",
+ "TIME_WAIT"
+};
+
/* Incremented every coarse grained timer shot (typically every 500 ms). */
u32_t tcp_ticks;
const u8_t tcp_backoff[13] =
@@ -394,7 +409,7 @@ u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb)
{
u32_t new_right_edge = pcb->rcv_nxt + pcb->rcv_wnd;
- if (TCP_SEQ_GEQ(new_right_edge, pcb->rcv_ann_right_edge + pcb->mss)) {
+ if (TCP_SEQ_GEQ(new_right_edge, pcb->rcv_ann_right_edge + LWIP_MIN((TCP_WND / 2), pcb->mss))) {
/* we can advertise more window */
pcb->rcv_ann_wnd = pcb->rcv_wnd;
return new_right_edge - pcb->rcv_ann_right_edge;
@@ -564,6 +579,7 @@ tcp_slowtmr(void)
struct tcp_pcb *pcb, *pcb2, *prev;
u16_t eff_wnd;
u8_t pcb_remove; /* flag if a PCB should be removed */
+ u8_t pcb_reset; /* flag if a RST should be sent when removing */
err_t err;
err = ERR_OK;
@@ -583,6 +599,7 @@ tcp_slowtmr(void)
LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT);
pcb_remove = 0;
+ pcb_reset = 0;
if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) {
++pcb_remove;
@@ -666,7 +683,8 @@ tcp_slowtmr(void)
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
- tcp_abort(pcb);
+ ++pcb_remove;
+ ++pcb_reset;
}
#if LWIP_TCP_KEEPALIVE
else if((u32_t)(tcp_ticks - pcb->tmr) >
@@ -726,6 +744,10 @@ tcp_slowtmr(void)
}
TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_ABRT);
+ if (pcb_reset) {
+ tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,
+ pcb->local_port, pcb->remote_port);
+ }
pcb2 = pcb->next;
memp_free(MEMP_TCP_PCB, pcb);
@@ -899,11 +921,12 @@ tcp_seg_copy(struct tcp_seg *seg)
* Default receive callback that is called if the user didn't register
* a recv callback for the pcb.
*/
-static err_t
+err_t
tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
- arg = arg;
+ LWIP_UNUSED_ARG(arg);
if (p != NULL) {
+ tcp_recved(pcb, p->tot_len);
pbuf_free(p);
} else if (err == ERR_OK) {
return tcp_close(pcb);
@@ -993,9 +1016,18 @@ tcp_alloc(u8_t prio)
pcb = memp_malloc(MEMP_TCP_PCB);
if (pcb == NULL) {
/* Try killing active connections with lower priority than the new one. */
+ LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing connection with prio lower than %d\n", prio));
tcp_kill_prio(prio);
/* Try to allocate a tcp_pcb again. */
pcb = memp_malloc(MEMP_TCP_PCB);
+ if (pcb != NULL) {
+ /* adjust err stats: memp_malloc failed twice before */
+ MEMP_STATS_DEC(err, MEMP_TCP_PCB);
+ }
+ }
+ if (pcb != NULL) {
+ /* adjust err stats: timewait PCB was freed above */
+ MEMP_STATS_DEC(err, MEMP_TCP_PCB);
}
}
if (pcb != NULL) {
@@ -1218,7 +1250,7 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
* Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first.
*
* @param pcblist PCB list to purge.
- * @param pcb tcp_pcb to purge. The pcb itself is also deallocated!
+ * @param pcb tcp_pcb to purge. The pcb itself is NOT deallocated!
*/
void
tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb)
@@ -1288,6 +1320,12 @@ tcp_eff_send_mss(u16_t sendmss, struct ip_addr *addr)
}
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
+const char*
+tcp_debug_state_str(enum tcp_state s)
+{
+ return tcp_state_str[s];
+}
+
#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
/**
* Print a tcp header for debugging purposes.
@@ -1333,42 +1371,7 @@ tcp_debug_print(struct tcp_hdr *tcphdr)
void
tcp_debug_print_state(enum tcp_state s)
{
- LWIP_DEBUGF(TCP_DEBUG, ("State: "));
- switch (s) {
- case CLOSED:
- LWIP_DEBUGF(TCP_DEBUG, ("CLOSED\n"));
- break;
- case LISTEN:
- LWIP_DEBUGF(TCP_DEBUG, ("LISTEN\n"));
- break;
- case SYN_SENT:
- LWIP_DEBUGF(TCP_DEBUG, ("SYN_SENT\n"));
- break;
- case SYN_RCVD:
- LWIP_DEBUGF(TCP_DEBUG, ("SYN_RCVD\n"));
- break;
- case ESTABLISHED:
- LWIP_DEBUGF(TCP_DEBUG, ("ESTABLISHED\n"));
- break;
- case FIN_WAIT_1:
- LWIP_DEBUGF(TCP_DEBUG, ("FIN_WAIT_1\n"));
- break;
- case FIN_WAIT_2:
- LWIP_DEBUGF(TCP_DEBUG, ("FIN_WAIT_2\n"));
- break;
- case CLOSE_WAIT:
- LWIP_DEBUGF(TCP_DEBUG, ("CLOSE_WAIT\n"));
- break;
- case CLOSING:
- LWIP_DEBUGF(TCP_DEBUG, ("CLOSING\n"));
- break;
- case LAST_ACK:
- LWIP_DEBUGF(TCP_DEBUG, ("LAST_ACK\n"));
- break;
- case TIME_WAIT:
- LWIP_DEBUGF(TCP_DEBUG, ("TIME_WAIT\n"));
- break;
- }
+ LWIP_DEBUGF(TCP_DEBUG, ("State: %s\n", tcp_state_str[s]));
}
/**
diff --git a/net/lwip/src/core/tcp_in.c b/net/lwip/src/core/tcp_in.c
index 362a4a62d6..51e8775901 100644
--- a/net/lwip/src/core/tcp_in.c
+++ b/net/lwip/src/core/tcp_in.c
@@ -74,7 +74,7 @@ struct tcp_pcb *tcp_input_pcb;
/* Forward declarations. */
static err_t tcp_process(struct tcp_pcb *pcb);
-static u8_t tcp_receive(struct tcp_pcb *pcb);
+static void tcp_receive(struct tcp_pcb *pcb);
static void tcp_parseopt(struct tcp_pcb *pcb);
static err_t tcp_listen_input(struct tcp_pcb_listen *pcb);
@@ -288,10 +288,8 @@ tcp_input(struct pbuf *p, struct netif *inp)
return;
}
}
-
tcp_input_pcb = pcb;
err = tcp_process(pcb);
- tcp_input_pcb = NULL;
/* A return value of ERR_ABRT means that tcp_abort() was called
and that the pcb has been freed. If so, we don't do anything. */
if (err != ERR_ABRT) {
@@ -338,12 +336,17 @@ tcp_input(struct pbuf *p, struct netif *inp)
TCP_EVENT_RECV(pcb, NULL, ERR_OK, err);
}
- /* If there were no errors, we try to send something out. */
- if (err == ERR_OK) {
- tcp_output(pcb);
- }
+ tcp_input_pcb = NULL;
+ /* Try to send something out. */
+ tcp_output(pcb);
+#if TCP_INPUT_DEBUG
+#if TCP_DEBUG
+ tcp_debug_print_state(pcb->state);
+#endif /* TCP_DEBUG */
+#endif /* TCP_INPUT_DEBUG */
}
}
+ tcp_input_pcb = NULL;
/* give up our reference to inseg.p */
@@ -352,12 +355,6 @@ tcp_input(struct pbuf *p, struct netif *inp)
pbuf_free(inseg.p);
inseg.p = NULL;
}
-#if TCP_INPUT_DEBUG
-#if TCP_DEBUG
- tcp_debug_print_state(pcb->state);
-#endif /* TCP_DEBUG */
-#endif /* TCP_INPUT_DEBUG */
-
} else {
/* If no matching PCB was found, send a TCP RST (reset) to the
@@ -481,13 +478,36 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
static err_t
tcp_timewait_input(struct tcp_pcb *pcb)
{
- if (TCP_SEQ_GT(seqno + tcplen, pcb->rcv_nxt)) {
- pcb->rcv_nxt = seqno + tcplen;
+ /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */
+ /* RFC 793 3.9 Event Processing - Segment Arrives:
+ * - first check sequence number - we skip that one in TIME_WAIT (always
+ * acceptable since we only send ACKs)
+ * - second check the RST bit (... return) */
+ if (flags & TCP_RST) {
+ return ERR_OK;
}
- if (tcplen > 0) {
- tcp_ack_now(pcb);
+ /* - fourth, check the SYN bit, */
+ if (flags & TCP_SYN) {
+ /* If an incoming segment is not acceptable, an acknowledgment
+ should be sent in reply */
+ if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) {
+ /* If the SYN is in the window it is an error, send a reset */
+ tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
+ tcphdr->dest, tcphdr->src);
+ return ERR_OK;
+ }
+ } else if (flags & TCP_FIN) {
+ /* - eighth, check the FIN bit: Remain in the TIME-WAIT state.
+ Restart the 2 MSL time-wait timeout.*/
+ pcb->tmr = tcp_ticks;
}
- return tcp_output(pcb);
+
+ if ((tcplen > 0)) {
+ /* Acknowledge data, FIN or out-of-window SYN */
+ pcb->flags |= TF_ACK_NOW;
+ return tcp_output(pcb);
+ }
+ return ERR_OK;
}
/**
@@ -628,6 +648,11 @@ tcp_process(struct tcp_pcb *pcb)
* we'd better pass it on to the application as well. */
tcp_receive(pcb);
+ /* Prevent ACK for SYN to generate a sent event */
+ if (pcb->acked != 0) {
+ pcb->acked--;
+ }
+
pcb->cwnd = ((old_cwnd == 1) ? (pcb->mss * 2) : pcb->mss);
if (recv_flags & TF_GOT_FIN) {
@@ -660,7 +685,7 @@ tcp_process(struct tcp_pcb *pcb)
if (recv_flags & TF_GOT_FIN) {
if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {
LWIP_DEBUGF(TCP_DEBUG,
- ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
+ ("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
tcp_ack_now(pcb);
tcp_pcb_purge(pcb);
TCP_RMV(&tcp_active_pcbs, pcb);
@@ -677,7 +702,7 @@ tcp_process(struct tcp_pcb *pcb)
case FIN_WAIT_2:
tcp_receive(pcb);
if (recv_flags & TF_GOT_FIN) {
- LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
+ LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: FIN_WAIT_2 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
tcp_ack_now(pcb);
tcp_pcb_purge(pcb);
TCP_RMV(&tcp_active_pcbs, pcb);
@@ -688,7 +713,7 @@ tcp_process(struct tcp_pcb *pcb)
case CLOSING:
tcp_receive(pcb);
if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
- LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
+ LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
tcp_pcb_purge(pcb);
TCP_RMV(&tcp_active_pcbs, pcb);
pcb->state = TIME_WAIT;
@@ -698,7 +723,7 @@ tcp_process(struct tcp_pcb *pcb)
case LAST_ACK:
tcp_receive(pcb);
if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
- LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
+ LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
/* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */
recv_flags |= TF_CLOSED;
}
@@ -709,6 +734,47 @@ tcp_process(struct tcp_pcb *pcb)
return ERR_OK;
}
+#if TCP_QUEUE_OOSEQ
+/**
+ * Insert segment into the list (segments covered with new one will be deleted)
+ *
+ * Called from tcp_receive()
+ */
+static void
+tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next)
+{
+ struct tcp_seg *old_seg;
+
+ if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
+ /* received segment overlaps all following segments */
+ tcp_segs_free(next);
+ next = NULL;
+ }
+ else {
+ /* delete some following segments
+ oos queue may have segments with FIN flag */
+ while (next &&
+ TCP_SEQ_GEQ((seqno + cseg->len),
+ (next->tcphdr->seqno + next->len))) {
+ /* cseg with FIN already processed */
+ if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
+ TCPH_FLAGS_SET(cseg->tcphdr, TCPH_FLAGS(cseg->tcphdr) | TCP_FIN);
+ }
+ old_seg = next;
+ next = next->next;
+ tcp_seg_free(old_seg);
+ }
+ if (next &&
+ TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) {
+ /* We need to trim the incoming segment. */
+ cseg->len = (u16_t)(next->tcphdr->seqno - seqno);
+ pbuf_realloc(cseg->p, cseg->len);
+ }
+ }
+ cseg->next = next;
+}
+#endif
+
/**
* Called by tcp_process. Checks if the given segment is an ACK for outstanding
* data, and if so frees the memory of the buffered data. Next, is places the
@@ -720,10 +786,8 @@ tcp_process(struct tcp_pcb *pcb)
* estimation, the RTT is estimated here as well.
*
* Called from tcp_process().
- *
- * @return 1 if the incoming segment is the next in sequence, 0 if not
*/
-static u8_t
+static void
tcp_receive(struct tcp_pcb *pcb)
{
struct tcp_seg *next;
@@ -735,7 +799,7 @@ tcp_receive(struct tcp_pcb *pcb)
s16_t m;
u32_t right_wnd_edge;
u16_t new_tot_len;
- u8_t accepted_inseq = 0;
+ int found_dupack = 0;
if (flags & TCP_ACK) {
right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2;
@@ -762,51 +826,62 @@ tcp_receive(struct tcp_pcb *pcb)
#endif /* TCP_WND_DEBUG */
}
- if (pcb->lastack == ackno) {
- pcb->acked = 0;
-
- if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge){
- ++pcb->dupacks;
- if (pcb->dupacks >= 3 && pcb->unacked != NULL) {
- if (!(pcb->flags & TF_INFR)) {
- /* This is fast retransmit. Retransmit the first unacked segment. */
- LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupacks %"U16_F" (%"U32_F"), fast retransmit %"U32_F"\n",
- (u16_t)pcb->dupacks, pcb->lastack,
- ntohl(pcb->unacked->tcphdr->seqno)));
- tcp_rexmit(pcb);
- /* Set ssthresh to max (FlightSize / 2, 2*SMSS) */
- /*pcb->ssthresh = LWIP_MAX((pcb->snd_max -
- pcb->lastack) / 2,
- 2 * pcb->mss);*/
- /* Set ssthresh to half of the minimum of the current cwnd and the advertised window */
- if (pcb->cwnd > pcb->snd_wnd)
- pcb->ssthresh = pcb->snd_wnd / 2;
- else
- pcb->ssthresh = pcb->cwnd / 2;
-
- /* The minimum value for ssthresh should be 2 MSS */
- if (pcb->ssthresh < 2*pcb->mss) {
- LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: The minimum value for ssthresh %"U16_F" should be min 2 mss %"U16_F"...\n", pcb->ssthresh, 2*pcb->mss));
- pcb->ssthresh = 2*pcb->mss;
- }
+ /* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a
+ * duplicate ack if:
+ * 1) It doesn't ACK new data
+ * 2) length of received packet is zero (i.e. no payload)
+ * 3) the advertised window hasn't changed
+ * 4) There is outstanding unacknowledged data (retransmission timer running)
+ * 5) The ACK is == biggest ACK sequence number so far seen (snd_una)
+ *
+ * If it passes all five, should process as a dupack:
+ * a) dupacks < 3: do nothing
+ * b) dupacks == 3: fast retransmit
+ * c) dupacks > 3: increase cwnd
+ *
+ * If it only passes 1-3, should reset dupack counter (and add to
+ * stats, which we don't do in lwIP)
+ *
+ * If it only passes 1, should reset dupack counter
+ *
+ */
- pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
- pcb->flags |= TF_INFR;
- } else {
- /* Inflate the congestion window, but not if it means that
- the value overflows. */
- if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
- pcb->cwnd += pcb->mss;
+ /* Clause 1 */
+ if (TCP_SEQ_LEQ(ackno, pcb->lastack)) {
+ pcb->acked = 0;
+ /* Clause 2 */
+ if (tcplen == 0) {
+ /* Clause 3 */
+ if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge){
+ /* Clause 4 */
+ if (pcb->rtime >= 0) {
+ /* Clause 5 */
+ if (pcb->lastack == ackno) {
+ found_dupack = 1;
+ if (pcb->dupacks + 1 > pcb->dupacks)
+ ++pcb->dupacks;
+ if (pcb->dupacks > 3) {
+ /* Inflate the congestion window, but not if it means that
+ the value overflows. */
+ if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
+ pcb->cwnd += pcb->mss;
+ }
+ } else if (pcb->dupacks == 3) {
+ /* Do fast retransmit */
+ tcp_rexmit_fast(pcb);
+ }
}
}
}
- } else {
- LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupack averted %"U32_F" %"U32_F"\n",
- pcb->snd_wl2 + pcb->snd_wnd, right_wnd_edge));
+ }
+ /* If Clause (1) or more is true, but not a duplicate ack, reset
+ * count of consecutive duplicate acks */
+ if (!found_dupack) {
+ pcb->dupacks = 0;
}
} else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){
/* We come here when the ACK acknowledges new data. */
-
+
/* Reset the "IN Fast Retransmit" flag, since we are no longer
in fast retransmit. Also reset the congestion window to the
slow start threshold. */
@@ -868,6 +943,11 @@ tcp_receive(struct tcp_pcb *pcb)
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
+ /* Prevent ACK for FIN to generate a sent event */
+ if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) {
+ pcb->acked--;
+ }
+
pcb->snd_queuelen -= pbuf_clen(next->p);
tcp_seg_free(next);
@@ -908,6 +988,10 @@ tcp_receive(struct tcp_pcb *pcb)
pcb->unsent = pcb->unsent->next;
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
+ /* Prevent ACK for FIN to generate a sent event */
+ if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) {
+ pcb->acked--;
+ }
pcb->snd_queuelen -= pbuf_clen(next->p);
tcp_seg_free(next);
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unsent)\n", (u16_t)pcb->snd_queuelen));
@@ -1051,7 +1135,6 @@ tcp_receive(struct tcp_pcb *pcb)
if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
pcb->rcv_nxt + pcb->rcv_wnd - 1)){
if (pcb->rcv_nxt == seqno) {
- accepted_inseq = 1;
/* The incoming segment is the next in sequence. We check if
we have to trim the end of the segment and update rcv_nxt
and pass the data to the application. */
@@ -1084,17 +1167,45 @@ tcp_receive(struct tcp_pcb *pcb)
("tcp_receive: received in-order FIN, binning ooseq queue\n"));
/* Received in-order FIN means anything that was received
* out of order must now have been received in-order, so
- * bin the ooseq queue */
+ * bin the ooseq queue
+ * rcv_nxt
+ * . |--ooseq--|
+ * .==seg============|FIN
+ */
while (pcb->ooseq != NULL) {
struct tcp_seg *old_ooseq = pcb->ooseq;
pcb->ooseq = pcb->ooseq->next;
- memp_free(MEMP_TCP_SEG, old_ooseq);
+ tcp_seg_free(old_ooseq);
}
- } else if (TCP_SEQ_LEQ(pcb->ooseq->tcphdr->seqno, seqno + tcplen)) {
- if (pcb->ooseq->len > 0) {
- /* We have to trim the second edge of the incoming segment. */
- LWIP_ASSERT("tcp_receive: trimmed segment would have zero length\n",
- TCP_SEQ_GT(pcb->ooseq->tcphdr->seqno, seqno));
+ }
+ else {
+ struct tcp_seg* next = pcb->ooseq;
+ struct tcp_seg *old_seg;
+ /* rcv_nxt
+ * . |--ooseq--|
+ * .==seg============|
+ */
+ while (next &&
+ TCP_SEQ_GEQ(seqno + tcplen,
+ next->tcphdr->seqno + next->len)) {
+ /* inseg doesn't have FIN (already processed) */
+ if (TCPH_FLAGS(next->tcphdr) & TCP_FIN &&
+ (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) {
+ TCPH_FLAGS_SET(inseg.tcphdr,
+ TCPH_FLAGS(inseg.tcphdr) | TCP_FIN);
+ tcplen = TCP_TCPLEN(&inseg);
+ }
+ old_seg = next;
+ next = next->next;
+ tcp_seg_free(old_seg);
+ }
+ /* rcv_nxt
+ * . |--ooseq--|
+ * .==seg============|
+ */
+ if (next &&
+ TCP_SEQ_GT(seqno + tcplen,
+ next->tcphdr->seqno)) {
/* FIN in inseg already handled by dropping whole ooseq queue */
inseg.len = (u16_t)(pcb->ooseq->tcphdr->seqno - seqno);
if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
@@ -1104,15 +1215,8 @@ tcp_receive(struct tcp_pcb *pcb)
tcplen = TCP_TCPLEN(&inseg);
LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n",
(seqno + tcplen) == pcb->ooseq->tcphdr->seqno);
- } else {
- /* does the ooseq segment contain only flags that are in inseg also? */
- if ((TCPH_FLAGS(inseg.tcphdr) & (TCP_FIN|TCP_SYN)) ==
- (TCPH_FLAGS(pcb->ooseq->tcphdr) & (TCP_FIN|TCP_SYN))) {
- struct tcp_seg *old_ooseq = pcb->ooseq;
- pcb->ooseq = pcb->ooseq->next;
- memp_free(MEMP_TCP_SEG, old_ooseq);
- }
}
+ pcb->ooseq = next;
}
}
#endif /* TCP_QUEUE_OOSEQ */
@@ -1180,7 +1284,6 @@ tcp_receive(struct tcp_pcb *pcb)
}
}
-
pcb->ooseq = cseg->next;
tcp_seg_free(cseg);
}
@@ -1192,7 +1295,7 @@ tcp_receive(struct tcp_pcb *pcb)
} else {
/* We get here if the incoming segment is out-of-sequence. */
- tcp_ack_now(pcb);
+ tcp_send_empty_ack(pcb);
#if TCP_QUEUE_OOSEQ
/* We queue the segment on the ->ooseq queue. */
if (pcb->ooseq == NULL) {
@@ -1219,25 +1322,16 @@ tcp_receive(struct tcp_pcb *pcb)
discard. */
if (inseg.len > next->len) {
/* The incoming segment is larger than the old
- segment. We replace the old segment with the new
+ segment. We replace some segments with the new
one. */
cseg = tcp_seg_copy(&inseg);
if (cseg != NULL) {
- cseg->next = next->next;
if (prev != NULL) {
prev->next = cseg;
} else {
pcb->ooseq = cseg;
}
- tcp_seg_free(next);
- if (cseg->next != NULL) {
- next = cseg->next;
- if (TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) {
- /* We need to trim the incoming segment. */
- cseg->len = (u16_t)(next->tcphdr->seqno - seqno);
- pbuf_realloc(cseg->p, cseg->len);
- }
- }
+ tcp_oos_insert_segment(cseg, next);
}
break;
} else {
@@ -1253,51 +1347,44 @@ tcp_receive(struct tcp_pcb *pcb)
than the sequence number of the first segment on the
queue. We put the incoming segment first on the
queue. */
-
- if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) {
- /* We need to trim the incoming segment. */
- inseg.len = (u16_t)(next->tcphdr->seqno - seqno);
- pbuf_realloc(inseg.p, inseg.len);
- }
cseg = tcp_seg_copy(&inseg);
if (cseg != NULL) {
- cseg->next = next;
pcb->ooseq = cseg;
+ tcp_oos_insert_segment(cseg, next);
}
break;
}
- } else
+ } else {
/*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) &&
TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/
- if(TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)){
- /* The sequence number of the incoming segment is in
- between the sequence numbers of the previous and
- the next segment on ->ooseq. We trim and insert the
- incoming segment and trim the previous segment, if
- needed. */
- if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) {
- /* We need to trim the incoming segment. */
- inseg.len = (u16_t)(next->tcphdr->seqno - seqno);
- pbuf_realloc(inseg.p, inseg.len);
- }
-
- cseg = tcp_seg_copy(&inseg);
- if (cseg != NULL) {
- cseg->next = next;
- prev->next = cseg;
- if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) {
- /* We need to trim the prev segment. */
- prev->len = (u16_t)(seqno - prev->tcphdr->seqno);
- pbuf_realloc(prev->p, prev->len);
+ if (TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)) {
+ /* The sequence number of the incoming segment is in
+ between the sequence numbers of the previous and
+ the next segment on ->ooseq. We trim trim the previous
+ segment, delete next segments that included in received segment
+ and trim received, if needed. */
+ cseg = tcp_seg_copy(&inseg);
+ if (cseg != NULL) {
+ if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) {
+ /* We need to trim the prev segment. */
+ prev->len = (u16_t)(seqno - prev->tcphdr->seqno);
+ pbuf_realloc(prev->p, prev->len);
+ }
+ prev->next = cseg;
+ tcp_oos_insert_segment(cseg, next);
}
+ break;
}
- break;
}
/* If the "next" segment is the last segment on the
ooseq queue, we add the incoming segment to the end
of the list. */
if (next->next == NULL &&
TCP_SEQ_GT(seqno, next->tcphdr->seqno)) {
+ if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
+ /* segment "next" already contains all data */
+ break;
+ }
next->next = tcp_seg_copy(&inseg);
if (next->next != NULL) {
if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) {
@@ -1316,7 +1403,8 @@ tcp_receive(struct tcp_pcb *pcb)
}
} else {
- tcp_ack_now(pcb);
+ /* The incoming segment is not withing the window. */
+ tcp_send_empty_ack(pcb);
}
} else {
/* Segments with length 0 is taken care of here. Segments that
@@ -1327,7 +1415,6 @@ tcp_receive(struct tcp_pcb *pcb)
tcp_ack_now(pcb);
}
}
- return accepted_inseq;
}
/**
diff --git a/net/lwip/src/core/tcp_out.c b/net/lwip/src/core/tcp_out.c
index ca72d9dcc5..ddada4204a 100644
--- a/net/lwip/src/core/tcp_out.c
+++ b/net/lwip/src/core/tcp_out.c
@@ -132,7 +132,7 @@ tcp_write(struct tcp_pcb *pcb, const void *data, u16_t len, u8_t apiflags)
}
return ERR_OK;
} else {
- LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | 3, ("tcp_write() called in invalid state\n"));
+ LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n"));
return ERR_CONN;
}
}
@@ -174,7 +174,8 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
/* fail on too much data */
if (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));
+ LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_WARNING,
+ ("tcp_enqueue: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n", len, pcb->snd_buf));
pcb->flags |= TF_NAGLEMEMERR;
return ERR_MEM;
}
@@ -194,7 +195,8 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
queuelen = pcb->snd_queuelen;
/* check for configured max queuelen and possible overflow */
if ((queuelen >= TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
- LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too long queue %"U16_F" (max %"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
+ LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_WARNING,
+ ("tcp_enqueue: too long queue %"U16_F" (max %"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
TCP_STATS_INC(tcp.memerr);
pcb->flags |= TF_NAGLEMEMERR;
return ERR_MEM;
@@ -218,7 +220,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
/* Allocate memory for tcp_seg, and fill in fields. */
seg = memp_malloc(MEMP_TCP_SEG);
if (seg == NULL) {
- LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2,
+ LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
("tcp_enqueue: could not allocate memory for tcp_seg\n"));
goto memerr;
}
@@ -243,7 +245,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
* ROM or other static memory, and need not be copied. */
if (apiflags & TCP_WRITE_FLAG_COPY) {
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen + optlen, PBUF_RAM)) == NULL) {
- LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2,
+ LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
("tcp_enqueue : could not allocate memory for pbuf copy size %"U16_F"\n", seglen));
goto memerr;
}
@@ -259,7 +261,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
else {
/* First, allocate a pbuf for the headers. */
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
- LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2,
+ LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
("tcp_enqueue: could not allocate memory for header pbuf\n"));
goto memerr;
}
@@ -275,7 +277,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
/* If allocation fails, we have to deallocate the header pbuf as well. */
pbuf_free(seg->p);
seg->p = NULL;
- LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2,
+ LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
("tcp_enqueue: could not allocate memory for zero-copy pbuf\n"));
goto memerr;
}
@@ -293,7 +295,8 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
/* Now that there are more segments queued, we check again if the
length of the queue exceeds the configured maximum or overflows. */
if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
- LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
+ LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
+ ("tcp_enqueue: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
goto memerr;
}
@@ -301,7 +304,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
/* build TCP header */
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 | LWIP_DBG_LEVEL_SERIOUS, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
TCP_STATS_INC(tcp.err);
goto memerr;
}
@@ -343,11 +346,13 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
if (useg != NULL &&
TCP_TCPLEN(useg) != 0 &&
!(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) &&
- !(flags & (TCP_SYN | TCP_FIN)) &&
+ (!(flags & (TCP_SYN | TCP_FIN)) || (flags == TCP_FIN)) &&
/* fit within max seg size */
(useg->len + queue->len <= pcb->mss) &&
/* only concatenate segments with the same options */
- (useg->flags == queue->flags)) {
+ (useg->flags == queue->flags) &&
+ /* segments are consecutive */
+ (ntohl(useg->tcphdr->seqno) + useg->len == ntohl(queue->tcphdr->seqno)) ) {
/* Remove TCP header from first segment of our to-be-queued list */
if(pbuf_header(queue->p, -(TCP_HLEN + optlen))) {
/* Can we cope with this failing? Just assert for now */
@@ -363,10 +368,16 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
queuelen--;
pbuf_free(old_q);
}
- LWIP_ASSERT("zero-length pbuf", (queue->p != NULL) && (queue->p->len > 0));
- pbuf_cat(useg->p, queue->p);
- useg->len += queue->len;
- useg->next = queue->next;
+ if (flags & TCP_FIN) {
+ /* the new segment contains only FIN, no data -> put the FIN into the last segment */
+ LWIP_ASSERT("FIN enqueued together with data", queue->p == NULL && queue->len == 0);
+ TCPH_SET_FLAG(useg->tcphdr, TCP_FIN);
+ } else {
+ LWIP_ASSERT("zero-length pbuf", (queue->p != NULL) && (queue->p->len > 0));
+ pbuf_cat(useg->p, queue->p);
+ useg->len += queue->len;
+ useg->next = queue->next;
+ }
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("tcp_enqueue: chaining segments, new len %"U16_F"\n", useg->len));
if (seg == queue) {
@@ -443,6 +454,58 @@ tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts)
}
#endif
+/** Send an ACK without data.
+ *
+ * @param pcb Protocol control block for the TCP connection to send the ACK
+ */
+err_t
+tcp_send_empty_ack(struct tcp_pcb *pcb)
+{
+ struct pbuf *p;
+ struct tcp_hdr *tcphdr;
+ u8_t optlen = 0;
+
+#if LWIP_TCP_TIMESTAMPS
+ if (pcb->flags & TF_TIMESTAMP) {
+ optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
+ }
+#endif
+ p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen, PBUF_RAM);
+ if (p == NULL) {
+ LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
+ return ERR_BUF;
+ }
+ 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 = tcp_output_set_header(pcb, p, optlen, htonl(pcb->snd_nxt));
+
+ /* NB. MSS option is only sent on SYNs, so ignore it here */
+#if LWIP_TCP_TIMESTAMPS
+ pcb->ts_lastacksent = pcb->rcv_nxt;
+
+ if (pcb->flags & TF_TIMESTAMP) {
+ tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1));
+ }
+#endif
+
+#if CHECKSUM_GEN_TCP
+ tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
+ IP_PROTO_TCP, p->tot_len);
+#endif
+#if LWIP_NETIF_HWADDRHINT
+ ip_output_hinted(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
+ IP_PROTO_TCP, &(pcb->addr_hint));
+#else /* LWIP_NETIF_HWADDRHINT*/
+ ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
+ IP_PROTO_TCP);
+#endif /* LWIP_NETIF_HWADDRHINT*/
+ pbuf_free(p);
+
+ return ERR_OK;
+}
/**
* Find out what we can send and send it
@@ -454,14 +517,11 @@ tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts)
err_t
tcp_output(struct tcp_pcb *pcb)
{
- struct pbuf *p;
- struct tcp_hdr *tcphdr;
struct tcp_seg *seg, *useg;
u32_t wnd, snd_nxt;
#if TCP_CWND_DEBUG
s16_t i = 0;
#endif /* TCP_CWND_DEBUG */
- u8_t optlen = 0;
/* First, check if we are invoked by the TCP input processing
code. If so, we do not output anything. Instead, we rely on the
@@ -475,12 +535,6 @@ tcp_output(struct tcp_pcb *pcb)
seg = pcb->unsent;
- /* useg should point to last segment on unacked queue */
- useg = pcb->unacked;
- if (useg != NULL) {
- for (; useg->next != NULL; useg = useg->next);
- }
-
/* If the TF_ACK_NOW flag is set and no data will be sent (either
* because the ->unsent queue is empty or because the window does
* not allow it), construct an empty ACK segment and send it.
@@ -490,44 +544,13 @@ tcp_output(struct tcp_pcb *pcb)
if (pcb->flags & TF_ACK_NOW &&
(seg == NULL ||
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
-#if LWIP_TCP_TIMESTAMPS
- if (pcb->flags & TF_TIMESTAMP)
- optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
-#endif
- p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen, PBUF_RAM);
- if (p == NULL) {
- LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
- return ERR_BUF;
- }
- 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 = tcp_output_set_header(pcb, p, optlen, htonl(pcb->snd_nxt));
-
- /* NB. MSS option is only sent on SYNs, so ignore it here */
-#if LWIP_TCP_TIMESTAMPS
- pcb->ts_lastacksent = pcb->rcv_nxt;
-
- if (pcb->flags & TF_TIMESTAMP)
- tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1));
-#endif
-
-#if CHECKSUM_GEN_TCP
- tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
- IP_PROTO_TCP, p->tot_len);
-#endif
-#if LWIP_NETIF_HWADDRHINT
- ip_output_hinted(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
- IP_PROTO_TCP, &(pcb->addr_hint));
-#else /* LWIP_NETIF_HWADDRHINT*/
- ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
- IP_PROTO_TCP);
-#endif /* LWIP_NETIF_HWADDRHINT*/
- pbuf_free(p);
+ return tcp_send_empty_ack(pcb);
+ }
- return ERR_OK;
+ /* useg should point to last segment on unacked queue */
+ useg = pcb->unacked;
+ if (useg != NULL) {
+ for (; useg->next != NULL; useg = useg->next);
}
#if TCP_OUTPUT_DEBUG
@@ -853,9 +876,50 @@ tcp_rexmit(struct tcp_pcb *pcb)
/* Do the actual retransmission. */
snmp_inc_tcpretranssegs();
- tcp_output(pcb);
+ /* No need to call tcp_output: we are always called from tcp_input()
+ and thus tcp_output directly returns. */
+}
+
+
+/**
+ * Handle retransmission after three dupacks received
+ *
+ * @param pcb the tcp_pcb for which to retransmit the first unacked segment
+ */
+void
+tcp_rexmit_fast(struct tcp_pcb *pcb)
+{
+ if (pcb->unacked != NULL && !(pcb->flags & TF_INFR)) {
+ /* This is fast retransmit. Retransmit the first unacked segment. */
+ LWIP_DEBUGF(TCP_FR_DEBUG,
+ ("tcp_receive: dupacks %"U16_F" (%"U32_F
+ "), fast retransmit %"U32_F"\n",
+ (u16_t)pcb->dupacks, pcb->lastack,
+ ntohl(pcb->unacked->tcphdr->seqno)));
+ tcp_rexmit(pcb);
+
+ /* Set ssthresh to half of the minimum of the current
+ * cwnd and the advertised window */
+ if (pcb->cwnd > pcb->snd_wnd)
+ pcb->ssthresh = pcb->snd_wnd / 2;
+ else
+ pcb->ssthresh = pcb->cwnd / 2;
+
+ /* The minimum value for ssthresh should be 2 MSS */
+ if (pcb->ssthresh < 2*pcb->mss) {
+ LWIP_DEBUGF(TCP_FR_DEBUG,
+ ("tcp_receive: The minimum value for ssthresh %"U16_F
+ " should be min 2 mss %"U16_F"...\n",
+ pcb->ssthresh, 2*pcb->mss));
+ pcb->ssthresh = 2*pcb->mss;
+ }
+
+ pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
+ pcb->flags |= TF_INFR;
+ }
}
+
/**
* Send keepalive packets to keep a connection active although
* no data is sent over it.
@@ -924,6 +988,8 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
struct pbuf *p;
struct tcp_hdr *tcphdr;
struct tcp_seg *seg;
+ u16_t len;
+ u8_t is_fin;
LWIP_DEBUGF(TCP_DEBUG,
("tcp_zero_window_probe: sending ZERO WINDOW probe to %"
@@ -944,8 +1010,10 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
if(seg == NULL)
return;
- p = pbuf_alloc(PBUF_IP, TCP_HLEN + 1, PBUF_RAM);
-
+ is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0);
+ len = is_fin ? TCP_HLEN : TCP_HLEN + 1;
+
+ p = pbuf_alloc(PBUF_IP, len, PBUF_RAM);
if(p == NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n"));
return;
@@ -955,8 +1023,13 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
tcphdr = tcp_output_set_header(pcb, p, 0, seg->tcphdr->seqno);
- /* Copy in one byte from the head of the unacked queue */
- *((char *)p->payload + sizeof(struct tcp_hdr)) = *(char *)seg->dataptr;
+ if (is_fin) {
+ /* FIN segment, no data */
+ TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN);
+ } else {
+ /* Data segment, copy in one byte from the head of the unacked queue */
+ *((char *)p->payload + sizeof(struct tcp_hdr)) = *(char *)seg->dataptr;
+ }
#if CHECKSUM_GEN_TCP
tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip,
diff --git a/net/lwip/src/core/udp.c b/net/lwip/src/core/udp.c
index d8d644d44c..96dab41b95 100644
--- a/net/lwip/src/core/udp.c
+++ b/net/lwip/src/core/udp.c
@@ -241,8 +241,8 @@ udp_input(struct pbuf *p, struct netif *inp)
if (inet_chksum_pseudo_partial(p, (struct ip_addr *)&(iphdr->src),
(struct ip_addr *)&(iphdr->dest),
IP_PROTO_UDPLITE, p->tot_len, chklen) != 0) {
- LWIP_DEBUGF(UDP_DEBUG | 2,
- ("udp_input: UDP Lite datagram discarded due to failing checksum\n"));
+ LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
+ ("udp_input: UDP Lite datagram discarded due to failing checksum\n"));
UDP_STATS_INC(udp.chkerr);
UDP_STATS_INC(udp.drop);
snmp_inc_udpinerrors();
@@ -258,7 +258,7 @@ udp_input(struct pbuf *p, struct netif *inp)
if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
(struct ip_addr *)&(iphdr->dest),
IP_PROTO_UDP, p->tot_len) != 0) {
- LWIP_DEBUGF(UDP_DEBUG | 2,
+ LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
("udp_input: UDP datagram discarded due to failing checksum\n"));
UDP_STATS_INC(udp.chkerr);
UDP_STATS_INC(udp.drop);
@@ -282,7 +282,7 @@ udp_input(struct pbuf *p, struct netif *inp)
/* callback */
if (pcb->recv != NULL) {
/* now the recv function is responsible for freeing p */
- pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src), src);
+ pcb->recv(pcb->recv_arg, pcb, p, &iphdr->src, src);
} else {
/* no recv function registered? then we have to free the pbuf! */
pbuf_free(p);
@@ -362,7 +362,7 @@ udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
{
struct netif *netif;
- LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | 3, ("udp_send\n"));
+ LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n"));
/* find the outgoing network interface for this packet */
#if LWIP_IGMP
@@ -373,7 +373,7 @@ udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
/* no outgoing network interface could be found? */
if (netif == NULL) {
- LWIP_DEBUGF(UDP_DEBUG | 1, ("udp_send: No route to 0x%"X32_F"\n", dst_ip->addr));
+ LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: No route to 0x%"X32_F"\n", dst_ip->addr));
UDP_STATS_INC(udp.rterr);
return ERR_RTE;
}
@@ -411,17 +411,18 @@ udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
#if IP_SOF_BROADCAST
/* broadcast filter? */
if ( ((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(dst_ip, netif) ) {
- LWIP_DEBUGF(UDP_DEBUG | 1, ("udp_sendto_if: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
+ LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
+ ("udp_sendto_if: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
return ERR_VAL;
}
#endif /* IP_SOF_BROADCAST */
/* if the PCB is not yet bound to a port, bind it here */
if (pcb->local_port == 0) {
- LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | 2, ("udp_send: not yet bound to a port, binding now\n"));
+ LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send: not yet bound to a port, binding now\n"));
err = udp_bind(pcb, &pcb->local_ip, pcb->local_port);
if (err != ERR_OK) {
- LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | 2, ("udp_send: forced port bind failed\n"));
+ LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: forced port bind failed\n"));
return err;
}
}
@@ -432,7 +433,7 @@ udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
q = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM);
/* new header pbuf could not be allocated? */
if (q == NULL) {
- LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | 2, ("udp_send: could not allocate header\n"));
+ LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: could not allocate header\n"));
return ERR_MEM;
}
/* chain header q in front of given pbuf p */
@@ -580,9 +581,9 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
struct udp_pcb *ipcb;
u8_t rebind;
- LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | 3, ("udp_bind(ipaddr = "));
+ LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_bind(ipaddr = "));
ip_addr_debug_print(UDP_DEBUG, ipaddr);
- LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | 3, (", port = %"U16_F")\n", port));
+ LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, (", port = %"U16_F")\n", port));
rebind = 0;
/* Check for double bind and rebind of the same pcb */
diff --git a/net/lwip/src/include/ipv4/lwip/autoip.h b/net/lwip/src/include/ipv4/lwip/autoip.h
index 076a2ed237..f2621658db 100644
--- a/net/lwip/src/include/ipv4/lwip/autoip.h
+++ b/net/lwip/src/include/ipv4/lwip/autoip.h
@@ -52,6 +52,10 @@
#include "lwip/udp.h"
#include "netif/etharp.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* AutoIP Timing */
#define AUTOIP_TMR_INTERVAL 100
#define AUTOIP_TICKS_PER_SECOND (1000 / AUTOIP_TMR_INTERVAL)
@@ -100,6 +104,13 @@ void autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr);
/** Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds */
void autoip_tmr(void);
+/** Handle a possible change in the network configuration */
+void autoip_network_changed(struct netif *netif);
+
+#ifdef __cplusplus
+}
+#endif
+
#endif /* LWIP_AUTOIP */
#endif /* __LWIP_AUTOIP_H__ */
diff --git a/net/lwip/src/include/ipv4/lwip/icmp.h b/net/lwip/src/include/ipv4/lwip/icmp.h
index ff838f43a1..c73961c917 100644
--- a/net/lwip/src/include/ipv4/lwip/icmp.h
+++ b/net/lwip/src/include/ipv4/lwip/icmp.h
@@ -33,9 +33,6 @@
#define __LWIP_ICMP_H__
#include "lwip/opt.h"
-
-#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */
-
#include "lwip/pbuf.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
@@ -70,11 +67,6 @@ enum icmp_te_type {
ICMP_TE_FRAG = 1 /* fragment reassembly time exceeded */
};
-void icmp_input(struct pbuf *p, struct netif *inp);
-
-void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t);
-void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t);
-
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
@@ -103,10 +95,17 @@ PACK_STRUCT_END
#define ICMPH_TYPE_SET(hdr, t) ((hdr)->type = (t))
#define ICMPH_CODE_SET(hdr, c) ((hdr)->code = (c))
+
+#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */
+
+void icmp_input(struct pbuf *p, struct netif *inp);
+void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t);
+void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t);
+
+#endif /* LWIP_ICMP */
+
#ifdef __cplusplus
}
#endif
-#endif /* LWIP_ICMP */
-
#endif /* __LWIP_ICMP_H__ */
diff --git a/net/lwip/src/include/ipv4/lwip/ip.h b/net/lwip/src/include/ipv4/lwip/ip.h
index 14eba3ca53..fd84f3043c 100644
--- a/net/lwip/src/include/ipv4/lwip/ip.h
+++ b/net/lwip/src/include/ipv4/lwip/ip.h
@@ -153,6 +153,11 @@ PACK_STRUCT_END
#define IPH_PROTO_SET(hdr, proto) (hdr)->_ttl_proto = (htons((proto) | (IPH_TTL(hdr) << 8)))
#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum)
+/** The interface that provided the packet for the current callback invocation. */
+extern struct netif *current_netif;
+/** Header of the input packet currently being processed. */
+extern const struct ip_hdr *current_header;
+
#define ip_init() /* Compatibility define, not init needed. */
struct netif *ip_route(struct ip_addr *dest);
err_t ip_input(struct pbuf *p, struct netif *inp);
@@ -170,8 +175,14 @@ err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest
u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options,
u16_t optlen);
#endif /* IP_OPTIONS_SEND */
-struct netif *ip_current_netif(void);
-const struct ip_hdr *ip_current_header(void);
+/** Get the interface that received the current packet.
+ * This function must only be called from a receive callback (udp_recv,
+ * raw_recv, tcp_accept). It will return NULL otherwise. */
+#define ip_current_netif() (current_netif)
+/** Get the IP header of the current packet.
+ * This function must only be called from a receive callback (udp_recv,
+ * raw_recv, tcp_accept). It will return NULL otherwise. */
+#define ip_current_header() (current_header)
#if IP_DEBUG
void ip_debug_print(struct pbuf *p);
#else
diff --git a/net/lwip/src/include/ipv4/lwip/ip_addr.h b/net/lwip/src/include/ipv4/lwip/ip_addr.h
index f2e4c22338..298e65768c 100644
--- a/net/lwip/src/include/ipv4/lwip/ip_addr.h
+++ b/net/lwip/src/include/ipv4/lwip/ip_addr.h
@@ -161,6 +161,11 @@ u8_t ip_addr_isbroadcast(struct ip_addr *, struct netif *);
#define ip4_addr3(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 8) & 0xff)
#define ip4_addr4(ipaddr) ((u16_t)(ntohl((ipaddr)->addr)) & 0xff)
+/**
+ * Same as inet_ntoa() but takes a struct ip_addr*
+ */
+#define ip_ntoa(addr) ((addr != NULL) ? inet_ntoa(*((struct in_addr*)(addr))) : "NULL")
+
#ifdef __cplusplus
}
#endif
diff --git a/net/lwip/src/include/lwip/api_msg.h b/net/lwip/src/include/lwip/api_msg.h
index 4272d77ccb..d3b0456838 100644
--- a/net/lwip/src/include/lwip/api_msg.h
+++ b/net/lwip/src/include/lwip/api_msg.h
@@ -83,7 +83,7 @@ struct api_msg_msg {
size_t len;
u8_t apiflags;
} w;
- /** used ofr do_recv */
+ /** used for do_recv */
struct {
u16_t len;
} r;
diff --git a/net/lwip/src/include/lwip/debug.h b/net/lwip/src/include/lwip/debug.h
index d5c4e47473..d8359ea3a5 100644
--- a/net/lwip/src/include/lwip/debug.h
+++ b/net/lwip/src/include/lwip/debug.h
@@ -35,12 +35,13 @@
#include "lwip/arch.h"
/** lower two bits indicate debug level
- * - 0 off
+ * - 0 all
* - 1 warning
* - 2 serious
* - 3 severe
*/
-#define LWIP_DBG_LEVEL_OFF 0x00
+#define LWIP_DBG_LEVEL_ALL 0x00
+#define LWIP_DBG_LEVEL_OFF LWIP_DBG_LEVEL_ALL /* compatibility define only */
#define LWIP_DBG_LEVEL_WARNING 0x01 /* bad checksums, dropped packets, ... */
#define LWIP_DBG_LEVEL_SERIOUS 0x02 /* memory allocation failures, ... */
#define LWIP_DBG_LEVEL_SEVERE 0x03
diff --git a/net/lwip/src/include/lwip/dhcp.h b/net/lwip/src/include/lwip/dhcp.h
index 825dba6ecb..db37e88493 100644
--- a/net/lwip/src/include/lwip/dhcp.h
+++ b/net/lwip/src/include/lwip/dhcp.h
@@ -24,22 +24,20 @@ extern "C" {
struct dhcp
{
- /** current DHCP state machine state */
- u8_t state;
- /** retries of current request */
- u8_t tries;
/** transaction identifier of last sent request */
u32_t xid;
/** our connection to the DHCP server */
struct udp_pcb *pcb;
- /** (first) pbuf of incoming msg */
- struct pbuf *p;
/** incoming msg */
struct dhcp_msg *msg_in;
/** incoming msg options */
- struct dhcp_msg *options_in;
+ void *options_in;
/** ingoing msg options length */
u16_t options_in_len;
+ /** current DHCP state machine state */
+ u8_t state;
+ /** retries of current request */
+ u8_t tries;
struct pbuf *p_out; /* pbuf of outcoming msg */
struct dhcp_msg *msg_out; /* outgoing msg */
@@ -124,6 +122,8 @@ err_t dhcp_release(struct netif *netif);
void dhcp_stop(struct netif *netif);
/** inform server of our manual IP address */
void dhcp_inform(struct netif *netif);
+/** Handle a possible change in the network configuration */
+void dhcp_network_changed(struct netif *netif);
/** if enabled, check whether the offered IP address is not in use, using ARP */
#if DHCP_DOES_ARP_CHECK
diff --git a/net/lwip/src/include/lwip/init.h b/net/lwip/src/include/lwip/init.h
index a4dc0577f4..c1455f5a7d 100644
--- a/net/lwip/src/include/lwip/init.h
+++ b/net/lwip/src/include/lwip/init.h
@@ -43,7 +43,7 @@ extern "C" {
/** x.X.x: Minor version of the stack */
#define LWIP_VERSION_MINOR 3U
/** x.x.X: Revision of the stack */
-#define LWIP_VERSION_REVISION 1U
+#define LWIP_VERSION_REVISION 2U
/** For release candidates, this is set to 1..254
* For official releases, this is set to 255 (LWIP_RC_RELEASE)
* For development versions (CVS), this is set to 0 (LWIP_RC_DEVELOPMENT) */
diff --git a/net/lwip/src/include/lwip/memp.h b/net/lwip/src/include/lwip/memp.h
index f0d0739943..702b57662d 100644
--- a/net/lwip/src/include/lwip/memp.h
+++ b/net/lwip/src/include/lwip/memp.h
@@ -84,8 +84,6 @@ extern const u16_t memp_sizes[MEMP_MAX];
#include "mem.h"
#define memp_init()
-#define memp_malloc(type) mem_malloc(memp_sizes[type])
-#define memp_free(type, mem) mem_free(mem)
#else /* MEMP_MEM_MALLOC */
@@ -98,6 +96,7 @@ struct memp_malloc_helper
#endif /* MEM_USE_POOLS */
void memp_init(void);
+#endif /* MEMP_MEM_MALLOC */
#if MEMP_OVERFLOW_CHECK
void *memp_malloc_fn(memp_t type, const char* file, const int line);
@@ -107,8 +106,6 @@ void *memp_malloc(memp_t type);
#endif
void memp_free(memp_t type, void *mem);
-#endif /* MEMP_MEM_MALLOC */
-
#ifdef __cplusplus
}
#endif
diff --git a/net/lwip/src/include/lwip/netbuf.h b/net/lwip/src/include/lwip/netbuf.h
index 6d84dd073b..0dfb367a4b 100644
--- a/net/lwip/src/include/lwip/netbuf.h
+++ b/net/lwip/src/include/lwip/netbuf.h
@@ -34,6 +34,7 @@
#include "lwip/opt.h"
#include "lwip/pbuf.h"
+#include "lwip/ip_addr.h"
#ifdef __cplusplus
extern "C" {
@@ -43,6 +44,10 @@ struct netbuf {
struct pbuf *p, *ptr;
struct ip_addr *addr;
u16_t port;
+#if LWIP_NETBUF_RECVINFO
+ struct ip_addr *toaddr;
+ u16_t toport;
+#endif /* LWIP_NETBUF_RECVINFO */
};
/* Network buffer functions: */
@@ -69,6 +74,10 @@ void netbuf_first (struct netbuf *buf);
#define netbuf_len(buf) ((buf)->p->tot_len)
#define netbuf_fromaddr(buf) ((buf)->addr)
#define netbuf_fromport(buf) ((buf)->port)
+#if LWIP_NETBUF_RECVINFO
+#define netbuf_destaddr(buf) ((buf)->toaddr)
+#define netbuf_destport(buf) ((buf)->toport)
+#endif /* LWIP_NETBUF_RECVINFO */
#ifdef __cplusplus
}
diff --git a/net/lwip/src/include/lwip/netdb.h b/net/lwip/src/include/lwip/netdb.h
index 0f7b2ec04a..29c9847c73 100644
--- a/net/lwip/src/include/lwip/netdb.h
+++ b/net/lwip/src/include/lwip/netdb.h
@@ -103,7 +103,7 @@ int lwip_getaddrinfo(const char *nodename,
#define gethostbyname(name) lwip_gethostbyname(name)
#define gethostbyname_r(name, ret, buf, buflen, result, h_errnop) \
lwip_gethostbyname_r(name, ret, buf, buflen, result, h_errnop)
-#define freeaddrinfo(addrinfo) lwip_freeaddrinfo(a)
+#define freeaddrinfo(addrinfo) lwip_freeaddrinfo(addrinfo)
#define getaddrinfo(nodname, servname, hints, res) \
lwip_getaddrinfo(nodname, servname, hints, res)
#endif /* LWIP_COMPAT_SOCKETS */
diff --git a/net/lwip/src/include/lwip/netif.h b/net/lwip/src/include/lwip/netif.h
index a325030526..c50a6da895 100644
--- a/net/lwip/src/include/lwip/netif.h
+++ b/net/lwip/src/include/lwip/netif.h
@@ -131,12 +131,12 @@ struct netif {
/* the hostname for this netif, NULL is a valid value */
char* hostname;
#endif /* LWIP_NETIF_HOSTNAME */
+ /** maximum transfer unit (in bytes) */
+ u16_t mtu;
/** number of bytes used in hwaddr */
u8_t hwaddr_len;
/** link level hardware address of this interface */
u8_t hwaddr[NETIF_MAX_HWADDR_LEN];
- /** maximum transfer unit (in bytes) */
- u16_t mtu;
/** flags (see NETIF_FLAG_ above) */
u8_t flags;
/** descriptive abbreviation */
diff --git a/net/lwip/src/include/lwip/netifapi.h b/net/lwip/src/include/lwip/netifapi.h
index 36c6bd0a24..4145dd740a 100644
--- a/net/lwip/src/include/lwip/netifapi.h
+++ b/net/lwip/src/include/lwip/netifapi.h
@@ -78,6 +78,11 @@ err_t netifapi_netif_add ( struct netif *netif,
err_t (* init)(struct netif *netif),
err_t (* input)(struct pbuf *p, struct netif *netif) );
+err_t netifapi_netif_set_addr ( struct netif *netif,
+ struct ip_addr *ipaddr,
+ struct ip_addr *netmask,
+ struct ip_addr *gw );
+
err_t netifapi_netif_common ( struct netif *netif,
void (* voidfunc)(struct netif *netif),
err_t (* errtfunc)(struct netif *netif) );
diff --git a/net/lwip/src/include/lwip/opt.h b/net/lwip/src/include/lwip/opt.h
index e8bd8b89e4..eb99a77846 100644
--- a/net/lwip/src/include/lwip/opt.h
+++ b/net/lwip/src/include/lwip/opt.h
@@ -366,6 +366,16 @@
#define ETHARP_TRUST_IP_MAC 1
#endif
+/**
+ * ETHARP_SUPPORT_VLAN==1: support receiving ethernet packets with VLAN header.
+ * Additionally, you can define ETHARP_VLAN_CHECK to an u16_t VLAN ID to check.
+ * If ETHARP_VLAN_CHECK is defined, only VLAN-traffic for this VLAN is accepted.
+ * If ETHARP_VLAN_CHECK is not defined, all traffic is accepted.
+ */
+#ifndef ETHARP_SUPPORT_VLAN
+#define ETHARP_SUPPORT_VLAN 0
+#endif
+
/*
--------------------------------
---------- IP options ----------
@@ -718,6 +728,13 @@
#define UDP_TTL (IP_DEFAULT_TTL)
#endif
+/**
+ * LWIP_NETBUF_RECVINFO==1: append destination addr and port to every netbuf.
+ */
+#ifndef LWIP_NETBUF_RECVINFO
+#define LWIP_NETBUF_RECVINFO 0
+#endif
+
/*
---------------------------------
---------- TCP options ----------
@@ -742,7 +759,7 @@
* (2 * TCP_MSS) for things to work well
*/
#ifndef TCP_WND
-#define TCP_WND 2048
+#define TCP_WND (4 * TCP_MSS)
#endif
/**
@@ -768,14 +785,14 @@
#endif
/**
- * TCP_MSS: TCP Maximum segment size. (default is 128, a *very*
- * conservative default.)
+ * TCP_MSS: TCP Maximum segment size. (default is 536, a conservative default,
+ * you might want to increase this.)
* For the receive side, this MSS is advertised to the remote side
* when opening a connection. For the transmit size, this MSS sets
* an upper limit on the MSS advertised by the remote host.
*/
#ifndef TCP_MSS
-#define TCP_MSS 128
+#define TCP_MSS 536
#endif
/**
@@ -803,7 +820,7 @@
* as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work.
*/
#ifndef TCP_SND_QUEUELEN
-#define TCP_SND_QUEUELEN (4 * (TCP_SND_BUF/TCP_MSS))
+#define TCP_SND_QUEUELEN (4 * (TCP_SND_BUF)/(TCP_MSS))
#endif
/**
@@ -812,7 +829,7 @@
* TCP snd_buf for select to return writable.
*/
#ifndef TCP_SNDLOWAT
-#define TCP_SNDLOWAT (TCP_SND_BUF/2)
+#define TCP_SNDLOWAT ((TCP_SND_BUF)/2)
#endif
/**
@@ -1322,21 +1339,21 @@
* MEM_STATS==1: Enable mem.c stats.
*/
#ifndef MEM_STATS
-#define MEM_STATS 1
+#define MEM_STATS ((MEM_LIBC_MALLOC == 0) && (MEM_USE_POOLS == 0))
#endif
/**
* MEMP_STATS==1: Enable memp.c pool stats.
*/
#ifndef MEMP_STATS
-#define MEMP_STATS 1
+#define MEMP_STATS (MEMP_MEM_MALLOC == 0)
#endif
/**
* SYS_STATS==1: Enable system stats (sem and mbox counts, etc).
*/
#ifndef SYS_STATS
-#define SYS_STATS 1
+#define SYS_STATS (NO_SYS == 0)
#endif
#else
@@ -1510,9 +1527,12 @@
#endif
#define PPP_MINMRU 128 /* No MRUs below this */
-
+#ifndef MAXNAMELEN
#define MAXNAMELEN 256 /* max length of hostname or name for auth */
+#endif
+#ifndef MAXSECRETLEN
#define MAXSECRETLEN 256 /* max length of password or secret */
+#endif
#endif /* PPP_SUPPORT */
@@ -1574,7 +1594,7 @@
* messages are written.
*/
#ifndef LWIP_DBG_MIN_LEVEL
-#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_OFF
+#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL
#endif
/**
diff --git a/net/lwip/src/include/lwip/sio.h b/net/lwip/src/include/lwip/sio.h
index 7d9162e49e..28ae2f225d 100644
--- a/net/lwip/src/include/lwip/sio.h
+++ b/net/lwip/src/include/lwip/sio.h
@@ -51,27 +51,87 @@ typedef void * sio_fd_t;
or be implemented in your custom sio.c file. */
#ifndef sio_open
-sio_fd_t sio_open(u8_t);
+/**
+ * Opens a serial device for communication.
+ *
+ * @param devnum device number
+ * @return handle to serial device if successful, NULL otherwise
+ */
+sio_fd_t sio_open(u8_t devnum);
#endif
#ifndef sio_send
-void sio_send(u8_t, sio_fd_t);
+/**
+ * Sends a single character to the serial device.
+ *
+ * @param c character to send
+ * @param fd serial device handle
+ *
+ * @note This function will block until the character can be sent.
+ */
+void sio_send(u8_t c, sio_fd_t fd);
#endif
#ifndef sio_recv
-u8_t sio_recv(sio_fd_t);
+/**
+ * Receives a single character from the serial device.
+ *
+ * @param fd serial device handle
+ *
+ * @note This function will block until a character is received.
+ */
+u8_t sio_recv(sio_fd_t fd);
#endif
#ifndef sio_read
-u32_t sio_read(sio_fd_t, u8_t *, u32_t);
+/**
+ * Reads from the serial device.
+ *
+ * @param fd serial device handle
+ * @param data pointer to data buffer for receiving
+ * @param len maximum length (in bytes) of data to receive
+ * @return number of bytes actually received - may be 0 if aborted by sio_read_abort
+ *
+ * @note This function will block until data can be received. The blocking
+ * can be cancelled by calling sio_read_abort().
+ */
+u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len);
+#endif
+
+#ifndef sio_tryread
+/**
+ * Tries to read from the serial device. Same as sio_read but returns
+ * immediately if no data is available and never blocks.
+ *
+ * @param fd serial device handle
+ * @param data pointer to data buffer for receiving
+ * @param len maximum length (in bytes) of data to receive
+ * @return number of bytes actually received
+ */
+u32_t sio_tryread(sio_fd_t fd, u8_t *data, u32_t len);
#endif
#ifndef sio_write
-u32_t sio_write(sio_fd_t, u8_t *, u32_t);
+/**
+ * Writes to the serial device.
+ *
+ * @param fd serial device handle
+ * @param data pointer to data to send
+ * @param len length (in bytes) of data to send
+ * @return number of bytes actually sent
+ *
+ * @note This function will block until all data can be sent.
+ */
+u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len);
#endif
#ifndef sio_read_abort
-void sio_read_abort(sio_fd_t);
+/**
+ * Aborts a blocking sio_read() call.
+ *
+ * @param fd serial device handle
+ */
+void sio_read_abort(sio_fd_t fd);
#endif
#ifdef __cplusplus
diff --git a/net/lwip/src/include/lwip/tcp.h b/net/lwip/src/include/lwip/tcp.h
index 8f6b9d3c13..c88d25d7ae 100644
--- a/net/lwip/src/include/lwip/tcp.h
+++ b/net/lwip/src/include/lwip/tcp.h
@@ -78,6 +78,9 @@ void tcp_err (struct tcp_pcb *pcb,
#define tcp_mss(pcb) ((pcb)->mss)
#define tcp_sndbuf(pcb) ((pcb)->snd_buf)
+#define tcp_nagle_disable(pcb) ((pcb)->flags |= TF_NODELAY)
+#define tcp_nagle_enable(pcb) ((pcb)->flags &= ~TF_NODELAY)
+#define tcp_nagle_disabled(pcb) (((pcb)->flags & TF_NODELAY) != 0)
#if TCP_LISTEN_BACKLOG
#define tcp_accepted(pcb) (((struct tcp_pcb_listen *)(pcb))->accepts_pending--)
@@ -122,9 +125,11 @@ void tcp_fasttmr (void);
/* Only used by IP to pass a TCP segment to TCP: */
void tcp_input (struct pbuf *p, struct netif *inp);
/* Used within the TCP code only: */
+err_t tcp_send_empty_ack(struct tcp_pcb *pcb);
err_t tcp_output (struct tcp_pcb *pcb);
void tcp_rexmit (struct tcp_pcb *pcb);
void tcp_rexmit_rto (struct tcp_pcb *pcb);
+void tcp_rexmit_fast (struct tcp_pcb *pcb);
u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb);
/**
@@ -134,9 +139,10 @@ u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb);
* - the TF_NODELAY flag is set (nagle algorithm turned off for this pcb) or
* - the only unsent segment is at least pcb->mss bytes long (or there is more
* than one unsent segment - with lwIP, this can happen although unsent->len < mss)
+ * - or if we are in fast-retransmit (TF_INFR)
*/
#define tcp_do_output_nagle(tpcb) ((((tpcb)->unacked == NULL) || \
- ((tpcb)->flags & TF_NODELAY) || \
+ ((tpcb)->flags & (TF_NODELAY | TF_INFR)) || \
(((tpcb)->unsent != NULL) && (((tpcb)->unsent->next != NULL) || \
((tpcb)->unsent->len >= (tpcb)->mss))) \
) ? 1 : 0)
@@ -230,12 +236,11 @@ PACK_STRUCT_END
#define TCPH_OFFSET_SET(phdr, offset) (phdr)->_hdrlen_rsvd_flags = htons(((offset) << 8) | TCPH_FLAGS(phdr))
#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr))
-#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons((ntohs((phdr)->_hdrlen_rsvd_flags) & ~TCP_FLAGS) | (flags))
-#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (flags))
+#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & htons((u16_t)(~(u16_t)(TCP_FLAGS)))) | htons(flags))
+#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | htons(flags))
#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (TCPH_FLAGS(phdr) & ~(flags)) )
-#define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & TCP_FIN || \
- TCPH_FLAGS((seg)->tcphdr) & TCP_SYN)? 1: 0))
+#define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0))
enum tcp_state {
CLOSED = 0,
@@ -489,9 +494,7 @@ err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb,
if((pcb)->recv != NULL) { \
(ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)); \
} else { \
- (ret) = ERR_OK; \
- if (p != NULL) \
- pbuf_free(p); \
+ (ret) = tcp_recv_null(NULL, (pcb), (p), (err)); \
} \
} while (0)
@@ -585,9 +588,14 @@ void tcp_zero_window_probe(struct tcp_pcb *pcb);
u16_t tcp_eff_send_mss(u16_t sendmss, struct ip_addr *addr);
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
+#if LWIP_CALLBACK_API
+err_t tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
+#endif /* LWIP_CALLBACK_API */
+
extern struct tcp_pcb *tcp_input_pcb;
extern u32_t tcp_ticks;
+const char* tcp_debug_state_str(enum tcp_state s);
#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
void tcp_debug_print(struct tcp_hdr *tcphdr);
void tcp_debug_print_flags(u8_t flags);
@@ -651,7 +659,7 @@ extern struct tcp_pcb *tcp_tmp_pcb; /* Only used for temporary storage. */
if(*pcbs == npcb) { \
*pcbs = (*pcbs)->next; \
} else for(tcp_tmp_pcb = *pcbs; tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \
- if(tcp_tmp_pcb->next != NULL && tcp_tmp_pcb->next == npcb) { \
+ if(tcp_tmp_pcb->next == npcb) { \
tcp_tmp_pcb->next = npcb->next; \
break; \
} \
@@ -679,7 +687,7 @@ extern struct tcp_pcb *tcp_tmp_pcb; /* Only used for temporary storage. */
for(tcp_tmp_pcb = *pcbs; \
tcp_tmp_pcb != NULL; \
tcp_tmp_pcb = tcp_tmp_pcb->next) { \
- if(tcp_tmp_pcb->next != NULL && tcp_tmp_pcb->next == npcb) { \
+ if(tcp_tmp_pcb->next == npcb) { \
tcp_tmp_pcb->next = npcb->next; \
break; \
} \
diff --git a/net/lwip/src/include/lwip/udp.h b/net/lwip/src/include/lwip/udp.h
index d7b2a38207..08d1817b30 100644
--- a/net/lwip/src/include/lwip/udp.h
+++ b/net/lwip/src/include/lwip/udp.h
@@ -94,6 +94,9 @@ struct udp_pcb {
* The callback is responsible for freeing the pbuf
* if it's not used any more.
*
+ * ATTENTION: Be aware that 'addr' points into the pbuf 'p' so freeing this pbuf
+ * makes 'addr' invalid, too.
+ *
* @param arg user supplied argument (udp_pcb.recv_arg)
* @param pcb the udp_pcb which received data
* @param p the packet buffer that was received
diff --git a/net/lwip/src/include/netif/etharp.h b/net/lwip/src/include/netif/etharp.h
index db691d91d2..72b8d79f08 100644
--- a/net/lwip/src/include/netif/etharp.h
+++ b/net/lwip/src/include/netif/etharp.h
@@ -85,13 +85,34 @@ PACK_STRUCT_END
# include "arch/epstruct.h"
#endif
+#define SIZEOF_ETH_HDR (14 + ETH_PAD_SIZE)
+
+#if ETHARP_SUPPORT_VLAN
+
+#ifdef PACK_STRUCT_USE_INCLUDES
+# include "arch/bpstruct.h"
+#endif
+PACK_STRUCT_BEGIN
+struct eth_vlan_hdr {
+ PACK_STRUCT_FIELD(u16_t tpid);
+ PACK_STRUCT_FIELD(u16_t prio_vid);
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+#ifdef PACK_STRUCT_USE_INCLUDES
+# include "arch/epstruct.h"
+#endif
+
+#define SIZEOF_VLAN_HDR 4
+#define VLAN_ID(vlan_hdr) (htons((vlan_hdr)->prio_vid) & 0xFFF)
+
+#endif /* ETHARP_SUPPORT_VLAN */
+
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
/** the ARP message */
struct etharp_hdr {
- PACK_STRUCT_FIELD(struct eth_hdr ethhdr);
PACK_STRUCT_FIELD(u16_t hwtype);
PACK_STRUCT_FIELD(u16_t proto);
PACK_STRUCT_FIELD(u16_t _hwlen_protolen);
@@ -106,24 +127,15 @@ PACK_STRUCT_END
# include "arch/epstruct.h"
#endif
-#ifdef PACK_STRUCT_USE_INCLUDES
-# include "arch/bpstruct.h"
-#endif
-PACK_STRUCT_BEGIN
-struct ethip_hdr {
- PACK_STRUCT_FIELD(struct eth_hdr eth);
- PACK_STRUCT_FIELD(struct ip_hdr ip);
-} PACK_STRUCT_STRUCT;
-PACK_STRUCT_END
-#ifdef PACK_STRUCT_USE_INCLUDES
-# include "arch/epstruct.h"
-#endif
+#define SIZEOF_ETHARP_HDR 28
+#define SIZEOF_ETHARP_PACKET (SIZEOF_ETH_HDR + SIZEOF_ETHARP_HDR)
/** 5 seconds period */
#define ARP_TMR_INTERVAL 5000
#define ETHTYPE_ARP 0x0806
#define ETHTYPE_IP 0x0800
+#define ETHTYPE_VLAN 0x8100
#define ETHTYPE_PPPOEDISC 0x8863 /* PPP Over Ethernet Discovery Stage */
#define ETHTYPE_PPPOE 0x8864 /* PPP Over Ethernet Session Stage */
diff --git a/net/lwip/src/include/netif/slipif.h b/net/lwip/src/include/netif/slipif.h
index aa08ada4a2..ccd03c8a16 100644
--- a/net/lwip/src/include/netif/slipif.h
+++ b/net/lwip/src/include/netif/slipif.h
@@ -41,6 +41,7 @@ extern "C" {
#endif
err_t slipif_init(struct netif * netif);
+void slipif_poll(struct netif *netif);
#ifdef __cplusplus
}
diff --git a/net/lwip/src/lwipopts.h b/net/lwip/src/lwipopts.h
index f5cc7a2e56..d7fb5f2d23 100644
--- a/net/lwip/src/lwipopts.h
+++ b/net/lwip/src/lwipopts.h
@@ -89,7 +89,13 @@
#define MEM_LIBC_MALLOC 1
#define mem_malloc rt_malloc
#define mem_free rt_free
-#define mem_calloc rt_calloc
+#define mem_calloc rt_calloc
+
+#ifdef RT_LWIP_USING_RT_MEM
+#define MEMP_MEM_MALLOC 1
+#else
+#define MEMP_MEM_MALLOC 0
+#endif
/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
sends a lot of data out of ROM (or other static memory), this
diff --git a/net/lwip/src/netif/FILES b/net/lwip/src/netif/FILES
index 1c4f5928d7..099dbf3ec2 100644
--- a/net/lwip/src/netif/FILES
+++ b/net/lwip/src/netif/FILES
@@ -23,3 +23,7 @@ slipif.c
protocol. It requires a sio (serial I/O) module to work.
ppp/ Point-to-Point Protocol stack
+ The PPP stack has been ported from ucip (http://ucip.sourceforge.net).
+ It matches quite well to pppd 2.3.1 (http://ppp.samba.org), although
+ compared to that, it has some modifications for embedded systems and
+ the source code has been reordered a bit. \ No newline at end of file
diff --git a/net/lwip/src/netif/etharp.c b/net/lwip/src/netif/etharp.c
index 73ea211736..8f6872fa2c 100644
--- a/net/lwip/src/netif/etharp.c
+++ b/net/lwip/src/netif/etharp.c
@@ -468,7 +468,7 @@ update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *e
{
s8_t i;
u8_t k;
- LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | 3, ("update_arp_entry()\n"));
+ LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry()\n"));
LWIP_ASSERT("netif->hwaddr_len == ETHARP_HWADDR_LEN", netif->hwaddr_len == ETHARP_HWADDR_LEN);
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_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),
@@ -579,13 +579,21 @@ etharp_find_addr(struct netif *netif, struct ip_addr *ipaddr,
void
etharp_ip_input(struct netif *netif, struct pbuf *p)
{
- struct ethip_hdr *hdr;
+ struct eth_hdr *ethhdr;
+ struct ip_hdr *iphdr;
LWIP_ERROR("netif != NULL", (netif != NULL), return;);
/* Only insert an entry if the source IP address of the
incoming IP packet comes from a host on the local network. */
- hdr = p->payload;
+ ethhdr = p->payload;
+ iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
+#if ETHARP_SUPPORT_VLAN
+ if (ethhdr->type == ETHTYPE_VLAN) {
+ iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
+ }
+#endif /* ETHARP_SUPPORT_VLAN */
+
/* source is not on the local network? */
- if (!ip_addr_netcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask))) {
+ if (!ip_addr_netcmp(&(iphdr->src), &(netif->ip_addr), &(netif->netmask))) {
/* do nothing */
return;
}
@@ -594,7 +602,7 @@ etharp_ip_input(struct netif *netif, struct pbuf *p)
/* update ARP table */
/* @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);
+ update_arp_entry(netif, &(iphdr->src), &(ethhdr->src), 0);
}
@@ -617,6 +625,7 @@ void
etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
{
struct etharp_hdr *hdr;
+ struct eth_hdr *ethhdr;
/* these are aligned properly, whereas the ARP header fields might not be */
struct ip_addr sipaddr, dipaddr;
u8_t i;
@@ -629,24 +638,32 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
/* drop short ARP packets: we have to check for p->len instead of p->tot_len here
since a struct etharp_hdr is pointed to p->payload, so it musn't be chained! */
- if (p->len < sizeof(struct etharp_hdr)) {
- LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | 1, ("etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len, (s16_t)sizeof(struct etharp_hdr)));
+ if (p->len < SIZEOF_ETHARP_PACKET) {
+ LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
+ ("etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len,
+ (s16_t)SIZEOF_ETHARP_PACKET));
ETHARP_STATS_INC(etharp.lenerr);
ETHARP_STATS_INC(etharp.drop);
pbuf_free(p);
return;
}
- hdr = p->payload;
+ ethhdr = p->payload;
+ hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
+#if ETHARP_SUPPORT_VLAN
+ if (ethhdr->type == ETHTYPE_VLAN) {
+ hdr = (struct etharp_hdr *)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
+ }
+#endif /* ETHARP_SUPPORT_VLAN */
/* RFC 826 "Packet Reception": */
if ((hdr->hwtype != htons(HWTYPE_ETHERNET)) ||
(hdr->_hwlen_protolen != htons((ETHARP_HWADDR_LEN << 8) | sizeof(struct ip_addr))) ||
(hdr->proto != htons(ETHTYPE_IP)) ||
- (hdr->ethhdr.type != htons(ETHTYPE_ARP))) {
- LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | 1,
+ (ethhdr->type != htons(ETHTYPE_ARP))) {
+ LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
("etharp_arp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",
- hdr->hwtype, ARPH_HWLEN(hdr), hdr->proto, ARPH_PROTOLEN(hdr), hdr->ethhdr.type));
+ hdr->hwtype, ARPH_HWLEN(hdr), hdr->proto, ARPH_PROTOLEN(hdr), ethhdr->type));
ETHARP_STATS_INC(etharp.proterr);
ETHARP_STATS_INC(etharp.drop);
pbuf_free(p);
@@ -719,12 +736,12 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
i--;
hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i];
#if LWIP_AUTOIP
- hdr->ethhdr.dest.addr[i] = ethdst_hwaddr[i];
+ ethhdr->dest.addr[i] = ethdst_hwaddr[i];
#else /* LWIP_AUTOIP */
- hdr->ethhdr.dest.addr[i] = hdr->shwaddr.addr[i];
+ ethhdr->dest.addr[i] = hdr->shwaddr.addr[i];
#endif /* LWIP_AUTOIP */
hdr->shwaddr.addr[i] = ethaddr->addr[i];
- hdr->ethhdr.src.addr[i] = ethaddr->addr[i];
+ ethhdr->src.addr[i] = ethaddr->addr[i];
}
/* hwtype, hwaddr_len, proto, protolen and the type in the ethernet header
@@ -788,7 +805,8 @@ etharp_output(struct netif *netif, struct pbuf *q, struct ip_addr *ipaddr)
/* make room for Ethernet header - should not fail */
if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
/* bail out */
- LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | 2, ("etharp_output: could not allocate room for header.\n"));
+ LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
+ ("etharp_output: could not allocate room for header.\n"));
LINK_STATS_INC(link.lenerr);
return ERR_BUF;
}
@@ -1034,23 +1052,26 @@ etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
struct pbuf *p;
err_t result = ERR_OK;
u8_t k; /* ARP entry index */
+ struct eth_hdr *ethhdr;
struct etharp_hdr *hdr;
#if LWIP_AUTOIP
const u8_t * ethdst_hwaddr;
#endif /* LWIP_AUTOIP */
/* allocate a pbuf for the outgoing ARP request packet */
- p = pbuf_alloc(PBUF_RAW, sizeof(struct etharp_hdr), PBUF_RAM);
+ p = pbuf_alloc(PBUF_RAW, SIZEOF_ETHARP_PACKET, PBUF_RAM);
/* could allocate a pbuf for an ARP request? */
if (p == NULL) {
- LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | 2, ("etharp_raw: could not allocate pbuf for ARP request.\n"));
+ LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
+ ("etharp_raw: could not allocate pbuf for ARP request.\n"));
ETHARP_STATS_INC(etharp.memerr);
return ERR_MEM;
}
LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr",
- (p->len >= sizeof(struct etharp_hdr)));
+ (p->len >= SIZEOF_ETHARP_PACKET));
- hdr = p->payload;
+ ethhdr = p->payload;
+ hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n"));
hdr->opcode = htons(opcode);
@@ -1070,11 +1091,11 @@ etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
hdr->dhwaddr.addr[k] = hwdst_addr->addr[k];
/* Write the Ethernet MAC-Addresses */
#if LWIP_AUTOIP
- hdr->ethhdr.dest.addr[k] = ethdst_hwaddr[k];
+ ethhdr->dest.addr[k] = ethdst_hwaddr[k];
#else /* LWIP_AUTOIP */
- hdr->ethhdr.dest.addr[k] = ethdst_addr->addr[k];
+ ethhdr->dest.addr[k] = ethdst_addr->addr[k];
#endif /* LWIP_AUTOIP */
- hdr->ethhdr.src.addr[k] = ethsrc_addr->addr[k];
+ ethhdr->src.addr[k] = ethsrc_addr->addr[k];
}
hdr->sipaddr = *(struct ip_addr2 *)ipsrc_addr;
hdr->dipaddr = *(struct ip_addr2 *)ipdst_addr;
@@ -1084,7 +1105,7 @@ etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
/* set hwlen and protolen together */
hdr->_hwlen_protolen = htons((ETHARP_HWADDR_LEN << 8) | sizeof(struct ip_addr));
- hdr->ethhdr.type = htons(ETHTYPE_ARP);
+ ethhdr->type = htons(ETHTYPE_ARP);
/* send ARP query */
result = netif->linkoutput(netif, p);
ETHARP_STATS_INC(etharp.xmit);
@@ -1126,6 +1147,7 @@ err_t
ethernet_input(struct pbuf *p, struct netif *netif)
{
struct eth_hdr* ethhdr;
+ u16_t type;
/* points to packet payload, which starts with an Ethernet header */
ethhdr = p->payload;
@@ -1137,7 +1159,22 @@ ethernet_input(struct pbuf *p, struct netif *netif)
(unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5],
(unsigned)htons(ethhdr->type)));
- switch (htons(ethhdr->type)) {
+ type = htons(ethhdr->type);
+#if ETHARP_SUPPORT_VLAN
+ if (type == ETHTYPE_VLAN) {
+ struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr*)(((char*)ethhdr) + SIZEOF_ETH_HDR);
+#ifdef ETHARP_VLAN_CHECK /* if not, allow all VLANs */
+ if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) {
+ /* silently ignore this packet: not for our VLAN */
+ pbuf_free(p);
+ return ERR_OK;
+ }
+#endif /* ETHARP_VLAN_CHECK */
+ type = htons(vlan->tpid);
+ }
+#endif /* ETHARP_SUPPORT_VLAN */
+
+ switch (type) {
/* IP packet? */
case ETHTYPE_IP:
#if ETHARP_TRUST_IP_MAC
@@ -1145,7 +1182,7 @@ ethernet_input(struct pbuf *p, struct netif *netif)
etharp_ip_input(netif, p);
#endif /* ETHARP_TRUST_IP_MAC */
/* skip Ethernet header */
- if(pbuf_header(p, -(s16_t)sizeof(struct eth_hdr))) {
+ if(pbuf_header(p, -(s16_t)SIZEOF_ETH_HDR)) {
LWIP_ASSERT("Can't move over header in packet", 0);
pbuf_free(p);
p = NULL;
diff --git a/net/lwip/src/netif/ethernetif.c b/net/lwip/src/netif/ethernetif.c
index 9eeee00c6c..63934d3993 100644
--- a/net/lwip/src/netif/ethernetif.c
+++ b/net/lwip/src/netif/ethernetif.c
@@ -301,26 +301,18 @@ FINSH_FUNCTION_EXPORT(set_dns, set DNS server address);
void list_if()
{
- struct ip_addr ip_addr;
- struct _ip_addr
- {
- rt_uint8_t addr0, addr1, addr2, addr3;
- } *addr;
-
rt_kprintf("Default network interface: %c%c\n", netif_default->name[0], netif_default->name[1]);
- addr = (struct _ip_addr*)&netif_default->ip_addr.addr;
- rt_kprintf("ip address: %d.%d.%d.%d\n", addr->addr0, addr->addr1, addr->addr2, addr->addr3);
-
- addr = (struct _ip_addr*)&netif_default->gw.addr;
- rt_kprintf("gw address: %d.%d.%d.%d\n", addr->addr0, addr->addr1, addr->addr2, addr->addr3);
-
- addr = (struct _ip_addr*)&netif_default->netmask.addr;
- rt_kprintf("net mask : %d.%d.%d.%d\n", addr->addr0, addr->addr1, addr->addr2, addr->addr3);
+ rt_kprintf("ip address: %s\n", ip_ntoa(&(netif_default->ip_addr.addr)));
+ rt_kprintf("gw address: %s\n", ip_ntoa(&(netif_default->ip_addr.addr)));
+ rt_kprintf("net mask : %s\n", ip_ntoa(&(netif_default->ip_addr.addr)));
#if LWIP_DNS
- ip_addr = dns_getserver(0);
- addr = (struct _ip_addr*)&ip_addr;
- rt_kprintf("dns server: %d.%d.%d.%d\n", addr->addr0, addr->addr1, addr->addr2, addr->addr3);
+ {
+ struct ip_addr ip_addr;
+
+ ip_addr = dns_getserver(0);
+ rt_kprintf("dns server: %d.%d.%d.%d\n", ip_ntoa(&ip_addr));
+ }
#endif
}
FINSH_FUNCTION_EXPORT(list_if, list network interface information);
diff --git a/net/lwip/src/netif/ppp/auth.c b/net/lwip/src/netif/ppp/auth.c
index 4c0ee6a8e2..cbd3eb21b0 100644
--- a/net/lwip/src/netif/ppp/auth.c
+++ b/net/lwip/src/netif/ppp/auth.c
@@ -82,6 +82,8 @@
#include "cbcp.h"
#endif /* CBCP_SUPPORT */
+#include <string.h>
+
/*************************/
/*** LOCAL DEFINITIONS ***/
/*************************/
diff --git a/net/lwip/src/netif/ppp/chap.c b/net/lwip/src/netif/ppp/chap.c
index 6d9c3c3cea..b3ea6b2220 100644
--- a/net/lwip/src/netif/ppp/chap.c
+++ b/net/lwip/src/netif/ppp/chap.c
@@ -82,6 +82,7 @@
#include "chap.h"
#include "chpms.h"
+#include <string.h>
/*************************/
/*** LOCAL DEFINITIONS ***/
diff --git a/net/lwip/src/netif/ppp/chpms.c b/net/lwip/src/netif/ppp/chpms.c
index 0c7521f20f..582cfd2dd7 100644
--- a/net/lwip/src/netif/ppp/chpms.c
+++ b/net/lwip/src/netif/ppp/chpms.c
@@ -1,4 +1,7 @@
/*** WARNING - THIS CODE HAS NOT BEEN FINISHED! ***/
+/*** The original PPPD code is written in a way to require either the UNIX DES
+ encryption functions encrypt(3) and setkey(3) or the DES library libdes.
+ Since both is not included in lwIP, MSCHAP currently does not work! */
/*****************************************************************************
* chpms.c - Network MicroSoft Challenge Handshake Authentication Protocol program file.
*
diff --git a/net/lwip/src/netif/ppp/fsm.c b/net/lwip/src/netif/ppp/fsm.c
index c073f1e368..ee549f230d 100644
--- a/net/lwip/src/netif/ppp/fsm.c
+++ b/net/lwip/src/netif/ppp/fsm.c
@@ -64,6 +64,8 @@
#include "fsm.h"
+#include <string.h>
+
/*************************/
/*** LOCAL DEFINITIONS ***/
@@ -551,7 +553,7 @@ fsm_timeout(void *arg)
break;
default:
- FSMDEBUG((LOG_INFO, "%s: Timeout event in state %d (%s)!\n",
+ FSMDEBUG((LOG_INFO, "%s: UNHANDLED timeout event in state %d (%s)!\n",
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
}
}
diff --git a/net/lwip/src/netif/ppp/ipcp.c b/net/lwip/src/netif/ppp/ipcp.c
index 3a403a0a6d..0ff4ce3fff 100644
--- a/net/lwip/src/netif/ppp/ipcp.c
+++ b/net/lwip/src/netif/ppp/ipcp.c
@@ -183,20 +183,7 @@ static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
/*** LOCAL FUNCTION DEFINITIONS ***/
/**********************************/
-/*
- * Non-standard inet_ntoa left here for compat with original ppp
- * sources. Assumes u32_t instead of struct in_addr.
- */
-
-char *
-_inet_ntoa(u32_t n)
-{
- struct in_addr ia;
- ia.s_addr = n;
- return inet_ntoa(ia);
-}
-
-#define inet_ntoa _inet_ntoa
+#define inet_ntoa(addr) ip_ntoa(((struct ip_addr*)&(addr)))
/*
* ipcp_init - Initialize IPCP.
diff --git a/net/lwip/src/netif/ppp/md5.c b/net/lwip/src/netif/ppp/md5.c
index d65ecedbfa..7a60d78325 100644
--- a/net/lwip/src/netif/ppp/md5.c
+++ b/net/lwip/src/netif/ppp/md5.c
@@ -42,6 +42,8 @@
#include "md5.h"
+#include <string.h>
+
/*
***********************************************************************
** Message-digest routines: **
diff --git a/net/lwip/src/netif/ppp/pap.c b/net/lwip/src/netif/ppp/pap.c
index 7c3fd7e4cf..e8c45dff9c 100644
--- a/net/lwip/src/netif/ppp/pap.c
+++ b/net/lwip/src/netif/ppp/pap.c
@@ -61,6 +61,8 @@
#include "auth.h"
#include "pap.h"
+#include <string.h>
+
/***********************************/
/*** LOCAL FUNCTION DECLARATIONS ***/
/***********************************/
@@ -490,6 +492,7 @@ upap_rauthack(upap_state *u, u_char *inp, int id, int len)
msg = (char *) inp;
PRINTMSG(msg, msglen);
+ UNTIMEOUT(upap_timeout, u); /* Cancel timeout */
u->us_clientstate = UPAPCS_OPEN;
auth_withpeer_success(u->us_unit, PPP_PAP);
diff --git a/net/lwip/src/netif/ppp/ppp.c b/net/lwip/src/netif/ppp/ppp.c
index 8720c3368a..13fa5ed090 100644
--- a/net/lwip/src/netif/ppp/ppp.c
+++ b/net/lwip/src/netif/ppp/ppp.c
@@ -166,7 +166,7 @@ typedef struct PPPControl_s {
ext_accm outACCM; /* Async-Ctl-Char-Map for output. */
#if PPPOS_SUPPORT && VJ_SUPPORT
int vjEnabled; /* Flag indicating VJ compression enabled. */
- struct vjcompress vjComp; /* Van Jabobsen compression header. */
+ struct vjcompress vjComp; /* Van Jacobson compression header. */
#endif /* PPPOS_SUPPORT && VJ_SUPPORT */
struct netif netif;
@@ -235,7 +235,7 @@ struct protent *ppp_protocols[] = {
* Buffers for outgoing packets. This must be accessed only from the appropriate
* PPP task so that it doesn't need to be protected to avoid collisions.
*/
-u_char *outpacket_buf[NUM_PPP];
+u_char outpacket_buf[NUM_PPP][PPP_MRU+PPP_HDRLEN];
/*****************************/
@@ -306,13 +306,11 @@ pppMainWakeup(int pd)
void
pppLinkTerminated(int pd)
{
- PPPControl *pc = &pppControl[pd];
-
PPPDEBUG((LOG_DEBUG, "pppLinkTerminated: unit %d\n", pd));
#if PPPOE_SUPPORT
- if(pc->ethif) {
- pppoe_disconnect(pc->pppoe_sc);
+ if(pppControl[pd].ethif) {
+ pppoe_disconnect(pppControl[pd].pppoe_sc);
} else
#endif /* PPPOE_SUPPORT */
{
@@ -325,13 +323,11 @@ pppLinkTerminated(int pd)
void
pppLinkDown(int pd)
{
- PPPControl *pc = &pppControl[pd];
-
PPPDEBUG((LOG_DEBUG, "pppLinkDown: unit %d\n", pd));
#if PPPOE_SUPPORT
- if(pc->ethif) {
- pppoe_disconnect(pc->pppoe_sc);
+ if(pppControl[pd].ethif) {
+ pppoe_disconnect(pppControl[pd].pppoe_sc);
} else
#endif /* PPPOE_SUPPORT */
{
@@ -383,7 +379,7 @@ pppHupCB(void *arg)
struct ppp_settings ppp_settings;
-err_t
+void
pppInit(void)
{
struct protent *protp;
@@ -395,16 +391,11 @@ pppInit(void)
magicInit();
+ subnetMask = htonl(0xffffff00);
+
for (i = 0; i < NUM_PPP; i++) {
pppControl[i].openFlag = 0;
- subnetMask = htonl(0xffffff00);
-
- outpacket_buf[i] = (u_char *)mem_malloc(PPP_MRU+PPP_HDRLEN);
- if(!outpacket_buf[i]) {
- return ERR_MEM;
- }
-
/*
* Initialize to the standard option set.
*/
@@ -413,17 +404,9 @@ pppInit(void)
}
}
-#if LINK_STATS
- /** @todo already done in stats_init (in fact, zeroed at boot). So, remove it? */
- /* Clear the statistics. */
- memset(&lwip_stats.link, 0, sizeof(lwip_stats.link));
-#endif /* LINK_STATS */
-
#if PPPOE_SUPPORT
pppoe_init();
#endif /* PPPOE_SUPPORT */
-
- return ERR_OK;
}
void
@@ -601,7 +584,7 @@ int pppOverEthernetOpen(struct netif *ethif, const char *service_name, const cha
pppControl[pd].openFlag = !0;
}
- /* Launch a deamon thread. */
+ /* PPP session descriptor found, start PPPoE */
if (pd >= 0) {
pppControl[pd].openFlag = 1;
@@ -824,9 +807,9 @@ static err_t
pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *ipaddr)
{
int pd = (int)netif->state;
- u_short protocol = PPP_IP;
PPPControl *pc = &pppControl[pd];
#if PPPOS_SUPPORT
+ u_short protocol = PPP_IP;
u_int fcsOut = PPP_INITFCS;
struct pbuf *headMB = NULL, *tailMB = NULL, *p;
u_char c;
@@ -839,7 +822,7 @@ pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *ipaddr)
* and the peer will just drop it if it's not accepting it. */
if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !pb) {
PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad parms prot=%d pb=%p\n",
- pd, protocol, pb));
+ pd, PPP_IP, pb));
LINK_STATS_INC(link.opterr);
LINK_STATS_INC(link.drop);
return ERR_ARG;
@@ -1294,7 +1277,7 @@ GetMask(u32_t addr)
* sifvjcomp - config tcp header compression
*/
int
-sifvjcomp( int pd, int vjcomp, int cidcomp, int maxcid)
+sifvjcomp(int pd, int vjcomp, int cidcomp, int maxcid)
{
#if PPPOS_SUPPORT && VJ_SUPPORT
PPPControl *pc = &pppControl[pd];
@@ -1304,6 +1287,11 @@ sifvjcomp( int pd, int vjcomp, int cidcomp, int maxcid)
pc->vjComp.maxSlotIndex = maxcid;
PPPDEBUG((LOG_INFO, "sifvjcomp: VJ compress enable=%d slot=%d max slot=%d\n",
vjcomp, cidcomp, maxcid));
+#else /* PPPOS_SUPPORT && VJ_SUPPORT */
+ LWIP_UNUSED_ARG(pd);
+ LWIP_UNUSED_ARG(vjcomp);
+ LWIP_UNUSED_ARG(cidcomp);
+ LWIP_UNUSED_ARG(maxcid);
#endif /* PPPOS_SUPPORT && VJ_SUPPORT */
return 0;
@@ -1381,6 +1369,8 @@ sifdown(int pd)
PPPDEBUG((LOG_WARNING, "sifdown[%d]: bad parms\n", pd));
} else {
pc->if_up = 0;
+ /* make sure the netif status callback is called */
+ netif_set_down(&pc->netif);
netif_remove(&pc->netif);
PPPDEBUG((LOG_DEBUG, "sifdown: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
if(pc->linkStatusCB) {
@@ -1537,8 +1527,8 @@ pppMain(void *arg)
if(c > 0) {
pppInProc(pd, p->payload, c);
} else {
- PPPDEBUG((LOG_DEBUG, "pppMain: unit %d sio_read len=%d returned %d\n", pd, p->len, c));
- sys_msleep(1); /* give other tasks a chance to run */
+ /* nothing received, give other tasks a chance to run */
+ sys_msleep(1);
}
}
}
@@ -1658,7 +1648,7 @@ pppInput(void *arg)
switch(protocol) {
case PPP_VJC_COMP: /* VJ compressed TCP */
-#if VJ_SUPPORT
+#if PPPOS_SUPPORT && VJ_SUPPORT
PPPDEBUG((LOG_INFO, "pppInput[%d]: vj_comp in pbuf len=%d\n", pd, nb->len));
/*
* Clip off the VJ header and prepend the rebuilt TCP/IP header and
@@ -1670,14 +1660,14 @@ pppInput(void *arg)
}
/* Something's wrong so drop it. */
PPPDEBUG((LOG_WARNING, "pppInput[%d]: Dropping VJ compressed\n", pd));
-#else /* VJ_SUPPORT */
+#else /* PPPOS_SUPPORT && VJ_SUPPORT */
/* No handler for this protocol so drop the packet. */
PPPDEBUG((LOG_INFO, "pppInput[%d]: drop VJ Comp in %d:%s\n", pd, nb->len, nb->payload));
-#endif /* VJ_SUPPORT */
+#endif /* PPPOS_SUPPORT && VJ_SUPPORT */
break;
case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */
-#if VJ_SUPPORT
+#if PPPOS_SUPPORT && VJ_SUPPORT
PPPDEBUG((LOG_INFO, "pppInput[%d]: vj_un in pbuf len=%d\n", pd, nb->len));
/*
* Process the TCP/IP header for VJ header compression and then pass
@@ -1689,12 +1679,12 @@ pppInput(void *arg)
}
/* Something's wrong so drop it. */
PPPDEBUG((LOG_WARNING, "pppInput[%d]: Dropping VJ uncompressed\n", pd));
-#else /* VJ_SUPPORT */
+#else /* PPPOS_SUPPORT && VJ_SUPPORT */
/* No handler for this protocol so drop the packet. */
PPPDEBUG((LOG_INFO,
"pppInput[%d]: drop VJ UnComp in %d:.*H\n",
pd, nb->len, LWIP_MIN(nb->len * 2, 40), nb->payload));
-#endif /* VJ_SUPPORT */
+#endif /* PPPOS_SUPPORT && VJ_SUPPORT */
break;
case PPP_IP: /* Internet Protocol */
diff --git a/net/lwip/src/netif/ppp/ppp.h b/net/lwip/src/netif/ppp/ppp.h
index d5caa0a7ed..ebc733be65 100644
--- a/net/lwip/src/netif/ppp/ppp.h
+++ b/net/lwip/src/netif/ppp/ppp.h
@@ -333,7 +333,7 @@ struct ppp_addrs {
*****************************/
/* Buffers for outgoing packets. */
-extern u_char *outpacket_buf[NUM_PPP];
+extern u_char outpacket_buf[NUM_PPP][PPP_MRU+PPP_HDRLEN];
extern struct ppp_settings ppp_settings;
@@ -345,7 +345,7 @@ extern struct protent *ppp_protocols[]; /* Table of pointers to supported protoc
***********************/
/* Initialize the PPP subsystem. */
-err_t pppInit(void);
+void pppInit(void);
/* Warning: Using PPPAUTHTYPE_ANY might have security consequences.
* RFC 1994 says:
diff --git a/net/lwip/src/netif/ppp/ppp_oe.c b/net/lwip/src/netif/ppp/ppp_oe.c
index c34c529b6f..5a8a45cf6b 100644
--- a/net/lwip/src/netif/ppp/ppp_oe.c
+++ b/net/lwip/src/netif/ppp/ppp_oe.c
@@ -398,7 +398,7 @@ pppoe_dispatch_disc_pkt(struct netif *netif, struct pbuf *pb)
#endif
struct pppoehdr *ph;
struct pppoetag pt;
- int off = 0, err, errortag;
+ int off, err, errortag;
struct eth_hdr *ethhdr;
pb = pppSingleBuf(pb);
@@ -410,7 +410,7 @@ pppoe_dispatch_disc_pkt(struct netif *netif, struct pbuf *pb)
goto done;
}
ethhdr = (struct eth_hdr *)pb->payload;
- off += sizeof(*ethhdr);
+ off = sizeof(*ethhdr);
ac_cookie = NULL;
ac_cookie_len = 0;
@@ -419,7 +419,7 @@ pppoe_dispatch_disc_pkt(struct netif *netif, struct pbuf *pb)
hunique_len = 0;
#endif
session = 0;
- if (pb->len - off <= PPPOE_HEADERLEN) {
+ if (pb->len - off < PPPOE_HEADERLEN) {
printf("pppoe: packet too short: %d\n", pb->len);
goto done;
}
diff --git a/net/lwip/src/netif/ppp/randm.c b/net/lwip/src/netif/ppp/randm.c
index 0c622a0b0a..83c4174171 100644
--- a/net/lwip/src/netif/ppp/randm.c
+++ b/net/lwip/src/netif/ppp/randm.c
@@ -41,6 +41,7 @@
#include "ppp.h"
#include "pppdebug.h"
+#include <string.h>
#if MD5_SUPPORT /* this module depends on MD5 */
#define RANDPOOLSZ 16 /* Bytes stored in the pool of randomness. */
diff --git a/net/lwip/src/netif/ppp/vj.c b/net/lwip/src/netif/ppp/vj.c
index 814ea72c5e..694b7027d0 100644
--- a/net/lwip/src/netif/ppp/vj.c
+++ b/net/lwip/src/netif/ppp/vj.c
@@ -136,7 +136,7 @@ vj_compress_init(struct vjcompress *comp)
}
/*
- * vj_compress_tcp - Attempt to do Van Jacobsen header compression on a
+ * vj_compress_tcp - Attempt to do Van Jacobson header compression on a
* packet. This assumes that nb and comp are not null and that the first
* buffer of the chain contains a valid IP header.
* Return the VJ type code indicating whether or not the packet was
diff --git a/net/lwip/src/netif/slipif.c b/net/lwip/src/netif/slipif.c
index 6cb2db4424..089d2d3eb8 100644
--- a/net/lwip/src/netif/slipif.c
+++ b/net/lwip/src/netif/slipif.c
@@ -39,7 +39,7 @@
/*
* This is an arch independent SLIP netif. The specific serial hooks must be
- * provided by another file. They are sio_open, sio_recv and sio_send
+ * provided by another file. They are sio_open, sio_read/sio_tryread and sio_send
*/
#include "netif/slipif.h"
@@ -54,12 +54,28 @@
#include "lwip/snmp.h"
#include "lwip/sio.h"
+#define SLIP_BLOCK 1
+#define SLIP_DONTBLOCK 0
+
#define SLIP_END 0300 /* 0xC0 */
#define SLIP_ESC 0333 /* 0xDB */
#define SLIP_ESC_END 0334 /* 0xDC */
#define SLIP_ESC_ESC 0335 /* 0xDD */
-#define MAX_SIZE 1500
+#define SLIP_MAX_SIZE 1500
+
+enum slipif_recv_state {
+ SLIP_RECV_NORMAL,
+ SLIP_RECV_ESCAPE,
+};
+
+struct slipif_priv {
+ sio_fd_t sd;
+ /* q is the whole pbuf chain for a packet, p is the current pbuf in the chain */
+ struct pbuf *p, *q;
+ enum slipif_recv_state state;
+ u16_t i, recved;
+};
/**
* Send a pbuf doing the necessary SLIP encapsulation
@@ -74,6 +90,7 @@
err_t
slipif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
{
+ struct slipif_priv *priv;
struct pbuf *q;
u16_t i;
u8_t c;
@@ -84,73 +101,101 @@ slipif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
LWIP_UNUSED_ARG(ipaddr);
+ priv = netif->state;
+
/* Send pbuf out on the serial I/O device. */
- sio_send(SLIP_END, netif->state);
+ sio_send(SLIP_END, priv->sd);
for (q = p; q != NULL; q = q->next) {
for (i = 0; i < q->len; i++) {
c = ((u8_t *)q->payload)[i];
switch (c) {
case SLIP_END:
- sio_send(SLIP_ESC, netif->state);
- sio_send(SLIP_ESC_END, netif->state);
+ sio_send(SLIP_ESC, priv->sd);
+ sio_send(SLIP_ESC_END, priv->sd);
break;
case SLIP_ESC:
- sio_send(SLIP_ESC, netif->state);
- sio_send(SLIP_ESC_ESC, netif->state);
+ sio_send(SLIP_ESC, priv->sd);
+ sio_send(SLIP_ESC_ESC, priv->sd);
break;
default:
- sio_send(c, netif->state);
+ sio_send(c, priv->sd);
break;
}
}
}
- sio_send(SLIP_END, netif->state);
+ sio_send(SLIP_END, priv->sd);
return ERR_OK;
}
/**
+ * Static function for easy use of blockig or non-blocking
+ * sio_read
+ *
+ * @param fd serial device handle
+ * @param data pointer to data buffer for receiving
+ * @param len maximum length (in bytes) of data to receive
+ * @param block if 1, call sio_read; if 0, call sio_tryread
+ * @return return value of sio_read of sio_tryread
+ */
+static u32_t
+slip_sio_read(sio_fd_t fd, u8_t* data, u32_t len, u8_t block)
+{
+ if (block) {
+ return sio_read(fd, data, len);
+ } else {
+ return sio_tryread(fd, data, len);
+ }
+}
+
+/**
* Handle the incoming SLIP stream character by character
*
- * Poll the serial layer by calling sio_recv()
+ * Poll the serial layer by calling sio_read() or sio_tryread().
*
* @param netif the lwip network interface structure for this slipif
- * @return The IP packet when SLIP_END is received
+ * @param block if 1, block until data is received; if 0, return when all data
+ * from the buffer is received (multiple calls to this function will
+ * return a complete packet, NULL is returned before - used for polling)
+ * @return The IP packet when SLIP_END is received
*/
static struct pbuf *
-slipif_input(struct netif *netif)
+slipif_input(struct netif *netif, u8_t block)
{
+ struct slipif_priv *priv;
u8_t c;
- /* q is the whole pbuf chain for a packet, p is the current pbuf in the chain */
- struct pbuf *p, *q;
- u16_t recved;
- u16_t i;
+ struct pbuf *t;
LWIP_ASSERT("netif != NULL", (netif != NULL));
LWIP_ASSERT("netif->state != NULL", (netif->state != NULL));
- q = p = NULL;
- recved = i = 0;
- c = 0;
+ priv = netif->state;
- while (1) {
- c = sio_recv(netif->state);
- switch (c) {
- case SLIP_END:
- if (recved > 0) {
- /* Received whole packet. */
- /* Trim the pbuf to the size of the received packet. */
- pbuf_realloc(q, recved);
-
- LINK_STATS_INC(link.recv);
-
- LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet\n"));
- return q;
+ while (slip_sio_read(priv->sd, &c, 1, block) > 0) {
+ switch (priv->state) {
+ case SLIP_RECV_NORMAL:
+ switch (c) {
+ case SLIP_END:
+ if (priv->recved > 0) {
+ /* Received whole packet. */
+ /* Trim the pbuf to the size of the received packet. */
+ pbuf_realloc(priv->q, priv->recved);
+
+ LINK_STATS_INC(link.recv);
+
+ LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet\n"));
+ t = priv->q;
+ priv->p = priv->q = NULL;
+ priv->i = priv->recved = 0;
+ return t;
+ }
+ continue;
+ case SLIP_ESC:
+ priv->state = SLIP_RECV_ESCAPE;
+ continue;
}
break;
-
- case SLIP_ESC:
- c = sio_recv(netif->state);
+ case SLIP_RECV_ESCAPE:
switch (c) {
case SLIP_ESC_END:
c = SLIP_END;
@@ -159,52 +204,52 @@ slipif_input(struct netif *netif)
c = SLIP_ESC;
break;
}
+ priv->state = SLIP_RECV_NORMAL;
/* FALLTHROUGH */
+ }
- default:
- /* byte received, packet not yet completely received */
- if (p == NULL) {
- /* allocate a new pbuf */
- LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n"));
- p = pbuf_alloc(PBUF_LINK, PBUF_POOL_BUFSIZE, PBUF_POOL);
+ /* byte received, packet not yet completely received */
+ if (priv->p == NULL) {
+ /* allocate a new pbuf */
+ LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n"));
+ priv->p = pbuf_alloc(PBUF_LINK, (PBUF_POOL_BUFSIZE - PBUF_LINK_HLEN), PBUF_POOL);
- if (p == NULL) {
- LINK_STATS_INC(link.drop);
- LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n"));
- /* don't process any further since we got no pbuf to receive to */
- break;
- }
+ if (priv->p == NULL) {
+ LINK_STATS_INC(link.drop);
+ LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n"));
+ /* don't process any further since we got no pbuf to receive to */
+ break;
+ }
- if (q != NULL) {
- /* 'chain' the pbuf to the existing chain */
- pbuf_cat(q, p);
- } else {
- /* p is the first pbuf in the chain */
- q = p;
- }
+ if (priv->q != NULL) {
+ /* 'chain' the pbuf to the existing chain */
+ pbuf_cat(priv->q, priv->p);
+ } else {
+ /* p is the first pbuf in the chain */
+ priv->q = priv->p;
}
+ }
- /* this automatically drops bytes if > MAX_SIZE */
- if ((p != NULL) && (recved <= MAX_SIZE)) {
- ((u8_t *)p->payload)[i] = c;
- recved++;
- i++;
- if (i >= p->len) {
- /* on to the next pbuf */
- i = 0;
- if (p->next != NULL && p->next->len > 0) {
- /* p is a chain, on to the next in the chain */
- p = p->next;
- } else {
- /* p is a single pbuf, set it to NULL so next time a new
- * pbuf is allocated */
- p = NULL;
- }
+ /* this automatically drops bytes if > SLIP_MAX_SIZE */
+ if ((priv->p != NULL) && (priv->recved <= SLIP_MAX_SIZE)) {
+ ((u8_t *)priv->p->payload)[priv->i] = c;
+ priv->recved++;
+ priv->i++;
+ if (priv->i >= priv->p->len) {
+ /* on to the next pbuf */
+ priv->i = 0;
+ if (priv->p->next != NULL && priv->p->next->len > 0) {
+ /* p is a chain, on to the next in the chain */
+ priv->p = priv->p->next;
+ } else {
+ /* p is a single pbuf, set it to NULL so next time a new
+ * pbuf is allocated */
+ priv->p = NULL;
}
}
- break;
}
}
+
return NULL;
}
@@ -217,13 +262,13 @@ slipif_input(struct netif *netif)
* @param nf the lwip network interface structure for this slipif
*/
static void
-slipif_loop(void *nf)
+slipif_loop_thread(void *nf)
{
struct pbuf *p;
struct netif *netif = (struct netif *)nf;
while (1) {
- p = slipif_input(netif);
+ p = slipif_input(netif, SLIP_BLOCK);
if (p != NULL) {
if (netif->input(p, netif) != ERR_OK) {
pbuf_free(p);
@@ -242,6 +287,7 @@ slipif_loop(void *nf)
*
* @param netif the lwip network interface structure for this slipif
* @return ERR_OK if serial line could be opened,
+ * ERR_MEM if no memory could be allocated,
* ERR_IF is serial line couldn't be opened
*
* @note netif->num must contain the number of the serial port to open
@@ -250,22 +296,39 @@ slipif_loop(void *nf)
err_t
slipif_init(struct netif *netif)
{
+ struct slipif_priv *priv;
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%"U16_F"\n", (u16_t)netif->num));
+ /* Allocate private data */
+ priv = mem_malloc(sizeof(struct slipif_priv));
+ if (!priv) {
+ return ERR_MEM;
+ }
+
netif->name[0] = 's';
netif->name[1] = 'l';
netif->output = slipif_output;
- netif->mtu = MAX_SIZE;
- netif->flags = NETIF_FLAG_POINTTOPOINT;
+ netif->mtu = SLIP_MAX_SIZE;
+ netif->flags |= NETIF_FLAG_POINTTOPOINT;
/* Try to open the serial port (netif->num contains the port number). */
- netif->state = sio_open(netif->num);
- if (!netif->state) {
+ priv->sd = sio_open(netif->num);
+ if (!priv->sd) {
/* Opening the serial port failed. */
+ mem_free(priv);
return ERR_IF;
}
+ /* Initialize private data */
+ priv->p = NULL;
+ priv->q = NULL;
+ priv->state = SLIP_RECV_NORMAL;
+ priv->i = 0;
+ priv->recved = 0;
+
+ netif->state = priv;
+
/* initialize the snmp variables and counters inside the struct netif
* ifSpeed: no assumption can be made without knowing more about the
* serial line!
@@ -273,7 +336,32 @@ slipif_init(struct netif *netif)
NETIF_INIT_SNMP(netif, snmp_ifType_slip, 0);
/* Create a thread to poll the serial line. */
- sys_thread_new(SLIPIF_THREAD_NAME, slipif_loop, netif, SLIPIF_THREAD_STACKSIZE, SLIPIF_THREAD_PRIO);
+ sys_thread_new(SLIPIF_THREAD_NAME, slipif_loop_thread, netif,
+ SLIPIF_THREAD_STACKSIZE, SLIPIF_THREAD_PRIO);
return ERR_OK;
}
+
+/**
+ * Polls the serial device and feeds the IP layer with incoming packets.
+ *
+ * @param netif The lwip network interface structure for this slipif
+ */
+void
+slipif_poll(struct netif *netif)
+{
+ struct pbuf *p;
+ struct slipif_priv *priv;
+
+ LWIP_ASSERT("netif != NULL", (netif != NULL));
+ LWIP_ASSERT("netif->state != NULL", (netif->state != NULL));
+
+ priv = netif->state;
+
+ while ((p = slipif_input(netif, SLIP_DONTBLOCK)) != NULL) {
+ if (netif->input(p, netif) != ERR_OK) {
+ pbuf_free(p);
+ }
+ }
+}
+
#endif /* LWIP_HAVE_SLIPIF */
diff --git a/net/lwip/test/unit/lwip_check.h b/net/lwip/test/unit/lwip_check.h
new file mode 100644
index 0000000000..d8984a127c
--- /dev/null
+++ b/net/lwip/test/unit/lwip_check.h
@@ -0,0 +1,37 @@
+#ifndef __LWIP_CHECK_H__
+#define __LWIP_CHECK_H__
+
+/* Common header file for lwIP unit tests using the check framework */
+
+#include <config.h>
+#include <check.h>
+#include <stdlib.h>
+
+#define FAIL_RET() do { fail(); return; } while(0)
+#define EXPECT(x) fail_unless(x)
+#define EXPECT_RET(x) do { fail_unless(x); if(!(x)) { return; }} while(0)
+#define EXPECT_RETX(x, y) do { fail_unless(x); if(!(x)) { return y; }} while(0)
+#define EXPECT_RETNULL(x) EXPECT_RETX(x, NULL)
+
+/** typedef for a function returning a test suite */
+typedef Suite* (suite_getter_fn)(void);
+
+/** Create a test suite */
+static Suite* create_suite(const char* name, TFun *tests, size_t num_tests, SFun setup, SFun teardown)
+{
+ size_t i;
+ Suite *s = suite_create(name);
+
+ for(i = 0; i < num_tests; i++) {
+ // Core test case
+ TCase *tc_core = tcase_create("Core");
+ if ((setup != NULL) || (teardown != NULL)) {
+ tcase_add_checked_fixture(tc_core, setup, teardown);
+ }
+ tcase_add_test(tc_core, tests[i]);
+ suite_add_tcase(s, tc_core);
+ }
+ return s;
+}
+
+#endif /* __LWIP_CHECK_H__ */
diff --git a/net/lwip/test/unit/lwip_unittests.c b/net/lwip/test/unit/lwip_unittests.c
new file mode 100644
index 0000000000..2dbeb6d45a
--- /dev/null
+++ b/net/lwip/test/unit/lwip_unittests.c
@@ -0,0 +1,42 @@
+#include "lwip_check.h"
+
+#include "udp/test_udp.h"
+#include "tcp/test_tcp.h"
+#include "tcp/test_tcp_oos.h"
+
+#include "lwip/init.h"
+
+
+int main()
+{
+ int number_failed;
+ SRunner *sr;
+ size_t i;
+ suite_getter_fn* suites[] = {
+ udp_suite,
+ tcp_suite,
+ tcp_oos_suite,
+ };
+ size_t num = sizeof(suites)/sizeof(void*);
+ LWIP_ASSERT("No suites defined", num > 0);
+
+ lwip_init();
+
+ sr = srunner_create((suites[0])());
+ for(i = 1; i < num; i++) {
+ srunner_add_suite(sr, ((suite_getter_fn*)suites[i])());
+ }
+
+#ifdef LWIP_UNITTESTS_NOFORK
+ srunner_set_fork_status(sr, CK_NOFORK);
+#endif
+#ifdef LWIP_UNITTESTS_FORK
+ srunner_set_fork_status(sr, CK_FORK);
+#endif
+
+ srunner_run_all(sr, CK_NORMAL);
+ number_failed = srunner_ntests_failed(sr);
+ srunner_free(sr);
+ return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
diff --git a/net/lwip/test/unit/tcp/tcp_helper.c b/net/lwip/test/unit/tcp/tcp_helper.c
new file mode 100644
index 0000000000..0957cbe42e
--- /dev/null
+++ b/net/lwip/test/unit/tcp/tcp_helper.c
@@ -0,0 +1,196 @@
+#include "tcp_helper.h"
+
+#include "lwip/tcp.h"
+#include "lwip/stats.h"
+#include "lwip/pbuf.h"
+#include "lwip/inet_chksum.h"
+
+#if !LWIP_STATS || !TCP_STATS || !MEMP_STATS
+#error "This tests needs TCP- and MEMP-statistics enabled"
+#endif
+
+/** Remove all pcbs on the given list. */
+static void
+tcp_remove(struct tcp_pcb* pcb_list)
+{
+ struct tcp_pcb *pcb = pcb_list;
+ struct tcp_pcb *pcb2;
+
+ while(pcb != NULL) {
+ pcb2 = pcb;
+ pcb = pcb->next;
+ tcp_abort(pcb2);
+ }
+}
+
+/** Remove all pcbs on listen-, active- and time-wait-list (bound- isn't exported). */
+void
+tcp_remove_all(void)
+{
+ //tcp_remove(tcp_bound_pcbs);
+ tcp_remove(tcp_listen_pcbs.pcbs);
+ tcp_remove(tcp_active_pcbs);
+ tcp_remove(tcp_tw_pcbs);
+ fail_unless(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
+ fail_unless(lwip_stats.memp[MEMP_TCP_PCB_LISTEN].used == 0);
+ fail_unless(lwip_stats.memp[MEMP_TCP_SEG].used == 0);
+ fail_unless(lwip_stats.memp[MEMP_PBUF_POOL].used == 0);
+}
+
+/** Create a TCP segment usable for passing to tcp_input
+ * - IP-addresses, ports, seqno and ackno are taken from pcb
+ * - seqno and ackno can be altered with an offset
+ */
+struct pbuf*
+tcp_create_rx_segment(struct tcp_pcb* pcb, void* data, size_t data_len, u32_t seqno_offset,
+ u32_t ackno_offset, u8_t headerflags)
+{
+ return tcp_create_segment(&pcb->remote_ip, &pcb->local_ip, pcb->remote_port, pcb->local_port,
+ data, data_len, pcb->rcv_nxt + seqno_offset, pcb->snd_nxt + ackno_offset, headerflags);
+}
+
+/** Create a TCP segment usable for passing to tcp_input */
+struct pbuf*
+tcp_create_segment(struct ip_addr* src_ip, struct ip_addr* dst_ip,
+ u16_t src_port, u16_t dst_port, void* data, size_t data_len,
+ u32_t seqno, u32_t ackno, u8_t headerflags)
+{
+ struct pbuf* p;
+ struct ip_hdr* iphdr;
+ struct tcp_hdr* tcphdr;
+ u16_t pbuf_len = sizeof(struct ip_hdr) + sizeof(struct tcp_hdr) + data_len;
+
+ p = pbuf_alloc(PBUF_RAW, pbuf_len, PBUF_POOL);
+ EXPECT_RETNULL(p != NULL);
+ EXPECT_RETNULL(p->next == NULL);
+
+ memset(p->payload, 0, p->len);
+
+ iphdr = p->payload;
+ /* fill IP header */
+ iphdr->dest.addr = dst_ip->addr;
+ iphdr->src.addr = src_ip->addr;
+ IPH_VHLTOS_SET(iphdr, 4, IP_HLEN / 4, 0);
+ IPH_LEN_SET(iphdr, htons(p->tot_len));
+ IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
+
+ pbuf_header(p, -(s16_t)sizeof(struct ip_hdr));
+
+ tcphdr = p->payload;
+ tcphdr->src = htons(src_port);
+ tcphdr->dest = htons(dst_port);
+ tcphdr->seqno = htonl(seqno);
+ tcphdr->ackno = htonl(ackno);
+ TCPH_HDRLEN_SET(tcphdr, sizeof(struct tcp_hdr)/4);
+ TCPH_FLAGS_SET(tcphdr, headerflags);
+ tcphdr->wnd = htonl(TCP_WND);
+
+ /* copy data */
+ memcpy((char*)tcphdr + sizeof(struct tcp_hdr), data, data_len);
+
+ /* calculate checksum */
+ tcphdr->chksum = inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest),
+ IP_PROTO_TCP, p->tot_len);
+
+ pbuf_header(p, sizeof(struct ip_hdr));
+
+ return p;
+}
+
+/** Safely bring a tcp_pcb into the requested state */
+void
+tcp_set_state(struct tcp_pcb* pcb, enum tcp_state state, struct ip_addr* local_ip,
+ struct ip_addr* remote_ip, u16_t local_port, u16_t remote_port)
+{
+ /* @todo: are these all states? */
+ /* @todo: remove from previous list */
+ pcb->state = state;
+ if (state == ESTABLISHED) {
+ TCP_REG(&tcp_active_pcbs, pcb);
+ pcb->local_ip.addr = local_ip->addr;
+ pcb->local_port = local_port;
+ pcb->remote_ip.addr = remote_ip->addr;
+ pcb->remote_port = remote_port;
+ } else if(state == LISTEN) {
+ TCP_REG(&tcp_listen_pcbs.pcbs, pcb);
+ pcb->local_ip.addr = local_ip->addr;
+ pcb->local_port = local_port;
+ } else if(state == TIME_WAIT) {
+ TCP_REG(&tcp_tw_pcbs, pcb);
+ pcb->local_ip.addr = local_ip->addr;
+ pcb->local_port = local_port;
+ pcb->remote_ip.addr = remote_ip->addr;
+ pcb->remote_port = remote_port;
+ } else {
+ fail();
+ }
+}
+
+void
+test_tcp_counters_err(void* arg, err_t err)
+{
+ struct test_tcp_counters* counters = arg;
+ EXPECT_RET(arg != NULL);
+ counters->err_calls++;
+ counters->last_err = err;
+}
+
+static void
+test_tcp_counters_check_rxdata(struct test_tcp_counters* counters, struct pbuf* p)
+{
+ struct pbuf* q;
+ u32_t i, received;
+ if(counters->expected_data == NULL) {
+ /* no data to compare */
+ return;
+ }
+ EXPECT_RET(counters->recved_bytes + p->tot_len <= counters->expected_data_len);
+ received = counters->recved_bytes;
+ for(q = p; q != NULL; q = q->next) {
+ char *data = q->payload;
+ for(i = 0; i < q->len; i++) {
+ EXPECT_RET(data[i] == counters->expected_data[received]);
+ received++;
+ }
+ }
+ EXPECT(received == counters->recved_bytes + p->tot_len);
+}
+
+err_t
+test_tcp_counters_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err)
+{
+ struct test_tcp_counters* counters = arg;
+ EXPECT_RETX(arg != NULL, ERR_OK);
+ EXPECT_RETX(pcb != NULL, ERR_OK);
+ EXPECT_RETX(err == ERR_OK, ERR_OK);
+
+ if (p != NULL) {
+ if (counters->close_calls == 0) {
+ counters->recv_calls++;
+ test_tcp_counters_check_rxdata(counters, p);
+ counters->recved_bytes += p->tot_len;
+ } else {
+ counters->recv_calls_after_close++;
+ counters->recved_bytes_after_close += p->tot_len;
+ }
+ pbuf_free(p);
+ } else {
+ counters->close_calls++;
+ }
+ EXPECT(counters->recv_calls_after_close == 0 && counters->recved_bytes_after_close == 0);
+ return ERR_OK;
+}
+
+/** Allocate a pcb and set up the test_tcp_counters_* callbacks */
+struct tcp_pcb*
+test_tcp_new_counters_pcb(struct test_tcp_counters* counters)
+{
+ struct tcp_pcb* pcb = tcp_new();
+ if (pcb != NULL) {
+ /* set up args and callbacks */
+ tcp_arg(pcb, counters);
+ tcp_recv(pcb, test_tcp_counters_recv);
+ tcp_err(pcb, test_tcp_counters_err);
+ }
+ return pcb;
+}
diff --git a/net/lwip/test/unit/tcp/tcp_helper.h b/net/lwip/test/unit/tcp/tcp_helper.h
new file mode 100644
index 0000000000..b61e0f0af3
--- /dev/null
+++ b/net/lwip/test/unit/tcp/tcp_helper.h
@@ -0,0 +1,36 @@
+#ifndef __TCP_HELPER_H__
+#define __TCP_HELPER_H__
+
+#include "../lwip_check.h"
+#include "lwip/arch.h"
+#include "lwip/tcp.h"
+
+/* counters used for test_tcp_counters_* callback functions */
+struct test_tcp_counters {
+ u32_t recv_calls;
+ u32_t recved_bytes;
+ u32_t recv_calls_after_close;
+ u32_t recved_bytes_after_close;
+ u32_t close_calls;
+ u32_t err_calls;
+ err_t last_err;
+ char* expected_data;
+ u32_t expected_data_len;
+};
+
+/* Helper functions */
+void tcp_remove_all(void);
+
+struct pbuf* tcp_create_segment(struct ip_addr* src_ip, struct ip_addr* dst_ip,
+ u16_t src_port, u16_t dst_port, void* data, size_t data_len,
+ u32_t seqno, u32_t ackno, u8_t headerflags);
+struct pbuf* tcp_create_rx_segment(struct tcp_pcb* pcb, void* data, size_t data_len,
+ u32_t seqno_offset, u32_t ackno_offset, u8_t headerflags);
+void tcp_set_state(struct tcp_pcb* pcb, enum tcp_state state, struct ip_addr* local_ip,
+ struct ip_addr* remote_ip, u16_t local_port, u16_t remote_port);
+void test_tcp_counters_err(void* arg, err_t err);
+err_t test_tcp_counters_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err);
+
+struct tcp_pcb* test_tcp_new_counters_pcb(struct test_tcp_counters* counters);
+
+#endif
diff --git a/net/lwip/test/unit/tcp/test_tcp.c b/net/lwip/test/unit/tcp/test_tcp.c
new file mode 100644
index 0000000000..350cb0cb93
--- /dev/null
+++ b/net/lwip/test/unit/tcp/test_tcp.c
@@ -0,0 +1,104 @@
+#include "test_tcp.h"
+
+#include "lwip/tcp.h"
+#include "lwip/stats.h"
+#include "tcp_helper.h"
+
+#if !LWIP_STATS || !TCP_STATS || !MEMP_STATS
+#error "This tests needs TCP- and MEMP-statistics enabled"
+#endif
+
+/* Setups/teardown functions */
+
+static void
+tcp_setup(void)
+{
+ tcp_remove_all();
+}
+
+static void
+tcp_teardown(void)
+{
+ tcp_remove_all();
+}
+
+
+/* Test functions */
+
+/** Call tcp_new() and tcp_abort() and test memp stats */
+START_TEST(test_tcp_new_abort)
+{
+ struct tcp_pcb* pcb;
+ LWIP_UNUSED_ARG(_i);
+
+ fail_unless(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
+
+ pcb = tcp_new();
+ fail_unless(pcb != NULL);
+ if (pcb != NULL) {
+ fail_unless(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
+ tcp_abort(pcb);
+ fail_unless(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
+ }
+}
+END_TEST
+
+/** Create an ESTABLISHED pcb and check if receive callback is called */
+START_TEST(test_tcp_recv_inseq)
+{
+ struct test_tcp_counters counters;
+ struct tcp_pcb* pcb;
+ struct pbuf* p;
+ char data[] = {1, 2, 3, 4};
+ struct ip_addr remote_ip, local_ip;
+ u16_t data_len;
+ u16_t remote_port = 0x100, local_port = 0x101;
+ struct netif netif;
+ LWIP_UNUSED_ARG(_i);
+
+ /* initialize local vars */
+ memset(&netif, 0, sizeof(netif));
+ IP4_ADDR(&local_ip, 192, 168, 1, 1);
+ IP4_ADDR(&remote_ip, 192, 168, 1, 2);
+ data_len = sizeof(data);
+ /* initialize counter struct */
+ memset(&counters, 0, sizeof(counters));
+ counters.expected_data_len = data_len;
+ counters.expected_data = data;
+
+ /* create and initialize the pcb */
+ pcb = test_tcp_new_counters_pcb(&counters);
+ EXPECT_RET(pcb != NULL);
+ tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
+
+ /* create a segment */
+ p = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0);
+ EXPECT(p != NULL);
+ if (p != NULL) {
+ /* pass the segment to tcp_input */
+ tcp_input(p, &netif);
+ /* check if counters are as expected */
+ EXPECT(counters.close_calls == 0);
+ EXPECT(counters.recv_calls == 1);
+ EXPECT(counters.recved_bytes == data_len);
+ EXPECT(counters.err_calls == 0);
+ }
+
+ /* make sure the pcb is freed */
+ EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
+ tcp_abort(pcb);
+ EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
+}
+END_TEST
+
+
+/** Create the suite including all tests for this module */
+Suite *
+tcp_suite(void)
+{
+ TFun tests[] = {
+ test_tcp_new_abort,
+ test_tcp_recv_inseq,
+ };
+ return create_suite("TCP", tests, sizeof(tests)/sizeof(TFun), tcp_setup, tcp_teardown);
+}
diff --git a/net/lwip/test/unit/tcp/test_tcp.h b/net/lwip/test/unit/tcp/test_tcp.h
new file mode 100644
index 0000000000..f1c4a463f3
--- /dev/null
+++ b/net/lwip/test/unit/tcp/test_tcp.h
@@ -0,0 +1,8 @@
+#ifndef __TEST_TCP_H__
+#define __TEST_TCP_H__
+
+#include "../lwip_check.h"
+
+Suite *tcp_suite(void);
+
+#endif
diff --git a/net/lwip/test/unit/tcp/test_tcp_oos.c b/net/lwip/test/unit/tcp/test_tcp_oos.c
new file mode 100644
index 0000000000..8e4c7f4d0e
--- /dev/null
+++ b/net/lwip/test/unit/tcp/test_tcp_oos.c
@@ -0,0 +1,433 @@
+#include "test_tcp_oos.h"
+
+#include "lwip/tcp.h"
+#include "lwip/stats.h"
+#include "tcp_helper.h"
+
+#if !LWIP_STATS || !TCP_STATS || !MEMP_STATS
+#error "This tests needs TCP- and MEMP-statistics enabled"
+#endif
+#if !TCP_QUEUE_OOSEQ
+#error "This tests needs TCP_QUEUE_OOSEQ enabled"
+#endif
+
+/** CHECK_SEGMENTS_ON_OOSEQ:
+ * 1: check count, seqno and len of segments on pcb->ooseq (strict)
+ * 0: only check that bytes are received in correct order (less strict) */
+#define CHECK_SEGMENTS_ON_OOSEQ 1
+
+#if CHECK_SEGMENTS_ON_OOSEQ
+#define EXPECT_OOSEQ(x) EXPECT(x)
+#else
+#define EXPECT_OOSEQ(x)
+#endif
+
+/* helper functions */
+
+/** Get the numbers of segments on the ooseq list */
+static int tcp_oos_count(struct tcp_pcb* pcb)
+{
+ int num = 0;
+ struct tcp_seg* seg = pcb->ooseq;
+ while(seg != NULL) {
+ num++;
+ seg = seg->next;
+ }
+ return num;
+}
+
+/** Get the seqno of a segment (by index) on the ooseq list
+ *
+ * @param pcb the pcb to check for ooseq segments
+ * @param seg_index index of the segment on the ooseq list
+ * @return seqno of the segment
+ */
+static u32_t
+tcp_oos_seg_seqno(struct tcp_pcb* pcb, int seg_index)
+{
+ int num = 0;
+ struct tcp_seg* seg = pcb->ooseq;
+
+ /* then check the actual segment */
+ while(seg != NULL) {
+ if(num == seg_index) {
+ return seg->tcphdr->seqno;
+ }
+ num++;
+ seg = seg->next;
+ }
+ fail();
+ return 0;
+}
+
+/** Get the tcplen of a segment (by index) on the ooseq list
+ *
+ * @param pcb the pcb to check for ooseq segments
+ * @param seg_index index of the segment on the ooseq list
+ * @return tcplen of the segment
+ */
+static int
+tcp_oos_seg_tcplen(struct tcp_pcb* pcb, int seg_index)
+{
+ int num = 0;
+ struct tcp_seg* seg = pcb->ooseq;
+
+ /* then check the actual segment */
+ while(seg != NULL) {
+ if(num == seg_index) {
+ return TCP_TCPLEN(seg);
+ }
+ num++;
+ seg = seg->next;
+ }
+ fail();
+ return -1;
+}
+
+/* Setup/teardown functions */
+
+static void
+tcp_oos_setup(void)
+{
+ tcp_remove_all();
+}
+
+static void
+tcp_oos_teardown(void)
+{
+ tcp_remove_all();
+}
+
+
+
+/* Test functions */
+
+/** create multiple segments and pass them to tcp_input in a wrong
+ * order to see if ooseq-caching works correctly
+ * FIN is received in out-of-sequence segments only */
+START_TEST(test_tcp_recv_ooseq_FIN_OOSEQ)
+{
+ struct test_tcp_counters counters;
+ struct tcp_pcb* pcb;
+ struct pbuf *p_8_9, *p_4_8, *p_4_10, *p_2_14, *p_fin, *pinseq;
+ char data[] = {
+ 1, 2, 3, 4,
+ 5, 6, 7, 8,
+ 9, 10, 11, 12,
+ 13, 14, 15, 16};
+ struct ip_addr remote_ip, local_ip;
+ u16_t data_len;
+ u16_t remote_port = 0x100, local_port = 0x101;
+ struct netif netif;
+ LWIP_UNUSED_ARG(_i);
+
+ /* initialize local vars */
+ memset(&netif, 0, sizeof(netif));
+ IP4_ADDR(&local_ip, 192, 168, 1, 1);
+ IP4_ADDR(&remote_ip, 192, 168, 1, 2);
+ data_len = sizeof(data);
+ /* initialize counter struct */
+ memset(&counters, 0, sizeof(counters));
+ counters.expected_data_len = data_len;
+ counters.expected_data = data;
+
+ /* create and initialize the pcb */
+ pcb = test_tcp_new_counters_pcb(&counters);
+ EXPECT_RET(pcb != NULL);
+ tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
+
+ /* create segments */
+ /* pinseq is sent as last segment! */
+ pinseq = tcp_create_rx_segment(pcb, &data[0], 4, 0, 0, TCP_ACK);
+ /* p1: 8 bytes before FIN */
+ /* seqno: 8..16 */
+ p_8_9 = tcp_create_rx_segment(pcb, &data[8], 8, 8, 0, TCP_ACK|TCP_FIN);
+ /* p2: 4 bytes before p1, including the first 4 bytes of p1 (partly duplicate) */
+ /* seqno: 4..11 */
+ p_4_8 = tcp_create_rx_segment(pcb, &data[4], 8, 4, 0, TCP_ACK);
+ /* p3: same as p2 but 2 bytes longer */
+ /* seqno: 4..13 */
+ p_4_10 = tcp_create_rx_segment(pcb, &data[4], 10, 4, 0, TCP_ACK);
+ /* p4: 14 bytes before FIN, includes data from p1 and p2, plus partly from pinseq */
+ /* seqno: 2..15 */
+ p_2_14 = tcp_create_rx_segment(pcb, &data[2], 14, 2, 0, TCP_ACK);
+ /* FIN, seqno 16 */
+ p_fin = tcp_create_rx_segment(pcb, NULL, 0,16, 0, TCP_ACK|TCP_FIN);
+ EXPECT(pinseq != NULL);
+ EXPECT(p_8_9 != NULL);
+ EXPECT(p_4_8 != NULL);
+ EXPECT(p_4_10 != NULL);
+ EXPECT(p_2_14 != NULL);
+ EXPECT(p_fin != NULL);
+ if ((pinseq != NULL) && (p_8_9 != NULL) && (p_4_8 != NULL) && (p_4_10 != NULL) && (p_2_14 != NULL) && (p_fin != NULL)) {
+ /* pass the segment to tcp_input */
+ tcp_input(p_8_9, &netif);
+ /* check if counters are as expected */
+ EXPECT(counters.close_calls == 0);
+ EXPECT(counters.recv_calls == 0);
+ EXPECT(counters.recved_bytes == 0);
+ EXPECT(counters.err_calls == 0);
+ /* check ooseq queue */
+ EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
+ EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 8);
+ EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 9); /* includes FIN */
+
+ /* pass the segment to tcp_input */
+ tcp_input(p_4_8, &netif);
+ /* check if counters are as expected */
+ EXPECT(counters.close_calls == 0);
+ EXPECT(counters.recv_calls == 0);
+ EXPECT(counters.recved_bytes == 0);
+ EXPECT(counters.err_calls == 0);
+ /* check ooseq queue */
+ EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
+ EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 4);
+ EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 4);
+ EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 8);
+ EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */
+
+ /* pass the segment to tcp_input */
+ tcp_input(p_4_10, &netif);
+ /* check if counters are as expected */
+ EXPECT(counters.close_calls == 0);
+ EXPECT(counters.recv_calls == 0);
+ EXPECT(counters.recved_bytes == 0);
+ EXPECT(counters.err_calls == 0);
+ /* ooseq queue: unchanged */
+ EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
+ EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 4);
+ EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 4);
+ EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 8);
+ EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */
+
+ /* pass the segment to tcp_input */
+ tcp_input(p_2_14, &netif);
+ /* check if counters are as expected */
+ EXPECT(counters.close_calls == 0);
+ EXPECT(counters.recv_calls == 0);
+ EXPECT(counters.recved_bytes == 0);
+ EXPECT(counters.err_calls == 0);
+ /* check ooseq queue */
+ EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
+ EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 2);
+ EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 6);
+ EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 8);
+ EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */
+
+ /* pass the segment to tcp_input */
+ tcp_input(p_fin, &netif);
+ /* check if counters are as expected */
+ EXPECT(counters.close_calls == 0);
+ EXPECT(counters.recv_calls == 0);
+ EXPECT(counters.recved_bytes == 0);
+ EXPECT(counters.err_calls == 0);
+ /* ooseq queue: unchanged */
+ EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
+ EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 2);
+ EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 6);
+ EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 8);
+ EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */
+
+ /* pass the segment to tcp_input */
+ tcp_input(pinseq, &netif);
+ /* check if counters are as expected */
+ EXPECT(counters.close_calls == 1);
+ EXPECT(counters.recv_calls == 1);
+ EXPECT(counters.recved_bytes == data_len);
+ EXPECT(counters.err_calls == 0);
+ EXPECT(pcb->ooseq == NULL);
+ }
+
+ /* make sure the pcb is freed */
+ EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
+ tcp_abort(pcb);
+ EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
+}
+END_TEST
+
+
+/** create multiple segments and pass them to tcp_input in a wrong
+ * order to see if ooseq-caching works correctly
+ * FIN is received IN-SEQUENCE at the end */
+START_TEST(test_tcp_recv_ooseq_FIN_INSEQ)
+{
+ struct test_tcp_counters counters;
+ struct tcp_pcb* pcb;
+ struct pbuf *p_1_2, *p_4_8, *p_3_11, *p_2_12, *p_15_1, *p_15_1a, *pinseq, *pinseqFIN;
+ char data[] = {
+ 1, 2, 3, 4,
+ 5, 6, 7, 8,
+ 9, 10, 11, 12,
+ 13, 14, 15, 16};
+ struct ip_addr remote_ip, local_ip;
+ u16_t data_len;
+ u16_t remote_port = 0x100, local_port = 0x101;
+ struct netif netif;
+ LWIP_UNUSED_ARG(_i);
+
+ /* initialize local vars */
+ memset(&netif, 0, sizeof(netif));
+ IP4_ADDR(&local_ip, 192, 168, 1, 1);
+ IP4_ADDR(&remote_ip, 192, 168, 1, 2);
+ data_len = sizeof(data);
+ /* initialize counter struct */
+ memset(&counters, 0, sizeof(counters));
+ counters.expected_data_len = data_len;
+ counters.expected_data = data;
+
+ /* create and initialize the pcb */
+ pcb = test_tcp_new_counters_pcb(&counters);
+ EXPECT_RET(pcb != NULL);
+ tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
+
+ /* create segments */
+ /* p1: 7 bytes - 2 before FIN */
+ /* seqno: 1..2 */
+ p_1_2 = tcp_create_rx_segment(pcb, &data[1], 2, 1, 0, TCP_ACK);
+ /* p2: 4 bytes before p1, including the first 4 bytes of p1 (partly duplicate) */
+ /* seqno: 4..11 */
+ p_4_8 = tcp_create_rx_segment(pcb, &data[4], 8, 4, 0, TCP_ACK);
+ /* p3: same as p2 but 2 bytes longer and one byte more at the front */
+ /* seqno: 3..13 */
+ p_3_11 = tcp_create_rx_segment(pcb, &data[3], 11, 3, 0, TCP_ACK);
+ /* p4: 13 bytes - 2 before FIN - should be ignored as contained in p1 and p3 */
+ /* seqno: 2..13 */
+ p_2_12 = tcp_create_rx_segment(pcb, &data[2], 12, 2, 0, TCP_ACK);
+ /* pinseq is the first segment that is held back to create ooseq! */
+ /* seqno: 0..3 */
+ pinseq = tcp_create_rx_segment(pcb, &data[0], 4, 0, 0, TCP_ACK);
+ /* p5: last byte before FIN */
+ /* seqno: 15 */
+ p_15_1 = tcp_create_rx_segment(pcb, &data[15], 1, 15, 0, TCP_ACK);
+ /* p6: same as p5, should be ignored */
+ p_15_1a= tcp_create_rx_segment(pcb, &data[15], 1, 15, 0, TCP_ACK);
+ /* pinseqFIN: last 2 bytes plus FIN */
+ /* only segment containing seqno 14 and FIN */
+ pinseqFIN = tcp_create_rx_segment(pcb, &data[14], 2, 14, 0, TCP_ACK|TCP_FIN);
+ EXPECT(pinseq != NULL);
+ EXPECT(p_1_2 != NULL);
+ EXPECT(p_4_8 != NULL);
+ EXPECT(p_3_11 != NULL);
+ EXPECT(p_2_12 != NULL);
+ EXPECT(p_15_1 != NULL);
+ EXPECT(p_15_1a != NULL);
+ EXPECT(pinseqFIN != NULL);
+ if ((pinseq != NULL) && (p_1_2 != NULL) && (p_4_8 != NULL) && (p_3_11 != NULL) && (p_2_12 != NULL)
+ && (p_15_1 != NULL) && (p_15_1a != NULL) && (pinseqFIN != NULL)) {
+ /* pass the segment to tcp_input */
+ tcp_input(p_1_2, &netif);
+ /* check if counters are as expected */
+ EXPECT(counters.close_calls == 0);
+ EXPECT(counters.recv_calls == 0);
+ EXPECT(counters.recved_bytes == 0);
+ EXPECT(counters.err_calls == 0);
+ /* check ooseq queue */
+ EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
+ EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1);
+ EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2);
+
+ /* pass the segment to tcp_input */
+ tcp_input(p_4_8, &netif);
+ /* check if counters are as expected */
+ EXPECT(counters.close_calls == 0);
+ EXPECT(counters.recv_calls == 0);
+ EXPECT(counters.recved_bytes == 0);
+ EXPECT(counters.err_calls == 0);
+ /* check ooseq queue */
+ EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
+ EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1);
+ EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2);
+ EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 4);
+ EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 8);
+
+ /* pass the segment to tcp_input */
+ tcp_input(p_3_11, &netif);
+ /* check if counters are as expected */
+ EXPECT(counters.close_calls == 0);
+ EXPECT(counters.recv_calls == 0);
+ EXPECT(counters.recved_bytes == 0);
+ EXPECT(counters.err_calls == 0);
+ /* check ooseq queue */
+ EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
+ EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1);
+ EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2);
+ /* p_3_11 has removed p_4_8 from ooseq */
+ EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 3);
+ EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 11);
+
+ /* pass the segment to tcp_input */
+ tcp_input(p_2_12, &netif);
+ /* check if counters are as expected */
+ EXPECT(counters.close_calls == 0);
+ EXPECT(counters.recv_calls == 0);
+ EXPECT(counters.recved_bytes == 0);
+ EXPECT(counters.err_calls == 0);
+ /* check ooseq queue */
+ EXPECT_OOSEQ(tcp_oos_count(pcb) == 3);
+ EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1);
+ EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1);
+ EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 2);
+ EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 1);
+ EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 2) == 3);
+ EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 2) == 11);
+
+ /* pass the segment to tcp_input */
+ tcp_input(pinseq, &netif);
+ /* check if counters are as expected */
+ EXPECT(counters.close_calls == 0);
+ EXPECT(counters.recv_calls == 1);
+ EXPECT(counters.recved_bytes == 14);
+ EXPECT(counters.err_calls == 0);
+ EXPECT(pcb->ooseq == NULL);
+
+ /* pass the segment to tcp_input */
+ tcp_input(p_15_1, &netif);
+ /* check if counters are as expected */
+ EXPECT(counters.close_calls == 0);
+ EXPECT(counters.recv_calls == 1);
+ EXPECT(counters.recved_bytes == 14);
+ EXPECT(counters.err_calls == 0);
+ /* check ooseq queue */
+ EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
+ EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 15);
+ EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1);
+
+ /* pass the segment to tcp_input */
+ tcp_input(p_15_1a, &netif);
+ /* check if counters are as expected */
+ EXPECT(counters.close_calls == 0);
+ EXPECT(counters.recv_calls == 1);
+ EXPECT(counters.recved_bytes == 14);
+ EXPECT(counters.err_calls == 0);
+ /* check ooseq queue: unchanged */
+ EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
+ EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 15);
+ EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1);
+
+ /* pass the segment to tcp_input */
+ tcp_input(pinseqFIN, &netif);
+ /* check if counters are as expected */
+ EXPECT(counters.close_calls == 1);
+ EXPECT(counters.recv_calls == 2);
+ EXPECT(counters.recved_bytes == data_len);
+ EXPECT(counters.err_calls == 0);
+ EXPECT(pcb->ooseq == NULL);
+ }
+
+ /* make sure the pcb is freed */
+ EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
+ tcp_abort(pcb);
+ EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
+}
+END_TEST
+
+/** Create the suite including all tests for this module */
+Suite *
+tcp_oos_suite(void)
+{
+ TFun tests[] = {
+ test_tcp_recv_ooseq_FIN_OOSEQ,
+ test_tcp_recv_ooseq_FIN_INSEQ,
+ };
+ return create_suite("TCP_OOS", tests, sizeof(tests)/sizeof(TFun), tcp_oos_setup, tcp_oos_teardown);
+}
diff --git a/net/lwip/test/unit/tcp/test_tcp_oos.h b/net/lwip/test/unit/tcp/test_tcp_oos.h
new file mode 100644
index 0000000000..5e411f0094
--- /dev/null
+++ b/net/lwip/test/unit/tcp/test_tcp_oos.h
@@ -0,0 +1,8 @@
+#ifndef __TEST_TCP_OOS_H__
+#define __TEST_TCP_OOS_H__
+
+#include "../lwip_check.h"
+
+Suite *tcp_oos_suite(void);
+
+#endif
diff --git a/net/lwip/test/unit/udp/test_udp.c b/net/lwip/test/unit/udp/test_udp.c
new file mode 100644
index 0000000000..d9b407e03b
--- /dev/null
+++ b/net/lwip/test/unit/udp/test_udp.c
@@ -0,0 +1,80 @@
+#include "test_udp.h"
+
+#include "lwip/udp.h"
+#include "lwip/stats.h"
+
+#if !LWIP_STATS || !UDP_STATS || !MEMP_STATS
+#error "This tests needs UDP- and MEMP-statistics enabled"
+#endif
+
+/* Helper functions */
+static void
+udp_remove_all(void)
+{
+ struct udp_pcb *pcb = udp_pcbs;
+ struct udp_pcb *pcb2;
+
+ while(pcb != NULL) {
+ pcb2 = pcb;
+ pcb = pcb->next;
+ udp_remove(pcb2);
+ }
+ fail_unless(lwip_stats.memp[MEMP_UDP_PCB].used == 0);
+}
+
+/* Setups/teardown functions */
+
+static void
+udp_setup(void)
+{
+ udp_remove_all();
+}
+
+static void
+udp_teardown(void)
+{
+ udp_remove_all();
+}
+
+
+/* Test functions */
+
+START_TEST(test_udp_new_remove)
+{
+ struct udp_pcb* pcb;
+ LWIP_UNUSED_ARG(_i);
+
+ fail_unless(lwip_stats.memp[MEMP_UDP_PCB].used == 0);
+
+ pcb = udp_new();
+ fail_unless(pcb != NULL);
+ if (pcb != NULL) {
+ fail_unless(lwip_stats.memp[MEMP_UDP_PCB].used == 1);
+ udp_remove(pcb);
+ fail_unless(lwip_stats.memp[MEMP_UDP_PCB].used == 0);
+ }
+}
+END_TEST
+
+START_TEST(test_udp_remove)
+{
+ struct udp_pcb* pcb;
+ LWIP_UNUSED_ARG(_i);
+
+ pcb = NULL;
+ //pcb = udp_new();
+ //fail_unless(pcb != NULL);
+}
+END_TEST
+
+
+/** Create the suite including all tests for this module */
+Suite *
+udp_suite(void)
+{
+ TFun tests[] = {
+ test_udp_new_remove,
+ test_udp_remove
+ };
+ return create_suite("UDP", tests, sizeof(tests)/sizeof(TFun), udp_setup, udp_teardown);
+}
diff --git a/net/lwip/test/unit/udp/test_udp.h b/net/lwip/test/unit/udp/test_udp.h
new file mode 100644
index 0000000000..9335368240
--- /dev/null
+++ b/net/lwip/test/unit/udp/test_udp.h
@@ -0,0 +1,8 @@
+#ifndef __TEST_UDP_H__
+#define __TEST_UDP_H__
+
+#include "../lwip_check.h"
+
+Suite* udp_suite(void);
+
+#endif