tcp: fix cwnd rollover introduced by ABC

Changes for TCP Appropriate Byte Counting introduce a potential cwnd
rollover by not taking into account integer promotion on tcpwnd_size_t
during inequality comparisions

This fixes the issue by introducing a macro TCP_WND_INC which detects
the rollover correctly and now holds the tcpwnd_size_t at the maximum
value rather than not incrementing the window.  This provides a slight
performance improvement by allowing full use of the tcpwnd_size_t number
space for the congestion window
This commit is contained in:
Joel Cunningham 2017-06-01 12:31:17 -05:00
parent 0df2c4f2be
commit 3eaf976152
2 changed files with 13 additions and 13 deletions

View File

@ -1200,22 +1200,14 @@ tcp_receive(struct tcp_pcb *pcb)
u8_t num_seg = (pcb->flags & TF_RTO) ? 1 : 2;
/* RFC 3465, section 2.2 Slow Start */
increase = LWIP_MIN(acked, (tcpwnd_size_t)(num_seg * pcb->mss));
if (pcb->cwnd + increase > pcb->cwnd) {
pcb->cwnd += increase;
}
TCP_WND_INC(pcb->cwnd, increase);
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"TCPWNDSIZE_F"\n", pcb->cwnd));
} else {
tcpwnd_size_t new_cwnd = pcb->cwnd;
/* RFC 3465, section 2.1 Congestion Avoidance */
if (pcb->bytes_acked + acked > pcb->bytes_acked) {
pcb->bytes_acked += acked;
if (pcb->bytes_acked >= pcb->cwnd) {
pcb->bytes_acked -= pcb->cwnd;
new_cwnd = pcb->cwnd + pcb->mss;
}
}
if (new_cwnd > pcb->cwnd) {
pcb->cwnd = new_cwnd;
TCP_WND_INC(pcb->bytes_acked, acked);
if (pcb->bytes_acked >= pcb->cwnd) {
pcb->bytes_acked -= pcb->cwnd;
TCP_WND_INC(pcb->cwnd, pcb->mss);
}
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"TCPWNDSIZE_F"\n", pcb->cwnd));
}

View File

@ -143,6 +143,14 @@ typedef err_t (*tcp_connected_fn)(void *arg, struct tcp_pcb *tpcb, err_t err);
#define TCPWND16(x) (x)
#define TCP_WND_MAX(pcb) TCP_WND
#endif
/* Increments a tcpwnd_size_t and holds at max value rather than rollover */
#define TCP_WND_INC(wnd, inc) do { \
if ((tcpwnd_size_t)(wnd + inc) >= wnd) { \
wnd += inc; \
} else { \
wnd = (tcpwnd_size_t)-1; \
} \
} while(0)
#if LWIP_WND_SCALE || TCP_LISTEN_BACKLOG || LWIP_TCP_TIMESTAMPS
typedef u16_t tcpflags_t;