174a4d8c2SCharles.Forsyth #include "u.h"
274a4d8c2SCharles.Forsyth #include "../port/lib.h"
374a4d8c2SCharles.Forsyth #include "mem.h"
474a4d8c2SCharles.Forsyth #include "dat.h"
574a4d8c2SCharles.Forsyth #include "fns.h"
674a4d8c2SCharles.Forsyth #include "../port/error.h"
774a4d8c2SCharles.Forsyth
874a4d8c2SCharles.Forsyth #include "ip.h"
974a4d8c2SCharles.Forsyth
1074a4d8c2SCharles.Forsyth enum
1174a4d8c2SCharles.Forsyth {
1274a4d8c2SCharles.Forsyth Maxtu= 16*1024,
1374a4d8c2SCharles.Forsyth };
1474a4d8c2SCharles.Forsyth
1574a4d8c2SCharles.Forsyth typedef struct LB LB;
1674a4d8c2SCharles.Forsyth struct LB
1774a4d8c2SCharles.Forsyth {
1874a4d8c2SCharles.Forsyth Proc *readp;
1974a4d8c2SCharles.Forsyth Queue *q;
2074a4d8c2SCharles.Forsyth Fs *f;
2174a4d8c2SCharles.Forsyth };
2274a4d8c2SCharles.Forsyth
2374a4d8c2SCharles.Forsyth static void loopbackread(void *a);
2474a4d8c2SCharles.Forsyth
2574a4d8c2SCharles.Forsyth static void
loopbackbind(Ipifc * ifc,int,char **)2674a4d8c2SCharles.Forsyth loopbackbind(Ipifc *ifc, int, char**)
2774a4d8c2SCharles.Forsyth {
2874a4d8c2SCharles.Forsyth LB *lb;
2974a4d8c2SCharles.Forsyth
3074a4d8c2SCharles.Forsyth lb = smalloc(sizeof(*lb));
3174a4d8c2SCharles.Forsyth lb->f = ifc->conv->p->f;
3274a4d8c2SCharles.Forsyth /* TO DO: make queue size a function of kernel memory */
3374a4d8c2SCharles.Forsyth lb->q = qopen(128*1024, Qmsg, nil, nil);
3474a4d8c2SCharles.Forsyth ifc->arg = lb;
3574a4d8c2SCharles.Forsyth ifc->mbps = 1000;
3674a4d8c2SCharles.Forsyth
37*6e425a9dSCharles.Forsyth kproc("loopbackread", loopbackread, ifc, 0);
3874a4d8c2SCharles.Forsyth
3974a4d8c2SCharles.Forsyth }
4074a4d8c2SCharles.Forsyth
4174a4d8c2SCharles.Forsyth static void
loopbackunbind(Ipifc * ifc)4274a4d8c2SCharles.Forsyth loopbackunbind(Ipifc *ifc)
4374a4d8c2SCharles.Forsyth {
4474a4d8c2SCharles.Forsyth LB *lb = ifc->arg;
4574a4d8c2SCharles.Forsyth
4674a4d8c2SCharles.Forsyth if(lb->readp)
4774a4d8c2SCharles.Forsyth postnote(lb->readp, 1, "unbind", 0);
4874a4d8c2SCharles.Forsyth
4974a4d8c2SCharles.Forsyth /* wait for reader to die */
5074a4d8c2SCharles.Forsyth while(lb->readp != 0)
5174a4d8c2SCharles.Forsyth tsleep(&up->sleep, return0, 0, 300);
5274a4d8c2SCharles.Forsyth
5374a4d8c2SCharles.Forsyth /* clean up */
5474a4d8c2SCharles.Forsyth qfree(lb->q);
5574a4d8c2SCharles.Forsyth free(lb);
5674a4d8c2SCharles.Forsyth }
5774a4d8c2SCharles.Forsyth
5874a4d8c2SCharles.Forsyth static void
loopbackbwrite(Ipifc * ifc,Block * bp,int,uchar *)5974a4d8c2SCharles.Forsyth loopbackbwrite(Ipifc *ifc, Block *bp, int, uchar*)
6074a4d8c2SCharles.Forsyth {
6174a4d8c2SCharles.Forsyth LB *lb;
6274a4d8c2SCharles.Forsyth
6374a4d8c2SCharles.Forsyth lb = ifc->arg;
6474a4d8c2SCharles.Forsyth if(qpass(lb->q, bp) < 0)
6574a4d8c2SCharles.Forsyth ifc->outerr++;
6674a4d8c2SCharles.Forsyth ifc->out++;
6774a4d8c2SCharles.Forsyth }
6874a4d8c2SCharles.Forsyth
6974a4d8c2SCharles.Forsyth static void
loopbackread(void * a)7074a4d8c2SCharles.Forsyth loopbackread(void *a)
7174a4d8c2SCharles.Forsyth {
7274a4d8c2SCharles.Forsyth Ipifc *ifc;
7374a4d8c2SCharles.Forsyth Block *bp;
7474a4d8c2SCharles.Forsyth LB *lb;
7574a4d8c2SCharles.Forsyth
7674a4d8c2SCharles.Forsyth ifc = a;
7774a4d8c2SCharles.Forsyth lb = ifc->arg;
7874a4d8c2SCharles.Forsyth lb->readp = up; /* hide identity under a rock for unbind */
7974a4d8c2SCharles.Forsyth if(waserror()){
8074a4d8c2SCharles.Forsyth lb->readp = 0;
8174a4d8c2SCharles.Forsyth pexit("hangup", 1);
8274a4d8c2SCharles.Forsyth }
8374a4d8c2SCharles.Forsyth for(;;){
8474a4d8c2SCharles.Forsyth bp = qbread(lb->q, Maxtu);
8574a4d8c2SCharles.Forsyth if(bp == nil)
8674a4d8c2SCharles.Forsyth continue;
8774a4d8c2SCharles.Forsyth ifc->in++;
8874a4d8c2SCharles.Forsyth if(!canrlock(ifc)){
8974a4d8c2SCharles.Forsyth freeb(bp);
9074a4d8c2SCharles.Forsyth continue;
9174a4d8c2SCharles.Forsyth }
9274a4d8c2SCharles.Forsyth if(waserror()){
9374a4d8c2SCharles.Forsyth runlock(ifc);
9474a4d8c2SCharles.Forsyth nexterror();
9574a4d8c2SCharles.Forsyth }
9674a4d8c2SCharles.Forsyth if(ifc->lifc == nil)
9774a4d8c2SCharles.Forsyth freeb(bp);
9874a4d8c2SCharles.Forsyth else
9974a4d8c2SCharles.Forsyth ipiput4(lb->f, ifc, bp);
10074a4d8c2SCharles.Forsyth runlock(ifc);
10174a4d8c2SCharles.Forsyth poperror();
10274a4d8c2SCharles.Forsyth }
10374a4d8c2SCharles.Forsyth }
10474a4d8c2SCharles.Forsyth
10574a4d8c2SCharles.Forsyth Medium loopbackmedium =
10674a4d8c2SCharles.Forsyth {
10774a4d8c2SCharles.Forsyth .hsize= 0,
10874a4d8c2SCharles.Forsyth .mintu= 0,
10974a4d8c2SCharles.Forsyth .maxtu= Maxtu,
11074a4d8c2SCharles.Forsyth .maclen= 0,
11174a4d8c2SCharles.Forsyth .name= "loopback",
11274a4d8c2SCharles.Forsyth .bind= loopbackbind,
11374a4d8c2SCharles.Forsyth .unbind= loopbackunbind,
11474a4d8c2SCharles.Forsyth .bwrite= loopbackbwrite,
11574a4d8c2SCharles.Forsyth };
11674a4d8c2SCharles.Forsyth
11774a4d8c2SCharles.Forsyth void
loopbackmediumlink(void)11874a4d8c2SCharles.Forsyth loopbackmediumlink(void)
11974a4d8c2SCharles.Forsyth {
12074a4d8c2SCharles.Forsyth addipmedium(&loopbackmedium);
12174a4d8c2SCharles.Forsyth }
122