From 6297ba31013f1b1c8fdde78eb70d53af96432390 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 9 Feb 2003 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2003-02-09 --- alphapc/etherif.h | 1 - bitsy/etherif.h | 1 - ip/ethermedium.c | 40 +++++---- ip/icmp6.c | 2 +- ip/ip.c | 2 +- ip/ip.h | 9 +- ip/ipifc.c | 16 ++-- ip/ipv6.c | 2 +- ip/loopbackmedium.c | 4 +- ip/netdevmedium.c | 10 +-- ip/pktmedium.c | 4 +- ip/tcp.c | 196 +++++++++++++++++++++++++++++++++----------- ip/tripmedium.c | 10 +-- mtx/etherif.h | 1 - pc/etherif.h | 1 - port/netif.c | 1 + port/netif.h | 1 + 17 files changed, 205 insertions(+), 96 deletions(-) diff --git a/alphapc/etherif.h b/alphapc/etherif.h index fc54938c274a90ab34aa87e271dacbc4148085da..c044e75efdb9e901465d3e86a79e896ea9cf66c3 100644 --- a/alphapc/etherif.h +++ b/alphapc/etherif.h @@ -9,7 +9,6 @@ struct Ether { int ctlrno; int tbdf; /* type+busno+devno+funcno */ - int mbps; /* Mbps */ int minmtu; int maxmtu; uchar ea[Eaddrlen]; diff --git a/bitsy/etherif.h b/bitsy/etherif.h index c1aa3661689f9903671ab1cb790af252dd29c267..f51294ffb42630e7956e01400a8876893108e477 100644 --- a/bitsy/etherif.h +++ b/bitsy/etherif.h @@ -9,7 +9,6 @@ struct Ether { int ctlrno; int tbdf; /* type+busno+devno+funcno */ - int mbps; /* Mbps */ int minmtu; int maxmtu; uchar ea[Eaddrlen]; diff --git a/ip/ethermedium.c b/ip/ethermedium.c index b477b8b324c63fed6aa0316fca6d45719bec6f77..394babc8adbffa493cdbe1d5e1a603f2df753199 100644 --- a/ip/ethermedium.c +++ b/ip/ethermedium.c @@ -35,8 +35,8 @@ Medium ethermedium = { .name= "ether", .hsize= 14, -.minmtu= 60, -.maxmtu= 1514, +.mintu= 60, +.maxtu= 1514, .maclen= 6, .bind= etherbind, .unbind= etherunbind, @@ -52,8 +52,8 @@ Medium gbemedium = { .name= "gbe", .hsize= 14, -.minmtu= 60, -.maxmtu= 9014, +.mintu= 60, +.maxtu= 9014, .maclen= 6, .bind= etherbind, .unbind= etherunbind, @@ -161,7 +161,7 @@ etherbind(Ipifc *ifc, int argc, char **argv) devtab[cchan4->type]->write(cchan4, nbmsg, strlen(nbmsg), 0); /* - * get mac address + * get mac address and speed */ snprint(addr, sizeof(addr), "%s/stats", dir); buf = smalloc(512); @@ -179,9 +179,15 @@ etherbind(Ipifc *ifc, int argc, char **argv) if(!ptr) error(Eio); ptr += 6; - parsemac(ifc->mac, ptr, 6); + ptr = strstr(buf, "mbps: "); + if(ptr){ + ptr += 6; + ifc->mbps = atoi(ptr); + } else + ifc->mbps = 100; + /* * open arp conversation */ @@ -287,8 +293,8 @@ etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip) bp = padblock(bp, ifc->m->hsize); if(bp->next) bp = concatblock(bp); - if(BLEN(bp) < ifc->minmtu) - bp = adjustblock(bp, ifc->minmtu); + if(BLEN(bp) < ifc->mintu) + bp = adjustblock(bp, ifc->mintu); eh = (Etherhdr*)bp->rp; /* copy in mac addresses and ether type */ @@ -331,7 +337,7 @@ etherread4(void *a) pexit("hangup", 1); } for(;;){ - bp = devtab[er->mchan4->type]->bread(er->mchan4, ifc->maxmtu, 0); + bp = devtab[er->mchan4->type]->bread(er->mchan4, ifc->maxtu, 0); if(!canrlock(ifc)){ freeb(bp); continue; @@ -370,7 +376,7 @@ etherread6(void *a) pexit("hangup", 1); } for(;;){ - bp = devtab[er->mchan6->type]->bread(er->mchan6, ifc->maxmtu, 0); + bp = devtab[er->mchan6->type]->bread(er->mchan6, ifc->maxtu, 0); if(!canrlock(ifc)){ freeb(bp); continue; @@ -465,8 +471,8 @@ sendarp(Ipifc *ifc, Arpent *a) arprelease(er->f->arp, a); n = sizeof(Etherarp); - if(n < a->type->minmtu) - n = a->type->minmtu; + if(n < a->type->mintu) + n = a->type->mintu; bp = allocb(n); memset(bp->rp, 0, n); e = (Etherarp*)bp->rp; @@ -542,8 +548,8 @@ sendgarp(Ipifc *ifc, uchar *ip) return; n = sizeof(Etherarp); - if(n < ifc->m->minmtu) - n = ifc->m->minmtu; + if(n < ifc->m->mintu) + n = ifc->m->mintu; bp = allocb(n); memset(bp->rp, 0, n); e = (Etherarp*)bp->rp; @@ -576,7 +582,7 @@ recvarp(Ipifc *ifc) static uchar eprinted[4]; Etherrock *er = ifc->arg; - ebp = devtab[er->achan->type]->bread(er->achan, ifc->maxmtu, 0); + ebp = devtab[er->achan->type]->bread(er->achan, ifc->maxtu, 0); if(ebp == nil) { print("arp: rcv: %r\n"); return; @@ -633,8 +639,8 @@ recvarp(Ipifc *ifc) break; n = sizeof(Etherarp); - if(n < ifc->minmtu) - n = ifc->minmtu; + if(n < ifc->mintu) + n = ifc->mintu; rbp = allocb(n); r = (Etherarp*)rbp->rp; memset(r, 0, sizeof(Etherarp)); diff --git a/ip/icmp6.c b/ip/icmp6.c index e9d3f033f80ed04e8bc65db4098ca4ff3b88fa64..c102b35707888ce38296be3a0db7be371f893aae 100644 --- a/ip/icmp6.c +++ b/ip/icmp6.c @@ -543,7 +543,7 @@ icmppkttoobig6(Fs *f, Ipifc *ifc, Block *bp) memmove(np->dst, p->src, IPaddrlen); np->type = PacketTooBigV6; np->code = 0; - hnputl(np->icmpid, ifc->maxmtu - ifc->m->hsize); + hnputl(np->icmpid, ifc->maxtu - ifc->m->hsize); memmove(nbp->rp + sizeof(IPICMP), bp->rp, sz - sizeof(IPICMP)); set_cksum(nbp); np->ttl = HOP_LIMIT; diff --git a/ip/ip.c b/ip/ip.c index c260b0fe8ab51491fad3b1c18f7ff320d84a3043..5467af7b09ec900d4ebff65427f434608c9189c4 100644 --- a/ip/ip.c +++ b/ip/ip.c @@ -294,7 +294,7 @@ ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos) goto raise; /* If we dont need to fragment just send it */ - medialen = ifc->maxmtu - ifc->m->hsize; + medialen = ifc->maxtu - ifc->m->hsize; if(len <= medialen) { if(!gating) hnputs(eh->id, incref(&ip->id4)); diff --git a/ip/ip.h b/ip/ip.h index 8863df5e9b4963d1e59b1299748a39b302004a07..ff73780c6b71114d63752d6ec7e9496b11f4b5b7 100644 --- a/ip/ip.h +++ b/ip/ip.h @@ -124,8 +124,8 @@ struct Medium { char *name; int hsize; /* medium header size */ - int minmtu; /* default min mtu */ - int maxmtu; /* default max mtu */ + int mintu; /* default min mtu */ + int maxtu; /* default max mtu */ int maclen; /* mac address length */ void (*bind)(Ipifc*, int, char**); void (*unbind)(Ipifc*); @@ -212,8 +212,9 @@ struct Ipifc Conv *conv; /* link to its conversation structure */ char dev[64]; /* device we're attached to */ Medium *m; /* Media pointer */ - int maxmtu; /* Maximum transfer unit */ - int minmtu; /* Minumum tranfer unit */ + int maxtu; /* Maximum transfer unit */ + int mintu; /* Minumum tranfer unit */ + int mbps; /* megabits per second */ void *arg; /* medium specific */ int reassemble; /* reassemble IP packets before forwarding */ diff --git a/ip/ipifc.c b/ip/ipifc.c index e2068ef9585de50893c8cf49e8a8a194d2da116d..f41caee90a7166318310984d54e1bc4f4503e6d2 100644 --- a/ip/ipifc.c +++ b/ip/ipifc.c @@ -140,8 +140,8 @@ ipifcbind(Conv *c, char **argv, int argc) /* set up parameters */ ifc->m = m; - ifc->minmtu = ifc->m->minmtu; - ifc->maxmtu = ifc->m->maxmtu; + ifc->mintu = ifc->m->mintu; + ifc->maxtu = ifc->m->maxtu; if(ifc->m->unbindonclose == 0) ifc->conv->inuse++; ifc->rp.mflag = 0; // default not managed @@ -226,7 +226,7 @@ ipifcunbind(Ipifc *ifc) -char sfixedformat[] = "device %s maxmtu %d sendra %d recvra %d mflag %d oflag %d maxraint %d minraint %d linkmtu %d reachtime %d rxmitra %d ttl %d routerlt %d pktin %lud pktout %lud errin %lud errout %lud\n"; +char sfixedformat[] = "device %s maxtu %d sendra %d recvra %d mflag %d oflag %d maxraint %d minraint %d linkmtu %d reachtime %d rxmitra %d ttl %d routerlt %d pktin %lud pktout %lud errin %lud errout %lud\n"; char slineformat[] = " %-40.40I %-10.10M %-40.40I %-12lud %-12lud\n"; @@ -241,7 +241,7 @@ ipifcstate(Conv *c, char *state, int n) ifc = (Ipifc*)c->ptcl; m = snprint(state, n, sfixedformat, - ifc->dev, ifc->maxmtu, ifc->sendra6, ifc->recvra6, + ifc->dev, ifc->maxtu, ifc->sendra6, ifc->recvra6, ifc->rp.mflag, ifc->rp.oflag, ifc->rp.maxraint, ifc->rp.minraint, ifc->rp.linkmtu, ifc->rp.reachtime, ifc->rp.rxmitra, ifc->rp.ttl, ifc->rp.routerlt, @@ -358,9 +358,9 @@ ipifcsetmtu(Ipifc *ifc, char **argv, int argc) if(ifc->m == nil) return Ebadarg; mtu = strtoul(argv[1], 0, 0); - if(mtu < ifc->m->minmtu || mtu > ifc->m->maxmtu) + if(mtu < ifc->m->mintu || mtu > ifc->m->maxtu) return Ebadarg; - ifc->maxmtu = mtu; + ifc->maxtu = mtu; return nil; } @@ -393,8 +393,8 @@ ipifcadd(Ipifc *ifc, char **argv, int argc, int tentative, Iplifc *lifcp) /* fall through */ case 5: mtu = strtoul(argv[4], 0, 0); - if(mtu >= ifc->m->minmtu && mtu <= ifc->m->maxmtu) - ifc->maxmtu = mtu; + if(mtu >= ifc->m->mintu && mtu <= ifc->m->maxtu) + ifc->maxtu = mtu; /* fall through */ case 4: parseip(ip, argv[1]); diff --git a/ip/ipv6.c b/ip/ipv6.c index f80132383273b0fa70540ea4674ff7169f13a84e..30f384eb6bea608f5474410faff14f97d2b92ceb 100644 --- a/ip/ipv6.c +++ b/ip/ipv6.c @@ -222,7 +222,7 @@ ipoput6(Fs *f, Block *bp, int gating, int ttl, int tos) } /* If we dont need to fragment just send it */ - medialen = ifc->maxmtu - ifc->m->hsize; + medialen = ifc->maxtu - ifc->m->hsize; if(len <= medialen) { hnputs(eh->ploadlen, len-IPV6HDR_LEN); ifc->m->bwrite(ifc, bp, V6, gate); diff --git a/ip/loopbackmedium.c b/ip/loopbackmedium.c index 678189b98ad89b860c94394ba69a815c00825d4c..a1f07f0509127387811572616e7906f6bbcac9b3 100644 --- a/ip/loopbackmedium.c +++ b/ip/loopbackmedium.c @@ -103,8 +103,8 @@ loopbackread(void *a) Medium loopbackmedium = { .hsize= 0, -.minmtu= 0, -.maxmtu= Maxtu, +.mintu= 0, +.maxtu= Maxtu, .maclen= 0, .name= "loopback", .bind= loopbackbind, diff --git a/ip/netdevmedium.c b/ip/netdevmedium.c index c13dd1b625b435f6a63af22cc709470d26f48f88..bcbdeeda2b1f801ddbbbfdd9cfba9b571d21e4ef 100644 --- a/ip/netdevmedium.c +++ b/ip/netdevmedium.c @@ -24,8 +24,8 @@ Medium netdevmedium = { .name= "netdev", .hsize= 0, -.minmtu= 0, -.maxmtu= 64000, +.mintu= 0, +.maxtu= 64000, .maclen= 0, .bind= netdevbind, .unbind= netdevunbind, @@ -88,8 +88,8 @@ netdevbwrite(Ipifc *ifc, Block *bp, int, uchar*) if(bp->next) bp = concatblock(bp); - if(BLEN(bp) < ifc->minmtu) - bp = adjustblock(bp, ifc->minmtu); + if(BLEN(bp) < ifc->mintu) + bp = adjustblock(bp, ifc->mintu); devtab[er->mchan->type]->bwrite(er->mchan, bp, 0); ifc->out++; @@ -114,7 +114,7 @@ netdevread(void *a) pexit("hangup", 1); } for(;;){ - bp = devtab[er->mchan->type]->bread(er->mchan, ifc->maxmtu, 0); + bp = devtab[er->mchan->type]->bread(er->mchan, ifc->maxtu, 0); if(bp == nil){ /* * get here if mchan is a pipe and other side hangs up diff --git a/ip/pktmedium.c b/ip/pktmedium.c index 9c136f6bc3b4004101d0ad5a548b279e89ee45cf..226a31abdd94a40ee222ba1ba42705f3419d8905 100644 --- a/ip/pktmedium.c +++ b/ip/pktmedium.c @@ -17,8 +17,8 @@ Medium pktmedium = { .name= "pkt", .hsize= 14, -.minmtu= 40, -.maxmtu= 4*1024, +.mintu= 40, +.maxtu= 4*1024, .maclen= 6, .bind= pktbind, .unbind= pktunbind, diff --git a/ip/tcp.c b/ip/tcp.c index d13d7cfa52538d86ee218ad2ef4647fcd51ad3cb..eccfe262f63fc6d715c9a50aa784b8f5d8dd8def 100644 --- a/ip/tcp.c +++ b/ip/tcp.c @@ -29,6 +29,7 @@ enum TcptimerDONE = 2, MAX_TIME = (1<<20), /* Forever */ TCP_ACK = 50, /* Timed ack sequence in ms */ + MAXBACKMS = 30000, /* longest backoff time (ms) before hangup */ URG = 0x20, /* Data marked urgent */ ACK = 0x10, /* Acknowledge is valid */ @@ -39,9 +40,10 @@ enum EOLOPT = 0, NOOPOPT = 1, - MAXBACKMS = 30000, /* longest backoff time (ms) before hangup */ MSSOPT = 2, MSS_LENGTH = 4, /* Mean segment size */ + WSOPT = 3, + WS_LENGTH = 3, /* Bits to scale window size by */ MSL2 = 10, MSPTICK = 50, /* Milliseconds per timer tick */ DEF_MSS = 1460, /* Default mean segment */ @@ -77,7 +79,9 @@ enum Maxlimbo = 1000, /* maximum procs waiting for response to SYN ACK */ NLHT = 256, /* hash table size, must be a power of 2 */ - LHTMASK = NLHT-1 + LHTMASK = NLHT-1, + + HaveWS = 1<<8, }; /* Must correspond to the enumeration above */ @@ -127,8 +131,7 @@ struct Tcp4hdr uchar tcpcksum[2]; uchar tcpurg[2]; /* Options segment */ - uchar tcpopt[2]; - uchar tcpmss[2]; + uchar tcpopt[1]; }; typedef struct Tcp6hdr Tcp6hdr; @@ -149,8 +152,7 @@ struct Tcp6hdr uchar tcpcksum[2]; uchar tcpurg[2]; /* Options segment */ - uchar tcpopt[2]; - uchar tcpmss[2]; + uchar tcpopt[1]; }; /* @@ -167,9 +169,10 @@ struct Tcp ulong seq; ulong ack; uchar flags; - ushort wnd; + ushort ws; /* window scale option (if not zero) */ + ulong wnd; ushort urg; - ushort mss; + ushort mss; /* max segment size option (if not zero) */ ushort len; /* size of data */ }; @@ -199,9 +202,10 @@ struct Tcpctl ulong una; /* Unacked data pointer */ ulong nxt; /* Next sequence expected */ ulong ptr; /* Data pointer */ - ushort wnd; /* Tcp send window */ + ulong wnd; /* Tcp send window */ ulong urg; /* Urgent data pointer */ ulong wl2; + int scale; /* how much to right shift window in xmitted packets */ /* to implement tahoe and reno TCP */ ulong dupacks; /* number of duplicate acks rcvd */ int recovery; /* loss recovery flag */ @@ -209,20 +213,23 @@ struct Tcpctl } snd; struct { ulong nxt; /* Receive pointer to next uchar slot */ - ushort wnd; /* Receive window incoming */ + ulong wnd; /* Receive window incoming */ ulong urg; /* Urgent pointer */ ulong lastacked; /* Last ack sent */ int blocked; int una; /* unacked data segs */ + int scale; /* how much to left shift window in rcved packets */ } rcv; ulong iss; /* Initial sequence number */ - ushort cwind; /* Congestion window */ + int sawwsopt; /* true if we saw a wsopt on the incoming SYN */ + ulong cwind; /* Congestion window */ + int scale; /* desired snd.scale */ ushort ssthresh; /* Slow start threshold */ int resent; /* Bytes just resent */ int irs; /* Initial received squence */ ushort mss; /* Mean segment size */ int rerecv; /* Overlap of data rerecevived */ - ushort window; /* Recevive window */ + ulong window; /* Recevive window */ uchar backoff; /* Exponential backoff counter */ int backedoff; /* ms we've backed off for rexmits */ uchar flags; /* State flags */ @@ -271,6 +278,8 @@ struct Limbo ulong irs; /* initial received sequence */ ulong iss; /* initial sent sequence */ ushort mss; /* mss from the other end */ + ushort rcvscale; /* how much to scale rcvd windows */ + ushort sndscale; /* how much to scale sent windows */ ulong lastsend; /* last time we sent a synack */ uchar version; /* v4 or v6 */ uchar rexmits; /* number of retransmissions */ @@ -362,9 +371,9 @@ void procsyn(Conv*, Tcp*); void tcpiput(Proto*, Ipifc*, Block*); void tcpoutput(Conv*); int tcptrim(Tcpctl*, Tcp*, Block**, ushort*); -void tcpstart(Conv*, int, ushort); +void tcpstart(Conv*, int); void tcptimeout(void*); -void tcpsndsyn(Tcpctl*); +void tcpsndsyn(Conv*, Tcpctl*); void tcprcvwin(Conv*); void tcpacktimer(void*); void tcpkeepalive(void*); @@ -372,6 +381,7 @@ void tcpsetkacounter(Tcpctl*); void tcprxmit(Conv*); void tcpsettimer(Tcpctl*); void tcpsynackrtt(Conv*); +void tcpsetscale(Conv*, Tcpctl*, ushort, ushort); static void limborexmit(Proto*); static void limbo(Conv*, uchar*, uchar*, Tcp*, int); @@ -427,7 +437,7 @@ tcpconnect(Conv *c, char **argv, int argc) e = Fsstdconnect(c, argv, argc); if(e != nil) return e; - tcpstart(c, TCP_CONNECT, QMAX); + tcpstart(c, TCP_CONNECT); return nil; } @@ -440,9 +450,9 @@ tcpstate(Conv *c, char *state, int n) s = (Tcpctl*)(c->ptcl); return snprint(state, n, - "%s srtt %d mdev %d cwin %d swin %d rwin %d timer.start %d timer.count %d rerecv %d\n", + "%s srtt %d mdev %d cwin %lud swin %lud>>%d rwin %lud>>%d timer.start %d timer.count %d rerecv %d\n", tcpstates[s->state], s->srtt, s->mdev, - s->cwind, s->snd.wnd, s->rcv.wnd, + s->cwind, s->snd.wnd, s->snd.scale, s->rcv.wnd, s->rcv.scale, s->timer.start, s->timer.count, s->rerecv); } @@ -463,7 +473,7 @@ tcpannounce(Conv *c, char **argv, int argc) e = Fsstdannounce(c, argv, argc); if(e != nil) return e; - tcpstart(c, TCP_LISTEN, QMAX); + tcpstart(c, TCP_LISTEN); Fsconnected(c, nil); return nil; @@ -554,7 +564,7 @@ tcprcvwin(Conv *s) /* Call with tcb locked */ Tcpctl *tcb; tcb = (Tcpctl*)s->ptcl; - w = QMAX - qlen(s->rq); + w = tcb->window - qlen(s->rq); if(w < 0) w = 0; tcb->rcv.wnd = w; @@ -740,7 +750,7 @@ localclose(Conv *s, char *reason) /* called with tcb locked */ /* mtu (- TCP + IP hdr len) of 1st hop */ int -tcpmtu(Proto *tcp, uchar *addr, int version) +tcpmtu(Proto *tcp, uchar *addr, int version, int *scale) { Ipifc *ifc; int mtu; @@ -751,14 +761,23 @@ tcpmtu(Proto *tcp, uchar *addr, int version) case V4: mtu = DEF_MSS; if(ifc != nil) - mtu = ifc->maxmtu - ifc->m->hsize - (TCP4_PKT + TCP4_HDRSIZE); + mtu = ifc->maxtu - ifc->m->hsize - (TCP4_PKT + TCP4_HDRSIZE); break; case V6: mtu = DEF_MSS6; if(ifc != nil) - mtu = ifc->maxmtu - ifc->m->hsize - (TCP6_PKT + TCP6_HDRSIZE); + mtu = ifc->maxtu - ifc->m->hsize - (TCP6_PKT + TCP6_HDRSIZE); break; } + if(ifc != nil){ + if(ifc->mbps > 100) + *scale = HaveWS | 3; + else if(ifc->mbps > 10) + *scale = HaveWS | 1; + else + *scale = HaveWS | 0; + } else + *scale = HaveWS | 0; return mtu; } @@ -769,6 +788,7 @@ inittcpctl(Conv *s, int mode) Tcpctl *tcb; Tcp4hdr* h4; Tcp6hdr* h6; + int mss; tcb = (Tcpctl*)s->ptcl; @@ -790,6 +810,8 @@ inittcpctl(Conv *s, int mode) tcb->katimer.func = tcpkeepalive; tcb->katimer.arg = s; + mss = DEF_MSS; + /* create a prototype(pseudo) header */ if(mode != TCP_LISTEN){ if(ipcmp(s->laddr, IPnoaddr) == 0) @@ -813,20 +835,28 @@ inittcpctl(Conv *s, int mode) hnputs(h6->tcpdport, s->rport); ipmove(h6->tcpsrc, s->laddr); ipmove(h6->tcpdst, s->raddr); + mss = DEF_MSS6; break; default: panic("inittcpctl: version %d", s->ipversion); } } - tcb->mss = tcb->cwind = tcpmtu(s->p, s->laddr, s->ipversion); + tcb->mss = tcb->cwind = mss; + + /* default is no window scaling */ + tcb->window = QMAX; + tcb->rcv.wnd = QMAX; + tcb->rcv.scale = 0; + tcb->snd.scale = 0; + qsetlimit(s->rq, QMAX); } /* * called with s qlocked */ void -tcpstart(Conv *s, int mode, ushort window) +tcpstart(Conv *s, int mode) { Tcpctl *tcb; Tcppriv *tpriv; @@ -846,10 +876,7 @@ tcpstart(Conv *s, int mode, ushort window) tcb = (Tcpctl*)s->ptcl; - /* Send SYN, go into SYN_SENT state */ inittcpctl(s, mode); - tcb->window = window; - tcb->rcv.wnd = window; iphtadd(&tpriv->ht, s); switch(mode) { @@ -862,7 +889,7 @@ tcpstart(Conv *s, int mode, ushort window) case TCP_CONNECT: tpriv->stats[ActiveOpens]++; tcb->flags |= ACTIVE; - tcpsndsyn(tcb); + tcpsndsyn(s, tcb); tcpsetstate(s, Syn_sent); tcpoutput(s); break; @@ -898,10 +925,13 @@ htontcp6(Tcp *tcph, Block *data, Tcp6hdr *ph, Tcpctl *tcb) Tcp6hdr *h; ushort csum; ushort hdrlen; + uchar *opt; hdrlen = TCP6_HDRSIZE; if(tcph->mss) hdrlen += MSS_LENGTH; + if(tcph->ws) + hdrlen += WS_LENGTH; if(data) { dlen = blocklen(data); @@ -930,14 +960,22 @@ htontcp6(Tcp *tcph, Block *data, Tcp6hdr *ph, Tcpctl *tcb) hnputl(h->tcpseq, tcph->seq); hnputl(h->tcpack, tcph->ack); hnputs(h->tcpflag, (hdrlen<<10) | tcph->flags); - hnputs(h->tcpwin, tcph->wnd); + hnputs(h->tcpwin, tcph->wnd>>(tcb != nil ? tcb->snd.scale : 0)); hnputs(h->tcpurg, tcph->urg); + opt = h->tcpopt; if(tcph->mss != 0){ - h->tcpopt[0] = MSSOPT; - h->tcpopt[1] = MSS_LENGTH; - hnputs(h->tcpmss, tcph->mss); + *opt++ = MSSOPT; + *opt++ = MSS_LENGTH; + hnputs(opt, tcph->mss); + opt += 2; } + if(tcph->ws != 0){ + *opt++ = WSOPT; + *opt++ = WS_LENGTH; + *opt = tcph->ws; + } + if(tcb != nil && tcb->nochecksum){ h->tcpcksum[0] = h->tcpcksum[1] = 0; } else { @@ -961,10 +999,13 @@ htontcp4(Tcp *tcph, Block *data, Tcp4hdr *ph, Tcpctl *tcb) Tcp4hdr *h; ushort csum; ushort hdrlen; + uchar *opt; hdrlen = TCP4_HDRSIZE; if(tcph->mss) hdrlen += MSS_LENGTH; + if(tcph->ws) + hdrlen += WS_LENGTH; if(data) { dlen = blocklen(data); @@ -989,14 +1030,22 @@ htontcp4(Tcp *tcph, Block *data, Tcp4hdr *ph, Tcpctl *tcb) hnputl(h->tcpseq, tcph->seq); hnputl(h->tcpack, tcph->ack); hnputs(h->tcpflag, (hdrlen<<10) | tcph->flags); - hnputs(h->tcpwin, tcph->wnd); + hnputs(h->tcpwin, tcph->wnd>>(tcb != nil ? tcb->snd.scale : 0)); hnputs(h->tcpurg, tcph->urg); + opt = h->tcpopt; if(tcph->mss != 0){ - h->tcpopt[0] = MSSOPT; - h->tcpopt[1] = MSS_LENGTH; - hnputs(h->tcpmss, tcph->mss); + *opt++ = MSSOPT; + *opt++ = MSS_LENGTH; + hnputs(opt, tcph->mss); + opt += 2; + } + if(tcph->ws != 0){ + *opt++ = WSOPT; + *opt++ = WS_LENGTH; + *opt = tcph->ws; } + if(tcb != nil && tcb->nochecksum){ h->tcpcksum[0] = h->tcpcksum[1] = 0; } else { @@ -1025,7 +1074,7 @@ ntohtcp6(Tcp *tcph, Block **bpp) tcph->dest = nhgets(h->tcpdport); tcph->seq = nhgetl(h->tcpseq); tcph->ack = nhgetl(h->tcpack); - hdrlen = (h->tcpflag[0] & 0xf0)>>2; + hdrlen = h->tcpflag[0]>>2; if(hdrlen < TCP6_HDRSIZE) { freeblist(*bpp); return -1; @@ -1035,6 +1084,7 @@ ntohtcp6(Tcp *tcph, Block **bpp) tcph->wnd = nhgets(h->tcpwin); tcph->urg = nhgets(h->tcpurg); tcph->mss = 0; + tcph->ws = 0; tcph->len = nhgets(h->ploadlen) - hdrlen; *bpp = pullupblock(*bpp, hdrlen+TCP6_PKT); @@ -1057,6 +1107,10 @@ ntohtcp6(Tcp *tcph, Block **bpp) if(optlen == MSS_LENGTH) tcph->mss = nhgets(optr+2); break; + case WSOPT: + if(optlen == WS_LENGTH) + tcph->ws = HaveWS | *(optr+2); + break; } n -= optlen; optr += optlen; @@ -1083,7 +1137,7 @@ ntohtcp4(Tcp *tcph, Block **bpp) tcph->seq = nhgetl(h->tcpseq); tcph->ack = nhgetl(h->tcpack); - hdrlen = (h->tcpflag[0] & 0xf0)>>2; + hdrlen = h->tcpflag[0]>>2; if(hdrlen < TCP4_HDRSIZE) { freeblist(*bpp); return -1; @@ -1093,6 +1147,7 @@ ntohtcp4(Tcp *tcph, Block **bpp) tcph->wnd = nhgets(h->tcpwin); tcph->urg = nhgets(h->tcpurg); tcph->mss = 0; + tcph->ws = 0; tcph->len = nhgets(h->length) - (hdrlen + TCP4_PKT); *bpp = pullupblock(*bpp, hdrlen+TCP4_PKT); @@ -1115,6 +1170,10 @@ ntohtcp4(Tcp *tcph, Block **bpp) if(optlen == MSS_LENGTH) tcph->mss = nhgets(optr+2); break; + case WSOPT: + if(optlen == WS_LENGTH) + tcph->ws = HaveWS | *(optr+2); + break; } n -= optlen; optr += optlen; @@ -1127,7 +1186,7 @@ ntohtcp4(Tcp *tcph, Block **bpp) * number and put a SYN on the send queue */ void -tcpsndsyn(Tcpctl *tcb) +tcpsndsyn(Conv *s, Tcpctl *tcb) { tcb->iss = (nrand(1<<16)<<16)|nrand(1<<16); tcb->rttseq = tcb->iss; @@ -1138,6 +1197,9 @@ tcpsndsyn(Tcpctl *tcb) tcb->flgcnt++; tcb->flags |= FORCE; tcb->sndsyntime = NOW; + + /* set desired mss and scale */ + tcb->mss = tcpmtu(s->p, s->laddr, s->ipversion, &tcb->scale); } void @@ -1204,6 +1266,7 @@ sndrst(Proto *tcp, uchar *source, uchar *dest, ushort length, Tcp *seg, uchar ve seg->wnd = 0; seg->urg = 0; seg->mss = 0; + seg->ws = 0; switch(version) { case V4: hbp = htontcp4(seg, nil, &ph4, nil); @@ -1244,6 +1307,7 @@ tcphangup(Conv *s) seg.wnd = 0; seg.urg = 0; seg.mss = 0; + seg.ws = 0; switch(s->ipversion) { case V4: tcb->protohdr.tcp4hdr.vihl = IP_VER4; @@ -1274,6 +1338,7 @@ sndsynack(Proto *tcp, Limbo *lp) Tcp4hdr ph4; Tcp6hdr ph6; Tcp seg; + int scale; /* make pseudo header */ switch(lp->version) { @@ -1305,9 +1370,18 @@ sndsynack(Proto *tcp, Limbo *lp) seg.ack = lp->irs+1; seg.flags = SYN|ACK; seg.urg = 0; - seg.mss = tcpmtu(tcp, lp->laddr, lp->version); + seg.mss = tcpmtu(tcp, lp->laddr, lp->version, &scale); seg.wnd = QMAX; + /* if the other side set scale, we should too */ + if(lp->rcvscale){ + seg.ws = scale; + lp->sndscale = scale; + } else { + seg.ws = 0; + lp->sndscale = 0; + } + switch(lp->version) { case V4: hbp = htontcp4(&seg, nil, &ph4, nil); @@ -1377,6 +1451,7 @@ limbo(Conv *s, uchar *source, uchar *dest, Tcp *seg, int version) lp->lport = seg->dest; lp->rport = seg->source; lp->mss = seg->mss; + lp->rcvscale = seg->ws; lp->irs = seg->seq; lp->iss = (nrand(1<<16)<<16)|nrand(1<<16); } @@ -1474,6 +1549,7 @@ limborst(Conv *s, Tcp *segp, uchar *src, uchar *dst, uchar version) } /* + * come here when we finally get an ACK to our SYN-ACK. * lookup call in limbo. if found, create a new conversation * * called with proto locked @@ -1558,6 +1634,9 @@ tcpincoming(Conv *s, Tcp *segp, uchar *src, uchar *dst, uchar version) if(lp->mss != 0 && lp->mss < tcb->mss) tcb->mss = lp->mss; + /* window scaling */ + tcpsetscale(new, tcb, lp->rcvscale, lp->sndscale); + /* the congestion window always starts out as a single segment */ tcb->snd.wnd = segp->wnd; tcb->cwind = tcb->mss; @@ -1664,7 +1743,8 @@ update(Conv *s, Tcp *seg) { int rtt, delta; Tcpctl *tcb; - ushort acked, expand; + ulong acked; + ulong expand; Tcppriv *tpriv; tpriv = s->p->priv; @@ -1752,7 +1832,7 @@ update(Conv *s, Tcp *seg) expand = ((int)tcb->mss * tcb->mss) / tcb->cwind; if(tcb->cwind + expand < tcb->cwind) - expand = 65535 - tcb->cwind; + expand = tcb->snd.wnd - tcb->cwind; if(tcb->cwind + expand > tcb->snd.wnd) expand = tcb->snd.wnd - tcb->cwind; if(expand != 0) @@ -1962,6 +2042,9 @@ reset: qlock(s); qunlock(tcp); + /* fix up window */ + seg.wnd <<= tcb->rcv.scale; + if(tcb->kacounter > 0) tcb->kacounter = MAXBACKMS / (tcb->katimer.start*MSPTICK); if(tcb->kacounter < 3) @@ -1991,10 +2074,11 @@ reset: update(s, &seg); tcpsynackrtt(s); tcpsetstate(s, Established); + tcpsetscale(s, tcb, seg.ws, tcb->scale); } else { tcb->time = NOW; - tcpsetstate(s, Syn_received); + tcpsetstate(s, Syn_received); /* DLP - shouldn't this be a reset? */ } if(length != 0 || (seg.flags & FIN)) @@ -2340,7 +2424,7 @@ tcpoutput(Conv *s) } ssize = sndcnt-sent; if(ssize && usable < 2) - netlog(s->p->f, Logtcp, "throttled snd.wnd 0x%ux cwind 0x%ux\n", + netlog(s->p->f, Logtcp, "throttled snd.wnd %lud cwind %lud\n", tcb->snd.wnd, tcb->cwind); if(usable < ssize) ssize = usable; @@ -2364,6 +2448,7 @@ tcpoutput(Conv *s) seg.dest = s->rport; seg.flags = ACK; seg.mss = 0; + seg.ws = 0; switch(tcb->state){ case Syn_sent: @@ -2371,7 +2456,8 @@ tcpoutput(Conv *s) if(tcb->snd.ptr == tcb->iss){ seg.flags |= SYN; dsize--; - seg.mss = tcpmtu(s->p, s->laddr, s->ipversion); + seg.mss = tcb->mss; + seg.ws = tcb->scale; } break; case Syn_received: @@ -2384,7 +2470,8 @@ tcpoutput(Conv *s) seg.flags |= SYN; dsize = 0; ssize = 1; - seg.mss = tcpmtu(s->p, s->laddr, s->ipversion); + seg.mss = tcb->mss; + seg.ws = tcb->scale; } break; } @@ -2506,6 +2593,7 @@ tcpsendka(Conv *s) seg.dest = s->rport; seg.flags = ACK|PSH; seg.mss = 0; + seg.ws = 0; if(tcpporthogdefense) seg.seq = tcb->snd.una-(1<<30)-nrand(1<<20); else @@ -3019,3 +3107,19 @@ tcpinit(Fs *fs) Fsproto(fs, tcp); } + +void +tcpsetscale(Conv *s, Tcpctl *tcb, ushort rcvscale, ushort sndscale) +{ + if(rcvscale){ + tcb->rcv.scale = rcvscale & 0xff; + tcb->snd.scale = sndscale & 0xff; + tcb->window = QMAX<snd.scale; + qsetlimit(s->rq, tcb->window); + } else { + tcb->rcv.scale = 0; + tcb->snd.scale = 0; + tcb->window = QMAX; + qsetlimit(s->rq, tcb->window); + } +} diff --git a/ip/tripmedium.c b/ip/tripmedium.c index aece203046932629533c20f63ffccebf60e978bc..cd6431df6e26f5f3a11175873660f001f7bf7344 100644 --- a/ip/tripmedium.c +++ b/ip/tripmedium.c @@ -21,8 +21,8 @@ static void tripares(Fs*, int, uchar*, uchar*, int, int); Medium tripmedium = { .name= "trip", -.minmtu= 20, -.maxmtu= 64*1024, +.mintu= 20, +.maxtu= 64*1024, .maclen= LCIMACSIZE, .bind= tripbind, .unbind= tripunbind, @@ -140,7 +140,7 @@ tripread(void *a) er->readp = up; /* hide identity under a rock for unbind */ for(;;) { - bp = devtab[er->mchan->type]->bread(er->mchan, ifc->maxmtu, 0); + bp = devtab[er->mchan->type]->bread(er->mchan, ifc->maxtu, 0); ifc->in++; ipiput4(er->fs, ifc, bp); } @@ -255,8 +255,8 @@ sendifcinfo(Ipifc *dest) continue; mtc.type = T_CTLIFADMIN; - mtc.maxtu = ifc->maxmtu; - mtc.mintu = ifc->minmtu; + mtc.maxtu = ifc->maxtu; + mtc.mintu = ifc->mintu; mtc.port = 0; if(ifc->m == &tripmedium) { diff --git a/mtx/etherif.h b/mtx/etherif.h index 5af59e14629aa7a477e37d4e7114b5c506400fc5..34fa2cc0251f40907ad69fbf35ad787aa4b8d872 100644 --- a/mtx/etherif.h +++ b/mtx/etherif.h @@ -9,7 +9,6 @@ struct Ether { int ctlrno; int tbdf; /* type+busno+devno+funcno */ - int mbps; /* Mbps */ int minmtu; int maxmtu; uchar ea[Eaddrlen]; diff --git a/pc/etherif.h b/pc/etherif.h index ff9751006be6a2ff94b79596b23a9205496ae5ab..d80e06c941d2cf7fa52ea58e15e277d3501a1196 100644 --- a/pc/etherif.h +++ b/pc/etherif.h @@ -9,7 +9,6 @@ struct Ether { int ctlrno; int tbdf; /* type+busno+devno+funcno */ - int mbps; /* Mbps */ int minmtu; int maxmtu; uchar ea[Eaddrlen]; diff --git a/port/netif.c b/port/netif.c index d10d8b34285eb282041c2e88d85709512a8be495..03b2787db7680da25a80012ce04641bb120c40ba 100644 --- a/port/netif.c +++ b/port/netif.c @@ -212,6 +212,7 @@ netifread(Netif *nif, Chan *c, void *a, long n, ulong offset) j += snprint(p+j, READSTR-j, "buffer errs: %d\n", nif->buffs); j += snprint(p+j, READSTR-j, "output errs: %d\n", nif->oerrs); j += snprint(p+j, READSTR-j, "prom: %d\n", nif->prom); + j += snprint(p+j, READSTR-j, "mbps: %d\n", nif->mbps); j += snprint(p+j, READSTR-j, "addr: "); for(i = 0; i < nif->alen; i++) j += snprint(p+j, READSTR-j, "%2.2ux", nif->addr[i]); diff --git a/port/netif.h b/port/netif.h index 7c14ff3d418df3fab45411cab5273cad849784a5..9f978f1381f9afc1d240f7d240eaf8c6a727b20e 100644 --- a/port/netif.h +++ b/port/netif.h @@ -74,6 +74,7 @@ struct Netif /* about net */ int limit; /* flow control */ int alen; /* address length */ + int mbps; /* megabits per sec */ uchar addr[Nmaxaddr]; uchar bcast[Nmaxaddr]; Netaddr *maddr; /* known multicast addresses */