M alphapc/devether.c => alphapc/devether.c +8 -1
@@ 241,8 241,15 @@ etherwrite(Chan* chan, void* buf, long n, vlong)
Block *bp;
ether = etherxx[chan->dev];
- if(NETTYPE(chan->qid.path) != Ndataqid)
+ if(NETTYPE(chan->qid.path) != Ndataqid){
+
+ if(n == sizeof("nonblocking")-1 && strncmp((char*)buf, "nonblocking", n) == 0){
+ qnoblock(ether->oq, 1);
+ return n;
+ }
+
return netifwrite(ether, chan, buf, n);
+ }
if(n > ETHERMAXTU)
error(Etoobig);
M bitsy/devether.c => bitsy/devether.c +4 -0
@@ 463,6 463,10 @@ etherwrite(Chan* chan, void* buf, long n, vlong)
l = netifwrite(ether, chan, buf, n);
if(l >= 0)
goto out;
+ if(n == sizeof("nonblocking")-1 && strncmp((char*)buf, "nonblocking", n) == 0){
+ qnoblock(ether->oq, 1);
+ goto out;
+ }
if(ether->ctl!=nil){
l = ether->ctl(ether,buf,n);
goto out;
M ip/devip.c => ip/devip.c +0 -4
@@ 1053,8 1053,6 @@ ipwrite(Chan* ch, void *v, long n, vlong off)
error(Eperm);
qwrite(c->wq, a, n);
- if(x->kick != nil)
- x->kick(c);
break;
case Qarp:
return arpwrite(f, a, n);
@@ 1147,8 1145,6 @@ ipbwrite(Chan* ch, Block* bp, ulong offset)
bp = concatblock(bp);
n = BLEN(bp);
qbwrite(c->wq, bp);
- if(x->kick != nil)
- x->kick(c);
return n;
default:
return devbwrite(ch, bp, offset);
M ip/esp.c => ip/esp.c +5 -4
@@ 120,6 120,7 @@ static void shaahinit(Espcb*, char*, uchar *key, int keylen);
static void md5ahinit(Espcb*, char*, uchar *key, int keylen);
static void desespinit(Espcb *ecb, char *name, uchar *k, int n);
static void rc4espinit(Espcb *ecb, char *name, uchar *k, int n);
+static void espkick(void *x);
static Algorithm espalg[] =
{
@@ 199,7 200,7 @@ static void
espcreate(Conv *c)
{
c->rq = qopen(64*1024, Qmsg, 0, 0);
- c->wq = qopen(64*1024, 0, 0, 0);
+ c->wq = qopen(64*1024, Qkick, espkick, c);
}
static void
@@ 219,9 220,10 @@ espclose(Conv *c)
memset(ecb, 0, sizeof(Espcb));
}
-void
-espkick(Conv *c)
+static void
+espkick(void *x)
{
+ Conv *c = x;
Esphdr *eh;
Esptail *et;
Userhdr *uh;
@@ 845,7 847,6 @@ espinit(Fs *fs)
esp = smalloc(sizeof(Proto));
esp->priv = smalloc(sizeof(Esppriv));
esp->name = "esp";
- esp->kick = espkick;
esp->connect = espconnect;
esp->announce = nil;
esp->ctl = espctl;
M ip/ethermedium.c => ip/ethermedium.c +13 -1
@@ 108,6 108,8 @@ struct Etherarp
uchar tpa[4];
};
+static char *nbmsg = "nonblocking";
+
/*
* called to bind an IP ifc to an ethernet device
* called with ifc wlock'd
@@ 145,7 147,7 @@ etherbind(Ipifc *ifc, int argc, char **argv)
}
/*
- * open ip conversation
+ * open ip converstation
*
* the dial will fail if the type is already open on
* this device.
@@ 154,6 156,11 @@ etherbind(Ipifc *ifc, int argc, char **argv)
mchan4 = chandial(addr, nil, dir, &cchan4);
/*
+ * make it non-blocking
+ */
+ devtab[cchan4->type]->write(cchan4, nbmsg, strlen(nbmsg), 0);
+
+ /*
* get mac address
*/
snprint(addr, sizeof(addr), "%s/stats", dir);
@@ 190,6 197,11 @@ etherbind(Ipifc *ifc, int argc, char **argv)
snprint(addr, sizeof(addr), "%s!0x86DD", argv[2]);
mchan6 = chandial(addr, nil, dir, &cchan6);
+ /*
+ * make it non-blocking
+ */
+ devtab[cchan6->type]->write(cchan6, nbmsg, strlen(nbmsg), 0);
+
er = smalloc(sizeof(*er));
er->mchan4 = mchan4;
er->cchan4 = cchan4;
M ip/gre.c => ip/gre.c +11 -9
@@ 47,6 47,8 @@ struct GREpriv
ulong lenerr; /* short packet */
};
+static void grekick(void *x);
+
static char*
greconnect(Conv *c, char **argv, int argc)
{
@@ 84,6 86,13 @@ greconnect(Conv *c, char **argv, int argc)
return nil;
}
+static void
+grecreate(Conv *c)
+{
+ c->rq = qopen(64*1024, Qmsg, 0, c);
+ c->wq = qopen(64*1024, Qkick, grekick, c);
+}
+
static int
grestate(Conv *c, char *state, int n)
{
@@ 91,13 100,6 @@ grestate(Conv *c, char *state, int n)
return snprint(state, n, "%s", "Datagram");
}
-static void
-grecreate(Conv *c)
-{
- c->rq = qopen(64*1024, Qmsg, 0, c);
- c->wq = qopen(64*1024, 0, 0, 0);
-}
-
static char*
greannounce(Conv*, char**, int)
{
@@ 119,8 121,9 @@ greclose(Conv *c)
int drop;
static void
-grekick(Conv *c)
+grekick(void *x)
{
+ Conv *c = x;
GREhdr *ghp;
Block *bp;
uchar laddr[IPaddrlen], raddr[IPaddrlen];
@@ 241,7 244,6 @@ greinit(Fs *fs)
gre = smalloc(sizeof(Proto));
gre->priv = smalloc(sizeof(GREpriv));
gre->name = "gre";
- gre->kick = grekick;
gre->connect = greconnect;
gre->announce = greannounce;
gre->state = grestate;
M ip/icmp.c => ip/icmp.c +12 -10
@@ 104,6 104,15 @@ struct Icmppriv
ulong out[Maxtype+1];
};
+static void icmpkick(void *x);
+
+static void
+icmpcreate(Conv *c)
+{
+ c->rq = qopen(64*1024, Qmsg, 0, c);
+ c->wq = qopen(64*1024, Qkick, icmpkick, c);
+}
+
extern char*
icmpconnect(Conv *c, char **argv, int argc)
{
@@ 124,13 133,6 @@ icmpstate(Conv *c, char *state, int n)
return snprint(state, n, "%s", "Datagram");
}
-extern void
-icmpcreate(Conv *c)
-{
- c->rq = qopen(64*1024, Qmsg, 0, c);
- c->wq = qopen(64*1024, 0, 0, 0);
-}
-
extern char*
icmpannounce(Conv *c, char **argv, int argc)
{
@@ 154,9 156,10 @@ icmpclose(Conv *c)
c->lport = 0;
}
-extern void
-icmpkick(Conv *c)
+static void
+icmpkick(void *x)
{
+ Conv *c = x;
Icmp *p;
Block *bp;
Icmppriv *ipriv;
@@ 455,7 458,6 @@ icmpinit(Fs *fs)
icmp = smalloc(sizeof(Proto));
icmp->priv = smalloc(sizeof(Icmppriv));
icmp->name = "icmp";
- icmp->kick = icmpkick;
icmp->connect = icmpconnect;
icmp->announce = icmpannounce;
icmp->state = icmpstate;
M ip/icmp6.c => ip/icmp6.c +13 -5
@@ 172,6 172,15 @@ enum {
mtuopt = 5,
};
+static void icmpkick6(void *x);
+
+static void
+icmpcreate6(Conv *c)
+{
+ c->rq = qopen(64*1024, Qmsg, 0, c);
+ c->wq = qopen(64*1024, Qkick, icmpkick6, c);
+}
+
static void
set_cksum(Block *bp)
{
@@ 218,9 227,10 @@ icmpadvise6(Proto *icmp, Block *bp, char *msg)
freeblist(bp);
}
-void
-icmpkick6(Conv *c)
+static void
+icmpkick6(void *x)
{
+ Conv *c = x;
IPICMP *p;
Block *bp;
uchar laddr[IPaddrlen], raddr[IPaddrlen];
@@ 880,7 890,6 @@ icmpstats6(Proto *icmp6, char *buf, int len)
extern int icmpstate(Conv *c, char *state, int n);
extern char* icmpannounce(Conv *c, char **argv, int argc);
extern char* icmpconnect(Conv *c, char **argv, int argc);
-extern void icmpcreate(Conv *c);
extern void icmpclose(Conv *c);
void
@@ 890,11 899,10 @@ icmp6init(Fs *fs)
icmp6->priv = smalloc(sizeof(Icmppriv6));
icmp6->name = "icmpv6";
- icmp6->kick = icmpkick6;
icmp6->connect = icmpconnect;
icmp6->announce = icmpannounce;
icmp6->state = icmpstate;
- icmp6->create = icmpcreate;
+ icmp6->create = icmpcreate6;
icmp6->close = icmpclose;
icmp6->rcv = icmpiput6;
icmp6->stats = icmpstats6;
M ip/igmp.c => ip/igmp.c +0 -1
@@ 274,7 274,6 @@ void
igmpinit(Fs *fs)
{
igmp.name = "igmp";
- igmp.kick = nil;
igmp.connect = nil;
igmp.announce = nil;
igmp.ctl = nil;
M ip/il.c => ip/il.c +3 -3
@@ 335,8 335,9 @@ ilclose(Conv *c)
}
void
-ilkick(Conv *c)
+ilkick(void *x)
{
+ Conv *c = x;
Ilhdr *ih;
Ilcb *ic;
int dlen;
@@ 417,7 418,7 @@ static void
ilcreate(Conv *c)
{
c->rq = qopen(64*1024, Qmsg, 0, c);
- c->wq = qopen(64*1024, 0, 0, 0);
+ c->wq = qopen(64*1024, Qkick, ilkick, c);
}
int
@@ 1378,7 1379,6 @@ ilinit(Fs *f)
il = smalloc(sizeof(Proto));
il->priv = smalloc(sizeof(Ilpriv));
il->name = "il";
- il->kick = ilkick;
il->connect = ilconnect;
il->announce = ilannounce;
il->state = ilstate;
M ip/ip.h => ip/ip.h +0 -1
@@ 283,7 283,6 @@ struct Proto
int x; /* protocol index */
int ipproto; /* ip protocol type */
- void (*kick)(Conv*);
char* (*connect)(Conv*, char**, int);
char* (*announce)(Conv*, char**, int);
char* (*bind)(Conv*, char**, int);
M ip/ipifc.c => ip/ipifc.c +2 -2
@@ 283,8 283,9 @@ ipifcinuse(Conv *c)
* called when a process writes to an interface's 'data'
*/
static void
-ipifckick(Conv *c)
+ipifckick(void *x)
{
+ Conv *c = x;
Block *bp;
Ipifc *ifc;
@@ 841,7 842,6 @@ ipifcinit(Fs *f)
ipifc = smalloc(sizeof(Proto));
ipifc->name = "ipifc";
- ipifc->kick = ipifckick;
ipifc->connect = ipifcconnect;
ipifc->announce = nil;
ipifc->bind = ipifcbind;
M ip/ipmux.c => ip/ipmux.c +4 -3
@@ 106,6 106,7 @@ struct Ipmuxrock
};
static int ipmuxsprint(Ipmux*, int, char*, int);
+static void ipmuxkick(void *x);
static char*
skipwhite(char *p)
@@ 613,7 614,7 @@ ipmuxcreate(Conv *c)
Ipmuxrock *r;
c->rq = qopen(64*1024, Qmsg, 0, c);
- c->wq = qopen(64*1024, 0, 0, 0);
+ c->wq = qopen(64*1024, Qkick, ipmuxkick, c);
r = (Ipmuxrock*)(c->ptcl);
r->chain = nil;
}
@@ 652,8 653,9 @@ ipmuxclose(Conv *c)
* the stack
*/
static void
-ipmuxkick(Conv *c)
+ipmuxkick(void *x)
{
+ Conv *c = x;
Block *bp;
struct Ip6hdr *ih6;
@@ 836,7 838,6 @@ ipmuxinit(Fs *f)
ipmux = smalloc(sizeof(Proto));
ipmux->priv = nil;
ipmux->name = "ipmux";
- ipmux->kick = ipmuxkick;
ipmux->connect = ipmuxconnect;
ipmux->announce = ipmuxannounce;
ipmux->state = ipmuxstate;
M ip/rudp.c => ip/rudp.c +4 -3
@@ 192,6 192,7 @@ void relackq(Reliable *, Block*);
void relhangup(Conv *, Reliable*);
void relrexmit(Conv *, Reliable*);
void relput(Reliable*);
+void rudpkick(void *x);
static void
rudpstartackproc(Proto *rudp)
@@ 264,7 265,7 @@ static void
rudpcreate(Conv *c)
{
c->rq = qopen(64*1024, Qmsg, 0, 0);
- c->wq = qopen(64*1024, 0, 0, 0);
+ c->wq = qopen(64*1024, Qkick, rudpkick, c);
}
static void
@@ 333,8 334,9 @@ flow(void *v)
}
void
-rudpkick(Conv *c)
+rudpkick(void *x)
{
+ Conv *c = x;
Udphdr *uh;
ushort rport;
uchar laddr[IPaddrlen], raddr[IPaddrlen];
@@ 708,7 710,6 @@ rudpinit(Fs *fs)
rudp = smalloc(sizeof(Proto));
rudp->priv = smalloc(sizeof(Rudppriv));
rudp->name = "rudp";
- rudp->kick = rudpkick;
rudp->connect = rudpconnect;
rudp->announce = rudpannounce;
rudp->ctl = rudpctl;
M ip/tcp.c => ip/tcp.c +24 -30
@@ 198,18 198,19 @@ struct Tcpctl
ulong una; /* Unacked data pointer */
ulong nxt; /* Next sequence expected */
ulong ptr; /* Data pointer */
- ushort wnd; /* Tcp send window */
+ ushort wnd; /* Tcp send window */
ulong urg; /* Urgent data pointer */
ulong wl2;
/* to implement tahoe and reno TCP */
- ulong dupacks; /* number of duplicate acks rcvd */
- int recovery; /* loss recovery flag */
- ulong rxt; /* right window marker for recovery */
+ ulong dupacks; /* number of duplicate acks rcvd */
+ int recovery; /* loss recovery flag */
+ ulong rxt; /* right window marker for recovery */
} snd;
struct {
ulong nxt; /* Receive pointer to next uchar slot */
ushort wnd; /* Receive window incoming */
ulong urg; /* Urgent pointer */
+ ulong lastacked; /* Last ack sent */
int blocked;
} rcv;
ulong iss; /* Initial sequence number */
@@ 220,7 221,6 @@ struct Tcpctl
ushort mss; /* Mean segment size */
int rerecv; /* Overlap of data rerecevived */
ushort window; /* Recevive window */
- ulong last_ack; /* Last acknowledege received */
uchar backoff; /* Exponential backoff counter */
int backedoff; /* ms we've backed off for rexmits */
uchar flags; /* State flags */
@@ 501,8 501,9 @@ tcpclose(Conv *c)
}
void
-tcpkick(Conv *s)
+tcpkick(void *x)
{
+ Conv *s = x;
Tcpctl *tcb;
tcb = (Tcpctl*)s->ptcl;
@@ 534,12 535,6 @@ tcpkick(Conv *s)
}
void
-tcpqkick(void *x)
-{
- tcpkick((Conv*)x);
-}
-
-void
tcprcvwin(Conv *s) /* Call with tcb locked */
{
int w;
@@ 581,7 576,7 @@ static void
tcpcreate(Conv *c)
{
c->rq = qopen(QMAX, Qcoalesce, tcpacktimer, c);
- c->wq = qopen(2*QMAX, Qkick, tcpqkick, c);
+ c->wq = qopen(2*QMAX, Qkick, tcpkick, c);
}
static void
@@ 1229,11 1224,11 @@ tcphangup(Conv *s)
if(s->raddr != 0) {
seg.flags = RST | ACK;
seg.ack = tcb->rcv.nxt;
+ tcb->rcv.lastacked = tcb->rcv.nxt;
seg.seq = tcb->snd.ptr;
seg.wnd = 0;
seg.urg = 0;
seg.mss = 0;
- tcb->last_ack = tcb->rcv.nxt;
switch(s->ipversion) {
case V4:
tcb->protohdr.tcp4hdr.vihl = IP_VER4;
@@ 1294,9 1289,9 @@ sndsynack(Proto *tcp, Limbo *lp)
seg.seq = lp->iss;
seg.ack = lp->irs+1;
seg.flags = SYN|ACK;
- seg.wnd = 0;
seg.urg = 0;
seg.mss = tcpmtu(tcp, lp->laddr, lp->version);
+ seg.wnd = QMAX;
switch(lp->version) {
case V4:
@@ 1660,7 1655,7 @@ update(Conv *s, Tcp *seg)
return;
}
- /* added by Dong for fast retransmission */
+ /* added by Dong Lin for fast retransmission */
if(seg->ack == tcb->snd.una
&& tcb->snd.una != tcb->snd.nxt
&& seg->len == 0
@@ 1779,9 1774,10 @@ done:
if(seq_gt(seg->ack, tcb->snd.urg))
tcb->snd.urg = seg->ack;
- tcphalt(tpriv, &tcb->timer);
if(tcb->snd.una != tcb->snd.nxt)
tcpgo(tpriv, &tcb->timer);
+ else
+ tcphalt(tpriv, &tcb->timer);
if(seq_lt(tcb->snd.ptr, tcb->snd.una))
tcb->snd.ptr = tcb->snd.una;
@@ 2003,10 1999,11 @@ reset:
* This is an attempt to defeat these stateless DOS attacks. See
* corresponding code in tcpsendka().
*/
- if(tcb->state != Syn_received){
+ if(tcb->state != Syn_received && (seg.flags & RST) == 0){
if(seq_within(seg.ack, tcb->snd.una-(1<<31), tcb->snd.una-(1<<29))){
- print("stateless hog %lux - %lux - %lux\n", tcb->snd.una-(1<<31), seg.ack,
- tcb->snd.una-(1<<29));
+ print("stateless hog %I.%d->%I.%d f %ux %lux - %lux - %lux\n",
+ source, seg.source, dest, seg.dest, seg.flags,
+ tcb->snd.una-(1<<31), seg.ack, tcb->snd.una-(1<<29));
localclose(s, "stateless hog");
}
}
@@ 2162,7 2159,7 @@ reset:
* force an ack if we've got 2 segs since we
* last acked.
*/
- if(tcb->rcv.nxt - tcb->last_ack >= 2*tcb->mss)
+ if(tcb->rcv.nxt - tcb->rcv.lastacked >= 2*tcb->mss)
tcb->flags |= FORCE;
/*
@@ 2365,9 2362,9 @@ tcpoutput(Conv *s)
}
break;
}
- tcb->last_ack = tcb->rcv.nxt;
seg.seq = tcb->snd.ptr;
seg.ack = tcb->rcv.nxt;
+ tcb->rcv.lastacked = tcb->rcv.nxt;
seg.wnd = tcb->rcv.wnd;
/* Pull out data to send */
@@ 2490,8 2487,8 @@ tcpsendka(Conv *s)
seg.mss = 0;
seg.seq = tcb->snd.una-(1<<30)-nrand(1<<20);
seg.ack = tcb->rcv.nxt;
+ tcb->rcv.lastacked = tcb->rcv.nxt;
seg.wnd = tcb->rcv.wnd;
- tcb->last_ack = tcb->rcv.nxt;
if(tcb->state == Finwait2){
seg.flags |= FIN;
} else {
@@ 2959,12 2956,10 @@ tcpsettimer(Tcpctl *tcb)
x = backoff(tcb->backoff) *
(tcb->mdev + (tcb->srtt>>LOGAGAIN) + MSPTICK) / MSPTICK;
- /* take into account delayed ack */
- if((tcb->snd.ptr - tcb->snd.una) <= 2*tcb->mss)
- x += TCP_ACK/MSPTICK;
-
- /* sanity check */
- if(x > (10000/MSPTICK))
+ /* bounded twixt 1/2 and 10 seconds */
+ if(x < 500/MSPTICK)
+ x = 500/MSPTICK;
+ else if(x > (10000/MSPTICK))
x = 10000/MSPTICK;
tcb->timer.start = x;
}
@@ 2978,7 2973,6 @@ tcpinit(Fs *fs)
tcp = smalloc(sizeof(Proto));
tpriv = tcp->priv = smalloc(sizeof(Tcppriv));
tcp->name = "tcp";
- tcp->kick = nil;
tcp->connect = tcpconnect;
tcp->announce = tcpannounce;
tcp->ctl = tcpctl;
M ip/udp.c => ip/udp.c +4 -3
@@ 93,6 93,7 @@ struct Udppriv
};
void (*etherprofiler)(char *name, int qlen);
+void udpkick(void *x);
/*
* protocol specific part of Conv
@@ 147,7 148,7 @@ static void
udpcreate(Conv *c)
{
c->rq = qopen(128*1024, Qmsg, 0, 0);
- c->wq = qopen(128*1024, 0, 0, 0);
+ c->wq = qopen(128*1024, Qkick, udpkick, c);
}
static void
@@ 175,8 176,9 @@ udpclose(Conv *c)
}
void
-udpkick(Conv *c)
+udpkick(void *x)
{
+ Conv *c = x;
Udp4hdr *uh4;
Udp6hdr *uh6;
ushort rport;
@@ 623,7 625,6 @@ udpinit(Fs *fs)
udp = smalloc(sizeof(Proto));
udp->priv = smalloc(sizeof(Udppriv));
udp->name = "udp";
- udp->kick = udpkick;
udp->connect = udpconnect;
udp->announce = udpannounce;
udp->ctl = udpctl;
M mtx/devether.c => mtx/devether.c +5 -0
@@ 247,6 247,11 @@ etherwrite(Chan* chan, void* buf, long n, vlong)
if(nn >= 0)
return nn;
+ if(n == sizeof("nonblocking")-1 && strncmp((char*)buf, "nonblocking", n) == 0){
+ qnoblock(ether->oq, 1);
+ return;
+ }
+
if(ether->ctl!=nil)
return ether->ctl(ether,buf,n);
M pc/devether.c => pc/devether.c +5 -2
@@ 247,7 247,10 @@ etherwrite(Chan* chan, void* buf, long n, vlong)
nn = netifwrite(ether, chan, buf, n);
if(nn >= 0)
return nn;
-
+ if(n == sizeof("nonblocking")-1 && strncmp((char*)buf, "nonblocking", n) == 0){
+ qnoblock(ether->oq, 1);
+ return n;
+ }
if(ether->ctl!=nil)
return ether->ctl(ether,buf,n);
@@ 414,7 417,7 @@ etherprobe(int cardno, int ctlrno)
print(buf);
if(ether->mbps >= 100){
- netifinit(ether, name, Ntypes, 512*1024);
+ netifinit(ether, name, Ntypes, 256*1024);
if(ether->oq == 0)
ether->oq = qopen(256*1024, Qmsg, 0, 0);
}
M pc/devtv.c => pc/devtv.c +1 -1
@@ 1072,7 1072,7 @@ tvinterrupt(Ureg *, Tv *tv)
break;
if (astat)
- print("vstat %.8uX, astat %.8uX\n", vstat, astat);
+ print("vstat %.8luX, astat %.8luX\n", vstat, astat);
bt848->intstat = vstat;
if (bt878)
M port/qio.c => port/qio.c +1 -0
@@ 1448,6 1448,7 @@ qsetlimit(Queue *q, int limit)
void
qnoblock(Queue *q, int onoff)
{
+print("nonblocking %d\n", onoff);
q->noblock = onoff;
}