📄 il.c
字号:
break; } mbfree(mb); break; }}staticvoidilsendctl(Chan *cp, Ilpkt *inih, int type, ulong id, ulong ack, int ilspec){ Ifc *ifc; Ilpkt *ih; Msgbuf *mb; Ilp *ilp; ilp = cp->pdata; mb = mballoc(Ensize+Ipsize+Ilsize, cp, Mbil3); ih = (Ilpkt*)mb->data; ih->proto = Ilproto; ifc = cp->ifc; memmove(ih->src, ifc->ipa, Pasize); hnputs(ih->illen, Ilsize); if(inih) { memmove(ih->dst, inih->src, Pasize); memmove(ih->ilsrc, inih->ildst, sizeof(ih->ilsrc)); memmove(ih->ildst, inih->ilsrc, sizeof(ih->ildst)); memmove(ih->ilid, inih->ilack, sizeof(ih->ilid)); memmove(ih->ilack, inih->ilid, sizeof(ih->ilack)); } else { memmove(ih->dst, ilp->iphis, Pasize); hnputs(ih->ilsrc, ilp->dstp); hnputs(ih->ildst, ilp->srcp); hnputl(ih->ilid, id); hnputl(ih->ilack, ack); ilp->acksent = ack; ilp->acktime = msec; } ih->iltype = type; ih->ilspec = ilspec; ih->ilsum[0] = 0; ih->ilsum[1] = 0; hnputs(ih->ilsum, ptclcsum((uchar*)mb->data+(Ensize+Ipsize), Ilsize)); ipsend(mb);}staticvoidilhangup(Chan *cp, char *msg, int dolock){ Ilp *ilp; int s; ilp = cp->pdata; s = ilp->state; ilp->state = Ilclosed; if(s == Ilsyncer) wakeup(&ilp->syn); if(msg != nil) print("hangup! %s %d/%I.%d\n", msg, ilp->srcp, ilp->iphis, ilp->dstp); ilfreeq(cp); fileinit(cp); cp->whotime = 0; strcpy(cp->whoname, "<none>"); if(dolock) lock(&il); ilp->alloc = 0; ilp->srcp = 0; ilp->dstp = 0; memset(ilp->iphis, 0, sizeof(ilp->iphis)); if(dolock) unlock(&il);}staticvoidilpullup(Chan *cp){ Ilpkt *oh; Msgbuf *mb; Ilp *ilp; ulong oid, dlen; ilp = cp->pdata; lock(ilp); while(ilp->outoforder) { mb = ilp->outoforder; oh = (Ilpkt*)mb->data; oid = nhgetl(oh->ilid); if(oid <= ilp->recvd) { ilp->outoforder = mb->next; mbfree(mb); continue; } if(oid != ilp->recvd+1) break; ilp->recvd = oid; ilp->outoforder = mb->next; /* * strip off the header */ dlen = nhgets(oh->illen)-Ilsize; mb->data += Ensize+Ipsize+Ilsize; mb->count = dlen; send(cp->send, mb); } unlock(ilp);}staticvoidiloutoforder(Chan *cp, Ilpkt *h, Msgbuf *mb){ Msgbuf **l, *f; Ilp *ilp; ulong id, ilid; uchar *lid; ilp = cp->pdata; id = nhgetl(h->ilid); /* * Window checks */ if(id <= ilp->recvd || id > ilp->recvd+ilp->window) { mbfree(mb); return; } /* * Packet is acceptable so * sort onto receive queue for pullup */ mb->next = 0; lock(ilp); if(ilp->outoforder == 0) { ilp->outoforder = mb; } else { l = &ilp->outoforder; for(f = *l; f; f = f->next) { lid = ((Ilpkt*)(f->data))->ilid; ilid = nhgetl(lid); if(id <= ilid) { if(id == ilid) { mbfree(mb); unlock(ilp); return; } mb->next = f; break; } l = &f->next; } *l = mb; } unlock(ilp);}staticvoidilrttcalc(Ilp *ilp, Msgbuf *mb){ int rtt, tt, pt, delay, rate; rtt = msec - ilp->rttstart + TK2MS(1) - 1; delay = ilp->delay; rate = ilp->rate; /* Guard against zero wrap */ if(rtt > 120000 || rtt < 0) return; /* this block had to be transmitted after the one acked so count its size */ ilp->rttlen += mb->count+Ipsize+Ilsize; if(ilp->rttlen < 256){ /* guess fixed delay as rtt of small packets */ delay += rtt - (delay>>LogAGain); if(delay < AGain) delay = AGain; ilp->delay = delay; } else { /* if packet took longer than avg rtt delay, recalc rate */ tt = rtt - (delay>>LogAGain); if(tt > 0){ rate += ilp->rttlen/tt - (rate>>LogAGain); if(rate < AGain) rate = AGain; ilp->rate = rate; } } /* mdev */ pt = ilp->rttlen/(rate>>LogAGain) + (delay>>LogAGain); ilp->mdev += abs(rtt-pt) - (ilp->mdev>>LogDGain); if(rtt > ilp->maxrtt) ilp->maxrtt = rtt;}staticvoidilackto(Chan *cp, ulong ackto, Msgbuf *mb){ Ilpkt *h; Ilp *ilp; ulong id; ilp = cp->pdata; if(ilp->rttack == ackto) ilrttcalc(ilp, mb); /* Cancel if we lost the packet we were interested in */ if(ilp->rttack <= ackto) ilp->rttack = 0; lock(ilp); while(ilp->unacked) { h = (Ilpkt*)ilp->unacked->data; id = nhgetl(h->ilid); if(ackto < id) break; mb = ilp->unacked; ilp->unacked = mb->next; mb->next = 0; ilp->unackedbytes -= mb->count; mbfree(mb); ilp->rexmit = 0; ilsettimeout(ilp); } unlock(ilp);}staticvoidilrexmit(Ilp *ilp){ Msgbuf *omb, *mb; Ilpkt *h; lock(ilp); omb = ilp->unacked; if(omb == 0) { unlock(ilp); return; }/* botch -- a reference count will save this copy */ mb = mballoc(omb->count, omb->chan, Mbil4); memmove(mb->data, omb->data, omb->count); unlock(ilp); h = (Ilpkt*)mb->data; h->iltype = Ildataquery; hnputl(h->ilack, ilp->recvd); h->ilspec = ilnextqt(ilp); h->ilsum[0] = 0; h->ilsum[1] = 0; hnputs(h->ilsum, ptclcsum((uchar*)mb->data+(Ensize+Ipsize), nhgets(h->illen))); ilbackoff(ilp); ipsend(mb);}staticvoidilfreeq(Chan *cp){ Ilp *ilp; Msgbuf *mb, *next; ilp = cp->pdata; lock(ilp); for(mb = ilp->unacked; mb; mb = next) { next = mb->next; mbfree(mb); } ilp->unacked = 0; for(mb = ilp->outoforder; mb; mb = next) { next = mb->next; mbfree(mb); } ilp->outoforder = 0; unlock(ilp);}staticvoidilsettimeout(Ilp *ilp){ Timet pt; pt = (ilp->delay>>LogAGain) + ilp->unackedbytes/(ilp->rate>>LogAGain) + (ilp->mdev>>(LogDGain-1)) + AckDelay; if(pt > MaxTimeout) pt = MaxTimeout; ilp->timeout = msec + pt;}staticvoidilbackoff(Ilp *ilp){ Timet pt; int i; pt = (ilp->delay>>LogAGain) + ilp->unackedbytes/(ilp->rate>>LogAGain) + (ilp->mdev>>(LogDGain-1)) + AckDelay; for(i = 0; i < ilp->rexmit; i++) pt = pt + (pt>>1); if(pt > MaxTimeout) pt = MaxTimeout; ilp->timeout = msec + pt; ilp->rexmit++;}/* * il timer * every 100ms */static Rendez ilt;staticvoidcallil(Alarm *a, void *){ cancel(a); wakeup(&ilt);}// complain if two numbers not within an hour of each other#define Tfuture (1000*60*60)intlater(Timet t1, Timet t2, char *x){ Timet dt; dt = t1 - t2; if(dt > 0) { if(dt > Tfuture) print("%s: way future %ld\n", x, dt); return 1; } if(dt < -Tfuture) { print("%s: way past %ld\n", x, -dt); return 1; } return 0;}staticvoidiltimer(void){ Chan *cp; Ilp *ilp;loop: lock(&il); for(cp = il.chan; cp; cp = ilp->chan) { ilp = cp->pdata; if(ilp->alloc == 0) continue; switch(ilp->state) { case Ilclosed: case Illistening: break; case Ilclosing: if(later(msec, ilp->timeout, "timeout")){ if(ilp->rexmit > MaxRexmit){ ilp->state = Ilclosed; ilhangup(cp, "connection timed out-0", 0); break; } ilsendctl(cp, 0, Ilclose, ilp->next, ilp->recvd, 0); ilbackoff(ilp); } break; case Ilsyncee: case Ilsyncer: if(later(msec, ilp->timeout, "timeout")){ if(ilp->rexmit > MaxRexmit){ ilp->state = Ilclosed; ilhangup(cp, "connection timed out-1", 0); break; } ilsendctl(cp, 0, Ilsync, ilp->start, ilp->recvd, 0); ilbackoff(ilp); } break; case Ilestablished: if(ilp->recvd != ilp->acksent) if(later(msec, ilp->acktime, "acktime")) ilsendctl(cp, 0, Ilack, ilp->next, ilp->recvd, 0); if(later(msec, ilp->querytime, "querytime")){ if(later(msec, ilp->lastrecv+DeathTime, "deathtime")){ ilhangup(cp, "connection timed out-2", 0); break; } ilsendctl(cp, 0, Ilquery, ilp->next, ilp->recvd, ilnextqt(ilp)); ilp->querytime = msec + QueryTime; } if(ilp->unacked != nil) if(later(msec, ilp->timeout, "timeout")) { if(ilp->rexmit > MaxRexmit) { ilp->state = Ilclosed; ilhangup(cp, "connection timed out-3", 0); break; } ilsendctl(cp, 0, Ilquery, ilp->next, ilp->recvd, ilnextqt(ilp)); ilbackoff(ilp); } break; } } unlock(&il); alarm(Iltickms, callil, 0); sleep(&ilt, no, 0); goto loop;}staticintnotsyncer(void *ic){ return ((Ilp*)ic)->state != Ilsyncer;}staticvoidcallildial(Alarm *a, void*){ cancel(a); wakeup(&ild);}staticintilnextqt(Ilp *ilp){ int x; lock(ilp); x = ilp->qtx; if(++x > Nqt) x = 1; ilp->qtx = x; ilp->qt[x] = ilp->next-1; /* highest xmitted packet */ ilp->qt[0] = ilp->qt[x]; /* compatibility with old implementations */ unlock(ilp); return x;}#define HOWMANY(x, y) (((x)+((y)-1))/(y))#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y))static voidilgoaway(Msgbuf *inmb, Ifc *ifc){ Chan *cp; int size; Ilpkt *ih, *inih; Msgbuf *mb; Ilp *ilp; uchar *p; inih = (Ilpkt*)inmb->data; /* allocate a temporary message, channel, and Ilp structure */ size = ROUNDUP(Ensize+Ipsize+Ilsize, BY2WD)+sizeof(Chan)+sizeof(Ilp); mb = mballoc(size, nil, Mbil3); p = mb->data; p += ROUNDUP(Ensize+Ipsize+Ilsize, BY2WD); cp = (Chan*)p; p += sizeof(Chan); ilp = (Ilp*)p; /* link them together */ cp->ifc = ifc; mb->chan = cp; cp->pdata = ilp; /* figure out next hop */ memmove(ilp->ipgate, inih->src, Pasize); if((nhgetl(ifc->ipa)&ifc->mask) != (nhgetl(inih->src)&ifc->mask)) iproute(ilp->ipgate, inih->src, ifc->netgate); /* create a close message */ ih = (Ilpkt*)mb->data; ih->proto = Ilproto; hnputs(ih->illen, Ilsize); memmove(ih->src, ifc->ipa, Pasize); memmove(ih->dst, inih->src, Pasize); memmove(ih->ilsrc, inih->ildst, sizeof(ih->ilsrc)); memmove(ih->ildst, inih->ilsrc, sizeof(ih->ildst)); memmove(ih->ilid, inih->ilack, sizeof(ih->ilid)); memmove(ih->ilack, inih->ilid, sizeof(ih->ilack)); ih->iltype = Ilclose; ih->ilspec = 0; ih->ilsum[0] = 0; ih->ilsum[1] = 0; hnputs(ih->ilsum, ptclcsum((uchar*)mb->data+(Ensize+Ipsize), Ilsize)); ipsend(mb);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -