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