bug #50476: initialize ssthresh to TCP_SND_BUF

This commit changes ssthresh to be the largest effective congestion
window (amount of in-flight data). This follows the guidance of RFC
5681 which recommends setting ssthresh arbitrarily high.

LwIP was previously using the receive window value at the end of the
3-way handshake and in the case of an active open where the receiver
used window scaling and/or window auto-tuning, this resulted in a very
small ssthresh value even though the window ramped up once the connection
was established

(cherry picked from commit b90a54f989)
This commit is contained in:
Joel Cunningham 2017-03-07 20:53:02 -06:00 committed by goldsimon
parent 2848b17e80
commit 2452bc9336
2 changed files with 8 additions and 12 deletions

View File

@ -948,7 +948,6 @@ tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port,
pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip); pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip);
#endif /* TCP_CALCULATE_EFF_SEND_MSS */ #endif /* TCP_CALCULATE_EFF_SEND_MSS */
pcb->cwnd = 1; pcb->cwnd = 1;
pcb->ssthresh = TCP_WND;
#if LWIP_CALLBACK_API #if LWIP_CALLBACK_API
pcb->connected = connected; pcb->connected = connected;
#else /* LWIP_CALLBACK_API */ #else /* LWIP_CALLBACK_API */
@ -1615,6 +1614,14 @@ tcp_alloc(u8_t prio)
pcb->tmr = tcp_ticks; pcb->tmr = tcp_ticks;
pcb->last_timer = tcp_timer_ctr; pcb->last_timer = tcp_timer_ctr;
/* RFC 5681 recommends setting ssthresh abritrarily high and gives an example
of using the largest advertised receive window. We've seen complications with
receiving TCPs that use window scaling and/or window auto-tuning where the
initial advertised window is very small and then grows rapidly once the
connection is established. To avoid these complications, we set ssthresh to the
largest effective cwnd (amount of in-flight data) that the sender can have. */
pcb->ssthresh = TCP_SND_BUF;
#if LWIP_CALLBACK_API #if LWIP_CALLBACK_API
pcb->recv = tcp_recv_null; pcb->recv = tcp_recv_null;
#endif /* LWIP_CALLBACK_API */ #endif /* LWIP_CALLBACK_API */

View File

@ -61,8 +61,6 @@
/** Initial CWND calculation as defined RFC 2581 */ /** Initial CWND calculation as defined RFC 2581 */
#define LWIP_TCP_CALC_INITIAL_CWND(mss) LWIP_MIN((4U * (mss)), LWIP_MAX((2U * (mss)), 4380U)); #define LWIP_TCP_CALC_INITIAL_CWND(mss) LWIP_MIN((4U * (mss)), LWIP_MAX((2U * (mss)), 4380U));
/** Initial slow start threshold value: we use the full window */
#define LWIP_TCP_INITIAL_SSTHRESH(pcb) ((pcb)->snd_wnd)
/* These variables are global to all functions involved in the input /* These variables are global to all functions involved in the input
processing of TCP segments. They are set by the tcp_input() processing of TCP segments. They are set by the tcp_input()
@ -615,7 +613,6 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
tcp_parseopt(npcb); tcp_parseopt(npcb);
npcb->snd_wnd = tcphdr->wnd; npcb->snd_wnd = tcphdr->wnd;
npcb->snd_wnd_max = npcb->snd_wnd; npcb->snd_wnd_max = npcb->snd_wnd;
npcb->ssthresh = LWIP_TCP_INITIAL_SSTHRESH(npcb);
#if TCP_CALCULATE_EFF_SEND_MSS #if TCP_CALCULATE_EFF_SEND_MSS
npcb->mss = tcp_eff_send_mss(npcb->mss, &npcb->local_ip, &npcb->remote_ip); npcb->mss = tcp_eff_send_mss(npcb->mss, &npcb->local_ip, &npcb->remote_ip);
@ -771,9 +768,6 @@ tcp_process(struct tcp_pcb *pcb)
pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip); pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip);
#endif /* TCP_CALCULATE_EFF_SEND_MSS */ #endif /* TCP_CALCULATE_EFF_SEND_MSS */
/* Set ssthresh again after changing 'mss' and 'snd_wnd' */
pcb->ssthresh = LWIP_TCP_INITIAL_SSTHRESH(pcb);
pcb->cwnd = LWIP_TCP_CALC_INITIAL_CWND(pcb->mss); pcb->cwnd = LWIP_TCP_CALC_INITIAL_CWND(pcb->mss);
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_process (SENT): cwnd %"TCPWNDSIZE_F LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_process (SENT): cwnd %"TCPWNDSIZE_F
" ssthresh %"TCPWNDSIZE_F"\n", " ssthresh %"TCPWNDSIZE_F"\n",
@ -855,11 +849,6 @@ tcp_process(struct tcp_pcb *pcb)
* we'd better pass it on to the application as well. */ * we'd better pass it on to the application as well. */
tcp_receive(pcb); tcp_receive(pcb);
/* passive open: update initial ssthresh now that the correct window is
known: if the remote side supports window scaling, the window sent
with the initial SYN can be smaller than the one used later */
pcb->ssthresh = LWIP_TCP_INITIAL_SSTHRESH(pcb);
/* Prevent ACK for SYN to generate a sent event */ /* Prevent ACK for SYN to generate a sent event */
if (recv_acked != 0) { if (recv_acked != 0) {
recv_acked--; recv_acked--;