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/udp.h> 19#include <bench/bench.h> 20#include <net_interfaces/flags.h> 21#include <net/net_filter.h> 22 23//#define DEBUG(x...) printf("devif_test: " x) 24#define DEBUG(x...) do {} while (0) 25 26 27#define NUM_ENQ 512 28#define MEMORY_SIZE BASE_PAGE_SIZE*NUM_ENQ 29#define TX_BUF_SIZE 2048 30#define RX_BUF_SIZE 2048 31 32static uint32_t ip_dst; 33static uint64_t mac_dst; 34static uint16_t port_src; 35static uint16_t port_dst; 36 37static struct capref memory_rx; 38static struct capref memory_tx; 39static regionid_t regid_rx; 40static regionid_t regid_tx; 41static struct frame_identity id; 42static void* va_rx; 43static void* va_tx; 44 45static uint32_t num_tx = 0; 46static uint32_t num_rx = 0; 47static struct udp_q* udp_q; 48static const char* cardname; 49 50/* 51static void wait_for_interrupt(void) 52{ 53 uint32_t tx = num_tx; 54 55 while(tx == num_tx) { 56 errval_t err = event_dispatch(get_default_waitset()); 57 if (err_is_fail(err)) { 58 USER_PANIC_ERR(err, "error in event_dispatch for wait_for_interrupt"); 59 } 60 } 61} 62*/ 63 64static uint64_t total_rx = 0; 65static bool reg_done = false; 66 67static bool use_interrupts = false; 68 69 70static void event_cb(void* queue) 71{ 72 struct devq* q = (struct devq*) udp_q; 73 74 errval_t err; 75 76 regionid_t rid; 77 genoffset_t offset; 78 genoffset_t length; 79 genoffset_t valid_data; 80 genoffset_t valid_length; 81 uint64_t flags; 82 83 err = SYS_ERR_OK; 84 85 uint64_t start = 0, end = 0; 86 87 if (!reg_done) { 88 return; 89 } 90 91 while (err == SYS_ERR_OK) { 92 start = rdtsc(); 93 err = devq_dequeue(q, &rid, &offset, &length, &valid_data, 94 &valid_length, &flags); 95 if (err_is_fail(err)) { 96 break; 97 } 98 99 if (flags & NETIF_TXFLAG) { 100 DEBUG("Received TX buffer back \n"); 101 num_tx++; 102 } else if (flags & NETIF_RXFLAG) { 103 num_rx++; 104 DEBUG("Received RX buffer \n"); 105 err = devq_enqueue(q, rid, offset, length, 0, 106 0, NETIF_RXFLAG); 107 end = rdtsc(); 108 total_rx += end - start; 109 } else { 110 printf("Unknown flags %lx \n", flags); 111 } 112 } 113} 114 115static void test_udp(void) 116{ 117 errval_t err; 118 struct devq* q; 119 120 // create queue with interrupts 121 udp_create(&udp_q, cardname, port_src, port_dst, 122 ip_dst, event_cb, !use_interrupts); 123 124 q = (struct devq*) udp_q; 125 126 assert(q != NULL); 127 128 num_tx = 0; 129 num_rx = 0; 130 err = devq_register(q, memory_rx, ®id_rx); 131 if (err_is_fail(err)){ 132 USER_PANIC("Registering memory to devq failed \n"); 133 } 134 135 // inesrt buffers 136 for (int i = 0; i < NUM_ENQ; i++) { 137 err = devq_enqueue(q, regid_rx, i*(RX_BUF_SIZE), RX_BUF_SIZE, 138 0, RX_BUF_SIZE, 139 NETIF_RXFLAG); 140 if (err_is_fail(err)){ 141 USER_PANIC("Devq enqueue RX buffer failed \n"); 142 } 143 } 144 145 146 err = devq_register(q, memory_tx, ®id_tx); 147 if (err_is_fail(err)){ 148 USER_PANIC("Registering memory to devq failed \n"); 149 } 150 151 reg_done = true; 152 // write something into the buffers 153 char* data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 154 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 155 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; 156 printf("Data length %zu \n", strlen(data)); 157 158 for (int i = 0; i < NUM_ENQ; i++) { 159 udp_write_buffer(udp_q, regid_tx, i*(TX_BUF_SIZE), 160 data, strlen(data)); 161 } 162 163 uint64_t total = 0, start = 0, end = 0; 164 for (int z = 0; z < NUM_ENQ; z++) { 165 166 start = rdtsc(); 167 for (int i = 0; i < NUM_ENQ; i++) { 168 err = devq_enqueue(q, regid_tx, i*(TX_BUF_SIZE), TX_BUF_SIZE, 169 0, strlen(data), NETIF_TXFLAG | NETIF_TXFLAG_LAST); 170 if (err_is_fail(err)){ 171 USER_PANIC("Devq enqueue failed \n"); 172 } 173 } 174 175 while (num_tx < NUM_ENQ*z) { 176 if (use_interrupts) { 177 event_dispatch(get_default_waitset()); 178 } else { 179 event_cb(q); 180 } 181 } 182 183 end = rdtsc(); 184 total += end - start; 185 } 186 printf("Average %f cycles TX\n", (double)total/(NUM_ENQ*NUM_ENQ)); 187 barrelfish_usleep(1000*1000); 188 printf("Testing receiving UDP packets \n"); 189 190 for (int z = 0; z < NUM_ENQ; z++) { 191 while(num_rx < NUM_ENQ*z) { 192 if (use_interrupts) { 193 event_dispatch(get_default_waitset()); 194 } else { 195 event_cb(q); 196 } 197 } 198 } 199 200 printf("Average %f cycles RX\n", (double)total_rx/(NUM_ENQ*NUM_ENQ)); 201 202 err = devq_deregister(q, regid_rx, &memory_rx); 203 if (err_is_fail(err)){ 204 printf("%s \n", err_getstring(err)); 205 USER_PANIC("Devq deregister tx failed \n"); 206 } 207 208 err = devq_deregister(q, regid_tx, &memory_tx); 209 if (err_is_fail(err)){ 210 printf("%s \n", err_getstring(err)); 211 USER_PANIC("Devq deregister tx failed \n"); 212 } 213 214 printf("Receiving UDP packets done \n"); 215 printf("SUCCESS: udp test ended \n"); 216} 217 218int main(int argc, char *argv[]) 219{ 220 errval_t err; 221 // Allocate memory 222 err = frame_alloc(&memory_tx, MEMORY_SIZE, NULL); 223 if (err_is_fail(err)){ 224 USER_PANIC("Allocating cap failed \n"); 225 } 226 227 err = frame_alloc(&memory_rx, MEMORY_SIZE, NULL); 228 if (err_is_fail(err)){ 229 USER_PANIC("Allocating cap failed \n"); 230 } 231 232 // RX frame 233 err = invoke_frame_identify(memory_rx, &id); 234 if (err_is_fail(err)) { 235 USER_PANIC("Frame identify failed \n"); 236 } 237 238 err = vspace_map_one_frame_attr(&va_rx, id.bytes, memory_rx, 239 VREGION_FLAGS_READ, NULL, NULL); 240 if (err_is_fail(err)) { 241 USER_PANIC("Frame mapping failed \n"); 242 } 243 244 // RX frame 245 err = invoke_frame_identify(memory_tx, &id); 246 if (err_is_fail(err)) { 247 USER_PANIC("Frame identify failed \n"); 248 } 249 250 err = vspace_map_one_frame_attr(&va_tx, id.bytes, memory_tx, 251 VREGION_FLAGS_READ_WRITE, NULL, NULL); 252 if (err_is_fail(err)) { 253 USER_PANIC("Frame mapping failed \n"); 254 } 255 256 if (argc > 5) { 257 char* end; 258 ip_dst = atoi(argv[1]); 259 mac_dst = strtoull(argv[2], &end, 10); 260 port_src = atoi(argv[3]); 261 port_dst = atoi(argv[4]); 262 cardname = argv[5]; 263 } else { 264 USER_PANIC("NO src or dst IP given \n"); 265 } 266 267 barrelfish_usleep(1000*1000*15); 268 269 test_udp(); 270} 271 272