mirror of
https://git.savannah.nongnu.org/git/lwip.git
synced 2026-05-26 01:57:01 +08:00
bug #50837: add zero-window probe timeout
This commit adds a timeout to the zero-window probing (persist timer) mechanism. LwIP has not historically had a timeout for the persist timer, leading to unbounded blocking if connection drops during the zero-window condition This commit also adds two units test, one to check the RTO timeout and a second to check the zero-window probe timeout
This commit is contained in:
@@ -1072,17 +1072,21 @@ tcp_slowtmr_start:
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n"));
|
||||
} else {
|
||||
if (pcb->persist_backoff > 0) {
|
||||
/* If snd_wnd is zero, use persist timer to send 1 byte probes
|
||||
* instead of using the standard retransmission mechanism. */
|
||||
u8_t backoff_cnt = tcp_persist_backoff[pcb->persist_backoff-1];
|
||||
if (pcb->persist_cnt < backoff_cnt) {
|
||||
pcb->persist_cnt++;
|
||||
}
|
||||
if (pcb->persist_cnt >= backoff_cnt) {
|
||||
if (tcp_zero_window_probe(pcb) == ERR_OK) {
|
||||
pcb->persist_cnt = 0;
|
||||
if (pcb->persist_backoff < sizeof(tcp_persist_backoff)) {
|
||||
pcb->persist_backoff++;
|
||||
if (pcb->persist_probe >= TCP_MAXRTX) {
|
||||
++pcb_remove; /* max probes reached */
|
||||
} else {
|
||||
/* If snd_wnd is zero, use persist timer to send 1 byte probes
|
||||
* instead of using the standard retransmission mechanism. */
|
||||
u8_t backoff_cnt = tcp_persist_backoff[pcb->persist_backoff-1];
|
||||
if (pcb->persist_cnt < backoff_cnt) {
|
||||
pcb->persist_cnt++;
|
||||
}
|
||||
if (pcb->persist_cnt >= backoff_cnt) {
|
||||
if (tcp_zero_window_probe(pcb) == ERR_OK) {
|
||||
pcb->persist_cnt = 0;
|
||||
if (pcb->persist_backoff < sizeof(tcp_persist_backoff)) {
|
||||
pcb->persist_backoff++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -765,6 +765,7 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
pcb->tmr = tcp_ticks;
|
||||
}
|
||||
pcb->keep_cnt_sent = 0;
|
||||
pcb->persist_probe = 0;
|
||||
|
||||
tcp_parseopt(pcb);
|
||||
|
||||
@@ -1093,10 +1094,11 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
/* start persist timer */
|
||||
pcb->persist_cnt = 0;
|
||||
pcb->persist_backoff = 1;
|
||||
pcb->persist_probe = 0;
|
||||
}
|
||||
} else if (pcb->persist_backoff > 0) {
|
||||
/* stop persist timer */
|
||||
pcb->persist_backoff = 0;
|
||||
pcb->persist_backoff = 0;
|
||||
}
|
||||
LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"TCPWNDSIZE_F"\n", pcb->snd_wnd));
|
||||
#if TCP_WND_DEBUG
|
||||
|
||||
@@ -1103,6 +1103,7 @@ tcp_output(struct tcp_pcb *pcb)
|
||||
if (pcb->persist_backoff == 0) {
|
||||
pcb->persist_cnt = 0;
|
||||
pcb->persist_backoff = 1;
|
||||
pcb->persist_probe = 0;
|
||||
}
|
||||
goto output_done;
|
||||
}
|
||||
@@ -1638,6 +1639,14 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/* increment probe count. NOTE: we record probe even if it fails
|
||||
to actually transmit due to an error. This ensures memory exhaustion/
|
||||
routing problem doesn't leave a zero-window pcb as an indefinite zombie.
|
||||
RTO mechanism has similar behavior, see pcb->nrtx */
|
||||
if (pcb->persist_probe < 0xFF) {
|
||||
++pcb->persist_probe;
|
||||
}
|
||||
|
||||
is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0);
|
||||
/* we want to send one seqno: either FIN or data (no options) */
|
||||
len = is_fin ? 0 : 1;
|
||||
|
||||
Reference in New Issue
Block a user