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 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 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 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 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 118 loopbackmediumlink(void) 119 { 120 addipmedium(&loopbackmedium); 121 } 122