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