? .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 --- a/CHANGELOG 23 Mar 2008 13:49:39 -0000 1.300 +++ b/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 + + 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 --- a/src/api/api_msg.c 21 Mar 2008 16:23:14 -0000 1.102 +++ b/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 --- a/src/api/err.c 13 Dec 2007 23:06:50 -0000 1.11 +++ b/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 --- a/src/api/netdb.c 26 Jan 2008 16:11:39 -0000 1.4 +++ b/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 --- a/src/api/sockets.c 13 Mar 2008 20:03:57 -0000 1.116 +++ b/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 --- a/src/api/tcpip.c 12 Jan 2008 11:52:22 -0000 1.70 +++ b/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 --- a/src/core/dhcp.c 4 Mar 2008 14:25:58 -0000 1.86 +++ b/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 --- a/src/core/mem.c 4 Mar 2008 16:31:32 -0000 1.59 +++ b/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 --- a/src/core/memp.c 25 Nov 2007 10:43:28 -0000 1.55 +++ b/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 --- a/src/core/netif.c 9 Oct 2007 20:00:55 -0000 1.65 +++ b/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 --- a/src/core/pbuf.c 4 Mar 2008 16:37:46 -0000 1.127 +++ b/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 --- a/src/core/stats.c 4 Mar 2008 16:31:32 -0000 1.27 +++ b/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 --- a/src/core/sys.c 25 Nov 2007 13:57:05 -0000 1.32 +++ b/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 --- a/src/core/tcp.c 22 Jan 2008 21:15:15 -0000 1.85 +++ b/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 --- a/src/core/tcp_in.c 22 Jan 2008 21:15:15 -0000 1.97 +++ b/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 --- a/src/core/ipv4/autoip.c 26 Jan 2008 16:11:40 -0000 1.16 +++ b/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 --- a/src/core/ipv4/inet_chksum.c 10 Mar 2008 16:12:31 -0000 1.4 +++ b/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 - /* 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 --- a/src/core/ipv4/ip.c 14 Jan 2008 20:53:23 -0000 1.66 +++ b/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 --- a/src/include/lwip/debug.h 22 Sep 2007 11:16:07 -0000 1.37 +++ b/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 --- a/src/include/lwip/err.h 13 Dec 2007 23:06:50 -0000 1.13 +++ b/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 --- a/src/include/lwip/mem.h 4 Mar 2008 16:31:32 -0000 1.21 +++ b/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 --- a/src/include/lwip/netif.h 9 Oct 2007 19:59:59 -0000 1.43 +++ b/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 --- a/src/include/lwip/opt.h 31 Jan 2008 18:19:29 -0000 1.116 +++ b/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 --- a/src/include/lwip/sio.h 6 Sep 2007 16:43:44 -0000 1.7 +++ b/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 --- a/src/include/lwip/sockets.h 2 Dec 2007 15:24:02 -0000 1.38 +++ b/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 --- a/src/include/lwip/stats.h 28 Nov 2007 21:25:07 -0000 1.19 +++ b/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 --- a/src/include/lwip/tcpip.h 12 Jan 2008 11:52:22 -0000 1.24 +++ b/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 --- a/src/include/netif/loopif.h 10 May 2007 10:59:20 -0000 1.7 +++ b/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 --- a/src/netif/etharp.c 4 Mar 2008 13:41:24 -0000 1.145 +++ b/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 --- a/src/netif/loopif.c 31 Aug 2007 10:14:09 -0000 1.26 +++ b/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 - -#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 --- a/src/netif/slipif.c 30 Nov 2007 17:22:21 -0000 1.29 +++ b/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 */