diff options
Diffstat (limited to 'os/ip/tcp.c')
| -rw-r--r-- | os/ip/tcp.c | 72 |
1 files changed, 44 insertions, 28 deletions
diff --git a/os/ip/tcp.c b/os/ip/tcp.c index c2bf7274..c6e0a54f 100644 --- a/os/ip/tcp.c +++ b/os/ip/tcp.c @@ -54,7 +54,7 @@ enum TCP_CONNECT = 1, /* Outgoing connection */ SYNACK_RXTIMER = 250, /* ms between SYNACK retransmits */ - TCPREXMTTHRESH = 3, /* dupack threshhold for rxt */ + TCPREXMTTHRESH = 3, /* dupack threshhold for rxt */ FORCE = 1, CLONE = 2, @@ -285,7 +285,7 @@ struct Limbo }; int tcp_irtt = DEF_RTT; /* Initial guess at round trip time */ -ushort tcp_mss = DEF_MSS; /* Maximum segment size to be sent */ +ushort tcp_mss = DEF_MSS; /* Maximum segment size to be sent */ enum { /* MIB stats */ @@ -350,7 +350,7 @@ struct Tcppriv ulong stats[Nstats]; }; -/* +/* * Setting tcpporthogdefense to non-zero enables Dong Lin's * solution to hijacked systems staking out port's as a form * of DoS attack. @@ -375,7 +375,7 @@ void tcprcvwin(Conv*); void tcpacktimer(void*); void tcpkeepalive(void*); void tcpsetkacounter(Tcpctl*); -void tcprxmit(Conv*); +void tcprxmit(Conv*); void tcpsettimer(Tcpctl*); void tcpsynackrtt(Conv*); void tcpsetscale(Conv*, Tcpctl*, ushort, ushort); @@ -711,7 +711,7 @@ backoff(int n) } void -localclose(Conv *s, char *reason) /* called with tcb locked */ +localclose(Conv *s, char *reason) /* called with tcb locked */ { Tcpctl *tcb; Reseq *rp,*rp1; @@ -1804,8 +1804,8 @@ update(Conv *s, Tcp *seg) /* * update window */ - if( seq_gt(seg->ack, tcb->snd.wl2) - || (tcb->snd.wl2 == seg->ack && seg->wnd > tcb->snd.wnd)){ + if(seq_gt(seg->ack, tcb->snd.wl2) + || (tcb->snd.wl2 == seg->ack && seg->wnd > tcb->snd.wnd)){ tcb->snd.wnd = seg->wnd; tcb->snd.wl2 = seg->ack; } @@ -1821,9 +1821,9 @@ update(Conv *s, Tcp *seg) return; } - /* + /* * any positive ack turns off fast rxt, - * (should we do new-reno on partial acks?) + * (should we do new-reno on partial acks?) */ if(!tcb->snd.recovery || seq_ge(seg->ack, tcb->snd.rxt)) { tcb->snd.dupacks = 0; @@ -1925,7 +1925,7 @@ tcpiput(Proto *tcp, Ipifc*, Block *bp) f = tcp->f; tpriv = tcp->priv; - + tpriv->stats[InSegs]++; h4 = (Tcp4hdr*)(bp->rp); @@ -1939,7 +1939,7 @@ tcpiput(Proto *tcp, Ipifc*, Block *bp) h4->Unused = 0; hnputs(h4->tcplen, length-TCP4_PKT); - if(!(bp->flag & Btcpck) && (h4->tcpcksum[0] || h4->tcpcksum[1]) && + if(!(bp->flag & Btcpck) && (h4->tcpcksum[0] || h4->tcpcksum[1]) && ptclcsum(bp, TCP4_IPLEN, length-TCP4_IPLEN)) { tpriv->stats[CsumErrs]++; tpriv->stats[InErrs]++; @@ -1978,7 +1978,7 @@ tcpiput(Proto *tcp, Ipifc*, Block *bp) h6->ploadlen[0] = h6->ploadlen[1] = h6->proto = 0; h6->ttl = proto; hnputl(h6->vcf, length); - if((h6->tcpcksum[0] || h6->tcpcksum[1]) && + if((h6->tcpcksum[0] || h6->tcpcksum[1]) && ptclcsum(bp, TCP6_IPLEN, length+TCP6_PHDRSIZE)) { tpriv->stats[CsumErrs]++; tpriv->stats[InErrs]++; @@ -2277,7 +2277,7 @@ reset: qpassnolim(s->rq, bp); bp = nil; - /* + /* * Force an ack every 2 data messages. This is * a hack for rob to make his home system run * faster. @@ -2412,20 +2412,20 @@ tcpoutput(Conv *s) for(msgs = 0; msgs < 100; msgs++) { tcb = (Tcpctl*)s->ptcl; - + switch(tcb->state) { case Listen: case Closed: case Finwait2: return; } - + /* force an ack when a window has opened up */ if(tcb->rcv.blocked && tcb->rcv.wnd > 0){ tcb->rcv.blocked = 0; tcb->flags |= FORCE; } - + sndcnt = qlen(s->wq)+tcb->flgcnt; sent = tcb->snd.ptr - tcb->snd.una; @@ -2841,8 +2841,7 @@ int addreseq(Tcpctl *tcb, Tcppriv *tpriv, Tcp *seg, Block *bp, ushort length) { Reseq *rp, *rp1; - int i; - static int once; + int i, rqlen, qmax; rp = malloc(sizeof(Reseq)); if(rp == nil){ @@ -2864,9 +2863,9 @@ addreseq(Tcpctl *tcb, Tcppriv *tpriv, Tcp *seg, Block *bp, ushort length) return 0; } - length = 0; + rqlen = 0; for(i = 0;; i++) { - length += rp1->length; + rqlen += rp1->length; if(rp1->next == nil || seq_lt(seg->seq, rp1->next->seg.seq)) { rp->next = rp1->next; rp1->next = rp; @@ -2876,12 +2875,29 @@ addreseq(Tcpctl *tcb, Tcppriv *tpriv, Tcp *seg, Block *bp, ushort length) } rp1 = rp1->next; } - if(length > QMAX && once++ == 0){ - print("very long tcp resequence queue: %d\n", length); - for(rp1 = tcb->reseq, i = 0; i < 10 && rp1 != nil; rp1 = rp1->next, i++) - print("0x%lux 0x%lux 0x%ux\n", rp1->seg.seq, rp1->seg.ack, - rp1->seg.flags); - return -1; + qmax = QMAX<<tcb->rcv.scale; + if(rqlen > qmax){ + print("resequence queue > window: %d > %d\n", rqlen, qmax); + i = 0; + for(rp1 = tcb->reseq; rp1 != nil; rp1 = rp1->next){ + print("%#lux %#lux %#ux\n", rp1->seg.seq, + rp1->seg.ack, rp1->seg.flags); + if(i++ > 10){ + print("...\n"); + break; + } + } + + // delete entire reassembly queue; wait for retransmit. + // - should we be smarter and only delete the tail? + for(rp = tcb->reseq; rp != nil; rp = rp1){ + rp1 = rp->next; + freeblist(rp->bp); + free(rp); + } + tcb->reseq = nil; + + return -1; } return 0; } @@ -2994,7 +3010,7 @@ tcpadvise(Proto *tcp, Block *bp, char *msg) v4tov6(source, h4->tcpsrc); psource = nhgets(h4->tcpsport); pdest = nhgets(h4->tcpdport); - } + } else { ipmove(dest, h6->tcpdst); ipmove(source, h6->tcpsrc); @@ -3122,7 +3138,7 @@ tcpsettimer(Tcpctl *tcb) /* round trip dependency */ x = backoff(tcb->backoff) * - (tcb->mdev + (tcb->srtt>>LOGAGAIN) + MSPTICK) / MSPTICK; + (tcb->mdev + (tcb->srtt>>LOGAGAIN) + MSPTICK) / MSPTICK; /* bounded twixt 1/2 and 64 seconds */ if(x < 500/MSPTICK) |
