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 <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_rx = 0;
73 static size_t bench_devq_deq_count_rx = 0;
74 static cycles_t bench_devq_deq_tx = 0;
75 static size_t bench_devq_deq_count_tx = 0;
79 errval_t net_if_get_hwaddr(struct netif *netif);
81 static err_t net_if_linkoutput(struct netif *netif, struct pbuf *p)
84 err = net_if_add_tx_buf(netif, p);
85 if (err_is_fail(err)) {
93 static void net_if_status_cb(struct netif *netif)
95 printf("ip_addr_cmp(&netif->ip_addr, IP_ADDR_ANY)=%u\n",
96 ip_addr_cmp(&netif->ip_addr, IP_ADDR_ANY));
97 if (!ip_addr_cmp(&netif->ip_addr, IP_ADDR_ANY)) {
99 debug_printf("######################################\n");
100 debug_printf("# IP Addr %s\n", ip4addr_ntoa(netif_ip4_addr(netif)));
101 debug_printf("# GW Addr %s\n", ip4addr_ntoa(netif_ip4_gw(netif)));
102 debug_printf("# Netmask %s\n", ip4addr_ntoa(netif_ip4_netmask(netif)));
103 debug_printf("######################################\n");
105 netif_set_default(netif);
106 printf("setting default interface\n");
111 static err_t netif_init_cb(struct netif *netif)
115 netif->hwaddr_len = ETHARP_HWADDR_LEN;
116 netif->flags = NETWORING_NETIF_FLAGS;
117 netif->mtu = NET_IF__MTU;
119 err = net_if_get_hwaddr(netif);
120 if (err_is_fail(err)) {
124 netif_set_status_callback(netif, net_if_status_cb);
126 netif_set_link_up(netif);
133 * ===============================================================================
134 * Network Interface Management
135 * ===============================================================================
140 * @brief initializes a netif structure for LWIP with a device queue
142 * @param netif the netif to be initialized
143 * @param devq the device queue to be used
145 * @return SYS_ERR_OK on success, errva on failure
147 errval_t net_if_init_devq(struct netif *netif, struct devq *devq)
149 NETDEBUG("netif=%p, devq=%p\n", netif, devq);
151 /* set the output functions */
152 netif->output = etharp_output;
153 netif->linkoutput = net_if_linkoutput;
155 /* set the interface name */
156 netif->name[0] = NET_IF__NAME0;
157 netif->name[1] = NET_IF__NAME1;
164 * @brief initializes the netif
172 errval_t net_if_add(struct netif *netif, void *st)
174 NETDEBUG("netif=%p, state=%p\n", netif, st);
176 netif_add(netif, IP_ADDR_ANY, IP_ADDR_ANY, IP_ADDR_ANY, st,
177 netif_init_cb, netif_input);
184 * @brief removes a network interface
186 * @param netif the LWIP netif
188 * @return SYS_ERR_OK on success, errval on failure
190 errval_t net_if_remove(struct netif *netif)
192 NETDEBUG("netif=%p\n", netif);
194 /* TODO: need other things to do here ? */
200 #define net_if_get_net_state(netif) ((struct net_state*)netif->state)
203 * @brief obtains the hardware address of the interface
205 * @param netif the networking interface
207 * @return SYS_ERR_OK on success, errval on failure
209 errval_t net_if_get_hwaddr(struct netif *netif)
213 struct devq *q = net_if_get_net_state(netif)->queue;
216 err = devq_control(q, 0, 0, &card_mac);
217 if (err_is_fail(err)) {
221 SMEMCPY(netif->hwaddr, &card_mac, netif->hwaddr_len);
227 * ===============================================================================
229 * ===============================================================================
235 * @brief adds a new receive buffer to the interface
237 * @param netif the LWIP netif
238 * @param pbuf packet buffer to be added
240 * @return SYS_ERR_OK on success, errval on failure
242 errval_t net_if_add_rx_buf(struct netif *netif, struct pbuf *pbuf)
244 struct net_state *st = netif->state;
245 struct net_buf_p *nb = (struct net_buf_p *)pbuf;
247 NETDEBUG("netif=%p <- pbuf=%p (reg=%u, offset=%" PRIxLPADDR ")\n", netif,
248 pbuf, nb->region->regionid, nb->offset);
251 assert(nb->magic == 0xdeadbeefcafebabe);
252 assert(nb->allocated == 1);
253 assert(nb->enqueued == 0);
254 assert(nb->flags == 0);
256 nb->flags = NETIF_RXFLAG;
260 #if BENCH_DEVQ_ENQUEUE
261 cycles_t tsc_start = rdtsc();
264 err = devq_enqueue(st->queue, nb->region->regionid, nb->offset,
265 nb->region->buffer_size, 0, nb->region->buffer_size,
268 #if BENCH_DEVQ_ENQUEUE
269 bench_devq_enq_rx += rdtsc() - tsc_start;
270 bench_devq_enq_rx_count++;
271 if (bench_devq_enq_rx_count== BENCH_NUM_MEASUREMENTS) {
272 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);
273 bench_devq_enq_rx = 0;
274 bench_devq_enq_rx_count = 0;
285 * @brief adds a new transmit buffer to the interface
287 * @param netif the LWIP netif
288 * @param pbuf packt boffer to be transmitted
290 * @return SYS_ERR_OK on success, errval on failure
292 errval_t net_if_add_tx_buf(struct netif *netif, struct pbuf *pbuf)
296 struct net_state *st = netif->state;
299 LINK_STATS_INC(link.xmit);
301 uint64_t flags = NETIF_TXFLAG;
302 for (struct pbuf * tmpp = pbuf; tmpp != 0; tmpp = tmpp->next) {
305 struct net_buf_p *nb = (struct net_buf_p *)tmpp;
307 NETDEBUG("netif=%p <- pbuf=%p (reg=%u, offset=%" PRIxLPADDR ")\n", netif,
308 pbuf, nb->region->regionid, nb->offset);
310 if (tmpp->next == NULL) {
311 flags |= NETIF_TXFLAG_LAST;
315 assert(nb->magic == 0xdeadbeefcafebabe);
316 assert(nb->allocated == 1);
317 assert(nb->enqueued == 0);
318 assert(nb->flags == 0);
326 cycles_t now = rdtsc();
327 bench_lwip_processing += now- nb->timestamp;
328 bench_lwip_processing2 += now - nb->timestamp2;
329 bench_lwip_processing_count++;
330 if (bench_lwip_processing_count == BENCH_NUM_MEASUREMENTS) {
331 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);
332 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);
333 bench_lwip_processing = 0;
334 bench_lwip_processing2 = 0;
335 bench_lwip_processing_count = 0;
340 size_t valid_data = (uintptr_t)tmpp->payload - (uintptr_t)nb->vbase;
341 assert((valid_data + tmpp->len) < nb->region->buffer_size);
342 assert(((uintptr_t)tmpp->payload - valid_data) == (uintptr_t)nb->vbase);
344 #if BENCH_DEVQ_ENQUEUE
345 cycles_t tsc_start = rdtsc();
347 err = devq_enqueue(st->queue, nb->region->regionid, nb->offset,
348 nb->region->buffer_size,
349 ((uintptr_t)tmpp->payload - (uintptr_t)nb->vbase),
351 #if BENCH_DEVQ_ENQUEUE
352 bench_devq_enq_tx += rdtsc() - tsc_start;
353 bench_devq_enq_tx_count++;
354 if (bench_devq_enq_tx_count== BENCH_NUM_MEASUREMENTS) {
355 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);
356 bench_devq_enq_tx = 0;
357 bench_devq_enq_tx_count = 0;
362 if (err_is_fail(err)) {
372 * ===============================================================================
373 * Polling the interfaces
374 * ===============================================================================
378 #define NET_IF_POLL_MAX 50
381 * @brief polls then network interface for new incoming packets
383 * @param netif the LWIP netif to be polled
385 * @return SYS_ERR_OK on success, errval on failure
387 errval_t net_if_poll(struct netif *netif)
389 //NETDEBUG("netif=%p\n", netif);
393 sys_check_timeouts();
395 struct net_state *st = netif->state;
397 /* XXX: return an error code ?? */
398 debug_printf("FOOBAR\n");
402 //for (int i = 0; i < NET_IF_POLL_MAX; i++) {
404 #if BENCH_DEVQ_DEQUEUE
405 cycles_t tsc_start = rdtsc();
408 err = devq_dequeue(st->queue, &buf.rid, &buf.offset, &buf.length,
409 &buf.valid_data, &buf.valid_length, &buf.flags);
412 #if BENCH_DEVQ_DEQUEUE
413 if (err == SYS_ERR_OK) {
414 cycles_t end = rdtsc();
415 if (buf.flags & NETIF_TXFLAG) {
416 bench_devq_deq_tx += end - tsc_start;
417 bench_devq_deq_count_tx++;
418 if (bench_devq_deq_count_tx == BENCH_NUM_MEASUREMENTS) {
419 debug_printf("BENCH DEQUEUE TX: %lu\n", bench_devq_deq_tx >> BENCH_NUM_MEASUREMENTS_BITS);
420 bench_devq_deq_tx = 0;
421 bench_devq_deq_count_tx = 0;
425 if (buf.flags & NETIF_RXFLAG) {
426 bench_devq_deq_rx += end - tsc_start;
427 bench_devq_deq_count_rx++;
428 if (bench_devq_deq_count_rx == BENCH_NUM_MEASUREMENTS) {
429 debug_printf("BENCH DEQUEUE RX: %lu\n", bench_devq_deq_rx >> BENCH_NUM_MEASUREMENTS_BITS);
430 bench_devq_deq_rx = 0;
431 bench_devq_deq_count_rx = 0;
437 if (err_is_fail(err)) {
438 if (err_no(err) == DEVQ_ERR_QUEUE_EMPTY) {
444 struct pbuf *p = net_buf_get_by_region(st->pool, buf.rid, buf.offset);
446 NETDEBUG("netif=%p, ERROR. No PBUF found for rid=%u, "
447 "offset=%"PRIxLPADDR "\n", netif, buf.rid, buf.offset);
448 debug_printf("BUFFER NOT FOUND!!!!");
455 struct net_buf_p *nb = (struct net_buf_p *)p;
457 assert((buf.valid_data + buf.valid_length) < nb->region->buffer_size);
459 if (nb->magic != 0xdeadbeefcafebabe || nb->enqueued != 1 || nb->allocated != 1 || nb->flags != buf.flags) {
460 debug_printf("ERROR: pbuf=%p, rid=%u, offset=%lx magic=%lx, enq=%u, alloc=%u, flags=%lx (%lx)\n",
461 p, nb->region->regionid, nb->offset, nb->magic, nb->enqueued, nb->allocated, nb->flags, buf.flags);
464 assert(nb->magic == 0xdeadbeefcafebabe);
465 assert(nb->flags == buf.flags);
466 assert(nb->enqueued == 1);
467 assert(nb->allocated == 1);
474 ((struct net_buf_p *)p)->timestamp = rdtsc();
477 if (buf.flags & NETIF_TXFLAG) {
478 NETDEBUG("netif=%p, TX done of pbuf=%p (rid=%u, offset=%"PRIxLPADDR ")\n",
479 netif, p, buf.rid, buf.offset);
483 assert(!(buf.flags & NETIF_RXFLAG));
485 } else if (buf.flags & NETIF_RXFLAG) {
486 NETDEBUG("netif=%p, RX done of pbuf=%p (rid=%u, offset=%"PRIxLPADDR ")\n",
487 netif, p, buf.rid, buf.offset);
489 p->len = buf.valid_length;
491 p->payload += buf.valid_data;
493 assert(!(buf.flags & NETIF_TXFLAG));
495 if (st->netif.input(p, &st->netif) != ERR_OK) {
496 net_if_add_rx_buf(&st->netif, p);
498 /* XXX: do this at another time ? */
499 p = net_buf_alloc(st->pool);
501 nb = (struct net_buf_p *)p;
502 assert(nb->magic == 0xdeadbeefcafebabe);
503 assert(nb->allocated == 1);
504 assert(nb->enqueued == 0);
505 assert(nb->flags == 0);
509 net_if_add_rx_buf(&st->netif, p);
511 USER_PANIC("Could not allocate a receive buffer\n");
515 debug_printf("WARNING: got buffer without a flag\n");
526 * @brief polls all added network interfaces
528 * @return SYS_ERR_OK on success, errval on failure
530 errval_t net_if_poll_all(void)
532 NETDEBUG("polling all interfaces\n");
535 struct netif *netif = netif_list;
537 err = net_if_poll(netif);
538 if (err_is_fail(err)) {
539 DEBUG_ERR(err, "failed to poll network interface");