2 #include "../port/lib.h"
6 #include "../port/error.h"
10 enum /* Connection state */
18 Ilopening, /* only for file server */
29 "Opening", /* only for file server */
32 enum /* Packet types */
57 Iltickms = 50, /* time base */
58 AckDelay = 2*Iltickms, /* max time twixt message rcvd & ack sent */
59 MaxTimeout = 30*Seconds, /* max time between rexmit */
60 QueryTime = 10*Seconds, /* time between subsequent queries */
61 DeathTime = 30*QueryTime,
63 MaxRexmit = 16, /* max retransmissions before hangup */
71 DefByteRate = 100, /* assume a megabit link */
72 DefRtt = 50, /* cross country on a great day */
82 typedef struct Ilcb Ilcb;
83 struct Ilcb /* Control block */
85 int state; /* Connection state */
87 QLock ackq; /* Unacknowledged queue */
91 QLock outo; /* Out of order packet queue */
93 ulong next; /* Id of next to send */
94 ulong recvd; /* Last packet received */
95 ulong acksent; /* Last packet acked */
96 ulong start; /* Local start id */
97 ulong rstart; /* Remote start id */
98 int window; /* Maximum receive window */
99 int rxquery; /* number of queries on this connection */
100 int rxtot; /* number of retransmits on this connection */
101 int rexmit; /* number of retransmits of *unacked */
102 ulong qt[Nqt+1]; /* state table for query messages */
103 int qtx; /* ... index into qt */
105 /* if set, fasttimeout causes a connection request to terminate after 4*Iltickms */
109 ulong lastxmit; /* time of last xmit */
110 ulong lastrecv; /* time of last recv */
111 ulong timeout; /* retransmission time for *unacked */
112 ulong acktime; /* time to send next ack */
113 ulong querytime; /* time to send next query */
115 /* adaptive measurements */
116 int delay; /* Average of the fixed rtt delay */
117 int rate; /* Average uchar rate */
118 int mdev; /* Mean deviation of rtt */
119 int maxrtt; /* largest rtt seen */
120 ulong rttack; /* The ack we are waiting for */
121 int rttlen; /* Length of rttack packet */
122 uvlong rttstart; /* Time we issued rttack packet */
134 typedef struct Ilhdr Ilhdr;
137 uchar vihl; /* Version and header length */
138 uchar tos; /* Type of service */
139 uchar length[2]; /* packet length */
140 uchar id[2]; /* Identification */
141 uchar frag[2]; /* Fragment information */
142 uchar ttl; /* Time to live */
143 uchar proto; /* Protocol */
144 uchar cksum[2]; /* Header checksum */
145 uchar src[4]; /* Ip source */
146 uchar dst[4]; /* Ip destination */
147 uchar ilsum[2]; /* Checksum including header */
148 uchar illen[2]; /* Packet length */
149 uchar iltype; /* Packet type */
150 uchar ilspec; /* Special */
151 uchar ilsrc[2]; /* Src port */
152 uchar ildst[2]; /* Dst port */
153 uchar ilid[4]; /* Sequence id */
154 uchar ilack[4]; /* Acked sequence */
161 CsumErrs, /* checksum errors */
162 HlenErrs, /* header length error */
163 LenErrs, /* short packet */
164 OutOfOrder, /* out of order */
165 Retrans, /* retransmissions */
173 static char *statnames[] =
177 [CsumErrs] "CsumErrs",
178 [HlenErrs] "HlenErr",
180 [OutOfOrder] "OutOfOrder",
183 [DupBytes] "DupBytes",
184 [DroppedMsgs] "DroppedMsgs",
187 typedef struct Ilpriv Ilpriv;
192 uvlong stats[Nstats];
194 ulong csumerr; /* checksum errors */
195 ulong hlenerr; /* header length error */
196 ulong lenerr; /* short packet */
197 ulong order; /* out of order */
198 ulong rexmit; /* retransmissions */
202 /* keeping track of the ack kproc */
207 /* state for query/dataquery messages */
210 void ilrcvmsg(Conv*, Block*);
211 int ilsendctl(Conv*, Ilhdr*, int, ulong, ulong, int);
212 void ilackq(Ilcb*, Block*);
213 void ilprocess(Conv*, Ilhdr*, Block*);
214 void ilpullup(Conv*);
215 void ilhangup(Conv*, char*);
217 void ilrexmit(Ilcb*);
218 void ilbackoff(Ilcb*);
219 void ilsettimeout(Ilcb*);
220 char* ilstart(Conv*, int, int);
221 void ilackproc(void*);
222 void iloutoforder(Conv*, Ilhdr*, Block*);
223 void iliput(Proto*, Ipifc*, Block*);
224 void iladvise(Proto*, Block*, char*);
226 void ilcbinit(Ilcb*);
227 int later(ulong, ulong, char*);
228 void ilreject(Fs*, Ilhdr*);
229 void illocalclose(Conv *c);
231 static int initseq = 25001;
232 static ulong scalediv, scalemul;
233 static char *etime = "connection timed out";
236 ilconnect(Conv *c, char **argv, int argc)
241 /* huge hack to quickly try an il connection */
244 p = strstr(argv[1], "!fasttimeout");
251 e = Fsstdconnect(c, argv, argc);
254 if(c->ipversion != V4)
255 return "only IP version 4 supported";
257 return ilstart(c, IL_CONNECT, fast);
261 ilstate(Conv *c, char *state, int n)
265 ic = (Ilcb*)(c->ptcl);
266 return snprint(state, n, "%s qin %d qout %d del %5.5d Br %5.5d md %5.5d una %5.5lud rex %5.5d rxq %5.5d max %5.5d\n",
268 c->rq ? qlen(c->rq) : 0,
269 c->wq ? qlen(c->wq) : 0,
270 ic->delay>>LogAGain, ic->rate>>LogAGain, ic->mdev>>LogDGain,
271 ic->unackedbytes, ic->rxtot, ic->rxquery, ic->maxrtt);
279 ic = (Ilcb*)(c->ptcl);
280 return ic->state != Ilclosed;
284 /* called with c locked */
286 ilannounce(Conv *c, char **argv, int argc)
290 e = Fsstdannounce(c, argv, argc);
293 e = ilstart(c, IL_LISTEN, 0);
302 illocalclose(Conv *c)
309 ic->state = Ilclosed;
310 iphtrem(&ipriv->ht, c);
311 ipmove(c->laddr, IPnoaddr);
333 ic->state = Ilclosing;
335 ilsendctl(c, nil, Ilclose, ic->next, ic->recvd, 0);
345 ilkick(void *x, Block *bp)
373 /* Make space to fit il & ip */
374 bp = padblock(bp, IL_IPSIZE+IL_HDRSIZE);
375 ih = (Ilhdr *)(bp->rp);
381 v6tov4(ih->dst, c->raddr);
382 v6tov4(ih->src, c->laddr);
383 ih->proto = IP_ILPROTO;
386 hnputs(ih->illen, dlen+IL_HDRSIZE);
387 hnputs(ih->ilsrc, c->lport);
388 hnputs(ih->ildst, c->rport);
392 hnputl(ih->ilid, id);
394 hnputl(ih->ilack, ack);
396 ic->acktime = NOW + AckDelay;
402 /* Checksum of ilheader plus data (not ip & no pseudo header) */
404 hnputs(ih->ilsum, ptclcsum(bp, IL_IPSIZE, dlen+IL_HDRSIZE));
409 /* Start the round trip timer for this packet if the timer is free */
410 if(ic->rttack == 0) {
412 ic->rttstart = fastticks(nil);
413 ic->rttlen = dlen + IL_IPSIZE + IL_HDRSIZE;
416 if(later(NOW, ic->timeout, nil))
418 ipoput4(f, bp, 0, c->ttl, c->tos, c);
419 priv->stats[OutMsgs]++;
425 c->rq = qopen(Maxrq, 0, 0, c);
426 c->wq = qbypass(ilkick, c);
430 ilxstats(Proto *il, char *buf, int len)
439 for(i = 0; i < Nstats; i++)
440 p = seprint(p, e, "%s: %llud\n", statnames[i], priv->stats[i]);
445 ilackq(Ilcb *ic, Block *bp)
452 /* Enqueue a copy on the unacked queue in case this one gets lost */
453 np = copyblock(bp, n);
455 ic->unackedtail->list = np;
458 ic->unackedtail = np;
460 ic->unackedbytes += n;
465 ilrttcalc(Ilcb *ic, Block *bp)
467 int rtt, tt, pt, delay, rate;
469 rtt = fastticks(nil) - ic->rttstart;
470 rtt = (rtt*scalemul)/scalediv;
474 /* Guard against zero wrap */
475 if(rtt > 120000 || rtt < 0)
478 /* this block had to be transmitted after the one acked so count its size */
479 ic->rttlen += blocklen(bp) + IL_IPSIZE + IL_HDRSIZE;
481 if(ic->rttlen < 256){
482 /* guess fixed delay as rtt of small packets */
483 delay += rtt - (delay>>LogAGain);
488 /* if packet took longer than avg rtt delay, recalc rate */
489 tt = rtt - (delay>>LogAGain);
491 rate += ic->rttlen/tt - (rate>>LogAGain);
499 pt = ic->rttlen/(rate>>LogAGain) + (delay>>LogAGain);
500 ic->mdev += abs(rtt-pt) - (ic->mdev>>LogDGain);
507 ilackto(Ilcb *ic, ulong ackto, Block *bp)
512 if(ic->rttack == ackto)
515 /* Cancel if we've passed the packet we were interested in */
516 if(ic->rttack <= ackto)
521 h = (Ilhdr *)ic->unacked->rp;
522 id = nhgetl(h->ilid);
527 ic->unacked = bp->list;
529 ic->unackedbytes -= blocklen(bp);
538 iliput(Proto *il, Ipifc*, Block *bp)
543 uchar raddr[IPaddrlen];
544 uchar laddr[IPaddrlen];
552 ih = (Ilhdr *)bp->rp;
554 if(plen > 0 && (ih->vihl&0xF0)!=IP_VER4)
555 goto raise; /* ignore non V4 packets */
557 if(plen < IL_IPSIZE+IL_HDRSIZE){
558 netlog(il->f, Logil, "il: hlenerr\n");
559 ipriv->stats[HlenErrs]++;
563 illen = nhgets(ih->illen);
564 if(illen+IL_IPSIZE > plen){
565 netlog(il->f, Logil, "il: lenerr\n");
566 ipriv->stats[LenErrs]++;
570 sp = nhgets(ih->ildst);
571 dp = nhgets(ih->ilsrc);
572 v4tov6(raddr, ih->src);
573 v4tov6(laddr, ih->dst);
575 if((csum = ptclcsum(bp, IL_IPSIZE, illen)) != 0) {
576 if(ih->iltype > Ilclose)
579 st = iltype[ih->iltype];
580 ipriv->stats[CsumErrs]++;
581 netlog(il->f, Logil, "il: cksum %ux %s, pkt(%ux id %ud ack %I/%d->%d)\n",
582 csum, st, nhgetl(ih->ilid), nhgetl(ih->ilack), raddr, sp, dp);
587 s = iphtlook(&ipriv->ht, raddr, dp, laddr, sp);
589 if(ih->iltype == Ilsync)
590 ilreject(il->f, ih); /* no listener */
596 if(ic->state == Illistening){
597 if(ih->iltype != Ilsync){
599 if(ih->iltype > Ilclose)
602 st = iltype[ih->iltype];
603 ilreject(il->f, ih); /* no channel and not sync */
604 netlog(il->f, Logil, "il: no channel, pkt(%s id %ud ack %ud %I/%ud->%ud)\n",
605 st, nhgetl(ih->ilid), nhgetl(ih->ilack), raddr, sp, dp);
609 new = Fsnewcall(s, raddr, dp, laddr, sp, V4);
612 netlog(il->f, Logil, "il: bad newcall %I/%ud->%ud\n", raddr, sp, dp);
613 ilsendctl(s, ih, Ilclose, 0, nhgetl(ih->ilid), 0);
621 ic->state = Ilsyncee;
623 ic->rstart = nhgetl(ih->ilid);
624 iphtadd(&ipriv->ht, s);
633 ilprocess(s, ih, bp);
642 _ilprocess(Conv *s, Ilhdr *h, Block *bp)
648 id = nhgetl(h->ilid);
649 ack = nhgetl(h->ilack);
654 ic->querytime = NOW + QueryTime;
656 priv->stats[InMsgs]++;
660 netlog(s->p->f, Logil, "il: unknown state %d\n", ic->state);
670 ilhangup(s, "connection rejected");
674 ilsendctl(s, nil, Ilack, ic->next, ic->recvd, 0);
675 ic->state = Ilestablished;
684 ilhangup(s, "connection rejected");
694 if(id != ic->rstart || ack != 0){
698 ilsendctl(s, nil, Ilsync, ic->start, ic->recvd, 0);
702 if(ack == ic->start) {
703 ic->state = Ilestablished;
710 if(ack == ic->start) {
711 ic->state = Ilestablished;
719 ilhangup(s, "remote close");
729 ilhangup(s, "remote close");
731 ilsendctl(s, nil, Ilack, ic->next, ic->rstart, 0);
736 * avoid consuming all the mount rpc buffers in the
737 * system. if the input queue is too long, drop this
740 if (s->rq && qlen(s->rq) >= Maxrq) {
741 priv->stats[DroppedMsgs]++;
746 ilackto(ic, ack, bp);
747 iloutoforder(s, h, bp);
751 ilackto(ic, ack, bp);
752 iloutoforder(s, h, bp);
754 ilsendctl(s, nil, Ilstate, ic->next, ic->recvd, h->ilspec);
757 ilackto(ic, ack, bp);
761 ilackto(ic, ack, bp);
762 ilsendctl(s, nil, Ilstate, ic->next, ic->recvd, h->ilspec);
766 if(ack >= ic->rttack)
768 ilackto(ic, ack, bp);
771 if(ic->qt[h->ilspec] > ack){
779 if(ack < ic->start || ack > ic->next)
782 ilsendctl(s, nil, Ilclose, ic->next, ic->recvd, 0);
783 ic->state = Ilclosing;
796 ilsendctl(s, nil, Ilclose, ic->next, ic->recvd, 0);
820 nb = copyblock(ic->unacked, blocklen(ic->unacked));
829 h->iltype = Ildataquery;
830 hnputl(h->ilack, ic->recvd);
831 h->ilspec = ilnextqt(ic);
834 hnputs(h->ilsum, ptclcsum(nb, IL_IPSIZE, nhgets(h->illen)));
837 id = nhgetl(h->ilid);
838 netlog(c->p->f, Logil, "il: rexmit %lud %lud: %d %lud: %I %d/%d\n", id, ic->recvd,
839 ic->rexmit, ic->timeout,
840 c->raddr, c->lport, c->rport);
844 ipoput4(c->p->f, nb, 0, c->ttl, c->tos, c);
854 ilprocess(Conv *s, Ilhdr *h, Block *bp)
861 netlog(s->p->f, Logilmsg, "%11s rcv %lud/%lud snt %lud/%lud pkt(%s id %d ack %ud %ud->%ud) ",
862 ilstates[ic->state], ic->rstart, ic->recvd, ic->start,
863 ic->next, iltype[h->iltype], nhgetl(h->ilid),
864 nhgetl(h->ilack), nhgets(h->ilsrc), nhgets(h->ildst));
866 _ilprocess(s, h, bp);
868 netlog(s->p->f, Logilmsg, "%11s rcv %lud snt %lud\n", ilstates[ic->state], ic->recvd, ic->next);
872 ilhangup(Conv *s, char *msg)
877 netlog(s->p->f, Logil, "il: hangup! %I %d/%d: %s\n", s->raddr,
878 s->lport, s->rport, msg?msg:"no reason");
881 callout = ic->state == Ilsyncer;
901 if(ic->state != Ilestablished)
905 while(ic->outoforder) {
908 oid = nhgetl(oh->ilid);
909 if(oid <= ic->recvd) {
910 ic->outoforder = bp->list;
914 if(oid != ic->recvd+1){
916 ipriv->stats[OutOfOrder]++;
921 ic->outoforder = bp->list;
924 dlen = nhgets(oh->illen)-IL_HDRSIZE;
925 bp = trimblock(bp, IL_IPSIZE+IL_HDRSIZE, dlen);
928 * Upper levels don't know about multiple-block
929 * messages so copy all into one (yick).
931 qpass(s->rq, packblock(concatblock(bp)));
937 iloutoforder(Conv *s, Ilhdr *h, Block *bp)
949 id = nhgetl(h->ilid);
951 if(id <= ic->recvd || id > ic->recvd+ic->window) {
952 netlog(s->p->f, Logil, "il: message outside window %lud <%lud-%lud>: %I %d/%d\n",
953 id, ic->recvd, ic->recvd+ic->window, s->raddr, s->lport, s->rport);
958 /* Packet is acceptable so sort onto receive queue for pullup */
960 if(ic->outoforder == nil)
964 for(f = *l; f; f = f->list) {
965 lid = ((Ilhdr*)(f->rp))->ilid;
969 ipriv->stats[DupMsg]++;
970 ipriv->stats[DupBytes] += blocklen(bp);
988 ilsendctl(Conv *ipc, Ilhdr *inih, int type, ulong id, ulong ack, int ilspec)
995 bp = allocb(IL_IPSIZE+IL_HDRSIZE);
996 bp->wp += IL_IPSIZE+IL_HDRSIZE;
998 ih = (Ilhdr *)(bp->rp);
1002 ih->proto = IP_ILPROTO;
1003 hnputs(ih->illen, IL_HDRSIZE);
1007 hnputl(ih->dst, nhgetl(inih->src));
1008 hnputl(ih->src, nhgetl(inih->dst));
1009 hnputs(ih->ilsrc, nhgets(inih->ildst));
1010 hnputs(ih->ildst, nhgets(inih->ilsrc));
1011 hnputl(ih->ilid, nhgetl(inih->ilack));
1012 hnputl(ih->ilack, nhgetl(inih->ilid));
1017 v6tov4(ih->dst, ipc->raddr);
1018 v6tov4(ih->src, ipc->laddr);
1019 hnputs(ih->ilsrc, ipc->lport);
1020 hnputs(ih->ildst, ipc->rport);
1021 hnputl(ih->ilid, id);
1022 hnputl(ih->ilack, ack);
1023 ic = (Ilcb*)ipc->ptcl;
1030 ih->ilspec = ilspec;
1035 hnputs(ih->ilsum, ptclcsum(bp, IL_IPSIZE, IL_HDRSIZE));
1038 panic("ipc is nil caller is %#p", getcallerpc(&ipc));
1040 panic("ipc->p is nil");
1042 netlog(ipc->p->f, Logilmsg, "ctl(%s id %d ack %d %d->%d)\n",
1043 iltype[ih->iltype], nhgetl(ih->ilid), nhgetl(ih->ilack),
1044 nhgets(ih->ilsrc), nhgets(ih->ildst));
1046 return ipoput4(ipc->p->f, bp, 0, ttl, tos, ipc);
1050 ilreject(Fs *f, Ilhdr *inih)
1055 bp = allocb(IL_IPSIZE+IL_HDRSIZE);
1056 bp->wp += IL_IPSIZE+IL_HDRSIZE;
1058 ih = (Ilhdr *)(bp->rp);
1062 ih->proto = IP_ILPROTO;
1063 hnputs(ih->illen, IL_HDRSIZE);
1066 hnputl(ih->dst, nhgetl(inih->src));
1067 hnputl(ih->src, nhgetl(inih->dst));
1068 hnputs(ih->ilsrc, nhgets(inih->ildst));
1069 hnputs(ih->ildst, nhgets(inih->ilsrc));
1070 hnputl(ih->ilid, nhgetl(inih->ilack));
1071 hnputl(ih->ilack, nhgetl(inih->ilid));
1072 ih->iltype = Ilclose;
1078 hnputs(ih->ilsum, ptclcsum(bp, IL_IPSIZE, IL_HDRSIZE));
1080 ipoput4(f, bp, 0, MAXTTL, DFLTTOS, nil);
1084 ilsettimeout(Ilcb *ic)
1088 pt = (ic->delay>>LogAGain)
1089 + ic->unackedbytes/(ic->rate>>LogAGain)
1090 + (ic->mdev>>(LogDGain-1))
1094 ic->timeout = NOW + pt;
1103 pt = (ic->delay>>LogAGain)
1104 + ic->unackedbytes/(ic->rate>>LogAGain)
1105 + (ic->mdev>>(LogDGain-1))
1107 for(i = 0; i < ic->rexmit; i++)
1111 ic->timeout = NOW + pt;
1114 ic->timeout = NOW+Iltickms;
1119 // complain if two numbers not within an hour of each other
1120 #define Tfuture (1000*60*60)
1122 later(ulong t1, ulong t2, char *x)
1128 if(x != nil && dt > Tfuture)
1129 print("%s: way future %d\n", x, dt);
1134 print("%s: way past %d\n", x, -dt);
1152 tsleep(&up->sleep, return0, 0, Iltickms);
1153 for(s = il->conv; s && *s; s++) {
1155 ic = (Ilcb*)p->ptcl;
1162 if(later(NOW, ic->timeout, "timeout0")) {
1163 if(ic->rexmit > MaxRexmit){
1167 ilsendctl(p, nil, Ilclose, ic->next, ic->recvd, 0);
1174 if(later(NOW, ic->timeout, "timeout1")) {
1175 if(ic->rexmit > MaxRexmit){
1179 ilsendctl(p, nil, Ilsync, ic->start, ic->recvd, 0);
1185 if(ic->recvd != ic->acksent)
1186 if(later(NOW, ic->acktime, "acktime"))
1187 ilsendctl(p, nil, Ilack, ic->next, ic->recvd, 0);
1189 if(later(NOW, ic->querytime, "querytime")){
1190 if(later(NOW, ic->lastrecv+DeathTime, "deathtime")){
1191 netlog(il->f, Logil, "il: hangup: deathtime\n");
1195 ilsendctl(p, nil, Ilquery, ic->next, ic->recvd, ilnextqt(ic));
1196 ic->querytime = NOW + QueryTime;
1199 if(ic->unacked != nil)
1200 if(later(NOW, ic->timeout, "timeout2")) {
1201 if(ic->rexmit > MaxRexmit){
1202 netlog(il->f, Logil, "il: hangup: too many rexmits\n");
1206 ilsendctl(p, nil, Ilquery, ic->next, ic->recvd, ilnextqt(ic));
1219 ic->start = nrand(0x1000000);
1220 ic->next = ic->start+1;
1222 ic->window = Defaultwin;
1223 ic->unackedbytes = 0;
1225 ic->outoforder = nil;
1230 ic->fasttimeout = 0;
1233 ic->delay = DefRtt<<LogAGain;
1234 ic->mdev = DefRtt<<LogDGain;
1235 ic->rate = DefByteRate<<LogAGain;
1236 ic->querytime = NOW + QueryTime;
1237 ic->lastrecv = NOW; /* or we'll timeout right away */
1242 ilstart(Conv *c, int type, int fasttimeout)
1246 char kpname[KNAMELEN];
1250 if(ipriv->ackprocstarted == 0){
1252 if(ipriv->ackprocstarted == 0){
1253 sprint(kpname, "#I%dilack", c->p->f->dev);
1254 kproc(kpname, ilackproc, c->p);
1255 ipriv->ackprocstarted = 1;
1257 qunlock(&ipriv->apl);
1260 ic = (Ilcb*)c->ptcl;
1263 if(ic->state != Ilclosed)
1269 /* timeout if we can't connect quickly */
1270 ic->fasttimeout = 1;
1271 ic->timeout = NOW+Iltickms;
1272 ic->rexmit = MaxRexmit - 4;
1277 netlog(c->p->f, Logil, "il: start: type %d\n", type);
1280 ic->state = Illistening;
1281 iphtadd(&ipriv->ht, c);
1284 ic->state = Ilsyncer;
1285 iphtadd(&ipriv->ht, c);
1286 if(ilsendctl(c, nil, Ilsync, ic->start, ic->recvd, 0) < 0)
1287 ilhangup(c, "no route");
1300 for(bp = ic->unacked; bp; bp = next) {
1308 for(bp = ic->outoforder; bp; bp = next) {
1312 ic->outoforder = nil;
1317 iladvise(Proto *il, Block *bp, char *msg)
1321 uchar source[IPaddrlen], dest[IPaddrlen];
1325 h = (Ilhdr*)(bp->rp);
1327 v4tov6(dest, h->dst);
1328 v4tov6(source, h->src);
1329 psource = nhgets(h->ilsrc);
1332 /* Look for a connection, unfortunately the destination port is missing */
1334 for(p = il->conv; *p; p++) {
1336 if(s->lport == psource)
1337 if(ipcmp(s->laddr, source) == 0)
1338 if(ipcmp(s->raddr, dest) == 0){
1342 ic = (Ilcb*)s->ptcl;
1366 ic->qt[x] = ic->next-1; /* highest xmitted packet */
1367 ic->qt[0] = ic->qt[x]; /* compatibility with old implementations */
1373 /* calculate scale constants that converts fast ticks to ms (more or less) */
1396 il = smalloc(sizeof(Proto));
1397 il->priv = smalloc(sizeof(Ilpriv));
1399 il->connect = ilconnect;
1400 il->announce = ilannounce;
1401 il->state = ilstate;
1402 il->create = ilcreate;
1403 il->close = ilclose;
1406 il->advise = iladvise;
1407 il->stats = ilxstats;
1408 il->inuse = ilinuse;
1410 il->ipproto = IP_ILPROTO;
1411 il->nc = scalednconv();
1412 il->ptclsize = sizeof(Ilcb);