mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-11-04 14:29:39 +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:
|
||||
|
||||
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
|
||||
|
@ -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. */
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user