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