devif: added dst MAC lookup to UDP queue init
[barrelfish] / usr / tests / devif / udp_queue.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 <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
32 static uint32_t ip_dst;
33 static uint64_t mac_dst;
34 static uint16_t port_src;
35 static uint16_t port_dst;
36
37 static struct capref memory_rx;
38 static struct capref memory_tx;
39 static regionid_t regid_rx;
40 static regionid_t regid_tx;
41 static struct frame_identity id;
42 static void* va_rx;
43 static void* va_tx;
44
45 static uint32_t num_tx = 0;
46 static uint32_t num_rx = 0;
47 static struct udp_q* udp_q;
48 static const char* cardname;
49
50 /*
51 static 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
64 static uint64_t total_rx = 0;
65 static bool reg_done = false;
66
67 static bool use_interrupts = false;
68
69
70 static 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
115 static 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, &regid_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, &regid_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
218 int 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