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