mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-10-01 04:12:07 +00:00
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:
parent
fc2d28b851
commit
8cc32bc29c
@ -526,6 +526,10 @@ HISTORY
|
|||||||
|
|
||||||
++ Bug fixes:
|
++ 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
|
2007-12-04 Simon Goldschmidt
|
||||||
* tcp.c, tcp_in.c: fix bug #21699 (segment leak in ooseq processing when last
|
* 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
|
data packet was lost): add assert that all segment lists are empty in
|
||||||
|
@ -385,9 +385,14 @@ tcp_recved(struct tcp_pcb *pcb, u16_t len)
|
|||||||
{
|
{
|
||||||
if ((u32_t)pcb->rcv_wnd + len > TCP_WND) {
|
if ((u32_t)pcb->rcv_wnd + len > TCP_WND) {
|
||||||
pcb->rcv_wnd = TCP_WND;
|
pcb->rcv_wnd = TCP_WND;
|
||||||
|
pcb->rcv_ann_wnd = TCP_WND;
|
||||||
} else {
|
} else {
|
||||||
pcb->rcv_wnd += len;
|
pcb->rcv_wnd += len;
|
||||||
|
if (pcb->rcv_wnd >= pcb->mss) {
|
||||||
|
pcb->rcv_ann_wnd = pcb->rcv_wnd;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!(pcb->flags & TF_ACK_DELAY) &&
|
if (!(pcb->flags & TF_ACK_DELAY) &&
|
||||||
!(pcb->flags & TF_ACK_NOW)) {
|
!(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->lastack = iss - 1;
|
||||||
pcb->snd_lbb = iss - 1;
|
pcb->snd_lbb = iss - 1;
|
||||||
pcb->rcv_wnd = TCP_WND;
|
pcb->rcv_wnd = TCP_WND;
|
||||||
|
pcb->rcv_ann_wnd = TCP_WND;
|
||||||
pcb->snd_wnd = TCP_WND;
|
pcb->snd_wnd = TCP_WND;
|
||||||
/* The send MSS is updated when an MSS option is received. */
|
/* The send MSS is updated when an MSS option is received. */
|
||||||
pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;
|
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_buf = TCP_SND_BUF;
|
||||||
pcb->snd_queuelen = 0;
|
pcb->snd_queuelen = 0;
|
||||||
pcb->rcv_wnd = TCP_WND;
|
pcb->rcv_wnd = TCP_WND;
|
||||||
|
pcb->rcv_ann_wnd = TCP_WND;
|
||||||
pcb->tos = 0;
|
pcb->tos = 0;
|
||||||
pcb->ttl = TCP_TTL;
|
pcb->ttl = TCP_TTL;
|
||||||
/* The send MSS is updated when an MSS option is received. */
|
/* The send MSS is updated when an MSS option is received. */
|
||||||
|
@ -477,10 +477,8 @@ tcp_process(struct tcp_pcb *pcb)
|
|||||||
acceptable = 1;
|
acceptable = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/*if (TCP_SEQ_GEQ(seqno, pcb->rcv_nxt) &&
|
if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
|
||||||
TCP_SEQ_LEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {
|
pcb->rcv_nxt+pcb->rcv_ann_wnd)) {
|
||||||
*/
|
|
||||||
if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) {
|
|
||||||
acceptable = 1;
|
acceptable = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -549,7 +547,7 @@ tcp_process(struct tcp_pcb *pcb)
|
|||||||
/* Call the user specified function to call when sucessfully
|
/* Call the user specified function to call when sucessfully
|
||||||
* connected. */
|
* connected. */
|
||||||
TCP_EVENT_CONNECTED(pcb, ERR_OK, err);
|
TCP_EVENT_CONNECTED(pcb, ERR_OK, err);
|
||||||
tcp_ack(pcb);
|
tcp_ack_now(pcb);
|
||||||
}
|
}
|
||||||
/* received ACK? possibly a half-open connection */
|
/* received ACK? possibly a half-open connection */
|
||||||
else if (flags & TCP_ACK) {
|
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
|
/* The sequence number must be within the window (above rcv_nxt
|
||||||
and below rcv_nxt + rcv_wnd) in order to be further
|
and below rcv_nxt + rcv_wnd) in order to be further
|
||||||
processed. */
|
processed. */
|
||||||
/*if (TCP_SEQ_GEQ(seqno, pcb->rcv_nxt) &&
|
if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
|
||||||
TCP_SEQ_LT(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/
|
pcb->rcv_nxt + pcb->rcv_ann_wnd - 1)){
|
||||||
if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd - 1)){
|
|
||||||
if (pcb->rcv_nxt == seqno) {
|
if (pcb->rcv_nxt == seqno) {
|
||||||
accepted_inseq = 1;
|
accepted_inseq = 1;
|
||||||
/* The incoming segment is the next in sequence. We check if
|
/* 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;
|
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
|
/* If there is data in the segment, we make preparations to
|
||||||
pass this up to the application. The ->recv_data variable
|
pass this up to the application. The ->recv_data variable
|
||||||
is used for holding the pbuf that goes to the
|
is used for holding the pbuf that goes to the
|
||||||
@ -1081,6 +1084,12 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||||||
} else {
|
} else {
|
||||||
pcb->rcv_wnd -= TCP_TCPLEN(cseg);
|
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) {
|
if (cseg->p->tot_len > 0) {
|
||||||
/* Chain this pbuf onto the pbuf that we will pass to
|
/* Chain this pbuf onto the pbuf that we will pass to
|
||||||
the application. */
|
the application. */
|
||||||
@ -1235,9 +1244,8 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) ||
|
if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
|
||||||
TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/
|
pcb->rcv_nxt + pcb->rcv_ann_wnd-1)){
|
||||||
if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){
|
|
||||||
tcp_ack_now(pcb);
|
tcp_ack_now(pcb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -460,7 +460,7 @@ tcp_output(struct tcp_pcb *pcb)
|
|||||||
tcphdr->seqno = htonl(pcb->snd_nxt);
|
tcphdr->seqno = htonl(pcb->snd_nxt);
|
||||||
tcphdr->ackno = htonl(pcb->rcv_nxt);
|
tcphdr->ackno = htonl(pcb->rcv_nxt);
|
||||||
TCPH_FLAGS_SET(tcphdr, TCP_ACK);
|
TCPH_FLAGS_SET(tcphdr, TCP_ACK);
|
||||||
tcphdr->wnd = htons(pcb->rcv_wnd);
|
tcphdr->wnd = htons(pcb->rcv_ann_wnd);
|
||||||
tcphdr->urgp = 0;
|
tcphdr->urgp = 0;
|
||||||
TCPH_HDRLEN_SET(tcphdr, 5);
|
TCPH_HDRLEN_SET(tcphdr, 5);
|
||||||
|
|
||||||
@ -593,13 +593,8 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
|||||||
wnd fields remain. */
|
wnd fields remain. */
|
||||||
seg->tcphdr->ackno = htonl(pcb->rcv_nxt);
|
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 */
|
/* advertise our receive window size in this TCP segment */
|
||||||
seg->tcphdr->wnd = htons(pcb->rcv_wnd);
|
seg->tcphdr->wnd = htons(pcb->rcv_ann_wnd);
|
||||||
}
|
|
||||||
|
|
||||||
/* If we don't have a local IP address, we get one by
|
/* If we don't have a local IP address, we get one by
|
||||||
calling ip_route(). */
|
calling ip_route(). */
|
||||||
@ -821,7 +816,7 @@ tcp_keepalive(struct tcp_pcb *pcb)
|
|||||||
tcphdr->seqno = htonl(pcb->snd_nxt - 1);
|
tcphdr->seqno = htonl(pcb->snd_nxt - 1);
|
||||||
tcphdr->ackno = htonl(pcb->rcv_nxt);
|
tcphdr->ackno = htonl(pcb->rcv_nxt);
|
||||||
TCPH_FLAGS_SET(tcphdr, 0);
|
TCPH_FLAGS_SET(tcphdr, 0);
|
||||||
tcphdr->wnd = htons(pcb->rcv_wnd);
|
tcphdr->wnd = htons(pcb->rcv_ann_wnd);
|
||||||
tcphdr->urgp = 0;
|
tcphdr->urgp = 0;
|
||||||
TCPH_HDRLEN_SET(tcphdr, 5);
|
TCPH_HDRLEN_SET(tcphdr, 5);
|
||||||
|
|
||||||
|
@ -281,6 +281,7 @@ struct tcp_pcb {
|
|||||||
/* receiver variables */
|
/* receiver variables */
|
||||||
u32_t rcv_nxt; /* next seqno expected */
|
u32_t rcv_nxt; /* next seqno expected */
|
||||||
u16_t rcv_wnd; /* receiver window */
|
u16_t rcv_wnd; /* receiver window */
|
||||||
|
u16_t rcv_ann_wnd; /* announced receive window */
|
||||||
|
|
||||||
/* Timers */
|
/* Timers */
|
||||||
u32_t tmr;
|
u32_t tmr;
|
||||||
|
Loading…
Reference in New Issue
Block a user