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, Universitaetstrasse 6, 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/debug.h> 21#include <devif/backends/descq.h> 22#include <devif/backends/null.h> 23#include <bench/bench.h> 24#include <net_interfaces/flags.h> 25 26//#define BENCH 27 28//#define DEBUG(x...) printf("devif_test: " x) 29#define DEBUG(x...) do {} while (0) 30 31#define BUF_SIZE 2048 32#define NUM_BUFS 128 33#define MEMORY_SIZE BUF_SIZE*NUM_BUFS 34 35static struct capref memory; 36static regionid_t regid; 37static struct frame_identity id; 38static lpaddr_t phys; 39 40static volatile uint32_t num_tx = 0; 41static volatile uint32_t num_rx = 0; 42 43static void* va; 44 45struct direct_state { 46 struct list_ele* first; 47 struct list_ele* last; 48}; 49 50struct 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 60static struct descq* queue; 61static struct debug_q* debug_q; 62static struct null_q* null_q; 63static struct devq* que; 64 65static volatile bool enq[NUM_BUFS]; 66 67#ifdef BENCH 68static uint64_t tot_deq = 0; 69static uint64_t tot_enq = 0; 70static uint64_t tot_notify = 0; 71static uint64_t start_enq = 0, end_enq = 0; 72static uint64_t start_deq = 0, end_deq = 0; 73static uint64_t start_not = 0, end_not = 0; 74 75static double avg_deq, avg_enq, avg_not; 76static double avg_deq_d, avg_enq_d, avg_not_d; 77static double avg_deq_n, avg_enq_n, avg_not_n; 78#endif 79 80 81static errval_t descq_notify(struct descq* q) 82{ 83 errval_t err = SYS_ERR_OK; 84 85 regionid_t rid; 86 genoffset_t offset; 87 genoffset_t length; 88 genoffset_t valid_data; 89 genoffset_t valid_length; 90 uint64_t flags; 91 92 while(err_is_ok(err)) { 93 94#ifdef BENCH 95 start_deq = rdtsc(); 96#endif 97 err = devq_dequeue(que, &rid, &offset, &length, &valid_data, 98 &valid_length, &flags); 99 if (err_is_ok(err)){ 100#ifdef BENCH 101 end_deq = rdtsc(); 102 tot_deq += end_deq - start_deq; 103#endif 104 num_rx++; 105 enq[offset/BUF_SIZE] = false; 106 } 107 } 108 return SYS_ERR_OK; 109} 110 111#define NUM_REGIONS 128 112 113#define NUM_ROUNDS 1000000 114 115static void test_register(void) 116{ 117 errval_t err; 118 struct capref regions[NUM_REGIONS]; 119 regionid_t rids[NUM_REGIONS]; 120 bool is_reg[NUM_REGIONS]; 121 122 for (int i = 0; i < NUM_REGIONS; i++) { 123 err = frame_alloc(®ions[i], BASE_PAGE_SIZE, NULL); 124 if (err_is_fail(err)){ 125 USER_PANIC("Allocating cap failed \n"); 126 } 127 is_reg[i] = false; 128 } 129 130 srand(rdtsc()); 131 int idx = 0; 132 struct capref ret; 133 for (int i = 0; i < NUM_ROUNDS/10; i++) { 134 idx = rand() % NUM_REGIONS; 135 if (is_reg[idx]) { 136 err = devq_deregister(que, rids[idx], &ret); 137 if (err_is_fail(err)){ 138 USER_PANIC("Registering memory to devq failed: %s\n", 139 err_getstring(err)); 140 } 141 is_reg[idx] = false; 142 } else { 143 err = devq_register(que, regions[idx], &rids[idx]); 144 if (err_is_fail(err)){ 145 USER_PANIC("Registering memory to devq failed: %s \n", 146 err_getstring(err)); 147 } 148 is_reg[idx] = true; 149 } 150 } 151 152 for (int i = 0; i < NUM_REGIONS; i++) { 153 if (is_reg[i]) { 154 err = devq_deregister(que, rids[i], &ret); 155 if (err_is_fail(err)){ 156 USER_PANIC("Registering memory to devq failed: %s\n", 157 err_getstring(err)); 158 } 159 } 160 } 161} 162 163static void test_enqueue_dequeue(void) 164{ 165 errval_t err; 166 num_tx = 0; 167 num_rx = 0; 168 // enqueue from the beginning of the region 169 for (int i = 0; i < NUM_BUFS/8; i++) { 170 err = devq_enqueue(que, regid, i*BUF_SIZE, BUF_SIZE, 171 0, BUF_SIZE, 0); 172 if (err_is_fail(err)){ 173 USER_PANIC("Enqueue failed: %s \n", err_getstring(err)); 174 } else { 175 num_tx++; 176 } 177 } 178 179 180 // enqueue from the end of the region 181 for (int i = 0; i < NUM_BUFS/8; i++) { 182 err = devq_enqueue(que, regid, MEMORY_SIZE-((i+1)*BUF_SIZE), 183 BUF_SIZE, 0, BUF_SIZE, 0); 184 if (err_is_fail(err)){ 185 USER_PANIC("Enqueue failed: %s \n", err_getstring(err)); 186 } else { 187 num_tx++; 188 } 189 } 190 191 err = devq_notify(que); 192 if (err_is_fail(err)) { 193 USER_PANIC("Devq notify failed: %s\n", err_getstring(err)); 194 } 195 196 while(num_rx < (NUM_BUFS/4)) { 197 event_dispatch(get_default_waitset()); 198 } 199} 200 201 202static void test_failures(void) 203{ 204 errval_t err; 205 num_tx = 0; 206 num_rx = 0; 207 208 209 err = devq_enqueue(que, regid, 0, BUF_SIZE, 210 0, BUF_SIZE, 0); 211 if (err_is_fail(err)) { 212 USER_PANIC("Enqueue failed: %s \n", err_getstring(err)); 213 } 214 215 // do the same enqueue again 216 217 err = devq_enqueue(que, regid, 0, BUF_SIZE, 218 0, BUF_SIZE, 0); 219 if (err_is_ok(err)) { 220 USER_PANIC("Enqueue should fail! \n"); 221 } 222 223 // revert to original state 224 err = devq_notify(que); 225 if (err_is_fail(err)) { 226 USER_PANIC("Enqueue failed: %s \n", err_getstring(err)); 227 } 228 229 while(num_rx < 1) { 230 event_dispatch(get_default_waitset()); 231 } 232 233 err = devq_enqueue(que, regid, 4096, BUF_SIZE, 234 0, BUF_SIZE, 0); 235 if (err_is_fail(err)) { 236 USER_PANIC("Enqueue failed: %s \n", err_getstring(err)); 237 } 238 239 // do an overlapping enqueue 240 err = devq_enqueue(que, regid, 5120, BUF_SIZE, 241 0, BUF_SIZE, 0); 242 if (err_is_ok(err)) { 243 USER_PANIC("Enqueue should fail! \n"); 244 } 245 246 // revert to original state 247 err = devq_notify(que); 248 if (err_is_fail(err)) { 249 USER_PANIC("Enqueue failed: %s \n", err_getstring(err)); 250 } 251 252 while(num_rx < 2) { 253 event_dispatch(get_default_waitset()); 254 } 255 256 // enqueue buffer not in region 257 err = devq_enqueue(que, regid, MEMORY_SIZE+BUF_SIZE, BUF_SIZE, 258 0, BUF_SIZE, 0); 259 if (err_is_ok(err)) { 260 USER_PANIC("Enqueue should fail! \n"); 261 } 262 263} 264 265 266static void test_randomized_test(void) 267{ 268 errval_t err; 269 num_tx = 0; 270 num_rx = 0; 271 memset((void*)enq, 0, sizeof(bool)*NUM_BUFS); 272 273#ifdef BENCH 274 tot_enq = 0; 275 tot_deq = 0; 276 tot_notify = 0; 277#endif 278 279 for (int i = 0; i < NUM_BUFS; i++) { 280 enq[i] = false; 281 } 282 283 srand(rdtsc()); 284 int idx = 0; 285 // enqueue from the beginning of the region 286 for (int i = 0; i < NUM_ROUNDS; i++) { 287 for (int j = 0; j < NUM_BUFS/2; j++) { 288 idx = rand() % NUM_BUFS; 289 while (enq[idx]) { 290 idx = rand() % NUM_BUFS; 291 } 292 293#ifdef BENCH 294 start_enq = rdtsc(); 295#endif 296 err = devq_enqueue(que, regid, idx*BUF_SIZE, BUF_SIZE, 297 0, BUF_SIZE, 0); 298 if (err_is_fail(err)){ 299 USER_PANIC("Enqueue failed: %s \n", err_getstring(err)); 300 } else { 301#ifdef BENCH 302 end_enq = rdtsc(); 303 tot_enq += end_enq - start_enq; 304#endif 305 enq[idx] = true; 306 num_tx++; 307 } 308 } 309 310 if ((i % 100000) == 0) { 311 printf("Round %d \n", i); 312 } 313 314#ifdef BENCH 315 start_not = rdtsc(); 316#endif 317 err = devq_notify(que); 318 if (err_is_fail(err)) { 319 USER_PANIC("Devq notify failed: %s\n", err_getstring(err)); 320 } 321#ifdef BENCH 322 end_not = rdtsc(); 323 tot_notify += end_not - start_not; 324#endif 325 while(num_rx < ((i+1)*NUM_BUFS/2)) { 326 event_dispatch(get_default_waitset()); 327 } 328 } 329 330} 331 332int main(int argc, char *argv[]) 333{ 334 errval_t err; 335 // Allocate memory 336 err = frame_alloc(&memory, MEMORY_SIZE, NULL); 337 if (err_is_fail(err)){ 338 USER_PANIC("Allocating cap failed \n"); 339 } 340 341 // RX frame 342 err = frame_identify(memory, &id); 343 if (err_is_fail(err)) { 344 USER_PANIC("Frame identify failed \n"); 345 } 346 347 err = vspace_map_one_frame_attr(&va, id.bytes, memory, 348 VREGION_FLAGS_READ, NULL, NULL); 349 if (err_is_fail(err)) { 350 USER_PANIC("Frame mapping failed \n"); 351 } 352 353 phys = id.base; 354 355 struct descq_func_pointer f; 356 f.notify = descq_notify; 357 358 debug_printf("Descriptor queue test started \n"); 359 err = descq_create(&queue, DESCQ_DEFAULT_SIZE, "test_queue", 360 false, NULL, &f); 361 if (err_is_fail(err)){ 362 USER_PANIC("Allocating devq failed \n"); 363 } 364 365 // stack debug queue on top 366 err = debug_create(&debug_q, (struct devq*) queue); 367 if (err_is_fail(err)) { 368 USER_PANIC("Allocating debug q failed \n"); 369 } 370 371 // stack null queue on top 372 err = null_create(&null_q, (struct devq*) debug_q); 373 if (err_is_fail(err)) { 374 USER_PANIC("Allocating null q failed \n"); 375 } 376 377 que = (struct devq*) debug_q; 378 379 err = devq_register(que, memory, ®id); 380 if (err_is_fail(err)){ 381 USER_PANIC("Registering memory to devq failed \n"); 382 } 383 384 printf("Starting failure handling test \n"); 385 test_failures(); 386 387 printf("Starting register/deregister test \n"); 388 test_register(); 389 390 printf("Starting enqueue/dequeue test \n"); 391 test_enqueue_dequeue(); 392 393 printf("Starting randomized test debug\n"); 394 que = (struct devq*) debug_q; 395 test_randomized_test(); 396 397#ifdef BENCH 398 avg_enq_d = ((double) tot_deq)/(NUM_ROUNDS*NUM_BUFS/2); 399 avg_deq_d = ((double) tot_enq)/(NUM_ROUNDS*NUM_BUFS/2); 400 avg_not_d = ((double) tot_notify)/NUM_ROUNDS; 401 402 printf("AVG deq debug %f \n", avg_enq_d); 403 printf("AVG enq debug %f \n", avg_deq_d); 404 printf("AVG notify debug %f \n", avg_not_d); 405 printf("############################################################ \n"); 406 407 408 err = devq_deregister(que, regid, &memory); 409 if (err_is_fail(err)){ 410 USER_PANIC("Deregistering memory from devq failed: %s \n", 411 err_getstring(err)); 412 } 413 414 printf("Starting randomized test non debug\n"); 415 que = (struct devq*) queue; 416 417 err = devq_register(que, memory, ®id); 418 if (err_is_fail(err)){ 419 USER_PANIC("Registering memory to devq failed \n"); 420 } 421 422 test_randomized_test(); 423 424 avg_enq = ((double) tot_deq)/(NUM_ROUNDS*NUM_BUFS/2); 425 avg_deq = ((double) tot_enq)/(NUM_ROUNDS*NUM_BUFS/2); 426 avg_not = ((double) tot_notify)/NUM_ROUNDS; 427 428 printf("AVG deq %f \n", avg_enq); 429 printf("AVG enq %f \n", avg_deq); 430 printf("AVG notify %f \n", avg_not); 431 printf("############################################################ \n"); 432 433 err = devq_deregister(que, regid, &memory); 434 if (err_is_fail(err)){ 435 USER_PANIC("Deregistering memory from devq failed: %s \n", 436 err_getstring(err)); 437 } 438 439 printf("Starting randomized test debug + null\n"); 440 que = (struct devq*) null_q; 441 442 err = devq_register(que, memory, ®id); 443 if (err_is_fail(err)){ 444 USER_PANIC("Registering memory to devq failed \n"); 445 } 446 447 test_randomized_test(); 448 449 avg_enq_n = ((double) tot_deq)/(NUM_ROUNDS*NUM_BUFS/2); 450 avg_deq_n = ((double) tot_enq)/(NUM_ROUNDS*NUM_BUFS/2); 451 avg_not_n = ((double) tot_notify)/NUM_ROUNDS; 452 453 printf("AVG deq debug + null %f \n", avg_enq_n); 454 printf("AVG enq debug + null %f \n", avg_deq_n); 455 printf("AVG notify debug + null %f \n", avg_not_n); 456 457 printf("############################################################ \n"); 458 459 printf("AVG enq overhead null %f \n", avg_enq_n - avg_enq_d); 460 printf("AVG deq overhead null %f \n", avg_deq_n - avg_deq_d); 461 printf("AVG notify overhead null %f \n", avg_not_n - avg_not_d); 462 463 printf("############################################################ \n"); 464 465 printf("AVG enq overhead debug %f \n", avg_enq_d-avg_enq); 466 printf("AVG deq overhead debug %f \n", avg_deq_d - avg_deq); 467 printf("AVG notify overhead debug %f \n", avg_not_d - avg_not); 468#endif 469 470 err = devq_deregister(que, regid, &memory); 471 if (err_is_fail(err)){ 472 USER_PANIC("Deregistering memory from devq failed: %s \n", 473 err_getstring(err)); 474 } 475 476 printf("SUCCESS \n"); 477} 478 479