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