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