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>
47static cycles_t tsc_per_us = 0;
48static 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
60static cycles_t bench_lwip_processing = 0;
61static cycles_t bench_lwip_processing2 = 0;
62static size_t bench_lwip_processing_count = 0;
63#endif
64
65#if BENCH_DEVQ_ENQUEUE
66static cycles_t bench_devq_enq_rx = 0;
67static size_t bench_devq_enq_rx_count = 0;
68static cycles_t bench_devq_enq_tx = 0;
69static size_t bench_devq_enq_tx_count = 0;
70#endif
71
72#if BENCH_DEVQ_DEQUEUE
73static cycles_t bench_devq_deq_rx = 0;
74static size_t bench_devq_deq_count_rx = 0;
75static cycles_t bench_devq_deq_tx = 0;
76static size_t bench_devq_deq_count_tx = 0;
77#endif
78
79#define net_if_get_net_state(netif) ((struct net_state*)netif->state)
80
81errval_t net_if_get_hwaddr(struct netif *netif);
82
83static err_t net_if_linkoutput(struct netif *netif, struct pbuf *p)
84{
85    errval_t err;
86    err = net_if_add_tx_buf(netif, p);
87    if (err_is_fail(err)) {
88        return ERR_IF;
89    }
90
91    return ERR_OK;
92}
93
94
95static void net_if_status_cb(struct netif *netif)
96{
97    if (!ip_addr_cmp(&netif->ip_addr, IP_ADDR_ANY)) {
98        printf("######################################\n");
99        printf("# Cardname %s\n", net_if_get_net_state(netif)->cardname);
100        printf("# IP Addr %s\n", ip4addr_ntoa(netif_ip4_addr(netif)));
101        printf("# GW Addr %s\n", ip4addr_ntoa(netif_ip4_gw(netif)));
102        printf("# Netmask %s\n", ip4addr_ntoa(netif_ip4_netmask(netif)));
103        printf("######################################\n");
104
105        netif_set_default(netif);
106        printf("setting default interface\n");
107
108        NETDEBUG("setting system ip config record to IP: %s\n",
109                ip4addr_ntoa(netif_ip4_addr(netif)));
110        /* register IP with octopus */
111        errval_t err;
112        err = oct_set(NET_CONFIG_CURRENT_IP_RECORD_FORMAT, netif_ip4_addr(netif)->addr,
113                      netif_ip4_gw(netif)->addr,
114                      netif_ip4_netmask(netif)->addr);
115        if (err_is_fail(err)) {
116            DEBUG_ERR(err, "failed to set the DHCP record\n");
117        }
118    }
119}
120
121
122static err_t netif_init_cb(struct netif *netif)
123{
124    errval_t err;
125
126    netif->hwaddr_len = ETHARP_HWADDR_LEN;
127    netif->flags      = NETWORING_NETIF_FLAGS;
128    netif->mtu        = NET_IF__MTU;
129
130    err =  net_if_get_hwaddr(netif);
131    if (err_is_fail(err)) {
132        return ERR_IF;
133    }
134
135    netif_set_status_callback(netif, net_if_status_cb);
136    netif_set_up(netif);
137    netif_set_link_up(netif);
138
139    return ERR_OK;
140}
141
142
143/*
144 * ===============================================================================
145 * Network Interface Management
146 * ===============================================================================
147 */
148
149
150/**
151 * @brief initializes a netif structure for LWIP with a device queue
152 *
153 * @param netif     the netif to be initialized
154 * @param devq      the device queue to be used
155 *
156 * @return SYS_ERR_OK on success, errva on failure
157 */
158errval_t net_if_init_devq(struct netif *netif, struct devq *devq)
159{
160    NETDEBUG("netif=%p, devq=%p\n", netif, devq);
161
162    /* set the output functions */
163    netif->output     = etharp_output;
164    netif->linkoutput = net_if_linkoutput;
165
166    /* set the interface name */
167    netif->name[0] = NET_IF__NAME0;
168    netif->name[1] = NET_IF__NAME1;
169
170    return SYS_ERR_OK;
171}
172
173
174/**
175 * @brief initializes the netif
176 *
177 * @param netif
178 * @param devq
179 * @param mac
180 *
181 * @return
182 */
183errval_t net_if_add(struct netif *netif, void *st)
184{
185    NETDEBUG("netif=%p, state=%p\n", netif, st);
186
187    netif_add(netif, IP_ADDR_ANY, IP_ADDR_ANY, IP_ADDR_ANY, st,
188              netif_init_cb, netif_input);
189
190    return SYS_ERR_OK;
191}
192
193
194/**
195 * @brief removes a network interface
196 *
197 * @param netif     the LWIP netif
198 *
199 * @return SYS_ERR_OK on success, errval on failure
200 */
201errval_t net_if_remove(struct netif *netif)
202{
203    NETDEBUG("netif=%p\n", netif);
204
205    /* TODO: need other things to do here ? */
206    netif_remove(netif);
207
208    return SYS_ERR_OK;
209}
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 */
218errval_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 */
251errval_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 */
301errval_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 10
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 */
396errval_t net_if_poll(struct netif *netif)
397{
398    //NETDEBUG("netif=%p\n", netif);
399
400    errval_t err;
401
402    struct net_state *st = netif->state;
403    if (st == NULL) {
404        /* XXX: return an error code ?? */
405        return SYS_ERR_OK;
406    }
407
408    for (int i = 0; i < NET_IF_POLL_MAX; i++) {
409    //for (;;) {
410#if BENCH_DEVQ_DEQUEUE
411        cycles_t tsc_start = rdtsc();
412#endif
413        struct devq_buf buf;
414        err = devq_dequeue(st->queue, &buf.rid, &buf.offset, &buf.length,
415                           &buf.valid_data, &buf.valid_length, &buf.flags);
416
417
418#if BENCH_DEVQ_DEQUEUE
419        if (err == SYS_ERR_OK) {
420            cycles_t end = rdtsc();
421            if (buf.flags & NETIF_TXFLAG) {
422                bench_devq_deq_tx += end - tsc_start;
423                bench_devq_deq_count_tx++;
424                if (bench_devq_deq_count_tx == BENCH_NUM_MEASUREMENTS) {
425                    debug_printf("BENCH DEQUEUE TX: %lu\n", bench_devq_deq_tx >> BENCH_NUM_MEASUREMENTS_BITS);
426                    bench_devq_deq_tx = 0;
427                    bench_devq_deq_count_tx = 0;
428                }
429            }
430
431            if (buf.flags & NETIF_RXFLAG) {
432                bench_devq_deq_rx += end - tsc_start;
433                bench_devq_deq_count_rx++;
434                if (bench_devq_deq_count_rx == BENCH_NUM_MEASUREMENTS) {
435                    debug_printf("BENCH DEQUEUE RX: %lu\n", bench_devq_deq_rx >> BENCH_NUM_MEASUREMENTS_BITS);
436                    bench_devq_deq_rx = 0;
437                    bench_devq_deq_count_rx = 0;
438                }
439            }
440        }
441
442#endif
443        if (err_is_fail(err)) {
444            if (err_no(err) == DEVQ_ERR_QUEUE_EMPTY) {
445                return LIB_ERR_NO_EVENT;
446            }
447            return err;
448        }
449
450        struct pbuf *p = net_buf_get_by_region(st->pool, buf.rid, buf.offset);
451        if (p == NULL) {
452            NETDEBUG("netif=%p, ERROR. No PBUF found for rid=%u, "
453                     "offset=%"PRIxLPADDR "\n", netif, buf.rid, buf.offset);
454            debug_printf("BUFFER NOT FOUND!!!!");
455            continue;
456        }
457
458
459
460#if NETBUF_DEBGUG
461        struct net_buf_p *nb = (struct net_buf_p *)p;
462
463        assert((buf.valid_data + buf.valid_length) < nb->region->buffer_size);
464
465        if (nb->magic != 0xdeadbeefcafebabe || nb->enqueued != 1 || nb->allocated != 1 || nb->flags != buf.flags) {
466            debug_printf("ERROR: pbuf=%p, rid=%u, offset=%lx magic=%lx, enq=%u, alloc=%u, flags=%lx (%lx)\n",
467                         p, nb->region->regionid, nb->offset, nb->magic, nb->enqueued, nb->allocated, nb->flags, buf.flags);
468        }
469
470        assert(nb->magic == 0xdeadbeefcafebabe);
471        assert(nb->flags == buf.flags);
472        assert(nb->enqueued == 1);
473        assert(nb->allocated == 1);
474
475        nb->enqueued = 0;
476        nb->flags = 0;
477#endif
478
479#if BENCH_LWIP_STACK
480        ((struct net_buf_p *)p)->timestamp = rdtsc();
481#endif
482
483        if (buf.flags & NETIF_TXFLAG) {
484            NETDEBUG("netif=%p, TX done of pbuf=%p (rid=%u, offset=%"PRIxLPADDR ")\n",
485                     netif, p, buf.rid, buf.offset);
486
487            pbuf_free(p);
488
489            assert(!(buf.flags & NETIF_RXFLAG));
490
491        } else if (buf.flags & NETIF_RXFLAG) {
492            NETDEBUG("netif=%p, RX done of pbuf=%p (rid=%u, offset=%"PRIxLPADDR ")\n",
493                     netif, p, buf.rid, buf.offset);
494
495            p->len = buf.valid_length;
496            p->tot_len = p->len;
497            p->payload += buf.valid_data;
498
499            assert(!(buf.flags & NETIF_TXFLAG));
500
501            if (st->netif.input(p, &st->netif) != ERR_OK) {
502                net_if_add_rx_buf(&st->netif, p);
503            } else {
504                /* XXX: do this at another time ? */
505                p = net_buf_alloc(st->pool);
506#if NETBUF_DEBGUG
507        nb = (struct net_buf_p *)p;
508        assert(nb->magic == 0xdeadbeefcafebabe);
509        assert(nb->allocated == 1);
510        assert(nb->enqueued == 0);
511        assert(nb->flags == 0);
512
513#endif
514                if (p) {
515                    net_if_add_rx_buf(&st->netif, p);
516                } else {
517                    USER_PANIC("Could not allocate a receive buffer\n");
518                }
519            }
520        } else {
521            debug_printf("WARNING: got buffer without a flag\n");
522        }
523    }
524    return SYS_ERR_OK;
525}
526
527/**
528 * @brief polls all added network interfaces
529 *
530 * @return SYS_ERR_OK on success, errval on failure
531 */
532errval_t net_if_poll_all(void)
533{
534    NETDEBUG("polling all interfaces\n");
535
536    errval_t err;
537    struct netif *netif = netif_list;
538    while (netif) {
539        err = net_if_poll(netif);
540        if (err_is_fail(err) && err_no(err) != LIB_ERR_NO_EVENT) {
541            DEBUG_ERR(err, "failed to poll network interface");
542        }
543    }
544    netif_poll_all();
545    net_lwip_timeout();
546    return SYS_ERR_OK;
547}
548