DeviceQueue: moved networking related flags to include/net_interfaces/flags.h
[barrelfish] / usr / tests / devif / queue_interface.c
1 /*
2  * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, ETH Zurich.
3  * All rights reserved.
4  *
5  * This file is distributed under the terms in the attached LICENSE file.
6  * If you do not find this file, copies can be found by writing to:
7  * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
8  */
9
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <time.h>
13 #include <barrelfish/barrelfish.h>
14 #include <barrelfish/waitset.h>
15 #include <barrelfish/waitset_chan.h>
16 #include <barrelfish/deferred.h>
17 #include <devif/queue_interface.h>
18 #include <devif/backends/net/sfn5122f_devif.h>
19 //#include <devif/backends/net/e10k_devif.h>
20 #include <devif/backends/descq.h>
21 #include <bench/bench.h>
22 #include <net_interfaces/flags.h>
23
24 #define BUF_SIZE 2048
25 #define NUM_ENQ 512
26 #define NUM_RX_BUF 1024
27 #define NUM_ROUNDS_TX 16384
28 #define NUM_ROUNDS_RX 128
29 #define MEMORY_SIZE BASE_PAGE_SIZE*512
30
31 static struct capref memory_rx;
32 static struct capref memory_tx;
33 static regionid_t regid_rx;
34 static regionid_t regid_tx;
35 static struct frame_identity id;
36 static lpaddr_t phys_rx;
37 static lpaddr_t phys_tx;
38
39 static volatile uint32_t num_tx = 0;
40 static volatile uint32_t num_rx = 0;
41
42 static void* va_rx;
43 static void* va_tx;
44
45 struct direct_state {
46     struct list_ele* first;
47     struct list_ele* last;
48 };
49
50 struct list_ele{
51     regionid_t rid;
52     bufferid_t bid;
53     lpaddr_t addr;
54     size_t len;
55     uint64_t flags;
56    
57     struct list_ele* next;
58 };
59
60
61 static struct waitset_chanstate *chan = NULL;
62 static struct waitset card_ws;
63
64
65 static uint8_t udp_header[8] = {
66     0x07, 0xD0, 0x07, 0xD0,
67     0x00, 0x80, 0x00, 0x00,
68 };
69
70 /*
71 static void print_buffer(size_t len, bufferid_t bid)
72 {
73     uint8_t* buf = (uint8_t*) va_rx+bid;
74     printf("Packet in region %p at address %p len %zu \n", 
75             va_rx, buf, len);
76     for (int i = 0; i < len; i++) {
77         if (((i % 10) == 0) && i > 0) {
78             printf("\n");
79         }
80         printf("%2X ", buf[i]);   
81     }
82     printf("\n");
83 }
84 */
85 static void wait_for_interrupt(void)
86 {
87     errval_t err = event_dispatch(&card_ws);
88     if (err_is_fail(err)) {
89         USER_PANIC_ERR(err, "error in event_dispatch for wait_for_interrupt");
90     }
91 }
92
93 static void sfn5122f_event_cb(void* queue)
94 {
95     struct devq* q = (struct devq*) queue;
96
97     errval_t err;
98
99     regionid_t rid;
100     bufferid_t bid;
101     lpaddr_t addr;
102     size_t len;
103     uint64_t flags;
104
105     err = SYS_ERR_OK;
106
107     while (err == SYS_ERR_OK) {    
108         err = devq_dequeue(q, &rid, &addr, &len, &bid, &flags);
109         if (err_is_fail(err)) {
110             break;
111         }
112
113         if (flags & NETIF_TXFLAG) {
114             num_tx++;
115         } else if (flags & NETIF_RXFLAG) {
116             num_rx++;
117             //print_buffer(len, bid);
118         } else {
119             printf("Unknown flags \n");
120         }
121     }
122
123     // MSIX is not working on sfn5122f yet so we have to "simulate interrupts"
124     err = waitset_chan_register(&card_ws, chan, 
125                                 MKCLOSURE(sfn5122f_event_cb, queue));
126     if (err_is_fail(err) && err_no(err) == LIB_ERR_CHAN_ALREADY_REGISTERED) {
127         printf("Got actual interrupt?\n");
128     }
129     else if (err_is_fail(err)) {
130         USER_PANIC_ERR(err, "Can't register our dummy channel.");
131     }
132     err = waitset_chan_trigger(chan);
133     if (err_is_fail(err)) {
134         USER_PANIC_ERR(err, "trigger failed.");
135     }
136 }
137
138 static void test_sfn5122f_tx(void) 
139 {
140     num_tx = 0;
141     num_rx = 0;
142
143     errval_t err;
144     struct devq* q;   
145     struct sfn5122f_queue* queue;
146
147     printf("SFN5122F direct device test started \n");
148     err = sfn5122f_queue_create(&queue, sfn5122f_event_cb, true, false);
149     if (err_is_fail(err)){
150         USER_PANIC("Allocating devq failed \n");
151     }    
152     
153     q = (struct devq*) queue;    
154     
155
156     waitset_init(&card_ws);
157
158     // MSIX is not working on sfn5122f yet so we have to "simulate interrupts"
159     chan = malloc(sizeof(struct waitset_chanstate));
160     waitset_chanstate_init(chan, CHANTYPE_AHCI);
161
162     err = waitset_chan_register(&card_ws, chan, MKCLOSURE(sfn5122f_event_cb, q));
163     if (err_is_fail(err)) {
164         USER_PANIC_ERR(err, "waitset_chan_regster failed.");
165     }
166
167     err = waitset_chan_trigger(chan);
168     if (err_is_fail(err)) {
169         USER_PANIC_ERR(err, "trigger failed.");
170     }
171
172     err = devq_register(q, memory_tx, &regid_tx);
173     if (err_is_fail(err)){
174         USER_PANIC("Registering memory to devq failed \n");
175     }
176     
177     lpaddr_t addr;  
178     bufferid_t bid;
179
180     // write something into the buffers
181     char* write = NULL;
182     uint16_t rest = 4096 -BUF_SIZE;
183
184     for (int i = 0; i < NUM_ENQ; i++) {
185         write = va_tx + i*(BUF_SIZE+rest);
186         for (int j = 0; j < 8; j++) {
187             write[j] = udp_header[j];
188         }
189         for (int j = 8; j < BUF_SIZE; j++) {
190             write[j] = 'a';
191         }
192     }
193
194     // Send something
195     cycles_t t1 = bench_tsc();   
196
197     for (int z = 0; z < NUM_ROUNDS_TX; z++) {
198         for (int i = 0; i < NUM_ENQ; i++) {
199             addr = phys_tx+(i*(BUF_SIZE));
200
201             err = devq_enqueue(q, regid_tx, addr, BUF_SIZE, 
202                                NETIF_TXFLAG | NETIF_TXFLAG_LAST, &bid);
203             if (err_is_fail(err)){
204                 USER_PANIC("Devq enqueue failed \n");
205             }    
206         }
207
208         while(true) {
209             if ((num_tx < NUM_ENQ)) {
210                 wait_for_interrupt();
211             } else {
212                 break;
213             }
214         }
215         num_tx = 0;
216     }
217
218     cycles_t t2 = bench_tsc();
219     cycles_t result = (t2 -t1 - bench_tscoverhead());
220  
221     uint64_t sent_bytes = (uint64_t) BUF_SIZE*NUM_ENQ*NUM_ROUNDS_TX;
222     double result_ms = (double) bench_tsc_to_ms(result);
223     double bw = sent_bytes / result_ms / 1000;
224     
225     printf("Write throughput %.2f [MB/s] for %.2f ms \n", bw, result_ms);  
226
227     err = devq_control(q, 1, 1);
228     if (err_is_fail(err)){
229         printf("%s \n", err_getstring(err));
230         USER_PANIC("Devq control failed \n");
231     }
232
233     err = devq_deregister(q, regid_tx, &memory_tx);
234     if (err_is_fail(err)){
235         printf("%s \n", err_getstring(err));
236         USER_PANIC("Devq deregister tx failed \n");
237     }
238     
239     err = sfn5122f_queue_destroy((struct sfn5122f_queue*) q);
240
241     printf("SUCCESS: SFN5122F tx test ended\n");
242 }
243
244
245 static void test_sfn5122f_rx(void) 
246 {
247     num_tx = 0;
248     num_rx = 0;
249
250     errval_t err;
251     struct devq* q;   
252     struct sfn5122f_queue* queue;
253
254     printf("SFN5122F direct device test started \n");
255     err = sfn5122f_queue_create(&queue, sfn5122f_event_cb, /* userlevel*/ true, 
256                                 /*MSIX interrupts*/ false);
257     if (err_is_fail(err)){
258         USER_PANIC("Allocating devq failed \n");
259     }    
260     
261     q = (struct devq*) queue;    
262     
263
264     waitset_init(&card_ws);
265
266     // MSIX is not working on sfn5122f yet so we have to "simulate interrupts"
267     chan = malloc(sizeof(struct waitset_chanstate));
268     waitset_chanstate_init(chan, CHANTYPE_AHCI);
269
270     err = waitset_chan_register(&card_ws, chan, MKCLOSURE(sfn5122f_event_cb, q));
271     if (err_is_fail(err)) {
272         USER_PANIC_ERR(err, "waitset_chan_regster failed.");
273     }
274
275     err = waitset_chan_trigger(chan);
276     if (err_is_fail(err)) {
277         USER_PANIC_ERR(err, "trigger failed.");
278     }
279
280     err = devq_register(q, memory_rx, &regid_rx);
281     if (err_is_fail(err)){
282         USER_PANIC("Registering memory to devq failed \n");
283     }
284     
285     lpaddr_t addr;  
286     bufferid_t bid;
287
288     // Enqueue RX buffers to receive into
289     for (int i = 0; i < NUM_ROUNDS_RX; i++){
290         addr = phys_rx+(i*2048);
291         err = devq_enqueue(q, regid_rx, addr, 2048, 
292                            NETIF_RXFLAG, &bid);
293         if (err_is_fail(err)){
294             USER_PANIC("Devq enqueue failed: %s\n", err_getstring(err));
295         }    
296
297     }
298
299     while (true) {
300         if ((num_rx < NUM_ROUNDS_RX)) {
301             wait_for_interrupt();
302         } else {
303             break;
304         }
305     }
306
307
308     err = devq_control(q, 1, 1);
309     if (err_is_fail(err)){
310         printf("%s \n", err_getstring(err));
311         USER_PANIC("Devq control failed \n");
312     }
313
314     err = devq_deregister(q, regid_rx, &memory_rx);
315     if (err_is_fail(err)){
316         printf("%s \n", err_getstring(err));
317         USER_PANIC("Devq deregister rx failed \n");
318     }
319    
320     err = sfn5122f_queue_destroy((struct sfn5122f_queue*) q);
321
322     printf("SUCCESS: SFN5122F rx test ended\n");
323 }
324
325
326 static errval_t descq_notify(struct descq* q) 
327 {   
328     errval_t err = SYS_ERR_OK;
329     struct devq* queue = (struct devq*) q;
330     
331     regionid_t rid;
332     bufferid_t bid;
333     lpaddr_t addr;
334     uint64_t flags;
335     size_t len;
336
337     while(err_is_ok(err)) {
338         err = devq_dequeue(queue, &rid, &addr, &len, &bid, &flags);
339         if (err_is_ok(err)){
340             num_rx++;
341         }
342     }
343     return SYS_ERR_OK;
344 }
345
346 static void test_idc_queue(void)
347 {
348     num_tx = 0;
349     num_rx = 0;
350
351     errval_t err;
352     struct devq* q;   
353     struct descq* queue;
354     struct descq_func_pointer* f;
355     f = malloc(sizeof(struct descq_func_pointer));
356     f->notify = descq_notify;
357
358     printf("Descriptor queue test started \n");
359     err = descq_create(&queue, DESCQ_DEFAULT_SIZE, "test_queue",
360                        false, f);
361     if (err_is_fail(err)){
362         USER_PANIC("Allocating devq failed \n");
363     }    
364    
365     q = (struct devq*) queue;    
366
367     err = devq_register(q, memory_rx, &regid_rx);
368     if (err_is_fail(err)){
369         USER_PANIC("Registering memory to devq failed \n");
370     }
371   
372     err = devq_register(q, memory_tx, &regid_tx);
373     if (err_is_fail(err)){
374         USER_PANIC("Registering memory to devq failed \n");
375     }
376  
377     lpaddr_t addr;
378     bufferid_t bid;
379     // Enqueue RX buffers to receive into
380     for (int j = 0; j < 1000000; j++){
381         for (int i = 0; i < 32; i++){
382             addr = phys_rx+(i*2048);
383             err = devq_enqueue(q, regid_rx, addr, 2048, 
384                                0, &bid);
385             if (err_is_fail(err)){
386                 // retry
387                 i--;
388             } else {
389                 num_tx++;
390             }
391         }
392
393         err = devq_notify(q);
394         if (err_is_fail(err)) {
395                 USER_PANIC("Devq notify failed: %s\n", err_getstring(err));
396         }
397         event_dispatch(get_default_waitset());
398     }    
399
400     while(num_tx != num_rx) {
401         event_dispatch(get_default_waitset());
402     }
403
404     err = devq_control(q, 1, 1);
405     if (err_is_fail(err)){
406         printf("%s \n", err_getstring(err));
407         USER_PANIC("Devq control failed \n");
408     }
409
410     err = devq_deregister(q, regid_rx, &memory_rx);
411     if (err_is_fail(err)){
412         printf("%s \n", err_getstring(err));
413         USER_PANIC("Devq deregister rx failed \n");
414     }
415
416     err = devq_deregister(q, regid_tx, &memory_tx);
417     if (err_is_fail(err)){
418         printf("%s \n", err_getstring(err));
419         USER_PANIC("Devq deregister tx failed \n");
420     }
421
422     printf("SUCCESS: IDC queue\n");
423 }
424
425
426 #if 0
427 static void e10k_event_cb(void* queue)
428 {
429     return;
430 }
431
432 static void test_e10k_queue(void) 
433 {
434     num_tx = 0;
435     num_rx = 0;
436
437     errval_t err;
438     struct devq* q;   
439     struct e10k_queue* queue;
440
441     printf("e10k test started \n");
442     err = e10k_queue_create(&queue, e10k_event_cb, /* interrupts*/ false, 
443                             /* RSC*/false);
444     if (err_is_fail(err)){
445         USER_PANIC("Allocating devq failed \n");
446     }    
447     
448     q = (struct devq*) queue;    
449  
450        
451     printf("e10k test endned \n");
452 }
453 #endif
454
455 int main(int argc, char *argv[])
456 {
457     errval_t err;
458     // Allocate memory
459     err = frame_alloc(&memory_rx, MEMORY_SIZE, NULL);
460     if (err_is_fail(err)){
461         USER_PANIC("Allocating cap failed \n");
462     }    
463
464     err = frame_alloc(&memory_tx, MEMORY_SIZE, NULL);
465     if (err_is_fail(err)){
466         USER_PANIC("Allocating cap failed \n");
467     }    
468     
469     // RX frame
470     err = invoke_frame_identify(memory_rx, &id);
471     if (err_is_fail(err)) {
472         USER_PANIC("Frame identify failed \n");
473     }
474
475     err = vspace_map_one_frame_attr(&va_rx, MEMORY_SIZE, memory_rx,
476                                     VREGION_FLAGS_READ, NULL, NULL); 
477     if (err_is_fail(err)) {
478         USER_PANIC("Frame mapping failed \n");
479     }
480
481     phys_rx = id.base;
482
483     // TX Frame
484     err = invoke_frame_identify(memory_tx, &id);
485     if (err_is_fail(err)) {
486         USER_PANIC("Frame identify failed \n");
487     }
488    
489     err = vspace_map_one_frame_attr(&va_tx, MEMORY_SIZE, memory_tx,
490                                     VREGION_FLAGS_WRITE, NULL, NULL); 
491     if (err_is_fail(err)) {
492         USER_PANIC("Frame mapping failed \n");
493     }
494
495     phys_tx = id.base;
496
497     if (strcmp(argv[1], "net_tx") == 0) {
498         test_sfn5122f_tx();
499     }
500
501     if (strcmp(argv[1], "net_rx") == 0) {
502         test_sfn5122f_rx();
503     }
504
505     if (strcmp(argv[1], "idc") == 0) {
506         test_idc_queue();
507     }
508     
509     /*
510     if (strcmp(argv[1], "e10k") == 0) {
511         test_e10k_queue();
512     }
513     */
514     barrelfish_usleep(1000*1000*5);
515 }
516