d2509d959f4890f4e897d2939b926968f2a0cdbb
[akaros.git] / kern / src / net / loopbackmedium.c
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 }