devif: added dst MAC lookup to UDP queue init
[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 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
169 int 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, &regid_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