M alphapc/etherif.h => alphapc/etherif.h +0 -1
@@ 9,7 9,6 @@ struct Ether {
int ctlrno;
int tbdf; /* type+busno+devno+funcno */
- int mbps; /* Mbps */
int minmtu;
int maxmtu;
uchar ea[Eaddrlen];
M bitsy/etherif.h => bitsy/etherif.h +0 -1
@@ 9,7 9,6 @@ struct Ether {
int ctlrno;
int tbdf; /* type+busno+devno+funcno */
- int mbps; /* Mbps */
int minmtu;
int maxmtu;
uchar ea[Eaddrlen];
M ip/ethermedium.c => ip/ethermedium.c +23 -17
@@ 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));
M ip/icmp6.c => ip/icmp6.c +1 -1
@@ 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;
M ip/ip.c => ip/ip.c +1 -1
@@ 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));
M ip/ip.h => ip/ip.h +5 -4
@@ 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 */
M ip/ipifc.c => ip/ipifc.c +8 -8
@@ 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]);
M ip/ipv6.c => ip/ipv6.c +1 -1
@@ 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);
M ip/loopbackmedium.c => ip/loopbackmedium.c +2 -2
@@ 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,
M ip/netdevmedium.c => ip/netdevmedium.c +5 -5
@@ 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
M ip/pktmedium.c => ip/pktmedium.c +2 -2
@@ 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,
M ip/tcp.c => ip/tcp.c +150 -46
@@ 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<<tcb->snd.scale;
+ qsetlimit(s->rq, tcb->window);
+ } else {
+ tcb->rcv.scale = 0;
+ tcb->snd.scale = 0;
+ tcb->window = QMAX;
+ qsetlimit(s->rq, tcb->window);
+ }
+}
M ip/tripmedium.c => ip/tripmedium.c +5 -5
@@ 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) {
M mtx/etherif.h => mtx/etherif.h +0 -1
@@ 9,7 9,6 @@ struct Ether {
int ctlrno;
int tbdf; /* type+busno+devno+funcno */
- int mbps; /* Mbps */
int minmtu;
int maxmtu;
uchar ea[Eaddrlen];
M pc/etherif.h => pc/etherif.h +0 -1
@@ 9,7 9,6 @@ struct Ether {
int ctlrno;
int tbdf; /* type+busno+devno+funcno */
- int mbps; /* Mbps */
int minmtu;
int maxmtu;
uchar ea[Eaddrlen];
M port/netif.c => port/netif.c +1 -0
@@ 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]);
M port/netif.h => port/netif.h +1 -0
@@ 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 */