il.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "../port/error.h"
  7. #include "ip.h"
  8. enum /* Connection state */
  9. {
  10. Ilclosed,
  11. Ilsyncer,
  12. Ilsyncee,
  13. Ilestablished,
  14. Illistening,
  15. Ilclosing,
  16. Ilopening, /* only for file server */
  17. };
  18. char *ilstates[] =
  19. {
  20. "Closed",
  21. "Syncer",
  22. "Syncee",
  23. "Established",
  24. "Listen",
  25. "Closing",
  26. "Opening", /* only for file server */
  27. };
  28. enum /* Packet types */
  29. {
  30. Ilsync,
  31. Ildata,
  32. Ildataquery,
  33. Ilack,
  34. Ilquery,
  35. Ilstate,
  36. Ilclose,
  37. };
  38. char *iltype[] =
  39. {
  40. "sync",
  41. "data",
  42. "dataquery",
  43. "ack",
  44. "query",
  45. "state",
  46. "close"
  47. };
  48. enum
  49. {
  50. Seconds = 1000,
  51. Iltickms = 50, /* time base */
  52. AckDelay = 2*Iltickms, /* max time twixt message rcvd & ack sent */
  53. MaxTimeout = 30*Seconds, /* max time between rexmit */
  54. QueryTime = 10*Seconds, /* time between subsequent queries */
  55. DeathTime = 30*QueryTime,
  56. MaxRexmit = 16, /* max retransmissions before hangup */
  57. Defaultwin = 20,
  58. LogAGain = 3,
  59. AGain = 1<<LogAGain,
  60. LogDGain = 2,
  61. DGain = 1<<LogDGain,
  62. DefByteRate = 100, /* assume a megabit link */
  63. DefRtt = 50, /* cross country on a great day */
  64. Maxrq = 64*1024,
  65. };
  66. enum
  67. {
  68. Nqt= 8,
  69. };
  70. typedef struct Ilcb Ilcb;
  71. struct Ilcb /* Control block */
  72. {
  73. int state; /* Connection state */
  74. Conv *conv;
  75. QLock ackq; /* Unacknowledged queue */
  76. Block *unacked;
  77. Block *unackedtail;
  78. ulong unackedbytes;
  79. QLock outo; /* Out of order packet queue */
  80. Block *outoforder;
  81. ulong next; /* Id of next to send */
  82. ulong recvd; /* Last packet received */
  83. ulong acksent; /* Last packet acked */
  84. ulong start; /* Local start id */
  85. ulong rstart; /* Remote start id */
  86. int window; /* Maximum receive window */
  87. int rxquery; /* number of queries on this connection */
  88. int rxtot; /* number of retransmits on this connection */
  89. int rexmit; /* number of retransmits of *unacked */
  90. ulong qt[Nqt+1]; /* state table for query messages */
  91. int qtx; /* ... index into qt */
  92. /* if set, fasttimeout causes a connection request to terminate after 4*Iltickms */
  93. int fasttimeout;
  94. /* timers */
  95. ulong lastxmit; /* time of last xmit */
  96. ulong lastrecv; /* time of last recv */
  97. ulong timeout; /* retransmission time for *unacked */
  98. ulong acktime; /* time to send next ack */
  99. ulong querytime; /* time to send next query */
  100. /* adaptive measurements */
  101. int delay; /* Average of the fixed rtt delay */
  102. int rate; /* Average uchar rate */
  103. int mdev; /* Mean deviation of rtt */
  104. int maxrtt; /* largest rtt seen */
  105. ulong rttack; /* The ack we are waiting for */
  106. int rttlen; /* Length of rttack packet */
  107. uvlong rttstart; /* Time we issued rttack packet */
  108. };
  109. enum
  110. {
  111. IL_IPSIZE = 20,
  112. IL_HDRSIZE = 18,
  113. IL_LISTEN = 0,
  114. IL_CONNECT = 1,
  115. IP_ILPROTO = 40,
  116. };
  117. typedef struct Ilhdr Ilhdr;
  118. struct Ilhdr
  119. {
  120. uchar vihl; /* Version and header length */
  121. uchar tos; /* Type of service */
  122. uchar length[2]; /* packet length */
  123. uchar id[2]; /* Identification */
  124. uchar frag[2]; /* Fragment information */
  125. uchar ttl; /* Time to live */
  126. uchar proto; /* Protocol */
  127. uchar cksum[2]; /* Header checksum */
  128. uchar src[4]; /* Ip source */
  129. uchar dst[4]; /* Ip destination */
  130. uchar ilsum[2]; /* Checksum including header */
  131. uchar illen[2]; /* Packet length */
  132. uchar iltype; /* Packet type */
  133. uchar ilspec; /* Special */
  134. uchar ilsrc[2]; /* Src port */
  135. uchar ildst[2]; /* Dst port */
  136. uchar ilid[4]; /* Sequence id */
  137. uchar ilack[4]; /* Acked sequence */
  138. };
  139. enum
  140. {
  141. InMsgs,
  142. OutMsgs,
  143. CsumErrs, /* checksum errors */
  144. HlenErrs, /* header length error */
  145. LenErrs, /* short packet */
  146. OutOfOrder, /* out of order */
  147. Retrans, /* retransmissions */
  148. DupMsg,
  149. DupBytes,
  150. DroppedMsgs,
  151. Nstats,
  152. };
  153. static char *statnames[] =
  154. {
  155. [InMsgs] "InMsgs",
  156. [OutMsgs] "OutMsgs",
  157. [CsumErrs] "CsumErrs",
  158. [HlenErrs] "HlenErr",
  159. [LenErrs] "LenErrs",
  160. [OutOfOrder] "OutOfOrder",
  161. [Retrans] "Retrans",
  162. [DupMsg] "DupMsg",
  163. [DupBytes] "DupBytes",
  164. [DroppedMsgs] "DroppedMsgs",
  165. };
  166. typedef struct Ilpriv Ilpriv;
  167. struct Ilpriv
  168. {
  169. Ipht ht;
  170. ulong stats[Nstats];
  171. ulong csumerr; /* checksum errors */
  172. ulong hlenerr; /* header length error */
  173. ulong lenerr; /* short packet */
  174. ulong order; /* out of order */
  175. ulong rexmit; /* retransmissions */
  176. ulong dup;
  177. ulong dupb;
  178. /* keeping track of the ack kproc */
  179. int ackprocstarted;
  180. QLock apl;
  181. };
  182. /* state for query/dataquery messages */
  183. void ilrcvmsg(Conv*, Block*);
  184. void ilsendctl(Conv*, Ilhdr*, int, ulong, ulong, int);
  185. void ilackq(Ilcb*, Block*);
  186. void ilprocess(Conv*, Ilhdr*, Block*);
  187. void ilpullup(Conv*);
  188. void ilhangup(Conv*, char*);
  189. void ilfreeq(Ilcb*);
  190. void ilrexmit(Ilcb*);
  191. void ilbackoff(Ilcb*);
  192. void ilsettimeout(Ilcb*);
  193. char* ilstart(Conv*, int, int);
  194. void ilackproc(void*);
  195. void iloutoforder(Conv*, Ilhdr*, Block*);
  196. void iliput(Proto*, Ipifc*, Block*);
  197. void iladvise(Proto*, Block*, char*);
  198. int ilnextqt(Ilcb*);
  199. void ilcbinit(Ilcb*);
  200. int later(ulong, ulong, char*);
  201. void ilreject(Fs*, Ilhdr*);
  202. void illocalclose(Conv *c);
  203. int ilcksum = 1;
  204. static int initseq = 25001;
  205. static ulong scalediv, scalemul;
  206. static char *etime = "connection timed out";
  207. static char*
  208. ilconnect(Conv *c, char **argv, int argc)
  209. {
  210. char *e, *p;
  211. int fast;
  212. /* huge hack to quickly try an il connection */
  213. fast = 0;
  214. if(argc > 1){
  215. p = strstr(argv[1], "!fasttimeout");
  216. if(p != nil){
  217. *p = 0;
  218. fast = 1;
  219. }
  220. }
  221. e = Fsstdconnect(c, argv, argc);
  222. if(e != nil)
  223. return e;
  224. return ilstart(c, IL_CONNECT, fast);
  225. }
  226. static int
  227. ilstate(Conv *c, char *state, int n)
  228. {
  229. Ilcb *ic;
  230. ic = (Ilcb*)(c->ptcl);
  231. 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",
  232. ilstates[ic->state],
  233. c->rq ? qlen(c->rq) : 0,
  234. c->wq ? qlen(c->wq) : 0,
  235. ic->delay>>LogAGain, ic->rate>>LogAGain, ic->mdev>>LogDGain,
  236. ic->unackedbytes, ic->rxtot, ic->rxquery, ic->maxrtt);
  237. }
  238. static int
  239. ilinuse(Conv *c)
  240. {
  241. Ilcb *ic;
  242. ic = (Ilcb*)(c->ptcl);
  243. return ic->state != Ilclosed;
  244. }
  245. /* called with c locked */
  246. static char*
  247. ilannounce(Conv *c, char **argv, int argc)
  248. {
  249. char *e;
  250. e = Fsstdannounce(c, argv, argc);
  251. if(e != nil)
  252. return e;
  253. e = ilstart(c, IL_LISTEN, 0);
  254. if(e != nil)
  255. return e;
  256. Fsconnected(c, nil);
  257. return nil;
  258. }
  259. void
  260. illocalclose(Conv *c)
  261. {
  262. Ilcb *ic;
  263. Ilpriv *ipriv;
  264. ipriv = c->p->priv;
  265. ic = (Ilcb*)c->ptcl;
  266. ic->state = Ilclosed;
  267. iphtrem(&ipriv->ht, c);
  268. ipmove(c->laddr, IPnoaddr);
  269. c->lport = 0;
  270. }
  271. static void
  272. ilclose(Conv *c)
  273. {
  274. Ilcb *ic;
  275. ic = (Ilcb*)c->ptcl;
  276. qclose(c->rq);
  277. qclose(c->wq);
  278. qclose(c->eq);
  279. switch(ic->state) {
  280. case Ilclosing:
  281. case Ilclosed:
  282. break;
  283. case Ilsyncer:
  284. case Ilsyncee:
  285. case Ilestablished:
  286. ic->state = Ilclosing;
  287. ilsettimeout(ic);
  288. ilsendctl(c, nil, Ilclose, ic->next, ic->recvd, 0);
  289. break;
  290. case Illistening:
  291. illocalclose(c);
  292. break;
  293. }
  294. ilfreeq(ic);
  295. }
  296. void
  297. ilkick(void *x, Block *bp)
  298. {
  299. Conv *c = x;
  300. Ilhdr *ih;
  301. Ilcb *ic;
  302. int dlen;
  303. ulong id, ack;
  304. Fs *f;
  305. Ilpriv *priv;
  306. f = c->p->f;
  307. priv = c->p->priv;
  308. ic = (Ilcb*)c->ptcl;
  309. if(bp == nil)
  310. return;
  311. switch(ic->state) {
  312. case Ilclosed:
  313. case Illistening:
  314. case Ilclosing:
  315. freeblist(bp);
  316. qhangup(c->rq, nil);
  317. return;
  318. }
  319. dlen = blocklen(bp);
  320. /* Make space to fit il & ip */
  321. bp = padblock(bp, IL_IPSIZE+IL_HDRSIZE);
  322. ih = (Ilhdr *)(bp->rp);
  323. ih->vihl = IP_VER4;
  324. /* Ip fields */
  325. ih->frag[0] = 0;
  326. ih->frag[1] = 0;
  327. v6tov4(ih->dst, c->raddr);
  328. v6tov4(ih->src, c->laddr);
  329. ih->proto = IP_ILPROTO;
  330. /* Il fields */
  331. hnputs(ih->illen, dlen+IL_HDRSIZE);
  332. hnputs(ih->ilsrc, c->lport);
  333. hnputs(ih->ildst, c->rport);
  334. qlock(&ic->ackq);
  335. id = ic->next++;
  336. hnputl(ih->ilid, id);
  337. ack = ic->recvd;
  338. hnputl(ih->ilack, ack);
  339. ic->acksent = ack;
  340. ic->acktime = NOW + AckDelay;
  341. ih->iltype = Ildata;
  342. ih->ilspec = 0;
  343. ih->ilsum[0] = 0;
  344. ih->ilsum[1] = 0;
  345. /* Checksum of ilheader plus data (not ip & no pseudo header) */
  346. if(ilcksum)
  347. hnputs(ih->ilsum, ptclcsum(bp, IL_IPSIZE, dlen+IL_HDRSIZE));
  348. ilackq(ic, bp);
  349. qunlock(&ic->ackq);
  350. /* Start the round trip timer for this packet if the timer is free */
  351. if(ic->rttack == 0) {
  352. ic->rttack = id;
  353. ic->rttstart = fastticks(nil);
  354. ic->rttlen = dlen + IL_IPSIZE + IL_HDRSIZE;
  355. }
  356. if(later(NOW, ic->timeout, nil))
  357. ilsettimeout(ic);
  358. ipoput4(f, bp, 0, c->ttl, c->tos, c);
  359. priv->stats[OutMsgs]++;
  360. }
  361. static void
  362. ilcreate(Conv *c)
  363. {
  364. c->rq = qopen(Maxrq, 0, 0, c);
  365. c->wq = qbypass(ilkick, c);
  366. }
  367. int
  368. ilxstats(Proto *il, char *buf, int len)
  369. {
  370. Ilpriv *priv;
  371. char *p, *e;
  372. int i;
  373. priv = il->priv;
  374. p = buf;
  375. e = p+len;
  376. for(i = 0; i < Nstats; i++)
  377. p = seprint(p, e, "%s: %lud\n", statnames[i], priv->stats[i]);
  378. return p - buf;
  379. }
  380. void
  381. ilackq(Ilcb *ic, Block *bp)
  382. {
  383. Block *np;
  384. int n;
  385. n = blocklen(bp);
  386. /* Enqueue a copy on the unacked queue in case this one gets lost */
  387. np = copyblock(bp, n);
  388. if(ic->unacked)
  389. ic->unackedtail->list = np;
  390. else
  391. ic->unacked = np;
  392. ic->unackedtail = np;
  393. np->list = nil;
  394. ic->unackedbytes += n;
  395. }
  396. static
  397. void
  398. ilrttcalc(Ilcb *ic, Block *bp)
  399. {
  400. int rtt, tt, pt, delay, rate;
  401. rtt = fastticks(nil) - ic->rttstart;
  402. rtt = (rtt*scalemul)/scalediv;
  403. delay = ic->delay;
  404. rate = ic->rate;
  405. /* Guard against zero wrap */
  406. if(rtt > 120000 || rtt < 0)
  407. return;
  408. /* this block had to be transmitted after the one acked so count its size */
  409. ic->rttlen += blocklen(bp) + IL_IPSIZE + IL_HDRSIZE;
  410. if(ic->rttlen < 256){
  411. /* guess fixed delay as rtt of small packets */
  412. delay += rtt - (delay>>LogAGain);
  413. if(delay < AGain)
  414. delay = AGain;
  415. ic->delay = delay;
  416. } else {
  417. /* if packet took longer than avg rtt delay, recalc rate */
  418. tt = rtt - (delay>>LogAGain);
  419. if(tt > 0){
  420. rate += ic->rttlen/tt - (rate>>LogAGain);
  421. if(rate < AGain)
  422. rate = AGain;
  423. ic->rate = rate;
  424. }
  425. }
  426. /* mdev */
  427. pt = ic->rttlen/(rate>>LogAGain) + (delay>>LogAGain);
  428. ic->mdev += abs(rtt-pt) - (ic->mdev>>LogDGain);
  429. if(rtt > ic->maxrtt)
  430. ic->maxrtt = rtt;
  431. }
  432. void
  433. ilackto(Ilcb *ic, ulong ackto, Block *bp)
  434. {
  435. Ilhdr *h;
  436. ulong id;
  437. if(ic->rttack == ackto)
  438. ilrttcalc(ic, bp);
  439. /* Cancel if we've passed the packet we were interested in */
  440. if(ic->rttack <= ackto)
  441. ic->rttack = 0;
  442. qlock(&ic->ackq);
  443. while(ic->unacked) {
  444. h = (Ilhdr *)ic->unacked->rp;
  445. id = nhgetl(h->ilid);
  446. if(ackto < id)
  447. break;
  448. bp = ic->unacked;
  449. ic->unacked = bp->list;
  450. bp->list = nil;
  451. ic->unackedbytes -= blocklen(bp);
  452. freeblist(bp);
  453. ic->rexmit = 0;
  454. ilsettimeout(ic);
  455. }
  456. qunlock(&ic->ackq);
  457. }
  458. void
  459. iliput(Proto *il, Ipifc*, Block *bp)
  460. {
  461. char *st;
  462. Ilcb *ic;
  463. Ilhdr *ih;
  464. uchar raddr[IPaddrlen];
  465. uchar laddr[IPaddrlen];
  466. ushort sp, dp, csum;
  467. int plen, illen;
  468. Conv *new, *s;
  469. Ilpriv *ipriv;
  470. ipriv = il->priv;
  471. ih = (Ilhdr *)bp->rp;
  472. plen = blocklen(bp);
  473. if(plen < IL_IPSIZE+IL_HDRSIZE){
  474. netlog(il->f, Logil, "il: hlenerr\n");
  475. ipriv->stats[HlenErrs]++;
  476. goto raise;
  477. }
  478. illen = nhgets(ih->illen);
  479. if(illen+IL_IPSIZE > plen){
  480. netlog(il->f, Logil, "il: lenerr\n");
  481. ipriv->stats[LenErrs]++;
  482. goto raise;
  483. }
  484. sp = nhgets(ih->ildst);
  485. dp = nhgets(ih->ilsrc);
  486. v4tov6(raddr, ih->src);
  487. v4tov6(laddr, ih->dst);
  488. if((csum = ptclcsum(bp, IL_IPSIZE, illen)) != 0) {
  489. if(ih->iltype > Ilclose)
  490. st = "?";
  491. else
  492. st = iltype[ih->iltype];
  493. ipriv->stats[CsumErrs]++;
  494. netlog(il->f, Logil, "il: cksum %ux %ux, pkt(%s id %lud ack %lud %I/%d->%d)\n",
  495. csum, st, nhgetl(ih->ilid), nhgetl(ih->ilack), raddr, sp, dp);
  496. goto raise;
  497. }
  498. qlock(il);
  499. s = iphtlook(&ipriv->ht, raddr, dp, laddr, sp);
  500. if(s == nil){
  501. if(ih->iltype == Ilsync)
  502. ilreject(il->f, ih); /* no listener */
  503. qunlock(il);
  504. goto raise;
  505. }
  506. ic = (Ilcb*)s->ptcl;
  507. if(ic->state == Illistening){
  508. if(ih->iltype != Ilsync){
  509. qunlock(il);
  510. if(ih->iltype > Ilclose)
  511. st = "?";
  512. else
  513. st = iltype[ih->iltype];
  514. ilreject(il->f, ih); /* no channel and not sync */
  515. netlog(il->f, Logil, "il: no channel, pkt(%s id %lud ack %lud %I/%ud->%ud)\n",
  516. st, nhgetl(ih->ilid), nhgetl(ih->ilack), raddr, sp, dp);
  517. goto raise;
  518. }
  519. new = Fsnewcall(s, raddr, dp, laddr, sp, V4);
  520. if(new == nil){
  521. qunlock(il);
  522. netlog(il->f, Logil, "il: bad newcall %I/%ud->%ud\n", raddr, sp, dp);
  523. ilsendctl(s, ih, Ilclose, 0, nhgetl(ih->ilid), 0);
  524. goto raise;
  525. }
  526. s = new;
  527. ic = (Ilcb*)s->ptcl;
  528. ic->conv = s;
  529. ic->state = Ilsyncee;
  530. ilcbinit(ic);
  531. ic->rstart = nhgetl(ih->ilid);
  532. iphtadd(&ipriv->ht, s);
  533. }
  534. qlock(s);
  535. qunlock(il);
  536. if(waserror()){
  537. qunlock(s);
  538. nexterror();
  539. }
  540. ilprocess(s, ih, bp);
  541. qunlock(s);
  542. poperror();
  543. return;
  544. raise:
  545. freeblist(bp);
  546. }
  547. void
  548. _ilprocess(Conv *s, Ilhdr *h, Block *bp)
  549. {
  550. Ilcb *ic;
  551. ulong id, ack;
  552. Ilpriv *priv;
  553. id = nhgetl(h->ilid);
  554. ack = nhgetl(h->ilack);
  555. ic = (Ilcb*)s->ptcl;
  556. ic->lastrecv = NOW;
  557. ic->querytime = NOW + QueryTime;
  558. priv = s->p->priv;
  559. priv->stats[InMsgs]++;
  560. switch(ic->state) {
  561. default:
  562. netlog(s->p->f, Logil, "il: unknown state %d\n", ic->state);
  563. case Ilclosed:
  564. freeblist(bp);
  565. break;
  566. case Ilsyncer:
  567. switch(h->iltype) {
  568. default:
  569. break;
  570. case Ilsync:
  571. if(ack != ic->start)
  572. ilhangup(s, "connection rejected");
  573. else {
  574. ic->recvd = id;
  575. ic->rstart = id;
  576. ilsendctl(s, nil, Ilack, ic->next, ic->recvd, 0);
  577. ic->state = Ilestablished;
  578. ic->fasttimeout = 0;
  579. ic->rexmit = 0;
  580. Fsconnected(s, nil);
  581. ilpullup(s);
  582. }
  583. break;
  584. case Ilclose:
  585. if(ack == ic->start)
  586. ilhangup(s, "connection rejected");
  587. break;
  588. }
  589. freeblist(bp);
  590. break;
  591. case Ilsyncee:
  592. switch(h->iltype) {
  593. default:
  594. break;
  595. case Ilsync:
  596. if(id != ic->rstart || ack != 0){
  597. illocalclose(s);
  598. } else {
  599. ic->recvd = id;
  600. ilsendctl(s, nil, Ilsync, ic->start, ic->recvd, 0);
  601. }
  602. break;
  603. case Ilack:
  604. if(ack == ic->start) {
  605. ic->state = Ilestablished;
  606. ic->fasttimeout = 0;
  607. ic->rexmit = 0;
  608. ilpullup(s);
  609. }
  610. break;
  611. case Ildata:
  612. if(ack == ic->start) {
  613. ic->state = Ilestablished;
  614. ic->fasttimeout = 0;
  615. ic->rexmit = 0;
  616. goto established;
  617. }
  618. break;
  619. case Ilclose:
  620. if(ack == ic->start)
  621. ilhangup(s, "remote close");
  622. break;
  623. }
  624. freeblist(bp);
  625. break;
  626. case Ilestablished:
  627. established:
  628. switch(h->iltype) {
  629. case Ilsync:
  630. if(id != ic->rstart)
  631. ilhangup(s, "remote close");
  632. else
  633. ilsendctl(s, nil, Ilack, ic->next, ic->rstart, 0);
  634. freeblist(bp);
  635. break;
  636. case Ildata:
  637. /*
  638. * avoid consuming all the mount rpc buffers in the
  639. * system. if the input queue is too long, drop this
  640. * packet.
  641. */
  642. if (s->rq && qlen(s->rq) >= Maxrq) {
  643. priv->stats[DroppedMsgs]++;
  644. freeblist(bp);
  645. break;
  646. }
  647. ilackto(ic, ack, bp);
  648. iloutoforder(s, h, bp);
  649. ilpullup(s);
  650. break;
  651. case Ildataquery:
  652. ilackto(ic, ack, bp);
  653. iloutoforder(s, h, bp);
  654. ilpullup(s);
  655. ilsendctl(s, nil, Ilstate, ic->next, ic->recvd, h->ilspec);
  656. break;
  657. case Ilack:
  658. ilackto(ic, ack, bp);
  659. freeblist(bp);
  660. break;
  661. case Ilquery:
  662. ilackto(ic, ack, bp);
  663. ilsendctl(s, nil, Ilstate, ic->next, ic->recvd, h->ilspec);
  664. freeblist(bp);
  665. break;
  666. case Ilstate:
  667. if(ack >= ic->rttack)
  668. ic->rttack = 0;
  669. ilackto(ic, ack, bp);
  670. if(h->ilspec > Nqt)
  671. h->ilspec = 0;
  672. if(ic->qt[h->ilspec] > ack){
  673. ilrexmit(ic);
  674. ilsettimeout(ic);
  675. }
  676. freeblist(bp);
  677. break;
  678. case Ilclose:
  679. freeblist(bp);
  680. if(ack < ic->start || ack > ic->next)
  681. break;
  682. ic->recvd = id;
  683. ilsendctl(s, nil, Ilclose, ic->next, ic->recvd, 0);
  684. ic->state = Ilclosing;
  685. ilsettimeout(ic);
  686. ilfreeq(ic);
  687. break;
  688. }
  689. break;
  690. case Illistening:
  691. freeblist(bp);
  692. break;
  693. case Ilclosing:
  694. switch(h->iltype) {
  695. case Ilclose:
  696. ic->recvd = id;
  697. ilsendctl(s, nil, Ilclose, ic->next, ic->recvd, 0);
  698. if(ack == ic->next)
  699. ilhangup(s, nil);
  700. break;
  701. default:
  702. break;
  703. }
  704. freeblist(bp);
  705. break;
  706. }
  707. }
  708. void
  709. ilrexmit(Ilcb *ic)
  710. {
  711. Ilhdr *h;
  712. Block *nb;
  713. Conv *c;
  714. ulong id;
  715. Ilpriv *priv;
  716. nb = nil;
  717. qlock(&ic->ackq);
  718. if(ic->unacked)
  719. nb = copyblock(ic->unacked, blocklen(ic->unacked));
  720. qunlock(&ic->ackq);
  721. if(nb == nil)
  722. return;
  723. h = (Ilhdr*)nb->rp;
  724. h->vihl = IP_VER4;
  725. h->iltype = Ildataquery;
  726. hnputl(h->ilack, ic->recvd);
  727. h->ilspec = ilnextqt(ic);
  728. h->ilsum[0] = 0;
  729. h->ilsum[1] = 0;
  730. hnputs(h->ilsum, ptclcsum(nb, IL_IPSIZE, nhgets(h->illen)));
  731. c = ic->conv;
  732. id = nhgetl(h->ilid);
  733. netlog(c->p->f, Logil, "il: rexmit %d %ud: %d %d: %i %d/%d\n", id, ic->recvd,
  734. ic->rexmit, ic->timeout,
  735. c->raddr, c->lport, c->rport);
  736. ilbackoff(ic);
  737. ipoput4(c->p->f, nb, 0, c->ttl, c->tos, c);
  738. /* statistics */
  739. ic->rxtot++;
  740. priv = c->p->priv;
  741. priv->rexmit++;
  742. }
  743. /* DEBUG */
  744. void
  745. ilprocess(Conv *s, Ilhdr *h, Block *bp)
  746. {
  747. Ilcb *ic;
  748. ic = (Ilcb*)s->ptcl;
  749. USED(ic);
  750. netlog(s->p->f, Logilmsg, "%11s rcv %d/%d snt %d/%d pkt(%s id %d ack %d %d->%d) ",
  751. ilstates[ic->state], ic->rstart, ic->recvd, ic->start,
  752. ic->next, iltype[h->iltype], nhgetl(h->ilid),
  753. nhgetl(h->ilack), nhgets(h->ilsrc), nhgets(h->ildst));
  754. _ilprocess(s, h, bp);
  755. netlog(s->p->f, Logilmsg, "%11s rcv %d snt %d\n", ilstates[ic->state], ic->recvd, ic->next);
  756. }
  757. void
  758. ilhangup(Conv *s, char *msg)
  759. {
  760. Ilcb *ic;
  761. int callout;
  762. netlog(s->p->f, Logil, "il: hangup! %I %d/%d: %s\n", s->raddr,
  763. s->lport, s->rport, msg?msg:"no reason");
  764. ic = (Ilcb*)s->ptcl;
  765. callout = ic->state == Ilsyncer;
  766. illocalclose(s);
  767. qhangup(s->rq, msg);
  768. qhangup(s->wq, msg);
  769. if(callout)
  770. Fsconnected(s, msg);
  771. }
  772. void
  773. ilpullup(Conv *s)
  774. {
  775. Ilcb *ic;
  776. Ilhdr *oh;
  777. Block *bp;
  778. ulong oid, dlen;
  779. Ilpriv *ipriv;
  780. ic = (Ilcb*)s->ptcl;
  781. if(ic->state != Ilestablished)
  782. return;
  783. qlock(&ic->outo);
  784. while(ic->outoforder) {
  785. bp = ic->outoforder;
  786. oh = (Ilhdr*)bp->rp;
  787. oid = nhgetl(oh->ilid);
  788. if(oid <= ic->recvd) {
  789. ic->outoforder = bp->list;
  790. freeblist(bp);
  791. continue;
  792. }
  793. if(oid != ic->recvd+1){
  794. ipriv = s->p->priv;
  795. ipriv->stats[OutOfOrder]++;
  796. break;
  797. }
  798. ic->recvd = oid;
  799. ic->outoforder = bp->list;
  800. bp->list = nil;
  801. dlen = nhgets(oh->illen)-IL_HDRSIZE;
  802. bp = trimblock(bp, IL_IPSIZE+IL_HDRSIZE, dlen);
  803. /*
  804. * Upper levels don't know about multiple-block
  805. * messages so copy all into one (yick).
  806. */
  807. bp = concatblock(bp);
  808. if(bp == 0)
  809. panic("ilpullup");
  810. bp = packblock(bp);
  811. if(bp == 0)
  812. panic("ilpullup2");
  813. qpass(s->rq, bp);
  814. }
  815. qunlock(&ic->outo);
  816. }
  817. void
  818. iloutoforder(Conv *s, Ilhdr *h, Block *bp)
  819. {
  820. Ilcb *ic;
  821. uchar *lid;
  822. Block *f, **l;
  823. ulong id, newid;
  824. Ilpriv *ipriv;
  825. ipriv = s->p->priv;
  826. ic = (Ilcb*)s->ptcl;
  827. bp->list = nil;
  828. id = nhgetl(h->ilid);
  829. /* Window checks */
  830. if(id <= ic->recvd || id > ic->recvd+ic->window) {
  831. netlog(s->p->f, Logil, "il: message outside window %ud <%ud-%ud>: %i %d/%d\n",
  832. id, ic->recvd, ic->recvd+ic->window, s->raddr, s->lport, s->rport);
  833. freeblist(bp);
  834. return;
  835. }
  836. /* Packet is acceptable so sort onto receive queue for pullup */
  837. qlock(&ic->outo);
  838. if(ic->outoforder == nil)
  839. ic->outoforder = bp;
  840. else {
  841. l = &ic->outoforder;
  842. for(f = *l; f; f = f->list) {
  843. lid = ((Ilhdr*)(f->rp))->ilid;
  844. newid = nhgetl(lid);
  845. if(id <= newid) {
  846. if(id == newid) {
  847. ipriv->stats[DupMsg]++;
  848. ipriv->stats[DupBytes] += blocklen(bp);
  849. qunlock(&ic->outo);
  850. freeblist(bp);
  851. return;
  852. }
  853. bp->list = f;
  854. *l = bp;
  855. qunlock(&ic->outo);
  856. return;
  857. }
  858. l = &f->list;
  859. }
  860. *l = bp;
  861. }
  862. qunlock(&ic->outo);
  863. }
  864. void
  865. ilsendctl(Conv *ipc, Ilhdr *inih, int type, ulong id, ulong ack, int ilspec)
  866. {
  867. Ilhdr *ih;
  868. Ilcb *ic;
  869. Block *bp;
  870. int ttl, tos;
  871. bp = allocb(IL_IPSIZE+IL_HDRSIZE);
  872. bp->wp += IL_IPSIZE+IL_HDRSIZE;
  873. ih = (Ilhdr *)(bp->rp);
  874. ih->vihl = IP_VER4;
  875. /* Ip fields */
  876. ih->proto = IP_ILPROTO;
  877. hnputs(ih->illen, IL_HDRSIZE);
  878. ih->frag[0] = 0;
  879. ih->frag[1] = 0;
  880. if(inih) {
  881. hnputl(ih->dst, nhgetl(inih->src));
  882. hnputl(ih->src, nhgetl(inih->dst));
  883. hnputs(ih->ilsrc, nhgets(inih->ildst));
  884. hnputs(ih->ildst, nhgets(inih->ilsrc));
  885. hnputl(ih->ilid, nhgetl(inih->ilack));
  886. hnputl(ih->ilack, nhgetl(inih->ilid));
  887. ttl = MAXTTL;
  888. tos = DFLTTOS;
  889. }
  890. else {
  891. v6tov4(ih->dst, ipc->raddr);
  892. v6tov4(ih->src, ipc->laddr);
  893. hnputs(ih->ilsrc, ipc->lport);
  894. hnputs(ih->ildst, ipc->rport);
  895. hnputl(ih->ilid, id);
  896. hnputl(ih->ilack, ack);
  897. ic = (Ilcb*)ipc->ptcl;
  898. ic->acksent = ack;
  899. ic->acktime = NOW;
  900. ttl = ipc->ttl;
  901. tos = ipc->tos;
  902. }
  903. ih->iltype = type;
  904. ih->ilspec = ilspec;
  905. ih->ilsum[0] = 0;
  906. ih->ilsum[1] = 0;
  907. if(ilcksum)
  908. hnputs(ih->ilsum, ptclcsum(bp, IL_IPSIZE, IL_HDRSIZE));
  909. if(ipc==nil)
  910. panic("ipc is nil caller is %#p", getcallerpc(&ipc));
  911. if(ipc->p==nil)
  912. panic("ipc->p is nil");
  913. netlog(ipc->p->f, Logilmsg, "ctl(%s id %d ack %d %d->%d)\n",
  914. iltype[ih->iltype], nhgetl(ih->ilid), nhgetl(ih->ilack),
  915. nhgets(ih->ilsrc), nhgets(ih->ildst));
  916. ipoput4(ipc->p->f, bp, 0, ttl, tos, ipc);
  917. }
  918. void
  919. ilreject(Fs *f, Ilhdr *inih)
  920. {
  921. Ilhdr *ih;
  922. Block *bp;
  923. bp = allocb(IL_IPSIZE+IL_HDRSIZE);
  924. bp->wp += IL_IPSIZE+IL_HDRSIZE;
  925. ih = (Ilhdr *)(bp->rp);
  926. ih->vihl = IP_VER4;
  927. /* Ip fields */
  928. ih->proto = IP_ILPROTO;
  929. hnputs(ih->illen, IL_HDRSIZE);
  930. ih->frag[0] = 0;
  931. ih->frag[1] = 0;
  932. hnputl(ih->dst, nhgetl(inih->src));
  933. hnputl(ih->src, nhgetl(inih->dst));
  934. hnputs(ih->ilsrc, nhgets(inih->ildst));
  935. hnputs(ih->ildst, nhgets(inih->ilsrc));
  936. hnputl(ih->ilid, nhgetl(inih->ilack));
  937. hnputl(ih->ilack, nhgetl(inih->ilid));
  938. ih->iltype = Ilclose;
  939. ih->ilspec = 0;
  940. ih->ilsum[0] = 0;
  941. ih->ilsum[1] = 0;
  942. if(ilcksum)
  943. hnputs(ih->ilsum, ptclcsum(bp, IL_IPSIZE, IL_HDRSIZE));
  944. ipoput4(f, bp, 0, MAXTTL, DFLTTOS, nil);
  945. }
  946. void
  947. ilsettimeout(Ilcb *ic)
  948. {
  949. ulong pt;
  950. pt = (ic->delay>>LogAGain)
  951. + ic->unackedbytes/(ic->rate>>LogAGain)
  952. + (ic->mdev>>(LogDGain-1))
  953. + AckDelay;
  954. if(pt > MaxTimeout)
  955. pt = MaxTimeout;
  956. ic->timeout = NOW + pt;
  957. }
  958. void
  959. ilbackoff(Ilcb *ic)
  960. {
  961. ulong pt;
  962. int i;
  963. pt = (ic->delay>>LogAGain)
  964. + ic->unackedbytes/(ic->rate>>LogAGain)
  965. + (ic->mdev>>(LogDGain-1))
  966. + AckDelay;
  967. for(i = 0; i < ic->rexmit; i++)
  968. pt = pt + (pt>>1);
  969. if(pt > MaxTimeout)
  970. pt = MaxTimeout;
  971. ic->timeout = NOW + pt;
  972. if(ic->fasttimeout)
  973. ic->timeout = NOW+Iltickms;
  974. ic->rexmit++;
  975. }
  976. // complain if two numbers not within an hour of each other
  977. #define Tfuture (1000*60*60)
  978. int
  979. later(ulong t1, ulong t2, char *x)
  980. {
  981. int dt;
  982. dt = t1 - t2;
  983. if(dt > 0) {
  984. if(x != nil && dt > Tfuture)
  985. print("%s: way future %d\n", x, dt);
  986. return 1;
  987. }
  988. if(dt < -Tfuture) {
  989. if(x != nil)
  990. print("%s: way past %d\n", x, -dt);
  991. return 1;
  992. }
  993. return 0;
  994. }
  995. void
  996. ilackproc(void *x)
  997. {
  998. Ilcb *ic;
  999. Conv **s, *p;
  1000. Proto *il;
  1001. il = x;
  1002. loop:
  1003. tsleep(&up->sleep, return0, 0, Iltickms);
  1004. for(s = il->conv; s && *s; s++) {
  1005. p = *s;
  1006. ic = (Ilcb*)p->ptcl;
  1007. switch(ic->state) {
  1008. case Ilclosed:
  1009. case Illistening:
  1010. break;
  1011. case Ilclosing:
  1012. if(later(NOW, ic->timeout, "timeout0")) {
  1013. if(ic->rexmit > MaxRexmit){
  1014. ilhangup(p, nil);
  1015. break;
  1016. }
  1017. ilsendctl(p, nil, Ilclose, ic->next, ic->recvd, 0);
  1018. ilbackoff(ic);
  1019. }
  1020. break;
  1021. case Ilsyncee:
  1022. case Ilsyncer:
  1023. if(later(NOW, ic->timeout, "timeout1")) {
  1024. if(ic->rexmit > MaxRexmit){
  1025. ilhangup(p, etime);
  1026. break;
  1027. }
  1028. ilsendctl(p, nil, Ilsync, ic->start, ic->recvd, 0);
  1029. ilbackoff(ic);
  1030. }
  1031. break;
  1032. case Ilestablished:
  1033. if(ic->recvd != ic->acksent)
  1034. if(later(NOW, ic->acktime, "acktime"))
  1035. ilsendctl(p, nil, Ilack, ic->next, ic->recvd, 0);
  1036. if(later(NOW, ic->querytime, "querytime")){
  1037. if(later(NOW, ic->lastrecv+DeathTime, "deathtime")){
  1038. netlog(il->f, Logil, "il: hangup: deathtime\n");
  1039. ilhangup(p, etime);
  1040. break;
  1041. }
  1042. ilsendctl(p, nil, Ilquery, ic->next, ic->recvd, ilnextqt(ic));
  1043. ic->querytime = NOW + QueryTime;
  1044. }
  1045. if(ic->unacked != nil)
  1046. if(later(NOW, ic->timeout, "timeout2")) {
  1047. if(ic->rexmit > MaxRexmit){
  1048. netlog(il->f, Logil, "il: hangup: too many rexmits\n");
  1049. ilhangup(p, etime);
  1050. break;
  1051. }
  1052. ilsendctl(p, nil, Ilquery, ic->next, ic->recvd, ilnextqt(ic));
  1053. ic->rxquery++;
  1054. ilbackoff(ic);
  1055. }
  1056. break;
  1057. }
  1058. }
  1059. goto loop;
  1060. }
  1061. void
  1062. ilcbinit(Ilcb *ic)
  1063. {
  1064. ic->start = nrand(0x1000000);
  1065. ic->next = ic->start+1;
  1066. ic->recvd = 0;
  1067. ic->window = Defaultwin;
  1068. ic->unackedbytes = 0;
  1069. ic->unacked = nil;
  1070. ic->outoforder = nil;
  1071. ic->rexmit = 0;
  1072. ic->rxtot = 0;
  1073. ic->rxquery = 0;
  1074. ic->qtx = 1;
  1075. ic->fasttimeout = 0;
  1076. /* timers */
  1077. ic->delay = DefRtt<<LogAGain;
  1078. ic->mdev = DefRtt<<LogDGain;
  1079. ic->rate = DefByteRate<<LogAGain;
  1080. ic->querytime = NOW + QueryTime;
  1081. ic->lastrecv = NOW; /* or we'll timeout right away */
  1082. ilsettimeout(ic);
  1083. }
  1084. char*
  1085. ilstart(Conv *c, int type, int fasttimeout)
  1086. {
  1087. Ilcb *ic;
  1088. Ilpriv *ipriv;
  1089. char kpname[KNAMELEN];
  1090. ipriv = c->p->priv;
  1091. if(ipriv->ackprocstarted == 0){
  1092. qlock(&ipriv->apl);
  1093. if(ipriv->ackprocstarted == 0){
  1094. sprint(kpname, "#I%dilack", c->p->f->dev);
  1095. kproc(kpname, ilackproc, c->p);
  1096. ipriv->ackprocstarted = 1;
  1097. }
  1098. qunlock(&ipriv->apl);
  1099. }
  1100. ic = (Ilcb*)c->ptcl;
  1101. ic->conv = c;
  1102. if(ic->state != Ilclosed)
  1103. return nil;
  1104. ilcbinit(ic);
  1105. if(fasttimeout){
  1106. /* timeout if we can't connect quickly */
  1107. ic->fasttimeout = 1;
  1108. ic->timeout = NOW+Iltickms;
  1109. ic->rexmit = MaxRexmit - 4;
  1110. };
  1111. switch(type) {
  1112. default:
  1113. netlog(c->p->f, Logil, "il: start: type %d\n", type);
  1114. break;
  1115. case IL_LISTEN:
  1116. ic->state = Illistening;
  1117. iphtadd(&ipriv->ht, c);
  1118. break;
  1119. case IL_CONNECT:
  1120. ic->state = Ilsyncer;
  1121. iphtadd(&ipriv->ht, c);
  1122. ilsendctl(c, nil, Ilsync, ic->start, ic->recvd, 0);
  1123. break;
  1124. }
  1125. return nil;
  1126. }
  1127. void
  1128. ilfreeq(Ilcb *ic)
  1129. {
  1130. Block *bp, *next;
  1131. qlock(&ic->ackq);
  1132. for(bp = ic->unacked; bp; bp = next) {
  1133. next = bp->list;
  1134. freeblist(bp);
  1135. }
  1136. ic->unacked = nil;
  1137. qunlock(&ic->ackq);
  1138. qlock(&ic->outo);
  1139. for(bp = ic->outoforder; bp; bp = next) {
  1140. next = bp->list;
  1141. freeblist(bp);
  1142. }
  1143. ic->outoforder = nil;
  1144. qunlock(&ic->outo);
  1145. }
  1146. void
  1147. iladvise(Proto *il, Block *bp, char *msg)
  1148. {
  1149. Ilhdr *h;
  1150. Ilcb *ic;
  1151. uchar source[IPaddrlen], dest[IPaddrlen];
  1152. ushort psource;
  1153. Conv *s, **p;
  1154. h = (Ilhdr*)(bp->rp);
  1155. v4tov6(dest, h->dst);
  1156. v4tov6(source, h->src);
  1157. psource = nhgets(h->ilsrc);
  1158. /* Look for a connection, unfortunately the destination port is missing */
  1159. qlock(il);
  1160. for(p = il->conv; *p; p++) {
  1161. s = *p;
  1162. if(s->lport == psource)
  1163. if(ipcmp(s->laddr, source) == 0)
  1164. if(ipcmp(s->raddr, dest) == 0){
  1165. qunlock(il);
  1166. ic = (Ilcb*)s->ptcl;
  1167. switch(ic->state){
  1168. case Ilsyncer:
  1169. ilhangup(s, msg);
  1170. break;
  1171. }
  1172. freeblist(bp);
  1173. return;
  1174. }
  1175. }
  1176. qunlock(il);
  1177. freeblist(bp);
  1178. }
  1179. int
  1180. ilnextqt(Ilcb *ic)
  1181. {
  1182. int x;
  1183. qlock(&ic->ackq);
  1184. x = ic->qtx;
  1185. if(++x > Nqt)
  1186. x = 1;
  1187. ic->qtx = x;
  1188. ic->qt[x] = ic->next-1; /* highest xmitted packet */
  1189. ic->qt[0] = ic->qt[x]; /* compatibility with old implementations */
  1190. qunlock(&ic->ackq);
  1191. return x;
  1192. }
  1193. /* calculate scale constants that converts fast ticks to ms (more or less) */
  1194. static void
  1195. inittimescale(void)
  1196. {
  1197. uvlong hz;
  1198. fastticks(&hz);
  1199. if(hz > 1000){
  1200. scalediv = hz/1000;
  1201. scalemul = 1;
  1202. } else {
  1203. scalediv = 1;
  1204. scalemul = 1000/hz;
  1205. }
  1206. }
  1207. void
  1208. ilinit(Fs *f)
  1209. {
  1210. Proto *il;
  1211. inittimescale();
  1212. il = smalloc(sizeof(Proto));
  1213. il->priv = smalloc(sizeof(Ilpriv));
  1214. il->name = "il";
  1215. il->connect = ilconnect;
  1216. il->announce = ilannounce;
  1217. il->state = ilstate;
  1218. il->create = ilcreate;
  1219. il->close = ilclose;
  1220. il->rcv = iliput;
  1221. il->ctl = nil;
  1222. il->advise = iladvise;
  1223. il->stats = ilxstats;
  1224. il->inuse = ilinuse;
  1225. il->gc = nil;
  1226. il->ipproto = IP_ILPROTO;
  1227. il->nc = scalednconv();
  1228. il->ptclsize = sizeof(Ilcb);
  1229. Fsproto(f, il);
  1230. }