2 * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, ETH Zurich.
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.
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>
25 //#define DEBUG(x...) printf("devif_test: " x)
26 #define DEBUG(x...) do {} while (0)
28 #define TX_BUF_SIZE 2048
29 #define RX_BUF_SIZE 2048
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
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;
46 static volatile uint32_t num_tx = 0;
47 static volatile uint32_t num_rx = 0;
53 struct list_ele* first;
54 struct list_ele* last;
64 struct list_ele* next;
68 static struct waitset_chanstate *chan = NULL;
69 static struct waitset card_ws;
72 static uint8_t udp_header[8] = {
73 0x07, 0xD0, 0x07, 0xD0,
74 0x00, 0x80, 0x00, 0x00,
77 static void print_buffer(size_t len, bufferid_t bid)
80 uint8_t* buf = (uint8_t*) va_rx+bid;
81 printf("Packet in region %p at address %p len %zu \n",
83 for (int i = 0; i < len; i++) {
84 if (((i % 10) == 0) && i > 0) {
87 printf("%2X ", buf[i]);
93 static void wait_for_interrupt(void)
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");
101 static void event_cb(void* queue)
103 struct devq* q = (struct devq*) queue;
110 genoffset_t valid_data;
111 genoffset_t valid_length;
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)) {
123 if (flags & NETIF_TXFLAG) {
124 DEBUG("Received TX buffer back \n");
126 } else if (flags & NETIF_RXFLAG) {
128 DEBUG("Received RX buffer \n");
129 print_buffer(valid_length, offset);
131 printf("Unknown flags %lx \n", flags);
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");
141 else if (err_is_fail(err)) {
142 USER_PANIC_ERR(err, "Can't register our dummy channel.");
144 err = waitset_chan_trigger(chan);
145 if (err_is_fail(err)) {
146 USER_PANIC_ERR(err, "trigger failed.");
150 static struct devq* create_net_queue(char* card_name)
153 if (strcmp(card_name, "sfn5122f") == 0) {
154 struct sfn5122f_queue* q;
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");
161 return (struct devq*) q;
164 if (strcmp(card_name, "e10k") == 0) {
165 struct e10k_queue* q;
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");
172 return (struct devq*) q;
175 USER_PANIC("Unknown card name\n");
180 static errval_t destroy_net_queue(struct devq* q, char* card_name)
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");
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");
199 USER_PANIC("Unknown card name\n");
204 static void test_net_tx(void)
213 q = create_net_queue(card);
216 waitset_init(&card_ws);
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);
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.");
227 err = waitset_chan_trigger(chan);
228 if (err_is_fail(err)) {
229 USER_PANIC_ERR(err, "trigger failed.");
232 err = devq_register(q, memory_tx, ®id_tx);
233 if (err_is_fail(err)){
234 USER_PANIC("Registering memory to devq failed \n");
238 // write something into the buffers
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];
246 for (int j = 8; j < TX_BUF_SIZE; j++) {
252 cycles_t t1 = bench_tsc();
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,
258 NETIF_TXFLAG | NETIF_TXFLAG_LAST);
259 if (err_is_fail(err)){
260 USER_PANIC("Devq enqueue failed \n");
265 if ((num_tx < NUM_ENQ)) {
266 wait_for_interrupt();
274 cycles_t t2 = bench_tsc();
275 cycles_t result = (t2 -t1 - bench_tscoverhead());
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;
281 printf("Write throughput %.2f [MB/s] for %.2f ms \n", bw, result_ms);
283 err = devq_control(q, 1, 1, NULL);
284 if (err_is_fail(err)){
285 printf("%s \n", err_getstring(err));
286 USER_PANIC("Devq control failed \n");
289 err = devq_deregister(q, regid_tx, &memory_tx);
290 if (err_is_fail(err)){
291 printf("%s \n", err_getstring(err));
292 USER_PANIC("Devq deregister tx failed \n");
295 err = destroy_net_queue(q, card);
296 if (err_is_fail(err)){
297 printf("%s \n", err_getstring(err));
298 USER_PANIC("Destroying %s queue failed \n", card);
301 printf("SUCCESS: %s tx test ended\n", card);
305 static void test_net_rx(void)
314 q = create_net_queue(card);
317 waitset_init(&card_ws);
319 // MSIX is not working on sfn5122f yet so we have to "simulate interrupts"
320 chan = malloc(sizeof(struct waitset_chanstate));
321 waitset_chanstate_init(chan, CHANTYPE_AHCI);
323 err = waitset_chan_register(&card_ws, chan, MKCLOSURE(event_cb, q));
324 if (err_is_fail(err)) {
325 USER_PANIC_ERR(err, "waitset_chan_regster failed.");
328 err = waitset_chan_trigger(chan);
329 if (err_is_fail(err)) {
330 USER_PANIC_ERR(err, "trigger failed.");
333 err = devq_register(q, memory_rx, ®id_rx);
334 if (err_is_fail(err)){
335 USER_PANIC("Registering memory to devq failed \n");
338 // Enqueue RX buffers to receive into
339 for (int i = 0; i < NUM_ROUNDS_RX; i++){
340 err = devq_enqueue(q, regid_rx, i*RX_BUF_SIZE, RX_BUF_SIZE,
343 if (err_is_fail(err)){
344 USER_PANIC("Devq enqueue failed: %s\n", err_getstring(err));
350 if ((num_rx < NUM_ROUNDS_RX)) {
351 wait_for_interrupt();
358 err = devq_control(q, 1, 1, NULL);
359 if (err_is_fail(err)){
360 printf("%s \n", err_getstring(err));
361 USER_PANIC("Devq control failed \n");
364 err = devq_deregister(q, regid_rx, &memory_rx);
365 if (err_is_fail(err)){
366 printf("%s \n", err_getstring(err));
367 USER_PANIC("Devq deregister rx failed \n");
370 err = destroy_net_queue(q, card);
371 if (err_is_fail(err)){
372 printf("%s \n", err_getstring(err));
373 USER_PANIC("Destroying %s queue failed \n", card);
376 printf("SUCCESS: %s rx test ended\n", card);
380 static errval_t descq_notify(struct descq* q)
382 errval_t err = SYS_ERR_OK;
383 struct devq* queue = (struct devq*) q;
388 genoffset_t valid_data;
389 genoffset_t valid_length;
392 while(err_is_ok(err)) {
393 err = devq_dequeue(queue, &rid, &offset, &length, &valid_data,
394 &valid_length, &flags);
402 static void test_idc_queue(void)
410 struct descq_func_pointer f;
411 f.notify = descq_notify;
413 debug_printf("Descriptor queue test started \n");
414 err = descq_create(&queue, DESCQ_DEFAULT_SIZE, "test_queue",
415 false, true, true, NULL, &f);
416 if (err_is_fail(err)){
417 USER_PANIC("Allocating devq failed \n");
420 q = (struct devq*) queue;
422 err = devq_register(q, memory_rx, ®id_rx);
423 if (err_is_fail(err)){
424 USER_PANIC("Registering memory to devq failed \n");
427 err = devq_register(q, memory_tx, ®id_tx);
428 if (err_is_fail(err)){
429 USER_PANIC("Registering memory to devq failed \n");
432 // Enqueue RX buffers to receive into
433 for (int j = 0; j < 1000000; j++){
434 for (int i = 0; i < 32; i++){
435 err = devq_enqueue(q, regid_rx, i*2048, 2048,
437 if (err_is_fail(err)){
445 err = devq_notify(q);
446 if (err_is_fail(err)) {
447 USER_PANIC("Devq notify failed: %s\n", err_getstring(err));
449 event_dispatch(get_default_waitset());
452 while(num_tx != num_rx) {
453 event_dispatch(get_default_waitset());
456 err = devq_control(q, 1, 1, NULL);
457 if (err_is_fail(err)){
458 printf("%s \n", err_getstring(err));
459 USER_PANIC("Devq control failed \n");
462 err = devq_deregister(q, regid_rx, &memory_rx);
463 if (err_is_fail(err)){
464 printf("%s \n", err_getstring(err));
465 USER_PANIC("Devq deregister rx failed \n");
468 err = devq_deregister(q, regid_tx, &memory_tx);
469 if (err_is_fail(err)){
470 printf("%s \n", err_getstring(err));
471 USER_PANIC("Devq deregister tx failed \n");
474 printf("SUCCESS: IDC queue\n");
477 int main(int argc, char *argv[])
481 err = frame_alloc(&memory_rx, MEMORY_SIZE, NULL);
482 if (err_is_fail(err)){
483 USER_PANIC("Allocating cap failed \n");
486 err = frame_alloc(&memory_tx, MEMORY_SIZE, NULL);
487 if (err_is_fail(err)){
488 USER_PANIC("Allocating cap failed \n");
492 err = invoke_frame_identify(memory_rx, &id);
493 if (err_is_fail(err)) {
494 USER_PANIC("Frame identify failed \n");
497 err = vspace_map_one_frame_attr(&va_rx, id.bytes, memory_rx,
498 VREGION_FLAGS_READ, NULL, NULL);
499 if (err_is_fail(err)) {
500 USER_PANIC("Frame mapping failed \n");
506 err = invoke_frame_identify(memory_tx, &id);
507 if (err_is_fail(err)) {
508 USER_PANIC("Frame identify failed \n");
511 err = vspace_map_one_frame_attr(&va_tx, id.bytes, memory_tx,
512 VREGION_FLAGS_WRITE, NULL, NULL);
513 if (err_is_fail(err)) {
514 USER_PANIC("Frame mapping failed \n");
521 printf("Card =%s \n", card);
526 if (strcmp(argv[1], "net_tx") == 0) {
530 if (strcmp(argv[1], "net_rx") == 0) {
534 if (strcmp(argv[1], "idc") == 0) {
538 barrelfish_usleep(1000*1000*5);