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
8 #include "ip.h"
9
10 enum
11 {
12 Maxtu= 16*1024,
13 };
14
15 typedef struct LB LB;
16 struct LB
17 {
18 Proc *readp;
19 Queue *q;
20 Fs *f;
21 };
22
23 static void loopbackread(void *a);
24
25 static void
loopbackbind(Ipifc * ifc,int,char **)26 loopbackbind(Ipifc *ifc, int, char**)
27 {
28 LB *lb;
29
30 lb = smalloc(sizeof(*lb));
31 lb->f = ifc->conv->p->f;
32 /* TO DO: make queue size a function of kernel memory */
33 lb->q = qopen(128*1024, Qmsg, nil, nil);
34 ifc->arg = lb;
35 ifc->mbps = 1000;
36
37 kproc("loopbackread", loopbackread, ifc, 0);
38
39 }
40
41 static void
loopbackunbind(Ipifc * ifc)42 loopbackunbind(Ipifc *ifc)
43 {
44 LB *lb = ifc->arg;
45
46 if(lb->readp)
47 postnote(lb->readp, 1, "unbind", 0);
48
49 /* wait for reader to die */
50 while(lb->readp != 0)
51 tsleep(&up->sleep, return0, 0, 300);
52
53 /* clean up */
54 qfree(lb->q);
55 free(lb);
56 }
57
58 static void
loopbackbwrite(Ipifc * ifc,Block * bp,int,uchar *)59 loopbackbwrite(Ipifc *ifc, Block *bp, int, uchar*)
60 {
61 LB *lb;
62
63 lb = ifc->arg;
64 if(qpass(lb->q, bp) < 0)
65 ifc->outerr++;
66 ifc->out++;
67 }
68
69 static void
loopbackread(void * a)70 loopbackread(void *a)
71 {
72 Ipifc *ifc;
73 Block *bp;
74 LB *lb;
75
76 ifc = a;
77 lb = ifc->arg;
78 lb->readp = up; /* hide identity under a rock for unbind */
79 if(waserror()){
80 lb->readp = 0;
81 pexit("hangup", 1);
82 }
83 for(;;){
84 bp = qbread(lb->q, Maxtu);
85 if(bp == nil)
86 continue;
87 ifc->in++;
88 if(!canrlock(ifc)){
89 freeb(bp);
90 continue;
91 }
92 if(waserror()){
93 runlock(ifc);
94 nexterror();
95 }
96 if(ifc->lifc == nil)
97 freeb(bp);
98 else
99 ipiput4(lb->f, ifc, bp);
100 runlock(ifc);
101 poperror();
102 }
103 }
104
105 Medium loopbackmedium =
106 {
107 .hsize= 0,
108 .mintu= 0,
109 .maxtu= Maxtu,
110 .maclen= 0,
111 .name= "loopback",
112 .bind= loopbackbind,
113 .unbind= loopbackunbind,
114 .bwrite= loopbackbwrite,
115 };
116
117 void
loopbackmediumlink(void)118 loopbackmediumlink(void)
119 {
120 addipmedium(&loopbackmedium);
121 }
122