diff --git a/CHANGELOG b/CHANGELOG index 9e7e1e57..3a2b17d1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -19,6 +19,10 @@ HISTORY ++ New features: + 2010-01-27: Simon Goldschmidt + * opt.h, tcp.h, init.c, api_msg.c: Added TCP_SNDQUEUELOWAT corresponding + to TCP_SNDLOWAT and added tcp_sndqueuelen() - this fixes bug #28605 + 2010-01-26: Simon Goldschmidt * snmp: Use memp pools for snmp instead of the heap; added 4 new pools. diff --git a/src/api/api_msg.c b/src/api/api_msg.c index cddd6f93..c796769d 100644 --- a/src/api/api_msg.c +++ b/src/api/api_msg.c @@ -292,7 +292,10 @@ sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len) } if (conn) { - if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT)) { + /* If the queued byte- or pbuf-count drops below the configured low-water limit, + let select mark this pcb as writable again. */ + if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) && + (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) { API_EVENT(conn, NETCONN_EVT_SENDPLUS, len); } } @@ -1101,7 +1104,10 @@ do_writemore(struct netconn *conn) conn->state = NETCONN_NONE; } err = tcp_output_nagle(conn->pcb.tcp); - if ((err == ERR_OK) && (tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT)) { + /* If the queued byte- or pbuf-count exceeds the configured low-water limit, + let select mark this pcb as non-writable. */ + if ((err == ERR_OK) && (tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT) || + (tcp_sndqueuelen(conn->pcb.tcp) >= TCP_SNDQUEUELOWAT)) { API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); } } else if (err == ERR_MEM) { diff --git a/src/core/init.c b/src/core/init.c index 944ffb54..2af563cf 100644 --- a/src/core/init.c +++ b/src/core/init.c @@ -219,8 +219,10 @@ lwip_sanity_check(void) LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly\n")); if (TCP_SND_QUEUELEN < (2 * (TCP_SND_BUF/TCP_MSS))) LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_SND_QUEUELEN must be at least as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work\n")); - if (TCP_SNDLOWAT > TCP_SND_BUF) - LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than or equal to TCP_SND_BUF.\n")); + if (TCP_SNDLOWAT >= TCP_SND_BUF) + LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than TCP_SND_BUF.\n")); + if (TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN) + LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_SNDQUEUELOWAT must be less than TCP_SND_QUEUELEN.\n")); if (TCP_WND > (PBUF_POOL_SIZE*PBUF_POOL_BUFSIZE)) LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_WND is larger than space provided by PBUF_POOL_SIZE*PBUF_POOL_BUFSIZE\n")); if (TCP_WND < TCP_MSS) diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h index cb65964c..73dbc269 100644 --- a/src/include/lwip/opt.h +++ b/src/include/lwip/opt.h @@ -901,14 +901,23 @@ #endif /** - * TCP_SNDLOWAT: TCP writable space (bytes). This must be less than or equal - * to TCP_SND_BUF. It is the amount of space which must be available in the - * TCP snd_buf for select to return writable. + * TCP_SNDLOWAT: TCP writable space (bytes). This must be less than + * TCP_SND_BUF. It is the amount of space which must be available in the + * TCP snd_buf for select to return writable (combined with TCP_SNDQUEUELOWAT). */ #ifndef TCP_SNDLOWAT #define TCP_SNDLOWAT ((TCP_SND_BUF)/2) #endif +/** + * TCP_SNDQUEUELOWAT: TCP writable bufs (pbuf count). This must be grater + * than TCP_SND_QUEUELEN. If the number of pbufs queued on a pcb drops below + * this number, select returns writable (combined with TCP_SNDLOWAT). + */ +#ifndef TCP_SNDQUEUELOWAT +#define TCP_SNDQUEUELOWAT ((TCP_SND_QUEUELEN)/2) +#endif + /** * TCP_LISTEN_BACKLOG: Enable the backlog option for tcp listen pcb. */ diff --git a/src/include/lwip/tcp.h b/src/include/lwip/tcp.h index dc392ac9..1a9b2629 100644 --- a/src/include/lwip/tcp.h +++ b/src/include/lwip/tcp.h @@ -142,11 +142,12 @@ void tcp_sent (struct tcp_pcb *pcb, tcp_sent_fn sent); void tcp_poll (struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval); void tcp_err (struct tcp_pcb *pcb, tcp_err_fn err); -#define tcp_mss(pcb) ((pcb)->mss) -#define tcp_sndbuf(pcb) ((pcb)->snd_buf) -#define tcp_nagle_disable(pcb) ((pcb)->flags |= TF_NODELAY) -#define tcp_nagle_enable(pcb) ((pcb)->flags &= ~TF_NODELAY) -#define tcp_nagle_disabled(pcb) (((pcb)->flags & TF_NODELAY) != 0) +#define tcp_mss(pcb) ((pcb)->mss) +#define tcp_sndbuf(pcb) ((pcb)->snd_buf) +#define tcp_sndqueuelen(pcb) ((pcb)->snd_queuelen) +#define tcp_nagle_disable(pcb) ((pcb)->flags |= TF_NODELAY) +#define tcp_nagle_enable(pcb) ((pcb)->flags &= ~TF_NODELAY) +#define tcp_nagle_disabled(pcb) (((pcb)->flags & TF_NODELAY) != 0) #if TCP_LISTEN_BACKLOG #define tcp_accepted(pcb) (((struct tcp_pcb_listen *)(pcb))->accepts_pending--)