Implement TSO
[akaros.git] / kern / src / net / loopbackmedium.c
1 // INFERNO
2 #include <vfs.h>
3 #include <kfs.h>
4 #include <slab.h>
5 #include <kmalloc.h>
6 #include <kref.h>
7 #include <string.h>
8 #include <stdio.h>
9 #include <assert.h>
10 #include <error.h>
11 #include <cpio.h>
12 #include <pmap.h>
13 #include <smp.h>
14 #include <ip.h>
15
16 enum {
17         Maxtu = 16 * 1024,
18 };
19
20 typedef struct LB LB;
21 struct LB {
22         struct proc *readp;
23         struct queue *q;
24         struct Fs *f;
25 };
26
27 static void loopbackread(void *a);
28
29 static void
30 loopbackbind(struct Ipifc *ifc, int unused_int, char **unused_char_pp_t)
31 {
32         LB *lb;
33
34         lb = kzmalloc(sizeof(*lb), 0);
35         lb->f = ifc->conv->p->f;
36         /* TO DO: make queue size a function of kernel memory */
37         lb->q = qopen(128 * 1024, Qmsg, NULL, NULL);
38         ifc->arg = lb;
39         ifc->mbps = 1000;
40
41         ktask("loopbackread", loopbackread, ifc);
42
43 }
44
45 static void loopbackunbind(struct Ipifc *ifc)
46 {
47         LB *lb = ifc->arg;
48
49         printk("%s is messed up, shouldn't track procs\n", __FUNCTION__);
50
51         /*if(lb->readp)
52            postnote(lb->readp, 1, "unbind", 0);
53          */
54
55         /* wait for reader to die */
56         while (lb->readp != 0)
57                 udelay_sched(300 * 1000);
58
59         /* clean up */
60         qfree(lb->q);
61         kfree(lb);
62 }
63
64 static void
65 loopbackbwrite(struct Ipifc *ifc, struct block *bp, int unused_int,
66                            uint8_t * unused_uint8_p_t)
67 {
68         LB *lb;
69
70         lb = ifc->arg;
71         if (qpass(lb->q, bp) < 0)
72                 ifc->outerr++;
73         ifc->out++;
74 }
75
76 static void loopbackread(void *a)
77 {
78         ERRSTACK(2);
79         struct Ipifc *ifc;
80         struct block *bp;
81         LB *lb;
82
83         ifc = a;
84         lb = ifc->arg;
85         lb->readp = current;    /* hide identity under a rock for unbind */
86         if (waserror()) {
87                 lb->readp = 0;
88                 warn("loopbackread exits unexpectedly");
89                 return;
90                 poperror();
91         }
92         for (;;) {
93                 bp = qbread(lb->q, Maxtu);
94                 if (bp == NULL)
95                         continue;
96                 ifc->in++;
97                 if (!canrlock(&ifc->rwlock)) {
98                         freeb(bp);
99                         continue;
100                 }
101                 if (waserror()) {
102                         runlock(&ifc->rwlock);
103                         nexterror();
104                 }
105                 if (ifc->lifc == NULL)
106                         freeb(bp);
107                 else
108                         ipiput4(lb->f, ifc, bp);
109                 runlock(&ifc->rwlock);
110                 poperror();
111         }
112         poperror();
113 }
114
115 struct medium loopbackmedium = {
116         .hsize = 0,
117         .mintu = 0,
118         .maxtu = Maxtu,
119         .maclen = 0,
120         .name = "loopback",
121         .bind = loopbackbind,
122         .unbind = loopbackunbind,
123         .bwrite = loopbackbwrite,
124 };
125
126 linker_func_4(loopbackmediumlink)
127 {
128         addipmedium(&loopbackmedium);
129 }