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>
21 #include <lwip/netif.h>
22 #include <lwip/timeouts.h>
23 #include "include/net/netif.h"
25 #include <netif/etharp.h>
27 #include "networking_internal.h"
30 #define NETDEBUG_SUBSYSTEM "net_if"
33 ///< the default MTU for the net interfaces
34 #define NET_IF__MTU 1500
36 ///< the networking interface flags
37 #define NETWORING_NETIF_FLAGS \
38 (NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET);
40 ///< the network interface name
41 #define NET_IF__NAME0 'e'
42 #define NET_IF__NAME1 'n'
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)
49 if (tsc_per_us == 0) {
50 sys_debug_get_tsc_per_ms(&tsc_per_us);
54 return cycles / (tsc_per_us);
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;
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;
71 #if BENCH_DEVQ_DEQUEUE
72 static cycles_t bench_devq_deq = 0;
73 static size_t bench_devq_deq_count = 0;
77 errval_t net_if_get_hwaddr(struct netif *netif);
79 static err_t net_if_linkoutput(struct netif *netif, struct pbuf *p)
82 err = net_if_add_tx_buf(netif, p);
83 if (err_is_fail(err)) {
91 static void net_if_status_cb(struct netif *netif)
93 printf("ip_addr_cmp(&netif->ip_addr, IP_ADDR_ANY)=%u\n",
94 ip_addr_cmp(&netif->ip_addr, IP_ADDR_ANY));
95 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");
109 static err_t netif_init_cb(struct netif *netif)
113 netif->hwaddr_len = ETHARP_HWADDR_LEN;
114 netif->flags = NETWORING_NETIF_FLAGS;
115 netif->mtu = NET_IF__MTU;
117 err = net_if_get_hwaddr(netif);
118 if (err_is_fail(err)) {
122 netif_set_status_callback(netif, net_if_status_cb);
124 netif_set_link_up(netif);
131 * ===============================================================================
132 * Network Interface Management
133 * ===============================================================================
138 * @brief initializes a netif structure for LWIP with a device queue
140 * @param netif the netif to be initialized
141 * @param devq the device queue to be used
143 * @return SYS_ERR_OK on success, errva on failure
145 errval_t net_if_init_devq(struct netif *netif, struct devq *devq)
147 NETDEBUG("netif=%p, devq=%p\n", netif, devq);
149 /* set the output functions */
150 netif->output = etharp_output;
151 netif->linkoutput = net_if_linkoutput;
153 /* set the interface name */
154 netif->name[0] = NET_IF__NAME0;
155 netif->name[1] = NET_IF__NAME1;
162 * @brief initializes the netif
170 errval_t net_if_add(struct netif *netif, void *st)
172 NETDEBUG("netif=%p, state=%p\n", netif, st);
174 netif_add(netif, IP_ADDR_ANY, IP_ADDR_ANY, IP_ADDR_ANY, st,
175 netif_init_cb, netif_input);
182 * @brief removes a network interface
184 * @param netif the LWIP netif
186 * @return SYS_ERR_OK on success, errval on failure
188 errval_t net_if_remove(struct netif *netif)
190 NETDEBUG("netif=%p\n", netif);
192 /* TODO: need other things to do here ? */
198 #define net_if_get_net_state(netif) ((struct net_state*)netif->state)
201 * @brief obtains the hardware address of the interface
203 * @param netif the networking interface
205 * @return SYS_ERR_OK on success, errval on failure
207 errval_t net_if_get_hwaddr(struct netif *netif)
211 struct devq *q = net_if_get_net_state(netif)->queue;
214 err = devq_control(q, 0, 0, &card_mac);
215 if (err_is_fail(err)) {
219 SMEMCPY(netif->hwaddr, &card_mac, netif->hwaddr_len);
225 * ===============================================================================
227 * ===============================================================================
233 * @brief adds a new receive buffer to the interface
235 * @param netif the LWIP netif
236 * @param pbuf packet buffer to be added
238 * @return SYS_ERR_OK on success, errval on failure
240 errval_t net_if_add_rx_buf(struct netif *netif, struct pbuf *pbuf)
242 struct net_state *st = netif->state;
243 struct net_buf_p *nb = (struct net_buf_p *)pbuf;
245 NETDEBUG("netif=%p <- pbuf=%p (reg=%u, offset=%" PRIxLPADDR ")\n", netif,
246 pbuf, nb->region->regionid, nb->offset);
249 assert(nb->magic == 0xdeadbeefcafebabe);
250 assert(nb->allocated == 1);
251 assert(nb->enqueued == 0);
252 assert(nb->flags == 0);
254 nb->flags = NETIF_RXFLAG;
258 #if BENCH_DEVQ_ENQUEUE
259 cycles_t tsc_start = rdtsc();
262 err = devq_enqueue(st->queue, nb->region->regionid, nb->offset,
263 nb->region->buffer_size, 0, nb->region->buffer_size,
266 #if BENCH_DEVQ_ENQUEUE
267 bench_devq_enq_rx += rdtsc() - tsc_start;
268 bench_devq_enq_rx_count++;
269 if (bench_devq_enq_rx_count== BENCH_NUM_MEASUREMENTS) {
270 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);
271 bench_devq_enq_rx = 0;
272 bench_devq_enq_rx_count = 0;
283 * @brief adds a new transmit buffer to the interface
285 * @param netif the LWIP netif
286 * @param pbuf packt boffer to be transmitted
288 * @return SYS_ERR_OK on success, errval on failure
290 errval_t net_if_add_tx_buf(struct netif *netif, struct pbuf *pbuf)
294 struct net_state *st = netif->state;
297 LINK_STATS_INC(link.xmit);
299 uint64_t flags = NETIF_TXFLAG;
300 for (struct pbuf * tmpp = pbuf; tmpp != 0; tmpp = tmpp->next) {
303 struct net_buf_p *nb = (struct net_buf_p *)tmpp;
305 NETDEBUG("netif=%p <- pbuf=%p (reg=%u, offset=%" PRIxLPADDR ")\n", netif,
306 pbuf, nb->region->regionid, nb->offset);
308 if (tmpp->next == NULL) {
309 flags |= NETIF_TXFLAG_LAST;
313 assert(nb->magic == 0xdeadbeefcafebabe);
314 assert(nb->allocated == 1);
315 assert(nb->enqueued == 0);
316 assert(nb->flags == 0);
324 cycles_t now = rdtsc();
325 bench_lwip_processing += now- nb->timestamp;
326 bench_lwip_processing2 += now - nb->timestamp2;
327 bench_lwip_processing_count++;
328 if (bench_lwip_processing_count == BENCH_NUM_MEASUREMENTS) {
329 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);
330 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);
331 bench_lwip_processing = 0;
332 bench_lwip_processing2 = 0;
333 bench_lwip_processing_count = 0;
338 size_t valid_data = (uintptr_t)tmpp->payload - (uintptr_t)nb->vbase;
339 assert((valid_data + tmpp->len) < nb->region->buffer_size);
340 assert(((uintptr_t)tmpp->payload - valid_data) == (uintptr_t)nb->vbase);
342 #if BENCH_DEVQ_ENQUEUE
343 cycles_t tsc_start = rdtsc();
345 err = devq_enqueue(st->queue, nb->region->regionid, nb->offset,
346 nb->region->buffer_size,
347 ((uintptr_t)tmpp->payload - (uintptr_t)nb->vbase),
349 #if BENCH_DEVQ_ENQUEUE
350 bench_devq_enq_tx += rdtsc() - tsc_start;
351 bench_devq_enq_tx_count++;
352 if (bench_devq_enq_tx_count== BENCH_NUM_MEASUREMENTS) {
353 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);
354 bench_devq_enq_tx = 0;
355 bench_devq_enq_tx_count = 0;
360 if (err_is_fail(err)) {
370 * ===============================================================================
371 * Polling the interfaces
372 * ===============================================================================
376 #define NET_IF_POLL_MAX 50
379 * @brief polls then network interface for new incoming packets
381 * @param netif the LWIP netif to be polled
383 * @return SYS_ERR_OK on success, errval on failure
385 errval_t net_if_poll(struct netif *netif)
387 //NETDEBUG("netif=%p\n", netif);
391 sys_check_timeouts();
393 struct net_state *st = netif->state;
395 /* XXX: return an error code ?? */
396 debug_printf("FOOBAR\n");
400 //for (int i = 0; i < NET_IF_POLL_MAX; i++) {
402 #if BENCH_DEVQ_DEQUEUE
403 cycles_t tsc_start = rdtsc();
406 err = devq_dequeue(st->queue, &buf.rid, &buf.offset, &buf.length,
407 &buf.valid_data, &buf.valid_length, &buf.flags);
410 #if BENCH_DEVQ_DEQUEUE
411 if (err == SYS_ERR_OK) {
412 bench_devq_deq += rdtsc() - tsc_start;
413 bench_devq_deq_count++;
414 if (bench_devq_deq_count== BENCH_NUM_MEASUREMENTS) {
415 debug_printf("BENCH DEQUEUE: %lu\n", bench_devq_deq >> BENCH_NUM_MEASUREMENTS_BITS);
417 bench_devq_deq_count = 0;
422 if (err_is_fail(err)) {
423 if (err_no(err) == DEVQ_ERR_QUEUE_EMPTY) {
429 struct pbuf *p = net_buf_get_by_region(st->pool, buf.rid, buf.offset);
431 NETDEBUG("netif=%p, ERROR. No PBUF found for rid=%u, "
432 "offset=%"PRIxLPADDR "\n", netif, buf.rid, buf.offset);
433 debug_printf("BUFFER NOT FOUND!!!!");
440 struct net_buf_p *nb = (struct net_buf_p *)p;
442 assert((buf.valid_data + buf.valid_length) < nb->region->buffer_size);
444 if (nb->magic != 0xdeadbeefcafebabe || nb->enqueued != 1 || nb->allocated != 1 || nb->flags != buf.flags) {
445 debug_printf("ERROR: pbuf=%p, rid=%u, offset=%lx magic=%lx, enq=%u, alloc=%u, flags=%lx (%lx)\n",
446 p, nb->region->regionid, nb->offset, nb->magic, nb->enqueued, nb->allocated, nb->flags, buf.flags);
449 assert(nb->magic == 0xdeadbeefcafebabe);
450 assert(nb->flags == buf.flags);
451 assert(nb->enqueued == 1);
452 assert(nb->allocated == 1);
459 ((struct net_buf_p *)p)->timestamp = rdtsc();
462 if (buf.flags & NETIF_TXFLAG) {
463 NETDEBUG("netif=%p, TX done of pbuf=%p (rid=%u, offset=%"PRIxLPADDR ")\n",
464 netif, p, buf.rid, buf.offset);
468 assert(!(buf.flags & NETIF_RXFLAG));
470 } else if (buf.flags & NETIF_RXFLAG) {
471 NETDEBUG("netif=%p, RX done of pbuf=%p (rid=%u, offset=%"PRIxLPADDR ")\n",
472 netif, p, buf.rid, buf.offset);
474 p->len = buf.valid_length;
476 p->payload += buf.valid_data;
478 assert(!(buf.flags & NETIF_TXFLAG));
480 if (st->netif.input(p, &st->netif) != ERR_OK) {
481 net_if_add_rx_buf(&st->netif, p);
483 /* XXX: do this at another time ? */
484 p = net_buf_alloc(st->pool);
486 nb = (struct net_buf_p *)p;
487 assert(nb->magic == 0xdeadbeefcafebabe);
488 assert(nb->allocated == 1);
489 assert(nb->enqueued == 0);
490 assert(nb->flags == 0);
494 net_if_add_rx_buf(&st->netif, p);
496 USER_PANIC("Could not allocate a receive buffer\n");
500 debug_printf("WARNING: got buffer without a flag\n");
511 * @brief polls all added network interfaces
513 * @return SYS_ERR_OK on success, errval on failure
515 errval_t net_if_poll_all(void)
517 NETDEBUG("polling all interfaces\n");
520 struct netif *netif = netif_list;
522 err = net_if_poll(netif);
523 if (err_is_fail(err)) {
524 DEBUG_ERR(err, "failed to poll network interface");