WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH] stubdom: use the 1.3.0 release + patch instead of ch

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH] stubdom: use the 1.3.0 release + patch instead of checking out from cvs
From: Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>
Date: Thu, 17 Jul 2008 15:33:19 +0100
Cc:
Delivery-date: Thu, 17 Jul 2008 07:33:55 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Mail-followup-to: Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>, xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mutt/1.5.12-2006-07-14
stubdom: use the 1.3.0 release + patch instead of checking out from cvs

Signed-off-by: Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>

diff -r e4bf34e529fa stubdom/Makefile
--- a/stubdom/Makefile  Thu Jul 17 15:14:14 2008 +0100
+++ b/stubdom/Makefile  Thu Jul 17 15:29:41 2008 +0100
@@ -14,7 +14,7 @@
 ZLIB_VERSION=1.2.3
 LIBPCI_VERSION=2.2.9
 NEWLIB_VERSION=1.16.0
-LWIP_DATE=2008-06-01
+LWIP_VERSION=1.3.0
 GRUB_VERSION=0.97
 
 WGET=wget -c
@@ -55,8 +55,8 @@
 TARGET_CPPFLAGS += -isystem $(CURDIR)/$(MINI_OS)/include/posix
 TARGET_CPPFLAGS += -isystem $(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/include
 TARGET_CPPFLAGS += -isystem $(GCC_INSTALL)include
-TARGET_CPPFLAGS += -isystem $(CURDIR)/lwip-cvs/src/include
-TARGET_CPPFLAGS += -isystem $(CURDIR)/lwip-cvs/src/include/ipv4
+TARGET_CPPFLAGS += -isystem $(CURDIR)/lwip/src/include
+TARGET_CPPFLAGS += -isystem $(CURDIR)/lwip/src/include/ipv4
 TARGET_CPPFLAGS += -I$(CURDIR)/include
 
 TARGET_LDFLAGS += -nostdlib -L$(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/lib
@@ -140,8 +140,13 @@
 # lwIP
 ######
 
-lwip-cvs:
-       cvs -z 9 -d :pserver:anonymous@xxxxxxxxxxxxxxxxxxxxxxx:/sources/lwip co 
-D $(LWIP_DATE) -d $@ lwip
+lwip-$(LWIP_VERSION).tar.gz:
+       $(WGET) http://download.savannah.gnu.org/releases/lwip/$@
+
+lwip: lwip-$(LWIP_VERSION).tar.gz
+       tar xzf $<
+       patch -d $@ -p0 < lwip.patch-cvs
+       touch $@
 
 #######
 # Links
@@ -214,12 +219,12 @@
        [ -f ioemu/config-host.mak ] || \
          ( cd ioemu ; \
           XEN_TARGET_ARCH=$(XEN_TARGET_ARCH) CFLAGS="$(TARGET_CFLAGS)" sh 
configure --prefix=/usr --enable-stubdom $(IOEMU_OPTIONS))
-       CPPFLAGS="$(TARGET_CPPFLAGS)" $(MAKE) -C ioemu 
LWIPDIR=$(CURDIR)/lwip-cvs TOOLS=
+       CPPFLAGS="$(TARGET_CPPFLAGS)" $(MAKE) -C ioemu LWIPDIR=$(CURDIR)/lwip 
TOOLS=
 else
        [ -f ioemu/config-host.mak ] || \
          ( cd ioemu ; \
           CONFIG_STUBDOM=yes XEN_ROOT=$(abspath $(XEN_ROOT)) 
XEN_TARGET_ARCH=$(XEN_TARGET_ARCH) CFLAGS="$(TARGET_CFLAGS)" sh ./xen-setup 
--cc=$(CC) --disable-gcc-check $(IOEMU_OPTIONS))
-       CPPFLAGS= TARGET_CPPFLAGS="$(TARGET_CPPFLAGS)" $(MAKE) -C ioemu 
LWIPDIR=$(CURDIR)/lwip-cvs TOOLS= CONFIG_STUBDOM=yes
+       CPPFLAGS= TARGET_CPPFLAGS="$(TARGET_CPPFLAGS)" $(MAKE) -C ioemu 
LWIPDIR=$(CURDIR)/lwip TOOLS= CONFIG_STUBDOM=yes
 endif
 
 ######
@@ -228,7 +233,7 @@
 
 .PHONY: caml
 caml: cross-newlib mk-headers
-       CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) -C $@ 
LWIPDIR=$(CURDIR)/lwip-cvs 
+       CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) -C $@ 
LWIPDIR=$(CURDIR)/lwip 
 
 ###
 # C
@@ -236,7 +241,7 @@
 
 .PHONY: c
 c: cross-newlib mk-headers
-       CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) -C $@ 
LWIPDIR=$(CURDIR)/lwip-cvs 
+       CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) -C $@ 
LWIPDIR=$(CURDIR)/lwip 
 
 ######
 # Grub
@@ -266,17 +271,17 @@
 else
 ioemu-stubdom: APP_OBJS=$(CURDIR)/ioemu/i386-stubdom/qemu.a 
$(CURDIR)/ioemu/i386-stubdom/libqemu.a $(CURDIR)/ioemu/libqemu_common.a
 endif
-ioemu-stubdom: mini-os-ioemu lwip-cvs libxc ioemu
-       DEF_CPPFLAGS="$(TARGET_CPPFLAGS)" DEF_CFLAGS="-DCONFIG_QEMU 
$(TARGET_CFLAGS)" DEF_LDFLAGS="$(TARGET_LDFLAGS)" $(MAKE) -C $(MINI_OS) 
OBJ_DIR=$(CURDIR)/$< LWIPDIR=$(CURDIR)/lwip-cvs APP_OBJS="$(APP_OBJS)"
+ioemu-stubdom: mini-os-ioemu lwip libxc ioemu
+       DEF_CPPFLAGS="$(TARGET_CPPFLAGS)" DEF_CFLAGS="-DCONFIG_QEMU 
$(TARGET_CFLAGS)" DEF_LDFLAGS="$(TARGET_LDFLAGS)" $(MAKE) -C $(MINI_OS) 
OBJ_DIR=$(CURDIR)/$< LWIPDIR=$(CURDIR)/lwip APP_OBJS="$(APP_OBJS)"
 
 CAMLLIB = $(shell ocamlc -where)
 .PHONY: caml-stubdom
-caml-stubdom: mini-os-caml lwip-cvs libxc caml
-       DEF_CPPFLAGS="$(TARGET_CPPFLAGS)" DEF_CFLAGS="-DCONFIG_CAML 
$(TARGET_CFLAGS)" DEF_LDFLAGS="$(TARGET_LDFLAGS)" $(MAKE) -C $(MINI_OS) 
OBJ_DIR=$(CURDIR)/$< LWIPDIR=$(CURDIR)/lwip-cvs 
APP_OBJS="$(CURDIR)/caml/main-caml.o $(CURDIR)/caml/caml.o 
$(CAMLLIB)/libasmrun.a"
+caml-stubdom: mini-os-caml lwip libxc caml
+       DEF_CPPFLAGS="$(TARGET_CPPFLAGS)" DEF_CFLAGS="-DCONFIG_CAML 
$(TARGET_CFLAGS)" DEF_LDFLAGS="$(TARGET_LDFLAGS)" $(MAKE) -C $(MINI_OS) 
OBJ_DIR=$(CURDIR)/$< LWIPDIR=$(CURDIR)/lwip 
APP_OBJS="$(CURDIR)/caml/main-caml.o $(CURDIR)/caml/caml.o 
$(CAMLLIB)/libasmrun.a"
 
 .PHONY: c-stubdom
-c-stubdom: mini-os-c lwip-cvs libxc c
-       DEF_CPPFLAGS="$(TARGET_CPPFLAGS)" DEF_CFLAGS="-DCONFIG_C 
$(TARGET_CFLAGS)" DEF_LDFLAGS="$(TARGET_LDFLAGS)" $(MAKE) -C $(MINI_OS) 
OBJ_DIR=$(CURDIR)/$< LWIPDIR=$(CURDIR)/lwip-cvs APP_OBJS=$(CURDIR)/c/main.a
+c-stubdom: mini-os-c lwip libxc c
+       DEF_CPPFLAGS="$(TARGET_CPPFLAGS)" DEF_CFLAGS="-DCONFIG_C 
$(TARGET_CFLAGS)" DEF_LDFLAGS="$(TARGET_LDFLAGS)" $(MAKE) -C $(MINI_OS) 
OBJ_DIR=$(CURDIR)/$< LWIPDIR=$(CURDIR)/lwip APP_OBJS=$(CURDIR)/c/main.a
 
 .PHONY: pv-grub
 pv-grub: mini-os-grub libxc grub
@@ -329,7 +334,7 @@
 .PHONY: patchclean
 patchclean: crossclean
        rm -fr newlib-$(NEWLIB_VERSION)
-       rm -fr lwip-cvs
+       rm -fr lwip
        rm -fr grub-upstream
 
 # clean downloads
@@ -338,6 +343,8 @@
        rm -f newlib-$(NEWLIB_VERSION).tar.gz
        rm -f zlib-$(ZLIB_VERSION).tar.gz
        rm -f pciutils-$(LIBPCI_VERSION).tar.bz2
+       rm -f grub-$(GRUB_VERSION).tar.gz
+       rm -f lwip-$(LWIP_VERSION).tar.gz
 
 .PHONY: distclean
 distclean: downloadclean
diff -r e4bf34e529fa stubdom/lwip.patch-cvs
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/lwip.patch-cvs    Thu Jul 17 15:29:41 2008 +0100
@@ -0,0 +1,2398 @@
+? .ChangeLog.swp
+? ChangeLog
+Index: CHANGELOG
+===================================================================
+RCS file: /sources/lwip/lwip/CHANGELOG,v
+retrieving revision 1.300
+retrieving revision 1.318
+diff -u -p -r1.300 -r1.318
+--- CHANGELOG  23 Mar 2008 13:49:39 -0000      1.300
++++ CHANGELOG  14 Jul 2008 20:12:36 -0000      1.318
+@@ -19,9 +19,77 @@ HISTORY
+ 
+   ++ New features:
+ 
++  2008-06-30 Simon Goldschmidt
++  * mem.c, opt.h, stats.h: fixed bug #21433: Calling mem_free/pbuf_free from
++    interrupt context isn't safe: LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 
allows
++    mem_free to run between mem_malloc iterations. Added illegal counter for
++    mem stats.
++
++  2008-06-27 Simon Goldschmidt
++  * stats.h/.c, some other files: patch #6483: stats module improvement:
++    Added defines to display each module's statistic individually, added stats
++    defines for MEM, MEMP and SYS modules, removed (unused) rexmit counter.
++
++  2008-06-17 Simon Goldschmidt
++  * err.h: patch #6459: Made err_t overridable to use a more efficient type
++    (define LWIP_ERR_T in cc.h)
++
++  2008-06-17 Simon Goldschmidt
++  * slipif.c: patch #6480: Added a configuration option for slipif for 
symmetry
++    to loopif
++
++  2008-06-17 Simon Goldschmidt (patch by Luca Ceresoli)
++  * netif.c, loopif.c, ip.c, netif.h, loopif.h, opt.h: Checked in slightly
++    modified version of patch # 6370: Moved loopif code to netif.c so that
++    loopback traffic is supported on all netifs (all local IPs).
++    Added option to limit loopback packets for each netifs.
++
+ 
+   ++ Bugfixes:
+ 
++  2008-08-14 Simon Goldschmidt
++  * api_msg.c: fixed bug #23847: do_close_internal references freed memory 
(when
++    tcp_close returns != ERR_OK)
++
++  2008-07-08 Frédéric Bernon
++  * stats.h: Fix some build bugs introduced with patch #6483 (missing some 
parameters
++    in macros, mainly if MEM_STATS=0 and MEMP_STATS=0).
++
++  2008-06-24 Jonathan Larmour
++  * tcp_in.c: Fix for bug #23693 as suggested by Art R. Ensure cseg is unused
++    if tcp_seg_copy fails.
++
++  2008-06-17 Simon Goldschmidt
++  * inet_chksum.c: Checked in some ideas of patch #6460 (loop optimizations)
++    and created defines for swapping bytes and folding u32 to u16.
++
++  2008-05-30 Kieran Mansley
++  * tcp_in.c Remove redundant "if" statement, and use real rcv_wnd
++    rather than rcv_ann_wnd when deciding if packets are in-window.
++    Contributed by <arasmussen@xxxxxxxxxxxxxxxxxxxxxxxxxxx>
++
++  2008-05-30 Kieran Mansley
++  * mem.h: Fix BUG#23254.  Change macro definition of mem_* to allow
++    passing as function pointers when MEM_LIBC_MALLOC is defined.
++
++  2008-05-09 Jonathan Larmour
++  * err.h, err.c, sockets.c: Fix bug #23119: Reorder timeout error code to
++    stop it being treated as a fatal error.
++
++  2008-04-15 Simon Goldschmidt
++  * dhcp.c: fixed bug #22804: dhcp_stop doesn't clear NETIF_FLAG_DHCP
++    (flag now cleared)
++
++  2008-03-27 Simon Goldschmidt
++  * mem.c, tcpip.c, tcpip.h, opt.h: fixed bug #21433 (Calling 
mem_free/pbuf_free
++    from interrupt context isn't safe): set LWIP_USE_HEAP_FROM_INTERRUPT to 1
++    in lwipopts.h or use pbuf_free_callback(p)/mem_free_callback(m) to free 
pbufs
++    or heap memory from interrupt context
++
++  2008-03-26 Simon Goldschmidt
++  * tcp_in.c, tcp.c: fixed bug #22249: division by zero could occur if a 
remote
++    host sent a zero mss as TCP option.
++
+ 
+ (STABLE-1.3.0)
+ 
+Index: src/api/api_msg.c
+===================================================================
+RCS file: /sources/lwip/lwip/src/api/api_msg.c,v
+retrieving revision 1.102
+retrieving revision 1.104
+diff -u -p -r1.102 -r1.104
+--- src/api/api_msg.c  21 Mar 2008 16:23:14 -0000      1.102
++++ src/api/api_msg.c  15 Jul 2008 11:18:58 -0000      1.104
+@@ -598,11 +598,16 @@ do_close_internal(struct netconn *conn)
+   LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL));
+ 
+   /* Set back some callback pointers */
++  tcp_arg(conn->pcb.tcp, NULL);
+   if (conn->pcb.tcp->state == LISTEN) {
+-    tcp_arg(conn->pcb.tcp, NULL);
+     tcp_accept(conn->pcb.tcp, NULL);
+   } else {
+     tcp_recv(conn->pcb.tcp, NULL);
++    tcp_accept(conn->pcb.tcp, NULL);
++    /* some callbacks have to be reset if tcp_close is not successful */
++    tcp_sent(conn->pcb.tcp, NULL);
++    tcp_poll(conn->pcb.tcp, NULL, 4);
++    tcp_err(conn->pcb.tcp, NULL);
+   }
+   /* Try to close the connection */
+   err = tcp_close(conn->pcb.tcp);
+@@ -610,11 +615,6 @@ do_close_internal(struct netconn *conn)
+     /* Closing succeeded */
+     conn->state = NETCONN_NONE;
+     /* Set back some callback pointers as conn is going away */
+-    tcp_err(conn->pcb.tcp, NULL);
+-    tcp_poll(conn->pcb.tcp, NULL, 4);
+-    tcp_sent(conn->pcb.tcp, NULL);
+-    tcp_recv(conn->pcb.tcp, NULL);
+-    tcp_arg(conn->pcb.tcp, NULL);
+     conn->pcb.tcp = NULL;
+     conn->err = ERR_OK;
+     /* Trigger select() in socket layer. This send should something else so 
the
+@@ -623,6 +623,14 @@ do_close_internal(struct netconn *conn)
+     API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
+     /* wake up the application task */
+     sys_sem_signal(conn->op_completed);
++  } else {
++    /* Closing failed, restore some of the callbacks */
++    /* Closing of listen pcb will never fail! */
++    LWIP_ASSERT("Closing a listen pcb may not fail!", (conn->pcb.tcp->state 
!= LISTEN));
++    tcp_sent(conn->pcb.tcp, sent_tcp);
++    tcp_poll(conn->pcb.tcp, poll_tcp, 4);
++    tcp_err(conn->pcb.tcp, err_tcp);
++    tcp_arg(conn->pcb.tcp, conn);
+   }
+   /* If closing didn't succeed, we get called again either
+      from poll_tcp or from sent_tcp */
+Index: src/api/err.c
+===================================================================
+RCS file: /sources/lwip/lwip/src/api/err.c,v
+retrieving revision 1.11
+retrieving revision 1.12
+diff -u -p -r1.11 -r1.12
+--- src/api/err.c      13 Dec 2007 23:06:50 -0000      1.11
++++ src/api/err.c      9 May 2008 12:14:23 -0000       1.12
+@@ -44,17 +44,17 @@ static const char *err_strerr[] = {
+            "Ok.",                    /* ERR_OK          0  */
+            "Out of memory error.",   /* ERR_MEM        -1  */
+            "Buffer error.",          /* ERR_BUF        -2  */
+-           "Routing problem.",       /* ERR_RTE        -3  */
+-           "Connection aborted.",    /* ERR_ABRT       -4  */
+-           "Connection reset.",      /* ERR_RST        -5  */
+-           "Connection closed.",     /* ERR_CLSD       -6  */
+-           "Not connected.",         /* ERR_CONN       -7  */
+-           "Illegal value.",         /* ERR_VAL        -8  */
+-           "Illegal argument.",      /* ERR_ARG        -9  */
+-           "Address in use.",        /* ERR_USE        -10 */
+-           "Low-level netif error.", /* ERR_IF         -11 */
+-           "Already connected.",     /* ERR_ISCONN     -12 */
+-           "Timeout.",               /* ERR_TIMEOUT    -13 */
++           "Timeout.",               /* ERR_TIMEOUT    -3 */
++           "Routing problem.",       /* ERR_RTE        -4  */
++           "Connection aborted.",    /* ERR_ABRT       -5  */
++           "Connection reset.",      /* ERR_RST        -6  */
++           "Connection closed.",     /* ERR_CLSD       -7  */
++           "Not connected.",         /* ERR_CONN       -8  */
++           "Illegal value.",         /* ERR_VAL        -9  */
++           "Illegal argument.",      /* ERR_ARG        -10 */
++           "Address in use.",        /* ERR_USE        -11 */
++           "Low-level netif error.", /* ERR_IF         -12 */
++           "Already connected.",     /* ERR_ISCONN     -13 */
+            "Operation in progress."  /* ERR_INPROGRESS -14 */
+ };
+ 
+Index: src/api/netdb.c
+===================================================================
+RCS file: /sources/lwip/lwip/src/api/netdb.c,v
+retrieving revision 1.4
+retrieving revision 1.5
+diff -u -p -r1.4 -r1.5
+--- src/api/netdb.c    26 Jan 2008 16:11:39 -0000      1.4
++++ src/api/netdb.c    16 Jul 2008 20:36:12 -0000      1.5
+@@ -326,7 +326,8 @@ lwip_getaddrinfo(const char *nodename, c
+   if (nodename != NULL) {
+     /* copy nodename to canonname if specified */
+     size_t namelen = strlen(nodename);
+-    ai->ai_canonname = mem_malloc(namelen + 1);
++    LWIP_ASSERT("namelen is too long", (namelen + 1) <= (mem_size_t)-1);
++    ai->ai_canonname = mem_malloc((mem_size_t)(namelen + 1));
+     if (ai->ai_canonname == NULL) {
+       goto memerr;
+     }
+Index: src/api/sockets.c
+===================================================================
+RCS file: /sources/lwip/lwip/src/api/sockets.c,v
+retrieving revision 1.116
+retrieving revision 1.117
+diff -u -p -r1.116 -r1.117
+--- src/api/sockets.c  13 Mar 2008 20:03:57 -0000      1.116
++++ src/api/sockets.c  9 May 2008 12:14:24 -0000       1.117
+@@ -128,17 +128,17 @@ static const int err_to_errno_table[] = 
+   0,             /* ERR_OK          0      No error, everything OK. */
+   ENOMEM,        /* ERR_MEM        -1      Out of memory error.     */
+   ENOBUFS,       /* ERR_BUF        -2      Buffer error.            */
+-  EHOSTUNREACH,  /* ERR_RTE        -3      Routing problem.         */
+-  ECONNABORTED,  /* ERR_ABRT       -4      Connection aborted.      */
+-  ECONNRESET,    /* ERR_RST        -5      Connection reset.        */
+-  ESHUTDOWN,     /* ERR_CLSD       -6      Connection closed.       */
+-  ENOTCONN,      /* ERR_CONN       -7      Not connected.           */
+-  EINVAL,        /* ERR_VAL        -8      Illegal value.           */
+-  EIO,           /* ERR_ARG        -9      Illegal argument.        */
+-  EADDRINUSE,    /* ERR_USE        -10     Address in use.          */
+-  -1,            /* ERR_IF         -11     Low-level netif error    */
+-  -1,            /* ERR_ISCONN     -12     Already connected.       */
+-  ETIMEDOUT,     /* ERR_TIMEOUT    -13     Timeout                  */
++  ETIMEDOUT,     /* ERR_TIMEOUT    -3      Timeout                  */
++  EHOSTUNREACH,  /* ERR_RTE        -4      Routing problem.         */
++  ECONNABORTED,  /* ERR_ABRT       -5      Connection aborted.      */
++  ECONNRESET,    /* ERR_RST        -6      Connection reset.        */
++  ESHUTDOWN,     /* ERR_CLSD       -7      Connection closed.       */
++  ENOTCONN,      /* ERR_CONN       -8      Not connected.           */
++  EINVAL,        /* ERR_VAL        -9      Illegal value.           */
++  EIO,           /* ERR_ARG        -10     Illegal argument.        */
++  EADDRINUSE,    /* ERR_USE        -11     Address in use.          */
++  -1,            /* ERR_IF         -12     Low-level netif error    */
++  -1,            /* ERR_ISCONN     -13     Already connected.       */
+   EINPROGRESS    /* ERR_INPROGRESS -14     Operation in progress    */
+ };
+ 
+Index: src/api/tcpip.c
+===================================================================
+RCS file: /sources/lwip/lwip/src/api/tcpip.c,v
+retrieving revision 1.70
+retrieving revision 1.73
+diff -u -p -r1.70 -r1.73
+--- src/api/tcpip.c    12 Jan 2008 11:52:22 -0000      1.70
++++ src/api/tcpip.c    27 Jun 2008 20:34:51 -0000      1.73
+@@ -518,4 +518,42 @@ tcpip_init(void (* initfunc)(void *), vo
+   sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, 
TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
+ }
+ 
++/**
++ * Simple callback function used with tcpip_callback to free a pbuf
++ * (pbuf_free has a wrong signature for tcpip_callback)
++ *
++ * @param p The pbuf (chain) to be dereferenced.
++ */
++static void
++pbuf_free_int(void *p)
++{
++  struct pbuf *q = p;
++  pbuf_free(q);
++}
++
++/**
++ * A simple wrapper function that allows you to free a pbuf from interrupt 
context.
++ *
++ * @param p The pbuf (chain) to be dereferenced.
++ * @return ERR_OK if callback could be enqueued, an err_t if not
++ */
++err_t
++pbuf_free_callback(struct pbuf *p)
++{
++  return tcpip_callback_with_block(pbuf_free_int, p, 0);
++}
++
++/**
++ * A simple wrapper function that allows you to free heap memory from
++ * interrupt context.
++ *
++ * @param m the heap memory to free
++ * @return ERR_OK if callback could be enqueued, an err_t if not
++ */
++err_t
++mem_free_callback(void *m)
++{
++  return tcpip_callback_with_block(mem_free, m, 0);
++}
++
+ #endif /* !NO_SYS */
+Index: src/core/dhcp.c
+===================================================================
+RCS file: /sources/lwip/lwip/src/core/dhcp.c,v
+retrieving revision 1.86
+retrieving revision 1.87
+diff -u -p -r1.86 -r1.87
+--- src/core/dhcp.c    4 Mar 2008 14:25:58 -0000       1.86
++++ src/core/dhcp.c    15 Apr 2008 17:24:55 -0000      1.87
+@@ -568,6 +568,8 @@ dhcp_start(struct netif *netif)
+   LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;);
+   dhcp = netif->dhcp;
+   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));
++  /* Remove the flag that says this netif is handled by DHCP,
++     it is set when we succeeded starting. */
+   netif->flags &= ~NETIF_FLAG_DHCP;
+ 
+   /* no DHCP client attached yet? */
+@@ -609,6 +611,7 @@ dhcp_start(struct netif *netif)
+     dhcp_stop(netif);
+     return ERR_MEM;
+   }
++  /* Set the flag that says this netif is handled by DHCP. */
+   netif->flags |= NETIF_FLAG_DHCP;
+   return result;
+ }
+@@ -1063,6 +1066,8 @@ dhcp_stop(struct netif *netif)
+ {
+   struct dhcp *dhcp = netif->dhcp;
+   LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return;);
++  /* Remove the flag that says this netif is handled by DHCP. */
++  netif->flags &= ~NETIF_FLAG_DHCP;
+ 
+   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_stop()\n"));
+   /* netif is DHCP configured? */
+Index: src/core/mem.c
+===================================================================
+RCS file: /sources/lwip/lwip/src/core/mem.c,v
+retrieving revision 1.59
+retrieving revision 1.62
+diff -u -p -r1.59 -r1.62
+--- src/core/mem.c     4 Mar 2008 16:31:32 -0000       1.59
++++ src/core/mem.c     30 Jun 2008 18:16:51 -0000      1.62
+@@ -177,9 +177,36 @@ static u8_t *ram;
+ static struct mem *ram_end;
+ /** pointer to the lowest free block, this is used for faster search */
+ static struct mem *lfree;
++
+ /** concurrent access protection */
+ static sys_sem_t mem_sem;
+ 
++#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
++
++static volatile u8_t mem_free_count;
++
++/* Allow mem_free from other (e.g. interrupt) context */
++#define LWIP_MEM_FREE_DECL_PROTECT()  SYS_ARCH_DECL_PROTECT(lev_free)
++#define LWIP_MEM_FREE_PROTECT()       SYS_ARCH_PROTECT(lev_free)
++#define LWIP_MEM_FREE_UNPROTECT()     SYS_ARCH_UNPROTECT(lev_free)
++#define LWIP_MEM_ALLOC_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_alloc)
++#define LWIP_MEM_ALLOC_PROTECT()      SYS_ARCH_PROTECT(lev_alloc)
++#define LWIP_MEM_ALLOC_UNPROTECT()    SYS_ARCH_UNPROTECT(lev_alloc)
++
++#else /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
++
++/* Protect the heap only by using a semaphore */
++#define LWIP_MEM_FREE_DECL_PROTECT()
++#define LWIP_MEM_FREE_PROTECT()    sys_arch_sem_wait(mem_sem, 0)
++#define LWIP_MEM_FREE_UNPROTECT()  sys_sem_signal(mem_sem)
++/* mem_malloc is protected using semaphore AND LWIP_MEM_ALLOC_PROTECT */
++#define LWIP_MEM_ALLOC_DECL_PROTECT()
++#define LWIP_MEM_ALLOC_PROTECT()
++#define LWIP_MEM_ALLOC_UNPROTECT()
++
++#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
++
++
+ /**
+  * "Plug holes" by combining adjacent empty struct mems.
+  * After this function is through, there should not exist
+@@ -255,9 +282,7 @@ mem_init(void)
+   /* initialize the lowest-free pointer to the start of the heap */
+   lfree = (struct mem *)ram;
+ 
+-#if MEM_STATS
+-  lwip_stats.mem.avail = MEM_SIZE_ALIGNED;
+-#endif /* MEM_STATS */
++  MEM_STATS_AVAIL(avail, MEM_SIZE_ALIGNED);
+ }
+ 
+ /**
+@@ -270,6 +295,7 @@ void
+ mem_free(void *rmem)
+ {
+   struct mem *mem;
++  LWIP_MEM_FREE_DECL_PROTECT();
+ 
+   if (rmem == NULL) {
+     LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | 2, ("mem_free(p == NULL) was 
called.\n"));
+@@ -277,20 +303,20 @@ mem_free(void *rmem)
+   }
+   LWIP_ASSERT("mem_free: sanity check alignment", (((mem_ptr_t)rmem) & 
(MEM_ALIGNMENT-1)) == 0);
+ 
+-  /* protect the heap from concurrent access */
+-  sys_arch_sem_wait(mem_sem, 0);
+-
+   LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
+     (u8_t *)rmem < (u8_t *)ram_end);
+ 
+   if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
++    SYS_ARCH_DECL_PROTECT(lev);
+     LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_free: illegal memory\n"));
+-#if MEM_STATS
+-    ++lwip_stats.mem.err;
+-#endif /* MEM_STATS */
+-    sys_sem_signal(mem_sem);
++    /* protect mem stats from concurrent access */
++    SYS_ARCH_PROTECT(lev);
++    MEM_STATS_INC(illegal);
++    SYS_ARCH_UNPROTECT(lev);
+     return;
+   }
++  /* protect the heap from concurrent access */
++  LWIP_MEM_FREE_PROTECT();
+   /* Get the corresponding struct mem ... */
+   mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
+   /* ... which has to be in a used state ... */
+@@ -303,13 +329,14 @@ mem_free(void *rmem)
+     lfree = mem;
+   }
+ 
+-#if MEM_STATS
+-  lwip_stats.mem.used -= mem->next - ((u8_t *)mem - ram);
+-#endif /* MEM_STATS */
++  MEM_STATS_DEC_USED(used, mem->next - ((u8_t *)mem - ram));
+ 
+   /* finally, see if prev or next are free also */
+   plug_holes(mem);
+-  sys_sem_signal(mem_sem);
++#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
++  mem_free_count = 1;
++#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
++  LWIP_MEM_FREE_UNPROTECT();
+ }
+ 
+ /**
+@@ -321,6 +348,8 @@ mem_free(void *rmem)
+  * @param newsize required size after shrinking (needs to be smaller than or
+  *                equal to the previous size)
+  * @return for compatibility reasons: is always == rmem, at the moment
++ *         or NULL if newsize is > old size, in which case rmem is NOT touched
++ *         or freed!
+  */
+ void *
+ mem_realloc(void *rmem, mem_size_t newsize)
+@@ -328,6 +357,8 @@ mem_realloc(void *rmem, mem_size_t newsi
+   mem_size_t size;
+   mem_size_t ptr, ptr2;
+   struct mem *mem, *mem2;
++  /* use the FREE_PROTECT here: it protects with sem OR SYS_ARCH_PROTECT */
++  LWIP_MEM_FREE_DECL_PROTECT();
+ 
+   /* Expand the size of the allocated memory region so that we can
+      adjust for alignment. */
+@@ -346,7 +377,12 @@ mem_realloc(void *rmem, mem_size_t newsi
+    (u8_t *)rmem < (u8_t *)ram_end);
+ 
+   if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
++    SYS_ARCH_DECL_PROTECT(lev);
+     LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_realloc: illegal memory\n"));
++    /* protect mem stats from concurrent access */
++    SYS_ARCH_PROTECT(lev);
++    MEM_STATS_INC(illegal);
++    SYS_ARCH_UNPROTECT(lev);
+     return rmem;
+   }
+   /* Get the corresponding struct mem ... */
+@@ -366,11 +402,9 @@ mem_realloc(void *rmem, mem_size_t newsi
+   }
+ 
+   /* protect the heap from concurrent access */
+-  sys_arch_sem_wait(mem_sem, 0);
++  LWIP_MEM_FREE_PROTECT();
+ 
+-#if MEM_STATS
+-  lwip_stats.mem.used -= (size - newsize);
+-#endif /* MEM_STATS */
++  MEM_STATS_DEC_USED(used, (size - newsize));
+ 
+   mem2 = (struct mem *)&ram[mem->next];
+   if(mem2->used == 0) {
+@@ -426,7 +460,10 @@ mem_realloc(void *rmem, mem_size_t newsi
+     -> don't do anyhting. 
+     -> the remaining space stays unused since it is too small
+   } */
+-  sys_sem_signal(mem_sem);
++#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
++  mem_free_count = 1;
++#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
++  LWIP_MEM_FREE_UNPROTECT();
+   return rmem;
+ }
+ 
+@@ -444,6 +481,10 @@ mem_malloc(mem_size_t size)
+ {
+   mem_size_t ptr, ptr2;
+   struct mem *mem, *mem2;
++#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
++  u8_t local_mem_free_count = 0;
++#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
++  LWIP_MEM_ALLOC_DECL_PROTECT();
+ 
+   if (size == 0) {
+     return NULL;
+@@ -464,88 +505,101 @@ mem_malloc(mem_size_t size)
+ 
+   /* protect the heap from concurrent access */
+   sys_arch_sem_wait(mem_sem, 0);
++  LWIP_MEM_ALLOC_PROTECT();
++#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
++  /* run as long as a mem_free disturbed mem_malloc */
++  do {
++    local_mem_free_count = 0;
++#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
++
++    /* Scan through the heap searching for a free block that is big enough,
++     * beginning with the lowest free block.
++     */
++    for (ptr = (u8_t *)lfree - ram; ptr < MEM_SIZE_ALIGNED - size;
++         ptr = ((struct mem *)&ram[ptr])->next) {
++      mem = (struct mem *)&ram[ptr];
++#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
++      mem_free_count = 0;
++      LWIP_MEM_ALLOC_UNPROTECT();
++      /* allow mem_free to run */
++      LWIP_MEM_ALLOC_PROTECT();
++      if (mem_free_count != 0) {
++        local_mem_free_count = mem_free_count;
++      }
++      mem_free_count = 0;
++#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
+ 
+-  /* Scan through the heap searching for a free block that is big enough,
+-   * beginning with the lowest free block.
+-   */
+-  for (ptr = (u8_t *)lfree - ram; ptr < MEM_SIZE_ALIGNED - size;
+-       ptr = ((struct mem *)&ram[ptr])->next) {
+-    mem = (struct mem *)&ram[ptr];
+-
+-    if ((!mem->used) &&
+-        (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) {
+-      /* mem is not used and at least perfect fit is possible:
+-       * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' 
of mem */
+-
+-      if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM 
+ MIN_SIZE_ALIGNED)) {
+-        /* (in addition to the above, we test if another struct mem 
(SIZEOF_STRUCT_MEM) containing
+-         * at least MIN_SIZE_ALIGNED of data also fits in the 'user data 
space' of 'mem')
+-         * -> split large block, create empty remainder,
+-         * remainder must be large enough to contain MIN_SIZE_ALIGNED data: if
+-         * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size,
+-         * struct mem would fit in but no data between mem2 and mem2->next
+-         * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty
+-         *       region that couldn't hold data, but when mem->next gets 
freed,
+-         *       the 2 regions would be combined, resulting in more free 
memory
+-         */
+-        ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
+-        /* create mem2 struct */
+-        mem2 = (struct mem *)&ram[ptr2];
+-        mem2->used = 0;
+-        mem2->next = mem->next;
+-        mem2->prev = ptr;
+-        /* and insert it between mem and mem->next */
+-        mem->next = ptr2;
+-        mem->used = 1;
+-
+-        if (mem2->next != MEM_SIZE_ALIGNED) {
+-          ((struct mem *)&ram[mem2->next])->prev = ptr2;
+-        }
+-#if MEM_STATS
+-        lwip_stats.mem.used += (size + SIZEOF_STRUCT_MEM);
+-        if (lwip_stats.mem.max < lwip_stats.mem.used) {
+-          lwip_stats.mem.max = lwip_stats.mem.used;
++      if ((!mem->used) &&
++          (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) {
++        /* mem is not used and at least perfect fit is possible:
++         * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data 
size' of mem */
++
++        if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + 
SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) {
++          /* (in addition to the above, we test if another struct mem 
(SIZEOF_STRUCT_MEM) containing
++           * at least MIN_SIZE_ALIGNED of data also fits in the 'user data 
space' of 'mem')
++           * -> split large block, create empty remainder,
++           * remainder must be large enough to contain MIN_SIZE_ALIGNED data: 
if
++           * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size,
++           * struct mem would fit in but no data between mem2 and mem2->next
++           * @todo we could leave out MIN_SIZE_ALIGNED. We would create an 
empty
++           *       region that couldn't hold data, but when mem->next gets 
freed,
++           *       the 2 regions would be combined, resulting in more free 
memory
++           */
++          ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
++          /* create mem2 struct */
++          mem2 = (struct mem *)&ram[ptr2];
++          mem2->used = 0;
++          mem2->next = mem->next;
++          mem2->prev = ptr;
++          /* and insert it between mem and mem->next */
++          mem->next = ptr2;
++          mem->used = 1;
++
++          if (mem2->next != MEM_SIZE_ALIGNED) {
++            ((struct mem *)&ram[mem2->next])->prev = ptr2;
++          }
++          MEM_STATS_INC_USED(used, (size + SIZEOF_STRUCT_MEM));
++        } else {
++          /* (a mem2 struct does no fit into the user data space of mem and 
mem->next will always
++           * be used at this point: if not we have 2 unused structs in a row, 
plug_holes should have
++           * take care of this).
++           * -> near fit or excact fit: do not split, no mem2 creation
++           * also can't move mem->next directly behind mem, since mem->next
++           * will always be used at this point!
++           */
++          mem->used = 1;
++          MEM_STATS_INC_USED(used, mem->next - ((u8_t *)mem - ram));
+         }
+-#endif /* MEM_STATS */
+-      } else {
+-        /* (a mem2 struct does no fit into the user data space of mem and 
mem->next will always
+-         * be used at this point: if not we have 2 unused structs in a row, 
plug_holes should have
+-         * take care of this).
+-         * -> near fit or excact fit: do not split, no mem2 creation
+-         * also can't move mem->next directly behind mem, since mem->next
+-         * will always be used at this point!
+-         */
+-        mem->used = 1;
+-#if MEM_STATS
+-        lwip_stats.mem.used += mem->next - ((u8_t *)mem - ram);
+-        if (lwip_stats.mem.max < lwip_stats.mem.used) {
+-          lwip_stats.mem.max = lwip_stats.mem.used;
+-        }
+-#endif /* MEM_STATS */
+-      }
+ 
+-      if (mem == lfree) {
+-        /* Find next free block after mem and update lowest free pointer */
+-        while (lfree->used && lfree != ram_end) {
+-          lfree = (struct mem *)&ram[lfree->next];
++        if (mem == lfree) {
++          /* Find next free block after mem and update lowest free pointer */
++          while (lfree->used && lfree != ram_end) {
++            LWIP_MEM_ALLOC_UNPROTECT();
++            /* prevent high interrupt latency... */
++            LWIP_MEM_ALLOC_PROTECT();
++            lfree = (struct mem *)&ram[lfree->next];
++          }
++          LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || 
(!lfree->used)));
+         }
+-        LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || 
(!lfree->used)));
+-      }
+-      sys_sem_signal(mem_sem);
+-      LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
+-       (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);
+-      LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
+-       (unsigned long)((u8_t *)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
+-      LWIP_ASSERT("mem_malloc: sanity check alignment",
+-        (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0);
++        LWIP_MEM_ALLOC_UNPROTECT();
++        sys_sem_signal(mem_sem);
++        LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
++         (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);
++        LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
++         (unsigned long)((u8_t *)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 
0);
++        LWIP_ASSERT("mem_malloc: sanity check alignment",
++          (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0);
+ 
+-      return (u8_t *)mem + SIZEOF_STRUCT_MEM;
++        return (u8_t *)mem + SIZEOF_STRUCT_MEM;
++      }
+     }
+-  }
++#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
++    /* if we got interrupted by a mem_free, try again */
++  } while(local_mem_free_count != 0);
++#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
+   LWIP_DEBUGF(MEM_DEBUG | 2, ("mem_malloc: could not allocate %"S16_F" 
bytes\n", (s16_t)size));
+-#if MEM_STATS
+-  ++lwip_stats.mem.err;
+-#endif /* MEM_STATS */
++  MEM_STATS_INC(err);
++  LWIP_MEM_ALLOC_UNPROTECT();
+   sys_sem_signal(mem_sem);
+   return NULL;
+ }
+Index: src/core/memp.c
+===================================================================
+RCS file: /sources/lwip/lwip/src/core/memp.c,v
+retrieving revision 1.55
+retrieving revision 1.56
+diff -u -p -r1.55 -r1.56
+--- src/core/memp.c    25 Nov 2007 10:43:28 -0000      1.55
++++ src/core/memp.c    27 Jun 2008 18:37:54 -0000      1.56
+@@ -252,13 +252,12 @@ memp_init(void)
+   struct memp *memp;
+   u16_t i, j;
+ 
+-#if MEMP_STATS
+   for (i = 0; i < MEMP_MAX; ++i) {
+-    lwip_stats.memp[i].used = lwip_stats.memp[i].max =
+-      lwip_stats.memp[i].err = 0;
+-    lwip_stats.memp[i].avail = memp_num[i];
++    MEMP_STATS_AVAIL(used, i, 0);
++    MEMP_STATS_AVAIL(max, i, 0);
++    MEMP_STATS_AVAIL(err, i, 0);
++    MEMP_STATS_AVAIL(avail, i, memp_num[i]);
+   }
+-#endif /* MEMP_STATS */
+ 
+   memp = LWIP_MEM_ALIGN(memp_memory);
+   /* for every pool: */
+@@ -315,20 +314,13 @@ memp_malloc_fn(memp_t type, const char* 
+     memp->file = file;
+     memp->line = line;
+ #endif /* MEMP_OVERFLOW_CHECK */
+-#if MEMP_STATS
+-    ++lwip_stats.memp[type].used;
+-    if (lwip_stats.memp[type].used > lwip_stats.memp[type].max) {
+-      lwip_stats.memp[type].max = lwip_stats.memp[type].used;
+-    }
+-#endif /* MEMP_STATS */
++    MEMP_STATS_INC_USED(used, type);
+     LWIP_ASSERT("memp_malloc: memp properly aligned",
+                 ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0);
+     memp = (struct memp*)((u8_t*)memp + MEMP_SIZE);
+   } else {
+     LWIP_DEBUGF(MEMP_DEBUG | 2, ("memp_malloc: out of memory in pool %s\n", 
memp_desc[type]));
+-#if MEMP_STATS
+-    ++lwip_stats.memp[type].err;
+-#endif /* MEMP_STATS */
++    MEMP_STATS_INC(err, type);
+   }
+ 
+   SYS_ARCH_UNPROTECT(old_level);
+@@ -365,9 +357,7 @@ memp_free(memp_t type, void *mem)
+ #endif /* MEMP_OVERFLOW_CHECK >= 2 */
+ #endif /* MEMP_OVERFLOW_CHECK */
+ 
+-#if MEMP_STATS
+-  lwip_stats.memp[type].used--; 
+-#endif /* MEMP_STATS */
++  MEMP_STATS_DEC(used, type); 
+   
+   memp->next = memp_tab[type]; 
+   memp_tab[type] = memp;
+Index: src/core/netif.c
+===================================================================
+RCS file: /sources/lwip/lwip/src/core/netif.c,v
+retrieving revision 1.65
+retrieving revision 1.68
+diff -u -p -r1.65 -r1.68
+--- src/core/netif.c   9 Oct 2007 20:00:55 -0000       1.65
++++ src/core/netif.c   19 Jun 2008 16:27:18 -0000      1.68
+@@ -45,6 +45,12 @@
+ #include "lwip/snmp.h"
+ #include "lwip/igmp.h"
+ #include "netif/etharp.h"
++#if ENABLE_LOOPBACK
++#include "lwip/sys.h"
++#if LWIP_NETIF_LOOPBACK_MULTITHREADING
++#include "lwip/tcpip.h"
++#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
++#endif /* ENABLE_LOOPBACK */
+ 
+ #if LWIP_NETIF_STATUS_CALLBACK
+ #define NETIF_STATUS_CALLBACK(n) { if (n->status_callback) 
(n->status_callback)(n); }
+@@ -106,6 +112,10 @@ netif_add(struct netif *netif, struct ip
+ #if LWIP_IGMP
+   netif->igmp_mac_filter = NULL;
+ #endif /* LWIP_IGMP */
++#if ENABLE_LOOPBACK
++  netif->loop_first = NULL;
++  netif->loop_last = NULL;
++#endif /* ENABLE_LOOPBACK */
+ 
+   /* remember netif specific state information data */
+   netif->state = state;
+@@ -114,6 +124,9 @@ netif_add(struct netif *netif, struct ip
+ #if LWIP_NETIF_HWADDRHINT
+   netif->addr_hint = NULL;
+ #endif /* LWIP_NETIF_HWADDRHINT*/
++#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS
++  netif->loop_cnt_current = 0;
++#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */
+ 
+   netif_set_addr(netif, ipaddr, netmask, gw);
+ 
+@@ -493,7 +506,158 @@ u8_t netif_is_link_up(struct netif *neti
+  */
+ void netif_set_link_callback(struct netif *netif, void (* 
link_callback)(struct netif *netif ))
+ {
+-    if ( netif )
+-        netif->link_callback = link_callback;
++  if (netif) {
++    netif->link_callback = link_callback;
++  }
+ }
+ #endif /* LWIP_NETIF_LINK_CALLBACK */
++
++#if ENABLE_LOOPBACK
++/**
++ * Send an IP packet to be received on the same netif (loopif-like).
++ * The pbuf is simply copied and handed back to netif->input.
++ * In multithreaded mode, this is done directly since netif->input must put
++ * the packet on a queue.
++ * In callback mode, the packet is put on an internal queue and is fed to
++ * netif->input by netif_poll().
++ *
++ * @param netif the lwip network interface structure
++ * @param p the (IP) packet to 'send'
++ * @param ipaddr the ip address to send the packet to (not used)
++ * @return ERR_OK if the packet has been sent
++ *         ERR_MEM if the pbuf used to copy the packet couldn't be allocated
++ */
++err_t
++netif_loop_output(struct netif *netif, struct pbuf *p,
++       struct ip_addr *ipaddr)
++{
++  struct pbuf *r;
++  err_t err;
++  struct pbuf *last;
++#if LWIP_LOOPBACK_MAX_PBUFS
++  u8_t clen = 0;
++#endif /* LWIP_LOOPBACK_MAX_PBUFS */
++  SYS_ARCH_DECL_PROTECT(lev);
++  LWIP_UNUSED_ARG(ipaddr);
++
++  /* Allocate a new pbuf */
++  r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM);
++  if (r == NULL) {
++    return ERR_MEM;
++  }
++#if LWIP_LOOPBACK_MAX_PBUFS
++  clen = pbuf_clen(r);
++  /* check for overflow or too many pbuf on queue */
++  if(((netif->loop_cnt_current + clen) < netif->loop_cnt_current) ||
++    ((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) {
++      pbuf_free(r);
++      r = NULL;
++      return ERR_MEM;
++  }
++  netif->loop_cnt_current += clen;
++#endif /* LWIP_LOOPBACK_MAX_PBUFS */
++
++  /* Copy the whole pbuf queue p into the single pbuf r */
++  if ((err = pbuf_copy(r, p)) != ERR_OK) {
++    pbuf_free(r);
++    r = NULL;
++    return err;
++  }
++
++  /* Put the packet on a linked list which gets emptied through calling
++     netif_poll(). */
++
++  /* let last point to the last pbuf in chain r */
++  for (last = r; last->next != NULL; last = last->next);
++
++  SYS_ARCH_PROTECT(lev);
++  if(netif->loop_first != NULL) {
++    LWIP_ASSERT("if first != NULL, last must also be != NULL", 
netif->loop_last != NULL);
++    netif->loop_last->next = r;
++    netif->loop_last = last;
++  } else {
++    netif->loop_first = r;
++    netif->loop_last = last;
++  }
++  SYS_ARCH_UNPROTECT(lev);
++
++#if LWIP_NETIF_LOOPBACK_MULTITHREADING
++  /* For multithreading environment, schedule a call to netif_poll */
++  tcpip_callback(netif_poll, netif);
++#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
++
++  return ERR_OK;
++}
++
++/**
++ * Call netif_poll() in the main loop of your application. This is to prevent
++ * reentering non-reentrant functions like tcp_input(). Packets passed to
++ * netif_loop_output() are put on a list that is passed to netif->input() by
++ * netif_poll().
++ */
++void
++netif_poll(struct netif *netif)
++{
++  struct pbuf *in;
++  SYS_ARCH_DECL_PROTECT(lev);
++
++  do {
++    /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is 
protected */
++    SYS_ARCH_PROTECT(lev);
++    in = netif->loop_first;
++    if(in != NULL) {
++      struct pbuf *in_end = in;
++#if LWIP_LOOPBACK_MAX_PBUFS
++      u8_t clen = pbuf_clen(in);
++      /* adjust the number of pbufs on queue */
++      LWIP_ASSERT("netif->loop_cnt_current underflow",
++        ((netif->loop_cnt_current - clen) < netif->loop_cnt_current));
++      netif->loop_cnt_current -= clen;
++#endif /* LWIP_LOOPBACK_MAX_PBUFS */
++      while(in_end->len != in_end->tot_len) {
++        LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", 
in_end->next != NULL);
++        in_end = in_end->next;
++      }
++      /* 'in_end' now points to the last pbuf from 'in' */
++      if(in_end == netif->loop_last) {
++        /* this was the last pbuf in the list */
++        netif->loop_first = netif->loop_last = NULL;
++      } else {
++        /* pop the pbuf off the list */
++        netif->loop_first = in_end->next;
++        LWIP_ASSERT("should not be null since first != last!", 
netif->loop_first != NULL);
++      }
++      /* De-queue the pbuf from its successors on the 'loop_' list. */
++      in_end->next = NULL;
++    }
++    SYS_ARCH_UNPROTECT(lev);
++
++    if(in != NULL) {
++      /* loopback packets are always IP packets! */
++      if(ip_input(in, netif) != ERR_OK) {
++        pbuf_free(in);
++      }
++      /* Don't reference the packet any more! */
++      in = NULL;
++    }
++  /* go on while there is a packet on the list */
++  } while(netif->loop_first != NULL);
++}
++
++#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
++/**
++ * Calls netif_poll() for every netif on the netif_list.
++ */
++void
++netif_poll_all(void)
++{
++  struct netif *netif = netif_list;
++  /* loop through netifs */
++  while (netif != NULL) {
++    netif_poll(netif);
++    /* proceed to next network interface */
++    netif = netif->next;
++  }
++}
++#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
++#endif /* ENABLE_LOOPBACK */
+Index: src/core/pbuf.c
+===================================================================
+RCS file: /sources/lwip/lwip/src/core/pbuf.c,v
+retrieving revision 1.127
+retrieving revision 1.128
+diff -u -p -r1.127 -r1.128
+--- src/core/pbuf.c    4 Mar 2008 16:37:46 -0000       1.127
++++ src/core/pbuf.c    1 Apr 2008 19:05:40 -0000       1.128
+@@ -667,8 +667,8 @@ pbuf_dechain(struct pbuf *p)
+  *
+  * @note Only one packet is copied, no packet queue!
+  *
+- * @param p_to pbuf source of the copy
+- * @param p_from pbuf destination of the copy
++ * @param p_to pbuf destination of the copy
++ * @param p_from pbuf source of the copy
+  *
+  * @return ERR_OK if pbuf was copied
+  *         ERR_ARG if one of the pbufs is NULL or p_to is not big
+Index: src/core/stats.c
+===================================================================
+RCS file: /sources/lwip/lwip/src/core/stats.c,v
+retrieving revision 1.27
+retrieving revision 1.28
+diff -u -p -r1.27 -r1.28
+--- src/core/stats.c   4 Mar 2008 16:31:32 -0000       1.27
++++ src/core/stats.c   27 Jun 2008 18:37:54 -0000      1.28
+@@ -54,7 +54,6 @@ stats_display_proto(struct stats_proto *
+ {
+   LWIP_PLATFORM_DIAG(("\n%s\n\t", name));
+   LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", proto->xmit)); 
+-  LWIP_PLATFORM_DIAG(("rexmit: %"STAT_COUNTER_F"\n\t", proto->rexmit)); 
+   LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", proto->recv)); 
+   LWIP_PLATFORM_DIAG(("fw: %"STAT_COUNTER_F"\n\t", proto->fw)); 
+   LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", proto->drop)); 
+@@ -68,6 +67,7 @@ stats_display_proto(struct stats_proto *
+   LWIP_PLATFORM_DIAG(("cachehit: %"STAT_COUNTER_F"\n", proto->cachehit)); 
+ }
+ 
++#if IGMP_STATS
+ void
+ stats_display_igmp(struct stats_igmp *igmp)
+ {
+@@ -82,7 +82,9 @@ stats_display_igmp(struct stats_igmp *ig
+   LWIP_PLATFORM_DIAG(("report_rxed: %"STAT_COUNTER_F"\n\t", 
igmp->report_rxed)); 
+   LWIP_PLATFORM_DIAG(("group_query_rxed: %"STAT_COUNTER_F"\n", 
igmp->group_query_rxed));
+ }
++#endif /* IGMP_STATS */
+ 
++#if MEM_STATS || MEMP_STATS
+ void
+ stats_display_mem(struct stats_mem *mem, char *name)
+ {
+@@ -93,48 +95,53 @@ stats_display_mem(struct stats_mem *mem,
+   LWIP_PLATFORM_DIAG(("err: %"U32_F"\n", (u32_t)mem->err));
+ }
+ 
++#if MEMP_STATS
+ void
+-stats_display(void)
++stats_display_memp(struct stats_mem *mem, int index)
+ {
+-#if MEMP_STATS
+-  s16_t i;
+   char * memp_names[] = {
+ #define LWIP_MEMPOOL(name,num,size,desc) desc,
+ #include "lwip/memp_std.h"
+   };
+-#endif
+-#if LINK_STATS
+-  stats_display_proto(&lwip_stats.link, "LINK");
+-#endif
+-#if ETHARP_STATS
+-  stats_display_proto(&lwip_stats.etharp, "ETHARP");
+-#endif
+-#if IPFRAG_STATS
+-  stats_display_proto(&lwip_stats.ip_frag, "IP_FRAG");
+-#endif
+-#if IP_STATS
+-  stats_display_proto(&lwip_stats.ip, "IP");
+-#endif
+-#if ICMP_STATS
+-  stats_display_proto(&lwip_stats.icmp, "ICMP");
+-#endif
+-#if IGMP_STATS
+-  stats_display_igmp(&lwip_stats.igmp);
+-#endif
+-#if UDP_STATS
+-  stats_display_proto(&lwip_stats.udp, "UDP");
+-#endif
+-#if TCP_STATS
+-  stats_display_proto(&lwip_stats.tcp, "TCP");
+-#endif
+-#if MEM_STATS
+-  stats_display_mem(&lwip_stats.mem, "HEAP");
+-#endif
+-#if MEMP_STATS
++  if(index < MEMP_MAX) {
++    stats_display_mem(mem, memp_names[index]);
++  }
++}
++#endif /* MEMP_STATS */
++#endif /* MEM_STATS || MEMP_STATS */
++
++#if SYS_STATS
++void
++stats_display_sys(struct stats_sys *sys)
++{
++  LWIP_PLATFORM_DIAG(("\nSYS\n\t"));
++  LWIP_PLATFORM_DIAG(("sem.used: %"U32_F"\n\t", (u32_t)sys->sem.used)); 
++  LWIP_PLATFORM_DIAG(("sem.max:  %"U32_F"\n\t", (u32_t)sys->sem.max)); 
++  LWIP_PLATFORM_DIAG(("sem.err:  %"U32_F"\n\t", (u32_t)sys->sem.err)); 
++  LWIP_PLATFORM_DIAG(("mbox.used: %"U32_F"\n\t", (u32_t)sys->mbox.used)); 
++  LWIP_PLATFORM_DIAG(("mbox.max:  %"U32_F"\n\t", (u32_t)sys->mbox.max)); 
++  LWIP_PLATFORM_DIAG(("mbox.err:  %"U32_F"\n\t", (u32_t)sys->mbox.err)); 
++}
++#endif /* SYS_STATS */
++
++void
++stats_display(void)
++{
++  s16_t i;
++
++  LINK_STATS_DISPLAY();
++  ETHARP_STATS_DISPLAY();
++  IPFRAG_STATS_DISPLAY();
++  IP_STATS_DISPLAY();
++  IGMP_STATS_DISPLAY();
++  ICMP_STATS_DISPLAY();
++  UDP_STATS_DISPLAY();
++  TCP_STATS_DISPLAY();
++  MEM_STATS_DISPLAY();
+   for (i = 0; i < MEMP_MAX; i++) {
+-    stats_display_mem(&lwip_stats.memp[i], memp_names[i]);
++    MEMP_STATS_DISPLAY(i);
+   }
+-#endif
++  SYS_STATS_DISPLAY();
+ }
+ #endif /* LWIP_STATS_DISPLAY */
+ 
+Index: src/core/sys.c
+===================================================================
+RCS file: /sources/lwip/lwip/src/core/sys.c,v
+retrieving revision 1.32
+retrieving revision 1.33
+diff -u -p -r1.32 -r1.33
+--- src/core/sys.c     25 Nov 2007 13:57:05 -0000      1.32
++++ src/core/sys.c     16 Jul 2008 20:36:12 -0000      1.33
+@@ -65,7 +65,7 @@ struct sswt_cb
+ void
+ sys_mbox_fetch(sys_mbox_t mbox, void **msg)
+ {
+-  u32_t time;
++  u32_t time_needed;
+   struct sys_timeouts *timeouts;
+   struct sys_timeo *tmptimeout;
+   sys_timeout_handler h;
+@@ -76,18 +76,18 @@ sys_mbox_fetch(sys_mbox_t mbox, void **m
+ 
+   if (!timeouts || !timeouts->next) {
+     UNLOCK_TCPIP_CORE();
+-    time = sys_arch_mbox_fetch(mbox, msg, 0);
++    time_needed = sys_arch_mbox_fetch(mbox, msg, 0);
+     LOCK_TCPIP_CORE();
+   } else {
+     if (timeouts->next->time > 0) {
+       UNLOCK_TCPIP_CORE();
+-      time = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time);
++      time_needed = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time);
+       LOCK_TCPIP_CORE();
+     } else {
+-      time = SYS_ARCH_TIMEOUT;
++      time_needed = SYS_ARCH_TIMEOUT;
+     }
+ 
+-    if (time == SYS_ARCH_TIMEOUT) {
++    if (time_needed == SYS_ARCH_TIMEOUT) {
+       /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
+          could be fetched. We should now call the timeout handler and
+          deallocate the memory allocated for the timeout. */
+@@ -107,8 +107,8 @@ sys_mbox_fetch(sys_mbox_t mbox, void **m
+       /* If time != SYS_ARCH_TIMEOUT, a message was received before the 
timeout
+          occured. The time variable is set to the number of
+          milliseconds we waited for the message. */
+-      if (time < timeouts->next->time) {
+-        timeouts->next->time -= time;
++      if (time_needed < timeouts->next->time) {
++        timeouts->next->time -= time_needed;
+       } else {
+         timeouts->next->time = 0;
+       }
+@@ -125,7 +125,7 @@ sys_mbox_fetch(sys_mbox_t mbox, void **m
+ void
+ sys_sem_wait(sys_sem_t sem)
+ {
+-  u32_t time;
++  u32_t time_needed;
+   struct sys_timeouts *timeouts;
+   struct sys_timeo *tmptimeout;
+   sys_timeout_handler h;
+@@ -139,12 +139,12 @@ sys_sem_wait(sys_sem_t sem)
+     sys_arch_sem_wait(sem, 0);
+   } else {
+     if (timeouts->next->time > 0) {
+-      time = sys_arch_sem_wait(sem, timeouts->next->time);
++      time_needed = sys_arch_sem_wait(sem, timeouts->next->time);
+     } else {
+-      time = SYS_ARCH_TIMEOUT;
++      time_needed = SYS_ARCH_TIMEOUT;
+     }
+ 
+-    if (time == SYS_ARCH_TIMEOUT) {
++    if (time_needed == SYS_ARCH_TIMEOUT) {
+       /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
+         could be fetched. We should now call the timeout handler and
+         deallocate the memory allocated for the timeout. */
+@@ -164,8 +164,8 @@ sys_sem_wait(sys_sem_t sem)
+       /* If time != SYS_ARCH_TIMEOUT, a message was received before the 
timeout
+          occured. The time variable is set to the number of
+          milliseconds we waited for the message. */
+-      if (time < timeouts->next->time) {
+-        timeouts->next->time -= time;
++      if (time_needed < timeouts->next->time) {
++        timeouts->next->time -= time_needed;
+       } else {
+         timeouts->next->time = 0;
+       }
+Index: src/core/tcp.c
+===================================================================
+RCS file: /sources/lwip/lwip/src/core/tcp.c,v
+retrieving revision 1.85
+retrieving revision 1.86
+diff -u -p -r1.85 -r1.86
+--- src/core/tcp.c     22 Jan 2008 21:15:15 -0000      1.85
++++ src/core/tcp.c     26 Mar 2008 11:57:13 -0000      1.86
+@@ -509,7 +509,8 @@ tcp_connect(struct tcp_pcb *pcb, struct 
+   pcb->rcv_wnd = TCP_WND;
+   pcb->rcv_ann_wnd = TCP_WND;
+   pcb->snd_wnd = TCP_WND;
+-  /* The send MSS is updated when an MSS option is received. */
++  /* As initial send MSS, we use TCP_MSS but limit it to 536.
++     The send MSS is updated when an MSS option is received. */
+   pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;
+ #if TCP_CALCULATE_EFF_SEND_MSS
+   pcb->mss = tcp_eff_send_mss(pcb->mss, ipaddr);
+@@ -991,7 +992,8 @@ tcp_alloc(u8_t prio)
+     pcb->rcv_ann_wnd = TCP_WND;
+     pcb->tos = 0;
+     pcb->ttl = TCP_TTL;
+-    /* The send MSS is updated when an MSS option is received. */
++    /* As initial send MSS, we use TCP_MSS but limit it to 536.
++       The send MSS is updated when an MSS option is received. */
+     pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;
+     pcb->rto = 3000 / TCP_SLOW_INTERVAL;
+     pcb->sa = 0;
+Index: src/core/tcp_in.c
+===================================================================
+RCS file: /sources/lwip/lwip/src/core/tcp_in.c,v
+retrieving revision 1.97
+retrieving revision 1.100
+diff -u -p -r1.97 -r1.100
+--- src/core/tcp_in.c  22 Jan 2008 21:15:15 -0000      1.97
++++ src/core/tcp_in.c  24 Jun 2008 15:46:39 -0000      1.100
+@@ -511,7 +511,7 @@ tcp_process(struct tcp_pcb *pcb)
+       }
+     } else {
+       if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, 
+-                          pcb->rcv_nxt+pcb->rcv_ann_wnd)) {
++                          pcb->rcv_nxt+pcb->rcv_wnd)) {
+         acceptable = 1;
+       }
+     }
+@@ -1038,7 +1038,7 @@ tcp_receive(struct tcp_pcb *pcb)
+        and below rcv_nxt + rcv_wnd) in order to be further
+        processed. */
+     if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, 
+-                        pcb->rcv_nxt + pcb->rcv_ann_wnd - 1)){
++                        pcb->rcv_nxt + pcb->rcv_wnd - 1)){
+       if (pcb->rcv_nxt == seqno) {
+         accepted_inseq = 1; 
+         /* The incoming segment is the next in sequence. We check if
+@@ -1195,14 +1195,14 @@ tcp_receive(struct tcp_pcb *pcb)
+                   } else {
+                     pcb->ooseq = cseg;
+                   }
+-                }
+-                tcp_seg_free(next);
+-                if (cseg->next != NULL) {
+-                  next = cseg->next;
+-                  if (TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) {
+-                    /* We need to trim the incoming segment. */
+-                    cseg->len = (u16_t)(next->tcphdr->seqno - seqno);
+-                    pbuf_realloc(cseg->p, cseg->len);
++                  tcp_seg_free(next);
++                  if (cseg->next != NULL) {
++                    next = cseg->next;
++                    if (TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) {
++                      /* We need to trim the incoming segment. */
++                      cseg->len = (u16_t)(next->tcphdr->seqno - seqno);
++                      pbuf_realloc(cseg->p, cseg->len);
++                    }
+                   }
+                 }
+                 break;
+@@ -1282,10 +1282,7 @@ tcp_receive(struct tcp_pcb *pcb)
+ 
+       }
+     } else {
+-      if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, 
+-                          pcb->rcv_nxt + pcb->rcv_ann_wnd-1)){
+-        tcp_ack_now(pcb);
+-      }
++      tcp_ack_now(pcb);
+     }
+   } else {
+     /* Segments with length 0 is taken care of here. Segments that
+@@ -1331,7 +1328,8 @@ tcp_parseopt(struct tcp_pcb *pcb)
+         opts[c + 1] == 0x04) {
+         /* An MSS option with the right option length. */
+         mss = (opts[c + 2] << 8) | opts[c + 3];
+-        pcb->mss = mss > TCP_MSS? TCP_MSS: mss;
++        /* Limit the mss to the configured TCP_MSS and prevent division by 
zero */
++        pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss;
+ 
+         /* And we are done processing options. */
+         break;
+Index: src/core/ipv4/autoip.c
+===================================================================
+RCS file: /sources/lwip/lwip/src/core/ipv4/autoip.c,v
+retrieving revision 1.16
+retrieving revision 1.17
+diff -u -p -r1.16 -r1.17
+--- src/core/ipv4/autoip.c     26 Jan 2008 16:11:40 -0000      1.16
++++ src/core/ipv4/autoip.c     17 Jun 2008 20:16:23 -0000      1.17
+@@ -395,8 +395,8 @@ autoip_arp_reply(struct netif *netif, st
+     /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
+      * structure packing (not using structure copy which breaks 
strict-aliasing rules).
+      */
+-    MEMCPY(&sipaddr, &hdr->sipaddr, sizeof(sipaddr));
+-    MEMCPY(&dipaddr, &hdr->dipaddr, sizeof(dipaddr));
++    SMEMCPY(&sipaddr, &hdr->sipaddr, sizeof(sipaddr));
++    SMEMCPY(&dipaddr, &hdr->dipaddr, sizeof(dipaddr));
+       
+     if ((netif->autoip->state == AUTOIP_STATE_PROBING) ||
+         ((netif->autoip->state == AUTOIP_STATE_ANNOUNCING) &&
+Index: src/core/ipv4/inet_chksum.c
+===================================================================
+RCS file: /sources/lwip/lwip/src/core/ipv4/inet_chksum.c,v
+retrieving revision 1.4
+retrieving revision 1.5
+diff -u -p -r1.4 -r1.5
+--- src/core/ipv4/inet_chksum.c        10 Mar 2008 16:12:31 -0000      1.4
++++ src/core/ipv4/inet_chksum.c        17 Jun 2008 20:06:25 -0000      1.5
+@@ -41,8 +41,6 @@
+ #include "lwip/inet_chksum.h"
+ #include "lwip/inet.h"
+ 
+-#include <string.h>
+-
+ /* These are some reference implementations of the checksum algorithm, with 
the
+  * aim of being simple, correct and fully portable. Checksumming is the
+  * first thing you would want to optimize for your platform. If you create
+@@ -65,6 +63,11 @@
+ # define LWIP_CHKSUM_ALGORITHM 0
+ #endif
+ 
++/** Like the name says... */
++#define SWAP_BYTES_IN_WORD(w) ((w & 0xff) << 8) | ((w & 0xff00) >> 8)
++/** Split an u32_t in two u16_ts and add them up */
++#define FOLD_U32T(u)          ((u >> 16) + (u & 0x0000ffffUL))
++
+ #if (LWIP_CHKSUM_ALGORITHM == 1) /* Version #1 */
+ /**
+  * lwip checksum
+@@ -86,8 +89,7 @@ lwip_standard_chksum(void *dataptr, u16_
+   acc = 0;
+   /* dataptr may be at odd or even addresses */
+   octetptr = (u8_t*)dataptr;
+-  while (len > 1)
+-  {
++  while (len > 1) {
+     /* declare first octet as most significant
+        thus assume network order, ignoring host order */
+     src = (*octetptr) << 8;
+@@ -98,8 +100,7 @@ lwip_standard_chksum(void *dataptr, u16_
+     acc += src;
+     len -= 2;
+   }
+-  if (len > 0)
+-  {
++  if (len > 0) {
+     /* accumulate remaining octet */
+     src = (*octetptr) << 8;
+     acc += src;
+@@ -154,19 +155,22 @@ lwip_standard_chksum(void *dataptr, int 
+   }
+ 
+   /* Consume left-over byte, if any */
+-  if (len > 0)
++  if (len > 0) {
+     ((u8_t *)&t)[0] = *(u8_t *)ps;;
++  }
+ 
+   /* Add end bytes */
+   sum += t;
+ 
+-  /*  Fold 32-bit sum to 16 bits */
+-  while ((sum >> 16) != 0)
+-    sum = (sum & 0xffff) + (sum >> 16);
++  /* Fold 32-bit sum to 16 bits
++     calling this twice is propably faster than if statements... */
++  sum = FOLD_U32T(sum);
++  sum = FOLD_U32T(sum);
+ 
+   /* Swap if alignment was odd */
+-  if (odd)
+-    sum = ((sum & 0xff) << 8) | ((sum & 0xff00) >> 8);
++  if (odd) {
++    sum = SWAP_BYTES_IN_WORD(sum);
++  }
+ 
+   return sum;
+ }
+@@ -211,18 +215,20 @@ lwip_standard_chksum(void *dataptr, int 
+ 
+   while (len > 7)  {
+     tmp = sum + *pl++;          /* ping */
+-    if (tmp < sum)
++    if (tmp < sum) {
+       tmp++;                    /* add back carry */
++    }
+ 
+     sum = tmp + *pl++;          /* pong */
+-    if (sum < tmp)
++    if (sum < tmp) {
+       sum++;                    /* add back carry */
++    }
+ 
+     len -= 8;
+   }
+ 
+   /* make room in upper bits */
+-  sum = (sum >> 16) + (sum & 0xffff);
++  sum = FOLD_U32T(sum);
+ 
+   ps = (u16_t *)pl;
+ 
+@@ -233,16 +239,20 @@ lwip_standard_chksum(void *dataptr, int 
+   }
+ 
+   /* dangling tail byte remaining? */
+-  if (len > 0)                  /* include odd byte */
++  if (len > 0) {                /* include odd byte */
+     ((u8_t *)&t)[0] = *(u8_t *)ps;
++  }
+ 
+   sum += t;                     /* add end bytes */
+ 
+-  while ((sum >> 16) != 0)      /* combine halves */
+-    sum = (sum >> 16) + (sum & 0xffff);
++  /* Fold 32-bit sum to 16 bits
++     calling this twice is propably faster than if statements... */
++  sum = FOLD_U32T(sum);
++  sum = FOLD_U32T(sum);
+ 
+-  if (odd)
+-    sum = ((sum & 0xff) << 8) | ((sum & 0xff00) >> 8);
++  if (odd) {
++    sum = SWAP_BYTES_IN_WORD(sum);
++  }
+ 
+   return sum;
+ }
+@@ -277,18 +287,18 @@ inet_chksum_pseudo(struct pbuf *p,
+       (void *)q, (void *)q->next));
+     acc += LWIP_CHKSUM(q->payload, q->len);
+     /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped 
lwip_chksum()=%"X32_F" \n", acc));*/
+-    while ((acc >> 16) != 0) {
+-      acc = (acc & 0xffffUL) + (acc >> 16);
+-    }
++    /* just executing this next line is probably faster that the if statement 
needed
++       to check whether we really need to execute it, and does no harm */
++    acc = FOLD_U32T(acc);
+     if (q->len % 2 != 0) {
+       swapped = 1 - swapped;
+-      acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
++      acc = SWAP_BYTES_IN_WORD(acc);
+     }
+     /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped 
lwip_chksum()=%"X32_F" \n", acc));*/
+   }
+ 
+   if (swapped) {
+-    acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
++    acc = SWAP_BYTES_IN_WORD(acc);
+   }
+   acc += (src->addr & 0xffffUL);
+   acc += ((src->addr >> 16) & 0xffffUL);
+@@ -297,9 +307,10 @@ inet_chksum_pseudo(struct pbuf *p,
+   acc += (u32_t)htons((u16_t)proto);
+   acc += (u32_t)htons(proto_len);
+ 
+-  while ((acc >> 16) != 0) {
+-    acc = (acc & 0xffffUL) + (acc >> 16);
+-  }
++  /* Fold 32-bit sum to 16 bits
++     calling this twice is propably faster than if statements... */
++  acc = FOLD_U32T(acc);
++  acc = FOLD_U32T(acc);
+   LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain 
lwip_chksum()=%"X32_F"\n", acc));
+   return (u16_t)~(acc & 0xffffUL);
+ }
+@@ -340,18 +351,17 @@ inet_chksum_pseudo_partial(struct pbuf *
+     chksum_len -= chklen;
+     LWIP_ASSERT("delete me", chksum_len < 0x7fff);
+     /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped 
lwip_chksum()=%"X32_F" \n", acc));*/
+-    while ((acc >> 16) != 0) {
+-      acc = (acc & 0xffffUL) + (acc >> 16);
+-    }
++    /* fold the upper bit down */
++    acc = FOLD_U32T(acc);
+     if (q->len % 2 != 0) {
+       swapped = 1 - swapped;
+-      acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
++      acc = SWAP_BYTES_IN_WORD(acc);
+     }
+     /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped 
lwip_chksum()=%"X32_F" \n", acc));*/
+   }
+ 
+   if (swapped) {
+-    acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
++    acc = SWAP_BYTES_IN_WORD(acc);
+   }
+   acc += (src->addr & 0xffffUL);
+   acc += ((src->addr >> 16) & 0xffffUL);
+@@ -360,9 +370,10 @@ inet_chksum_pseudo_partial(struct pbuf *
+   acc += (u32_t)htons((u16_t)proto);
+   acc += (u32_t)htons(proto_len);
+ 
+-  while ((acc >> 16) != 0) {
+-    acc = (acc & 0xffffUL) + (acc >> 16);
+-  }
++  /* Fold 32-bit sum to 16 bits
++     calling this twice is propably faster than if statements... */
++  acc = FOLD_U32T(acc);
++  acc = FOLD_U32T(acc);
+   LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain 
lwip_chksum()=%"X32_F"\n", acc));
+   return (u16_t)~(acc & 0xffffUL);
+ }
+@@ -380,13 +391,7 @@ inet_chksum_pseudo_partial(struct pbuf *
+ u16_t
+ inet_chksum(void *dataptr, u16_t len)
+ {
+-  u32_t acc;
+-
+-  acc = LWIP_CHKSUM(dataptr, len);
+-  while ((acc >> 16) != 0) {
+-    acc = (acc & 0xffff) + (acc >> 16);
+-  }
+-  return (u16_t)~(acc & 0xffff);
++  return ~LWIP_CHKSUM(dataptr, len);
+ }
+ 
+ /**
+@@ -407,17 +412,15 @@ inet_chksum_pbuf(struct pbuf *p)
+   swapped = 0;
+   for(q = p; q != NULL; q = q->next) {
+     acc += LWIP_CHKSUM(q->payload, q->len);
+-    while ((acc >> 16) != 0) {
+-      acc = (acc & 0xffffUL) + (acc >> 16);
+-    }
++    acc = FOLD_U32T(acc);
+     if (q->len % 2 != 0) {
+       swapped = 1 - swapped;
+-      acc = (acc & 0x00ffUL << 8) | (acc & 0xff00UL >> 8);
++      acc = SWAP_BYTES_IN_WORD(acc);
+     }
+   }
+ 
+   if (swapped) {
+-    acc = ((acc & 0x00ffUL) << 8) | ((acc & 0xff00UL) >> 8);
++    acc = SWAP_BYTES_IN_WORD(acc);
+   }
+   return (u16_t)~(acc & 0xffffUL);
+ }
+Index: src/core/ipv4/ip.c
+===================================================================
+RCS file: /sources/lwip/lwip/src/core/ipv4/ip.c,v
+retrieving revision 1.66
+retrieving revision 1.68
+diff -u -p -r1.66 -r1.68
+--- src/core/ipv4/ip.c 14 Jan 2008 20:53:23 -0000      1.66
++++ src/core/ipv4/ip.c 17 Jun 2008 19:39:22 -0000      1.68
+@@ -531,9 +531,19 @@ ip_output_if(struct pbuf *p, struct ip_a
+   LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], 
netif->name[1], netif->num));
+   ip_debug_print(p);
+ 
+-  LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
++#if (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF)
++  if (ip_addr_cmp(dest, &netif->ip_addr)) {
++    /* Packet to self, enqueue it for loopback */
++    LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()"));
++
++    return netif_loop_output(netif, p, dest);
++  } else
++#endif /* (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF) */
++  {
++    LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
+ 
+-  return netif->output(netif, p, dest);
++    return netif->output(netif, p, dest);
++  }
+ }
+ 
+ /**
+Index: src/include/lwip/debug.h
+===================================================================
+RCS file: /sources/lwip/lwip/src/include/lwip/debug.h,v
+retrieving revision 1.37
+retrieving revision 1.39
+diff -u -p -r1.37 -r1.39
+--- src/include/lwip/debug.h   22 Sep 2007 11:16:07 -0000      1.37
++++ src/include/lwip/debug.h   16 Jul 2008 20:36:22 -0000      1.39
+@@ -61,26 +61,28 @@
+ #define LWIP_DBG_HALT          0x08U
+ 
+ #ifndef LWIP_NOASSERT
+-#define LWIP_ASSERT(x,y) do { if(!(y)) LWIP_PLATFORM_ASSERT(x); } while(0)
++#define LWIP_ASSERT(message, assertion) do { if(!(assertion)) \
++  LWIP_PLATFORM_ASSERT(message); } while(0)
+ #else  /* LWIP_NOASSERT */
+-#define LWIP_ASSERT(x,y) 
++#define LWIP_ASSERT(message, assertion) 
+ #endif /* LWIP_NOASSERT */
+ 
+-/** print "m" message only if "e" is true, and execute "h" expression */
++/** if "expression" isn't true, then print "message" and execute "handler" 
expression */
+ #ifndef LWIP_ERROR
+-#define LWIP_ERROR(m,e,h) do { if (!(e)) { LWIP_PLATFORM_ASSERT(m); h;}} 
while(0)
++#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \
++  LWIP_PLATFORM_ASSERT(message); handler;}} while(0)
+ #endif /* LWIP_ERROR */
+ 
+ #ifdef LWIP_DEBUG
+ /** print debug message only if debug message type is enabled...
+  *  AND is of correct type AND is at least LWIP_DBG_LEVEL
+  */
+-#define LWIP_DEBUGF(debug,x) do { \
++#define LWIP_DEBUGF(debug, message) do { \
+                                if ( \
+                                    ((debug) & LWIP_DBG_ON) && \
+                                    ((debug) & LWIP_DBG_TYPES_ON) && \
+                                    ((s16_t)((debug) & LWIP_DBG_MASK_LEVEL) >= 
LWIP_DBG_MIN_LEVEL)) { \
+-                                 LWIP_PLATFORM_DIAG(x); \
++                                 LWIP_PLATFORM_DIAG(message); \
+                                  if ((debug) & LWIP_DBG_HALT) { \
+                                    while(1); \
+                                  } \
+@@ -88,7 +90,7 @@
+                              } while(0)
+ 
+ #else  /* LWIP_DEBUG */
+-#define LWIP_DEBUGF(debug,x) 
++#define LWIP_DEBUGF(debug, message) 
+ #endif /* LWIP_DEBUG */
+ 
+ #endif /* __LWIP_DEBUG_H__ */
+Index: src/include/lwip/err.h
+===================================================================
+RCS file: /sources/lwip/lwip/src/include/lwip/err.h,v
+retrieving revision 1.13
+retrieving revision 1.15
+diff -u -p -r1.13 -r1.15
+--- src/include/lwip/err.h     13 Dec 2007 23:06:50 -0000      1.13
++++ src/include/lwip/err.h     17 Jun 2008 20:27:32 -0000      1.15
+@@ -33,37 +33,43 @@
+ #define __LWIP_ERR_H__
+ 
+ #include "lwip/opt.h"
++#include "lwip/arch.h"
+ 
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+ 
+-typedef s8_t err_t;
++/** Define LWIP_ERR_T in cc.h if you want to use
++ *  a different type for your platform (must be signed). */
++#ifdef LWIP_ERR_T
++typedef LWIP_ERR_T err_t;
++#else /* LWIP_ERR_T */
++ typedef s8_t err_t;
++#endif /* LWIP_ERR_T*/
+ 
+ /* Definitions for error constants. */
+ 
+ #define ERR_OK          0    /* No error, everything OK. */
+ #define ERR_MEM        -1    /* Out of memory error.     */
+ #define ERR_BUF        -2    /* Buffer error.            */
+-#define ERR_RTE        -3    /* Routing problem.         */
++#define ERR_TIMEOUT    -3    /* Timeout.                 */
++#define ERR_RTE        -4    /* Routing problem.         */
+ 
+ #define ERR_IS_FATAL(e) ((e) < ERR_RTE)
+ 
+-#define ERR_ABRT       -4    /* Connection aborted.      */
+-#define ERR_RST        -5    /* Connection reset.        */
+-#define ERR_CLSD       -6    /* Connection closed.       */
+-#define ERR_CONN       -7    /* Not connected.           */
++#define ERR_ABRT       -5    /* Connection aborted.      */
++#define ERR_RST        -6    /* Connection reset.        */
++#define ERR_CLSD       -7    /* Connection closed.       */
++#define ERR_CONN       -8    /* Not connected.           */
+ 
+-#define ERR_VAL        -8    /* Illegal value.           */
++#define ERR_VAL        -9    /* Illegal value.           */
+ 
+-#define ERR_ARG        -9    /* Illegal argument.        */
++#define ERR_ARG        -10   /* Illegal argument.        */
+ 
+-#define ERR_USE        -10   /* Address in use.          */
++#define ERR_USE        -11   /* Address in use.          */
+ 
+-#define ERR_IF         -11   /* Low-level netif error    */
+-#define ERR_ISCONN     -12   /* Already connected.       */
+-
+-#define ERR_TIMEOUT    -13   /* Timeout.                 */
++#define ERR_IF         -12   /* Low-level netif error    */
++#define ERR_ISCONN     -13   /* Already connected.       */
+ 
+ #define ERR_INPROGRESS -14   /* Operation in progress    */
+ 
+Index: src/include/lwip/mem.h
+===================================================================
+RCS file: /sources/lwip/lwip/src/include/lwip/mem.h,v
+retrieving revision 1.21
+retrieving revision 1.22
+diff -u -p -r1.21 -r1.22
+--- src/include/lwip/mem.h     4 Mar 2008 16:31:32 -0000       1.21
++++ src/include/lwip/mem.h     30 May 2008 11:37:15 -0000      1.22
+@@ -50,16 +50,16 @@ typedef size_t mem_size_t;
+  * allow these defines to be overridden.
+  */
+ #ifndef mem_free
+-#define mem_free(x) free(x)
++#define mem_free free
+ #endif
+ #ifndef mem_malloc
+-#define mem_malloc(x) malloc(x)
++#define mem_malloc malloc
+ #endif
+ #ifndef mem_calloc
+-#define mem_calloc(x, y) calloc(x, y)
++#define mem_calloc calloc
+ #endif
+ #ifndef mem_realloc
+-#define mem_realloc(x, size) (x)
++#define mem_realloc realloc
+ #endif
+ #else /* MEM_LIBC_MALLOC */
+ 
+Index: src/include/lwip/netif.h
+===================================================================
+RCS file: /sources/lwip/lwip/src/include/lwip/netif.h,v
+retrieving revision 1.43
+retrieving revision 1.46
+diff -u -p -r1.43 -r1.46
+--- src/include/lwip/netif.h   9 Oct 2007 19:59:59 -0000       1.43
++++ src/include/lwip/netif.h   19 Jun 2008 16:27:23 -0000      1.46
+@@ -34,6 +34,8 @@
+ 
+ #include "lwip/opt.h"
+ 
++#define ENABLE_LOOPBACK (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF)
++
+ #include "lwip/err.h"
+ 
+ #include "lwip/ip_addr.h"
+@@ -165,6 +167,14 @@ struct netif {
+ #if LWIP_NETIF_HWADDRHINT
+   u8_t *addr_hint;
+ #endif /* LWIP_NETIF_HWADDRHINT */
++#if ENABLE_LOOPBACK
++  /* List of packets to be queued for ourselves. */
++  struct pbuf *loop_first;
++  struct pbuf *loop_last;
++#if LWIP_LOOPBACK_MAX_PBUFS
++  u16_t loop_cnt_current;
++#endif /* LWIP_LOOPBACK_MAX_PBUFS */
++#endif /* ENABLE_LOOPBACK */
+ };
+ 
+ #if LWIP_SNMP
+@@ -242,4 +252,12 @@ void netif_set_link_callback(struct neti
+ }
+ #endif
+ 
++#if ENABLE_LOOPBACK
++err_t netif_loop_output(struct netif *netif, struct pbuf *p, struct ip_addr 
*dest_ip);
++void netif_poll(struct netif *netif);
++#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
++void netif_poll_all(void);
++#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
++#endif /* ENABLE_LOOPBACK */
++
+ #endif /* __LWIP_NETIF_H__ */
+Index: src/include/lwip/opt.h
+===================================================================
+RCS file: /sources/lwip/lwip/src/include/lwip/opt.h,v
+retrieving revision 1.116
+retrieving revision 1.122
+diff -u -p -r1.116 -r1.122
+--- src/include/lwip/opt.h     31 Jan 2008 18:19:29 -0000      1.116
++++ src/include/lwip/opt.h     30 Jun 2008 18:16:52 -0000      1.122
+@@ -155,6 +155,27 @@
+ #define MEMP_USE_CUSTOM_POOLS           0
+ #endif
+ 
++/**
++ * Set this to 1 if you want to free PBUF_RAM pbufs (or call mem_free()) from
++ * interrupt context (or another context that doesn't allow waiting for a
++ * semaphore).
++ * If set to 1, mem_malloc will be protected by a semaphore and 
SYS_ARCH_PROTECT,
++ * while mem_free will only use SYS_ARCH_PROTECT. mem_malloc 
SYS_ARCH_UNPROTECTs
++ * with each loop so that mem_free can run.
++ *
++ * ATTENTION: As you can see from the above description, this leads to dis-/
++ * enabling interrupts often, which can be slow! Also, on low memory, 
mem_malloc
++ * can need longer.
++ *
++ * If you don't want that, at least for NO_SYS=0, you can still use the 
following
++ * functions to enqueue a deallocation call which then runs in the 
tcpip_thread
++ * context:
++ * - pbuf_free_callback(p);
++ * - mem_free_callback(m);
++ */
++#ifndef LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
++#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 0
++#endif
+ 
+ /*
+    ------------------------------------------------
+@@ -815,6 +836,39 @@
+ #define LWIP_NETIF_HWADDRHINT           0
+ #endif
+ 
++/**
++ * LWIP_NETIF_LOOPBACK==1: Support sending packets with a destination IP
++ * address equal to the netif IP address, looping them back up the stack.
++ */
++#ifndef LWIP_NETIF_LOOPBACK
++#define LWIP_NETIF_LOOPBACK             0
++#endif
++
++/**
++ * LWIP_LOOPBACK_MAX_PBUFS: Maximum number of pbufs on queue for loopback
++ * sending for each netif (0 = disabled)
++ */
++#ifndef LWIP_LOOPBACK_MAX_PBUFS
++#define LWIP_LOOPBACK_MAX_PBUFS         0
++#endif
++
++/**
++ * LWIP_NETIF_LOOPBACK_MULTITHREADING: Indicates whether threading is enabled 
in
++ * the system, as netifs must change how they behave depending on this setting
++ * for the LWIP_NETIF_LOOPBACK option to work.
++ * Setting this is needed to avoid reentering non-reentrant functions like
++ * tcp_input().
++ *    LWIP_NETIF_LOOPBACK_MULTITHREADING==1: Indicates that the user is using 
a
++ *       multithreaded environment like tcpip.c. In this case, netif->input()
++ *       is called directly.
++ *    LWIP_NETIF_LOOPBACK_MULTITHREADING==0: Indicates a polling (or NO_SYS) 
setup.
++ *       The packets are put on a list and netif_poll() must be called in
++ *       the main application loop.
++ */
++#ifndef LWIP_NETIF_LOOPBACK_MULTITHREADING
++#define LWIP_NETIF_LOOPBACK_MULTITHREADING    (!NO_SYS)
++#endif
++
+ /*
+    ------------------------------------
+    ---------- LOOPIF options ----------
+@@ -827,20 +881,16 @@
+ #define LWIP_HAVE_LOOPIF                0
+ #endif
+ 
++/*
++   ------------------------------------
++   ---------- SLIPIF options ----------
++   ------------------------------------
++*/
+ /**
+- * LWIP_LOOPIF_MULTITHREADING: Indicates whether threading is enabled in
+- * the system, as LOOPIF must change how it behaves depending on this setting.
+- * Setting this is needed to avoid reentering non-reentrant functions like
+- * tcp_input().
+- *    LWIP_LOOPIF_MULTITHREADING==1: Indicates that the user is using a
+- *       multithreaded environment like tcpip.c. In this case, netif->input()
+- *       is called directly.
+- *    LWIP_LOOPIF_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup.
+- *       The packets are put on a list and loopif_poll() must be called in
+- *       the main application loop.
++ * LWIP_HAVE_SLIPIF==1: Support slip interface and slipif.c
+  */
+-#ifndef LWIP_LOOPIF_MULTITHREADING
+-#define LWIP_LOOPIF_MULTITHREADING      1
++#ifndef LWIP_HAVE_SLIPIF
++#define LWIP_HAVE_SLIPIF                0
+ #endif
+ 
+ /*
+Index: src/include/lwip/sio.h
+===================================================================
+RCS file: /sources/lwip/lwip/src/include/lwip/sio.h,v
+retrieving revision 1.7
+retrieving revision 1.8
+diff -u -p -r1.7 -r1.8
+--- src/include/lwip/sio.h     6 Sep 2007 16:43:44 -0000       1.7
++++ src/include/lwip/sio.h     27 Mar 2008 18:06:02 -0000      1.8
+@@ -32,16 +32,24 @@
+  * It needs to be implemented by those platforms which need SLIP or PPP
+  */
+ 
++#ifndef __SIO_H__
++#define __SIO_H__
++
+ #include "lwip/arch.h"
+ 
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+ 
++/* If you want to define sio_fd_t elsewhere or differently,
++   define this in your cc.h file. */
+ #ifndef __sio_fd_t_defined
+ typedef void * sio_fd_t;
+ #endif
+ 
++/* The following functions can be defined to something else in your cc.h file
++   or be implemented in your custom sio.c file. */
++
+ #ifndef sio_open
+ sio_fd_t sio_open(u8_t);
+ #endif
+@@ -69,3 +77,5 @@ void sio_read_abort(sio_fd_t);
+ #ifdef __cplusplus
+ }
+ #endif
++
++#endif /* __SIO_H__ */
+Index: src/include/lwip/sockets.h
+===================================================================
+RCS file: /sources/lwip/lwip/src/include/lwip/sockets.h,v
+retrieving revision 1.38
+retrieving revision 1.39
+diff -u -p -r1.38 -r1.39
+--- src/include/lwip/sockets.h 2 Dec 2007 15:24:02 -0000       1.38
++++ src/include/lwip/sockets.h 26 Apr 2008 10:46:23 -0000      1.39
+@@ -177,7 +177,22 @@ typedef struct ip_mreq {
+ } ip_mreq;
+ #endif /* LWIP_IGMP */
+ 
+-/* Unimplemented for now... */
++/*
++ * The Type of Service provides an indication of the abstract
++ * parameters of the quality of service desired.  These parameters are
++ * to be used to guide the selection of the actual service parameters
++ * when transmitting a datagram through a particular network.  Several
++ * networks offer service precedence, which somehow treats high
++ * precedence traffic as more important than other traffic (generally
++ * by accepting only traffic above a certain precedence at time of high
++ * load).  The major choice is a three way tradeoff between low-delay,
++ * high-reliability, and high-throughput.
++ * The use of the Delay, Throughput, and Reliability indications may
++ * increase the cost (in some sense) of the service.  In many networks
++ * better performance for one of these parameters is coupled with worse
++ * performance on another.  Except for very unusual cases at most two
++ * of these three indications should be set.
++ */
+ #define IPTOS_TOS_MASK          0x1E
+ #define IPTOS_TOS(tos)          ((tos) & IPTOS_TOS_MASK)
+ #define IPTOS_LOWDELAY          0x10
+@@ -187,7 +202,13 @@ typedef struct ip_mreq {
+ #define IPTOS_MINCOST           IPTOS_LOWCOST
+ 
+ /*
+- * Definitions for IP precedence (also in ip_tos) (Unimplemented)
++ * The Network Control precedence designation is intended to be used
++ * within a network only.  The actual use and control of that
++ * designation is up to each network. The Internetwork Control
++ * designation is intended for use by gateway control originators only.
++ * If the actual use of these precedence designations is of concern to
++ * a particular network, it is the responsibility of that network to
++ * control the access to, and use of, those precedence designations.
+  */
+ #define IPTOS_PREC_MASK                 0xe0
+ #define IPTOS_PREC(tos)                ((tos) & IPTOS_PREC_MASK)
+Index: src/include/lwip/stats.h
+===================================================================
+RCS file: /sources/lwip/lwip/src/include/lwip/stats.h,v
+retrieving revision 1.19
+retrieving revision 1.23
+diff -u -p -r1.19 -r1.23
+--- src/include/lwip/stats.h   28 Nov 2007 21:25:07 -0000      1.19
++++ src/include/lwip/stats.h   8 Jul 2008 09:15:57 -0000       1.23
+@@ -57,7 +57,6 @@ extern "C" {
+ 
+ struct stats_proto {
+   STAT_COUNTER xmit;             /* Transmitted packets. */
+-  STAT_COUNTER rexmit;           /* Retransmitted packets. */
+   STAT_COUNTER recv;             /* Received packets. */
+   STAT_COUNTER fw;               /* Forwarded packets. */
+   STAT_COUNTER drop;             /* Dropped packets. */
+@@ -87,7 +86,8 @@ struct stats_mem {
+   mem_size_t avail;
+   mem_size_t used;
+   mem_size_t max;
+-  mem_size_t err;
++  STAT_COUNTER err;
++  STAT_COUNTER illegal;
+ };
+ 
+ struct stats_syselem {
+@@ -142,64 +142,138 @@ extern struct stats_ lwip_stats;
+ #define stats_init() /* Compatibility define, not init needed. */
+ 
+ #define STATS_INC(x) ++lwip_stats.x
++#define STATS_DEC(x) --lwip_stats.x
+ #else
+ #define stats_init()
+ #define STATS_INC(x)
++#define STATS_DEC(x)
+ #endif /* LWIP_STATS */
+ 
+ #if TCP_STATS
+ #define TCP_STATS_INC(x) STATS_INC(x)
++#define TCP_STATS_DISPLAY() stats_display_proto(&lwip_stats.tcp, "TCP")
+ #else
+ #define TCP_STATS_INC(x)
++#define TCP_STATS_DISPLAY()
+ #endif
+ 
+ #if UDP_STATS
+ #define UDP_STATS_INC(x) STATS_INC(x)
++#define UDP_STATS_DISPLAY() stats_display_proto(&lwip_stats.udp, "UDP")
+ #else
+ #define UDP_STATS_INC(x)
++#define UDP_STATS_DISPLAY()
+ #endif
+ 
+ #if ICMP_STATS
+ #define ICMP_STATS_INC(x) STATS_INC(x)
++#define ICMP_STATS_DISPLAY() stats_display_proto(&lwip_stats.icmp, "ICMP")
+ #else
+ #define ICMP_STATS_INC(x)
++#define ICMP_STATS_DISPLAY()
+ #endif
+ 
+ #if IGMP_STATS
+ #define IGMP_STATS_INC(x) STATS_INC(x)
++#define IGMP_STATS_DISPLAY() stats_display_igmp(&lwip_stats.igmp)
+ #else
+ #define IGMP_STATS_INC(x)
++#define IGMP_STATS_DISPLAY()
+ #endif
+ 
+ #if IP_STATS
+ #define IP_STATS_INC(x) STATS_INC(x)
++#define IP_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip, "IP")
+ #else
+ #define IP_STATS_INC(x)
++#define IP_STATS_DISPLAY()
+ #endif
+ 
+ #if IPFRAG_STATS
+ #define IPFRAG_STATS_INC(x) STATS_INC(x)
++#define IPFRAG_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip_frag, 
"IP_FRAG")
+ #else
+ #define IPFRAG_STATS_INC(x)
++#define IPFRAG_STATS_DISPLAY()
+ #endif
+ 
+ #if ETHARP_STATS
+ #define ETHARP_STATS_INC(x) STATS_INC(x)
++#define ETHARP_STATS_DISPLAY() stats_display_proto(&lwip_stats.etharp, 
"ETHARP")
+ #else
+ #define ETHARP_STATS_INC(x)
++#define ETHARP_STATS_DISPLAY()
+ #endif
+ 
+ #if LINK_STATS
+ #define LINK_STATS_INC(x) STATS_INC(x)
++#define LINK_STATS_DISPLAY() stats_display_proto(&lwip_stats.link, "LINK")
+ #else
+ #define LINK_STATS_INC(x)
++#define LINK_STATS_DISPLAY()
++#endif
++
++#if MEM_STATS
++#define MEM_STATS_AVAIL(x, y) lwip_stats.mem.x = y
++#define MEM_STATS_INC(x) STATS_INC(mem.x)
++#define MEM_STATS_INC_USED(x, y) do { lwip_stats.mem.used += y; \
++                                    if (lwip_stats.mem.max < 
lwip_stats.mem.used) { \
++                                        lwip_stats.mem.max = 
lwip_stats.mem.used; \
++                                    } \
++                                 } while(0)
++#define MEM_STATS_DEC_USED(x, y) lwip_stats.mem.x -= y
++#define MEM_STATS_DISPLAY() stats_display_mem(&lwip_stats.mem, "HEAP")
++#else
++#define MEM_STATS_AVAIL(x, y)
++#define MEM_STATS_INC(x)
++#define MEM_STATS_INC_USED(x, y)
++#define MEM_STATS_DEC_USED(x, y)
++#define MEM_STATS_DISPLAY()
++#endif
++
++#if MEMP_STATS
++#define MEMP_STATS_AVAIL(x, i, y) lwip_stats.memp[i].x = y
++#define MEMP_STATS_INC(x, i) STATS_INC(memp[i].x)
++#define MEMP_STATS_DEC(x, i) STATS_DEC(memp[i].x)
++#define MEMP_STATS_INC_USED(x, i) do { ++lwip_stats.memp[i].used; \
++                                    if (lwip_stats.memp[i].max < 
lwip_stats.memp[i].used) { \
++                                        lwip_stats.memp[i].max = 
lwip_stats.memp[i].used; \
++                                    } \
++                                 } while(0)
++#define MEMP_STATS_DISPLAY(i) stats_display_memp(&lwip_stats.memp[i], i)
++#else
++#define MEMP_STATS_AVAIL(x, i, y)
++#define MEMP_STATS_INC(x, i)
++#define MEMP_STATS_DEC(x, i)
++#define MEMP_STATS_INC_USED(x, i)
++#define MEMP_STATS_DISPLAY(i)
++#endif
++
++#if SYS_STATS
++#define SYS_STATS_INC(x) STATS_INC(sys.x)
++#define SYS_STATS_DEC(x) STATS_DEC(sys.x)
++#define SYS_STATS_DISPLAY() stats_display_sys(&lwip_stats.sys)
++#else
++#define SYS_STATS_INC(x)
++#define SYS_STATS_DEC(x)
++#define SYS_STATS_DISPLAY()
+ #endif
+ 
+ /* Display of statistics */
+ #if LWIP_STATS_DISPLAY
+ void stats_display(void);
++void stats_display_proto(struct stats_proto *proto, char *name);
++void stats_display_igmp(struct stats_igmp *igmp);
++void stats_display_mem(struct stats_mem *mem, char *name);
++void stats_display_memp(struct stats_mem *mem, int index);
++void stats_display_sys(struct stats_sys *sys);
+ #else
+ #define stats_display()
++#define stats_display_proto(proto, name)
++#define stats_display_igmp(igmp)
++#define stats_display_mem(mem, name)
++#define stats_display_memp(mem, index)
++#define stats_display_sys(sys)
+ #endif /* LWIP_STATS_DISPLAY */
+ 
+ #ifdef __cplusplus
+Index: src/include/lwip/tcpip.h
+===================================================================
+RCS file: /sources/lwip/lwip/src/include/lwip/tcpip.h,v
+retrieving revision 1.24
+retrieving revision 1.27
+diff -u -p -r1.24 -r1.27
+--- src/include/lwip/tcpip.h   12 Jan 2008 11:52:22 -0000      1.24
++++ src/include/lwip/tcpip.h   27 Jun 2008 20:34:55 -0000      1.27
+@@ -83,7 +83,11 @@ err_t tcpip_netifapi_lock(struct netifap
+ #endif /* LWIP_NETIF_API */
+ 
+ err_t tcpip_callback_with_block(void (*f)(void *ctx), void *ctx, u8_t block);
+-#define tcpip_callback(f,ctx) tcpip_callback_with_block(f,ctx,1)
++#define tcpip_callback(f, ctx)              tcpip_callback_with_block(f, ctx, 
1)
++
++/* free pbufs or heap memory from another context without blocking */
++err_t pbuf_free_callback(struct pbuf *p);
++err_t mem_free_callback(void *m);
+ 
+ err_t tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg);
+ #define tcpip_untimeout(h, arg) tcpip_timeout(0xffffffff, h, arg)
+Index: src/include/netif/loopif.h
+===================================================================
+RCS file: /sources/lwip/lwip/src/include/netif/loopif.h,v
+retrieving revision 1.7
+retrieving revision 1.9
+diff -u -p -r1.7 -r1.9
+--- src/include/netif/loopif.h 10 May 2007 10:59:20 -0000      1.7
++++ src/include/netif/loopif.h 17 Jun 2008 20:12:22 -0000      1.9
+@@ -32,6 +32,7 @@
+ #ifndef __NETIF_LOOPIF_H__
+ #define __NETIF_LOOPIF_H__
+ 
++#include "lwip/opt.h"
+ #include "lwip/netif.h"
+ #include "lwip/err.h"
+ 
+@@ -39,9 +40,9 @@
+ extern "C" {
+ #endif
+ 
+-#if !LWIP_LOOPIF_MULTITHREADING
+-void loopif_poll(struct netif *netif);
+-#endif
++#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
++#define loopif_poll netif_poll
++#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
+ 
+ err_t loopif_init(struct netif *netif);
+ 
+Index: src/netif/etharp.c
+===================================================================
+RCS file: /sources/lwip/lwip/src/netif/etharp.c,v
+retrieving revision 1.145
+retrieving revision 1.148
+diff -u -p -r1.145 -r1.148
+--- src/netif/etharp.c 4 Mar 2008 13:41:24 -0000       1.145
++++ src/netif/etharp.c 19 Jun 2008 16:40:59 -0000      1.148
+@@ -353,7 +353,7 @@ find_entry(struct ip_addr *ipaddr, u8_t 
+    * 1) empty entry
+    * 2) oldest stable entry
+    * 3) oldest pending entry without queued packets
+-   * 4) oldest pending entry without queued packets
++   * 4) oldest pending entry with queued packets
+    * 
+    * { ETHARP_TRY_HARD is set at this point }
+    */ 
+@@ -1130,7 +1130,14 @@ ethernet_input(struct pbuf *p, struct ne
+ 
+   /* points to packet payload, which starts with an Ethernet header */
+   ethhdr = p->payload;
+-  
++  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE,
++    ("ethernet_input: dest:%02x:%02x:%02x:%02x:%02x:%02x, 
src:%02x:%02x:%02x:%02x:%02x:%02x, type:%2hx\n",
++     (unsigned)ethhdr->dest.addr[0], (unsigned)ethhdr->dest.addr[1], 
(unsigned)ethhdr->dest.addr[2],
++     (unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], 
(unsigned)ethhdr->dest.addr[5],
++     (unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], 
(unsigned)ethhdr->src.addr[2],
++     (unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], 
(unsigned)ethhdr->src.addr[5],
++     (unsigned)htons(ethhdr->type)));
++
+   switch (htons(ethhdr->type)) {
+     /* IP packet? */
+     case ETHTYPE_IP:
+@@ -1165,6 +1172,8 @@ ethernet_input(struct pbuf *p, struct ne
+ #endif /* PPPOE_SUPPORT */
+ 
+     default:
++      ETHARP_STATS_INC(etharp.proterr);
++      ETHARP_STATS_INC(etharp.drop);
+       pbuf_free(p);
+       p = NULL;
+       break;
+Index: src/netif/loopif.c
+===================================================================
+RCS file: /sources/lwip/lwip/src/netif/loopif.c,v
+retrieving revision 1.26
+retrieving revision 1.27
+diff -u -p -r1.26 -r1.27
+--- src/netif/loopif.c 31 Aug 2007 10:14:09 -0000      1.26
++++ src/netif/loopif.c 12 Jun 2008 20:10:10 -0000      1.27
+@@ -40,149 +40,8 @@
+ #if LWIP_HAVE_LOOPIF
+ 
+ #include "netif/loopif.h"
+-#include "lwip/pbuf.h"
+ #include "lwip/snmp.h"
+ 
+-#include <string.h>
+-
+-#if !LWIP_LOOPIF_MULTITHREADING
+-
+-#include "lwip/sys.h"
+-#include "lwip/mem.h"
+-
+-/* helper struct for the linked list of pbufs */
+-struct loopif_private {
+-  struct pbuf *first;
+-  struct pbuf *last;
+-};
+-
+-/**
+- * Call loopif_poll() in the main loop of your application. This is to prevent
+- * reentering non-reentrant functions like tcp_input(). Packets passed to
+- * loopif_output() are put on a list that is passed to netif->input() by
+- * loopif_poll().
+- *
+- * @param netif the lwip network interface structure for this loopif
+- */
+-void
+-loopif_poll(struct netif *netif)
+-{
+-  SYS_ARCH_DECL_PROTECT(lev);
+-  struct pbuf *in, *in_end;
+-  struct loopif_private *priv = (struct loopif_private*)netif->state;
+-
+-  LWIP_ERROR("priv != NULL", (priv != NULL), return;);
+-
+-  do {
+-    /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is 
protected */
+-    SYS_ARCH_PROTECT(lev);
+-    in = priv->first;
+-    if(in) {
+-      in_end = in;
+-      while(in_end->len != in_end->tot_len) {
+-        LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", 
in_end->next != NULL);
+-        in_end = in_end->next;
+-      }
+-      /* 'in_end' now points to the last pbuf from 'in' */
+-      if(in_end == priv->last) {
+-        /* this was the last pbuf in the list */
+-        priv->first = priv->last = NULL;
+-      } else {
+-        /* pop the pbuf off the list */
+-        priv->first = in_end->next;
+-        LWIP_ASSERT("should not be null since first != last!", priv->first != 
NULL);
+-      }
+-    }
+-    SYS_ARCH_UNPROTECT(lev);
+-  
+-    if(in != NULL) {
+-      if(in_end->next != NULL) {
+-        /* De-queue the pbuf from its successors on the 'priv' list. */
+-        in_end->next = NULL;
+-      }
+-      if(netif->input(in, netif) != ERR_OK) {
+-        pbuf_free(in);
+-      }
+-      /* Don't reference the packet any more! */
+-      in = NULL;
+-      in_end = NULL;
+-    }
+-  /* go on while there is a packet on the list */
+-  } while(priv->first != NULL);
+-}
+-#endif /* LWIP_LOOPIF_MULTITHREADING */
+-
+-/**
+- * Send an IP packet over the loopback interface.
+- * The pbuf is simply copied and handed back to netif->input.
+- * In multithreaded mode, this is done directly since netif->input must put
+- * the packet on a queue.
+- * In callback mode, the packet is put on an internal queue and is fed to
+- * netif->input by loopif_poll().
+- *
+- * @param netif the lwip network interface structure for this loopif
+- * @param p the (IP) packet to 'send'
+- * @param ipaddr the ip address to send the packet to (not used for loopif)
+- * @return ERR_OK if the packet has been sent
+- *         ERR_MEM if the pbuf used to copy the packet couldn't be allocated
+- */
+-static err_t
+-loopif_output(struct netif *netif, struct pbuf *p,
+-       struct ip_addr *ipaddr)
+-{
+-#if !LWIP_LOOPIF_MULTITHREADING
+-  SYS_ARCH_DECL_PROTECT(lev);
+-  struct loopif_private *priv;
+-  struct pbuf *last;
+-#endif /* LWIP_LOOPIF_MULTITHREADING */
+-  struct pbuf *r;
+-  err_t err;
+-
+-  LWIP_UNUSED_ARG(ipaddr);
+-
+-  /* Allocate a new pbuf */
+-  r = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
+-  if (r == NULL) {
+-    return ERR_MEM;
+-  }
+-
+-  /* Copy the whole pbuf queue p into the single pbuf r */
+-  if ((err = pbuf_copy(r, p)) != ERR_OK) {
+-    pbuf_free(r);
+-    r = NULL;
+-    return err;
+-  }
+-
+-#if LWIP_LOOPIF_MULTITHREADING
+-  /* Multithreading environment, netif->input() is supposed to put the packet
+-     into a mailbox, so we can safely call it here without risking to re-enter
+-     functions that are not reentrant (TCP!!!) */
+-  if(netif->input(r, netif) != ERR_OK) {
+-    pbuf_free(r);
+-    r = NULL;
+-  }
+-#else /* LWIP_LOOPIF_MULTITHREADING */
+-  /* Raw API without threads: put the packet on a linked list which gets 
emptied
+-     through calling loopif_poll(). */
+-  priv = (struct loopif_private*)netif->state;
+-
+-  /* let last point to the last pbuf in chain r */
+-  for (last = r; last->next != NULL; last = last->next);
+-  SYS_ARCH_PROTECT(lev);
+-  if(priv->first != NULL) {
+-    LWIP_ASSERT("if first != NULL, last must also be != NULL", priv->last != 
NULL);
+-    priv->last->next = r;
+-    priv->last = last;
+-  } else {
+-    priv->first = r;
+-    priv->last = last;
+-  }
+-  SYS_ARCH_UNPROTECT(lev);
+-#endif /* LWIP_LOOPIF_MULTITHREADING */
+-
+-  return ERR_OK;    
+-}
+-
+ /**
+  * Initialize a lwip network interface structure for a loopback interface
+  *
+@@ -193,16 +52,6 @@ loopif_output(struct netif *netif, struc
+ err_t
+ loopif_init(struct netif *netif)
+ {
+-#if !LWIP_LOOPIF_MULTITHREADING
+-  struct loopif_private *priv;
+-
+-  priv = (struct loopif_private*)mem_malloc(sizeof(struct loopif_private));
+-  if(priv == NULL) 
+-    return ERR_MEM;
+-  priv->first = priv->last = NULL;
+-  netif->state = priv;
+-#endif /* LWIP_LOOPIF_MULTITHREADING */
+-
+   /* initialize the snmp variables and counters inside the struct netif
+    * ifSpeed: no assumption can be made!
+    */
+@@ -210,7 +59,7 @@ loopif_init(struct netif *netif)
+ 
+   netif->name[0] = 'l';
+   netif->name[1] = 'o';
+-  netif->output = loopif_output;
++  netif->output = netif_loop_output;
+   return ERR_OK;
+ }
+ 
+Index: src/netif/slipif.c
+===================================================================
+RCS file: /sources/lwip/lwip/src/netif/slipif.c,v
+retrieving revision 1.29
+retrieving revision 1.30
+diff -u -p -r1.29 -r1.30
+--- src/netif/slipif.c 30 Nov 2007 17:22:21 -0000      1.29
++++ src/netif/slipif.c 17 Jun 2008 20:14:05 -0000      1.30
+@@ -44,6 +44,9 @@
+ 
+ #include "netif/slipif.h"
+ #include "lwip/opt.h"
++
++#if LWIP_HAVE_SLIPIF
++
+ #include "lwip/def.h"
+ #include "lwip/pbuf.h"
+ #include "lwip/sys.h"
+@@ -273,3 +276,4 @@ slipif_init(struct netif *netif)
+   sys_thread_new(SLIPIF_THREAD_NAME, slipif_loop, netif, 
SLIPIF_THREAD_STACKSIZE, SLIPIF_THREAD_PRIO);
+   return ERR_OK;
+ }
++#endif /* LWIP_HAVE_SLIPIF */

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH] stubdom: use the 1.3.0 release + patch instead of checking out from cvs, Samuel Thibault <=