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 <barrelfish/sys_debug.h> 18#include <devif/queue_interface.h> 19#include <devif/backends/net/udp.h> 20#include <bench/bench.h> 21#include <net_interfaces/flags.h> 22 23 24#define BENCH 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_BUF 1024 31#define MEMORY_SIZE RX_BUF_SIZE*NUM_BUF 32 33 34 35static struct devq* udp_q; 36static struct capref memory_rx; 37static regionid_t regid_rx; 38static struct frame_identity id; 39static lpaddr_t phys_rx; 40static void* va_rx; 41 42static uint32_t ip_dst; 43static uint64_t mac_dst; 44static uint16_t port_src; 45static uint16_t port_dst; 46static const char* cardname; 47 48 49static uint64_t bytes = 0; 50#ifdef BENCH 51static uint64_t num_dequeue_tx = 0; 52static uint64_t num_dequeue_rx = 0; 53static uint64_t num_enqueue_tx = 0; 54static uint64_t num_enqueue_rx = 0; 55static uint64_t enq_s, enq_e; 56static uint64_t deq_s, deq_e; 57static uint64_t tot_enq_rx, tot_deq_rx; 58static uint64_t tot_enq_tx, tot_deq_tx; 59#endif 60static uint64_t num_rx = 0; 61static uint64_t start; 62static uint64_t end; 63static uint64_t tsc_per_ms; 64 65static bool use_irq = false; 66 67static void event_cb(void* queue) 68{ 69 struct devq* q = (struct devq*) udp_q; 70 71 errval_t err; 72 73 regionid_t rid; 74 genoffset_t offset; 75 genoffset_t length; 76 genoffset_t valid_data; 77 genoffset_t valid_length; 78 uint64_t flags; 79 80 err = SYS_ERR_OK; 81 82 while (err == SYS_ERR_OK) { 83#ifdef BENCH 84 deq_s = rdtsc(); 85#endif 86 err = devq_dequeue(q, &rid, &offset, &length, &valid_data, 87 &valid_length, &flags); 88 89 if (err_is_fail(err)) { 90 break; 91 } 92 93 if (flags & NETIF_TXFLAG) { 94#ifdef BENCH 95 deq_e = rdtsc(); 96 num_dequeue_tx++; 97 tot_deq_tx += deq_e - deq_s; 98#endif 99 DEBUG("Received TX buffer back \n"); 100#ifdef BENCH 101 enq_s = rdtsc(); 102#endif 103 err = devq_enqueue(q, rid, offset, length, 0, 104 0, NETIF_RXFLAG); 105 if (err_is_fail(err)) { 106 break; 107 } 108#ifdef BENCH 109 enq_e = rdtsc(); 110 num_enqueue_rx++; 111 tot_enq_rx += enq_e - enq_s; 112#endif 113 } else if (flags & NETIF_RXFLAG) { 114#ifdef BENCH 115 deq_e = rdtsc(); 116 num_dequeue_rx++; 117 tot_deq_rx += deq_e - deq_s; 118#endif 119 num_rx++; 120 bytes += valid_length; 121 DEBUG("Received RX buffer \n"); 122#ifdef BENCH 123 enq_s = rdtsc(); 124#endif 125 // TODO change to TX flag 126 //printf("offset %lu lenght %lu valid_length %lu \n", offset, length, valid_length); 127 err = devq_enqueue(q, rid, offset, length, 0, 128 valid_length, NETIF_TXFLAG | NETIF_TXFLAG_LAST); 129 if (err_is_fail(err)) { 130 break; 131 } 132#ifdef BENCH 133 enq_e = rdtsc(); 134 tot_enq_tx += enq_e - enq_s; 135 num_enqueue_tx++; 136#endif 137 if ((num_rx % 1000000) == 0) { 138 end = rdtsc(); 139 double time = ((double) end-start)/(tsc_per_ms*1000); 140 printf("Mbit/s %f during %f seconds \n", 141 ((double)bytes*8)/(1000*1000*time), time); 142 printf("Num packets/s %f \n", (double) 1000000/time); 143#ifdef BENCH 144 printf("AVG deq_rx %f micro seconds\n", ((double) (tot_deq_rx/num_dequeue_rx)/(tsc_per_ms/1000))); 145 printf("AVG enq_rx %f micro seconds\n", ((double) (tot_enq_rx/num_enqueue_rx)/(tsc_per_ms/1000))); 146 printf("AVG deq_tx %f micro seconds\n", ((double) (tot_deq_tx/num_dequeue_tx)/(tsc_per_ms/1000))); 147 printf("AVG enq_tx %f micro seconds\n", ((double) (tot_enq_tx/num_enqueue_tx)/(tsc_per_ms/1000))); 148 149 tot_deq_rx = 0; 150 tot_deq_tx = 0; 151 tot_enq_rx = 0; 152 tot_enq_tx = 0; 153 num_enqueue_rx = 0; 154 num_enqueue_tx = 0; 155 num_dequeue_rx = 0; 156 num_dequeue_tx = 0; 157#endif 158 num_rx = 0; 159 bytes = 0; 160 start = rdtsc(); 161 } 162 } else { 163 printf("Unknown flags %lx \n", flags); 164 } 165 166 } 167} 168 169int main(int argc, char *argv[]) 170{ 171 if (argc > 5) { 172 char* stop; 173 ip_dst = atoi(argv[1]); 174 mac_dst = strtoull(argv[2], &stop, 10); 175 176 port_src = atoi(argv[3]); 177 port_dst = atoi(argv[4]); 178 cardname = argv[5]; 179 } else { 180 USER_PANIC("NO src or dst IP given \n"); 181 } 182 183 errval_t err; 184 // Allocate memory 185 err = frame_alloc(&memory_rx, MEMORY_SIZE, NULL); 186 if (err_is_fail(err)){ 187 USER_PANIC("Allocating cap failed \n"); 188 } 189 190 // RX frame 191 err = invoke_frame_identify(memory_rx, &id); 192 if (err_is_fail(err)) { 193 USER_PANIC("Frame identify failed \n"); 194 } 195 196 err = vspace_map_one_frame_attr(&va_rx, id.bytes, memory_rx, 197 VREGION_FLAGS_READ_WRITE, NULL, NULL); 198 if (err_is_fail(err)) { 199 USER_PANIC("Frame mapping failed \n"); 200 } 201 202 phys_rx = id.base; 203 204 err = udp_create((struct udp_q**) &udp_q, cardname, port_src, port_dst, 205 ip_dst, event_cb, true); 206 if (err_is_fail(err)) { 207 USER_PANIC("Queue creation failed \n"); 208 } 209 210 err = devq_register(udp_q, memory_rx, ®id_rx); 211 if (err_is_fail(err)) { 212 USER_PANIC("Register failed \n"); 213 } 214 215 for (int j = 0; j < NUM_BUF; j++) { 216 err = devq_enqueue(udp_q, regid_rx, j*RX_BUF_SIZE, RX_BUF_SIZE, 0, RX_BUF_SIZE, 217 NETIF_RXFLAG); 218 if (err_is_fail(err)) { 219 USER_PANIC("Err %s \n", err_getstring(err)); 220 } 221 } 222 223 err = sys_debug_get_tsc_per_ms(&tsc_per_ms); 224 assert(err_is_ok(err)); 225 226 barrelfish_usleep(1000*1000*15); 227 228 if (use_irq) { 229 while (true) { 230 event_dispatch(get_default_waitset()); 231 } 232 } else { 233 printf("Testing receiving UDP packets \n"); 234 start = rdtsc(); 235 while(true) { 236 event_cb(udp_q); 237 } 238 } 239 240} 241 242