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