2007-12-20 Kieran Mansley (based on patch from Per-Henrik Lundbolm)

* tcp.c, tcp_in.c, tcp_out.c, tcp.h: fix bug #20199 (better handling
    of silly window avoidance and prevent lwIP from shrinking the window)
This commit is contained in:
kieranm 2007-12-20 14:51:35 +00:00
parent fc2d28b851
commit 8cc32bc29c
5 changed files with 44 additions and 29 deletions

View File

@ -526,6 +526,10 @@ HISTORY
++ Bug fixes:
2007-12-20 Kieran Mansley (based on patch from Per-Henrik Lundbolm)
* tcp.c, tcp_in.c, tcp_out.c, tcp.h: fix bug #20199 (better handling
of silly window avoidance and prevent lwIP from shrinking the window)
2007-12-04 Simon Goldschmidt
* tcp.c, tcp_in.c: fix bug #21699 (segment leak in ooseq processing when last
data packet was lost): add assert that all segment lists are empty in

View File

@ -385,9 +385,14 @@ tcp_recved(struct tcp_pcb *pcb, u16_t len)
{
if ((u32_t)pcb->rcv_wnd + len > TCP_WND) {
pcb->rcv_wnd = TCP_WND;
pcb->rcv_ann_wnd = TCP_WND;
} else {
pcb->rcv_wnd += len;
if (pcb->rcv_wnd >= pcb->mss) {
pcb->rcv_ann_wnd = pcb->rcv_wnd;
}
}
if (!(pcb->flags & TF_ACK_DELAY) &&
!(pcb->flags & TF_ACK_NOW)) {
/*
@ -494,6 +499,7 @@ tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
pcb->lastack = iss - 1;
pcb->snd_lbb = iss - 1;
pcb->rcv_wnd = TCP_WND;
pcb->rcv_ann_wnd = TCP_WND;
pcb->snd_wnd = TCP_WND;
/* The send MSS is updated when an MSS option is received. */
pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;
@ -936,6 +942,7 @@ tcp_alloc(u8_t prio)
pcb->snd_buf = TCP_SND_BUF;
pcb->snd_queuelen = 0;
pcb->rcv_wnd = TCP_WND;
pcb->rcv_ann_wnd = TCP_WND;
pcb->tos = 0;
pcb->ttl = TCP_TTL;
/* The send MSS is updated when an MSS option is received. */

View File

@ -477,10 +477,8 @@ tcp_process(struct tcp_pcb *pcb)
acceptable = 1;
}
} else {
/*if (TCP_SEQ_GEQ(seqno, pcb->rcv_nxt) &&
TCP_SEQ_LEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {
*/
if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) {
if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
pcb->rcv_nxt+pcb->rcv_ann_wnd)) {
acceptable = 1;
}
}
@ -549,7 +547,7 @@ tcp_process(struct tcp_pcb *pcb)
/* Call the user specified function to call when sucessfully
* connected. */
TCP_EVENT_CONNECTED(pcb, ERR_OK, err);
tcp_ack(pcb);
tcp_ack_now(pcb);
}
/* received ACK? possibly a half-open connection */
else if (flags & TCP_ACK) {
@ -1001,9 +999,8 @@ tcp_receive(struct tcp_pcb *pcb)
/* The sequence number must be within the window (above rcv_nxt
and below rcv_nxt + rcv_wnd) in order to be further
processed. */
/*if (TCP_SEQ_GEQ(seqno, pcb->rcv_nxt) &&
TCP_SEQ_LT(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/
if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd - 1)){
if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
pcb->rcv_nxt + pcb->rcv_ann_wnd - 1)){
if (pcb->rcv_nxt == seqno) {
accepted_inseq = 1;
/* The incoming segment is the next in sequence. We check if
@ -1045,6 +1042,12 @@ tcp_receive(struct tcp_pcb *pcb)
pcb->rcv_wnd -= tcplen;
}
if (pcb->rcv_ann_wnd < tcplen) {
pcb->rcv_ann_wnd = 0;
} else {
pcb->rcv_ann_wnd -= tcplen;
}
/* If there is data in the segment, we make preparations to
pass this up to the application. The ->recv_data variable
is used for holding the pbuf that goes to the
@ -1081,6 +1084,12 @@ tcp_receive(struct tcp_pcb *pcb)
} else {
pcb->rcv_wnd -= TCP_TCPLEN(cseg);
}
if (pcb->rcv_ann_wnd < TCP_TCPLEN(cseg)) {
pcb->rcv_ann_wnd = 0;
} else {
pcb->rcv_ann_wnd -= TCP_TCPLEN(cseg);
}
if (cseg->p->tot_len > 0) {
/* Chain this pbuf onto the pbuf that we will pass to
the application. */
@ -1235,9 +1244,8 @@ tcp_receive(struct tcp_pcb *pcb)
}
} else {
/*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) ||
TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/
if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){
if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
pcb->rcv_nxt + pcb->rcv_ann_wnd-1)){
tcp_ack_now(pcb);
}
}

View File

@ -460,7 +460,7 @@ tcp_output(struct tcp_pcb *pcb)
tcphdr->seqno = htonl(pcb->snd_nxt);
tcphdr->ackno = htonl(pcb->rcv_nxt);
TCPH_FLAGS_SET(tcphdr, TCP_ACK);
tcphdr->wnd = htons(pcb->rcv_wnd);
tcphdr->wnd = htons(pcb->rcv_ann_wnd);
tcphdr->urgp = 0;
TCPH_HDRLEN_SET(tcphdr, 5);
@ -593,13 +593,8 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
wnd fields remain. */
seg->tcphdr->ackno = htonl(pcb->rcv_nxt);
/* silly window avoidance */
if (pcb->rcv_wnd < pcb->mss) {
seg->tcphdr->wnd = 0;
} else {
/* advertise our receive window size in this TCP segment */
seg->tcphdr->wnd = htons(pcb->rcv_wnd);
}
/* advertise our receive window size in this TCP segment */
seg->tcphdr->wnd = htons(pcb->rcv_ann_wnd);
/* If we don't have a local IP address, we get one by
calling ip_route(). */
@ -815,15 +810,15 @@ tcp_keepalive(struct tcp_pcb *pcb)
LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
(p->len >= sizeof(struct tcp_hdr)));
tcphdr = p->payload;
tcphdr->src = htons(pcb->local_port);
tcphdr->dest = htons(pcb->remote_port);
tcphdr->seqno = htonl(pcb->snd_nxt - 1);
tcphdr->ackno = htonl(pcb->rcv_nxt);
TCPH_FLAGS_SET(tcphdr, 0);
tcphdr->wnd = htons(pcb->rcv_wnd);
tcphdr->urgp = 0;
TCPH_HDRLEN_SET(tcphdr, 5);
tcphdr = p->payload;
tcphdr->src = htons(pcb->local_port);
tcphdr->dest = htons(pcb->remote_port);
tcphdr->seqno = htonl(pcb->snd_nxt - 1);
tcphdr->ackno = htonl(pcb->rcv_nxt);
TCPH_FLAGS_SET(tcphdr, 0);
tcphdr->wnd = htons(pcb->rcv_ann_wnd);
tcphdr->urgp = 0;
TCPH_HDRLEN_SET(tcphdr, 5);
tcphdr->chksum = 0;
#if CHECKSUM_GEN_TCP

View File

@ -281,7 +281,8 @@ struct tcp_pcb {
/* receiver variables */
u32_t rcv_nxt; /* next seqno expected */
u16_t rcv_wnd; /* receiver window */
u16_t rcv_ann_wnd; /* announced receive window */
/* Timers */
u32_t tmr;
u8_t polltmr, pollinterval;