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