M ip/gre.c => ip/gre.c +3 -5
@@ 47,7 47,7 @@ struct GREpriv
ulong lenerr; /* short packet */
};
-static void grekick(void *x);
+static void grekick(void *x, Block *bp);
static char*
greconnect(Conv *c, char **argv, int argc)
@@ 90,7 90,7 @@ static void
grecreate(Conv *c)
{
c->rq = qopen(64*1024, Qmsg, 0, c);
- c->wq = qopen(64*1024, Qkick, grekick, c);
+ c->wq = qbypass(grekick, c);
}
static int
@@ 121,14 121,12 @@ greclose(Conv *c)
int drop;
static void
-grekick(void *x)
+grekick(void *x, Block *bp)
{
Conv *c = x;
GREhdr *ghp;
- Block *bp;
uchar laddr[IPaddrlen], raddr[IPaddrlen];
- bp = qget(c->wq);
if(bp == nil)
return;
M ip/icmp.c => ip/icmp.c +3 -5
@@ 104,13 104,13 @@ struct Icmppriv
ulong out[Maxtype+1];
};
-static void icmpkick(void *x);
+static void icmpkick(void *x, Block*);
static void
icmpcreate(Conv *c)
{
c->rq = qopen(64*1024, Qmsg, 0, c);
- c->wq = qopen(64*1024, Qkick, icmpkick, c);
+ c->wq = qbypass(icmpkick, c);
}
extern char*
@@ 157,14 157,12 @@ icmpclose(Conv *c)
}
static void
-icmpkick(void *x)
+icmpkick(void *x, Block *bp)
{
Conv *c = x;
Icmp *p;
- Block *bp;
Icmppriv *ipriv;
- bp = qget(c->wq);
if(bp == nil)
return;
M ip/icmp6.c => ip/icmp6.c +3 -5
@@ 172,13 172,13 @@ enum {
mtuopt = 5,
};
-static void icmpkick6(void *x);
+static void icmpkick6(void *x, Block *bp);
static void
icmpcreate6(Conv *c)
{
c->rq = qopen(64*1024, Qmsg, 0, c);
- c->wq = qopen(64*1024, Qkick, icmpkick6, c);
+ c->wq = qbypass(icmpkick6, c);
}
static void
@@ 228,16 228,14 @@ icmpadvise6(Proto *icmp, Block *bp, char *msg)
}
static void
-icmpkick6(void *x)
+icmpkick6(void *x, Block *bp)
{
Conv *c = x;
IPICMP *p;
- Block *bp;
uchar laddr[IPaddrlen], raddr[IPaddrlen];
Icmppriv6 *ipriv = c->p->priv;
Icmpcb6 *icb = (Icmpcb6*)c->ptcl;
- bp = qget(c->wq);
if(bp == nil)
return;
M ip/il.c => ip/il.c +2 -4
@@ 335,14 335,13 @@ ilclose(Conv *c)
}
void
-ilkick(void *x)
+ilkick(void *x, Block *bp)
{
Conv *c = x;
Ilhdr *ih;
Ilcb *ic;
int dlen;
ulong id, ack;
- Block *bp;
Fs *f;
Ilpriv *priv;
@@ 350,7 349,6 @@ ilkick(void *x)
priv = c->p->priv;
ic = (Ilcb*)c->ptcl;
- bp = qget(c->wq);
if(bp == nil)
return;
@@ 418,7 416,7 @@ static void
ilcreate(Conv *c)
{
c->rq = qopen(64*1024, 0, 0, c);
- c->wq = qopen(64*1024, Qkick, ilkick, c);
+ c->wq = qbypass(ilkick, c);
}
int
M ip/ip.c => ip/ip.c +6 -9
@@ 220,7 220,7 @@ iprouting(Fs *f, int on)
f->ip->stats[Forwarding] = 1;
}
-void
+int
ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos)
{
Ipifc *ifc;
@@ 231,7 231,7 @@ ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos)
int lid, len, seglen, chunk, dlen, blklen, offset, medialen;
Route *r, *sr;
IP *ip;
- Proto *pr;
+ int rv = 0;
ip = f->ip;
@@ 263,11 263,7 @@ ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos)
if(r == nil){
ip->stats[OutNoRoutes]++;
netlog(f, Logip, "no interface %V\n", eh->dst);
- if(!gating){
- freeblist(bp);
-print("ipoput4: no route\n");
- error("no route");
- }
+ rv = -1;
goto free;
}
@@ 315,7 311,7 @@ print("ipoput4: no route\n");
ifc->m->bwrite(ifc, bp, V4, gate);
runlock(ifc);
poperror();
- return;
+ return 0;
}
if((eh->frag[0] & (IP_DF>>8)) && !gating) print("%V: DF set\n", eh->dst);
@@ 404,7 400,8 @@ raise:
runlock(ifc);
poperror();
free:
- freeblist(bp);
+ freeblist(bp);
+ return rv;
}
void
M ip/ip.h => ip/ip.h +2 -2
@@ 620,8 620,8 @@ extern void icmpttlexceeded(Fs*, uchar*, Block*);
extern ushort ipcsum(uchar*);
extern void ipiput4(Fs*, Ipifc*, Block*);
extern void ipiput6(Fs*, Ipifc*, Block*);
-extern void ipoput4(Fs*, Block*, int, int, int);
-extern void ipoput6(Fs*, Block*, int, int, int);
+extern int ipoput4(Fs*, Block*, int, int, int);
+extern int ipoput6(Fs*, Block*, int, int, int);
extern int ipstats(Fs*, char*, int);
extern ushort ptclbsum(uchar*, int);
extern ushort ptclcsum(Block*, int, int);
M ip/ipv6.c => ip/ipv6.c +5 -4
@@ 131,7 131,7 @@ struct IP
int iprouting; /* true if we route like a gateway */
};
-void
+int
ipoput6(Fs *f, Block *bp, int gating, int ttl, int tos)
{
int tentative;
@@ 143,7 143,7 @@ ipoput6(Fs *f, Block *bp, int gating, int ttl, int tos)
Fraghdr6 fraghdr;
Block *xp, *nb;
IP *ip;
-
+ int rv = 0;
ip = f->ip;
@@ 184,6 184,7 @@ ipoput6(Fs *f, Block *bp, int gating, int ttl, int tos)
// print("no route for %I, src %I free\n", eh->dst, eh->src);
ip->stats[OutNoRoutes]++;
netlog(f, Logip, "no interface %I\n", eh->dst);
+ rv = -1;
goto free;
}
@@ 228,7 229,7 @@ ipoput6(Fs *f, Block *bp, int gating, int ttl, int tos)
ifc->m->bwrite(ifc, bp, V6, gate);
runlock(ifc);
poperror();
- return;
+ return 0;
}
if(gating)
@@ 328,7 329,7 @@ raise:
poperror();
free:
freeblist(bp);
-
+ return rv;
}
void
M ip/tcp.c => ip/tcp.c +12 -13
@@ 2411,11 2411,6 @@ tcpoutput(Conv *s)
tpriv = s->p->priv;
version = s->ipversion;
- if(waserror()){
- localclose(s, up->errstr);
- return;
- }
-
for(msgs = 0; msgs < 100; msgs++) {
tcb = (Tcpctl*)s->ptcl;
@@ 2423,7 2418,7 @@ tcpoutput(Conv *s)
case Listen:
case Closed:
case Finwait2:
- goto out;
+ return;
}
/* force an ack when a window has opened up */
@@ 2550,7 2545,7 @@ tcpoutput(Conv *s)
hbp = htontcp4(&seg, bp, &tcb->protohdr.tcp4hdr, tcb);
if(hbp == nil) {
freeblist(bp);
- goto out;
+ return;
}
break;
case V6:
@@ 2558,7 2553,7 @@ tcpoutput(Conv *s)
hbp = htontcp6(&seg, bp, &tcb->protohdr.tcp6hdr, tcb);
if(hbp == nil) {
freeblist(bp);
- goto out;
+ return;
}
break;
default:
@@ 2590,10 2585,16 @@ tcpoutput(Conv *s)
switch(version){
case V4:
- ipoput4(f, hbp, 0, s->ttl, s->tos);
+ if(ipoput4(f, hbp, 0, s->ttl, s->tos) < 0){
+ /* a negative return means no route */
+ localclose(s, "no route");
+ }
break;
case V6:
- ipoput6(f, hbp, 0, s->ttl, s->tos);
+ if(ipoput6(f, hbp, 0, s->ttl, s->tos) < 0){
+ /* a negative return means no route */
+ localclose(s, "no route");
+ }
break;
default:
panic("tcpoutput2: version %d", version);
@@ 2604,8 2605,6 @@ tcpoutput(Conv *s)
qlock(s);
}
}
-out:
- poperror();
}
/*
@@ 2745,7 2744,7 @@ tcprxmit(Conv *s)
tcb->snd.ptr = tcb->snd.una;
/*
- * We should be halving the slow start thershhold (down to one
+ * We should be halving the slow start threshhold (down to one
* mss) but leaving it at mss seems to work well enough
*/
tcb->ssthresh = tcb->mss;
M ip/udp.c => ip/udp.c +3 -5
@@ 93,7 93,7 @@ struct Udppriv
};
void (*etherprofiler)(char *name, int qlen);
-void udpkick(void *x);
+void udpkick(void *x, Block *bp);
/*
* protocol specific part of Conv
@@ 148,7 148,7 @@ static void
udpcreate(Conv *c)
{
c->rq = qopen(128*1024, Qmsg, 0, 0);
- c->wq = qopen(128*1024, Qkick, udpkick, c);
+ c->wq = qbypass(udpkick, c);
}
static void
@@ 176,14 176,13 @@ udpclose(Conv *c)
}
void
-udpkick(void *x)
+udpkick(void *x, Block *bp)
{
Conv *c = x;
Udp4hdr *uh4;
Udp6hdr *uh6;
ushort rport;
uchar laddr[IPaddrlen], raddr[IPaddrlen];
- Block *bp;
Udpcb *ucb;
int dlen, ptcllen;
Udppriv *upriv;
@@ 194,7 193,6 @@ udpkick(void *x)
f = c->p->f;
netlog(c->p->f, Logudp, "udp: kick\n");
- bp = qget(c->wq);
if(bp == nil)
return;
M port/portfns.h => port/portfns.h +1 -0
@@ 241,6 241,7 @@ ulong pwait(Waitmsg*);
void qaddlist(Queue*, Block*);
Block* qbread(Queue*, int);
long qbwrite(Queue*, Block*);
+Queue* qbypass(void (*)(void*, Block*), void*);
int qcanread(Queue*);
void qclose(Queue*);
int qconsume(Queue*, void*, int);
M port/qio.c => port/qio.c +26 -3
@@ 38,6 38,7 @@ struct Queue
int eof; /* number of eofs read by user */
void (*kick)(void*); /* restart output */
+ void (*bypass)(void*, Block*); /* bypass queue altogether */
void* arg; /* argument to kick */
QLock rlock; /* mutex for reading processes */
@@ 795,7 796,6 @@ qopen(int limit, int msg, void (*kick)(void*), void *arg)
if(q == 0)
return 0;
- ilock(q);
q->limit = q->inilim = limit;
q->kick = kick;
q->arg = arg;
@@ 804,7 804,24 @@ qopen(int limit, int msg, void (*kick)(void*), void *arg)
q->state |= Qstarve;
q->eof = 0;
q->noblock = 0;
- iunlock(q);
+
+ return q;
+}
+
+/* open a queue to be bypassed */
+Queue*
+qbypass(void (*bypass)(void*, Block*), void *arg)
+{
+ Queue *q;
+
+ q = malloc(sizeof(Queue));
+ if(q == 0)
+ return 0;
+
+ q->limit = 0;
+ q->arg = arg;
+ q->bypass = bypass;
+ q->state = 0;
return q;
}
@@ 1143,8 1160,14 @@ qbwrite(Queue *q, Block *b)
int n, dowakeup;
Proc *p;
- dowakeup = 0;
n = BLEN(b);
+
+ if(q->bypass){
+ (*q->bypass)(q->arg, b);
+ return n;
+ }
+
+ dowakeup = 0;
qlock(&q->wlock);
if(waserror()){
if(b != nil)