1? .ChangeLog.swp
2? ChangeLog
3Index: CHANGELOG
4===================================================================
5RCS file: /sources/lwip/lwip/CHANGELOG,v
6retrieving revision 1.300
7retrieving revision 1.318
8diff -u -p -r1.300 -r1.318
9--- CHANGELOG	23 Mar 2008 13:49:39 -0000	1.300
10+++ CHANGELOG	14 Jul 2008 20:12:36 -0000	1.318
11@@ -19,9 +19,77 @@ HISTORY
12
13   ++ New features:
14
15+  2008-06-30 Simon Goldschmidt
16+  * mem.c, opt.h, stats.h: fixed bug #21433: Calling mem_free/pbuf_free from
17+    interrupt context isn't safe: LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT allows
18+    mem_free to run between mem_malloc iterations. Added illegal counter for
19+    mem stats.
20+
21+  2008-06-27 Simon Goldschmidt
22+  * stats.h/.c, some other files: patch #6483: stats module improvement:
23+    Added defines to display each module's statistic individually, added stats
24+    defines for MEM, MEMP and SYS modules, removed (unused) rexmit counter.
25+
26+  2008-06-17 Simon Goldschmidt
27+  * err.h: patch #6459: Made err_t overridable to use a more efficient type
28+    (define LWIP_ERR_T in cc.h)
29+
30+  2008-06-17 Simon Goldschmidt
31+  * slipif.c: patch #6480: Added a configuration option for slipif for symmetry
32+    to loopif
33+
34+  2008-06-17 Simon Goldschmidt (patch by Luca Ceresoli)
35+  * netif.c, loopif.c, ip.c, netif.h, loopif.h, opt.h: Checked in slightly
36+    modified version of patch # 6370: Moved loopif code to netif.c so that
37+    loopback traffic is supported on all netifs (all local IPs).
38+    Added option to limit loopback packets for each netifs.
39+
40
41   ++ Bugfixes:
42
43+  2008-08-14 Simon Goldschmidt
44+  * api_msg.c: fixed bug #23847: do_close_internal references freed memory (when
45+    tcp_close returns != ERR_OK)
46+
47+  2008-07-08 Fr�d�ric Bernon
48+  * stats.h: Fix some build bugs introduced with patch #6483 (missing some parameters
49+    in macros, mainly if MEM_STATS=0 and MEMP_STATS=0).
50+
51+  2008-06-24 Jonathan Larmour
52+  * tcp_in.c: Fix for bug #23693 as suggested by Art R. Ensure cseg is unused
53+    if tcp_seg_copy fails.
54+
55+  2008-06-17 Simon Goldschmidt
56+  * inet_chksum.c: Checked in some ideas of patch #6460 (loop optimizations)
57+    and created defines for swapping bytes and folding u32 to u16.
58+
59+  2008-05-30 Kieran Mansley
60+  * tcp_in.c Remove redundant "if" statement, and use real rcv_wnd
61+    rather than rcv_ann_wnd when deciding if packets are in-window.
62+    Contributed by <arasmussen@consultant.datasys.swri.edu>
63+
64+  2008-05-30 Kieran Mansley
65+  * mem.h: Fix BUG#23254.  Change macro definition of mem_* to allow
66+    passing as function pointers when MEM_LIBC_MALLOC is defined.
67+
68+  2008-05-09 Jonathan Larmour
69+  * err.h, err.c, sockets.c: Fix bug #23119: Reorder timeout error code to
70+    stop it being treated as a fatal error.
71+
72+  2008-04-15 Simon Goldschmidt
73+  * dhcp.c: fixed bug #22804: dhcp_stop doesn't clear NETIF_FLAG_DHCP
74+    (flag now cleared)
75+
76+  2008-03-27 Simon Goldschmidt
77+  * mem.c, tcpip.c, tcpip.h, opt.h: fixed bug #21433 (Calling mem_free/pbuf_free
78+    from interrupt context isn't safe): set LWIP_USE_HEAP_FROM_INTERRUPT to 1
79+    in lwipopts.h or use pbuf_free_callback(p)/mem_free_callback(m) to free pbufs
80+    or heap memory from interrupt context
81+
82+  2008-03-26 Simon Goldschmidt
83+  * tcp_in.c, tcp.c: fixed bug #22249: division by zero could occur if a remote
84+    host sent a zero mss as TCP option.
85+
86
87 (STABLE-1.3.0)
88
89Index: src/api/api_msg.c
90===================================================================
91RCS file: /sources/lwip/lwip/src/api/api_msg.c,v
92retrieving revision 1.102
93retrieving revision 1.104
94diff -u -p -r1.102 -r1.104
95--- src/api/api_msg.c	21 Mar 2008 16:23:14 -0000	1.102
96+++ src/api/api_msg.c	15 Jul 2008 11:18:58 -0000	1.104
97@@ -598,11 +598,16 @@ do_close_internal(struct netconn *conn)
98   LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL));
99
100   /* Set back some callback pointers */
101+  tcp_arg(conn->pcb.tcp, NULL);
102   if (conn->pcb.tcp->state == LISTEN) {
103-    tcp_arg(conn->pcb.tcp, NULL);
104     tcp_accept(conn->pcb.tcp, NULL);
105   } else {
106     tcp_recv(conn->pcb.tcp, NULL);
107+    tcp_accept(conn->pcb.tcp, NULL);
108+    /* some callbacks have to be reset if tcp_close is not successful */
109+    tcp_sent(conn->pcb.tcp, NULL);
110+    tcp_poll(conn->pcb.tcp, NULL, 4);
111+    tcp_err(conn->pcb.tcp, NULL);
112   }
113   /* Try to close the connection */
114   err = tcp_close(conn->pcb.tcp);
115@@ -610,11 +615,6 @@ do_close_internal(struct netconn *conn)
116     /* Closing succeeded */
117     conn->state = NETCONN_NONE;
118     /* Set back some callback pointers as conn is going away */
119-    tcp_err(conn->pcb.tcp, NULL);
120-    tcp_poll(conn->pcb.tcp, NULL, 4);
121-    tcp_sent(conn->pcb.tcp, NULL);
122-    tcp_recv(conn->pcb.tcp, NULL);
123-    tcp_arg(conn->pcb.tcp, NULL);
124     conn->pcb.tcp = NULL;
125     conn->err = ERR_OK;
126     /* Trigger select() in socket layer. This send should something else so the
127@@ -623,6 +623,14 @@ do_close_internal(struct netconn *conn)
128     API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
129     /* wake up the application task */
130     sys_sem_signal(conn->op_completed);
131+  } else {
132+    /* Closing failed, restore some of the callbacks */
133+    /* Closing of listen pcb will never fail! */
134+    LWIP_ASSERT("Closing a listen pcb may not fail!", (conn->pcb.tcp->state != LISTEN));
135+    tcp_sent(conn->pcb.tcp, sent_tcp);
136+    tcp_poll(conn->pcb.tcp, poll_tcp, 4);
137+    tcp_err(conn->pcb.tcp, err_tcp);
138+    tcp_arg(conn->pcb.tcp, conn);
139   }
140   /* If closing didn't succeed, we get called again either
141      from poll_tcp or from sent_tcp */
142Index: src/api/err.c
143===================================================================
144RCS file: /sources/lwip/lwip/src/api/err.c,v
145retrieving revision 1.11
146retrieving revision 1.12
147diff -u -p -r1.11 -r1.12
148--- src/api/err.c	13 Dec 2007 23:06:50 -0000	1.11
149+++ src/api/err.c	9 May 2008 12:14:23 -0000	1.12
150@@ -44,17 +44,17 @@ static const char *err_strerr[] = {
151            "Ok.",                    /* ERR_OK          0  */
152            "Out of memory error.",   /* ERR_MEM        -1  */
153            "Buffer error.",          /* ERR_BUF        -2  */
154-           "Routing problem.",       /* ERR_RTE        -3  */
155-           "Connection aborted.",    /* ERR_ABRT       -4  */
156-           "Connection reset.",      /* ERR_RST        -5  */
157-           "Connection closed.",     /* ERR_CLSD       -6  */
158-           "Not connected.",         /* ERR_CONN       -7  */
159-           "Illegal value.",         /* ERR_VAL        -8  */
160-           "Illegal argument.",      /* ERR_ARG        -9  */
161-           "Address in use.",        /* ERR_USE        -10 */
162-           "Low-level netif error.", /* ERR_IF         -11 */
163-           "Already connected.",     /* ERR_ISCONN     -12 */
164-           "Timeout.",               /* ERR_TIMEOUT    -13 */
165+           "Timeout.",               /* ERR_TIMEOUT    -3 */
166+           "Routing problem.",       /* ERR_RTE        -4  */
167+           "Connection aborted.",    /* ERR_ABRT       -5  */
168+           "Connection reset.",      /* ERR_RST        -6  */
169+           "Connection closed.",     /* ERR_CLSD       -7  */
170+           "Not connected.",         /* ERR_CONN       -8  */
171+           "Illegal value.",         /* ERR_VAL        -9  */
172+           "Illegal argument.",      /* ERR_ARG        -10 */
173+           "Address in use.",        /* ERR_USE        -11 */
174+           "Low-level netif error.", /* ERR_IF         -12 */
175+           "Already connected.",     /* ERR_ISCONN     -13 */
176            "Operation in progress."  /* ERR_INPROGRESS -14 */
177 };
178
179Index: src/api/netdb.c
180===================================================================
181RCS file: /sources/lwip/lwip/src/api/netdb.c,v
182retrieving revision 1.4
183retrieving revision 1.5
184diff -u -p -r1.4 -r1.5
185--- src/api/netdb.c	26 Jan 2008 16:11:39 -0000	1.4
186+++ src/api/netdb.c	16 Jul 2008 20:36:12 -0000	1.5
187@@ -326,7 +326,8 @@ lwip_getaddrinfo(const char *nodename, c
188   if (nodename != NULL) {
189     /* copy nodename to canonname if specified */
190     size_t namelen = strlen(nodename);
191-    ai->ai_canonname = mem_malloc(namelen + 1);
192+    LWIP_ASSERT("namelen is too long", (namelen + 1) <= (mem_size_t)-1);
193+    ai->ai_canonname = mem_malloc((mem_size_t)(namelen + 1));
194     if (ai->ai_canonname == NULL) {
195       goto memerr;
196     }
197Index: src/api/sockets.c
198===================================================================
199RCS file: /sources/lwip/lwip/src/api/sockets.c,v
200retrieving revision 1.116
201retrieving revision 1.117
202diff -u -p -r1.116 -r1.117
203--- src/api/sockets.c	13 Mar 2008 20:03:57 -0000	1.116
204+++ src/api/sockets.c	9 May 2008 12:14:24 -0000	1.117
205@@ -128,17 +128,17 @@ static const int err_to_errno_table[] =
206   0,             /* ERR_OK          0      No error, everything OK. */
207   ENOMEM,        /* ERR_MEM        -1      Out of memory error.     */
208   ENOBUFS,       /* ERR_BUF        -2      Buffer error.            */
209-  EHOSTUNREACH,  /* ERR_RTE        -3      Routing problem.         */
210-  ECONNABORTED,  /* ERR_ABRT       -4      Connection aborted.      */
211-  ECONNRESET,    /* ERR_RST        -5      Connection reset.        */
212-  ESHUTDOWN,     /* ERR_CLSD       -6      Connection closed.       */
213-  ENOTCONN,      /* ERR_CONN       -7      Not connected.           */
214-  EINVAL,        /* ERR_VAL        -8      Illegal value.           */
215-  EIO,           /* ERR_ARG        -9      Illegal argument.        */
216-  EADDRINUSE,    /* ERR_USE        -10     Address in use.          */
217-  -1,            /* ERR_IF         -11     Low-level netif error    */
218-  -1,            /* ERR_ISCONN     -12     Already connected.       */
219-  ETIMEDOUT,     /* ERR_TIMEOUT    -13     Timeout                  */
220+  ETIMEDOUT,     /* ERR_TIMEOUT    -3      Timeout                  */
221+  EHOSTUNREACH,  /* ERR_RTE        -4      Routing problem.         */
222+  ECONNABORTED,  /* ERR_ABRT       -5      Connection aborted.      */
223+  ECONNRESET,    /* ERR_RST        -6      Connection reset.        */
224+  ESHUTDOWN,     /* ERR_CLSD       -7      Connection closed.       */
225+  ENOTCONN,      /* ERR_CONN       -8      Not connected.           */
226+  EINVAL,        /* ERR_VAL        -9      Illegal value.           */
227+  EIO,           /* ERR_ARG        -10     Illegal argument.        */
228+  EADDRINUSE,    /* ERR_USE        -11     Address in use.          */
229+  -1,            /* ERR_IF         -12     Low-level netif error    */
230+  -1,            /* ERR_ISCONN     -13     Already connected.       */
231   EINPROGRESS    /* ERR_INPROGRESS -14     Operation in progress    */
232 };
233
234Index: src/api/tcpip.c
235===================================================================
236RCS file: /sources/lwip/lwip/src/api/tcpip.c,v
237retrieving revision 1.70
238retrieving revision 1.73
239diff -u -p -r1.70 -r1.73
240--- src/api/tcpip.c	12 Jan 2008 11:52:22 -0000	1.70
241+++ src/api/tcpip.c	27 Jun 2008 20:34:51 -0000	1.73
242@@ -518,4 +518,42 @@ tcpip_init(void (* initfunc)(void *), vo
243   sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
244 }
245
246+/**
247+ * Simple callback function used with tcpip_callback to free a pbuf
248+ * (pbuf_free has a wrong signature for tcpip_callback)
249+ *
250+ * @param p The pbuf (chain) to be dereferenced.
251+ */
252+static void
253+pbuf_free_int(void *p)
254+{
255+  struct pbuf *q = p;
256+  pbuf_free(q);
257+}
258+
259+/**
260+ * A simple wrapper function that allows you to free a pbuf from interrupt context.
261+ *
262+ * @param p The pbuf (chain) to be dereferenced.
263+ * @return ERR_OK if callback could be enqueued, an err_t if not
264+ */
265+err_t
266+pbuf_free_callback(struct pbuf *p)
267+{
268+  return tcpip_callback_with_block(pbuf_free_int, p, 0);
269+}
270+
271+/**
272+ * A simple wrapper function that allows you to free heap memory from
273+ * interrupt context.
274+ *
275+ * @param m the heap memory to free
276+ * @return ERR_OK if callback could be enqueued, an err_t if not
277+ */
278+err_t
279+mem_free_callback(void *m)
280+{
281+  return tcpip_callback_with_block(mem_free, m, 0);
282+}
283+
284 #endif /* !NO_SYS */
285Index: src/core/dhcp.c
286===================================================================
287RCS file: /sources/lwip/lwip/src/core/dhcp.c,v
288retrieving revision 1.86
289retrieving revision 1.87
290diff -u -p -r1.86 -r1.87
291--- src/core/dhcp.c	4 Mar 2008 14:25:58 -0000	1.86
292+++ src/core/dhcp.c	15 Apr 2008 17:24:55 -0000	1.87
293@@ -568,6 +568,8 @@ dhcp_start(struct netif *netif)
294   LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;);
295   dhcp = netif->dhcp;
296   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
297+  /* Remove the flag that says this netif is handled by DHCP,
298+     it is set when we succeeded starting. */
299   netif->flags &= ~NETIF_FLAG_DHCP;
300
301   /* no DHCP client attached yet? */
302@@ -609,6 +611,7 @@ dhcp_start(struct netif *netif)
303     dhcp_stop(netif);
304     return ERR_MEM;
305   }
306+  /* Set the flag that says this netif is handled by DHCP. */
307   netif->flags |= NETIF_FLAG_DHCP;
308   return result;
309 }
310@@ -1063,6 +1066,8 @@ dhcp_stop(struct netif *netif)
311 {
312   struct dhcp *dhcp = netif->dhcp;
313   LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return;);
314+  /* Remove the flag that says this netif is handled by DHCP. */
315+  netif->flags &= ~NETIF_FLAG_DHCP;
316
317   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_stop()\n"));
318   /* netif is DHCP configured? */
319Index: src/core/mem.c
320===================================================================
321RCS file: /sources/lwip/lwip/src/core/mem.c,v
322retrieving revision 1.59
323retrieving revision 1.62
324diff -u -p -r1.59 -r1.62
325--- src/core/mem.c	4 Mar 2008 16:31:32 -0000	1.59
326+++ src/core/mem.c	30 Jun 2008 18:16:51 -0000	1.62
327@@ -177,9 +177,36 @@ static u8_t *ram;
328 static struct mem *ram_end;
329 /** pointer to the lowest free block, this is used for faster search */
330 static struct mem *lfree;
331+
332 /** concurrent access protection */
333 static sys_sem_t mem_sem;
334
335+#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
336+
337+static volatile u8_t mem_free_count;
338+
339+/* Allow mem_free from other (e.g. interrupt) context */
340+#define LWIP_MEM_FREE_DECL_PROTECT()  SYS_ARCH_DECL_PROTECT(lev_free)
341+#define LWIP_MEM_FREE_PROTECT()       SYS_ARCH_PROTECT(lev_free)
342+#define LWIP_MEM_FREE_UNPROTECT()     SYS_ARCH_UNPROTECT(lev_free)
343+#define LWIP_MEM_ALLOC_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_alloc)
344+#define LWIP_MEM_ALLOC_PROTECT()      SYS_ARCH_PROTECT(lev_alloc)
345+#define LWIP_MEM_ALLOC_UNPROTECT()    SYS_ARCH_UNPROTECT(lev_alloc)
346+
347+#else /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
348+
349+/* Protect the heap only by using a semaphore */
350+#define LWIP_MEM_FREE_DECL_PROTECT()
351+#define LWIP_MEM_FREE_PROTECT()    sys_arch_sem_wait(mem_sem, 0)
352+#define LWIP_MEM_FREE_UNPROTECT()  sys_sem_signal(mem_sem)
353+/* mem_malloc is protected using semaphore AND LWIP_MEM_ALLOC_PROTECT */
354+#define LWIP_MEM_ALLOC_DECL_PROTECT()
355+#define LWIP_MEM_ALLOC_PROTECT()
356+#define LWIP_MEM_ALLOC_UNPROTECT()
357+
358+#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
359+
360+
361 /**
362  * "Plug holes" by combining adjacent empty struct mems.
363  * After this function is through, there should not exist
364@@ -255,9 +282,7 @@ mem_init(void)
365   /* initialize the lowest-free pointer to the start of the heap */
366   lfree = (struct mem *)ram;
367
368-#if MEM_STATS
369-  lwip_stats.mem.avail = MEM_SIZE_ALIGNED;
370-#endif /* MEM_STATS */
371+  MEM_STATS_AVAIL(avail, MEM_SIZE_ALIGNED);
372 }
373
374 /**
375@@ -270,6 +295,7 @@ void
376 mem_free(void *rmem)
377 {
378   struct mem *mem;
379+  LWIP_MEM_FREE_DECL_PROTECT();
380
381   if (rmem == NULL) {
382     LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | 2, ("mem_free(p == NULL) was called.\n"));
383@@ -277,20 +303,20 @@ mem_free(void *rmem)
384   }
385   LWIP_ASSERT("mem_free: sanity check alignment", (((mem_ptr_t)rmem) & (MEM_ALIGNMENT-1)) == 0);
386
387-  /* protect the heap from concurrent access */
388-  sys_arch_sem_wait(mem_sem, 0);
389-
390   LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
391     (u8_t *)rmem < (u8_t *)ram_end);
392
393   if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
394+    SYS_ARCH_DECL_PROTECT(lev);
395     LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_free: illegal memory\n"));
396-#if MEM_STATS
397-    ++lwip_stats.mem.err;
398-#endif /* MEM_STATS */
399-    sys_sem_signal(mem_sem);
400+    /* protect mem stats from concurrent access */
401+    SYS_ARCH_PROTECT(lev);
402+    MEM_STATS_INC(illegal);
403+    SYS_ARCH_UNPROTECT(lev);
404     return;
405   }
406+  /* protect the heap from concurrent access */
407+  LWIP_MEM_FREE_PROTECT();
408   /* Get the corresponding struct mem ... */
409   mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
410   /* ... which has to be in a used state ... */
411@@ -303,13 +329,14 @@ mem_free(void *rmem)
412     lfree = mem;
413   }
414
415-#if MEM_STATS
416-  lwip_stats.mem.used -= mem->next - ((u8_t *)mem - ram);
417-#endif /* MEM_STATS */
418+  MEM_STATS_DEC_USED(used, mem->next - ((u8_t *)mem - ram));
419
420   /* finally, see if prev or next are free also */
421   plug_holes(mem);
422-  sys_sem_signal(mem_sem);
423+#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
424+  mem_free_count = 1;
425+#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
426+  LWIP_MEM_FREE_UNPROTECT();
427 }
428
429 /**
430@@ -321,6 +348,8 @@ mem_free(void *rmem)
431  * @param newsize required size after shrinking (needs to be smaller than or
432  *                equal to the previous size)
433  * @return for compatibility reasons: is always == rmem, at the moment
434+ *         or NULL if newsize is > old size, in which case rmem is NOT touched
435+ *         or freed!
436  */
437 void *
438 mem_realloc(void *rmem, mem_size_t newsize)
439@@ -328,6 +357,8 @@ mem_realloc(void *rmem, mem_size_t newsi
440   mem_size_t size;
441   mem_size_t ptr, ptr2;
442   struct mem *mem, *mem2;
443+  /* use the FREE_PROTECT here: it protects with sem OR SYS_ARCH_PROTECT */
444+  LWIP_MEM_FREE_DECL_PROTECT();
445
446   /* Expand the size of the allocated memory region so that we can
447      adjust for alignment. */
448@@ -346,7 +377,12 @@ mem_realloc(void *rmem, mem_size_t newsi
449    (u8_t *)rmem < (u8_t *)ram_end);
450
451   if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
452+    SYS_ARCH_DECL_PROTECT(lev);
453     LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_realloc: illegal memory\n"));
454+    /* protect mem stats from concurrent access */
455+    SYS_ARCH_PROTECT(lev);
456+    MEM_STATS_INC(illegal);
457+    SYS_ARCH_UNPROTECT(lev);
458     return rmem;
459   }
460   /* Get the corresponding struct mem ... */
461@@ -366,11 +402,9 @@ mem_realloc(void *rmem, mem_size_t newsi
462   }
463
464   /* protect the heap from concurrent access */
465-  sys_arch_sem_wait(mem_sem, 0);
466+  LWIP_MEM_FREE_PROTECT();
467
468-#if MEM_STATS
469-  lwip_stats.mem.used -= (size - newsize);
470-#endif /* MEM_STATS */
471+  MEM_STATS_DEC_USED(used, (size - newsize));
472
473   mem2 = (struct mem *)&ram[mem->next];
474   if(mem2->used == 0) {
475@@ -426,7 +460,10 @@ mem_realloc(void *rmem, mem_size_t newsi
476     -> don't do anyhting.
477     -> the remaining space stays unused since it is too small
478   } */
479-  sys_sem_signal(mem_sem);
480+#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
481+  mem_free_count = 1;
482+#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
483+  LWIP_MEM_FREE_UNPROTECT();
484   return rmem;
485 }
486
487@@ -444,6 +481,10 @@ mem_malloc(mem_size_t size)
488 {
489   mem_size_t ptr, ptr2;
490   struct mem *mem, *mem2;
491+#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
492+  u8_t local_mem_free_count = 0;
493+#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
494+  LWIP_MEM_ALLOC_DECL_PROTECT();
495
496   if (size == 0) {
497     return NULL;
498@@ -464,88 +505,101 @@ mem_malloc(mem_size_t size)
499
500   /* protect the heap from concurrent access */
501   sys_arch_sem_wait(mem_sem, 0);
502+  LWIP_MEM_ALLOC_PROTECT();
503+#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
504+  /* run as long as a mem_free disturbed mem_malloc */
505+  do {
506+    local_mem_free_count = 0;
507+#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
508+
509+    /* Scan through the heap searching for a free block that is big enough,
510+     * beginning with the lowest free block.
511+     */
512+    for (ptr = (u8_t *)lfree - ram; ptr < MEM_SIZE_ALIGNED - size;
513+         ptr = ((struct mem *)&ram[ptr])->next) {
514+      mem = (struct mem *)&ram[ptr];
515+#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
516+      mem_free_count = 0;
517+      LWIP_MEM_ALLOC_UNPROTECT();
518+      /* allow mem_free to run */
519+      LWIP_MEM_ALLOC_PROTECT();
520+      if (mem_free_count != 0) {
521+        local_mem_free_count = mem_free_count;
522+      }
523+      mem_free_count = 0;
524+#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
525
526-  /* Scan through the heap searching for a free block that is big enough,
527-   * beginning with the lowest free block.
528-   */
529-  for (ptr = (u8_t *)lfree - ram; ptr < MEM_SIZE_ALIGNED - size;
530-       ptr = ((struct mem *)&ram[ptr])->next) {
531-    mem = (struct mem *)&ram[ptr];
532-
533-    if ((!mem->used) &&
534-        (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) {
535-      /* mem is not used and at least perfect fit is possible:
536-       * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */
537-
538-      if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) {
539-        /* (in addition to the above, we test if another struct mem (SIZEOF_STRUCT_MEM) containing
540-         * at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem')
541-         * -> split large block, create empty remainder,
542-         * remainder must be large enough to contain MIN_SIZE_ALIGNED data: if
543-         * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size,
544-         * struct mem would fit in but no data between mem2 and mem2->next
545-         * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty
546-         *       region that couldn't hold data, but when mem->next gets freed,
547-         *       the 2 regions would be combined, resulting in more free memory
548-         */
549-        ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
550-        /* create mem2 struct */
551-        mem2 = (struct mem *)&ram[ptr2];
552-        mem2->used = 0;
553-        mem2->next = mem->next;
554-        mem2->prev = ptr;
555-        /* and insert it between mem and mem->next */
556-        mem->next = ptr2;
557-        mem->used = 1;
558-
559-        if (mem2->next != MEM_SIZE_ALIGNED) {
560-          ((struct mem *)&ram[mem2->next])->prev = ptr2;
561-        }
562-#if MEM_STATS
563-        lwip_stats.mem.used += (size + SIZEOF_STRUCT_MEM);
564-        if (lwip_stats.mem.max < lwip_stats.mem.used) {
565-          lwip_stats.mem.max = lwip_stats.mem.used;
566+      if ((!mem->used) &&
567+          (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) {
568+        /* mem is not used and at least perfect fit is possible:
569+         * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */
570+
571+        if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) {
572+          /* (in addition to the above, we test if another struct mem (SIZEOF_STRUCT_MEM) containing
573+           * at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem')
574+           * -> split large block, create empty remainder,
575+           * remainder must be large enough to contain MIN_SIZE_ALIGNED data: if
576+           * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size,
577+           * struct mem would fit in but no data between mem2 and mem2->next
578+           * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty
579+           *       region that couldn't hold data, but when mem->next gets freed,
580+           *       the 2 regions would be combined, resulting in more free memory
581+           */
582+          ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
583+          /* create mem2 struct */
584+          mem2 = (struct mem *)&ram[ptr2];
585+          mem2->used = 0;
586+          mem2->next = mem->next;
587+          mem2->prev = ptr;
588+          /* and insert it between mem and mem->next */
589+          mem->next = ptr2;
590+          mem->used = 1;
591+
592+          if (mem2->next != MEM_SIZE_ALIGNED) {
593+            ((struct mem *)&ram[mem2->next])->prev = ptr2;
594+          }
595+          MEM_STATS_INC_USED(used, (size + SIZEOF_STRUCT_MEM));
596+        } else {
597+          /* (a mem2 struct does no fit into the user data space of mem and mem->next will always
598+           * be used at this point: if not we have 2 unused structs in a row, plug_holes should have
599+           * take care of this).
600+           * -> near fit or excact fit: do not split, no mem2 creation
601+           * also can't move mem->next directly behind mem, since mem->next
602+           * will always be used at this point!
603+           */
604+          mem->used = 1;
605+          MEM_STATS_INC_USED(used, mem->next - ((u8_t *)mem - ram));
606         }
607-#endif /* MEM_STATS */
608-      } else {
609-        /* (a mem2 struct does no fit into the user data space of mem and mem->next will always
610-         * be used at this point: if not we have 2 unused structs in a row, plug_holes should have
611-         * take care of this).
612-         * -> near fit or excact fit: do not split, no mem2 creation
613-         * also can't move mem->next directly behind mem, since mem->next
614-         * will always be used at this point!
615-         */
616-        mem->used = 1;
617-#if MEM_STATS
618-        lwip_stats.mem.used += mem->next - ((u8_t *)mem - ram);
619-        if (lwip_stats.mem.max < lwip_stats.mem.used) {
620-          lwip_stats.mem.max = lwip_stats.mem.used;
621-        }
622-#endif /* MEM_STATS */
623-      }
624
625-      if (mem == lfree) {
626-        /* Find next free block after mem and update lowest free pointer */
627-        while (lfree->used && lfree != ram_end) {
628-          lfree = (struct mem *)&ram[lfree->next];
629+        if (mem == lfree) {
630+          /* Find next free block after mem and update lowest free pointer */
631+          while (lfree->used && lfree != ram_end) {
632+            LWIP_MEM_ALLOC_UNPROTECT();
633+            /* prevent high interrupt latency... */
634+            LWIP_MEM_ALLOC_PROTECT();
635+            lfree = (struct mem *)&ram[lfree->next];
636+          }
637+          LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used)));
638         }
639-        LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used)));
640-      }
641-      sys_sem_signal(mem_sem);
642-      LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
643-       (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);
644-      LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
645-       (unsigned long)((u8_t *)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
646-      LWIP_ASSERT("mem_malloc: sanity check alignment",
647-        (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0);
648+        LWIP_MEM_ALLOC_UNPROTECT();
649+        sys_sem_signal(mem_sem);
650+        LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
651+         (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);
652+        LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
653+         (unsigned long)((u8_t *)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
654+        LWIP_ASSERT("mem_malloc: sanity check alignment",
655+          (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0);
656
657-      return (u8_t *)mem + SIZEOF_STRUCT_MEM;
658+        return (u8_t *)mem + SIZEOF_STRUCT_MEM;
659+      }
660     }
661-  }
662+#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
663+    /* if we got interrupted by a mem_free, try again */
664+  } while(local_mem_free_count != 0);
665+#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
666   LWIP_DEBUGF(MEM_DEBUG | 2, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size));
667-#if MEM_STATS
668-  ++lwip_stats.mem.err;
669-#endif /* MEM_STATS */
670+  MEM_STATS_INC(err);
671+  LWIP_MEM_ALLOC_UNPROTECT();
672   sys_sem_signal(mem_sem);
673   return NULL;
674 }
675Index: src/core/memp.c
676===================================================================
677RCS file: /sources/lwip/lwip/src/core/memp.c,v
678retrieving revision 1.55
679retrieving revision 1.56
680diff -u -p -r1.55 -r1.56
681--- src/core/memp.c	25 Nov 2007 10:43:28 -0000	1.55
682+++ src/core/memp.c	27 Jun 2008 18:37:54 -0000	1.56
683@@ -252,13 +252,12 @@ memp_init(void)
684   struct memp *memp;
685   u16_t i, j;
686
687-#if MEMP_STATS
688   for (i = 0; i < MEMP_MAX; ++i) {
689-    lwip_stats.memp[i].used = lwip_stats.memp[i].max =
690-      lwip_stats.memp[i].err = 0;
691-    lwip_stats.memp[i].avail = memp_num[i];
692+    MEMP_STATS_AVAIL(used, i, 0);
693+    MEMP_STATS_AVAIL(max, i, 0);
694+    MEMP_STATS_AVAIL(err, i, 0);
695+    MEMP_STATS_AVAIL(avail, i, memp_num[i]);
696   }
697-#endif /* MEMP_STATS */
698
699   memp = LWIP_MEM_ALIGN(memp_memory);
700   /* for every pool: */
701@@ -315,20 +314,13 @@ memp_malloc_fn(memp_t type, const char*
702     memp->file = file;
703     memp->line = line;
704 #endif /* MEMP_OVERFLOW_CHECK */
705-#if MEMP_STATS
706-    ++lwip_stats.memp[type].used;
707-    if (lwip_stats.memp[type].used > lwip_stats.memp[type].max) {
708-      lwip_stats.memp[type].max = lwip_stats.memp[type].used;
709-    }
710-#endif /* MEMP_STATS */
711+    MEMP_STATS_INC_USED(used, type);
712     LWIP_ASSERT("memp_malloc: memp properly aligned",
713                 ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0);
714     memp = (struct memp*)((u8_t*)memp + MEMP_SIZE);
715   } else {
716     LWIP_DEBUGF(MEMP_DEBUG | 2, ("memp_malloc: out of memory in pool %s\n", memp_desc[type]));
717-#if MEMP_STATS
718-    ++lwip_stats.memp[type].err;
719-#endif /* MEMP_STATS */
720+    MEMP_STATS_INC(err, type);
721   }
722
723   SYS_ARCH_UNPROTECT(old_level);
724@@ -365,9 +357,7 @@ memp_free(memp_t type, void *mem)
725 #endif /* MEMP_OVERFLOW_CHECK >= 2 */
726 #endif /* MEMP_OVERFLOW_CHECK */
727
728-#if MEMP_STATS
729-  lwip_stats.memp[type].used--;
730-#endif /* MEMP_STATS */
731+  MEMP_STATS_DEC(used, type);
732
733   memp->next = memp_tab[type];
734   memp_tab[type] = memp;
735Index: src/core/netif.c
736===================================================================
737RCS file: /sources/lwip/lwip/src/core/netif.c,v
738retrieving revision 1.65
739retrieving revision 1.68
740diff -u -p -r1.65 -r1.68
741--- src/core/netif.c	9 Oct 2007 20:00:55 -0000	1.65
742+++ src/core/netif.c	19 Jun 2008 16:27:18 -0000	1.68
743@@ -45,6 +45,12 @@
744 #include "lwip/snmp.h"
745 #include "lwip/igmp.h"
746 #include "netif/etharp.h"
747+#if ENABLE_LOOPBACK
748+#include "lwip/sys.h"
749+#if LWIP_NETIF_LOOPBACK_MULTITHREADING
750+#include "lwip/tcpip.h"
751+#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
752+#endif /* ENABLE_LOOPBACK */
753
754 #if LWIP_NETIF_STATUS_CALLBACK
755 #define NETIF_STATUS_CALLBACK(n) { if (n->status_callback) (n->status_callback)(n); }
756@@ -106,6 +112,10 @@ netif_add(struct netif *netif, struct ip
757 #if LWIP_IGMP
758   netif->igmp_mac_filter = NULL;
759 #endif /* LWIP_IGMP */
760+#if ENABLE_LOOPBACK
761+  netif->loop_first = NULL;
762+  netif->loop_last = NULL;
763+#endif /* ENABLE_LOOPBACK */
764
765   /* remember netif specific state information data */
766   netif->state = state;
767@@ -114,6 +124,9 @@ netif_add(struct netif *netif, struct ip
768 #if LWIP_NETIF_HWADDRHINT
769   netif->addr_hint = NULL;
770 #endif /* LWIP_NETIF_HWADDRHINT*/
771+#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS
772+  netif->loop_cnt_current = 0;
773+#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */
774
775   netif_set_addr(netif, ipaddr, netmask, gw);
776
777@@ -493,7 +506,158 @@ u8_t netif_is_link_up(struct netif *neti
778  */
779 void netif_set_link_callback(struct netif *netif, void (* link_callback)(struct netif *netif ))
780 {
781-    if ( netif )
782-        netif->link_callback = link_callback;
783+  if (netif) {
784+    netif->link_callback = link_callback;
785+  }
786 }
787 #endif /* LWIP_NETIF_LINK_CALLBACK */
788+
789+#if ENABLE_LOOPBACK
790+/**
791+ * Send an IP packet to be received on the same netif (loopif-like).
792+ * The pbuf is simply copied and handed back to netif->input.
793+ * In multithreaded mode, this is done directly since netif->input must put
794+ * the packet on a queue.
795+ * In callback mode, the packet is put on an internal queue and is fed to
796+ * netif->input by netif_poll().
797+ *
798+ * @param netif the lwip network interface structure
799+ * @param p the (IP) packet to 'send'
800+ * @param ipaddr the ip address to send the packet to (not used)
801+ * @return ERR_OK if the packet has been sent
802+ *         ERR_MEM if the pbuf used to copy the packet couldn't be allocated
803+ */
804+err_t
805+netif_loop_output(struct netif *netif, struct pbuf *p,
806+       struct ip_addr *ipaddr)
807+{
808+  struct pbuf *r;
809+  err_t err;
810+  struct pbuf *last;
811+#if LWIP_LOOPBACK_MAX_PBUFS
812+  u8_t clen = 0;
813+#endif /* LWIP_LOOPBACK_MAX_PBUFS */
814+  SYS_ARCH_DECL_PROTECT(lev);
815+  LWIP_UNUSED_ARG(ipaddr);
816+
817+  /* Allocate a new pbuf */
818+  r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM);
819+  if (r == NULL) {
820+    return ERR_MEM;
821+  }
822+#if LWIP_LOOPBACK_MAX_PBUFS
823+  clen = pbuf_clen(r);
824+  /* check for overflow or too many pbuf on queue */
825+  if(((netif->loop_cnt_current + clen) < netif->loop_cnt_current) ||
826+    ((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) {
827+      pbuf_free(r);
828+      r = NULL;
829+      return ERR_MEM;
830+  }
831+  netif->loop_cnt_current += clen;
832+#endif /* LWIP_LOOPBACK_MAX_PBUFS */
833+
834+  /* Copy the whole pbuf queue p into the single pbuf r */
835+  if ((err = pbuf_copy(r, p)) != ERR_OK) {
836+    pbuf_free(r);
837+    r = NULL;
838+    return err;
839+  }
840+
841+  /* Put the packet on a linked list which gets emptied through calling
842+     netif_poll(). */
843+
844+  /* let last point to the last pbuf in chain r */
845+  for (last = r; last->next != NULL; last = last->next);
846+
847+  SYS_ARCH_PROTECT(lev);
848+  if(netif->loop_first != NULL) {
849+    LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL);
850+    netif->loop_last->next = r;
851+    netif->loop_last = last;
852+  } else {
853+    netif->loop_first = r;
854+    netif->loop_last = last;
855+  }
856+  SYS_ARCH_UNPROTECT(lev);
857+
858+#if LWIP_NETIF_LOOPBACK_MULTITHREADING
859+  /* For multithreading environment, schedule a call to netif_poll */
860+  tcpip_callback(netif_poll, netif);
861+#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
862+
863+  return ERR_OK;
864+}
865+
866+/**
867+ * Call netif_poll() in the main loop of your application. This is to prevent
868+ * reentering non-reentrant functions like tcp_input(). Packets passed to
869+ * netif_loop_output() are put on a list that is passed to netif->input() by
870+ * netif_poll().
871+ */
872+void
873+netif_poll(struct netif *netif)
874+{
875+  struct pbuf *in;
876+  SYS_ARCH_DECL_PROTECT(lev);
877+
878+  do {
879+    /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */
880+    SYS_ARCH_PROTECT(lev);
881+    in = netif->loop_first;
882+    if(in != NULL) {
883+      struct pbuf *in_end = in;
884+#if LWIP_LOOPBACK_MAX_PBUFS
885+      u8_t clen = pbuf_clen(in);
886+      /* adjust the number of pbufs on queue */
887+      LWIP_ASSERT("netif->loop_cnt_current underflow",
888+        ((netif->loop_cnt_current - clen) < netif->loop_cnt_current));
889+      netif->loop_cnt_current -= clen;
890+#endif /* LWIP_LOOPBACK_MAX_PBUFS */
891+      while(in_end->len != in_end->tot_len) {
892+        LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
893+        in_end = in_end->next;
894+      }
895+      /* 'in_end' now points to the last pbuf from 'in' */
896+      if(in_end == netif->loop_last) {
897+        /* this was the last pbuf in the list */
898+        netif->loop_first = netif->loop_last = NULL;
899+      } else {
900+        /* pop the pbuf off the list */
901+        netif->loop_first = in_end->next;
902+        LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL);
903+      }
904+      /* De-queue the pbuf from its successors on the 'loop_' list. */
905+      in_end->next = NULL;
906+    }
907+    SYS_ARCH_UNPROTECT(lev);
908+
909+    if(in != NULL) {
910+      /* loopback packets are always IP packets! */
911+      if(ip_input(in, netif) != ERR_OK) {
912+        pbuf_free(in);
913+      }
914+      /* Don't reference the packet any more! */
915+      in = NULL;
916+    }
917+  /* go on while there is a packet on the list */
918+  } while(netif->loop_first != NULL);
919+}
920+
921+#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
922+/**
923+ * Calls netif_poll() for every netif on the netif_list.
924+ */
925+void
926+netif_poll_all(void)
927+{
928+  struct netif *netif = netif_list;
929+  /* loop through netifs */
930+  while (netif != NULL) {
931+    netif_poll(netif);
932+    /* proceed to next network interface */
933+    netif = netif->next;
934+  }
935+}
936+#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
937+#endif /* ENABLE_LOOPBACK */
938Index: src/core/pbuf.c
939===================================================================
940RCS file: /sources/lwip/lwip/src/core/pbuf.c,v
941retrieving revision 1.127
942retrieving revision 1.128
943diff -u -p -r1.127 -r1.128
944--- src/core/pbuf.c	4 Mar 2008 16:37:46 -0000	1.127
945+++ src/core/pbuf.c	1 Apr 2008 19:05:40 -0000	1.128
946@@ -667,8 +667,8 @@ pbuf_dechain(struct pbuf *p)
947  *
948  * @note Only one packet is copied, no packet queue!
949  *
950- * @param p_to pbuf source of the copy
951- * @param p_from pbuf destination of the copy
952+ * @param p_to pbuf destination of the copy
953+ * @param p_from pbuf source of the copy
954  *
955  * @return ERR_OK if pbuf was copied
956  *         ERR_ARG if one of the pbufs is NULL or p_to is not big
957Index: src/core/stats.c
958===================================================================
959RCS file: /sources/lwip/lwip/src/core/stats.c,v
960retrieving revision 1.27
961retrieving revision 1.28
962diff -u -p -r1.27 -r1.28
963--- src/core/stats.c	4 Mar 2008 16:31:32 -0000	1.27
964+++ src/core/stats.c	27 Jun 2008 18:37:54 -0000	1.28
965@@ -54,7 +54,6 @@ stats_display_proto(struct stats_proto *
966 {
967   LWIP_PLATFORM_DIAG(("\n%s\n\t", name));
968   LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", proto->xmit));
969-  LWIP_PLATFORM_DIAG(("rexmit: %"STAT_COUNTER_F"\n\t", proto->rexmit));
970   LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", proto->recv));
971   LWIP_PLATFORM_DIAG(("fw: %"STAT_COUNTER_F"\n\t", proto->fw));
972   LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", proto->drop));
973@@ -68,6 +67,7 @@ stats_display_proto(struct stats_proto *
974   LWIP_PLATFORM_DIAG(("cachehit: %"STAT_COUNTER_F"\n", proto->cachehit));
975 }
976
977+#if IGMP_STATS
978 void
979 stats_display_igmp(struct stats_igmp *igmp)
980 {
981@@ -82,7 +82,9 @@ stats_display_igmp(struct stats_igmp *ig
982   LWIP_PLATFORM_DIAG(("report_rxed: %"STAT_COUNTER_F"\n\t", igmp->report_rxed));
983   LWIP_PLATFORM_DIAG(("group_query_rxed: %"STAT_COUNTER_F"\n", igmp->group_query_rxed));
984 }
985+#endif /* IGMP_STATS */
986
987+#if MEM_STATS || MEMP_STATS
988 void
989 stats_display_mem(struct stats_mem *mem, char *name)
990 {
991@@ -93,48 +95,53 @@ stats_display_mem(struct stats_mem *mem,
992   LWIP_PLATFORM_DIAG(("err: %"U32_F"\n", (u32_t)mem->err));
993 }
994
995+#if MEMP_STATS
996 void
997-stats_display(void)
998+stats_display_memp(struct stats_mem *mem, int index)
999 {
1000-#if MEMP_STATS
1001-  s16_t i;
1002   char * memp_names[] = {
1003 #define LWIP_MEMPOOL(name,num,size,desc) desc,
1004 #include "lwip/memp_std.h"
1005   };
1006-#endif
1007-#if LINK_STATS
1008-  stats_display_proto(&lwip_stats.link, "LINK");
1009-#endif
1010-#if ETHARP_STATS
1011-  stats_display_proto(&lwip_stats.etharp, "ETHARP");
1012-#endif
1013-#if IPFRAG_STATS
1014-  stats_display_proto(&lwip_stats.ip_frag, "IP_FRAG");
1015-#endif
1016-#if IP_STATS
1017-  stats_display_proto(&lwip_stats.ip, "IP");
1018-#endif
1019-#if ICMP_STATS
1020-  stats_display_proto(&lwip_stats.icmp, "ICMP");
1021-#endif
1022-#if IGMP_STATS
1023-  stats_display_igmp(&lwip_stats.igmp);
1024-#endif
1025-#if UDP_STATS
1026-  stats_display_proto(&lwip_stats.udp, "UDP");
1027-#endif
1028-#if TCP_STATS
1029-  stats_display_proto(&lwip_stats.tcp, "TCP");
1030-#endif
1031-#if MEM_STATS
1032-  stats_display_mem(&lwip_stats.mem, "HEAP");
1033-#endif
1034-#if MEMP_STATS
1035+  if(index < MEMP_MAX) {
1036+    stats_display_mem(mem, memp_names[index]);
1037+  }
1038+}
1039+#endif /* MEMP_STATS */
1040+#endif /* MEM_STATS || MEMP_STATS */
1041+
1042+#if SYS_STATS
1043+void
1044+stats_display_sys(struct stats_sys *sys)
1045+{
1046+  LWIP_PLATFORM_DIAG(("\nSYS\n\t"));
1047+  LWIP_PLATFORM_DIAG(("sem.used: %"U32_F"\n\t", (u32_t)sys->sem.used));
1048+  LWIP_PLATFORM_DIAG(("sem.max:  %"U32_F"\n\t", (u32_t)sys->sem.max));
1049+  LWIP_PLATFORM_DIAG(("sem.err:  %"U32_F"\n\t", (u32_t)sys->sem.err));
1050+  LWIP_PLATFORM_DIAG(("mbox.used: %"U32_F"\n\t", (u32_t)sys->mbox.used));
1051+  LWIP_PLATFORM_DIAG(("mbox.max:  %"U32_F"\n\t", (u32_t)sys->mbox.max));
1052+  LWIP_PLATFORM_DIAG(("mbox.err:  %"U32_F"\n\t", (u32_t)sys->mbox.err));
1053+}
1054+#endif /* SYS_STATS */
1055+
1056+void
1057+stats_display(void)
1058+{
1059+  s16_t i;
1060+
1061+  LINK_STATS_DISPLAY();
1062+  ETHARP_STATS_DISPLAY();
1063+  IPFRAG_STATS_DISPLAY();
1064+  IP_STATS_DISPLAY();
1065+  IGMP_STATS_DISPLAY();
1066+  ICMP_STATS_DISPLAY();
1067+  UDP_STATS_DISPLAY();
1068+  TCP_STATS_DISPLAY();
1069+  MEM_STATS_DISPLAY();
1070   for (i = 0; i < MEMP_MAX; i++) {
1071-    stats_display_mem(&lwip_stats.memp[i], memp_names[i]);
1072+    MEMP_STATS_DISPLAY(i);
1073   }
1074-#endif
1075+  SYS_STATS_DISPLAY();
1076 }
1077 #endif /* LWIP_STATS_DISPLAY */
1078
1079Index: src/core/sys.c
1080===================================================================
1081RCS file: /sources/lwip/lwip/src/core/sys.c,v
1082retrieving revision 1.32
1083retrieving revision 1.33
1084diff -u -p -r1.32 -r1.33
1085--- src/core/sys.c	25 Nov 2007 13:57:05 -0000	1.32
1086+++ src/core/sys.c	16 Jul 2008 20:36:12 -0000	1.33
1087@@ -65,7 +65,7 @@ struct sswt_cb
1088 void
1089 sys_mbox_fetch(sys_mbox_t mbox, void **msg)
1090 {
1091-  u32_t time;
1092+  u32_t time_needed;
1093   struct sys_timeouts *timeouts;
1094   struct sys_timeo *tmptimeout;
1095   sys_timeout_handler h;
1096@@ -76,18 +76,18 @@ sys_mbox_fetch(sys_mbox_t mbox, void **m
1097
1098   if (!timeouts || !timeouts->next) {
1099     UNLOCK_TCPIP_CORE();
1100-    time = sys_arch_mbox_fetch(mbox, msg, 0);
1101+    time_needed = sys_arch_mbox_fetch(mbox, msg, 0);
1102     LOCK_TCPIP_CORE();
1103   } else {
1104     if (timeouts->next->time > 0) {
1105       UNLOCK_TCPIP_CORE();
1106-      time = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time);
1107+      time_needed = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time);
1108       LOCK_TCPIP_CORE();
1109     } else {
1110-      time = SYS_ARCH_TIMEOUT;
1111+      time_needed = SYS_ARCH_TIMEOUT;
1112     }
1113
1114-    if (time == SYS_ARCH_TIMEOUT) {
1115+    if (time_needed == SYS_ARCH_TIMEOUT) {
1116       /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
1117          could be fetched. We should now call the timeout handler and
1118          deallocate the memory allocated for the timeout. */
1119@@ -107,8 +107,8 @@ sys_mbox_fetch(sys_mbox_t mbox, void **m
1120       /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout
1121          occured. The time variable is set to the number of
1122          milliseconds we waited for the message. */
1123-      if (time < timeouts->next->time) {
1124-        timeouts->next->time -= time;
1125+      if (time_needed < timeouts->next->time) {
1126+        timeouts->next->time -= time_needed;
1127       } else {
1128         timeouts->next->time = 0;
1129       }
1130@@ -125,7 +125,7 @@ sys_mbox_fetch(sys_mbox_t mbox, void **m
1131 void
1132 sys_sem_wait(sys_sem_t sem)
1133 {
1134-  u32_t time;
1135+  u32_t time_needed;
1136   struct sys_timeouts *timeouts;
1137   struct sys_timeo *tmptimeout;
1138   sys_timeout_handler h;
1139@@ -139,12 +139,12 @@ sys_sem_wait(sys_sem_t sem)
1140     sys_arch_sem_wait(sem, 0);
1141   } else {
1142     if (timeouts->next->time > 0) {
1143-      time = sys_arch_sem_wait(sem, timeouts->next->time);
1144+      time_needed = sys_arch_sem_wait(sem, timeouts->next->time);
1145     } else {
1146-      time = SYS_ARCH_TIMEOUT;
1147+      time_needed = SYS_ARCH_TIMEOUT;
1148     }
1149
1150-    if (time == SYS_ARCH_TIMEOUT) {
1151+    if (time_needed == SYS_ARCH_TIMEOUT) {
1152       /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
1153         could be fetched. We should now call the timeout handler and
1154         deallocate the memory allocated for the timeout. */
1155@@ -164,8 +164,8 @@ sys_sem_wait(sys_sem_t sem)
1156       /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout
1157          occured. The time variable is set to the number of
1158          milliseconds we waited for the message. */
1159-      if (time < timeouts->next->time) {
1160-        timeouts->next->time -= time;
1161+      if (time_needed < timeouts->next->time) {
1162+        timeouts->next->time -= time_needed;
1163       } else {
1164         timeouts->next->time = 0;
1165       }
1166Index: src/core/tcp.c
1167===================================================================
1168RCS file: /sources/lwip/lwip/src/core/tcp.c,v
1169retrieving revision 1.85
1170retrieving revision 1.86
1171diff -u -p -r1.85 -r1.86
1172--- src/core/tcp.c	22 Jan 2008 21:15:15 -0000	1.85
1173+++ src/core/tcp.c	26 Mar 2008 11:57:13 -0000	1.86
1174@@ -509,7 +509,8 @@ tcp_connect(struct tcp_pcb *pcb, struct
1175   pcb->rcv_wnd = TCP_WND;
1176   pcb->rcv_ann_wnd = TCP_WND;
1177   pcb->snd_wnd = TCP_WND;
1178-  /* The send MSS is updated when an MSS option is received. */
1179+  /* As initial send MSS, we use TCP_MSS but limit it to 536.
1180+     The send MSS is updated when an MSS option is received. */
1181   pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;
1182 #if TCP_CALCULATE_EFF_SEND_MSS
1183   pcb->mss = tcp_eff_send_mss(pcb->mss, ipaddr);
1184@@ -991,7 +992,8 @@ tcp_alloc(u8_t prio)
1185     pcb->rcv_ann_wnd = TCP_WND;
1186     pcb->tos = 0;
1187     pcb->ttl = TCP_TTL;
1188-    /* The send MSS is updated when an MSS option is received. */
1189+    /* As initial send MSS, we use TCP_MSS but limit it to 536.
1190+       The send MSS is updated when an MSS option is received. */
1191     pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;
1192     pcb->rto = 3000 / TCP_SLOW_INTERVAL;
1193     pcb->sa = 0;
1194Index: src/core/tcp_in.c
1195===================================================================
1196RCS file: /sources/lwip/lwip/src/core/tcp_in.c,v
1197retrieving revision 1.97
1198retrieving revision 1.100
1199diff -u -p -r1.97 -r1.100
1200--- src/core/tcp_in.c	22 Jan 2008 21:15:15 -0000	1.97
1201+++ src/core/tcp_in.c	24 Jun 2008 15:46:39 -0000	1.100
1202@@ -511,7 +511,7 @@ tcp_process(struct tcp_pcb *pcb)
1203       }
1204     } else {
1205       if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
1206-                          pcb->rcv_nxt+pcb->rcv_ann_wnd)) {
1207+                          pcb->rcv_nxt+pcb->rcv_wnd)) {
1208         acceptable = 1;
1209       }
1210     }
1211@@ -1038,7 +1038,7 @@ tcp_receive(struct tcp_pcb *pcb)
1212        and below rcv_nxt + rcv_wnd) in order to be further
1213        processed. */
1214     if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
1215-                        pcb->rcv_nxt + pcb->rcv_ann_wnd - 1)){
1216+                        pcb->rcv_nxt + pcb->rcv_wnd - 1)){
1217       if (pcb->rcv_nxt == seqno) {
1218         accepted_inseq = 1;
1219         /* The incoming segment is the next in sequence. We check if
1220@@ -1195,14 +1195,14 @@ tcp_receive(struct tcp_pcb *pcb)
1221                   } else {
1222                     pcb->ooseq = cseg;
1223                   }
1224-                }
1225-                tcp_seg_free(next);
1226-                if (cseg->next != NULL) {
1227-                  next = cseg->next;
1228-                  if (TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) {
1229-                    /* We need to trim the incoming segment. */
1230-                    cseg->len = (u16_t)(next->tcphdr->seqno - seqno);
1231-                    pbuf_realloc(cseg->p, cseg->len);
1232+                  tcp_seg_free(next);
1233+                  if (cseg->next != NULL) {
1234+                    next = cseg->next;
1235+                    if (TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) {
1236+                      /* We need to trim the incoming segment. */
1237+                      cseg->len = (u16_t)(next->tcphdr->seqno - seqno);
1238+                      pbuf_realloc(cseg->p, cseg->len);
1239+                    }
1240                   }
1241                 }
1242                 break;
1243@@ -1282,10 +1282,7 @@ tcp_receive(struct tcp_pcb *pcb)
1244
1245       }
1246     } else {
1247-      if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
1248-                          pcb->rcv_nxt + pcb->rcv_ann_wnd-1)){
1249-        tcp_ack_now(pcb);
1250-      }
1251+      tcp_ack_now(pcb);
1252     }
1253   } else {
1254     /* Segments with length 0 is taken care of here. Segments that
1255@@ -1331,7 +1328,8 @@ tcp_parseopt(struct tcp_pcb *pcb)
1256         opts[c + 1] == 0x04) {
1257         /* An MSS option with the right option length. */
1258         mss = (opts[c + 2] << 8) | opts[c + 3];
1259-        pcb->mss = mss > TCP_MSS? TCP_MSS: mss;
1260+        /* Limit the mss to the configured TCP_MSS and prevent division by zero */
1261+        pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss;
1262
1263         /* And we are done processing options. */
1264         break;
1265Index: src/core/ipv4/autoip.c
1266===================================================================
1267RCS file: /sources/lwip/lwip/src/core/ipv4/autoip.c,v
1268retrieving revision 1.16
1269retrieving revision 1.17
1270diff -u -p -r1.16 -r1.17
1271--- src/core/ipv4/autoip.c	26 Jan 2008 16:11:40 -0000	1.16
1272+++ src/core/ipv4/autoip.c	17 Jun 2008 20:16:23 -0000	1.17
1273@@ -395,8 +395,8 @@ autoip_arp_reply(struct netif *netif, st
1274     /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
1275      * structure packing (not using structure copy which breaks strict-aliasing rules).
1276      */
1277-    MEMCPY(&sipaddr, &hdr->sipaddr, sizeof(sipaddr));
1278-    MEMCPY(&dipaddr, &hdr->dipaddr, sizeof(dipaddr));
1279+    SMEMCPY(&sipaddr, &hdr->sipaddr, sizeof(sipaddr));
1280+    SMEMCPY(&dipaddr, &hdr->dipaddr, sizeof(dipaddr));
1281
1282     if ((netif->autoip->state == AUTOIP_STATE_PROBING) ||
1283         ((netif->autoip->state == AUTOIP_STATE_ANNOUNCING) &&
1284Index: src/core/ipv4/inet_chksum.c
1285===================================================================
1286RCS file: /sources/lwip/lwip/src/core/ipv4/inet_chksum.c,v
1287retrieving revision 1.4
1288retrieving revision 1.5
1289diff -u -p -r1.4 -r1.5
1290--- src/core/ipv4/inet_chksum.c	10 Mar 2008 16:12:31 -0000	1.4
1291+++ src/core/ipv4/inet_chksum.c	17 Jun 2008 20:06:25 -0000	1.5
1292@@ -41,8 +41,6 @@
1293 #include "lwip/inet_chksum.h"
1294 #include "lwip/inet.h"
1295
1296-#include <string.h>
1297-
1298 /* These are some reference implementations of the checksum algorithm, with the
1299  * aim of being simple, correct and fully portable. Checksumming is the
1300  * first thing you would want to optimize for your platform. If you create
1301@@ -65,6 +63,11 @@
1302 # define LWIP_CHKSUM_ALGORITHM 0
1303 #endif
1304
1305+/** Like the name says... */
1306+#define SWAP_BYTES_IN_WORD(w) ((w & 0xff) << 8) | ((w & 0xff00) >> 8)
1307+/** Split an u32_t in two u16_ts and add them up */
1308+#define FOLD_U32T(u)          ((u >> 16) + (u & 0x0000ffffUL))
1309+
1310 #if (LWIP_CHKSUM_ALGORITHM == 1) /* Version #1 */
1311 /**
1312  * lwip checksum
1313@@ -86,8 +89,7 @@ lwip_standard_chksum(void *dataptr, u16_
1314   acc = 0;
1315   /* dataptr may be at odd or even addresses */
1316   octetptr = (u8_t*)dataptr;
1317-  while (len > 1)
1318-  {
1319+  while (len > 1) {
1320     /* declare first octet as most significant
1321        thus assume network order, ignoring host order */
1322     src = (*octetptr) << 8;
1323@@ -98,8 +100,7 @@ lwip_standard_chksum(void *dataptr, u16_
1324     acc += src;
1325     len -= 2;
1326   }
1327-  if (len > 0)
1328-  {
1329+  if (len > 0) {
1330     /* accumulate remaining octet */
1331     src = (*octetptr) << 8;
1332     acc += src;
1333@@ -154,19 +155,22 @@ lwip_standard_chksum(void *dataptr, int
1334   }
1335
1336   /* Consume left-over byte, if any */
1337-  if (len > 0)
1338+  if (len > 0) {
1339     ((u8_t *)&t)[0] = *(u8_t *)ps;;
1340+  }
1341
1342   /* Add end bytes */
1343   sum += t;
1344
1345-  /*  Fold 32-bit sum to 16 bits */
1346-  while ((sum >> 16) != 0)
1347-    sum = (sum & 0xffff) + (sum >> 16);
1348+  /* Fold 32-bit sum to 16 bits
1349+     calling this twice is propably faster than if statements... */
1350+  sum = FOLD_U32T(sum);
1351+  sum = FOLD_U32T(sum);
1352
1353   /* Swap if alignment was odd */
1354-  if (odd)
1355-    sum = ((sum & 0xff) << 8) | ((sum & 0xff00) >> 8);
1356+  if (odd) {
1357+    sum = SWAP_BYTES_IN_WORD(sum);
1358+  }
1359
1360   return sum;
1361 }
1362@@ -211,18 +215,20 @@ lwip_standard_chksum(void *dataptr, int
1363
1364   while (len > 7)  {
1365     tmp = sum + *pl++;          /* ping */
1366-    if (tmp < sum)
1367+    if (tmp < sum) {
1368       tmp++;                    /* add back carry */
1369+    }
1370
1371     sum = tmp + *pl++;          /* pong */
1372-    if (sum < tmp)
1373+    if (sum < tmp) {
1374       sum++;                    /* add back carry */
1375+    }
1376
1377     len -= 8;
1378   }
1379
1380   /* make room in upper bits */
1381-  sum = (sum >> 16) + (sum & 0xffff);
1382+  sum = FOLD_U32T(sum);
1383
1384   ps = (u16_t *)pl;
1385
1386@@ -233,16 +239,20 @@ lwip_standard_chksum(void *dataptr, int
1387   }
1388
1389   /* dangling tail byte remaining? */
1390-  if (len > 0)                  /* include odd byte */
1391+  if (len > 0) {                /* include odd byte */
1392     ((u8_t *)&t)[0] = *(u8_t *)ps;
1393+  }
1394
1395   sum += t;                     /* add end bytes */
1396
1397-  while ((sum >> 16) != 0)      /* combine halves */
1398-    sum = (sum >> 16) + (sum & 0xffff);
1399+  /* Fold 32-bit sum to 16 bits
1400+     calling this twice is propably faster than if statements... */
1401+  sum = FOLD_U32T(sum);
1402+  sum = FOLD_U32T(sum);
1403
1404-  if (odd)
1405-    sum = ((sum & 0xff) << 8) | ((sum & 0xff00) >> 8);
1406+  if (odd) {
1407+    sum = SWAP_BYTES_IN_WORD(sum);
1408+  }
1409
1410   return sum;
1411 }
1412@@ -277,18 +287,18 @@ inet_chksum_pseudo(struct pbuf *p,
1413       (void *)q, (void *)q->next));
1414     acc += LWIP_CHKSUM(q->payload, q->len);
1415     /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/
1416-    while ((acc >> 16) != 0) {
1417-      acc = (acc & 0xffffUL) + (acc >> 16);
1418-    }
1419+    /* just executing this next line is probably faster that the if statement needed
1420+       to check whether we really need to execute it, and does no harm */
1421+    acc = FOLD_U32T(acc);
1422     if (q->len % 2 != 0) {
1423       swapped = 1 - swapped;
1424-      acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
1425+      acc = SWAP_BYTES_IN_WORD(acc);
1426     }
1427     /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/
1428   }
1429
1430   if (swapped) {
1431-    acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
1432+    acc = SWAP_BYTES_IN_WORD(acc);
1433   }
1434   acc += (src->addr & 0xffffUL);
1435   acc += ((src->addr >> 16) & 0xffffUL);
1436@@ -297,9 +307,10 @@ inet_chksum_pseudo(struct pbuf *p,
1437   acc += (u32_t)htons((u16_t)proto);
1438   acc += (u32_t)htons(proto_len);
1439
1440-  while ((acc >> 16) != 0) {
1441-    acc = (acc & 0xffffUL) + (acc >> 16);
1442-  }
1443+  /* Fold 32-bit sum to 16 bits
1444+     calling this twice is propably faster than if statements... */
1445+  acc = FOLD_U32T(acc);
1446+  acc = FOLD_U32T(acc);
1447   LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
1448   return (u16_t)~(acc & 0xffffUL);
1449 }
1450@@ -340,18 +351,17 @@ inet_chksum_pseudo_partial(struct pbuf *
1451     chksum_len -= chklen;
1452     LWIP_ASSERT("delete me", chksum_len < 0x7fff);
1453     /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/
1454-    while ((acc >> 16) != 0) {
1455-      acc = (acc & 0xffffUL) + (acc >> 16);
1456-    }
1457+    /* fold the upper bit down */
1458+    acc = FOLD_U32T(acc);
1459     if (q->len % 2 != 0) {
1460       swapped = 1 - swapped;
1461-      acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
1462+      acc = SWAP_BYTES_IN_WORD(acc);
1463     }
1464     /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/
1465   }
1466
1467   if (swapped) {
1468-    acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
1469+    acc = SWAP_BYTES_IN_WORD(acc);
1470   }
1471   acc += (src->addr & 0xffffUL);
1472   acc += ((src->addr >> 16) & 0xffffUL);
1473@@ -360,9 +370,10 @@ inet_chksum_pseudo_partial(struct pbuf *
1474   acc += (u32_t)htons((u16_t)proto);
1475   acc += (u32_t)htons(proto_len);
1476
1477-  while ((acc >> 16) != 0) {
1478-    acc = (acc & 0xffffUL) + (acc >> 16);
1479-  }
1480+  /* Fold 32-bit sum to 16 bits
1481+     calling this twice is propably faster than if statements... */
1482+  acc = FOLD_U32T(acc);
1483+  acc = FOLD_U32T(acc);
1484   LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
1485   return (u16_t)~(acc & 0xffffUL);
1486 }
1487@@ -380,13 +391,7 @@ inet_chksum_pseudo_partial(struct pbuf *
1488 u16_t
1489 inet_chksum(void *dataptr, u16_t len)
1490 {
1491-  u32_t acc;
1492-
1493-  acc = LWIP_CHKSUM(dataptr, len);
1494-  while ((acc >> 16) != 0) {
1495-    acc = (acc & 0xffff) + (acc >> 16);
1496-  }
1497-  return (u16_t)~(acc & 0xffff);
1498+  return ~LWIP_CHKSUM(dataptr, len);
1499 }
1500
1501 /**
1502@@ -407,17 +412,15 @@ inet_chksum_pbuf(struct pbuf *p)
1503   swapped = 0;
1504   for(q = p; q != NULL; q = q->next) {
1505     acc += LWIP_CHKSUM(q->payload, q->len);
1506-    while ((acc >> 16) != 0) {
1507-      acc = (acc & 0xffffUL) + (acc >> 16);
1508-    }
1509+    acc = FOLD_U32T(acc);
1510     if (q->len % 2 != 0) {
1511       swapped = 1 - swapped;
1512-      acc = (acc & 0x00ffUL << 8) | (acc & 0xff00UL >> 8);
1513+      acc = SWAP_BYTES_IN_WORD(acc);
1514     }
1515   }
1516
1517   if (swapped) {
1518-    acc = ((acc & 0x00ffUL) << 8) | ((acc & 0xff00UL) >> 8);
1519+    acc = SWAP_BYTES_IN_WORD(acc);
1520   }
1521   return (u16_t)~(acc & 0xffffUL);
1522 }
1523Index: src/core/ipv4/ip.c
1524===================================================================
1525RCS file: /sources/lwip/lwip/src/core/ipv4/ip.c,v
1526retrieving revision 1.66
1527retrieving revision 1.68
1528diff -u -p -r1.66 -r1.68
1529--- src/core/ipv4/ip.c	14 Jan 2008 20:53:23 -0000	1.66
1530+++ src/core/ipv4/ip.c	17 Jun 2008 19:39:22 -0000	1.68
1531@@ -531,9 +531,19 @@ ip_output_if(struct pbuf *p, struct ip_a
1532   LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num));
1533   ip_debug_print(p);
1534
1535-  LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
1536+#if (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF)
1537+  if (ip_addr_cmp(dest, &netif->ip_addr)) {
1538+    /* Packet to self, enqueue it for loopback */
1539+    LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()"));
1540+
1541+    return netif_loop_output(netif, p, dest);
1542+  } else
1543+#endif /* (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF) */
1544+  {
1545+    LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
1546
1547-  return netif->output(netif, p, dest);
1548+    return netif->output(netif, p, dest);
1549+  }
1550 }
1551
1552 /**
1553Index: src/include/lwip/debug.h
1554===================================================================
1555RCS file: /sources/lwip/lwip/src/include/lwip/debug.h,v
1556retrieving revision 1.37
1557retrieving revision 1.39
1558diff -u -p -r1.37 -r1.39
1559--- src/include/lwip/debug.h	22 Sep 2007 11:16:07 -0000	1.37
1560+++ src/include/lwip/debug.h	16 Jul 2008 20:36:22 -0000	1.39
1561@@ -61,26 +61,28 @@
1562 #define LWIP_DBG_HALT          0x08U
1563
1564 #ifndef LWIP_NOASSERT
1565-#define LWIP_ASSERT(x,y) do { if(!(y)) LWIP_PLATFORM_ASSERT(x); } while(0)
1566+#define LWIP_ASSERT(message, assertion) do { if(!(assertion)) \
1567+  LWIP_PLATFORM_ASSERT(message); } while(0)
1568 #else  /* LWIP_NOASSERT */
1569-#define LWIP_ASSERT(x,y)
1570+#define LWIP_ASSERT(message, assertion)
1571 #endif /* LWIP_NOASSERT */
1572
1573-/** print "m" message only if "e" is true, and execute "h" expression */
1574+/** if "expression" isn't true, then print "message" and execute "handler" expression */
1575 #ifndef LWIP_ERROR
1576-#define LWIP_ERROR(m,e,h) do { if (!(e)) { LWIP_PLATFORM_ASSERT(m); h;}} while(0)
1577+#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \
1578+  LWIP_PLATFORM_ASSERT(message); handler;}} while(0)
1579 #endif /* LWIP_ERROR */
1580
1581 #ifdef LWIP_DEBUG
1582 /** print debug message only if debug message type is enabled...
1583  *  AND is of correct type AND is at least LWIP_DBG_LEVEL
1584  */
1585-#define LWIP_DEBUGF(debug,x) do { \
1586+#define LWIP_DEBUGF(debug, message) do { \
1587                                if ( \
1588                                    ((debug) & LWIP_DBG_ON) && \
1589                                    ((debug) & LWIP_DBG_TYPES_ON) && \
1590                                    ((s16_t)((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL)) { \
1591-                                 LWIP_PLATFORM_DIAG(x); \
1592+                                 LWIP_PLATFORM_DIAG(message); \
1593                                  if ((debug) & LWIP_DBG_HALT) { \
1594                                    while(1); \
1595                                  } \
1596@@ -88,7 +90,7 @@
1597                              } while(0)
1598
1599 #else  /* LWIP_DEBUG */
1600-#define LWIP_DEBUGF(debug,x)
1601+#define LWIP_DEBUGF(debug, message)
1602 #endif /* LWIP_DEBUG */
1603
1604 #endif /* __LWIP_DEBUG_H__ */
1605Index: src/include/lwip/err.h
1606===================================================================
1607RCS file: /sources/lwip/lwip/src/include/lwip/err.h,v
1608retrieving revision 1.13
1609retrieving revision 1.15
1610diff -u -p -r1.13 -r1.15
1611--- src/include/lwip/err.h	13 Dec 2007 23:06:50 -0000	1.13
1612+++ src/include/lwip/err.h	17 Jun 2008 20:27:32 -0000	1.15
1613@@ -33,37 +33,43 @@
1614 #define __LWIP_ERR_H__
1615
1616 #include "lwip/opt.h"
1617+#include "lwip/arch.h"
1618
1619 #ifdef __cplusplus
1620 extern "C" {
1621 #endif
1622
1623-typedef s8_t err_t;
1624+/** Define LWIP_ERR_T in cc.h if you want to use
1625+ *  a different type for your platform (must be signed). */
1626+#ifdef LWIP_ERR_T
1627+typedef LWIP_ERR_T err_t;
1628+#else /* LWIP_ERR_T */
1629+ typedef s8_t err_t;
1630+#endif /* LWIP_ERR_T*/
1631
1632 /* Definitions for error constants. */
1633
1634 #define ERR_OK          0    /* No error, everything OK. */
1635 #define ERR_MEM        -1    /* Out of memory error.     */
1636 #define ERR_BUF        -2    /* Buffer error.            */
1637-#define ERR_RTE        -3    /* Routing problem.         */
1638+#define ERR_TIMEOUT    -3    /* Timeout.                 */
1639+#define ERR_RTE        -4    /* Routing problem.         */
1640
1641 #define ERR_IS_FATAL(e) ((e) < ERR_RTE)
1642
1643-#define ERR_ABRT       -4    /* Connection aborted.      */
1644-#define ERR_RST        -5    /* Connection reset.        */
1645-#define ERR_CLSD       -6    /* Connection closed.       */
1646-#define ERR_CONN       -7    /* Not connected.           */
1647+#define ERR_ABRT       -5    /* Connection aborted.      */
1648+#define ERR_RST        -6    /* Connection reset.        */
1649+#define ERR_CLSD       -7    /* Connection closed.       */
1650+#define ERR_CONN       -8    /* Not connected.           */
1651
1652-#define ERR_VAL        -8    /* Illegal value.           */
1653+#define ERR_VAL        -9    /* Illegal value.           */
1654
1655-#define ERR_ARG        -9    /* Illegal argument.        */
1656+#define ERR_ARG        -10   /* Illegal argument.        */
1657
1658-#define ERR_USE        -10   /* Address in use.          */
1659+#define ERR_USE        -11   /* Address in use.          */
1660
1661-#define ERR_IF         -11   /* Low-level netif error    */
1662-#define ERR_ISCONN     -12   /* Already connected.       */
1663-
1664-#define ERR_TIMEOUT    -13   /* Timeout.                 */
1665+#define ERR_IF         -12   /* Low-level netif error    */
1666+#define ERR_ISCONN     -13   /* Already connected.       */
1667
1668 #define ERR_INPROGRESS -14   /* Operation in progress    */
1669
1670Index: src/include/lwip/mem.h
1671===================================================================
1672RCS file: /sources/lwip/lwip/src/include/lwip/mem.h,v
1673retrieving revision 1.21
1674retrieving revision 1.22
1675diff -u -p -r1.21 -r1.22
1676--- src/include/lwip/mem.h	4 Mar 2008 16:31:32 -0000	1.21
1677+++ src/include/lwip/mem.h	30 May 2008 11:37:15 -0000	1.22
1678@@ -50,16 +50,16 @@ typedef size_t mem_size_t;
1679  * allow these defines to be overridden.
1680  */
1681 #ifndef mem_free
1682-#define mem_free(x) free(x)
1683+#define mem_free free
1684 #endif
1685 #ifndef mem_malloc
1686-#define mem_malloc(x) malloc(x)
1687+#define mem_malloc malloc
1688 #endif
1689 #ifndef mem_calloc
1690-#define mem_calloc(x, y) calloc(x, y)
1691+#define mem_calloc calloc
1692 #endif
1693 #ifndef mem_realloc
1694-#define mem_realloc(x, size) (x)
1695+#define mem_realloc realloc
1696 #endif
1697 #else /* MEM_LIBC_MALLOC */
1698
1699Index: src/include/lwip/netif.h
1700===================================================================
1701RCS file: /sources/lwip/lwip/src/include/lwip/netif.h,v
1702retrieving revision 1.43
1703retrieving revision 1.46
1704diff -u -p -r1.43 -r1.46
1705--- src/include/lwip/netif.h	9 Oct 2007 19:59:59 -0000	1.43
1706+++ src/include/lwip/netif.h	19 Jun 2008 16:27:23 -0000	1.46
1707@@ -34,6 +34,8 @@
1708
1709 #include "lwip/opt.h"
1710
1711+#define ENABLE_LOOPBACK (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF)
1712+
1713 #include "lwip/err.h"
1714
1715 #include "lwip/ip_addr.h"
1716@@ -165,6 +167,14 @@ struct netif {
1717 #if LWIP_NETIF_HWADDRHINT
1718   u8_t *addr_hint;
1719 #endif /* LWIP_NETIF_HWADDRHINT */
1720+#if ENABLE_LOOPBACK
1721+  /* List of packets to be queued for ourselves. */
1722+  struct pbuf *loop_first;
1723+  struct pbuf *loop_last;
1724+#if LWIP_LOOPBACK_MAX_PBUFS
1725+  u16_t loop_cnt_current;
1726+#endif /* LWIP_LOOPBACK_MAX_PBUFS */
1727+#endif /* ENABLE_LOOPBACK */
1728 };
1729
1730 #if LWIP_SNMP
1731@@ -242,4 +252,12 @@ void netif_set_link_callback(struct neti
1732 }
1733 #endif
1734
1735+#if ENABLE_LOOPBACK
1736+err_t netif_loop_output(struct netif *netif, struct pbuf *p, struct ip_addr *dest_ip);
1737+void netif_poll(struct netif *netif);
1738+#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
1739+void netif_poll_all(void);
1740+#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
1741+#endif /* ENABLE_LOOPBACK */
1742+
1743 #endif /* __LWIP_NETIF_H__ */
1744Index: src/include/lwip/opt.h
1745===================================================================
1746RCS file: /sources/lwip/lwip/src/include/lwip/opt.h,v
1747retrieving revision 1.116
1748retrieving revision 1.122
1749diff -u -p -r1.116 -r1.122
1750--- src/include/lwip/opt.h	31 Jan 2008 18:19:29 -0000	1.116
1751+++ src/include/lwip/opt.h	30 Jun 2008 18:16:52 -0000	1.122
1752@@ -155,6 +155,27 @@
1753 #define MEMP_USE_CUSTOM_POOLS           0
1754 #endif
1755
1756+/**
1757+ * Set this to 1 if you want to free PBUF_RAM pbufs (or call mem_free()) from
1758+ * interrupt context (or another context that doesn't allow waiting for a
1759+ * semaphore).
1760+ * If set to 1, mem_malloc will be protected by a semaphore and SYS_ARCH_PROTECT,
1761+ * while mem_free will only use SYS_ARCH_PROTECT. mem_malloc SYS_ARCH_UNPROTECTs
1762+ * with each loop so that mem_free can run.
1763+ *
1764+ * ATTENTION: As you can see from the above description, this leads to dis-/
1765+ * enabling interrupts often, which can be slow! Also, on low memory, mem_malloc
1766+ * can need longer.
1767+ *
1768+ * If you don't want that, at least for NO_SYS=0, you can still use the following
1769+ * functions to enqueue a deallocation call which then runs in the tcpip_thread
1770+ * context:
1771+ * - pbuf_free_callback(p);
1772+ * - mem_free_callback(m);
1773+ */
1774+#ifndef LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
1775+#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 0
1776+#endif
1777
1778 /*
1779    ------------------------------------------------
1780@@ -815,6 +836,39 @@
1781 #define LWIP_NETIF_HWADDRHINT           0
1782 #endif
1783
1784+/**
1785+ * LWIP_NETIF_LOOPBACK==1: Support sending packets with a destination IP
1786+ * address equal to the netif IP address, looping them back up the stack.
1787+ */
1788+#ifndef LWIP_NETIF_LOOPBACK
1789+#define LWIP_NETIF_LOOPBACK             0
1790+#endif
1791+
1792+/**
1793+ * LWIP_LOOPBACK_MAX_PBUFS: Maximum number of pbufs on queue for loopback
1794+ * sending for each netif (0 = disabled)
1795+ */
1796+#ifndef LWIP_LOOPBACK_MAX_PBUFS
1797+#define LWIP_LOOPBACK_MAX_PBUFS         0
1798+#endif
1799+
1800+/**
1801+ * LWIP_NETIF_LOOPBACK_MULTITHREADING: Indicates whether threading is enabled in
1802+ * the system, as netifs must change how they behave depending on this setting
1803+ * for the LWIP_NETIF_LOOPBACK option to work.
1804+ * Setting this is needed to avoid reentering non-reentrant functions like
1805+ * tcp_input().
1806+ *    LWIP_NETIF_LOOPBACK_MULTITHREADING==1: Indicates that the user is using a
1807+ *       multithreaded environment like tcpip.c. In this case, netif->input()
1808+ *       is called directly.
1809+ *    LWIP_NETIF_LOOPBACK_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup.
1810+ *       The packets are put on a list and netif_poll() must be called in
1811+ *       the main application loop.
1812+ */
1813+#ifndef LWIP_NETIF_LOOPBACK_MULTITHREADING
1814+#define LWIP_NETIF_LOOPBACK_MULTITHREADING    (!NO_SYS)
1815+#endif
1816+
1817 /*
1818    ------------------------------------
1819    ---------- LOOPIF options ----------
1820@@ -827,20 +881,16 @@
1821 #define LWIP_HAVE_LOOPIF                0
1822 #endif
1823
1824+/*
1825+   ------------------------------------
1826+   ---------- SLIPIF options ----------
1827+   ------------------------------------
1828+*/
1829 /**
1830- * LWIP_LOOPIF_MULTITHREADING: Indicates whether threading is enabled in
1831- * the system, as LOOPIF must change how it behaves depending on this setting.
1832- * Setting this is needed to avoid reentering non-reentrant functions like
1833- * tcp_input().
1834- *    LWIP_LOOPIF_MULTITHREADING==1: Indicates that the user is using a
1835- *       multithreaded environment like tcpip.c. In this case, netif->input()
1836- *       is called directly.
1837- *    LWIP_LOOPIF_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup.
1838- *       The packets are put on a list and loopif_poll() must be called in
1839- *       the main application loop.
1840+ * LWIP_HAVE_SLIPIF==1: Support slip interface and slipif.c
1841  */
1842-#ifndef LWIP_LOOPIF_MULTITHREADING
1843-#define LWIP_LOOPIF_MULTITHREADING      1
1844+#ifndef LWIP_HAVE_SLIPIF
1845+#define LWIP_HAVE_SLIPIF                0
1846 #endif
1847
1848 /*
1849Index: src/include/lwip/sio.h
1850===================================================================
1851RCS file: /sources/lwip/lwip/src/include/lwip/sio.h,v
1852retrieving revision 1.7
1853retrieving revision 1.8
1854diff -u -p -r1.7 -r1.8
1855--- src/include/lwip/sio.h	6 Sep 2007 16:43:44 -0000	1.7
1856+++ src/include/lwip/sio.h	27 Mar 2008 18:06:02 -0000	1.8
1857@@ -32,16 +32,24 @@
1858  * It needs to be implemented by those platforms which need SLIP or PPP
1859  */
1860
1861+#ifndef __SIO_H__
1862+#define __SIO_H__
1863+
1864 #include "lwip/arch.h"
1865
1866 #ifdef __cplusplus
1867 extern "C" {
1868 #endif
1869
1870+/* If you want to define sio_fd_t elsewhere or differently,
1871+   define this in your cc.h file. */
1872 #ifndef __sio_fd_t_defined
1873 typedef void * sio_fd_t;
1874 #endif
1875
1876+/* The following functions can be defined to something else in your cc.h file
1877+   or be implemented in your custom sio.c file. */
1878+
1879 #ifndef sio_open
1880 sio_fd_t sio_open(u8_t);
1881 #endif
1882@@ -69,3 +77,5 @@ void sio_read_abort(sio_fd_t);
1883 #ifdef __cplusplus
1884 }
1885 #endif
1886+
1887+#endif /* __SIO_H__ */
1888Index: src/include/lwip/sockets.h
1889===================================================================
1890RCS file: /sources/lwip/lwip/src/include/lwip/sockets.h,v
1891retrieving revision 1.38
1892retrieving revision 1.39
1893diff -u -p -r1.38 -r1.39
1894--- src/include/lwip/sockets.h	2 Dec 2007 15:24:02 -0000	1.38
1895+++ src/include/lwip/sockets.h	26 Apr 2008 10:46:23 -0000	1.39
1896@@ -177,7 +177,22 @@ typedef struct ip_mreq {
1897 } ip_mreq;
1898 #endif /* LWIP_IGMP */
1899
1900-/* Unimplemented for now... */
1901+/*
1902+ * The Type of Service provides an indication of the abstract
1903+ * parameters of the quality of service desired.  These parameters are
1904+ * to be used to guide the selection of the actual service parameters
1905+ * when transmitting a datagram through a particular network.  Several
1906+ * networks offer service precedence, which somehow treats high
1907+ * precedence traffic as more important than other traffic (generally
1908+ * by accepting only traffic above a certain precedence at time of high
1909+ * load).  The major choice is a three way tradeoff between low-delay,
1910+ * high-reliability, and high-throughput.
1911+ * The use of the Delay, Throughput, and Reliability indications may
1912+ * increase the cost (in some sense) of the service.  In many networks
1913+ * better performance for one of these parameters is coupled with worse
1914+ * performance on another.  Except for very unusual cases at most two
1915+ * of these three indications should be set.
1916+ */
1917 #define IPTOS_TOS_MASK          0x1E
1918 #define IPTOS_TOS(tos)          ((tos) & IPTOS_TOS_MASK)
1919 #define IPTOS_LOWDELAY          0x10
1920@@ -187,7 +202,13 @@ typedef struct ip_mreq {
1921 #define IPTOS_MINCOST           IPTOS_LOWCOST
1922
1923 /*
1924- * Definitions for IP precedence (also in ip_tos) (Unimplemented)
1925+ * The Network Control precedence designation is intended to be used
1926+ * within a network only.  The actual use and control of that
1927+ * designation is up to each network. The Internetwork Control
1928+ * designation is intended for use by gateway control originators only.
1929+ * If the actual use of these precedence designations is of concern to
1930+ * a particular network, it is the responsibility of that network to
1931+ * control the access to, and use of, those precedence designations.
1932  */
1933 #define IPTOS_PREC_MASK                 0xe0
1934 #define IPTOS_PREC(tos)                ((tos) & IPTOS_PREC_MASK)
1935Index: src/include/lwip/stats.h
1936===================================================================
1937RCS file: /sources/lwip/lwip/src/include/lwip/stats.h,v
1938retrieving revision 1.19
1939retrieving revision 1.23
1940diff -u -p -r1.19 -r1.23
1941--- src/include/lwip/stats.h	28 Nov 2007 21:25:07 -0000	1.19
1942+++ src/include/lwip/stats.h	8 Jul 2008 09:15:57 -0000	1.23
1943@@ -57,7 +57,6 @@ extern "C" {
1944
1945 struct stats_proto {
1946   STAT_COUNTER xmit;             /* Transmitted packets. */
1947-  STAT_COUNTER rexmit;           /* Retransmitted packets. */
1948   STAT_COUNTER recv;             /* Received packets. */
1949   STAT_COUNTER fw;               /* Forwarded packets. */
1950   STAT_COUNTER drop;             /* Dropped packets. */
1951@@ -87,7 +86,8 @@ struct stats_mem {
1952   mem_size_t avail;
1953   mem_size_t used;
1954   mem_size_t max;
1955-  mem_size_t err;
1956+  STAT_COUNTER err;
1957+  STAT_COUNTER illegal;
1958 };
1959
1960 struct stats_syselem {
1961@@ -142,64 +142,138 @@ extern struct stats_ lwip_stats;
1962 #define stats_init() /* Compatibility define, not init needed. */
1963
1964 #define STATS_INC(x) ++lwip_stats.x
1965+#define STATS_DEC(x) --lwip_stats.x
1966 #else
1967 #define stats_init()
1968 #define STATS_INC(x)
1969+#define STATS_DEC(x)
1970 #endif /* LWIP_STATS */
1971
1972 #if TCP_STATS
1973 #define TCP_STATS_INC(x) STATS_INC(x)
1974+#define TCP_STATS_DISPLAY() stats_display_proto(&lwip_stats.tcp, "TCP")
1975 #else
1976 #define TCP_STATS_INC(x)
1977+#define TCP_STATS_DISPLAY()
1978 #endif
1979
1980 #if UDP_STATS
1981 #define UDP_STATS_INC(x) STATS_INC(x)
1982+#define UDP_STATS_DISPLAY() stats_display_proto(&lwip_stats.udp, "UDP")
1983 #else
1984 #define UDP_STATS_INC(x)
1985+#define UDP_STATS_DISPLAY()
1986 #endif
1987
1988 #if ICMP_STATS
1989 #define ICMP_STATS_INC(x) STATS_INC(x)
1990+#define ICMP_STATS_DISPLAY() stats_display_proto(&lwip_stats.icmp, "ICMP")
1991 #else
1992 #define ICMP_STATS_INC(x)
1993+#define ICMP_STATS_DISPLAY()
1994 #endif
1995
1996 #if IGMP_STATS
1997 #define IGMP_STATS_INC(x) STATS_INC(x)
1998+#define IGMP_STATS_DISPLAY() stats_display_igmp(&lwip_stats.igmp)
1999 #else
2000 #define IGMP_STATS_INC(x)
2001+#define IGMP_STATS_DISPLAY()
2002 #endif
2003
2004 #if IP_STATS
2005 #define IP_STATS_INC(x) STATS_INC(x)
2006+#define IP_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip, "IP")
2007 #else
2008 #define IP_STATS_INC(x)
2009+#define IP_STATS_DISPLAY()
2010 #endif
2011
2012 #if IPFRAG_STATS
2013 #define IPFRAG_STATS_INC(x) STATS_INC(x)
2014+#define IPFRAG_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip_frag, "IP_FRAG")
2015 #else
2016 #define IPFRAG_STATS_INC(x)
2017+#define IPFRAG_STATS_DISPLAY()
2018 #endif
2019
2020 #if ETHARP_STATS
2021 #define ETHARP_STATS_INC(x) STATS_INC(x)
2022+#define ETHARP_STATS_DISPLAY() stats_display_proto(&lwip_stats.etharp, "ETHARP")
2023 #else
2024 #define ETHARP_STATS_INC(x)
2025+#define ETHARP_STATS_DISPLAY()
2026 #endif
2027
2028 #if LINK_STATS
2029 #define LINK_STATS_INC(x) STATS_INC(x)
2030+#define LINK_STATS_DISPLAY() stats_display_proto(&lwip_stats.link, "LINK")
2031 #else
2032 #define LINK_STATS_INC(x)
2033+#define LINK_STATS_DISPLAY()
2034+#endif
2035+
2036+#if MEM_STATS
2037+#define MEM_STATS_AVAIL(x, y) lwip_stats.mem.x = y
2038+#define MEM_STATS_INC(x) STATS_INC(mem.x)
2039+#define MEM_STATS_INC_USED(x, y) do { lwip_stats.mem.used += y; \
2040+                                    if (lwip_stats.mem.max < lwip_stats.mem.used) { \
2041+                                        lwip_stats.mem.max = lwip_stats.mem.used; \
2042+                                    } \
2043+                                 } while(0)
2044+#define MEM_STATS_DEC_USED(x, y) lwip_stats.mem.x -= y
2045+#define MEM_STATS_DISPLAY() stats_display_mem(&lwip_stats.mem, "HEAP")
2046+#else
2047+#define MEM_STATS_AVAIL(x, y)
2048+#define MEM_STATS_INC(x)
2049+#define MEM_STATS_INC_USED(x, y)
2050+#define MEM_STATS_DEC_USED(x, y)
2051+#define MEM_STATS_DISPLAY()
2052+#endif
2053+
2054+#if MEMP_STATS
2055+#define MEMP_STATS_AVAIL(x, i, y) lwip_stats.memp[i].x = y
2056+#define MEMP_STATS_INC(x, i) STATS_INC(memp[i].x)
2057+#define MEMP_STATS_DEC(x, i) STATS_DEC(memp[i].x)
2058+#define MEMP_STATS_INC_USED(x, i) do { ++lwip_stats.memp[i].used; \
2059+                                    if (lwip_stats.memp[i].max < lwip_stats.memp[i].used) { \
2060+                                        lwip_stats.memp[i].max = lwip_stats.memp[i].used; \
2061+                                    } \
2062+                                 } while(0)
2063+#define MEMP_STATS_DISPLAY(i) stats_display_memp(&lwip_stats.memp[i], i)
2064+#else
2065+#define MEMP_STATS_AVAIL(x, i, y)
2066+#define MEMP_STATS_INC(x, i)
2067+#define MEMP_STATS_DEC(x, i)
2068+#define MEMP_STATS_INC_USED(x, i)
2069+#define MEMP_STATS_DISPLAY(i)
2070+#endif
2071+
2072+#if SYS_STATS
2073+#define SYS_STATS_INC(x) STATS_INC(sys.x)
2074+#define SYS_STATS_DEC(x) STATS_DEC(sys.x)
2075+#define SYS_STATS_DISPLAY() stats_display_sys(&lwip_stats.sys)
2076+#else
2077+#define SYS_STATS_INC(x)
2078+#define SYS_STATS_DEC(x)
2079+#define SYS_STATS_DISPLAY()
2080 #endif
2081
2082 /* Display of statistics */
2083 #if LWIP_STATS_DISPLAY
2084 void stats_display(void);
2085+void stats_display_proto(struct stats_proto *proto, char *name);
2086+void stats_display_igmp(struct stats_igmp *igmp);
2087+void stats_display_mem(struct stats_mem *mem, char *name);
2088+void stats_display_memp(struct stats_mem *mem, int index);
2089+void stats_display_sys(struct stats_sys *sys);
2090 #else
2091 #define stats_display()
2092+#define stats_display_proto(proto, name)
2093+#define stats_display_igmp(igmp)
2094+#define stats_display_mem(mem, name)
2095+#define stats_display_memp(mem, index)
2096+#define stats_display_sys(sys)
2097 #endif /* LWIP_STATS_DISPLAY */
2098
2099 #ifdef __cplusplus
2100Index: src/include/lwip/tcpip.h
2101===================================================================
2102RCS file: /sources/lwip/lwip/src/include/lwip/tcpip.h,v
2103retrieving revision 1.24
2104retrieving revision 1.27
2105diff -u -p -r1.24 -r1.27
2106--- src/include/lwip/tcpip.h	12 Jan 2008 11:52:22 -0000	1.24
2107+++ src/include/lwip/tcpip.h	27 Jun 2008 20:34:55 -0000	1.27
2108@@ -83,7 +83,11 @@ err_t tcpip_netifapi_lock(struct netifap
2109 #endif /* LWIP_NETIF_API */
2110
2111 err_t tcpip_callback_with_block(void (*f)(void *ctx), void *ctx, u8_t block);
2112-#define tcpip_callback(f,ctx) tcpip_callback_with_block(f,ctx,1)
2113+#define tcpip_callback(f, ctx)              tcpip_callback_with_block(f, ctx, 1)
2114+
2115+/* free pbufs or heap memory from another context without blocking */
2116+err_t pbuf_free_callback(struct pbuf *p);
2117+err_t mem_free_callback(void *m);
2118
2119 err_t tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg);
2120 #define tcpip_untimeout(h, arg) tcpip_timeout(0xffffffff, h, arg)
2121Index: src/include/netif/loopif.h
2122===================================================================
2123RCS file: /sources/lwip/lwip/src/include/netif/loopif.h,v
2124retrieving revision 1.7
2125retrieving revision 1.9
2126diff -u -p -r1.7 -r1.9
2127--- src/include/netif/loopif.h	10 May 2007 10:59:20 -0000	1.7
2128+++ src/include/netif/loopif.h	17 Jun 2008 20:12:22 -0000	1.9
2129@@ -32,6 +32,7 @@
2130 #ifndef __NETIF_LOOPIF_H__
2131 #define __NETIF_LOOPIF_H__
2132
2133+#include "lwip/opt.h"
2134 #include "lwip/netif.h"
2135 #include "lwip/err.h"
2136
2137@@ -39,9 +40,9 @@
2138 extern "C" {
2139 #endif
2140
2141-#if !LWIP_LOOPIF_MULTITHREADING
2142-void loopif_poll(struct netif *netif);
2143-#endif
2144+#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
2145+#define loopif_poll netif_poll
2146+#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
2147
2148 err_t loopif_init(struct netif *netif);
2149
2150Index: src/netif/etharp.c
2151===================================================================
2152RCS file: /sources/lwip/lwip/src/netif/etharp.c,v
2153retrieving revision 1.145
2154retrieving revision 1.148
2155diff -u -p -r1.145 -r1.148
2156--- src/netif/etharp.c	4 Mar 2008 13:41:24 -0000	1.145
2157+++ src/netif/etharp.c	19 Jun 2008 16:40:59 -0000	1.148
2158@@ -353,7 +353,7 @@ find_entry(struct ip_addr *ipaddr, u8_t
2159    * 1) empty entry
2160    * 2) oldest stable entry
2161    * 3) oldest pending entry without queued packets
2162-   * 4) oldest pending entry without queued packets
2163+   * 4) oldest pending entry with queued packets
2164    *
2165    * { ETHARP_TRY_HARD is set at this point }
2166    */
2167@@ -1130,7 +1130,14 @@ ethernet_input(struct pbuf *p, struct ne
2168
2169   /* points to packet payload, which starts with an Ethernet header */
2170   ethhdr = p->payload;
2171-
2172+  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE,
2173+    ("ethernet_input: dest:%02x:%02x:%02x:%02x:%02x:%02x, src:%02x:%02x:%02x:%02x:%02x:%02x, type:%2hx\n",
2174+     (unsigned)ethhdr->dest.addr[0], (unsigned)ethhdr->dest.addr[1], (unsigned)ethhdr->dest.addr[2],
2175+     (unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5],
2176+     (unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2],
2177+     (unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5],
2178+     (unsigned)htons(ethhdr->type)));
2179+
2180   switch (htons(ethhdr->type)) {
2181     /* IP packet? */
2182     case ETHTYPE_IP:
2183@@ -1165,6 +1172,8 @@ ethernet_input(struct pbuf *p, struct ne
2184 #endif /* PPPOE_SUPPORT */
2185
2186     default:
2187+      ETHARP_STATS_INC(etharp.proterr);
2188+      ETHARP_STATS_INC(etharp.drop);
2189       pbuf_free(p);
2190       p = NULL;
2191       break;
2192Index: src/netif/loopif.c
2193===================================================================
2194RCS file: /sources/lwip/lwip/src/netif/loopif.c,v
2195retrieving revision 1.26
2196retrieving revision 1.27
2197diff -u -p -r1.26 -r1.27
2198--- src/netif/loopif.c	31 Aug 2007 10:14:09 -0000	1.26
2199+++ src/netif/loopif.c	12 Jun 2008 20:10:10 -0000	1.27
2200@@ -40,149 +40,8 @@
2201 #if LWIP_HAVE_LOOPIF
2202
2203 #include "netif/loopif.h"
2204-#include "lwip/pbuf.h"
2205 #include "lwip/snmp.h"
2206
2207-#include <string.h>
2208-
2209-#if !LWIP_LOOPIF_MULTITHREADING
2210-
2211-#include "lwip/sys.h"
2212-#include "lwip/mem.h"
2213-
2214-/* helper struct for the linked list of pbufs */
2215-struct loopif_private {
2216-  struct pbuf *first;
2217-  struct pbuf *last;
2218-};
2219-
2220-/**
2221- * Call loopif_poll() in the main loop of your application. This is to prevent
2222- * reentering non-reentrant functions like tcp_input(). Packets passed to
2223- * loopif_output() are put on a list that is passed to netif->input() by
2224- * loopif_poll().
2225- *
2226- * @param netif the lwip network interface structure for this loopif
2227- */
2228-void
2229-loopif_poll(struct netif *netif)
2230-{
2231-  SYS_ARCH_DECL_PROTECT(lev);
2232-  struct pbuf *in, *in_end;
2233-  struct loopif_private *priv = (struct loopif_private*)netif->state;
2234-
2235-  LWIP_ERROR("priv != NULL", (priv != NULL), return;);
2236-
2237-  do {
2238-    /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */
2239-    SYS_ARCH_PROTECT(lev);
2240-    in = priv->first;
2241-    if(in) {
2242-      in_end = in;
2243-      while(in_end->len != in_end->tot_len) {
2244-        LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
2245-        in_end = in_end->next;
2246-      }
2247-      /* 'in_end' now points to the last pbuf from 'in' */
2248-      if(in_end == priv->last) {
2249-        /* this was the last pbuf in the list */
2250-        priv->first = priv->last = NULL;
2251-      } else {
2252-        /* pop the pbuf off the list */
2253-        priv->first = in_end->next;
2254-        LWIP_ASSERT("should not be null since first != last!", priv->first != NULL);
2255-      }
2256-    }
2257-    SYS_ARCH_UNPROTECT(lev);
2258-
2259-    if(in != NULL) {
2260-      if(in_end->next != NULL) {
2261-        /* De-queue the pbuf from its successors on the 'priv' list. */
2262-        in_end->next = NULL;
2263-      }
2264-      if(netif->input(in, netif) != ERR_OK) {
2265-        pbuf_free(in);
2266-      }
2267-      /* Don't reference the packet any more! */
2268-      in = NULL;
2269-      in_end = NULL;
2270-    }
2271-  /* go on while there is a packet on the list */
2272-  } while(priv->first != NULL);
2273-}
2274-#endif /* LWIP_LOOPIF_MULTITHREADING */
2275-
2276-/**
2277- * Send an IP packet over the loopback interface.
2278- * The pbuf is simply copied and handed back to netif->input.
2279- * In multithreaded mode, this is done directly since netif->input must put
2280- * the packet on a queue.
2281- * In callback mode, the packet is put on an internal queue and is fed to
2282- * netif->input by loopif_poll().
2283- *
2284- * @param netif the lwip network interface structure for this loopif
2285- * @param p the (IP) packet to 'send'
2286- * @param ipaddr the ip address to send the packet to (not used for loopif)
2287- * @return ERR_OK if the packet has been sent
2288- *         ERR_MEM if the pbuf used to copy the packet couldn't be allocated
2289- */
2290-static err_t
2291-loopif_output(struct netif *netif, struct pbuf *p,
2292-       struct ip_addr *ipaddr)
2293-{
2294-#if !LWIP_LOOPIF_MULTITHREADING
2295-  SYS_ARCH_DECL_PROTECT(lev);
2296-  struct loopif_private *priv;
2297-  struct pbuf *last;
2298-#endif /* LWIP_LOOPIF_MULTITHREADING */
2299-  struct pbuf *r;
2300-  err_t err;
2301-
2302-  LWIP_UNUSED_ARG(ipaddr);
2303-
2304-  /* Allocate a new pbuf */
2305-  r = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
2306-  if (r == NULL) {
2307-    return ERR_MEM;
2308-  }
2309-
2310-  /* Copy the whole pbuf queue p into the single pbuf r */
2311-  if ((err = pbuf_copy(r, p)) != ERR_OK) {
2312-    pbuf_free(r);
2313-    r = NULL;
2314-    return err;
2315-  }
2316-
2317-#if LWIP_LOOPIF_MULTITHREADING
2318-  /* Multithreading environment, netif->input() is supposed to put the packet
2319-     into a mailbox, so we can safely call it here without risking to re-enter
2320-     functions that are not reentrant (TCP!!!) */
2321-  if(netif->input(r, netif) != ERR_OK) {
2322-    pbuf_free(r);
2323-    r = NULL;
2324-  }
2325-#else /* LWIP_LOOPIF_MULTITHREADING */
2326-  /* Raw API without threads: put the packet on a linked list which gets emptied
2327-     through calling loopif_poll(). */
2328-  priv = (struct loopif_private*)netif->state;
2329-
2330-  /* let last point to the last pbuf in chain r */
2331-  for (last = r; last->next != NULL; last = last->next);
2332-  SYS_ARCH_PROTECT(lev);
2333-  if(priv->first != NULL) {
2334-    LWIP_ASSERT("if first != NULL, last must also be != NULL", priv->last != NULL);
2335-    priv->last->next = r;
2336-    priv->last = last;
2337-  } else {
2338-    priv->first = r;
2339-    priv->last = last;
2340-  }
2341-  SYS_ARCH_UNPROTECT(lev);
2342-#endif /* LWIP_LOOPIF_MULTITHREADING */
2343-
2344-  return ERR_OK;
2345-}
2346-
2347 /**
2348  * Initialize a lwip network interface structure for a loopback interface
2349  *
2350@@ -193,16 +52,6 @@ loopif_output(struct netif *netif, struc
2351 err_t
2352 loopif_init(struct netif *netif)
2353 {
2354-#if !LWIP_LOOPIF_MULTITHREADING
2355-  struct loopif_private *priv;
2356-
2357-  priv = (struct loopif_private*)mem_malloc(sizeof(struct loopif_private));
2358-  if(priv == NULL)
2359-    return ERR_MEM;
2360-  priv->first = priv->last = NULL;
2361-  netif->state = priv;
2362-#endif /* LWIP_LOOPIF_MULTITHREADING */
2363-
2364   /* initialize the snmp variables and counters inside the struct netif
2365    * ifSpeed: no assumption can be made!
2366    */
2367@@ -210,7 +59,7 @@ loopif_init(struct netif *netif)
2368
2369   netif->name[0] = 'l';
2370   netif->name[1] = 'o';
2371-  netif->output = loopif_output;
2372+  netif->output = netif_loop_output;
2373   return ERR_OK;
2374 }
2375
2376Index: src/netif/slipif.c
2377===================================================================
2378RCS file: /sources/lwip/lwip/src/netif/slipif.c,v
2379retrieving revision 1.29
2380retrieving revision 1.30
2381diff -u -p -r1.29 -r1.30
2382--- src/netif/slipif.c	30 Nov 2007 17:22:21 -0000	1.29
2383+++ src/netif/slipif.c	17 Jun 2008 20:14:05 -0000	1.30
2384@@ -44,6 +44,9 @@
2385
2386 #include "netif/slipif.h"
2387 #include "lwip/opt.h"
2388+
2389+#if LWIP_HAVE_SLIPIF
2390+
2391 #include "lwip/def.h"
2392 #include "lwip/pbuf.h"
2393 #include "lwip/sys.h"
2394@@ -273,3 +276,4 @@ slipif_init(struct netif *netif)
2395   sys_thread_new(SLIPIF_THREAD_NAME, slipif_loop, netif, SLIPIF_THREAD_STACKSIZE, SLIPIF_THREAD_PRIO);
2396   return ERR_OK;
2397 }
2398+#endif /* LWIP_HAVE_SLIPIF */
2399