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