M ip/ip.h => ip/ip.h +1 -0
@@ 333,6 333,7 @@ enum
Runi= (1<<3), /* a unicast self address */
Rbcast= (1<<4), /* a broadcast self address */
Rmulti= (1<<5), /* a multicast self address */
+ Rproxy= (1<<6), /* this route should be proxied */
};
struct Routewalk
M ip/ipifc.c => ip/ipifc.c +7 -5
@@ 345,10 345,15 @@ ipifcadd(Ipifc *ifc, char **argv, int argc)
f = ifc->conv->p->f;
+ type = Rifc;
memset(ip, 0, IPaddrlen);
memset(mask, 0, IPaddrlen);
memset(rem, 0, IPaddrlen);
switch(argc){
+ case 6:
+ if(strcmp(argv[5], "proxy") == 0)
+ type |= Rproxy;
+ /* fall through */
case 5:
mtu = strtoul(argv[4], 0, 0);
if(mtu >= ifc->m->minmtu && mtu <= ifc->m->maxmtu)
@@ 396,7 401,6 @@ ipifcadd(Ipifc *ifc, char **argv, int argc)
*l = lifc;
/* add a route for the local network */
- type = Rifc;
if(ipcmp(mask, IPallbits) == 0){
/* point to point networks are a hack */
if(ipcmp(ip, rem) == 0)
@@ 410,7 414,7 @@ ipifcadd(Ipifc *ifc, char **argv, int argc)
addselfcache(f, ifc, lifc, ip, Runi);
- if(type & Rptpt){
+ if((type & (Rptpt|Rproxy)) == (Rptpt|Rproxy)){
ipifcregisterproxy(f, ifc, rem);
goto out;
}
@@ 1088,9 1092,7 @@ ipproxyifc(Fs *f, Ipifc *ifc, uchar *ip)
r = v6lookup(f, ip);
if(r == nil)
return 0;
- if((r->type & Rifc) == 0)
- return 0;
- if((r->type & Rptpt) == 0)
+ if((r->type & (Rifc|Rptpt|Rproxy)) != (Rifc|Rptpt|Rproxy))
return 0;
/* see if this is on the right interface */
M ip/udp.c => ip/udp.c +25 -16
@@ 234,7 234,7 @@ udpiput(Proto *udp, uchar *ia, Block *bp)
{
int len, olen, ottl;
Udphdr *uh;
- Conv *c, **p;
+ Conv *c, **p, *gc;
Udpcb *ucb;
uchar raddr[IPaddrlen], laddr[IPaddrlen];
ushort rport, lport;
@@ 272,8 272,12 @@ udpiput(Proto *udp, uchar *ia, Block *bp)
qlock(udp);
- /* Look for a conversation structure for this port */
- c = nil;
+ /*
+ * Look for a conversation structure for this port. One
+ * with headers off wins over one with headers on, i.e.,
+ * specific wins over generic.
+ */
+ gc = c = nil;
for(p = udp->conv; *p; p++) {
c = *p;
if(c->inuse == 0)
@@ 282,8 286,10 @@ udpiput(Proto *udp, uchar *ia, Block *bp)
ucb = (Udpcb*)c->ptcl;
/* with headers turned on, descriminate only on local port */
- if(ucb->headers)
- break;
+ if(ucb->headers && gc == nil){
+ gc = c;
+ continue;
+ }
/* otherwise discriminate on lport, rport, and raddr */
if(c->rport == 0 || c->rport == rport)
@@ 292,17 298,20 @@ udpiput(Proto *udp, uchar *ia, Block *bp)
break;
}
}
-
- if(*p == nil) {
- upriv->ustats.udpNoPorts++;
- qunlock(udp);
- netlog(f, Logudp, "udp: no conv %I!%d -> %I!%d\n", raddr, rport,
- laddr, lport);
- uh->Unused = ottl;
- hnputs(uh->udpplen, olen);
- icmpnoconv(f, bp);
- freeblist(bp);
- return;
+ if(*p == nil){
+ if(gc != nil)
+ c = gc;
+ else {
+ upriv->ustats.udpNoPorts++;
+ qunlock(udp);
+ netlog(f, Logudp, "udp: no conv %I!%d -> %I!%d\n", raddr, rport,
+ laddr, lport);
+ uh->Unused = ottl;
+ hnputs(uh->udpplen, olen);
+ icmpnoconv(f, bp);
+ freeblist(bp);
+ return;
+ }
}
ucb = (Udpcb*)c->ptcl;
M pc/devlml.c => pc/devlml.c +1 -1
@@ 351,7 351,7 @@ lmlintr(Ureg *, void *) {
}
thetime = todget(nil);
jpgheader[fno].sec = (ulong)(thetime / 1000000000LL);
- jpgheader[fno].usec = (ulong)(thetime % 1000000000LL) / 1000;
+ jpgheader[fno].nsec = (ulong)(thetime % 1000000000LL);
jpgheader[fno].frameSize =
(codeData->statCom[fno] & 0x00ffffff) >> 1;
jpgheader[fno].frameSeqNo = codeData->statCom[fno] >> 24;
M pc/devlml.h => pc/devlml.h +1 -1
@@ 71,7 71,7 @@ struct FrameHeader { // Don't modify this struct, used by h/w
char nm[4];
ushort frameNo;
ulong sec;
- ulong usec;
+ ulong nsec;
ulong frameSize;
ulong frameSeqNo;
};
M pc/vgamach64xx.c => pc/vgamach64xx.c +1 -0
@@ 25,6 25,7 @@ static ushort mach64xxdid[] = {
('G'<<8)|'Q',
('G'<<8)|'T',
('G'<<8)|'U',
+ ('G'<<8)|'Z',
('V'<<8)|'T',
('V'<<8)|'U',
0,
M port/devsdp.c => port/devsdp.c +92 -68
@@ 36,7 36,8 @@ enum
Maxconv= 256, // power of 2
Nfs= 4, // number of file systems
- Maxretries= 4,
+ MaxRetries= 8,
+ KeepAlive = 60, // keep alive in seconds
KeyLength= 32,
};
@@ 70,7 71,8 @@ struct OneWay
// conv states
enum {
CInit,
- COpening,
+ CDial,
+ CAccept,
COpen,
CClosing,
CClosed,
@@ 127,11 129,11 @@ enum {
};
enum {
- ConOpen,
+ ConOpenRequest,
ConOpenAck,
- ConOpenNack,
ConClose,
ConCloseAck,
+ ConReset,
};
struct ConnectPkt
@@ 181,7 183,8 @@ static Dirtab *dirtab[MaxQ];
static Sdp sdptab[Nfs];
static char *convstatename[] = {
[CInit] "Init",
- [COpening] "Opening",
+ [CDial] "Dial",
+ [CAccept] "Accept",
[COpen] "Open",
[CClosing] "Closing",
[CClosed] "Closed",
@@ 325,7 328,6 @@ sdpopen(Chan* ch, int omode)
if(strcmp(up->user, c->owner) != 0 || (perm & c->perm) != perm)
error(Eperm);
c->ref++;
-print(c->ref = %d\n", c->ref);
if(TYPE(ch->qid) == Qdata)
c->dataopen++;
qunlock(c);
@@ 373,6 375,7 @@ print("close c->ref = %d\n", c->ref);
default:
convsetstate(c, CClosed);
break;
+ case CAccept:
case COpen:
convsetstate(c, CClosing);
break;
@@ 391,7 394,6 @@ sdpread(Chan *ch, void *a, long n, vlong off)
{
char buf[256];
Sdp *sdp = sdptab + ch->dev;
- char *s;
Conv *c;
Block *b;
@@ 408,23 410,7 @@ sdpread(Chan *ch, void *a, long n, vlong off)
case Qstatus:
c = sdp->conv[CONV(ch->qid)];
qlock(c);
- switch(c->state) {
- default:
- panic("unknown state");
- case CClosed:
- s = "closed";
- break;
- case COpening:
- s = "opening";
- break;
- case COpen:
- s = "open";
- break;
- case CClosing:
- s = "closing";
- break;
- }
- n = readstr(off, a, n, s);
+ n = readstr(off, a, n, convstatename[c->state]);
qunlock(c);
return n;
case Qctl:
@@ 498,11 484,11 @@ print("cmd = %s\n", arg0);
if(cb->nf != 2)
error("usage: accect id");
c->dialid = atoi(cb->f[1]);
- convsetstate(c, COpen);
+ convsetstate(c, CAccept);
} else if(strcmp(arg0, "dial") == 0) {
if(cb->nf != 1)
error("usage: dial");
- convsetstate(c, COpening);
+ convsetstate(c, CDial);
} else if(strcmp(arg0, "drop") == 0) {
if(cb->nf != 2)
error("usage: drop permil");
@@ 620,16 606,25 @@ sdpclone(Sdp *sdp)
}
// assume c is locked
+static void
+convretryinit(Conv *c)
+{
+ c->retries = 0;
+ // +2 to avoid rounding effects.
+ c->timeout = TK2SEC(m->ticks) + 2;
+};
+
+// assume c is locked
static int
convretry(Conv *c)
{
c->retries++;
- if(c->retries > Maxretries) {
+ if(c->retries > MaxRetries) {
print("convretry: giving up\n");
convsetstate(c, CClosed);
return 0;
}
- c->timeout = TK2SEC(m->ticks) + (1<<c->retries);
+ c->timeout = TK2SEC(m->ticks) + (c->retries+1);
return 1;
}
@@ 643,17 638,20 @@ convtimer(Conv *c, ulong sec)
qunlock(c);
nexterror();
}
+print("convtimer: %s\n", convstatename[c->state]);
switch(c->state) {
- case COpening:
-print("COpening timeout\n");
+ case CDial:
+ if(convretry(c))
+ convoput2(c, ConOpenRequest, c->dialid, 0);
+ break;
+ case CAccept:
if(convretry(c))
- convoput2(c, ConOpen, c->dialid, 0);
+ convoput2(c, ConOpenAck, c->dialid, c->acceptid);
break;
case COpen:
- // check for control packet
+ // check for control packet and keepalive
break;
case CClosing:
-print("CClosing timeout\n");
if(convretry(c))
convoput2(c, ConClose, c->dialid, c->acceptid);
break;
@@ 716,31 714,30 @@ print("convsetstate %s -> %s\n", convstatename[c->state], convstatename[state]);
switch(state) {
default:
panic("setstate: bad state: %d", state);
- case COpening:
- if(c->state != CInit)
- error("convsetstate: illegal transition");
+ case CDial:
+ assert(c->state == CInit);
c->dialid = (rand()<<16) + rand();
- c->timeout = TK2SEC(m->ticks) + 2;
- c->retries = 0;
- convoput2(c, ConOpen, c->dialid, 0);
+ convretryinit(c);
+ convoput2(c, ConOpenRequest, c->dialid, 0);
+ break;
+ case CAccept:
+ assert(c->state == CInit);
+ c->acceptid = (rand()<<16) + rand();
+ convretryinit(c);
+ convoput2(c, ConOpenAck, c->dialid, c->acceptid);
break;
case COpen:
- switch(c->state) {
- default:
- error("convsetstate: illegal transition");
- case CInit:
- c->acceptid = (rand()<<16) + rand();
+ assert(c->state == CDial || c->state == CAccept);
+ if(c->state == CDial) {
+ convretryinit(c);
convoput2(c, ConOpenAck, c->dialid, c->acceptid);
- break;
- case COpening:
- break;
}
// setup initial key and auth method
break;
case CClosing:
+ assert(c->state == COpen);
+ convretryinit(c);
convoput2(c, ConClose, c->dialid, c->acceptid);
- c->timeout = TK2SEC(m->ticks) + 2;
- c->retries = 0;
break;
case CClosed:
if(c->readproc)
@@ 900,32 897,59 @@ conviput2(Conv *c, Block *b)
print("conviput2: %d %uld %uld\n", con->op, dialid, acceptid);
switch(con->op) {
- case ConOpen:
- if(c->state != COpen || dialid != c->dialid || acceptid != c->acceptid)
- convoput2(c, ConOpenNack, dialid, acceptid);
- else
- convoput2(c, ConOpenAck, dialid, acceptid);
- break;
- case ConOpenAck:
- if(c->state != COpening || dialid != c->dialid)
+ case ConOpenRequest:
+ switch(c->state) {
+ default:
+ convoput2(c, ConReset, dialid, acceptid);
+ break;
+ case CInit:
+ c->dialid = dialid;
+ convsetstate(c, CAccept);
break;
- c->acceptid = acceptid;
- convsetstate(c, COpen);
+ case CAccept:
+ case COpen:
+ if(dialid != c->dialid || acceptid != c->acceptid)
+ convoput2(c, ConReset, dialid, acceptid);
+ break;
+ }
break;
- case ConOpenNack:
- if(c->state != COpening || dialid != c->dialid)
+ case ConOpenAck:
+ switch(c->state) {
+ case CDial:
+ if(dialid != c->dialid) {
+ convoput2(c, ConReset, dialid, acceptid);
+ break;
+ }
+ c->acceptid = acceptid;
+ convsetstate(c, COpen);
break;
- convsetstate(c, CClosed);
+ case CAccept:
+ if(dialid != c->dialid || acceptid != c->acceptid) {
+ convoput2(c, ConReset, dialid, acceptid);
+ break;
+ }
+ convsetstate(c, COpen);
+ }
break;
case ConClose:
- if(dialid != c->dialid || acceptid != c->acceptid)
+ convoput2(c, ConCloseAck, dialid, acceptid);
+ // fall though
+ case ConReset:
+ switch(c->state) {
+ case CDial:
+ if(dialid == c->dialid)
+ convsetstate(c, CClosed);
break;
- convsetstate(c, CClosed);
- break;
- case ConCloseAck:
- if(c->state != CClosing || dialid != c->dialid || acceptid != c->acceptid)
+ case CAccept:
+ case COpen:
+ case CClosing:
+ if(dialid == c->dialid && acceptid == c->acceptid)
+ convsetstate(c, CClosed);
break;
- convsetstate(c, CClosed);
+ }
+ case ConCloseAck:
+ if(c->state == CClosing && dialid == c->dialid && acceptid == c->acceptid)
+ convsetstate(c, CClosed);
break;
}
}