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