libnet: benchmark mode only count dequeues that do not fail
[barrelfish] / lib / net / netif.c
1 /*
2  * Copyright (c) 2017, 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, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
8  */
9
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14
15 #include <barrelfish/barrelfish.h>
16 #include <devif/queue_interface.h>
17 #include <net_interfaces/flags.h>
18
19
20 #include <lwip/opt.h>
21 #include <lwip/netif.h>
22 #include <lwip/timeouts.h>
23 #include "include/net/netif.h"
24
25 #include <netif/etharp.h>
26
27 #include "networking_internal.h"
28
29
30 #define NETDEBUG_SUBSYSTEM "net_if"
31
32
33 ///< the default MTU for the net interfaces
34 #define NET_IF__MTU 1500
35
36 ///< the networking interface flags
37 #define NETWORING_NETIF_FLAGS \
38     (NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET);
39
40 ///< the network interface name
41 #define NET_IF__NAME0 'e'
42 #define NET_IF__NAME1 'n'
43
44 #if (BENCH_LWIP_STACK || BENCH_DEVQ_ENQUEUE || BENCH_DEVQ_DEQUEUE)
45 #include <barrelfish/sys_debug.h>
46 static cycles_t tsc_per_us = 0;
47 static inline uint64_t cycles_to_us(cycles_t cycles)
48 {
49     if (tsc_per_us == 0) {
50         sys_debug_get_tsc_per_ms(&tsc_per_us);
51         tsc_per_us /= 1000;
52     }
53
54     return cycles / (tsc_per_us);
55 }
56 #endif
57
58 #if BENCH_LWIP_STACK
59 static cycles_t bench_lwip_processing = 0;
60 static cycles_t bench_lwip_processing2 = 0;
61 static size_t bench_lwip_processing_count = 0;
62 #endif
63
64 #if BENCH_DEVQ_ENQUEUE
65 static cycles_t bench_devq_enq_rx = 0;
66 static size_t bench_devq_enq_rx_count = 0;
67 static cycles_t bench_devq_enq_tx = 0;
68 static size_t bench_devq_enq_tx_count = 0;
69 #endif
70
71 #if BENCH_DEVQ_DEQUEUE
72 static cycles_t bench_devq_deq = 0;
73 static size_t bench_devq_deq_count = 0;
74 #endif
75
76
77 errval_t net_if_get_hwaddr(struct netif *netif);
78
79 static err_t net_if_linkoutput(struct netif *netif, struct pbuf *p)
80 {
81     errval_t err;
82     err = net_if_add_tx_buf(netif, p);
83     if (err_is_fail(err)) {
84         return ERR_IF;
85     }
86
87     return ERR_OK;
88 }
89
90
91 static void net_if_status_cb(struct netif *netif)
92 {
93     printf("ip_addr_cmp(&netif->ip_addr, IP_ADDR_ANY)=%u\n",
94             ip_addr_cmp(&netif->ip_addr, IP_ADDR_ANY));
95     if (!ip_addr_cmp(&netif->ip_addr, IP_ADDR_ANY)) {
96
97         debug_printf("######################################\n");
98         debug_printf("# IP Addr %s\n", ip4addr_ntoa(netif_ip4_addr(netif)));
99         debug_printf("# GW Addr %s\n", ip4addr_ntoa(netif_ip4_gw(netif)));
100         debug_printf("# Netmask %s\n", ip4addr_ntoa(netif_ip4_netmask(netif)));
101         debug_printf("######################################\n");
102
103         netif_set_default(netif);
104         printf("setting default interface\n");
105     }
106 }
107
108
109 static err_t netif_init_cb(struct netif *netif)
110 {
111     errval_t err;
112
113     netif->hwaddr_len = ETHARP_HWADDR_LEN;
114     netif->flags      = NETWORING_NETIF_FLAGS;
115     netif->mtu        = NET_IF__MTU;
116
117     err =  net_if_get_hwaddr(netif);
118     if (err_is_fail(err)) {
119         return ERR_IF;
120     }
121
122     netif_set_status_callback(netif, net_if_status_cb);
123     netif_set_up(netif);
124     netif_set_link_up(netif);
125
126     return ERR_OK;
127 }
128
129
130 /*
131  * ===============================================================================
132  * Network Interface Management
133  * ===============================================================================
134  */
135
136
137 /**
138  * @brief initializes a netif structure for LWIP with a device queue
139  *
140  * @param netif     the netif to be initialized
141  * @param devq      the device queue to be used
142  *
143  * @return SYS_ERR_OK on success, errva on failure
144  */
145 errval_t net_if_init_devq(struct netif *netif, struct devq *devq)
146 {
147     NETDEBUG("netif=%p, devq=%p\n", netif, devq);
148
149     /* set the output functions */
150     netif->output     = etharp_output;
151     netif->linkoutput = net_if_linkoutput;
152
153     /* set the interface name */
154     netif->name[0] = NET_IF__NAME0;
155     netif->name[1] = NET_IF__NAME1;
156
157     return SYS_ERR_OK;
158 }
159
160
161 /**
162  * @brief initializes the netif
163  *
164  * @param netif
165  * @param devq
166  * @param mac
167  *
168  * @return
169  */
170 errval_t net_if_add(struct netif *netif, void *st)
171 {
172     NETDEBUG("netif=%p, state=%p\n", netif, st);
173
174     netif_add(netif, IP_ADDR_ANY, IP_ADDR_ANY, IP_ADDR_ANY, st,
175               netif_init_cb, netif_input);
176
177     return SYS_ERR_OK;
178 }
179
180
181 /**
182  * @brief removes a network interface
183  *
184  * @param netif     the LWIP netif
185  *
186  * @return SYS_ERR_OK on success, errval on failure
187  */
188 errval_t net_if_remove(struct netif *netif)
189 {
190     NETDEBUG("netif=%p\n", netif);
191
192     /* TODO: need other things to do here ? */
193     netif_remove(netif);
194
195     return SYS_ERR_OK;
196 }
197
198 #define net_if_get_net_state(netif) ((struct net_state*)netif->state)
199
200 /**
201  * @brief obtains the hardware address of the interface
202  *
203  * @param netif      the networking interface
204
205  * @return SYS_ERR_OK on success, errval on failure
206  */
207 errval_t net_if_get_hwaddr(struct netif *netif)
208 {
209     errval_t err;
210
211     struct devq *q = net_if_get_net_state(netif)->queue;
212
213     uint64_t card_mac;
214     err = devq_control(q, 0, 0, &card_mac);
215     if (err_is_fail(err)) {
216         return err;
217     }
218
219     SMEMCPY(netif->hwaddr, &card_mac, netif->hwaddr_len);
220
221     return SYS_ERR_OK;
222 }
223
224 /*
225  * ===============================================================================
226  * Buffer Management
227  * ===============================================================================
228  */
229
230
231
232 /**
233  * @brief adds a new receive buffer to the interface
234  *
235  * @param netif     the LWIP netif
236  * @param pbuf      packet buffer to be added
237  *
238  * @return SYS_ERR_OK on success, errval on failure
239  */
240 errval_t net_if_add_rx_buf(struct netif *netif, struct pbuf *pbuf)
241 {
242     struct net_state *st = netif->state;
243     struct net_buf_p *nb = (struct net_buf_p *)pbuf;
244
245     NETDEBUG("netif=%p <- pbuf=%p   (reg=%u, offset=%" PRIxLPADDR ")\n", netif,
246              pbuf, nb->region->regionid, nb->offset);
247
248 #if NETBUF_DEBGUG
249     assert(nb->magic == 0xdeadbeefcafebabe);
250     assert(nb->allocated == 1);
251     assert(nb->enqueued == 0);
252     assert(nb->flags == 0);
253     nb->enqueued = 1;
254     nb->flags = NETIF_RXFLAG;
255 #endif
256
257
258 #if BENCH_DEVQ_ENQUEUE
259     cycles_t tsc_start = rdtsc();
260 #endif
261     errval_t err;
262     err =  devq_enqueue(st->queue, nb->region->regionid, nb->offset,
263                         nb->region->buffer_size, 0, nb->region->buffer_size,
264                         NETIF_RXFLAG);
265
266 #if BENCH_DEVQ_ENQUEUE
267     bench_devq_enq_rx += rdtsc() - tsc_start;
268     bench_devq_enq_rx_count++;
269     if (bench_devq_enq_rx_count== BENCH_NUM_MEASUREMENTS) {
270         debug_printf("BENCH ENQUEUE RX: %lu us (%lu)\n", cycles_to_us(bench_devq_enq_rx >> BENCH_NUM_MEASUREMENTS_BITS), bench_devq_enq_rx >> BENCH_NUM_MEASUREMENTS_BITS);
271         bench_devq_enq_rx = 0;
272         bench_devq_enq_rx_count = 0;
273     }
274 #endif
275
276     return err;
277 }
278
279
280
281
282 /**
283  * @brief adds a new transmit buffer to the interface
284  *
285  * @param netif     the LWIP netif
286  * @param pbuf      packt boffer to be transmitted
287  *
288  * @return  SYS_ERR_OK on success, errval on failure
289  */
290 errval_t net_if_add_tx_buf(struct netif *netif, struct pbuf *pbuf)
291 {
292     errval_t err;
293
294     struct net_state *st = netif->state;
295
296
297     LINK_STATS_INC(link.xmit);
298
299     uint64_t flags = NETIF_TXFLAG;
300     for (struct pbuf * tmpp = pbuf; tmpp != 0; tmpp = tmpp->next) {
301         pbuf_ref(tmpp);
302
303         struct net_buf_p *nb = (struct net_buf_p *)tmpp;
304
305         NETDEBUG("netif=%p <- pbuf=%p   (reg=%u, offset=%" PRIxLPADDR ")\n", netif,
306                  pbuf, nb->region->regionid, nb->offset);
307
308         if (tmpp->next == NULL) {
309             flags |= NETIF_TXFLAG_LAST;
310         }
311
312 #if NETBUF_DEBGUG
313         assert(nb->magic == 0xdeadbeefcafebabe);
314         assert(nb->allocated == 1);
315         assert(nb->enqueued == 0);
316         assert(nb->flags == 0);
317         nb->enqueued = 1;
318         nb->flags = flags;
319 #endif
320
321
322 #if BENCH_LWIP_STACK
323         if (nb->timestamp) {
324             cycles_t now = rdtsc();
325             bench_lwip_processing += now- nb->timestamp;
326             bench_lwip_processing2 += now - nb->timestamp2;
327             bench_lwip_processing_count++;
328             if (bench_lwip_processing_count == BENCH_NUM_MEASUREMENTS) {
329                 debug_printf("BENCH LWIP PROCESS: %lu us (%lu)\n", cycles_to_us(bench_lwip_processing >> BENCH_NUM_MEASUREMENTS_BITS), bench_lwip_processing >> BENCH_NUM_MEASUREMENTS_BITS);
330                 debug_printf("BENCH LWIP PROCESS2: %lu us (%lu)\n", cycles_to_us(bench_lwip_processing2 >> BENCH_NUM_MEASUREMENTS_BITS), bench_lwip_processing2>> BENCH_NUM_MEASUREMENTS_BITS);
331                 bench_lwip_processing = 0;
332                 bench_lwip_processing2 = 0;
333                 bench_lwip_processing_count = 0;
334             }
335         }
336 #endif
337
338         size_t valid_data = (uintptr_t)tmpp->payload - (uintptr_t)nb->vbase;
339         assert((valid_data + tmpp->len) < nb->region->buffer_size);
340         assert(((uintptr_t)tmpp->payload - valid_data) == (uintptr_t)nb->vbase);
341
342 #if BENCH_DEVQ_ENQUEUE
343     cycles_t tsc_start = rdtsc();
344 #endif
345         err = devq_enqueue(st->queue, nb->region->regionid, nb->offset,
346                            nb->region->buffer_size,
347                            ((uintptr_t)tmpp->payload - (uintptr_t)nb->vbase),
348                            tmpp->len, flags);
349 #if BENCH_DEVQ_ENQUEUE
350     bench_devq_enq_tx += rdtsc() - tsc_start;
351     bench_devq_enq_tx_count++;
352     if (bench_devq_enq_tx_count== BENCH_NUM_MEASUREMENTS) {
353         debug_printf("BENCH ENQUEUE TX: %lu us (%lu)\n", cycles_to_us(bench_devq_enq_tx >> BENCH_NUM_MEASUREMENTS_BITS), bench_devq_enq_tx >> BENCH_NUM_MEASUREMENTS_BITS);
354         bench_devq_enq_tx = 0;
355         bench_devq_enq_tx_count = 0;
356     }
357
358 #endif
359
360         if (err_is_fail(err)) {
361             return err;
362         }
363     }
364
365     return SYS_ERR_OK;
366 }
367
368
369 /*
370  * ===============================================================================
371  * Polling the interfaces
372  * ===============================================================================
373  */
374
375
376 #define NET_IF_POLL_MAX 50
377
378 /**
379  * @brief polls then network interface for new incoming packets
380  *
381  * @param netif     the LWIP netif to be polled
382  *
383  * @return SYS_ERR_OK on success, errval on failure
384  */
385 errval_t net_if_poll(struct netif *netif)
386 {
387     //NETDEBUG("netif=%p\n", netif);
388
389     errval_t err;
390
391     sys_check_timeouts();
392
393     struct net_state *st = netif->state;
394     if (st == NULL) {
395         /* XXX: return an error code ?? */
396         debug_printf("FOOBAR\n");
397         return SYS_ERR_OK;
398     }
399
400     //for (int i = 0; i < NET_IF_POLL_MAX; i++) {
401     for (;;) {
402 #if BENCH_DEVQ_DEQUEUE
403         cycles_t tsc_start = rdtsc();
404 #endif
405         struct devq_buf buf;
406         err = devq_dequeue(st->queue, &buf.rid, &buf.offset, &buf.length,
407                            &buf.valid_data, &buf.valid_length, &buf.flags);
408
409
410 #if BENCH_DEVQ_DEQUEUE
411         if (err == SYS_ERR_OK) {
412             bench_devq_deq += rdtsc() - tsc_start;
413             bench_devq_deq_count++;
414             if (bench_devq_deq_count== BENCH_NUM_MEASUREMENTS) {
415                 debug_printf("BENCH DEQUEUE: %lu\n", bench_devq_deq >> BENCH_NUM_MEASUREMENTS_BITS);
416                 bench_devq_deq = 0;
417                 bench_devq_deq_count = 0;
418             }
419         }
420
421 #endif
422         if (err_is_fail(err)) {
423             if (err_no(err) == DEVQ_ERR_QUEUE_EMPTY) {
424                 return SYS_ERR_OK;
425             }
426             return err;
427         }
428
429         struct pbuf *p = net_buf_get_by_region(st->pool, buf.rid, buf.offset);
430         if (p == NULL) {
431             NETDEBUG("netif=%p, ERROR. No PBUF found for rid=%u, "
432                      "offset=%"PRIxLPADDR "\n", netif, buf.rid, buf.offset);
433             debug_printf("BUFFER NOT FOUND!!!!");
434             continue;
435         }
436
437
438
439 #if NETBUF_DEBGUG
440         struct net_buf_p *nb = (struct net_buf_p *)p;
441
442         assert((buf.valid_data + buf.valid_length) < nb->region->buffer_size);
443
444         if (nb->magic != 0xdeadbeefcafebabe || nb->enqueued != 1 || nb->allocated != 1 || nb->flags != buf.flags) {
445             debug_printf("ERROR: pbuf=%p, rid=%u, offset=%lx magic=%lx, enq=%u, alloc=%u, flags=%lx (%lx)\n",
446                          p, nb->region->regionid, nb->offset, nb->magic, nb->enqueued, nb->allocated, nb->flags, buf.flags);
447         }
448
449         assert(nb->magic == 0xdeadbeefcafebabe);
450         assert(nb->flags == buf.flags);
451         assert(nb->enqueued == 1);
452         assert(nb->allocated == 1);
453
454         nb->enqueued = 0;
455         nb->flags = 0;
456 #endif
457
458 #if BENCH_LWIP_STACK
459         ((struct net_buf_p *)p)->timestamp = rdtsc();
460 #endif
461
462         if (buf.flags & NETIF_TXFLAG) {
463             NETDEBUG("netif=%p, TX done of pbuf=%p (rid=%u, offset=%"PRIxLPADDR ")\n",
464                      netif, p, buf.rid, buf.offset);
465
466             pbuf_free(p);
467
468             assert(!(buf.flags & NETIF_RXFLAG));
469
470         } else if (buf.flags & NETIF_RXFLAG) {
471             NETDEBUG("netif=%p, RX done of pbuf=%p (rid=%u, offset=%"PRIxLPADDR ")\n",
472                      netif, p, buf.rid, buf.offset);
473
474             p->len = buf.valid_length;
475             p->tot_len = p->len;
476             p->payload += buf.valid_data;
477
478             assert(!(buf.flags & NETIF_TXFLAG));
479
480             if (st->netif.input(p, &st->netif) != ERR_OK) {
481                 net_if_add_rx_buf(&st->netif, p);
482             } else {
483                 /* XXX: do this at another time ? */
484                 p = net_buf_alloc(st->pool);
485 #if NETBUF_DEBGUG
486         nb = (struct net_buf_p *)p;
487         assert(nb->magic == 0xdeadbeefcafebabe);
488         assert(nb->allocated == 1);
489         assert(nb->enqueued == 0);
490         assert(nb->flags == 0);
491
492 #endif
493                 if (p) {
494                     net_if_add_rx_buf(&st->netif, p);
495                 } else {
496                     USER_PANIC("Could not allocate a receive buffer\n");
497                 }
498             }
499         } else {
500             debug_printf("WARNING: got buffer without a flag\n");
501         }
502     }
503
504
505
506
507     return SYS_ERR_OK;
508 }
509
510 /**
511  * @brief polls all added network interfaces
512  *
513  * @return SYS_ERR_OK on success, errval on failure
514  */
515 errval_t net_if_poll_all(void)
516 {
517     NETDEBUG("polling all interfaces\n");
518
519     errval_t err;
520     struct netif *netif = netif_list;
521     while(netif) {
522         err = net_if_poll(netif);
523         if (err_is_fail(err)) {
524             DEBUG_ERR(err, "failed to poll network interface");
525         }
526     }
527     return SYS_ERR_OK;
528 }
529
530