2 * Copyright (c) 2017, ETH Zurich.
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.
15 #include <barrelfish/barrelfish.h>
16 #include <devif/queue_interface.h>
17 #include <net_interfaces/flags.h>
18 #include <octopus/octopus.h>
22 #include <lwip/netif.h>
23 #include <lwip/timeouts.h>
24 #include <net/netif.h>
26 #include <netif/etharp.h>
28 #include "networking_internal.h"
31 #define NETDEBUG_SUBSYSTEM "net_if"
34 ///< the default MTU for the net interfaces
35 #define NET_IF__MTU 1500
37 ///< the networking interface flags
38 #define NETWORING_NETIF_FLAGS \
39 (NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET);
41 ///< the network interface name
42 #define NET_IF__NAME0 'e'
43 #define NET_IF__NAME1 'n'
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)
50 if (tsc_per_us == 0) {
51 sys_debug_get_tsc_per_ms(&tsc_per_us);
55 return cycles / (tsc_per_us);
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;
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;
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;
80 errval_t net_if_get_hwaddr(struct netif *netif);
82 static err_t net_if_linkoutput(struct netif *netif, struct pbuf *p)
85 err = net_if_add_tx_buf(netif, p);
86 if (err_is_fail(err)) {
94 static void net_if_status_cb(struct netif *netif)
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");
103 netif_set_default(netif);
104 printf("setting default interface\n");
106 NETDEBUG("setting system ip config record to IP: %s\n",
107 ip4addr_ntoa(netif_ip4_addr(netif)));
108 /* register IP with octopus */
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");
120 static err_t netif_init_cb(struct netif *netif)
124 netif->hwaddr_len = ETHARP_HWADDR_LEN;
125 netif->flags = NETWORING_NETIF_FLAGS;
126 netif->mtu = NET_IF__MTU;
128 err = net_if_get_hwaddr(netif);
129 if (err_is_fail(err)) {
133 netif_set_status_callback(netif, net_if_status_cb);
135 netif_set_link_up(netif);
142 * ===============================================================================
143 * Network Interface Management
144 * ===============================================================================
149 * @brief initializes a netif structure for LWIP with a device queue
151 * @param netif the netif to be initialized
152 * @param devq the device queue to be used
154 * @return SYS_ERR_OK on success, errva on failure
156 errval_t net_if_init_devq(struct netif *netif, struct devq *devq)
158 NETDEBUG("netif=%p, devq=%p\n", netif, devq);
160 /* set the output functions */
161 netif->output = etharp_output;
162 netif->linkoutput = net_if_linkoutput;
164 /* set the interface name */
165 netif->name[0] = NET_IF__NAME0;
166 netif->name[1] = NET_IF__NAME1;
173 * @brief initializes the netif
181 errval_t net_if_add(struct netif *netif, void *st)
183 NETDEBUG("netif=%p, state=%p\n", netif, st);
185 netif_add(netif, IP_ADDR_ANY, IP_ADDR_ANY, IP_ADDR_ANY, st,
186 netif_init_cb, netif_input);
193 * @brief removes a network interface
195 * @param netif the LWIP netif
197 * @return SYS_ERR_OK on success, errval on failure
199 errval_t net_if_remove(struct netif *netif)
201 NETDEBUG("netif=%p\n", netif);
203 /* TODO: need other things to do here ? */
209 #define net_if_get_net_state(netif) ((struct net_state*)netif->state)
212 * @brief obtains the hardware address of the interface
214 * @param netif the networking interface
216 * @return SYS_ERR_OK on success, errval on failure
218 errval_t net_if_get_hwaddr(struct netif *netif)
222 struct devq *q = net_if_get_net_state(netif)->queue;
225 err = devq_control(q, 0, 0, &card_mac);
226 if (err_is_fail(err)) {
230 SMEMCPY(netif->hwaddr, &card_mac, netif->hwaddr_len);
236 * ===============================================================================
238 * ===============================================================================
244 * @brief adds a new receive buffer to the interface
246 * @param netif the LWIP netif
247 * @param pbuf packet buffer to be added
249 * @return SYS_ERR_OK on success, errval on failure
251 errval_t net_if_add_rx_buf(struct netif *netif, struct pbuf *pbuf)
253 struct net_state *st = netif->state;
254 struct net_buf_p *nb = (struct net_buf_p *)pbuf;
256 NETDEBUG("netif=%p <- pbuf=%p (reg=%u, offset=%" PRIxLPADDR ")\n", netif,
257 pbuf, nb->region->regionid, nb->offset);
260 assert(nb->magic == 0xdeadbeefcafebabe);
261 assert(nb->allocated == 1);
262 assert(nb->enqueued == 0);
263 assert(nb->flags == 0);
265 nb->flags = NETIF_RXFLAG;
269 #if BENCH_DEVQ_ENQUEUE
270 cycles_t tsc_start = rdtsc();
273 err = devq_enqueue(st->queue, nb->region->regionid, nb->offset,
274 nb->region->buffer_size, 0, nb->region->buffer_size,
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;
294 * @brief adds a new transmit buffer to the interface
296 * @param netif the LWIP netif
297 * @param pbuf packt boffer to be transmitted
299 * @return SYS_ERR_OK on success, errval on failure
301 errval_t net_if_add_tx_buf(struct netif *netif, struct pbuf *pbuf)
305 struct net_state *st = netif->state;
308 LINK_STATS_INC(link.xmit);
310 uint64_t flags = NETIF_TXFLAG;
311 for (struct pbuf * tmpp = pbuf; tmpp != 0; tmpp = tmpp->next) {
314 struct net_buf_p *nb = (struct net_buf_p *)tmpp;
316 NETDEBUG("netif=%p <- pbuf=%p (reg=%u, offset=%" PRIxLPADDR ")\n", netif,
317 pbuf, nb->region->regionid, nb->offset);
319 if (tmpp->next == NULL) {
320 flags |= NETIF_TXFLAG_LAST;
324 assert(nb->magic == 0xdeadbeefcafebabe);
325 assert(nb->allocated == 1);
326 assert(nb->enqueued == 0);
327 assert(nb->flags == 0);
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;
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);
353 #if BENCH_DEVQ_ENQUEUE
354 cycles_t tsc_start = rdtsc();
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),
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;
371 if (err_is_fail(err)) {
381 * ===============================================================================
382 * Polling the interfaces
383 * ===============================================================================
387 #define NET_IF_POLL_MAX 50
390 * @brief polls then network interface for new incoming packets
392 * @param netif the LWIP netif to be polled
394 * @return SYS_ERR_OK on success, errval on failure
396 errval_t net_if_poll(struct netif *netif)
398 //NETDEBUG("netif=%p\n", netif);
402 sys_check_timeouts();
404 struct net_state *st = netif->state;
406 /* XXX: return an error code ?? */
407 debug_printf("FOOBAR\n");
411 //for (int i = 0; i < NET_IF_POLL_MAX; i++) {
413 #if BENCH_DEVQ_DEQUEUE
414 cycles_t tsc_start = rdtsc();
417 err = devq_dequeue(st->queue, &buf.rid, &buf.offset, &buf.length,
418 &buf.valid_data, &buf.valid_length, &buf.flags);
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;
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;
446 if (err_is_fail(err)) {
447 if (err_no(err) == DEVQ_ERR_QUEUE_EMPTY) {
453 struct pbuf *p = net_buf_get_by_region(st->pool, buf.rid, buf.offset);
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!!!!");
464 struct net_buf_p *nb = (struct net_buf_p *)p;
466 assert((buf.valid_data + buf.valid_length) < nb->region->buffer_size);
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);
473 assert(nb->magic == 0xdeadbeefcafebabe);
474 assert(nb->flags == buf.flags);
475 assert(nb->enqueued == 1);
476 assert(nb->allocated == 1);
483 ((struct net_buf_p *)p)->timestamp = rdtsc();
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);
492 assert(!(buf.flags & NETIF_RXFLAG));
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);
498 p->len = buf.valid_length;
500 p->payload += buf.valid_data;
502 assert(!(buf.flags & NETIF_TXFLAG));
504 if (st->netif.input(p, &st->netif) != ERR_OK) {
505 net_if_add_rx_buf(&st->netif, p);
507 /* XXX: do this at another time ? */
508 p = net_buf_alloc(st->pool);
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);
518 net_if_add_rx_buf(&st->netif, p);
520 USER_PANIC("Could not allocate a receive buffer\n");
524 debug_printf("WARNING: got buffer without a flag\n");
535 * @brief polls all added network interfaces
537 * @return SYS_ERR_OK on success, errval on failure
539 errval_t net_if_poll_all(void)
541 NETDEBUG("polling all interfaces\n");
544 struct netif *netif = netif_list;
546 err = net_if_poll(netif);
547 if (err_is_fail(err)) {
548 DEBUG_ERR(err, "failed to poll network interface");