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