📄 il.c
字号:
ic->fasttimeout = 0; ic->rexmit = 0; goto established; } break; case Ilclose: if(ack == ic->start) ilhangup(s, "remote close"); break; } freeblist(bp); break; case Ilestablished: established: switch(h->iltype) { case Ilsync: if(id != ic->rstart) ilhangup(s, "remote close"); else ilsendctl(s, nil, Ilack, ic->next, ic->rstart, 0); freeblist(bp); break; case Ildata: /* * avoid consuming all the mount rpc buffers in the * system. if the input queue is too long, drop this * packet. */ if (s->rq && qlen(s->rq) >= Maxrq) { priv->stats[DroppedMsgs]++; freeblist(bp); break; } ilackto(ic, ack, bp); iloutoforder(s, h, bp); ilpullup(s); break; case Ildataquery: ilackto(ic, ack, bp); iloutoforder(s, h, bp); ilpullup(s); ilsendctl(s, nil, Ilstate, ic->next, ic->recvd, h->ilspec); break; case Ilack: ilackto(ic, ack, bp); freeblist(bp); break; case Ilquery: ilackto(ic, ack, bp); ilsendctl(s, nil, Ilstate, ic->next, ic->recvd, h->ilspec); freeblist(bp); break; case Ilstate: if(ack >= ic->rttack) ic->rttack = 0; ilackto(ic, ack, bp); if(h->ilspec > Nqt) h->ilspec = 0; if(ic->qt[h->ilspec] > ack){ ilrexmit(ic); ilsettimeout(ic); } freeblist(bp); break; case Ilclose: freeblist(bp); if(ack < ic->start || ack > ic->next) break; ic->recvd = id; ilsendctl(s, nil, Ilclose, ic->next, ic->recvd, 0); ic->state = Ilclosing; ilsettimeout(ic); ilfreeq(ic); break; } break; case Illistening: freeblist(bp); break; case Ilclosing: switch(h->iltype) { case Ilclose: ic->recvd = id; ilsendctl(s, nil, Ilclose, ic->next, ic->recvd, 0); if(ack == ic->next) ilhangup(s, nil); break; default: break; } freeblist(bp); break; }}voidilrexmit(Ilcb *ic){ Ilhdr *h; Block *nb; Conv *c; ulong id; Ilpriv *priv; nb = nil; qlock(&ic->ackq); if(ic->unacked) nb = copyblock(ic->unacked, blocklen(ic->unacked)); qunlock(&ic->ackq); if(nb == nil) return; h = (Ilhdr*)nb->rp; h->vihl = IP_VER4; h->iltype = Ildataquery; hnputl(h->ilack, ic->recvd); h->ilspec = ilnextqt(ic); h->ilsum[0] = 0; h->ilsum[1] = 0; hnputs(h->ilsum, ptclcsum(nb, IL_IPSIZE, nhgets(h->illen))); c = ic->conv; id = nhgetl(h->ilid); netlog(c->p->f, Logil, "il: rexmit %d %ud: %d %d: %i %d/%d\n", id, ic->recvd, ic->rexmit, ic->timeout, c->raddr, c->lport, c->rport); ilbackoff(ic); ipoput4(c->p->f, nb, 0, c->ttl, c->tos, c); /* statistics */ ic->rxtot++; priv = c->p->priv; priv->rexmit++;}/* DEBUG */voidilprocess(Conv *s, Ilhdr *h, Block *bp){ Ilcb *ic; ic = (Ilcb*)s->ptcl; USED(ic); netlog(s->p->f, Logilmsg, "%11s rcv %d/%d snt %d/%d pkt(%s id %d ack %d %d->%d) ", ilstates[ic->state], ic->rstart, ic->recvd, ic->start, ic->next, iltype[h->iltype], nhgetl(h->ilid), nhgetl(h->ilack), nhgets(h->ilsrc), nhgets(h->ildst)); _ilprocess(s, h, bp); netlog(s->p->f, Logilmsg, "%11s rcv %d snt %d\n", ilstates[ic->state], ic->recvd, ic->next);}voidilhangup(Conv *s, char *msg){ Ilcb *ic; int callout; netlog(s->p->f, Logil, "il: hangup! %I %d/%d: %s\n", s->raddr, s->lport, s->rport, msg?msg:"no reason"); ic = (Ilcb*)s->ptcl; callout = ic->state == Ilsyncer; illocalclose(s); qhangup(s->rq, msg); qhangup(s->wq, msg); if(callout) Fsconnected(s, msg);}voidilpullup(Conv *s){ Ilcb *ic; Ilhdr *oh; Block *bp; ulong oid, dlen; Ilpriv *ipriv; ic = (Ilcb*)s->ptcl; if(ic->state != Ilestablished) return; qlock(&ic->outo); while(ic->outoforder) { bp = ic->outoforder; oh = (Ilhdr*)bp->rp; oid = nhgetl(oh->ilid); if(oid <= ic->recvd) { ic->outoforder = bp->list; freeblist(bp); continue; } if(oid != ic->recvd+1){ ipriv = s->p->priv; ipriv->stats[OutOfOrder]++; break; } ic->recvd = oid; ic->outoforder = bp->list; bp->list = nil; dlen = nhgets(oh->illen)-IL_HDRSIZE; bp = trimblock(bp, IL_IPSIZE+IL_HDRSIZE, dlen); /* * Upper levels don't know about multiple-block * messages so copy all into one (yick). */ bp = concatblock(bp); if(bp == 0) panic("ilpullup"); bp = packblock(bp); if(bp == 0) panic("ilpullup2"); qpass(s->rq, bp); } qunlock(&ic->outo);}voidiloutoforder(Conv *s, Ilhdr *h, Block *bp){ Ilcb *ic; uchar *lid; Block *f, **l; ulong id, newid; Ilpriv *ipriv; ipriv = s->p->priv; ic = (Ilcb*)s->ptcl; bp->list = nil; id = nhgetl(h->ilid); /* Window checks */ if(id <= ic->recvd || id > ic->recvd+ic->window) { netlog(s->p->f, Logil, "il: message outside window %ud <%ud-%ud>: %i %d/%d\n", id, ic->recvd, ic->recvd+ic->window, s->raddr, s->lport, s->rport); freeblist(bp); return; } /* Packet is acceptable so sort onto receive queue for pullup */ qlock(&ic->outo); if(ic->outoforder == nil) ic->outoforder = bp; else { l = &ic->outoforder; for(f = *l; f; f = f->list) { lid = ((Ilhdr*)(f->rp))->ilid; newid = nhgetl(lid); if(id <= newid) { if(id == newid) { ipriv->stats[DupMsg]++; ipriv->stats[DupBytes] += blocklen(bp); qunlock(&ic->outo); freeblist(bp); return; } bp->list = f; *l = bp; qunlock(&ic->outo); return; } l = &f->list; } *l = bp; } qunlock(&ic->outo);}voidilsendctl(Conv *ipc, Ilhdr *inih, int type, ulong id, ulong ack, int ilspec){ Ilhdr *ih; Ilcb *ic; Block *bp; int ttl, tos; bp = allocb(IL_IPSIZE+IL_HDRSIZE); bp->wp += IL_IPSIZE+IL_HDRSIZE; ih = (Ilhdr *)(bp->rp); ih->vihl = IP_VER4; /* Ip fields */ ih->proto = IP_ILPROTO; hnputs(ih->illen, IL_HDRSIZE); ih->frag[0] = 0; ih->frag[1] = 0; if(inih) { hnputl(ih->dst, nhgetl(inih->src)); hnputl(ih->src, nhgetl(inih->dst)); hnputs(ih->ilsrc, nhgets(inih->ildst)); hnputs(ih->ildst, nhgets(inih->ilsrc)); hnputl(ih->ilid, nhgetl(inih->ilack)); hnputl(ih->ilack, nhgetl(inih->ilid)); ttl = MAXTTL; tos = DFLTTOS; } else { v6tov4(ih->dst, ipc->raddr); v6tov4(ih->src, ipc->laddr); hnputs(ih->ilsrc, ipc->lport); hnputs(ih->ildst, ipc->rport); hnputl(ih->ilid, id); hnputl(ih->ilack, ack); ic = (Ilcb*)ipc->ptcl; ic->acksent = ack; ic->acktime = NOW; ttl = ipc->ttl; tos = ipc->tos; } ih->iltype = type; ih->ilspec = ilspec; ih->ilsum[0] = 0; ih->ilsum[1] = 0; if(ilcksum) hnputs(ih->ilsum, ptclcsum(bp, IL_IPSIZE, IL_HDRSIZE));if(ipc==nil) panic("ipc is nil caller is %.8lux", getcallerpc(&ipc));if(ipc->p==nil) panic("ipc->p is nil"); netlog(ipc->p->f, Logilmsg, "ctl(%s id %d ack %d %d->%d)\n", iltype[ih->iltype], nhgetl(ih->ilid), nhgetl(ih->ilack), nhgets(ih->ilsrc), nhgets(ih->ildst)); ipoput4(ipc->p->f, bp, 0, ttl, tos, ipc);}voidilreject(Fs *f, Ilhdr *inih){ Ilhdr *ih; Block *bp; bp = allocb(IL_IPSIZE+IL_HDRSIZE); bp->wp += IL_IPSIZE+IL_HDRSIZE; ih = (Ilhdr *)(bp->rp); ih->vihl = IP_VER4; /* Ip fields */ ih->proto = IP_ILPROTO; hnputs(ih->illen, IL_HDRSIZE); ih->frag[0] = 0; ih->frag[1] = 0; hnputl(ih->dst, nhgetl(inih->src)); hnputl(ih->src, nhgetl(inih->dst)); hnputs(ih->ilsrc, nhgets(inih->ildst)); hnputs(ih->ildst, nhgets(inih->ilsrc)); hnputl(ih->ilid, nhgetl(inih->ilack)); hnputl(ih->ilack, nhgetl(inih->ilid)); ih->iltype = Ilclose; ih->ilspec = 0; ih->ilsum[0] = 0; ih->ilsum[1] = 0; if(ilcksum) hnputs(ih->ilsum, ptclcsum(bp, IL_IPSIZE, IL_HDRSIZE)); ipoput4(f, bp, 0, MAXTTL, DFLTTOS, nil);}voidilsettimeout(Ilcb *ic){ ulong pt; pt = (ic->delay>>LogAGain) + ic->unackedbytes/(ic->rate>>LogAGain) + (ic->mdev>>(LogDGain-1)) + AckDelay; if(pt > MaxTimeout) pt = MaxTimeout; ic->timeout = NOW + pt;}voidilbackoff(Ilcb *ic){ ulong pt; int i; pt = (ic->delay>>LogAGain) + ic->unackedbytes/(ic->rate>>LogAGain) + (ic->mdev>>(LogDGain-1)) + AckDelay; for(i = 0; i < ic->rexmit; i++) pt = pt + (pt>>1); if(pt > MaxTimeout) pt = MaxTimeout; ic->timeout = NOW + pt; if(ic->fasttimeout) ic->timeout = NOW+Iltickms; ic->rexmit++;}// complain if two numbers not within an hour of each other#define Tfuture (1000*60*60)intlater(ulong t1, ulong t2, char *x){ int dt; dt = t1 - t2; if(dt > 0) { if(x != nil && dt > Tfuture) print("%s: way future %d\n", x, dt); return 1; } if(dt < -Tfuture) { if(x != nil) print("%s: way past %d\n", x, -dt); return 1; } return 0;}voidilackproc(void *x){ Ilcb *ic; Conv **s, *p; Proto *il; il = x;loop: tsleep(&up->sleep, return0, 0, Iltickms); for(s = il->conv; s && *s; s++) { p = *s; ic = (Ilcb*)p->ptcl; switch(ic->state) { case Ilclosed: case Illistening: break; case Ilclosing: if(later(NOW, ic->timeout, "timeout0")) { if(ic->rexmit > MaxRexmit){ ilhangup(p, nil); break; } ilsendctl(p, nil, Ilclose, ic->next, ic->recvd, 0); ilbackoff(ic); } break; case Ilsyncee: case Ilsyncer: if(later(NOW, ic->timeout, "timeout1")) { if(ic->rexmit > MaxRexmit){ ilhangup(p, etime); break; } ilsendctl(p, nil, Ilsync, ic->start, ic->recvd, 0); ilbackoff(ic); } break; case Ilestablished: if(ic->recvd != ic->acksent) if(later(NOW, ic->acktime, "acktime")) ilsendctl(p, nil, Ilack, ic->next, ic->recvd, 0); if(later(NOW, ic->querytime, "querytime")){ if(later(NOW, ic->lastrecv+DeathTime, "deathtime")){ netlog(il->f, Logil, "il: hangup: deathtime\n"); ilhangup(p, etime); break; } ilsendctl(p, nil, Ilquery, ic->next, ic->recvd, ilnextqt(ic)); ic->querytime = NOW + QueryTime; } if(ic->unacked != nil) if(later(NOW, ic->timeout, "timeout2")) { if(ic->rexmit > MaxRexmit){ netlog(il->f, Logil, "il: hangup: too many rexmits\n"); ilhangup(p, etime); break; } ilsendctl(p, nil, Ilquery, ic->next, ic->recvd, ilnextqt(ic)); ic->rxquery++; ilbackoff(ic); } break; } } goto loop;}voidilcbinit(Ilcb *ic){ ic->start = nrand(0x1000000); ic->next = ic->start+1; ic->recvd = 0; ic->window = Defaultwin; ic->unackedbytes = 0; ic->unacked = nil; ic->outoforder = nil; ic->rexmit = 0; ic->rxtot = 0; ic->rxquery = 0; ic->qtx = 1; ic->fasttimeout = 0; /* timers */ ic->delay = DefRtt<<LogAGain; ic->mdev = DefRtt<<LogDGain; ic->rate = DefByteRate<<LogAGain; ic->querytime = NOW + QueryTime; ic->lastrecv = NOW; /* or we'll timeout right away */ ilsettimeout(ic);}char*ilstart(Conv *c, int type, int fasttimeout){ Ilcb *ic; Ilpriv *ipriv; char kpname[KNAMELEN]; ipriv = c->p->priv; if(ipriv->ackprocstarted == 0){ qlock(&ipriv->apl); if(ipriv->ackprocstarted == 0){ sprint(kpname, "#I%dilack", c->p->f->dev); kproc(kpname, ilackproc, c->p); ipriv->ackprocstarted = 1; } qunlock(&ipriv->apl); } ic = (Ilcb*)c->ptcl; ic->conv = c; if(ic->state != Ilclosed) return nil; ilcbinit(ic); if(fasttimeout){ /* timeout if we can't connect quickly */ ic->fasttimeout = 1; ic->timeout = NOW+Iltickms; ic->rexmit = MaxRexmit - 4; }; switch(type) { default: netlog(c->p->f, Logil, "il: start: type %d\n", type); break; case IL_LISTEN: ic->state = Illistening; iphtadd(&ipriv->ht, c); break; case IL_CONNECT: ic->state = Ilsyncer; iphtadd(&ipriv->ht, c); ilsendctl(c, nil, Ilsync, ic->start, ic->recvd, 0); break; } return nil;}voidilfreeq(Ilcb *ic){ Block *bp, *next; qlock(&ic->ackq); for(bp = ic->unacked; bp; bp = next) { next = bp->list; freeblist(bp); } ic->unacked = nil; qunlock(&ic->ackq); qlock(&ic->outo); for(bp = ic->outoforder; bp; bp = next) { next = bp->list; freeblist(bp); } ic->outoforder = nil; qunlock(&ic->outo);}voidiladvise(Proto *il, Block *bp, char *msg){ Ilhdr *h; Ilcb *ic; uchar source[IPaddrlen], dest[IPaddrlen]; ushort psource; Conv *s, **p; h = (Ilhdr*)(bp->rp); v4tov6(dest, h->dst); v4tov6(source, h->src); psource = nhgets(h->ilsrc); /* Look for a connection, unfortunately the destination port is missing */ qlock(il); for(p = il->conv; *p; p++) { s = *p; if(s->lport == psource) if(ipcmp(s->laddr, source) == 0) if(ipcmp(s->raddr, dest) == 0){ qunlock(il); ic = (Ilcb*)s->ptcl; switch(ic->state){ case Ilsyncer: ilhangup(s, msg); break; } freeblist(bp); return; } } qunlock(il); freeblist(bp);}intilnextqt(Ilcb *ic){ int x; qlock(&ic->ackq); x = ic->qtx; if(++x > Nqt) x = 1; ic->qtx = x; ic->qt[x] = ic->next-1; /* highest xmitted packet */ ic->qt[0] = ic->qt[x]; /* compatibility with old implementations */ qunlock(&ic->ackq); return x;}/* calculate scale constants that converts fast ticks to ms (more or less) */static voidinittimescale(void){ uvlong hz; fastticks(&hz); if(hz > 1000){ scalediv = hz/1000; scalemul = 1; } else { scalediv = 1; scalemul = 1000/hz; }}voidilinit(Fs *f){ Proto *il; inittimescale(); il = smalloc(sizeof(Proto)); il->priv = smalloc(sizeof(Ilpriv)); il->name = "il"; il->connect = ilconnect; il->announce = ilannounce; il->state = ilstate; il->create = ilcreate; il->close = ilclose; il->rcv = iliput; il->ctl = nil; il->advise = iladvise; il->stats = ilxstats; il->inuse = ilinuse; il->gc = nil; il->ipproto = IP_ILPROTO; il->nc = scalednconv(); il->ptclsize = sizeof(Ilcb); Fsproto(f, il);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -