ia64/xen-unstable

changeset 18079:a8603b2fb786

stubdom: use lwip 1.3.0 release + patch instead of checking out from cvs

Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jul 17 15:37:09 2008 +0100 (2008-07-17)
parents 6f82840f173b
children 400e5d4877ca e126614f0def
files stubdom/Makefile stubdom/lwip.patch-cvs
line diff
     1.1 --- a/stubdom/Makefile	Thu Jul 17 15:33:15 2008 +0100
     1.2 +++ b/stubdom/Makefile	Thu Jul 17 15:37:09 2008 +0100
     1.3 @@ -13,7 +13,7 @@ IOEMU_OPTIONS=--disable-sdl --disable-op
     1.4  ZLIB_VERSION=1.2.3
     1.5  LIBPCI_VERSION=2.2.9
     1.6  NEWLIB_VERSION=1.16.0
     1.7 -LWIP_DATE=2008-06-01
     1.8 +LWIP_VERSION=1.3.0
     1.9  GRUB_VERSION=0.97
    1.10  
    1.11  WGET=wget -c
    1.12 @@ -54,8 +54,8 @@ TARGET_CPPFLAGS += -nostdinc
    1.13  TARGET_CPPFLAGS += -isystem $(CURDIR)/$(MINI_OS)/include/posix
    1.14  TARGET_CPPFLAGS += -isystem $(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/include
    1.15  TARGET_CPPFLAGS += -isystem $(GCC_INSTALL)include
    1.16 -TARGET_CPPFLAGS += -isystem $(CURDIR)/lwip-cvs/src/include
    1.17 -TARGET_CPPFLAGS += -isystem $(CURDIR)/lwip-cvs/src/include/ipv4
    1.18 +TARGET_CPPFLAGS += -isystem $(CURDIR)/lwip/src/include
    1.19 +TARGET_CPPFLAGS += -isystem $(CURDIR)/lwip/src/include/ipv4
    1.20  TARGET_CPPFLAGS += -I$(CURDIR)/include
    1.21  
    1.22  TARGET_LDFLAGS += -nostdlib -L$(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/lib
    1.23 @@ -139,8 +139,13 @@ cross-libpci: $(LIBPCI_STAMPFILE)
    1.24  # lwIP
    1.25  ######
    1.26  
    1.27 -lwip-cvs:
    1.28 -	cvs -z 9 -d :pserver:anonymous@cvs.savannah.nongnu.org:/sources/lwip co -D $(LWIP_DATE) -d $@ lwip
    1.29 +lwip-$(LWIP_VERSION).tar.gz:
    1.30 +	$(WGET) http://download.savannah.gnu.org/releases/lwip/$@
    1.31 +
    1.32 +lwip: lwip-$(LWIP_VERSION).tar.gz
    1.33 +	tar xzf $<
    1.34 +	patch -d $@ -p0 < lwip.patch-cvs
    1.35 +	touch $@
    1.36  
    1.37  #######
    1.38  # Links
    1.39 @@ -213,12 +218,12 @@ ifeq ($(CONFIG_QEMU),ioemu)
    1.40  	[ -f ioemu/config-host.mak ] || \
    1.41  	  ( cd ioemu ; \
    1.42            XEN_TARGET_ARCH=$(XEN_TARGET_ARCH) CFLAGS="$(TARGET_CFLAGS)" sh configure --prefix=/usr --enable-stubdom $(IOEMU_OPTIONS))
    1.43 -	CPPFLAGS="$(TARGET_CPPFLAGS)" $(MAKE) -C ioemu LWIPDIR=$(CURDIR)/lwip-cvs TOOLS=
    1.44 +	CPPFLAGS="$(TARGET_CPPFLAGS)" $(MAKE) -C ioemu LWIPDIR=$(CURDIR)/lwip TOOLS=
    1.45  else
    1.46  	[ -f ioemu/config-host.mak ] || \
    1.47  	  ( cd ioemu ; \
    1.48            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))
    1.49 -	CPPFLAGS= TARGET_CPPFLAGS="$(TARGET_CPPFLAGS)" $(MAKE) -C ioemu LWIPDIR=$(CURDIR)/lwip-cvs TOOLS= CONFIG_STUBDOM=yes
    1.50 +	CPPFLAGS= TARGET_CPPFLAGS="$(TARGET_CPPFLAGS)" $(MAKE) -C ioemu LWIPDIR=$(CURDIR)/lwip TOOLS= CONFIG_STUBDOM=yes
    1.51  endif
    1.52  
    1.53  ######
    1.54 @@ -227,7 +232,7 @@ endif
    1.55  
    1.56  .PHONY: caml
    1.57  caml: cross-newlib mk-headers
    1.58 -	CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) -C $@ LWIPDIR=$(CURDIR)/lwip-cvs 
    1.59 +	CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) -C $@ LWIPDIR=$(CURDIR)/lwip 
    1.60  
    1.61  ###
    1.62  # C
    1.63 @@ -235,7 +240,7 @@ caml: cross-newlib mk-headers
    1.64  
    1.65  .PHONY: c
    1.66  c: cross-newlib mk-headers
    1.67 -	CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) -C $@ LWIPDIR=$(CURDIR)/lwip-cvs 
    1.68 +	CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) -C $@ LWIPDIR=$(CURDIR)/lwip 
    1.69  
    1.70  ######
    1.71  # Grub
    1.72 @@ -265,17 +270,17 @@ ioemu-stubdom: APP_OBJS=$(CURDIR)/ioemu/
    1.73  else
    1.74  ioemu-stubdom: APP_OBJS=$(CURDIR)/ioemu/i386-stubdom/qemu.a $(CURDIR)/ioemu/i386-stubdom/libqemu.a $(CURDIR)/ioemu/libqemu_common.a
    1.75  endif
    1.76 -ioemu-stubdom: mini-os-ioemu lwip-cvs libxc ioemu
    1.77 -	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)"
    1.78 +ioemu-stubdom: mini-os-ioemu lwip libxc ioemu
    1.79 +	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)"
    1.80  
    1.81  CAMLLIB = $(shell ocamlc -where)
    1.82  .PHONY: caml-stubdom
    1.83 -caml-stubdom: mini-os-caml lwip-cvs libxc caml
    1.84 -	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"
    1.85 +caml-stubdom: mini-os-caml lwip libxc caml
    1.86 +	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"
    1.87  
    1.88  .PHONY: c-stubdom
    1.89 -c-stubdom: mini-os-c lwip-cvs libxc c
    1.90 -	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
    1.91 +c-stubdom: mini-os-c lwip libxc c
    1.92 +	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
    1.93  
    1.94  .PHONY: pv-grub
    1.95  pv-grub: mini-os-grub libxc grub
    1.96 @@ -328,7 +333,7 @@ crossclean: clean
    1.97  .PHONY: patchclean
    1.98  patchclean: crossclean
    1.99  	rm -fr newlib-$(NEWLIB_VERSION)
   1.100 -	rm -fr lwip-cvs
   1.101 +	rm -fr lwip
   1.102  	rm -fr grub-upstream
   1.103  
   1.104  # clean downloads
   1.105 @@ -337,6 +342,8 @@ downloadclean: patchclean
   1.106  	rm -f newlib-$(NEWLIB_VERSION).tar.gz
   1.107  	rm -f zlib-$(ZLIB_VERSION).tar.gz
   1.108  	rm -f pciutils-$(LIBPCI_VERSION).tar.bz2
   1.109 +	rm -f grub-$(GRUB_VERSION).tar.gz
   1.110 +	rm -f lwip-$(LWIP_VERSION).tar.gz
   1.111  
   1.112  .PHONY: distclean
   1.113  distclean: downloadclean
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/stubdom/lwip.patch-cvs	Thu Jul 17 15:37:09 2008 +0100
     2.3 @@ -0,0 +1,2398 @@
     2.4 +? .ChangeLog.swp
     2.5 +? ChangeLog
     2.6 +Index: CHANGELOG
     2.7 +===================================================================
     2.8 +RCS file: /sources/lwip/lwip/CHANGELOG,v
     2.9 +retrieving revision 1.300
    2.10 +retrieving revision 1.318
    2.11 +diff -u -p -r1.300 -r1.318
    2.12 +--- CHANGELOG	23 Mar 2008 13:49:39 -0000	1.300
    2.13 ++++ CHANGELOG	14 Jul 2008 20:12:36 -0000	1.318
    2.14 +@@ -19,9 +19,77 @@ HISTORY
    2.15 + 
    2.16 +   ++ New features:
    2.17 + 
    2.18 ++  2008-06-30 Simon Goldschmidt
    2.19 ++  * mem.c, opt.h, stats.h: fixed bug #21433: Calling mem_free/pbuf_free from
    2.20 ++    interrupt context isn't safe: LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT allows
    2.21 ++    mem_free to run between mem_malloc iterations. Added illegal counter for
    2.22 ++    mem stats.
    2.23 ++
    2.24 ++  2008-06-27 Simon Goldschmidt
    2.25 ++  * stats.h/.c, some other files: patch #6483: stats module improvement:
    2.26 ++    Added defines to display each module's statistic individually, added stats
    2.27 ++    defines for MEM, MEMP and SYS modules, removed (unused) rexmit counter.
    2.28 ++
    2.29 ++  2008-06-17 Simon Goldschmidt
    2.30 ++  * err.h: patch #6459: Made err_t overridable to use a more efficient type
    2.31 ++    (define LWIP_ERR_T in cc.h)
    2.32 ++
    2.33 ++  2008-06-17 Simon Goldschmidt
    2.34 ++  * slipif.c: patch #6480: Added a configuration option for slipif for symmetry
    2.35 ++    to loopif
    2.36 ++
    2.37 ++  2008-06-17 Simon Goldschmidt (patch by Luca Ceresoli)
    2.38 ++  * netif.c, loopif.c, ip.c, netif.h, loopif.h, opt.h: Checked in slightly
    2.39 ++    modified version of patch # 6370: Moved loopif code to netif.c so that
    2.40 ++    loopback traffic is supported on all netifs (all local IPs).
    2.41 ++    Added option to limit loopback packets for each netifs.
    2.42 ++
    2.43 + 
    2.44 +   ++ Bugfixes:
    2.45 + 
    2.46 ++  2008-08-14 Simon Goldschmidt
    2.47 ++  * api_msg.c: fixed bug #23847: do_close_internal references freed memory (when
    2.48 ++    tcp_close returns != ERR_OK)
    2.49 ++
    2.50 ++  2008-07-08 Frédéric Bernon
    2.51 ++  * stats.h: Fix some build bugs introduced with patch #6483 (missing some parameters
    2.52 ++    in macros, mainly if MEM_STATS=0 and MEMP_STATS=0).
    2.53 ++
    2.54 ++  2008-06-24 Jonathan Larmour
    2.55 ++  * tcp_in.c: Fix for bug #23693 as suggested by Art R. Ensure cseg is unused
    2.56 ++    if tcp_seg_copy fails.
    2.57 ++
    2.58 ++  2008-06-17 Simon Goldschmidt
    2.59 ++  * inet_chksum.c: Checked in some ideas of patch #6460 (loop optimizations)
    2.60 ++    and created defines for swapping bytes and folding u32 to u16.
    2.61 ++
    2.62 ++  2008-05-30 Kieran Mansley
    2.63 ++  * tcp_in.c Remove redundant "if" statement, and use real rcv_wnd
    2.64 ++    rather than rcv_ann_wnd when deciding if packets are in-window.
    2.65 ++    Contributed by <arasmussen@consultant.datasys.swri.edu>
    2.66 ++
    2.67 ++  2008-05-30 Kieran Mansley
    2.68 ++  * mem.h: Fix BUG#23254.  Change macro definition of mem_* to allow
    2.69 ++    passing as function pointers when MEM_LIBC_MALLOC is defined.
    2.70 ++
    2.71 ++  2008-05-09 Jonathan Larmour
    2.72 ++  * err.h, err.c, sockets.c: Fix bug #23119: Reorder timeout error code to
    2.73 ++    stop it being treated as a fatal error.
    2.74 ++
    2.75 ++  2008-04-15 Simon Goldschmidt
    2.76 ++  * dhcp.c: fixed bug #22804: dhcp_stop doesn't clear NETIF_FLAG_DHCP
    2.77 ++    (flag now cleared)
    2.78 ++
    2.79 ++  2008-03-27 Simon Goldschmidt
    2.80 ++  * mem.c, tcpip.c, tcpip.h, opt.h: fixed bug #21433 (Calling mem_free/pbuf_free
    2.81 ++    from interrupt context isn't safe): set LWIP_USE_HEAP_FROM_INTERRUPT to 1
    2.82 ++    in lwipopts.h or use pbuf_free_callback(p)/mem_free_callback(m) to free pbufs
    2.83 ++    or heap memory from interrupt context
    2.84 ++
    2.85 ++  2008-03-26 Simon Goldschmidt
    2.86 ++  * tcp_in.c, tcp.c: fixed bug #22249: division by zero could occur if a remote
    2.87 ++    host sent a zero mss as TCP option.
    2.88 ++
    2.89 + 
    2.90 + (STABLE-1.3.0)
    2.91 + 
    2.92 +Index: src/api/api_msg.c
    2.93 +===================================================================
    2.94 +RCS file: /sources/lwip/lwip/src/api/api_msg.c,v
    2.95 +retrieving revision 1.102
    2.96 +retrieving revision 1.104
    2.97 +diff -u -p -r1.102 -r1.104
    2.98 +--- src/api/api_msg.c	21 Mar 2008 16:23:14 -0000	1.102
    2.99 ++++ src/api/api_msg.c	15 Jul 2008 11:18:58 -0000	1.104
   2.100 +@@ -598,11 +598,16 @@ do_close_internal(struct netconn *conn)
   2.101 +   LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL));
   2.102 + 
   2.103 +   /* Set back some callback pointers */
   2.104 ++  tcp_arg(conn->pcb.tcp, NULL);
   2.105 +   if (conn->pcb.tcp->state == LISTEN) {
   2.106 +-    tcp_arg(conn->pcb.tcp, NULL);
   2.107 +     tcp_accept(conn->pcb.tcp, NULL);
   2.108 +   } else {
   2.109 +     tcp_recv(conn->pcb.tcp, NULL);
   2.110 ++    tcp_accept(conn->pcb.tcp, NULL);
   2.111 ++    /* some callbacks have to be reset if tcp_close is not successful */
   2.112 ++    tcp_sent(conn->pcb.tcp, NULL);
   2.113 ++    tcp_poll(conn->pcb.tcp, NULL, 4);
   2.114 ++    tcp_err(conn->pcb.tcp, NULL);
   2.115 +   }
   2.116 +   /* Try to close the connection */
   2.117 +   err = tcp_close(conn->pcb.tcp);
   2.118 +@@ -610,11 +615,6 @@ do_close_internal(struct netconn *conn)
   2.119 +     /* Closing succeeded */
   2.120 +     conn->state = NETCONN_NONE;
   2.121 +     /* Set back some callback pointers as conn is going away */
   2.122 +-    tcp_err(conn->pcb.tcp, NULL);
   2.123 +-    tcp_poll(conn->pcb.tcp, NULL, 4);
   2.124 +-    tcp_sent(conn->pcb.tcp, NULL);
   2.125 +-    tcp_recv(conn->pcb.tcp, NULL);
   2.126 +-    tcp_arg(conn->pcb.tcp, NULL);
   2.127 +     conn->pcb.tcp = NULL;
   2.128 +     conn->err = ERR_OK;
   2.129 +     /* Trigger select() in socket layer. This send should something else so the
   2.130 +@@ -623,6 +623,14 @@ do_close_internal(struct netconn *conn)
   2.131 +     API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
   2.132 +     /* wake up the application task */
   2.133 +     sys_sem_signal(conn->op_completed);
   2.134 ++  } else {
   2.135 ++    /* Closing failed, restore some of the callbacks */
   2.136 ++    /* Closing of listen pcb will never fail! */
   2.137 ++    LWIP_ASSERT("Closing a listen pcb may not fail!", (conn->pcb.tcp->state != LISTEN));
   2.138 ++    tcp_sent(conn->pcb.tcp, sent_tcp);
   2.139 ++    tcp_poll(conn->pcb.tcp, poll_tcp, 4);
   2.140 ++    tcp_err(conn->pcb.tcp, err_tcp);
   2.141 ++    tcp_arg(conn->pcb.tcp, conn);
   2.142 +   }
   2.143 +   /* If closing didn't succeed, we get called again either
   2.144 +      from poll_tcp or from sent_tcp */
   2.145 +Index: src/api/err.c
   2.146 +===================================================================
   2.147 +RCS file: /sources/lwip/lwip/src/api/err.c,v
   2.148 +retrieving revision 1.11
   2.149 +retrieving revision 1.12
   2.150 +diff -u -p -r1.11 -r1.12
   2.151 +--- src/api/err.c	13 Dec 2007 23:06:50 -0000	1.11
   2.152 ++++ src/api/err.c	9 May 2008 12:14:23 -0000	1.12
   2.153 +@@ -44,17 +44,17 @@ static const char *err_strerr[] = {
   2.154 +            "Ok.",                    /* ERR_OK          0  */
   2.155 +            "Out of memory error.",   /* ERR_MEM        -1  */
   2.156 +            "Buffer error.",          /* ERR_BUF        -2  */
   2.157 +-           "Routing problem.",       /* ERR_RTE        -3  */
   2.158 +-           "Connection aborted.",    /* ERR_ABRT       -4  */
   2.159 +-           "Connection reset.",      /* ERR_RST        -5  */
   2.160 +-           "Connection closed.",     /* ERR_CLSD       -6  */
   2.161 +-           "Not connected.",         /* ERR_CONN       -7  */
   2.162 +-           "Illegal value.",         /* ERR_VAL        -8  */
   2.163 +-           "Illegal argument.",      /* ERR_ARG        -9  */
   2.164 +-           "Address in use.",        /* ERR_USE        -10 */
   2.165 +-           "Low-level netif error.", /* ERR_IF         -11 */
   2.166 +-           "Already connected.",     /* ERR_ISCONN     -12 */
   2.167 +-           "Timeout.",               /* ERR_TIMEOUT    -13 */
   2.168 ++           "Timeout.",               /* ERR_TIMEOUT    -3 */
   2.169 ++           "Routing problem.",       /* ERR_RTE        -4  */
   2.170 ++           "Connection aborted.",    /* ERR_ABRT       -5  */
   2.171 ++           "Connection reset.",      /* ERR_RST        -6  */
   2.172 ++           "Connection closed.",     /* ERR_CLSD       -7  */
   2.173 ++           "Not connected.",         /* ERR_CONN       -8  */
   2.174 ++           "Illegal value.",         /* ERR_VAL        -9  */
   2.175 ++           "Illegal argument.",      /* ERR_ARG        -10 */
   2.176 ++           "Address in use.",        /* ERR_USE        -11 */
   2.177 ++           "Low-level netif error.", /* ERR_IF         -12 */
   2.178 ++           "Already connected.",     /* ERR_ISCONN     -13 */
   2.179 +            "Operation in progress."  /* ERR_INPROGRESS -14 */
   2.180 + };
   2.181 + 
   2.182 +Index: src/api/netdb.c
   2.183 +===================================================================
   2.184 +RCS file: /sources/lwip/lwip/src/api/netdb.c,v
   2.185 +retrieving revision 1.4
   2.186 +retrieving revision 1.5
   2.187 +diff -u -p -r1.4 -r1.5
   2.188 +--- src/api/netdb.c	26 Jan 2008 16:11:39 -0000	1.4
   2.189 ++++ src/api/netdb.c	16 Jul 2008 20:36:12 -0000	1.5
   2.190 +@@ -326,7 +326,8 @@ lwip_getaddrinfo(const char *nodename, c
   2.191 +   if (nodename != NULL) {
   2.192 +     /* copy nodename to canonname if specified */
   2.193 +     size_t namelen = strlen(nodename);
   2.194 +-    ai->ai_canonname = mem_malloc(namelen + 1);
   2.195 ++    LWIP_ASSERT("namelen is too long", (namelen + 1) <= (mem_size_t)-1);
   2.196 ++    ai->ai_canonname = mem_malloc((mem_size_t)(namelen + 1));
   2.197 +     if (ai->ai_canonname == NULL) {
   2.198 +       goto memerr;
   2.199 +     }
   2.200 +Index: src/api/sockets.c
   2.201 +===================================================================
   2.202 +RCS file: /sources/lwip/lwip/src/api/sockets.c,v
   2.203 +retrieving revision 1.116
   2.204 +retrieving revision 1.117
   2.205 +diff -u -p -r1.116 -r1.117
   2.206 +--- src/api/sockets.c	13 Mar 2008 20:03:57 -0000	1.116
   2.207 ++++ src/api/sockets.c	9 May 2008 12:14:24 -0000	1.117
   2.208 +@@ -128,17 +128,17 @@ static const int err_to_errno_table[] = 
   2.209 +   0,             /* ERR_OK          0      No error, everything OK. */
   2.210 +   ENOMEM,        /* ERR_MEM        -1      Out of memory error.     */
   2.211 +   ENOBUFS,       /* ERR_BUF        -2      Buffer error.            */
   2.212 +-  EHOSTUNREACH,  /* ERR_RTE        -3      Routing problem.         */
   2.213 +-  ECONNABORTED,  /* ERR_ABRT       -4      Connection aborted.      */
   2.214 +-  ECONNRESET,    /* ERR_RST        -5      Connection reset.        */
   2.215 +-  ESHUTDOWN,     /* ERR_CLSD       -6      Connection closed.       */
   2.216 +-  ENOTCONN,      /* ERR_CONN       -7      Not connected.           */
   2.217 +-  EINVAL,        /* ERR_VAL        -8      Illegal value.           */
   2.218 +-  EIO,           /* ERR_ARG        -9      Illegal argument.        */
   2.219 +-  EADDRINUSE,    /* ERR_USE        -10     Address in use.          */
   2.220 +-  -1,            /* ERR_IF         -11     Low-level netif error    */
   2.221 +-  -1,            /* ERR_ISCONN     -12     Already connected.       */
   2.222 +-  ETIMEDOUT,     /* ERR_TIMEOUT    -13     Timeout                  */
   2.223 ++  ETIMEDOUT,     /* ERR_TIMEOUT    -3      Timeout                  */
   2.224 ++  EHOSTUNREACH,  /* ERR_RTE        -4      Routing problem.         */
   2.225 ++  ECONNABORTED,  /* ERR_ABRT       -5      Connection aborted.      */
   2.226 ++  ECONNRESET,    /* ERR_RST        -6      Connection reset.        */
   2.227 ++  ESHUTDOWN,     /* ERR_CLSD       -7      Connection closed.       */
   2.228 ++  ENOTCONN,      /* ERR_CONN       -8      Not connected.           */
   2.229 ++  EINVAL,        /* ERR_VAL        -9      Illegal value.           */
   2.230 ++  EIO,           /* ERR_ARG        -10     Illegal argument.        */
   2.231 ++  EADDRINUSE,    /* ERR_USE        -11     Address in use.          */
   2.232 ++  -1,            /* ERR_IF         -12     Low-level netif error    */
   2.233 ++  -1,            /* ERR_ISCONN     -13     Already connected.       */
   2.234 +   EINPROGRESS    /* ERR_INPROGRESS -14     Operation in progress    */
   2.235 + };
   2.236 + 
   2.237 +Index: src/api/tcpip.c
   2.238 +===================================================================
   2.239 +RCS file: /sources/lwip/lwip/src/api/tcpip.c,v
   2.240 +retrieving revision 1.70
   2.241 +retrieving revision 1.73
   2.242 +diff -u -p -r1.70 -r1.73
   2.243 +--- src/api/tcpip.c	12 Jan 2008 11:52:22 -0000	1.70
   2.244 ++++ src/api/tcpip.c	27 Jun 2008 20:34:51 -0000	1.73
   2.245 +@@ -518,4 +518,42 @@ tcpip_init(void (* initfunc)(void *), vo
   2.246 +   sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
   2.247 + }
   2.248 + 
   2.249 ++/**
   2.250 ++ * Simple callback function used with tcpip_callback to free a pbuf
   2.251 ++ * (pbuf_free has a wrong signature for tcpip_callback)
   2.252 ++ *
   2.253 ++ * @param p The pbuf (chain) to be dereferenced.
   2.254 ++ */
   2.255 ++static void
   2.256 ++pbuf_free_int(void *p)
   2.257 ++{
   2.258 ++  struct pbuf *q = p;
   2.259 ++  pbuf_free(q);
   2.260 ++}
   2.261 ++
   2.262 ++/**
   2.263 ++ * A simple wrapper function that allows you to free a pbuf from interrupt context.
   2.264 ++ *
   2.265 ++ * @param p The pbuf (chain) to be dereferenced.
   2.266 ++ * @return ERR_OK if callback could be enqueued, an err_t if not
   2.267 ++ */
   2.268 ++err_t
   2.269 ++pbuf_free_callback(struct pbuf *p)
   2.270 ++{
   2.271 ++  return tcpip_callback_with_block(pbuf_free_int, p, 0);
   2.272 ++}
   2.273 ++
   2.274 ++/**
   2.275 ++ * A simple wrapper function that allows you to free heap memory from
   2.276 ++ * interrupt context.
   2.277 ++ *
   2.278 ++ * @param m the heap memory to free
   2.279 ++ * @return ERR_OK if callback could be enqueued, an err_t if not
   2.280 ++ */
   2.281 ++err_t
   2.282 ++mem_free_callback(void *m)
   2.283 ++{
   2.284 ++  return tcpip_callback_with_block(mem_free, m, 0);
   2.285 ++}
   2.286 ++
   2.287 + #endif /* !NO_SYS */
   2.288 +Index: src/core/dhcp.c
   2.289 +===================================================================
   2.290 +RCS file: /sources/lwip/lwip/src/core/dhcp.c,v
   2.291 +retrieving revision 1.86
   2.292 +retrieving revision 1.87
   2.293 +diff -u -p -r1.86 -r1.87
   2.294 +--- src/core/dhcp.c	4 Mar 2008 14:25:58 -0000	1.86
   2.295 ++++ src/core/dhcp.c	15 Apr 2008 17:24:55 -0000	1.87
   2.296 +@@ -568,6 +568,8 @@ dhcp_start(struct netif *netif)
   2.297 +   LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;);
   2.298 +   dhcp = netif->dhcp;
   2.299 +   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));
   2.300 ++  /* Remove the flag that says this netif is handled by DHCP,
   2.301 ++     it is set when we succeeded starting. */
   2.302 +   netif->flags &= ~NETIF_FLAG_DHCP;
   2.303 + 
   2.304 +   /* no DHCP client attached yet? */
   2.305 +@@ -609,6 +611,7 @@ dhcp_start(struct netif *netif)
   2.306 +     dhcp_stop(netif);
   2.307 +     return ERR_MEM;
   2.308 +   }
   2.309 ++  /* Set the flag that says this netif is handled by DHCP. */
   2.310 +   netif->flags |= NETIF_FLAG_DHCP;
   2.311 +   return result;
   2.312 + }
   2.313 +@@ -1063,6 +1066,8 @@ dhcp_stop(struct netif *netif)
   2.314 + {
   2.315 +   struct dhcp *dhcp = netif->dhcp;
   2.316 +   LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return;);
   2.317 ++  /* Remove the flag that says this netif is handled by DHCP. */
   2.318 ++  netif->flags &= ~NETIF_FLAG_DHCP;
   2.319 + 
   2.320 +   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_stop()\n"));
   2.321 +   /* netif is DHCP configured? */
   2.322 +Index: src/core/mem.c
   2.323 +===================================================================
   2.324 +RCS file: /sources/lwip/lwip/src/core/mem.c,v
   2.325 +retrieving revision 1.59
   2.326 +retrieving revision 1.62
   2.327 +diff -u -p -r1.59 -r1.62
   2.328 +--- src/core/mem.c	4 Mar 2008 16:31:32 -0000	1.59
   2.329 ++++ src/core/mem.c	30 Jun 2008 18:16:51 -0000	1.62
   2.330 +@@ -177,9 +177,36 @@ static u8_t *ram;
   2.331 + static struct mem *ram_end;
   2.332 + /** pointer to the lowest free block, this is used for faster search */
   2.333 + static struct mem *lfree;
   2.334 ++
   2.335 + /** concurrent access protection */
   2.336 + static sys_sem_t mem_sem;
   2.337 + 
   2.338 ++#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
   2.339 ++
   2.340 ++static volatile u8_t mem_free_count;
   2.341 ++
   2.342 ++/* Allow mem_free from other (e.g. interrupt) context */
   2.343 ++#define LWIP_MEM_FREE_DECL_PROTECT()  SYS_ARCH_DECL_PROTECT(lev_free)
   2.344 ++#define LWIP_MEM_FREE_PROTECT()       SYS_ARCH_PROTECT(lev_free)
   2.345 ++#define LWIP_MEM_FREE_UNPROTECT()     SYS_ARCH_UNPROTECT(lev_free)
   2.346 ++#define LWIP_MEM_ALLOC_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_alloc)
   2.347 ++#define LWIP_MEM_ALLOC_PROTECT()      SYS_ARCH_PROTECT(lev_alloc)
   2.348 ++#define LWIP_MEM_ALLOC_UNPROTECT()    SYS_ARCH_UNPROTECT(lev_alloc)
   2.349 ++
   2.350 ++#else /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
   2.351 ++
   2.352 ++/* Protect the heap only by using a semaphore */
   2.353 ++#define LWIP_MEM_FREE_DECL_PROTECT()
   2.354 ++#define LWIP_MEM_FREE_PROTECT()    sys_arch_sem_wait(mem_sem, 0)
   2.355 ++#define LWIP_MEM_FREE_UNPROTECT()  sys_sem_signal(mem_sem)
   2.356 ++/* mem_malloc is protected using semaphore AND LWIP_MEM_ALLOC_PROTECT */
   2.357 ++#define LWIP_MEM_ALLOC_DECL_PROTECT()
   2.358 ++#define LWIP_MEM_ALLOC_PROTECT()
   2.359 ++#define LWIP_MEM_ALLOC_UNPROTECT()
   2.360 ++
   2.361 ++#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
   2.362 ++
   2.363 ++
   2.364 + /**
   2.365 +  * "Plug holes" by combining adjacent empty struct mems.
   2.366 +  * After this function is through, there should not exist
   2.367 +@@ -255,9 +282,7 @@ mem_init(void)
   2.368 +   /* initialize the lowest-free pointer to the start of the heap */
   2.369 +   lfree = (struct mem *)ram;
   2.370 + 
   2.371 +-#if MEM_STATS
   2.372 +-  lwip_stats.mem.avail = MEM_SIZE_ALIGNED;
   2.373 +-#endif /* MEM_STATS */
   2.374 ++  MEM_STATS_AVAIL(avail, MEM_SIZE_ALIGNED);
   2.375 + }
   2.376 + 
   2.377 + /**
   2.378 +@@ -270,6 +295,7 @@ void
   2.379 + mem_free(void *rmem)
   2.380 + {
   2.381 +   struct mem *mem;
   2.382 ++  LWIP_MEM_FREE_DECL_PROTECT();
   2.383 + 
   2.384 +   if (rmem == NULL) {
   2.385 +     LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | 2, ("mem_free(p == NULL) was called.\n"));
   2.386 +@@ -277,20 +303,20 @@ mem_free(void *rmem)
   2.387 +   }
   2.388 +   LWIP_ASSERT("mem_free: sanity check alignment", (((mem_ptr_t)rmem) & (MEM_ALIGNMENT-1)) == 0);
   2.389 + 
   2.390 +-  /* protect the heap from concurrent access */
   2.391 +-  sys_arch_sem_wait(mem_sem, 0);
   2.392 +-
   2.393 +   LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
   2.394 +     (u8_t *)rmem < (u8_t *)ram_end);
   2.395 + 
   2.396 +   if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
   2.397 ++    SYS_ARCH_DECL_PROTECT(lev);
   2.398 +     LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_free: illegal memory\n"));
   2.399 +-#if MEM_STATS
   2.400 +-    ++lwip_stats.mem.err;
   2.401 +-#endif /* MEM_STATS */
   2.402 +-    sys_sem_signal(mem_sem);
   2.403 ++    /* protect mem stats from concurrent access */
   2.404 ++    SYS_ARCH_PROTECT(lev);
   2.405 ++    MEM_STATS_INC(illegal);
   2.406 ++    SYS_ARCH_UNPROTECT(lev);
   2.407 +     return;
   2.408 +   }
   2.409 ++  /* protect the heap from concurrent access */
   2.410 ++  LWIP_MEM_FREE_PROTECT();
   2.411 +   /* Get the corresponding struct mem ... */
   2.412 +   mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
   2.413 +   /* ... which has to be in a used state ... */
   2.414 +@@ -303,13 +329,14 @@ mem_free(void *rmem)
   2.415 +     lfree = mem;
   2.416 +   }
   2.417 + 
   2.418 +-#if MEM_STATS
   2.419 +-  lwip_stats.mem.used -= mem->next - ((u8_t *)mem - ram);
   2.420 +-#endif /* MEM_STATS */
   2.421 ++  MEM_STATS_DEC_USED(used, mem->next - ((u8_t *)mem - ram));
   2.422 + 
   2.423 +   /* finally, see if prev or next are free also */
   2.424 +   plug_holes(mem);
   2.425 +-  sys_sem_signal(mem_sem);
   2.426 ++#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
   2.427 ++  mem_free_count = 1;
   2.428 ++#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
   2.429 ++  LWIP_MEM_FREE_UNPROTECT();
   2.430 + }
   2.431 + 
   2.432 + /**
   2.433 +@@ -321,6 +348,8 @@ mem_free(void *rmem)
   2.434 +  * @param newsize required size after shrinking (needs to be smaller than or
   2.435 +  *                equal to the previous size)
   2.436 +  * @return for compatibility reasons: is always == rmem, at the moment
   2.437 ++ *         or NULL if newsize is > old size, in which case rmem is NOT touched
   2.438 ++ *         or freed!
   2.439 +  */
   2.440 + void *
   2.441 + mem_realloc(void *rmem, mem_size_t newsize)
   2.442 +@@ -328,6 +357,8 @@ mem_realloc(void *rmem, mem_size_t newsi
   2.443 +   mem_size_t size;
   2.444 +   mem_size_t ptr, ptr2;
   2.445 +   struct mem *mem, *mem2;
   2.446 ++  /* use the FREE_PROTECT here: it protects with sem OR SYS_ARCH_PROTECT */
   2.447 ++  LWIP_MEM_FREE_DECL_PROTECT();
   2.448 + 
   2.449 +   /* Expand the size of the allocated memory region so that we can
   2.450 +      adjust for alignment. */
   2.451 +@@ -346,7 +377,12 @@ mem_realloc(void *rmem, mem_size_t newsi
   2.452 +    (u8_t *)rmem < (u8_t *)ram_end);
   2.453 + 
   2.454 +   if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
   2.455 ++    SYS_ARCH_DECL_PROTECT(lev);
   2.456 +     LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_realloc: illegal memory\n"));
   2.457 ++    /* protect mem stats from concurrent access */
   2.458 ++    SYS_ARCH_PROTECT(lev);
   2.459 ++    MEM_STATS_INC(illegal);
   2.460 ++    SYS_ARCH_UNPROTECT(lev);
   2.461 +     return rmem;
   2.462 +   }
   2.463 +   /* Get the corresponding struct mem ... */
   2.464 +@@ -366,11 +402,9 @@ mem_realloc(void *rmem, mem_size_t newsi
   2.465 +   }
   2.466 + 
   2.467 +   /* protect the heap from concurrent access */
   2.468 +-  sys_arch_sem_wait(mem_sem, 0);
   2.469 ++  LWIP_MEM_FREE_PROTECT();
   2.470 + 
   2.471 +-#if MEM_STATS
   2.472 +-  lwip_stats.mem.used -= (size - newsize);
   2.473 +-#endif /* MEM_STATS */
   2.474 ++  MEM_STATS_DEC_USED(used, (size - newsize));
   2.475 + 
   2.476 +   mem2 = (struct mem *)&ram[mem->next];
   2.477 +   if(mem2->used == 0) {
   2.478 +@@ -426,7 +460,10 @@ mem_realloc(void *rmem, mem_size_t newsi
   2.479 +     -> don't do anyhting. 
   2.480 +     -> the remaining space stays unused since it is too small
   2.481 +   } */
   2.482 +-  sys_sem_signal(mem_sem);
   2.483 ++#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
   2.484 ++  mem_free_count = 1;
   2.485 ++#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
   2.486 ++  LWIP_MEM_FREE_UNPROTECT();
   2.487 +   return rmem;
   2.488 + }
   2.489 + 
   2.490 +@@ -444,6 +481,10 @@ mem_malloc(mem_size_t size)
   2.491 + {
   2.492 +   mem_size_t ptr, ptr2;
   2.493 +   struct mem *mem, *mem2;
   2.494 ++#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
   2.495 ++  u8_t local_mem_free_count = 0;
   2.496 ++#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
   2.497 ++  LWIP_MEM_ALLOC_DECL_PROTECT();
   2.498 + 
   2.499 +   if (size == 0) {
   2.500 +     return NULL;
   2.501 +@@ -464,88 +505,101 @@ mem_malloc(mem_size_t size)
   2.502 + 
   2.503 +   /* protect the heap from concurrent access */
   2.504 +   sys_arch_sem_wait(mem_sem, 0);
   2.505 ++  LWIP_MEM_ALLOC_PROTECT();
   2.506 ++#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
   2.507 ++  /* run as long as a mem_free disturbed mem_malloc */
   2.508 ++  do {
   2.509 ++    local_mem_free_count = 0;
   2.510 ++#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
   2.511 ++
   2.512 ++    /* Scan through the heap searching for a free block that is big enough,
   2.513 ++     * beginning with the lowest free block.
   2.514 ++     */
   2.515 ++    for (ptr = (u8_t *)lfree - ram; ptr < MEM_SIZE_ALIGNED - size;
   2.516 ++         ptr = ((struct mem *)&ram[ptr])->next) {
   2.517 ++      mem = (struct mem *)&ram[ptr];
   2.518 ++#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
   2.519 ++      mem_free_count = 0;
   2.520 ++      LWIP_MEM_ALLOC_UNPROTECT();
   2.521 ++      /* allow mem_free to run */
   2.522 ++      LWIP_MEM_ALLOC_PROTECT();
   2.523 ++      if (mem_free_count != 0) {
   2.524 ++        local_mem_free_count = mem_free_count;
   2.525 ++      }
   2.526 ++      mem_free_count = 0;
   2.527 ++#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
   2.528 + 
   2.529 +-  /* Scan through the heap searching for a free block that is big enough,
   2.530 +-   * beginning with the lowest free block.
   2.531 +-   */
   2.532 +-  for (ptr = (u8_t *)lfree - ram; ptr < MEM_SIZE_ALIGNED - size;
   2.533 +-       ptr = ((struct mem *)&ram[ptr])->next) {
   2.534 +-    mem = (struct mem *)&ram[ptr];
   2.535 +-
   2.536 +-    if ((!mem->used) &&
   2.537 +-        (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) {
   2.538 +-      /* mem is not used and at least perfect fit is possible:
   2.539 +-       * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */
   2.540 +-
   2.541 +-      if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) {
   2.542 +-        /* (in addition to the above, we test if another struct mem (SIZEOF_STRUCT_MEM) containing
   2.543 +-         * at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem')
   2.544 +-         * -> split large block, create empty remainder,
   2.545 +-         * remainder must be large enough to contain MIN_SIZE_ALIGNED data: if
   2.546 +-         * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size,
   2.547 +-         * struct mem would fit in but no data between mem2 and mem2->next
   2.548 +-         * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty
   2.549 +-         *       region that couldn't hold data, but when mem->next gets freed,
   2.550 +-         *       the 2 regions would be combined, resulting in more free memory
   2.551 +-         */
   2.552 +-        ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
   2.553 +-        /* create mem2 struct */
   2.554 +-        mem2 = (struct mem *)&ram[ptr2];
   2.555 +-        mem2->used = 0;
   2.556 +-        mem2->next = mem->next;
   2.557 +-        mem2->prev = ptr;
   2.558 +-        /* and insert it between mem and mem->next */
   2.559 +-        mem->next = ptr2;
   2.560 +-        mem->used = 1;
   2.561 +-
   2.562 +-        if (mem2->next != MEM_SIZE_ALIGNED) {
   2.563 +-          ((struct mem *)&ram[mem2->next])->prev = ptr2;
   2.564 +-        }
   2.565 +-#if MEM_STATS
   2.566 +-        lwip_stats.mem.used += (size + SIZEOF_STRUCT_MEM);
   2.567 +-        if (lwip_stats.mem.max < lwip_stats.mem.used) {
   2.568 +-          lwip_stats.mem.max = lwip_stats.mem.used;
   2.569 ++      if ((!mem->used) &&
   2.570 ++          (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) {
   2.571 ++        /* mem is not used and at least perfect fit is possible:
   2.572 ++         * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */
   2.573 ++
   2.574 ++        if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) {
   2.575 ++          /* (in addition to the above, we test if another struct mem (SIZEOF_STRUCT_MEM) containing
   2.576 ++           * at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem')
   2.577 ++           * -> split large block, create empty remainder,
   2.578 ++           * remainder must be large enough to contain MIN_SIZE_ALIGNED data: if
   2.579 ++           * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size,
   2.580 ++           * struct mem would fit in but no data between mem2 and mem2->next
   2.581 ++           * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty
   2.582 ++           *       region that couldn't hold data, but when mem->next gets freed,
   2.583 ++           *       the 2 regions would be combined, resulting in more free memory
   2.584 ++           */
   2.585 ++          ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
   2.586 ++          /* create mem2 struct */
   2.587 ++          mem2 = (struct mem *)&ram[ptr2];
   2.588 ++          mem2->used = 0;
   2.589 ++          mem2->next = mem->next;
   2.590 ++          mem2->prev = ptr;
   2.591 ++          /* and insert it between mem and mem->next */
   2.592 ++          mem->next = ptr2;
   2.593 ++          mem->used = 1;
   2.594 ++
   2.595 ++          if (mem2->next != MEM_SIZE_ALIGNED) {
   2.596 ++            ((struct mem *)&ram[mem2->next])->prev = ptr2;
   2.597 ++          }
   2.598 ++          MEM_STATS_INC_USED(used, (size + SIZEOF_STRUCT_MEM));
   2.599 ++        } else {
   2.600 ++          /* (a mem2 struct does no fit into the user data space of mem and mem->next will always
   2.601 ++           * be used at this point: if not we have 2 unused structs in a row, plug_holes should have
   2.602 ++           * take care of this).
   2.603 ++           * -> near fit or excact fit: do not split, no mem2 creation
   2.604 ++           * also can't move mem->next directly behind mem, since mem->next
   2.605 ++           * will always be used at this point!
   2.606 ++           */
   2.607 ++          mem->used = 1;
   2.608 ++          MEM_STATS_INC_USED(used, mem->next - ((u8_t *)mem - ram));
   2.609 +         }
   2.610 +-#endif /* MEM_STATS */
   2.611 +-      } else {
   2.612 +-        /* (a mem2 struct does no fit into the user data space of mem and mem->next will always
   2.613 +-         * be used at this point: if not we have 2 unused structs in a row, plug_holes should have
   2.614 +-         * take care of this).
   2.615 +-         * -> near fit or excact fit: do not split, no mem2 creation
   2.616 +-         * also can't move mem->next directly behind mem, since mem->next
   2.617 +-         * will always be used at this point!
   2.618 +-         */
   2.619 +-        mem->used = 1;
   2.620 +-#if MEM_STATS
   2.621 +-        lwip_stats.mem.used += mem->next - ((u8_t *)mem - ram);
   2.622 +-        if (lwip_stats.mem.max < lwip_stats.mem.used) {
   2.623 +-          lwip_stats.mem.max = lwip_stats.mem.used;
   2.624 +-        }
   2.625 +-#endif /* MEM_STATS */
   2.626 +-      }
   2.627 + 
   2.628 +-      if (mem == lfree) {
   2.629 +-        /* Find next free block after mem and update lowest free pointer */
   2.630 +-        while (lfree->used && lfree != ram_end) {
   2.631 +-          lfree = (struct mem *)&ram[lfree->next];
   2.632 ++        if (mem == lfree) {
   2.633 ++          /* Find next free block after mem and update lowest free pointer */
   2.634 ++          while (lfree->used && lfree != ram_end) {
   2.635 ++            LWIP_MEM_ALLOC_UNPROTECT();
   2.636 ++            /* prevent high interrupt latency... */
   2.637 ++            LWIP_MEM_ALLOC_PROTECT();
   2.638 ++            lfree = (struct mem *)&ram[lfree->next];
   2.639 ++          }
   2.640 ++          LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used)));
   2.641 +         }
   2.642 +-        LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used)));
   2.643 +-      }
   2.644 +-      sys_sem_signal(mem_sem);
   2.645 +-      LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
   2.646 +-       (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);
   2.647 +-      LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
   2.648 +-       (unsigned long)((u8_t *)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
   2.649 +-      LWIP_ASSERT("mem_malloc: sanity check alignment",
   2.650 +-        (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0);
   2.651 ++        LWIP_MEM_ALLOC_UNPROTECT();
   2.652 ++        sys_sem_signal(mem_sem);
   2.653 ++        LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
   2.654 ++         (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);
   2.655 ++        LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
   2.656 ++         (unsigned long)((u8_t *)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
   2.657 ++        LWIP_ASSERT("mem_malloc: sanity check alignment",
   2.658 ++          (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0);
   2.659 + 
   2.660 +-      return (u8_t *)mem + SIZEOF_STRUCT_MEM;
   2.661 ++        return (u8_t *)mem + SIZEOF_STRUCT_MEM;
   2.662 ++      }
   2.663 +     }
   2.664 +-  }
   2.665 ++#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
   2.666 ++    /* if we got interrupted by a mem_free, try again */
   2.667 ++  } while(local_mem_free_count != 0);
   2.668 ++#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
   2.669 +   LWIP_DEBUGF(MEM_DEBUG | 2, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size));
   2.670 +-#if MEM_STATS
   2.671 +-  ++lwip_stats.mem.err;
   2.672 +-#endif /* MEM_STATS */
   2.673 ++  MEM_STATS_INC(err);
   2.674 ++  LWIP_MEM_ALLOC_UNPROTECT();
   2.675 +   sys_sem_signal(mem_sem);
   2.676 +   return NULL;
   2.677 + }
   2.678 +Index: src/core/memp.c
   2.679 +===================================================================
   2.680 +RCS file: /sources/lwip/lwip/src/core/memp.c,v
   2.681 +retrieving revision 1.55
   2.682 +retrieving revision 1.56
   2.683 +diff -u -p -r1.55 -r1.56
   2.684 +--- src/core/memp.c	25 Nov 2007 10:43:28 -0000	1.55
   2.685 ++++ src/core/memp.c	27 Jun 2008 18:37:54 -0000	1.56
   2.686 +@@ -252,13 +252,12 @@ memp_init(void)
   2.687 +   struct memp *memp;
   2.688 +   u16_t i, j;
   2.689 + 
   2.690 +-#if MEMP_STATS
   2.691 +   for (i = 0; i < MEMP_MAX; ++i) {
   2.692 +-    lwip_stats.memp[i].used = lwip_stats.memp[i].max =
   2.693 +-      lwip_stats.memp[i].err = 0;
   2.694 +-    lwip_stats.memp[i].avail = memp_num[i];
   2.695 ++    MEMP_STATS_AVAIL(used, i, 0);
   2.696 ++    MEMP_STATS_AVAIL(max, i, 0);
   2.697 ++    MEMP_STATS_AVAIL(err, i, 0);
   2.698 ++    MEMP_STATS_AVAIL(avail, i, memp_num[i]);
   2.699 +   }
   2.700 +-#endif /* MEMP_STATS */
   2.701 + 
   2.702 +   memp = LWIP_MEM_ALIGN(memp_memory);
   2.703 +   /* for every pool: */
   2.704 +@@ -315,20 +314,13 @@ memp_malloc_fn(memp_t type, const char* 
   2.705 +     memp->file = file;
   2.706 +     memp->line = line;
   2.707 + #endif /* MEMP_OVERFLOW_CHECK */
   2.708 +-#if MEMP_STATS
   2.709 +-    ++lwip_stats.memp[type].used;
   2.710 +-    if (lwip_stats.memp[type].used > lwip_stats.memp[type].max) {
   2.711 +-      lwip_stats.memp[type].max = lwip_stats.memp[type].used;
   2.712 +-    }
   2.713 +-#endif /* MEMP_STATS */
   2.714 ++    MEMP_STATS_INC_USED(used, type);
   2.715 +     LWIP_ASSERT("memp_malloc: memp properly aligned",
   2.716 +                 ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0);
   2.717 +     memp = (struct memp*)((u8_t*)memp + MEMP_SIZE);
   2.718 +   } else {
   2.719 +     LWIP_DEBUGF(MEMP_DEBUG | 2, ("memp_malloc: out of memory in pool %s\n", memp_desc[type]));
   2.720 +-#if MEMP_STATS
   2.721 +-    ++lwip_stats.memp[type].err;
   2.722 +-#endif /* MEMP_STATS */
   2.723 ++    MEMP_STATS_INC(err, type);
   2.724 +   }
   2.725 + 
   2.726 +   SYS_ARCH_UNPROTECT(old_level);
   2.727 +@@ -365,9 +357,7 @@ memp_free(memp_t type, void *mem)
   2.728 + #endif /* MEMP_OVERFLOW_CHECK >= 2 */
   2.729 + #endif /* MEMP_OVERFLOW_CHECK */
   2.730 + 
   2.731 +-#if MEMP_STATS
   2.732 +-  lwip_stats.memp[type].used--; 
   2.733 +-#endif /* MEMP_STATS */
   2.734 ++  MEMP_STATS_DEC(used, type); 
   2.735 +   
   2.736 +   memp->next = memp_tab[type]; 
   2.737 +   memp_tab[type] = memp;
   2.738 +Index: src/core/netif.c
   2.739 +===================================================================
   2.740 +RCS file: /sources/lwip/lwip/src/core/netif.c,v
   2.741 +retrieving revision 1.65
   2.742 +retrieving revision 1.68
   2.743 +diff -u -p -r1.65 -r1.68
   2.744 +--- src/core/netif.c	9 Oct 2007 20:00:55 -0000	1.65
   2.745 ++++ src/core/netif.c	19 Jun 2008 16:27:18 -0000	1.68
   2.746 +@@ -45,6 +45,12 @@
   2.747 + #include "lwip/snmp.h"
   2.748 + #include "lwip/igmp.h"
   2.749 + #include "netif/etharp.h"
   2.750 ++#if ENABLE_LOOPBACK
   2.751 ++#include "lwip/sys.h"
   2.752 ++#if LWIP_NETIF_LOOPBACK_MULTITHREADING
   2.753 ++#include "lwip/tcpip.h"
   2.754 ++#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
   2.755 ++#endif /* ENABLE_LOOPBACK */
   2.756 + 
   2.757 + #if LWIP_NETIF_STATUS_CALLBACK
   2.758 + #define NETIF_STATUS_CALLBACK(n) { if (n->status_callback) (n->status_callback)(n); }
   2.759 +@@ -106,6 +112,10 @@ netif_add(struct netif *netif, struct ip
   2.760 + #if LWIP_IGMP
   2.761 +   netif->igmp_mac_filter = NULL;
   2.762 + #endif /* LWIP_IGMP */
   2.763 ++#if ENABLE_LOOPBACK
   2.764 ++  netif->loop_first = NULL;
   2.765 ++  netif->loop_last = NULL;
   2.766 ++#endif /* ENABLE_LOOPBACK */
   2.767 + 
   2.768 +   /* remember netif specific state information data */
   2.769 +   netif->state = state;
   2.770 +@@ -114,6 +124,9 @@ netif_add(struct netif *netif, struct ip
   2.771 + #if LWIP_NETIF_HWADDRHINT
   2.772 +   netif->addr_hint = NULL;
   2.773 + #endif /* LWIP_NETIF_HWADDRHINT*/
   2.774 ++#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS
   2.775 ++  netif->loop_cnt_current = 0;
   2.776 ++#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */
   2.777 + 
   2.778 +   netif_set_addr(netif, ipaddr, netmask, gw);
   2.779 + 
   2.780 +@@ -493,7 +506,158 @@ u8_t netif_is_link_up(struct netif *neti
   2.781 +  */
   2.782 + void netif_set_link_callback(struct netif *netif, void (* link_callback)(struct netif *netif ))
   2.783 + {
   2.784 +-    if ( netif )
   2.785 +-        netif->link_callback = link_callback;
   2.786 ++  if (netif) {
   2.787 ++    netif->link_callback = link_callback;
   2.788 ++  }
   2.789 + }
   2.790 + #endif /* LWIP_NETIF_LINK_CALLBACK */
   2.791 ++
   2.792 ++#if ENABLE_LOOPBACK
   2.793 ++/**
   2.794 ++ * Send an IP packet to be received on the same netif (loopif-like).
   2.795 ++ * The pbuf is simply copied and handed back to netif->input.
   2.796 ++ * In multithreaded mode, this is done directly since netif->input must put
   2.797 ++ * the packet on a queue.
   2.798 ++ * In callback mode, the packet is put on an internal queue and is fed to
   2.799 ++ * netif->input by netif_poll().
   2.800 ++ *
   2.801 ++ * @param netif the lwip network interface structure
   2.802 ++ * @param p the (IP) packet to 'send'
   2.803 ++ * @param ipaddr the ip address to send the packet to (not used)
   2.804 ++ * @return ERR_OK if the packet has been sent
   2.805 ++ *         ERR_MEM if the pbuf used to copy the packet couldn't be allocated
   2.806 ++ */
   2.807 ++err_t
   2.808 ++netif_loop_output(struct netif *netif, struct pbuf *p,
   2.809 ++       struct ip_addr *ipaddr)
   2.810 ++{
   2.811 ++  struct pbuf *r;
   2.812 ++  err_t err;
   2.813 ++  struct pbuf *last;
   2.814 ++#if LWIP_LOOPBACK_MAX_PBUFS
   2.815 ++  u8_t clen = 0;
   2.816 ++#endif /* LWIP_LOOPBACK_MAX_PBUFS */
   2.817 ++  SYS_ARCH_DECL_PROTECT(lev);
   2.818 ++  LWIP_UNUSED_ARG(ipaddr);
   2.819 ++
   2.820 ++  /* Allocate a new pbuf */
   2.821 ++  r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM);
   2.822 ++  if (r == NULL) {
   2.823 ++    return ERR_MEM;
   2.824 ++  }
   2.825 ++#if LWIP_LOOPBACK_MAX_PBUFS
   2.826 ++  clen = pbuf_clen(r);
   2.827 ++  /* check for overflow or too many pbuf on queue */
   2.828 ++  if(((netif->loop_cnt_current + clen) < netif->loop_cnt_current) ||
   2.829 ++    ((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) {
   2.830 ++      pbuf_free(r);
   2.831 ++      r = NULL;
   2.832 ++      return ERR_MEM;
   2.833 ++  }
   2.834 ++  netif->loop_cnt_current += clen;
   2.835 ++#endif /* LWIP_LOOPBACK_MAX_PBUFS */
   2.836 ++
   2.837 ++  /* Copy the whole pbuf queue p into the single pbuf r */
   2.838 ++  if ((err = pbuf_copy(r, p)) != ERR_OK) {
   2.839 ++    pbuf_free(r);
   2.840 ++    r = NULL;
   2.841 ++    return err;
   2.842 ++  }
   2.843 ++
   2.844 ++  /* Put the packet on a linked list which gets emptied through calling
   2.845 ++     netif_poll(). */
   2.846 ++
   2.847 ++  /* let last point to the last pbuf in chain r */
   2.848 ++  for (last = r; last->next != NULL; last = last->next);
   2.849 ++
   2.850 ++  SYS_ARCH_PROTECT(lev);
   2.851 ++  if(netif->loop_first != NULL) {
   2.852 ++    LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL);
   2.853 ++    netif->loop_last->next = r;
   2.854 ++    netif->loop_last = last;
   2.855 ++  } else {
   2.856 ++    netif->loop_first = r;
   2.857 ++    netif->loop_last = last;
   2.858 ++  }
   2.859 ++  SYS_ARCH_UNPROTECT(lev);
   2.860 ++
   2.861 ++#if LWIP_NETIF_LOOPBACK_MULTITHREADING
   2.862 ++  /* For multithreading environment, schedule a call to netif_poll */
   2.863 ++  tcpip_callback(netif_poll, netif);
   2.864 ++#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
   2.865 ++
   2.866 ++  return ERR_OK;
   2.867 ++}
   2.868 ++
   2.869 ++/**
   2.870 ++ * Call netif_poll() in the main loop of your application. This is to prevent
   2.871 ++ * reentering non-reentrant functions like tcp_input(). Packets passed to
   2.872 ++ * netif_loop_output() are put on a list that is passed to netif->input() by
   2.873 ++ * netif_poll().
   2.874 ++ */
   2.875 ++void
   2.876 ++netif_poll(struct netif *netif)
   2.877 ++{
   2.878 ++  struct pbuf *in;
   2.879 ++  SYS_ARCH_DECL_PROTECT(lev);
   2.880 ++
   2.881 ++  do {
   2.882 ++    /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */
   2.883 ++    SYS_ARCH_PROTECT(lev);
   2.884 ++    in = netif->loop_first;
   2.885 ++    if(in != NULL) {
   2.886 ++      struct pbuf *in_end = in;
   2.887 ++#if LWIP_LOOPBACK_MAX_PBUFS
   2.888 ++      u8_t clen = pbuf_clen(in);
   2.889 ++      /* adjust the number of pbufs on queue */
   2.890 ++      LWIP_ASSERT("netif->loop_cnt_current underflow",
   2.891 ++        ((netif->loop_cnt_current - clen) < netif->loop_cnt_current));
   2.892 ++      netif->loop_cnt_current -= clen;
   2.893 ++#endif /* LWIP_LOOPBACK_MAX_PBUFS */
   2.894 ++      while(in_end->len != in_end->tot_len) {
   2.895 ++        LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
   2.896 ++        in_end = in_end->next;
   2.897 ++      }
   2.898 ++      /* 'in_end' now points to the last pbuf from 'in' */
   2.899 ++      if(in_end == netif->loop_last) {
   2.900 ++        /* this was the last pbuf in the list */
   2.901 ++        netif->loop_first = netif->loop_last = NULL;
   2.902 ++      } else {
   2.903 ++        /* pop the pbuf off the list */
   2.904 ++        netif->loop_first = in_end->next;
   2.905 ++        LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL);
   2.906 ++      }
   2.907 ++      /* De-queue the pbuf from its successors on the 'loop_' list. */
   2.908 ++      in_end->next = NULL;
   2.909 ++    }
   2.910 ++    SYS_ARCH_UNPROTECT(lev);
   2.911 ++
   2.912 ++    if(in != NULL) {
   2.913 ++      /* loopback packets are always IP packets! */
   2.914 ++      if(ip_input(in, netif) != ERR_OK) {
   2.915 ++        pbuf_free(in);
   2.916 ++      }
   2.917 ++      /* Don't reference the packet any more! */
   2.918 ++      in = NULL;
   2.919 ++    }
   2.920 ++  /* go on while there is a packet on the list */
   2.921 ++  } while(netif->loop_first != NULL);
   2.922 ++}
   2.923 ++
   2.924 ++#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
   2.925 ++/**
   2.926 ++ * Calls netif_poll() for every netif on the netif_list.
   2.927 ++ */
   2.928 ++void
   2.929 ++netif_poll_all(void)
   2.930 ++{
   2.931 ++  struct netif *netif = netif_list;
   2.932 ++  /* loop through netifs */
   2.933 ++  while (netif != NULL) {
   2.934 ++    netif_poll(netif);
   2.935 ++    /* proceed to next network interface */
   2.936 ++    netif = netif->next;
   2.937 ++  }
   2.938 ++}
   2.939 ++#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
   2.940 ++#endif /* ENABLE_LOOPBACK */
   2.941 +Index: src/core/pbuf.c
   2.942 +===================================================================
   2.943 +RCS file: /sources/lwip/lwip/src/core/pbuf.c,v
   2.944 +retrieving revision 1.127
   2.945 +retrieving revision 1.128
   2.946 +diff -u -p -r1.127 -r1.128
   2.947 +--- src/core/pbuf.c	4 Mar 2008 16:37:46 -0000	1.127
   2.948 ++++ src/core/pbuf.c	1 Apr 2008 19:05:40 -0000	1.128
   2.949 +@@ -667,8 +667,8 @@ pbuf_dechain(struct pbuf *p)
   2.950 +  *
   2.951 +  * @note Only one packet is copied, no packet queue!
   2.952 +  *
   2.953 +- * @param p_to pbuf source of the copy
   2.954 +- * @param p_from pbuf destination of the copy
   2.955 ++ * @param p_to pbuf destination of the copy
   2.956 ++ * @param p_from pbuf source of the copy
   2.957 +  *
   2.958 +  * @return ERR_OK if pbuf was copied
   2.959 +  *         ERR_ARG if one of the pbufs is NULL or p_to is not big
   2.960 +Index: src/core/stats.c
   2.961 +===================================================================
   2.962 +RCS file: /sources/lwip/lwip/src/core/stats.c,v
   2.963 +retrieving revision 1.27
   2.964 +retrieving revision 1.28
   2.965 +diff -u -p -r1.27 -r1.28
   2.966 +--- src/core/stats.c	4 Mar 2008 16:31:32 -0000	1.27
   2.967 ++++ src/core/stats.c	27 Jun 2008 18:37:54 -0000	1.28
   2.968 +@@ -54,7 +54,6 @@ stats_display_proto(struct stats_proto *
   2.969 + {
   2.970 +   LWIP_PLATFORM_DIAG(("\n%s\n\t", name));
   2.971 +   LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", proto->xmit)); 
   2.972 +-  LWIP_PLATFORM_DIAG(("rexmit: %"STAT_COUNTER_F"\n\t", proto->rexmit)); 
   2.973 +   LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", proto->recv)); 
   2.974 +   LWIP_PLATFORM_DIAG(("fw: %"STAT_COUNTER_F"\n\t", proto->fw)); 
   2.975 +   LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", proto->drop)); 
   2.976 +@@ -68,6 +67,7 @@ stats_display_proto(struct stats_proto *
   2.977 +   LWIP_PLATFORM_DIAG(("cachehit: %"STAT_COUNTER_F"\n", proto->cachehit)); 
   2.978 + }
   2.979 + 
   2.980 ++#if IGMP_STATS
   2.981 + void
   2.982 + stats_display_igmp(struct stats_igmp *igmp)
   2.983 + {
   2.984 +@@ -82,7 +82,9 @@ stats_display_igmp(struct stats_igmp *ig
   2.985 +   LWIP_PLATFORM_DIAG(("report_rxed: %"STAT_COUNTER_F"\n\t", igmp->report_rxed)); 
   2.986 +   LWIP_PLATFORM_DIAG(("group_query_rxed: %"STAT_COUNTER_F"\n", igmp->group_query_rxed));
   2.987 + }
   2.988 ++#endif /* IGMP_STATS */
   2.989 + 
   2.990 ++#if MEM_STATS || MEMP_STATS
   2.991 + void
   2.992 + stats_display_mem(struct stats_mem *mem, char *name)
   2.993 + {
   2.994 +@@ -93,48 +95,53 @@ stats_display_mem(struct stats_mem *mem,
   2.995 +   LWIP_PLATFORM_DIAG(("err: %"U32_F"\n", (u32_t)mem->err));
   2.996 + }
   2.997 + 
   2.998 ++#if MEMP_STATS
   2.999 + void
  2.1000 +-stats_display(void)
  2.1001 ++stats_display_memp(struct stats_mem *mem, int index)
  2.1002 + {
  2.1003 +-#if MEMP_STATS
  2.1004 +-  s16_t i;
  2.1005 +   char * memp_names[] = {
  2.1006 + #define LWIP_MEMPOOL(name,num,size,desc) desc,
  2.1007 + #include "lwip/memp_std.h"
  2.1008 +   };
  2.1009 +-#endif
  2.1010 +-#if LINK_STATS
  2.1011 +-  stats_display_proto(&lwip_stats.link, "LINK");
  2.1012 +-#endif
  2.1013 +-#if ETHARP_STATS
  2.1014 +-  stats_display_proto(&lwip_stats.etharp, "ETHARP");
  2.1015 +-#endif
  2.1016 +-#if IPFRAG_STATS
  2.1017 +-  stats_display_proto(&lwip_stats.ip_frag, "IP_FRAG");
  2.1018 +-#endif
  2.1019 +-#if IP_STATS
  2.1020 +-  stats_display_proto(&lwip_stats.ip, "IP");
  2.1021 +-#endif
  2.1022 +-#if ICMP_STATS
  2.1023 +-  stats_display_proto(&lwip_stats.icmp, "ICMP");
  2.1024 +-#endif
  2.1025 +-#if IGMP_STATS
  2.1026 +-  stats_display_igmp(&lwip_stats.igmp);
  2.1027 +-#endif
  2.1028 +-#if UDP_STATS
  2.1029 +-  stats_display_proto(&lwip_stats.udp, "UDP");
  2.1030 +-#endif
  2.1031 +-#if TCP_STATS
  2.1032 +-  stats_display_proto(&lwip_stats.tcp, "TCP");
  2.1033 +-#endif
  2.1034 +-#if MEM_STATS
  2.1035 +-  stats_display_mem(&lwip_stats.mem, "HEAP");
  2.1036 +-#endif
  2.1037 +-#if MEMP_STATS
  2.1038 ++  if(index < MEMP_MAX) {
  2.1039 ++    stats_display_mem(mem, memp_names[index]);
  2.1040 ++  }
  2.1041 ++}
  2.1042 ++#endif /* MEMP_STATS */
  2.1043 ++#endif /* MEM_STATS || MEMP_STATS */
  2.1044 ++
  2.1045 ++#if SYS_STATS
  2.1046 ++void
  2.1047 ++stats_display_sys(struct stats_sys *sys)
  2.1048 ++{
  2.1049 ++  LWIP_PLATFORM_DIAG(("\nSYS\n\t"));
  2.1050 ++  LWIP_PLATFORM_DIAG(("sem.used: %"U32_F"\n\t", (u32_t)sys->sem.used)); 
  2.1051 ++  LWIP_PLATFORM_DIAG(("sem.max:  %"U32_F"\n\t", (u32_t)sys->sem.max)); 
  2.1052 ++  LWIP_PLATFORM_DIAG(("sem.err:  %"U32_F"\n\t", (u32_t)sys->sem.err)); 
  2.1053 ++  LWIP_PLATFORM_DIAG(("mbox.used: %"U32_F"\n\t", (u32_t)sys->mbox.used)); 
  2.1054 ++  LWIP_PLATFORM_DIAG(("mbox.max:  %"U32_F"\n\t", (u32_t)sys->mbox.max)); 
  2.1055 ++  LWIP_PLATFORM_DIAG(("mbox.err:  %"U32_F"\n\t", (u32_t)sys->mbox.err)); 
  2.1056 ++}
  2.1057 ++#endif /* SYS_STATS */
  2.1058 ++
  2.1059 ++void
  2.1060 ++stats_display(void)
  2.1061 ++{
  2.1062 ++  s16_t i;
  2.1063 ++
  2.1064 ++  LINK_STATS_DISPLAY();
  2.1065 ++  ETHARP_STATS_DISPLAY();
  2.1066 ++  IPFRAG_STATS_DISPLAY();
  2.1067 ++  IP_STATS_DISPLAY();
  2.1068 ++  IGMP_STATS_DISPLAY();
  2.1069 ++  ICMP_STATS_DISPLAY();
  2.1070 ++  UDP_STATS_DISPLAY();
  2.1071 ++  TCP_STATS_DISPLAY();
  2.1072 ++  MEM_STATS_DISPLAY();
  2.1073 +   for (i = 0; i < MEMP_MAX; i++) {
  2.1074 +-    stats_display_mem(&lwip_stats.memp[i], memp_names[i]);
  2.1075 ++    MEMP_STATS_DISPLAY(i);
  2.1076 +   }
  2.1077 +-#endif
  2.1078 ++  SYS_STATS_DISPLAY();
  2.1079 + }
  2.1080 + #endif /* LWIP_STATS_DISPLAY */
  2.1081 + 
  2.1082 +Index: src/core/sys.c
  2.1083 +===================================================================
  2.1084 +RCS file: /sources/lwip/lwip/src/core/sys.c,v
  2.1085 +retrieving revision 1.32
  2.1086 +retrieving revision 1.33
  2.1087 +diff -u -p -r1.32 -r1.33
  2.1088 +--- src/core/sys.c	25 Nov 2007 13:57:05 -0000	1.32
  2.1089 ++++ src/core/sys.c	16 Jul 2008 20:36:12 -0000	1.33
  2.1090 +@@ -65,7 +65,7 @@ struct sswt_cb
  2.1091 + void
  2.1092 + sys_mbox_fetch(sys_mbox_t mbox, void **msg)
  2.1093 + {
  2.1094 +-  u32_t time;
  2.1095 ++  u32_t time_needed;
  2.1096 +   struct sys_timeouts *timeouts;
  2.1097 +   struct sys_timeo *tmptimeout;
  2.1098 +   sys_timeout_handler h;
  2.1099 +@@ -76,18 +76,18 @@ sys_mbox_fetch(sys_mbox_t mbox, void **m
  2.1100 + 
  2.1101 +   if (!timeouts || !timeouts->next) {
  2.1102 +     UNLOCK_TCPIP_CORE();
  2.1103 +-    time = sys_arch_mbox_fetch(mbox, msg, 0);
  2.1104 ++    time_needed = sys_arch_mbox_fetch(mbox, msg, 0);
  2.1105 +     LOCK_TCPIP_CORE();
  2.1106 +   } else {
  2.1107 +     if (timeouts->next->time > 0) {
  2.1108 +       UNLOCK_TCPIP_CORE();
  2.1109 +-      time = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time);
  2.1110 ++      time_needed = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time);
  2.1111 +       LOCK_TCPIP_CORE();
  2.1112 +     } else {
  2.1113 +-      time = SYS_ARCH_TIMEOUT;
  2.1114 ++      time_needed = SYS_ARCH_TIMEOUT;
  2.1115 +     }
  2.1116 + 
  2.1117 +-    if (time == SYS_ARCH_TIMEOUT) {
  2.1118 ++    if (time_needed == SYS_ARCH_TIMEOUT) {
  2.1119 +       /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
  2.1120 +          could be fetched. We should now call the timeout handler and
  2.1121 +          deallocate the memory allocated for the timeout. */
  2.1122 +@@ -107,8 +107,8 @@ sys_mbox_fetch(sys_mbox_t mbox, void **m
  2.1123 +       /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout
  2.1124 +          occured. The time variable is set to the number of
  2.1125 +          milliseconds we waited for the message. */
  2.1126 +-      if (time < timeouts->next->time) {
  2.1127 +-        timeouts->next->time -= time;
  2.1128 ++      if (time_needed < timeouts->next->time) {
  2.1129 ++        timeouts->next->time -= time_needed;
  2.1130 +       } else {
  2.1131 +         timeouts->next->time = 0;
  2.1132 +       }
  2.1133 +@@ -125,7 +125,7 @@ sys_mbox_fetch(sys_mbox_t mbox, void **m
  2.1134 + void
  2.1135 + sys_sem_wait(sys_sem_t sem)
  2.1136 + {
  2.1137 +-  u32_t time;
  2.1138 ++  u32_t time_needed;
  2.1139 +   struct sys_timeouts *timeouts;
  2.1140 +   struct sys_timeo *tmptimeout;
  2.1141 +   sys_timeout_handler h;
  2.1142 +@@ -139,12 +139,12 @@ sys_sem_wait(sys_sem_t sem)
  2.1143 +     sys_arch_sem_wait(sem, 0);
  2.1144 +   } else {
  2.1145 +     if (timeouts->next->time > 0) {
  2.1146 +-      time = sys_arch_sem_wait(sem, timeouts->next->time);
  2.1147 ++      time_needed = sys_arch_sem_wait(sem, timeouts->next->time);
  2.1148 +     } else {
  2.1149 +-      time = SYS_ARCH_TIMEOUT;
  2.1150 ++      time_needed = SYS_ARCH_TIMEOUT;
  2.1151 +     }
  2.1152 + 
  2.1153 +-    if (time == SYS_ARCH_TIMEOUT) {
  2.1154 ++    if (time_needed == SYS_ARCH_TIMEOUT) {
  2.1155 +       /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
  2.1156 +         could be fetched. We should now call the timeout handler and
  2.1157 +         deallocate the memory allocated for the timeout. */
  2.1158 +@@ -164,8 +164,8 @@ sys_sem_wait(sys_sem_t sem)
  2.1159 +       /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout
  2.1160 +          occured. The time variable is set to the number of
  2.1161 +          milliseconds we waited for the message. */
  2.1162 +-      if (time < timeouts->next->time) {
  2.1163 +-        timeouts->next->time -= time;
  2.1164 ++      if (time_needed < timeouts->next->time) {
  2.1165 ++        timeouts->next->time -= time_needed;
  2.1166 +       } else {
  2.1167 +         timeouts->next->time = 0;
  2.1168 +       }
  2.1169 +Index: src/core/tcp.c
  2.1170 +===================================================================
  2.1171 +RCS file: /sources/lwip/lwip/src/core/tcp.c,v
  2.1172 +retrieving revision 1.85
  2.1173 +retrieving revision 1.86
  2.1174 +diff -u -p -r1.85 -r1.86
  2.1175 +--- src/core/tcp.c	22 Jan 2008 21:15:15 -0000	1.85
  2.1176 ++++ src/core/tcp.c	26 Mar 2008 11:57:13 -0000	1.86
  2.1177 +@@ -509,7 +509,8 @@ tcp_connect(struct tcp_pcb *pcb, struct 
  2.1178 +   pcb->rcv_wnd = TCP_WND;
  2.1179 +   pcb->rcv_ann_wnd = TCP_WND;
  2.1180 +   pcb->snd_wnd = TCP_WND;
  2.1181 +-  /* The send MSS is updated when an MSS option is received. */
  2.1182 ++  /* As initial send MSS, we use TCP_MSS but limit it to 536.
  2.1183 ++     The send MSS is updated when an MSS option is received. */
  2.1184 +   pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;
  2.1185 + #if TCP_CALCULATE_EFF_SEND_MSS
  2.1186 +   pcb->mss = tcp_eff_send_mss(pcb->mss, ipaddr);
  2.1187 +@@ -991,7 +992,8 @@ tcp_alloc(u8_t prio)
  2.1188 +     pcb->rcv_ann_wnd = TCP_WND;
  2.1189 +     pcb->tos = 0;
  2.1190 +     pcb->ttl = TCP_TTL;
  2.1191 +-    /* The send MSS is updated when an MSS option is received. */
  2.1192 ++    /* As initial send MSS, we use TCP_MSS but limit it to 536.
  2.1193 ++       The send MSS is updated when an MSS option is received. */
  2.1194 +     pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;
  2.1195 +     pcb->rto = 3000 / TCP_SLOW_INTERVAL;
  2.1196 +     pcb->sa = 0;
  2.1197 +Index: src/core/tcp_in.c
  2.1198 +===================================================================
  2.1199 +RCS file: /sources/lwip/lwip/src/core/tcp_in.c,v
  2.1200 +retrieving revision 1.97
  2.1201 +retrieving revision 1.100
  2.1202 +diff -u -p -r1.97 -r1.100
  2.1203 +--- src/core/tcp_in.c	22 Jan 2008 21:15:15 -0000	1.97
  2.1204 ++++ src/core/tcp_in.c	24 Jun 2008 15:46:39 -0000	1.100
  2.1205 +@@ -511,7 +511,7 @@ tcp_process(struct tcp_pcb *pcb)
  2.1206 +       }
  2.1207 +     } else {
  2.1208 +       if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, 
  2.1209 +-                          pcb->rcv_nxt+pcb->rcv_ann_wnd)) {
  2.1210 ++                          pcb->rcv_nxt+pcb->rcv_wnd)) {
  2.1211 +         acceptable = 1;
  2.1212 +       }
  2.1213 +     }
  2.1214 +@@ -1038,7 +1038,7 @@ tcp_receive(struct tcp_pcb *pcb)
  2.1215 +        and below rcv_nxt + rcv_wnd) in order to be further
  2.1216 +        processed. */
  2.1217 +     if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, 
  2.1218 +-                        pcb->rcv_nxt + pcb->rcv_ann_wnd - 1)){
  2.1219 ++                        pcb->rcv_nxt + pcb->rcv_wnd - 1)){
  2.1220 +       if (pcb->rcv_nxt == seqno) {
  2.1221 +         accepted_inseq = 1; 
  2.1222 +         /* The incoming segment is the next in sequence. We check if
  2.1223 +@@ -1195,14 +1195,14 @@ tcp_receive(struct tcp_pcb *pcb)
  2.1224 +                   } else {
  2.1225 +                     pcb->ooseq = cseg;
  2.1226 +                   }
  2.1227 +-                }
  2.1228 +-                tcp_seg_free(next);
  2.1229 +-                if (cseg->next != NULL) {
  2.1230 +-                  next = cseg->next;
  2.1231 +-                  if (TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) {
  2.1232 +-                    /* We need to trim the incoming segment. */
  2.1233 +-                    cseg->len = (u16_t)(next->tcphdr->seqno - seqno);
  2.1234 +-                    pbuf_realloc(cseg->p, cseg->len);
  2.1235 ++                  tcp_seg_free(next);
  2.1236 ++                  if (cseg->next != NULL) {
  2.1237 ++                    next = cseg->next;
  2.1238 ++                    if (TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) {
  2.1239 ++                      /* We need to trim the incoming segment. */
  2.1240 ++                      cseg->len = (u16_t)(next->tcphdr->seqno - seqno);
  2.1241 ++                      pbuf_realloc(cseg->p, cseg->len);
  2.1242 ++                    }
  2.1243 +                   }
  2.1244 +                 }
  2.1245 +                 break;
  2.1246 +@@ -1282,10 +1282,7 @@ tcp_receive(struct tcp_pcb *pcb)
  2.1247 + 
  2.1248 +       }
  2.1249 +     } else {
  2.1250 +-      if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, 
  2.1251 +-                          pcb->rcv_nxt + pcb->rcv_ann_wnd-1)){
  2.1252 +-        tcp_ack_now(pcb);
  2.1253 +-      }
  2.1254 ++      tcp_ack_now(pcb);
  2.1255 +     }
  2.1256 +   } else {
  2.1257 +     /* Segments with length 0 is taken care of here. Segments that
  2.1258 +@@ -1331,7 +1328,8 @@ tcp_parseopt(struct tcp_pcb *pcb)
  2.1259 +         opts[c + 1] == 0x04) {
  2.1260 +         /* An MSS option with the right option length. */
  2.1261 +         mss = (opts[c + 2] << 8) | opts[c + 3];
  2.1262 +-        pcb->mss = mss > TCP_MSS? TCP_MSS: mss;
  2.1263 ++        /* Limit the mss to the configured TCP_MSS and prevent division by zero */
  2.1264 ++        pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss;
  2.1265 + 
  2.1266 +         /* And we are done processing options. */
  2.1267 +         break;
  2.1268 +Index: src/core/ipv4/autoip.c
  2.1269 +===================================================================
  2.1270 +RCS file: /sources/lwip/lwip/src/core/ipv4/autoip.c,v
  2.1271 +retrieving revision 1.16
  2.1272 +retrieving revision 1.17
  2.1273 +diff -u -p -r1.16 -r1.17
  2.1274 +--- src/core/ipv4/autoip.c	26 Jan 2008 16:11:40 -0000	1.16
  2.1275 ++++ src/core/ipv4/autoip.c	17 Jun 2008 20:16:23 -0000	1.17
  2.1276 +@@ -395,8 +395,8 @@ autoip_arp_reply(struct netif *netif, st
  2.1277 +     /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
  2.1278 +      * structure packing (not using structure copy which breaks strict-aliasing rules).
  2.1279 +      */
  2.1280 +-    MEMCPY(&sipaddr, &hdr->sipaddr, sizeof(sipaddr));
  2.1281 +-    MEMCPY(&dipaddr, &hdr->dipaddr, sizeof(dipaddr));
  2.1282 ++    SMEMCPY(&sipaddr, &hdr->sipaddr, sizeof(sipaddr));
  2.1283 ++    SMEMCPY(&dipaddr, &hdr->dipaddr, sizeof(dipaddr));
  2.1284 +       
  2.1285 +     if ((netif->autoip->state == AUTOIP_STATE_PROBING) ||
  2.1286 +         ((netif->autoip->state == AUTOIP_STATE_ANNOUNCING) &&
  2.1287 +Index: src/core/ipv4/inet_chksum.c
  2.1288 +===================================================================
  2.1289 +RCS file: /sources/lwip/lwip/src/core/ipv4/inet_chksum.c,v
  2.1290 +retrieving revision 1.4
  2.1291 +retrieving revision 1.5
  2.1292 +diff -u -p -r1.4 -r1.5
  2.1293 +--- src/core/ipv4/inet_chksum.c	10 Mar 2008 16:12:31 -0000	1.4
  2.1294 ++++ src/core/ipv4/inet_chksum.c	17 Jun 2008 20:06:25 -0000	1.5
  2.1295 +@@ -41,8 +41,6 @@
  2.1296 + #include "lwip/inet_chksum.h"
  2.1297 + #include "lwip/inet.h"
  2.1298 + 
  2.1299 +-#include <string.h>
  2.1300 +-
  2.1301 + /* These are some reference implementations of the checksum algorithm, with the
  2.1302 +  * aim of being simple, correct and fully portable. Checksumming is the
  2.1303 +  * first thing you would want to optimize for your platform. If you create
  2.1304 +@@ -65,6 +63,11 @@
  2.1305 + # define LWIP_CHKSUM_ALGORITHM 0
  2.1306 + #endif
  2.1307 + 
  2.1308 ++/** Like the name says... */
  2.1309 ++#define SWAP_BYTES_IN_WORD(w) ((w & 0xff) << 8) | ((w & 0xff00) >> 8)
  2.1310 ++/** Split an u32_t in two u16_ts and add them up */
  2.1311 ++#define FOLD_U32T(u)          ((u >> 16) + (u & 0x0000ffffUL))
  2.1312 ++
  2.1313 + #if (LWIP_CHKSUM_ALGORITHM == 1) /* Version #1 */
  2.1314 + /**
  2.1315 +  * lwip checksum
  2.1316 +@@ -86,8 +89,7 @@ lwip_standard_chksum(void *dataptr, u16_
  2.1317 +   acc = 0;
  2.1318 +   /* dataptr may be at odd or even addresses */
  2.1319 +   octetptr = (u8_t*)dataptr;
  2.1320 +-  while (len > 1)
  2.1321 +-  {
  2.1322 ++  while (len > 1) {
  2.1323 +     /* declare first octet as most significant
  2.1324 +        thus assume network order, ignoring host order */
  2.1325 +     src = (*octetptr) << 8;
  2.1326 +@@ -98,8 +100,7 @@ lwip_standard_chksum(void *dataptr, u16_
  2.1327 +     acc += src;
  2.1328 +     len -= 2;
  2.1329 +   }
  2.1330 +-  if (len > 0)
  2.1331 +-  {
  2.1332 ++  if (len > 0) {
  2.1333 +     /* accumulate remaining octet */
  2.1334 +     src = (*octetptr) << 8;
  2.1335 +     acc += src;
  2.1336 +@@ -154,19 +155,22 @@ lwip_standard_chksum(void *dataptr, int 
  2.1337 +   }
  2.1338 + 
  2.1339 +   /* Consume left-over byte, if any */
  2.1340 +-  if (len > 0)
  2.1341 ++  if (len > 0) {
  2.1342 +     ((u8_t *)&t)[0] = *(u8_t *)ps;;
  2.1343 ++  }
  2.1344 + 
  2.1345 +   /* Add end bytes */
  2.1346 +   sum += t;
  2.1347 + 
  2.1348 +-  /*  Fold 32-bit sum to 16 bits */
  2.1349 +-  while ((sum >> 16) != 0)
  2.1350 +-    sum = (sum & 0xffff) + (sum >> 16);
  2.1351 ++  /* Fold 32-bit sum to 16 bits
  2.1352 ++     calling this twice is propably faster than if statements... */
  2.1353 ++  sum = FOLD_U32T(sum);
  2.1354 ++  sum = FOLD_U32T(sum);
  2.1355 + 
  2.1356 +   /* Swap if alignment was odd */
  2.1357 +-  if (odd)
  2.1358 +-    sum = ((sum & 0xff) << 8) | ((sum & 0xff00) >> 8);
  2.1359 ++  if (odd) {
  2.1360 ++    sum = SWAP_BYTES_IN_WORD(sum);
  2.1361 ++  }
  2.1362 + 
  2.1363 +   return sum;
  2.1364 + }
  2.1365 +@@ -211,18 +215,20 @@ lwip_standard_chksum(void *dataptr, int 
  2.1366 + 
  2.1367 +   while (len > 7)  {
  2.1368 +     tmp = sum + *pl++;          /* ping */
  2.1369 +-    if (tmp < sum)
  2.1370 ++    if (tmp < sum) {
  2.1371 +       tmp++;                    /* add back carry */
  2.1372 ++    }
  2.1373 + 
  2.1374 +     sum = tmp + *pl++;          /* pong */
  2.1375 +-    if (sum < tmp)
  2.1376 ++    if (sum < tmp) {
  2.1377 +       sum++;                    /* add back carry */
  2.1378 ++    }
  2.1379 + 
  2.1380 +     len -= 8;
  2.1381 +   }
  2.1382 + 
  2.1383 +   /* make room in upper bits */
  2.1384 +-  sum = (sum >> 16) + (sum & 0xffff);
  2.1385 ++  sum = FOLD_U32T(sum);
  2.1386 + 
  2.1387 +   ps = (u16_t *)pl;
  2.1388 + 
  2.1389 +@@ -233,16 +239,20 @@ lwip_standard_chksum(void *dataptr, int 
  2.1390 +   }
  2.1391 + 
  2.1392 +   /* dangling tail byte remaining? */
  2.1393 +-  if (len > 0)                  /* include odd byte */
  2.1394 ++  if (len > 0) {                /* include odd byte */
  2.1395 +     ((u8_t *)&t)[0] = *(u8_t *)ps;
  2.1396 ++  }
  2.1397 + 
  2.1398 +   sum += t;                     /* add end bytes */
  2.1399 + 
  2.1400 +-  while ((sum >> 16) != 0)      /* combine halves */
  2.1401 +-    sum = (sum >> 16) + (sum & 0xffff);
  2.1402 ++  /* Fold 32-bit sum to 16 bits
  2.1403 ++     calling this twice is propably faster than if statements... */
  2.1404 ++  sum = FOLD_U32T(sum);
  2.1405 ++  sum = FOLD_U32T(sum);
  2.1406 + 
  2.1407 +-  if (odd)
  2.1408 +-    sum = ((sum & 0xff) << 8) | ((sum & 0xff00) >> 8);
  2.1409 ++  if (odd) {
  2.1410 ++    sum = SWAP_BYTES_IN_WORD(sum);
  2.1411 ++  }
  2.1412 + 
  2.1413 +   return sum;
  2.1414 + }
  2.1415 +@@ -277,18 +287,18 @@ inet_chksum_pseudo(struct pbuf *p,
  2.1416 +       (void *)q, (void *)q->next));
  2.1417 +     acc += LWIP_CHKSUM(q->payload, q->len);
  2.1418 +     /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/
  2.1419 +-    while ((acc >> 16) != 0) {
  2.1420 +-      acc = (acc & 0xffffUL) + (acc >> 16);
  2.1421 +-    }
  2.1422 ++    /* just executing this next line is probably faster that the if statement needed
  2.1423 ++       to check whether we really need to execute it, and does no harm */
  2.1424 ++    acc = FOLD_U32T(acc);
  2.1425 +     if (q->len % 2 != 0) {
  2.1426 +       swapped = 1 - swapped;
  2.1427 +-      acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
  2.1428 ++      acc = SWAP_BYTES_IN_WORD(acc);
  2.1429 +     }
  2.1430 +     /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/
  2.1431 +   }
  2.1432 + 
  2.1433 +   if (swapped) {
  2.1434 +-    acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
  2.1435 ++    acc = SWAP_BYTES_IN_WORD(acc);
  2.1436 +   }
  2.1437 +   acc += (src->addr & 0xffffUL);
  2.1438 +   acc += ((src->addr >> 16) & 0xffffUL);
  2.1439 +@@ -297,9 +307,10 @@ inet_chksum_pseudo(struct pbuf *p,
  2.1440 +   acc += (u32_t)htons((u16_t)proto);
  2.1441 +   acc += (u32_t)htons(proto_len);
  2.1442 + 
  2.1443 +-  while ((acc >> 16) != 0) {
  2.1444 +-    acc = (acc & 0xffffUL) + (acc >> 16);
  2.1445 +-  }
  2.1446 ++  /* Fold 32-bit sum to 16 bits
  2.1447 ++     calling this twice is propably faster than if statements... */
  2.1448 ++  acc = FOLD_U32T(acc);
  2.1449 ++  acc = FOLD_U32T(acc);
  2.1450 +   LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
  2.1451 +   return (u16_t)~(acc & 0xffffUL);
  2.1452 + }
  2.1453 +@@ -340,18 +351,17 @@ inet_chksum_pseudo_partial(struct pbuf *
  2.1454 +     chksum_len -= chklen;
  2.1455 +     LWIP_ASSERT("delete me", chksum_len < 0x7fff);
  2.1456 +     /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/
  2.1457 +-    while ((acc >> 16) != 0) {
  2.1458 +-      acc = (acc & 0xffffUL) + (acc >> 16);
  2.1459 +-    }
  2.1460 ++    /* fold the upper bit down */
  2.1461 ++    acc = FOLD_U32T(acc);
  2.1462 +     if (q->len % 2 != 0) {
  2.1463 +       swapped = 1 - swapped;
  2.1464 +-      acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
  2.1465 ++      acc = SWAP_BYTES_IN_WORD(acc);
  2.1466 +     }
  2.1467 +     /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/
  2.1468 +   }
  2.1469 + 
  2.1470 +   if (swapped) {
  2.1471 +-    acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
  2.1472 ++    acc = SWAP_BYTES_IN_WORD(acc);
  2.1473 +   }
  2.1474 +   acc += (src->addr & 0xffffUL);
  2.1475 +   acc += ((src->addr >> 16) & 0xffffUL);
  2.1476 +@@ -360,9 +370,10 @@ inet_chksum_pseudo_partial(struct pbuf *
  2.1477 +   acc += (u32_t)htons((u16_t)proto);
  2.1478 +   acc += (u32_t)htons(proto_len);
  2.1479 + 
  2.1480 +-  while ((acc >> 16) != 0) {
  2.1481 +-    acc = (acc & 0xffffUL) + (acc >> 16);
  2.1482 +-  }
  2.1483 ++  /* Fold 32-bit sum to 16 bits
  2.1484 ++     calling this twice is propably faster than if statements... */
  2.1485 ++  acc = FOLD_U32T(acc);
  2.1486 ++  acc = FOLD_U32T(acc);
  2.1487 +   LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
  2.1488 +   return (u16_t)~(acc & 0xffffUL);
  2.1489 + }
  2.1490 +@@ -380,13 +391,7 @@ inet_chksum_pseudo_partial(struct pbuf *
  2.1491 + u16_t
  2.1492 + inet_chksum(void *dataptr, u16_t len)
  2.1493 + {
  2.1494 +-  u32_t acc;
  2.1495 +-
  2.1496 +-  acc = LWIP_CHKSUM(dataptr, len);
  2.1497 +-  while ((acc >> 16) != 0) {
  2.1498 +-    acc = (acc & 0xffff) + (acc >> 16);
  2.1499 +-  }
  2.1500 +-  return (u16_t)~(acc & 0xffff);
  2.1501 ++  return ~LWIP_CHKSUM(dataptr, len);
  2.1502 + }
  2.1503 + 
  2.1504 + /**
  2.1505 +@@ -407,17 +412,15 @@ inet_chksum_pbuf(struct pbuf *p)
  2.1506 +   swapped = 0;
  2.1507 +   for(q = p; q != NULL; q = q->next) {
  2.1508 +     acc += LWIP_CHKSUM(q->payload, q->len);
  2.1509 +-    while ((acc >> 16) != 0) {
  2.1510 +-      acc = (acc & 0xffffUL) + (acc >> 16);
  2.1511 +-    }
  2.1512 ++    acc = FOLD_U32T(acc);
  2.1513 +     if (q->len % 2 != 0) {
  2.1514 +       swapped = 1 - swapped;
  2.1515 +-      acc = (acc & 0x00ffUL << 8) | (acc & 0xff00UL >> 8);
  2.1516 ++      acc = SWAP_BYTES_IN_WORD(acc);
  2.1517 +     }
  2.1518 +   }
  2.1519 + 
  2.1520 +   if (swapped) {
  2.1521 +-    acc = ((acc & 0x00ffUL) << 8) | ((acc & 0xff00UL) >> 8);
  2.1522 ++    acc = SWAP_BYTES_IN_WORD(acc);
  2.1523 +   }
  2.1524 +   return (u16_t)~(acc & 0xffffUL);
  2.1525 + }
  2.1526 +Index: src/core/ipv4/ip.c
  2.1527 +===================================================================
  2.1528 +RCS file: /sources/lwip/lwip/src/core/ipv4/ip.c,v
  2.1529 +retrieving revision 1.66
  2.1530 +retrieving revision 1.68
  2.1531 +diff -u -p -r1.66 -r1.68
  2.1532 +--- src/core/ipv4/ip.c	14 Jan 2008 20:53:23 -0000	1.66
  2.1533 ++++ src/core/ipv4/ip.c	17 Jun 2008 19:39:22 -0000	1.68
  2.1534 +@@ -531,9 +531,19 @@ ip_output_if(struct pbuf *p, struct ip_a
  2.1535 +   LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num));
  2.1536 +   ip_debug_print(p);
  2.1537 + 
  2.1538 +-  LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
  2.1539 ++#if (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF)
  2.1540 ++  if (ip_addr_cmp(dest, &netif->ip_addr)) {
  2.1541 ++    /* Packet to self, enqueue it for loopback */
  2.1542 ++    LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()"));
  2.1543 ++
  2.1544 ++    return netif_loop_output(netif, p, dest);
  2.1545 ++  } else
  2.1546 ++#endif /* (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF) */
  2.1547 ++  {
  2.1548 ++    LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
  2.1549 + 
  2.1550 +-  return netif->output(netif, p, dest);
  2.1551 ++    return netif->output(netif, p, dest);
  2.1552 ++  }
  2.1553 + }
  2.1554 + 
  2.1555 + /**
  2.1556 +Index: src/include/lwip/debug.h
  2.1557 +===================================================================
  2.1558 +RCS file: /sources/lwip/lwip/src/include/lwip/debug.h,v
  2.1559 +retrieving revision 1.37
  2.1560 +retrieving revision 1.39
  2.1561 +diff -u -p -r1.37 -r1.39
  2.1562 +--- src/include/lwip/debug.h	22 Sep 2007 11:16:07 -0000	1.37
  2.1563 ++++ src/include/lwip/debug.h	16 Jul 2008 20:36:22 -0000	1.39
  2.1564 +@@ -61,26 +61,28 @@
  2.1565 + #define LWIP_DBG_HALT          0x08U
  2.1566 + 
  2.1567 + #ifndef LWIP_NOASSERT
  2.1568 +-#define LWIP_ASSERT(x,y) do { if(!(y)) LWIP_PLATFORM_ASSERT(x); } while(0)
  2.1569 ++#define LWIP_ASSERT(message, assertion) do { if(!(assertion)) \
  2.1570 ++  LWIP_PLATFORM_ASSERT(message); } while(0)
  2.1571 + #else  /* LWIP_NOASSERT */
  2.1572 +-#define LWIP_ASSERT(x,y) 
  2.1573 ++#define LWIP_ASSERT(message, assertion) 
  2.1574 + #endif /* LWIP_NOASSERT */
  2.1575 + 
  2.1576 +-/** print "m" message only if "e" is true, and execute "h" expression */
  2.1577 ++/** if "expression" isn't true, then print "message" and execute "handler" expression */
  2.1578 + #ifndef LWIP_ERROR
  2.1579 +-#define LWIP_ERROR(m,e,h) do { if (!(e)) { LWIP_PLATFORM_ASSERT(m); h;}} while(0)
  2.1580 ++#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \
  2.1581 ++  LWIP_PLATFORM_ASSERT(message); handler;}} while(0)
  2.1582 + #endif /* LWIP_ERROR */
  2.1583 + 
  2.1584 + #ifdef LWIP_DEBUG
  2.1585 + /** print debug message only if debug message type is enabled...
  2.1586 +  *  AND is of correct type AND is at least LWIP_DBG_LEVEL
  2.1587 +  */
  2.1588 +-#define LWIP_DEBUGF(debug,x) do { \
  2.1589 ++#define LWIP_DEBUGF(debug, message) do { \
  2.1590 +                                if ( \
  2.1591 +                                    ((debug) & LWIP_DBG_ON) && \
  2.1592 +                                    ((debug) & LWIP_DBG_TYPES_ON) && \
  2.1593 +                                    ((s16_t)((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL)) { \
  2.1594 +-                                 LWIP_PLATFORM_DIAG(x); \
  2.1595 ++                                 LWIP_PLATFORM_DIAG(message); \
  2.1596 +                                  if ((debug) & LWIP_DBG_HALT) { \
  2.1597 +                                    while(1); \
  2.1598 +                                  } \
  2.1599 +@@ -88,7 +90,7 @@
  2.1600 +                              } while(0)
  2.1601 + 
  2.1602 + #else  /* LWIP_DEBUG */
  2.1603 +-#define LWIP_DEBUGF(debug,x) 
  2.1604 ++#define LWIP_DEBUGF(debug, message) 
  2.1605 + #endif /* LWIP_DEBUG */
  2.1606 + 
  2.1607 + #endif /* __LWIP_DEBUG_H__ */
  2.1608 +Index: src/include/lwip/err.h
  2.1609 +===================================================================
  2.1610 +RCS file: /sources/lwip/lwip/src/include/lwip/err.h,v
  2.1611 +retrieving revision 1.13
  2.1612 +retrieving revision 1.15
  2.1613 +diff -u -p -r1.13 -r1.15
  2.1614 +--- src/include/lwip/err.h	13 Dec 2007 23:06:50 -0000	1.13
  2.1615 ++++ src/include/lwip/err.h	17 Jun 2008 20:27:32 -0000	1.15
  2.1616 +@@ -33,37 +33,43 @@
  2.1617 + #define __LWIP_ERR_H__
  2.1618 + 
  2.1619 + #include "lwip/opt.h"
  2.1620 ++#include "lwip/arch.h"
  2.1621 + 
  2.1622 + #ifdef __cplusplus
  2.1623 + extern "C" {
  2.1624 + #endif
  2.1625 + 
  2.1626 +-typedef s8_t err_t;
  2.1627 ++/** Define LWIP_ERR_T in cc.h if you want to use
  2.1628 ++ *  a different type for your platform (must be signed). */
  2.1629 ++#ifdef LWIP_ERR_T
  2.1630 ++typedef LWIP_ERR_T err_t;
  2.1631 ++#else /* LWIP_ERR_T */
  2.1632 ++ typedef s8_t err_t;
  2.1633 ++#endif /* LWIP_ERR_T*/
  2.1634 + 
  2.1635 + /* Definitions for error constants. */
  2.1636 + 
  2.1637 + #define ERR_OK          0    /* No error, everything OK. */
  2.1638 + #define ERR_MEM        -1    /* Out of memory error.     */
  2.1639 + #define ERR_BUF        -2    /* Buffer error.            */
  2.1640 +-#define ERR_RTE        -3    /* Routing problem.         */
  2.1641 ++#define ERR_TIMEOUT    -3    /* Timeout.                 */
  2.1642 ++#define ERR_RTE        -4    /* Routing problem.         */
  2.1643 + 
  2.1644 + #define ERR_IS_FATAL(e) ((e) < ERR_RTE)
  2.1645 + 
  2.1646 +-#define ERR_ABRT       -4    /* Connection aborted.      */
  2.1647 +-#define ERR_RST        -5    /* Connection reset.        */
  2.1648 +-#define ERR_CLSD       -6    /* Connection closed.       */
  2.1649 +-#define ERR_CONN       -7    /* Not connected.           */
  2.1650 ++#define ERR_ABRT       -5    /* Connection aborted.      */
  2.1651 ++#define ERR_RST        -6    /* Connection reset.        */
  2.1652 ++#define ERR_CLSD       -7    /* Connection closed.       */
  2.1653 ++#define ERR_CONN       -8    /* Not connected.           */
  2.1654 + 
  2.1655 +-#define ERR_VAL        -8    /* Illegal value.           */
  2.1656 ++#define ERR_VAL        -9    /* Illegal value.           */
  2.1657 + 
  2.1658 +-#define ERR_ARG        -9    /* Illegal argument.        */
  2.1659 ++#define ERR_ARG        -10   /* Illegal argument.        */
  2.1660 + 
  2.1661 +-#define ERR_USE        -10   /* Address in use.          */
  2.1662 ++#define ERR_USE        -11   /* Address in use.          */
  2.1663 + 
  2.1664 +-#define ERR_IF         -11   /* Low-level netif error    */
  2.1665 +-#define ERR_ISCONN     -12   /* Already connected.       */
  2.1666 +-
  2.1667 +-#define ERR_TIMEOUT    -13   /* Timeout.                 */
  2.1668 ++#define ERR_IF         -12   /* Low-level netif error    */
  2.1669 ++#define ERR_ISCONN     -13   /* Already connected.       */
  2.1670 + 
  2.1671 + #define ERR_INPROGRESS -14   /* Operation in progress    */
  2.1672 + 
  2.1673 +Index: src/include/lwip/mem.h
  2.1674 +===================================================================
  2.1675 +RCS file: /sources/lwip/lwip/src/include/lwip/mem.h,v
  2.1676 +retrieving revision 1.21
  2.1677 +retrieving revision 1.22
  2.1678 +diff -u -p -r1.21 -r1.22
  2.1679 +--- src/include/lwip/mem.h	4 Mar 2008 16:31:32 -0000	1.21
  2.1680 ++++ src/include/lwip/mem.h	30 May 2008 11:37:15 -0000	1.22
  2.1681 +@@ -50,16 +50,16 @@ typedef size_t mem_size_t;
  2.1682 +  * allow these defines to be overridden.
  2.1683 +  */
  2.1684 + #ifndef mem_free
  2.1685 +-#define mem_free(x) free(x)
  2.1686 ++#define mem_free free
  2.1687 + #endif
  2.1688 + #ifndef mem_malloc
  2.1689 +-#define mem_malloc(x) malloc(x)
  2.1690 ++#define mem_malloc malloc
  2.1691 + #endif
  2.1692 + #ifndef mem_calloc
  2.1693 +-#define mem_calloc(x, y) calloc(x, y)
  2.1694 ++#define mem_calloc calloc
  2.1695 + #endif
  2.1696 + #ifndef mem_realloc
  2.1697 +-#define mem_realloc(x, size) (x)
  2.1698 ++#define mem_realloc realloc
  2.1699 + #endif
  2.1700 + #else /* MEM_LIBC_MALLOC */
  2.1701 + 
  2.1702 +Index: src/include/lwip/netif.h
  2.1703 +===================================================================
  2.1704 +RCS file: /sources/lwip/lwip/src/include/lwip/netif.h,v
  2.1705 +retrieving revision 1.43
  2.1706 +retrieving revision 1.46
  2.1707 +diff -u -p -r1.43 -r1.46
  2.1708 +--- src/include/lwip/netif.h	9 Oct 2007 19:59:59 -0000	1.43
  2.1709 ++++ src/include/lwip/netif.h	19 Jun 2008 16:27:23 -0000	1.46
  2.1710 +@@ -34,6 +34,8 @@
  2.1711 + 
  2.1712 + #include "lwip/opt.h"
  2.1713 + 
  2.1714 ++#define ENABLE_LOOPBACK (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF)
  2.1715 ++
  2.1716 + #include "lwip/err.h"
  2.1717 + 
  2.1718 + #include "lwip/ip_addr.h"
  2.1719 +@@ -165,6 +167,14 @@ struct netif {
  2.1720 + #if LWIP_NETIF_HWADDRHINT
  2.1721 +   u8_t *addr_hint;
  2.1722 + #endif /* LWIP_NETIF_HWADDRHINT */
  2.1723 ++#if ENABLE_LOOPBACK
  2.1724 ++  /* List of packets to be queued for ourselves. */
  2.1725 ++  struct pbuf *loop_first;
  2.1726 ++  struct pbuf *loop_last;
  2.1727 ++#if LWIP_LOOPBACK_MAX_PBUFS
  2.1728 ++  u16_t loop_cnt_current;
  2.1729 ++#endif /* LWIP_LOOPBACK_MAX_PBUFS */
  2.1730 ++#endif /* ENABLE_LOOPBACK */
  2.1731 + };
  2.1732 + 
  2.1733 + #if LWIP_SNMP
  2.1734 +@@ -242,4 +252,12 @@ void netif_set_link_callback(struct neti
  2.1735 + }
  2.1736 + #endif
  2.1737 + 
  2.1738 ++#if ENABLE_LOOPBACK
  2.1739 ++err_t netif_loop_output(struct netif *netif, struct pbuf *p, struct ip_addr *dest_ip);
  2.1740 ++void netif_poll(struct netif *netif);
  2.1741 ++#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
  2.1742 ++void netif_poll_all(void);
  2.1743 ++#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
  2.1744 ++#endif /* ENABLE_LOOPBACK */
  2.1745 ++
  2.1746 + #endif /* __LWIP_NETIF_H__ */
  2.1747 +Index: src/include/lwip/opt.h
  2.1748 +===================================================================
  2.1749 +RCS file: /sources/lwip/lwip/src/include/lwip/opt.h,v
  2.1750 +retrieving revision 1.116
  2.1751 +retrieving revision 1.122
  2.1752 +diff -u -p -r1.116 -r1.122
  2.1753 +--- src/include/lwip/opt.h	31 Jan 2008 18:19:29 -0000	1.116
  2.1754 ++++ src/include/lwip/opt.h	30 Jun 2008 18:16:52 -0000	1.122
  2.1755 +@@ -155,6 +155,27 @@
  2.1756 + #define MEMP_USE_CUSTOM_POOLS           0
  2.1757 + #endif
  2.1758 + 
  2.1759 ++/**
  2.1760 ++ * Set this to 1 if you want to free PBUF_RAM pbufs (or call mem_free()) from
  2.1761 ++ * interrupt context (or another context that doesn't allow waiting for a
  2.1762 ++ * semaphore).
  2.1763 ++ * If set to 1, mem_malloc will be protected by a semaphore and SYS_ARCH_PROTECT,
  2.1764 ++ * while mem_free will only use SYS_ARCH_PROTECT. mem_malloc SYS_ARCH_UNPROTECTs
  2.1765 ++ * with each loop so that mem_free can run.
  2.1766 ++ *
  2.1767 ++ * ATTENTION: As you can see from the above description, this leads to dis-/
  2.1768 ++ * enabling interrupts often, which can be slow! Also, on low memory, mem_malloc
  2.1769 ++ * can need longer.
  2.1770 ++ *
  2.1771 ++ * If you don't want that, at least for NO_SYS=0, you can still use the following
  2.1772 ++ * functions to enqueue a deallocation call which then runs in the tcpip_thread
  2.1773 ++ * context:
  2.1774 ++ * - pbuf_free_callback(p);
  2.1775 ++ * - mem_free_callback(m);
  2.1776 ++ */
  2.1777 ++#ifndef LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
  2.1778 ++#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 0
  2.1779 ++#endif
  2.1780 + 
  2.1781 + /*
  2.1782 +    ------------------------------------------------
  2.1783 +@@ -815,6 +836,39 @@
  2.1784 + #define LWIP_NETIF_HWADDRHINT           0
  2.1785 + #endif
  2.1786 + 
  2.1787 ++/**
  2.1788 ++ * LWIP_NETIF_LOOPBACK==1: Support sending packets with a destination IP
  2.1789 ++ * address equal to the netif IP address, looping them back up the stack.
  2.1790 ++ */
  2.1791 ++#ifndef LWIP_NETIF_LOOPBACK
  2.1792 ++#define LWIP_NETIF_LOOPBACK             0
  2.1793 ++#endif
  2.1794 ++
  2.1795 ++/**
  2.1796 ++ * LWIP_LOOPBACK_MAX_PBUFS: Maximum number of pbufs on queue for loopback
  2.1797 ++ * sending for each netif (0 = disabled)
  2.1798 ++ */
  2.1799 ++#ifndef LWIP_LOOPBACK_MAX_PBUFS
  2.1800 ++#define LWIP_LOOPBACK_MAX_PBUFS         0
  2.1801 ++#endif
  2.1802 ++
  2.1803 ++/**
  2.1804 ++ * LWIP_NETIF_LOOPBACK_MULTITHREADING: Indicates whether threading is enabled in
  2.1805 ++ * the system, as netifs must change how they behave depending on this setting
  2.1806 ++ * for the LWIP_NETIF_LOOPBACK option to work.
  2.1807 ++ * Setting this is needed to avoid reentering non-reentrant functions like
  2.1808 ++ * tcp_input().
  2.1809 ++ *    LWIP_NETIF_LOOPBACK_MULTITHREADING==1: Indicates that the user is using a
  2.1810 ++ *       multithreaded environment like tcpip.c. In this case, netif->input()
  2.1811 ++ *       is called directly.
  2.1812 ++ *    LWIP_NETIF_LOOPBACK_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup.
  2.1813 ++ *       The packets are put on a list and netif_poll() must be called in
  2.1814 ++ *       the main application loop.
  2.1815 ++ */
  2.1816 ++#ifndef LWIP_NETIF_LOOPBACK_MULTITHREADING
  2.1817 ++#define LWIP_NETIF_LOOPBACK_MULTITHREADING    (!NO_SYS)
  2.1818 ++#endif
  2.1819 ++
  2.1820 + /*
  2.1821 +    ------------------------------------
  2.1822 +    ---------- LOOPIF options ----------
  2.1823 +@@ -827,20 +881,16 @@
  2.1824 + #define LWIP_HAVE_LOOPIF                0
  2.1825 + #endif
  2.1826 + 
  2.1827 ++/*
  2.1828 ++   ------------------------------------
  2.1829 ++   ---------- SLIPIF options ----------
  2.1830 ++   ------------------------------------
  2.1831 ++*/
  2.1832 + /**
  2.1833 +- * LWIP_LOOPIF_MULTITHREADING: Indicates whether threading is enabled in
  2.1834 +- * the system, as LOOPIF must change how it behaves depending on this setting.
  2.1835 +- * Setting this is needed to avoid reentering non-reentrant functions like
  2.1836 +- * tcp_input().
  2.1837 +- *    LWIP_LOOPIF_MULTITHREADING==1: Indicates that the user is using a
  2.1838 +- *       multithreaded environment like tcpip.c. In this case, netif->input()
  2.1839 +- *       is called directly.
  2.1840 +- *    LWIP_LOOPIF_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup.
  2.1841 +- *       The packets are put on a list and loopif_poll() must be called in
  2.1842 +- *       the main application loop.
  2.1843 ++ * LWIP_HAVE_SLIPIF==1: Support slip interface and slipif.c
  2.1844 +  */
  2.1845 +-#ifndef LWIP_LOOPIF_MULTITHREADING
  2.1846 +-#define LWIP_LOOPIF_MULTITHREADING      1
  2.1847 ++#ifndef LWIP_HAVE_SLIPIF
  2.1848 ++#define LWIP_HAVE_SLIPIF                0
  2.1849 + #endif
  2.1850 + 
  2.1851 + /*
  2.1852 +Index: src/include/lwip/sio.h
  2.1853 +===================================================================
  2.1854 +RCS file: /sources/lwip/lwip/src/include/lwip/sio.h,v
  2.1855 +retrieving revision 1.7
  2.1856 +retrieving revision 1.8
  2.1857 +diff -u -p -r1.7 -r1.8
  2.1858 +--- src/include/lwip/sio.h	6 Sep 2007 16:43:44 -0000	1.7
  2.1859 ++++ src/include/lwip/sio.h	27 Mar 2008 18:06:02 -0000	1.8
  2.1860 +@@ -32,16 +32,24 @@
  2.1861 +  * It needs to be implemented by those platforms which need SLIP or PPP
  2.1862 +  */
  2.1863 + 
  2.1864 ++#ifndef __SIO_H__
  2.1865 ++#define __SIO_H__
  2.1866 ++
  2.1867 + #include "lwip/arch.h"
  2.1868 + 
  2.1869 + #ifdef __cplusplus
  2.1870 + extern "C" {
  2.1871 + #endif
  2.1872 + 
  2.1873 ++/* If you want to define sio_fd_t elsewhere or differently,
  2.1874 ++   define this in your cc.h file. */
  2.1875 + #ifndef __sio_fd_t_defined
  2.1876 + typedef void * sio_fd_t;
  2.1877 + #endif
  2.1878 + 
  2.1879 ++/* The following functions can be defined to something else in your cc.h file
  2.1880 ++   or be implemented in your custom sio.c file. */
  2.1881 ++
  2.1882 + #ifndef sio_open
  2.1883 + sio_fd_t sio_open(u8_t);
  2.1884 + #endif
  2.1885 +@@ -69,3 +77,5 @@ void sio_read_abort(sio_fd_t);
  2.1886 + #ifdef __cplusplus
  2.1887 + }
  2.1888 + #endif
  2.1889 ++
  2.1890 ++#endif /* __SIO_H__ */
  2.1891 +Index: src/include/lwip/sockets.h
  2.1892 +===================================================================
  2.1893 +RCS file: /sources/lwip/lwip/src/include/lwip/sockets.h,v
  2.1894 +retrieving revision 1.38
  2.1895 +retrieving revision 1.39
  2.1896 +diff -u -p -r1.38 -r1.39
  2.1897 +--- src/include/lwip/sockets.h	2 Dec 2007 15:24:02 -0000	1.38
  2.1898 ++++ src/include/lwip/sockets.h	26 Apr 2008 10:46:23 -0000	1.39
  2.1899 +@@ -177,7 +177,22 @@ typedef struct ip_mreq {
  2.1900 + } ip_mreq;
  2.1901 + #endif /* LWIP_IGMP */
  2.1902 + 
  2.1903 +-/* Unimplemented for now... */
  2.1904 ++/*
  2.1905 ++ * The Type of Service provides an indication of the abstract
  2.1906 ++ * parameters of the quality of service desired.  These parameters are
  2.1907 ++ * to be used to guide the selection of the actual service parameters
  2.1908 ++ * when transmitting a datagram through a particular network.  Several
  2.1909 ++ * networks offer service precedence, which somehow treats high
  2.1910 ++ * precedence traffic as more important than other traffic (generally
  2.1911 ++ * by accepting only traffic above a certain precedence at time of high
  2.1912 ++ * load).  The major choice is a three way tradeoff between low-delay,
  2.1913 ++ * high-reliability, and high-throughput.
  2.1914 ++ * The use of the Delay, Throughput, and Reliability indications may
  2.1915 ++ * increase the cost (in some sense) of the service.  In many networks
  2.1916 ++ * better performance for one of these parameters is coupled with worse
  2.1917 ++ * performance on another.  Except for very unusual cases at most two
  2.1918 ++ * of these three indications should be set.
  2.1919 ++ */
  2.1920 + #define IPTOS_TOS_MASK          0x1E
  2.1921 + #define IPTOS_TOS(tos)          ((tos) & IPTOS_TOS_MASK)
  2.1922 + #define IPTOS_LOWDELAY          0x10
  2.1923 +@@ -187,7 +202,13 @@ typedef struct ip_mreq {
  2.1924 + #define IPTOS_MINCOST           IPTOS_LOWCOST
  2.1925 + 
  2.1926 + /*
  2.1927 +- * Definitions for IP precedence (also in ip_tos) (Unimplemented)
  2.1928 ++ * The Network Control precedence designation is intended to be used
  2.1929 ++ * within a network only.  The actual use and control of that
  2.1930 ++ * designation is up to each network. The Internetwork Control
  2.1931 ++ * designation is intended for use by gateway control originators only.
  2.1932 ++ * If the actual use of these precedence designations is of concern to
  2.1933 ++ * a particular network, it is the responsibility of that network to
  2.1934 ++ * control the access to, and use of, those precedence designations.
  2.1935 +  */
  2.1936 + #define IPTOS_PREC_MASK                 0xe0
  2.1937 + #define IPTOS_PREC(tos)                ((tos) & IPTOS_PREC_MASK)
  2.1938 +Index: src/include/lwip/stats.h
  2.1939 +===================================================================
  2.1940 +RCS file: /sources/lwip/lwip/src/include/lwip/stats.h,v
  2.1941 +retrieving revision 1.19
  2.1942 +retrieving revision 1.23
  2.1943 +diff -u -p -r1.19 -r1.23
  2.1944 +--- src/include/lwip/stats.h	28 Nov 2007 21:25:07 -0000	1.19
  2.1945 ++++ src/include/lwip/stats.h	8 Jul 2008 09:15:57 -0000	1.23
  2.1946 +@@ -57,7 +57,6 @@ extern "C" {
  2.1947 + 
  2.1948 + struct stats_proto {
  2.1949 +   STAT_COUNTER xmit;             /* Transmitted packets. */
  2.1950 +-  STAT_COUNTER rexmit;           /* Retransmitted packets. */
  2.1951 +   STAT_COUNTER recv;             /* Received packets. */
  2.1952 +   STAT_COUNTER fw;               /* Forwarded packets. */
  2.1953 +   STAT_COUNTER drop;             /* Dropped packets. */
  2.1954 +@@ -87,7 +86,8 @@ struct stats_mem {
  2.1955 +   mem_size_t avail;
  2.1956 +   mem_size_t used;
  2.1957 +   mem_size_t max;
  2.1958 +-  mem_size_t err;
  2.1959 ++  STAT_COUNTER err;
  2.1960 ++  STAT_COUNTER illegal;
  2.1961 + };
  2.1962 + 
  2.1963 + struct stats_syselem {
  2.1964 +@@ -142,64 +142,138 @@ extern struct stats_ lwip_stats;
  2.1965 + #define stats_init() /* Compatibility define, not init needed. */
  2.1966 + 
  2.1967 + #define STATS_INC(x) ++lwip_stats.x
  2.1968 ++#define STATS_DEC(x) --lwip_stats.x
  2.1969 + #else
  2.1970 + #define stats_init()
  2.1971 + #define STATS_INC(x)
  2.1972 ++#define STATS_DEC(x)
  2.1973 + #endif /* LWIP_STATS */
  2.1974 + 
  2.1975 + #if TCP_STATS
  2.1976 + #define TCP_STATS_INC(x) STATS_INC(x)
  2.1977 ++#define TCP_STATS_DISPLAY() stats_display_proto(&lwip_stats.tcp, "TCP")
  2.1978 + #else
  2.1979 + #define TCP_STATS_INC(x)
  2.1980 ++#define TCP_STATS_DISPLAY()
  2.1981 + #endif
  2.1982 + 
  2.1983 + #if UDP_STATS
  2.1984 + #define UDP_STATS_INC(x) STATS_INC(x)
  2.1985 ++#define UDP_STATS_DISPLAY() stats_display_proto(&lwip_stats.udp, "UDP")
  2.1986 + #else
  2.1987 + #define UDP_STATS_INC(x)
  2.1988 ++#define UDP_STATS_DISPLAY()
  2.1989 + #endif
  2.1990 + 
  2.1991 + #if ICMP_STATS
  2.1992 + #define ICMP_STATS_INC(x) STATS_INC(x)
  2.1993 ++#define ICMP_STATS_DISPLAY() stats_display_proto(&lwip_stats.icmp, "ICMP")
  2.1994 + #else
  2.1995 + #define ICMP_STATS_INC(x)
  2.1996 ++#define ICMP_STATS_DISPLAY()
  2.1997 + #endif
  2.1998 + 
  2.1999 + #if IGMP_STATS
  2.2000 + #define IGMP_STATS_INC(x) STATS_INC(x)
  2.2001 ++#define IGMP_STATS_DISPLAY() stats_display_igmp(&lwip_stats.igmp)
  2.2002 + #else
  2.2003 + #define IGMP_STATS_INC(x)
  2.2004 ++#define IGMP_STATS_DISPLAY()
  2.2005 + #endif
  2.2006 + 
  2.2007 + #if IP_STATS
  2.2008 + #define IP_STATS_INC(x) STATS_INC(x)
  2.2009 ++#define IP_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip, "IP")
  2.2010 + #else
  2.2011 + #define IP_STATS_INC(x)
  2.2012 ++#define IP_STATS_DISPLAY()
  2.2013 + #endif
  2.2014 + 
  2.2015 + #if IPFRAG_STATS
  2.2016 + #define IPFRAG_STATS_INC(x) STATS_INC(x)
  2.2017 ++#define IPFRAG_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip_frag, "IP_FRAG")
  2.2018 + #else
  2.2019 + #define IPFRAG_STATS_INC(x)
  2.2020 ++#define IPFRAG_STATS_DISPLAY()
  2.2021 + #endif
  2.2022 + 
  2.2023 + #if ETHARP_STATS
  2.2024 + #define ETHARP_STATS_INC(x) STATS_INC(x)
  2.2025 ++#define ETHARP_STATS_DISPLAY() stats_display_proto(&lwip_stats.etharp, "ETHARP")
  2.2026 + #else
  2.2027 + #define ETHARP_STATS_INC(x)
  2.2028 ++#define ETHARP_STATS_DISPLAY()
  2.2029 + #endif
  2.2030 + 
  2.2031 + #if LINK_STATS
  2.2032 + #define LINK_STATS_INC(x) STATS_INC(x)
  2.2033 ++#define LINK_STATS_DISPLAY() stats_display_proto(&lwip_stats.link, "LINK")
  2.2034 + #else
  2.2035 + #define LINK_STATS_INC(x)
  2.2036 ++#define LINK_STATS_DISPLAY()
  2.2037 ++#endif
  2.2038 ++
  2.2039 ++#if MEM_STATS
  2.2040 ++#define MEM_STATS_AVAIL(x, y) lwip_stats.mem.x = y
  2.2041 ++#define MEM_STATS_INC(x) STATS_INC(mem.x)
  2.2042 ++#define MEM_STATS_INC_USED(x, y) do { lwip_stats.mem.used += y; \
  2.2043 ++                                    if (lwip_stats.mem.max < lwip_stats.mem.used) { \
  2.2044 ++                                        lwip_stats.mem.max = lwip_stats.mem.used; \
  2.2045 ++                                    } \
  2.2046 ++                                 } while(0)
  2.2047 ++#define MEM_STATS_DEC_USED(x, y) lwip_stats.mem.x -= y
  2.2048 ++#define MEM_STATS_DISPLAY() stats_display_mem(&lwip_stats.mem, "HEAP")
  2.2049 ++#else
  2.2050 ++#define MEM_STATS_AVAIL(x, y)
  2.2051 ++#define MEM_STATS_INC(x)
  2.2052 ++#define MEM_STATS_INC_USED(x, y)
  2.2053 ++#define MEM_STATS_DEC_USED(x, y)
  2.2054 ++#define MEM_STATS_DISPLAY()
  2.2055 ++#endif
  2.2056 ++
  2.2057 ++#if MEMP_STATS
  2.2058 ++#define MEMP_STATS_AVAIL(x, i, y) lwip_stats.memp[i].x = y
  2.2059 ++#define MEMP_STATS_INC(x, i) STATS_INC(memp[i].x)
  2.2060 ++#define MEMP_STATS_DEC(x, i) STATS_DEC(memp[i].x)
  2.2061 ++#define MEMP_STATS_INC_USED(x, i) do { ++lwip_stats.memp[i].used; \
  2.2062 ++                                    if (lwip_stats.memp[i].max < lwip_stats.memp[i].used) { \
  2.2063 ++                                        lwip_stats.memp[i].max = lwip_stats.memp[i].used; \
  2.2064 ++                                    } \
  2.2065 ++                                 } while(0)
  2.2066 ++#define MEMP_STATS_DISPLAY(i) stats_display_memp(&lwip_stats.memp[i], i)
  2.2067 ++#else
  2.2068 ++#define MEMP_STATS_AVAIL(x, i, y)
  2.2069 ++#define MEMP_STATS_INC(x, i)
  2.2070 ++#define MEMP_STATS_DEC(x, i)
  2.2071 ++#define MEMP_STATS_INC_USED(x, i)
  2.2072 ++#define MEMP_STATS_DISPLAY(i)
  2.2073 ++#endif
  2.2074 ++
  2.2075 ++#if SYS_STATS
  2.2076 ++#define SYS_STATS_INC(x) STATS_INC(sys.x)
  2.2077 ++#define SYS_STATS_DEC(x) STATS_DEC(sys.x)
  2.2078 ++#define SYS_STATS_DISPLAY() stats_display_sys(&lwip_stats.sys)
  2.2079 ++#else
  2.2080 ++#define SYS_STATS_INC(x)
  2.2081 ++#define SYS_STATS_DEC(x)
  2.2082 ++#define SYS_STATS_DISPLAY()
  2.2083 + #endif
  2.2084 + 
  2.2085 + /* Display of statistics */
  2.2086 + #if LWIP_STATS_DISPLAY
  2.2087 + void stats_display(void);
  2.2088 ++void stats_display_proto(struct stats_proto *proto, char *name);
  2.2089 ++void stats_display_igmp(struct stats_igmp *igmp);
  2.2090 ++void stats_display_mem(struct stats_mem *mem, char *name);
  2.2091 ++void stats_display_memp(struct stats_mem *mem, int index);
  2.2092 ++void stats_display_sys(struct stats_sys *sys);
  2.2093 + #else
  2.2094 + #define stats_display()
  2.2095 ++#define stats_display_proto(proto, name)
  2.2096 ++#define stats_display_igmp(igmp)
  2.2097 ++#define stats_display_mem(mem, name)
  2.2098 ++#define stats_display_memp(mem, index)
  2.2099 ++#define stats_display_sys(sys)
  2.2100 + #endif /* LWIP_STATS_DISPLAY */
  2.2101 + 
  2.2102 + #ifdef __cplusplus
  2.2103 +Index: src/include/lwip/tcpip.h
  2.2104 +===================================================================
  2.2105 +RCS file: /sources/lwip/lwip/src/include/lwip/tcpip.h,v
  2.2106 +retrieving revision 1.24
  2.2107 +retrieving revision 1.27
  2.2108 +diff -u -p -r1.24 -r1.27
  2.2109 +--- src/include/lwip/tcpip.h	12 Jan 2008 11:52:22 -0000	1.24
  2.2110 ++++ src/include/lwip/tcpip.h	27 Jun 2008 20:34:55 -0000	1.27
  2.2111 +@@ -83,7 +83,11 @@ err_t tcpip_netifapi_lock(struct netifap
  2.2112 + #endif /* LWIP_NETIF_API */
  2.2113 + 
  2.2114 + err_t tcpip_callback_with_block(void (*f)(void *ctx), void *ctx, u8_t block);
  2.2115 +-#define tcpip_callback(f,ctx) tcpip_callback_with_block(f,ctx,1)
  2.2116 ++#define tcpip_callback(f, ctx)              tcpip_callback_with_block(f, ctx, 1)
  2.2117 ++
  2.2118 ++/* free pbufs or heap memory from another context without blocking */
  2.2119 ++err_t pbuf_free_callback(struct pbuf *p);
  2.2120 ++err_t mem_free_callback(void *m);
  2.2121 + 
  2.2122 + err_t tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg);
  2.2123 + #define tcpip_untimeout(h, arg) tcpip_timeout(0xffffffff, h, arg)
  2.2124 +Index: src/include/netif/loopif.h
  2.2125 +===================================================================
  2.2126 +RCS file: /sources/lwip/lwip/src/include/netif/loopif.h,v
  2.2127 +retrieving revision 1.7
  2.2128 +retrieving revision 1.9
  2.2129 +diff -u -p -r1.7 -r1.9
  2.2130 +--- src/include/netif/loopif.h	10 May 2007 10:59:20 -0000	1.7
  2.2131 ++++ src/include/netif/loopif.h	17 Jun 2008 20:12:22 -0000	1.9
  2.2132 +@@ -32,6 +32,7 @@
  2.2133 + #ifndef __NETIF_LOOPIF_H__
  2.2134 + #define __NETIF_LOOPIF_H__
  2.2135 + 
  2.2136 ++#include "lwip/opt.h"
  2.2137 + #include "lwip/netif.h"
  2.2138 + #include "lwip/err.h"
  2.2139 + 
  2.2140 +@@ -39,9 +40,9 @@
  2.2141 + extern "C" {
  2.2142 + #endif
  2.2143 + 
  2.2144 +-#if !LWIP_LOOPIF_MULTITHREADING
  2.2145 +-void loopif_poll(struct netif *netif);
  2.2146 +-#endif
  2.2147 ++#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
  2.2148 ++#define loopif_poll netif_poll
  2.2149 ++#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
  2.2150 + 
  2.2151 + err_t loopif_init(struct netif *netif);
  2.2152 + 
  2.2153 +Index: src/netif/etharp.c
  2.2154 +===================================================================
  2.2155 +RCS file: /sources/lwip/lwip/src/netif/etharp.c,v
  2.2156 +retrieving revision 1.145
  2.2157 +retrieving revision 1.148
  2.2158 +diff -u -p -r1.145 -r1.148
  2.2159 +--- src/netif/etharp.c	4 Mar 2008 13:41:24 -0000	1.145
  2.2160 ++++ src/netif/etharp.c	19 Jun 2008 16:40:59 -0000	1.148
  2.2161 +@@ -353,7 +353,7 @@ find_entry(struct ip_addr *ipaddr, u8_t 
  2.2162 +    * 1) empty entry
  2.2163 +    * 2) oldest stable entry
  2.2164 +    * 3) oldest pending entry without queued packets
  2.2165 +-   * 4) oldest pending entry without queued packets
  2.2166 ++   * 4) oldest pending entry with queued packets
  2.2167 +    * 
  2.2168 +    * { ETHARP_TRY_HARD is set at this point }
  2.2169 +    */ 
  2.2170 +@@ -1130,7 +1130,14 @@ ethernet_input(struct pbuf *p, struct ne
  2.2171 + 
  2.2172 +   /* points to packet payload, which starts with an Ethernet header */
  2.2173 +   ethhdr = p->payload;
  2.2174 +-  
  2.2175 ++  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE,
  2.2176 ++    ("ethernet_input: dest:%02x:%02x:%02x:%02x:%02x:%02x, src:%02x:%02x:%02x:%02x:%02x:%02x, type:%2hx\n",
  2.2177 ++     (unsigned)ethhdr->dest.addr[0], (unsigned)ethhdr->dest.addr[1], (unsigned)ethhdr->dest.addr[2],
  2.2178 ++     (unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5],
  2.2179 ++     (unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2],
  2.2180 ++     (unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5],
  2.2181 ++     (unsigned)htons(ethhdr->type)));
  2.2182 ++
  2.2183 +   switch (htons(ethhdr->type)) {
  2.2184 +     /* IP packet? */
  2.2185 +     case ETHTYPE_IP:
  2.2186 +@@ -1165,6 +1172,8 @@ ethernet_input(struct pbuf *p, struct ne
  2.2187 + #endif /* PPPOE_SUPPORT */
  2.2188 + 
  2.2189 +     default:
  2.2190 ++      ETHARP_STATS_INC(etharp.proterr);
  2.2191 ++      ETHARP_STATS_INC(etharp.drop);
  2.2192 +       pbuf_free(p);
  2.2193 +       p = NULL;
  2.2194 +       break;
  2.2195 +Index: src/netif/loopif.c
  2.2196 +===================================================================
  2.2197 +RCS file: /sources/lwip/lwip/src/netif/loopif.c,v
  2.2198 +retrieving revision 1.26
  2.2199 +retrieving revision 1.27
  2.2200 +diff -u -p -r1.26 -r1.27
  2.2201 +--- src/netif/loopif.c	31 Aug 2007 10:14:09 -0000	1.26
  2.2202 ++++ src/netif/loopif.c	12 Jun 2008 20:10:10 -0000	1.27
  2.2203 +@@ -40,149 +40,8 @@
  2.2204 + #if LWIP_HAVE_LOOPIF
  2.2205 + 
  2.2206 + #include "netif/loopif.h"
  2.2207 +-#include "lwip/pbuf.h"
  2.2208 + #include "lwip/snmp.h"
  2.2209 + 
  2.2210 +-#include <string.h>
  2.2211 +-
  2.2212 +-#if !LWIP_LOOPIF_MULTITHREADING
  2.2213 +-
  2.2214 +-#include "lwip/sys.h"
  2.2215 +-#include "lwip/mem.h"
  2.2216 +-
  2.2217 +-/* helper struct for the linked list of pbufs */
  2.2218 +-struct loopif_private {
  2.2219 +-  struct pbuf *first;
  2.2220 +-  struct pbuf *last;
  2.2221 +-};
  2.2222 +-
  2.2223 +-/**
  2.2224 +- * Call loopif_poll() in the main loop of your application. This is to prevent
  2.2225 +- * reentering non-reentrant functions like tcp_input(). Packets passed to
  2.2226 +- * loopif_output() are put on a list that is passed to netif->input() by
  2.2227 +- * loopif_poll().
  2.2228 +- *
  2.2229 +- * @param netif the lwip network interface structure for this loopif
  2.2230 +- */
  2.2231 +-void
  2.2232 +-loopif_poll(struct netif *netif)
  2.2233 +-{
  2.2234 +-  SYS_ARCH_DECL_PROTECT(lev);
  2.2235 +-  struct pbuf *in, *in_end;
  2.2236 +-  struct loopif_private *priv = (struct loopif_private*)netif->state;
  2.2237 +-
  2.2238 +-  LWIP_ERROR("priv != NULL", (priv != NULL), return;);
  2.2239 +-
  2.2240 +-  do {
  2.2241 +-    /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */
  2.2242 +-    SYS_ARCH_PROTECT(lev);
  2.2243 +-    in = priv->first;
  2.2244 +-    if(in) {
  2.2245 +-      in_end = in;
  2.2246 +-      while(in_end->len != in_end->tot_len) {
  2.2247 +-        LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
  2.2248 +-        in_end = in_end->next;
  2.2249 +-      }
  2.2250 +-      /* 'in_end' now points to the last pbuf from 'in' */
  2.2251 +-      if(in_end == priv->last) {
  2.2252 +-        /* this was the last pbuf in the list */
  2.2253 +-        priv->first = priv->last = NULL;
  2.2254 +-      } else {
  2.2255 +-        /* pop the pbuf off the list */
  2.2256 +-        priv->first = in_end->next;
  2.2257 +-        LWIP_ASSERT("should not be null since first != last!", priv->first != NULL);
  2.2258 +-      }
  2.2259 +-    }
  2.2260 +-    SYS_ARCH_UNPROTECT(lev);
  2.2261 +-  
  2.2262 +-    if(in != NULL) {
  2.2263 +-      if(in_end->next != NULL) {
  2.2264 +-        /* De-queue the pbuf from its successors on the 'priv' list. */
  2.2265 +-        in_end->next = NULL;
  2.2266 +-      }
  2.2267 +-      if(netif->input(in, netif) != ERR_OK) {
  2.2268 +-        pbuf_free(in);
  2.2269 +-      }
  2.2270 +-      /* Don't reference the packet any more! */
  2.2271 +-      in = NULL;
  2.2272 +-      in_end = NULL;
  2.2273 +-    }
  2.2274 +-  /* go on while there is a packet on the list */
  2.2275 +-  } while(priv->first != NULL);
  2.2276 +-}
  2.2277 +-#endif /* LWIP_LOOPIF_MULTITHREADING */
  2.2278 +-
  2.2279 +-/**
  2.2280 +- * Send an IP packet over the loopback interface.
  2.2281 +- * The pbuf is simply copied and handed back to netif->input.
  2.2282 +- * In multithreaded mode, this is done directly since netif->input must put
  2.2283 +- * the packet on a queue.
  2.2284 +- * In callback mode, the packet is put on an internal queue and is fed to
  2.2285 +- * netif->input by loopif_poll().
  2.2286 +- *
  2.2287 +- * @param netif the lwip network interface structure for this loopif
  2.2288 +- * @param p the (IP) packet to 'send'
  2.2289 +- * @param ipaddr the ip address to send the packet to (not used for loopif)
  2.2290 +- * @return ERR_OK if the packet has been sent
  2.2291 +- *         ERR_MEM if the pbuf used to copy the packet couldn't be allocated
  2.2292 +- */
  2.2293 +-static err_t
  2.2294 +-loopif_output(struct netif *netif, struct pbuf *p,
  2.2295 +-       struct ip_addr *ipaddr)
  2.2296 +-{
  2.2297 +-#if !LWIP_LOOPIF_MULTITHREADING
  2.2298 +-  SYS_ARCH_DECL_PROTECT(lev);
  2.2299 +-  struct loopif_private *priv;
  2.2300 +-  struct pbuf *last;
  2.2301 +-#endif /* LWIP_LOOPIF_MULTITHREADING */
  2.2302 +-  struct pbuf *r;
  2.2303 +-  err_t err;
  2.2304 +-
  2.2305 +-  LWIP_UNUSED_ARG(ipaddr);
  2.2306 +-
  2.2307 +-  /* Allocate a new pbuf */
  2.2308 +-  r = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
  2.2309 +-  if (r == NULL) {
  2.2310 +-    return ERR_MEM;
  2.2311 +-  }
  2.2312 +-
  2.2313 +-  /* Copy the whole pbuf queue p into the single pbuf r */
  2.2314 +-  if ((err = pbuf_copy(r, p)) != ERR_OK) {
  2.2315 +-    pbuf_free(r);
  2.2316 +-    r = NULL;
  2.2317 +-    return err;
  2.2318 +-  }
  2.2319 +-
  2.2320 +-#if LWIP_LOOPIF_MULTITHREADING
  2.2321 +-  /* Multithreading environment, netif->input() is supposed to put the packet
  2.2322 +-     into a mailbox, so we can safely call it here without risking to re-enter
  2.2323 +-     functions that are not reentrant (TCP!!!) */
  2.2324 +-  if(netif->input(r, netif) != ERR_OK) {
  2.2325 +-    pbuf_free(r);
  2.2326 +-    r = NULL;
  2.2327 +-  }
  2.2328 +-#else /* LWIP_LOOPIF_MULTITHREADING */
  2.2329 +-  /* Raw API without threads: put the packet on a linked list which gets emptied
  2.2330 +-     through calling loopif_poll(). */
  2.2331 +-  priv = (struct loopif_private*)netif->state;
  2.2332 +-
  2.2333 +-  /* let last point to the last pbuf in chain r */
  2.2334 +-  for (last = r; last->next != NULL; last = last->next);
  2.2335 +-  SYS_ARCH_PROTECT(lev);
  2.2336 +-  if(priv->first != NULL) {
  2.2337 +-    LWIP_ASSERT("if first != NULL, last must also be != NULL", priv->last != NULL);
  2.2338 +-    priv->last->next = r;
  2.2339 +-    priv->last = last;
  2.2340 +-  } else {
  2.2341 +-    priv->first = r;
  2.2342 +-    priv->last = last;
  2.2343 +-  }
  2.2344 +-  SYS_ARCH_UNPROTECT(lev);
  2.2345 +-#endif /* LWIP_LOOPIF_MULTITHREADING */
  2.2346 +-
  2.2347 +-  return ERR_OK;    
  2.2348 +-}
  2.2349 +-
  2.2350 + /**
  2.2351 +  * Initialize a lwip network interface structure for a loopback interface
  2.2352 +  *
  2.2353 +@@ -193,16 +52,6 @@ loopif_output(struct netif *netif, struc
  2.2354 + err_t
  2.2355 + loopif_init(struct netif *netif)
  2.2356 + {
  2.2357 +-#if !LWIP_LOOPIF_MULTITHREADING
  2.2358 +-  struct loopif_private *priv;
  2.2359 +-
  2.2360 +-  priv = (struct loopif_private*)mem_malloc(sizeof(struct loopif_private));
  2.2361 +-  if(priv == NULL) 
  2.2362 +-    return ERR_MEM;
  2.2363 +-  priv->first = priv->last = NULL;
  2.2364 +-  netif->state = priv;
  2.2365 +-#endif /* LWIP_LOOPIF_MULTITHREADING */
  2.2366 +-
  2.2367 +   /* initialize the snmp variables and counters inside the struct netif
  2.2368 +    * ifSpeed: no assumption can be made!
  2.2369 +    */
  2.2370 +@@ -210,7 +59,7 @@ loopif_init(struct netif *netif)
  2.2371 + 
  2.2372 +   netif->name[0] = 'l';
  2.2373 +   netif->name[1] = 'o';
  2.2374 +-  netif->output = loopif_output;
  2.2375 ++  netif->output = netif_loop_output;
  2.2376 +   return ERR_OK;
  2.2377 + }
  2.2378 + 
  2.2379 +Index: src/netif/slipif.c
  2.2380 +===================================================================
  2.2381 +RCS file: /sources/lwip/lwip/src/netif/slipif.c,v
  2.2382 +retrieving revision 1.29
  2.2383 +retrieving revision 1.30
  2.2384 +diff -u -p -r1.29 -r1.30
  2.2385 +--- src/netif/slipif.c	30 Nov 2007 17:22:21 -0000	1.29
  2.2386 ++++ src/netif/slipif.c	17 Jun 2008 20:14:05 -0000	1.30
  2.2387 +@@ -44,6 +44,9 @@
  2.2388 + 
  2.2389 + #include "netif/slipif.h"
  2.2390 + #include "lwip/opt.h"
  2.2391 ++
  2.2392 ++#if LWIP_HAVE_SLIPIF
  2.2393 ++
  2.2394 + #include "lwip/def.h"
  2.2395 + #include "lwip/pbuf.h"
  2.2396 + #include "lwip/sys.h"
  2.2397 +@@ -273,3 +276,4 @@ slipif_init(struct netif *netif)
  2.2398 +   sys_thread_new(SLIPIF_THREAD_NAME, slipif_loop, netif, SLIPIF_THREAD_STACKSIZE, SLIPIF_THREAD_PRIO);
  2.2399 +   return ERR_OK;
  2.2400 + }
  2.2401 ++#endif /* LWIP_HAVE_SLIPIF */