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// stdlib includes 11 12// barrelfish includes 13 14// lwip includes 15#include "lwip/init.h" 16#include "lwip/netif.h" 17#include "lwip/ip.h" 18#include "lwip/dhcp.h" 19#include "lwip/prot/ethernet.h" 20#include "lwip/timeouts.h" 21 22#include <barrelfish/barrelfish.h> 23#include <barrelfish/deferred.h> 24#include <barrelfish/waitset.h> 25#include <barrelfish/waitset_chan.h> 26 27#include <net/net_filter.h> 28#include <net_sockets/net_sockets.h> 29#include <net_interfaces/flags.h> 30#include "networking_internal.h" 31#include "net_queue_internal.h" 32 33struct net_state state = {0}; 34struct waitset_chanstate net_loopback_poll_channel; 35struct deferred_event net_lwip_timer; 36 37#define NETWORKING_DEFAULT_QUEUE_ID 0 38#define NETWORKING_BUFFER_COUNT (4096 * 3) 39#define NETWORKING_BUFFER_RX_POPULATE (4096 - 10) 40#define NETWORKING_BUFFER_SIZE 2048 41 42static const char* default_name = "net_sockets_server"; 43 44#define NETDEBUG_SUBSYSTEM "net" 45 46/** 47 * @brief obtains the default setting for initializaion of the driver 48 * 49 * @param queue returns the queue to be used 50 * @param cardname returns the card name to be used 51 * 52 * @return SYS_ERR_OK on success, SKB_ERR_* on failure 53 */ 54errval_t networking_get_defaults(uint64_t *queue, const char **cardname, uint32_t *flags) 55{ 56 /* TODO: get some reasonable values */ 57 58 *queue = NETWORKING_DEFAULT_QUEUE_ID; 59 *cardname = default_name; 60 *flags = NET_FLAGS_POLLING | NET_FLAGS_BLOCKING_INIT; 61 62 return SYS_ERR_OK; 63} 64 65static void int_handler(void* args) 66{ 67 NETDEBUG("Enter int_handler!\n"); 68 struct net_state *st = devq_get_state(args); 69 70 if (st) { 71 net_if_poll(&st->netif); 72 net_lwip_timeout(); 73 } 74} 75 76static void net_loopback_poll(void *arg) 77{ 78 netif_poll_all(); 79 net_lwip_timeout(); 80} 81 82void net_if_trigger_loopback(void) 83{ 84 errval_t err; 85 86 err = waitset_chan_trigger(&net_loopback_poll_channel); 87 assert(err_is_ok(err)); 88} 89 90void net_lwip_timeout(void) 91{ 92 errval_t err; 93 94 sys_check_timeouts(); 95 deferred_event_cancel(&net_lwip_timer); 96 uint32_t delay = sys_timeouts_sleeptime(); 97 if (delay != 0xffffffff) { 98 err = deferred_event_register(&net_lwip_timer, get_default_waitset(), 99 delay * 1000, MKCLOSURE((void (*)(void *))net_lwip_timeout, NULL)); 100 assert(err_is_ok(err)); 101 } 102} 103 104/** 105 * @brief creates a queue to the given card and the queueid 106 * 107 * @param cardname network card to create the queue for 108 * @param ep endpoint to networking card, possibly null 109 * @param queueid queueid of the network card 110 * @param retqueue returns endpoint to netfilter interface of this queue 111 * @param retqueue returns the pointer to the queue 112 * 113 * @return SYS_ERR_OK on success, errval on failure 114 */ 115errval_t networking_create_queue(const char *cardname, struct capref* ep, 116 uint64_t* queueid, struct capref* filter_ep, 117 struct devq **retqueue) 118{ 119 struct net_state *st = get_default_net_state(); 120 bool poll = st->flags & NET_FLAGS_POLLING; 121 bool default_q = st->flags & NET_FLAGS_DEFAULT_QUEUE; 122 return net_queue_internal_create(int_handler, cardname, ep, queueid, default_q, 123 poll, filter_ep, retqueue); 124} 125 126 127static errval_t networking_poll_st(struct net_state *st) 128{ 129 event_dispatch_non_block(get_default_waitset()); 130 if (st->flags & NET_FLAGS_POLLING) { 131 return net_if_poll(&st->netif); 132 } else { 133 return event_dispatch(get_default_waitset()); 134 } 135} 136 137/** 138 * @brief initializes the networking library with a given device queue 139 * 140 * @param st the networking state to initialize 141 * @param q the device queue to initialize the networking on 142 * @param flags supplied initialization flags 143 * 144 * @return SYS_ERR_OK on success, errval on failure 145 */ 146static errval_t networking_init_with_queue_st(struct net_state *st, struct devq *q, 147 net_flags_t flags) 148{ 149 errval_t err; 150 151 NETDEBUG("initializing networking with devq=%p, flags=%" PRIx32 "...\n", q, 152 flags); 153 154 if (st->initialized) { 155 debug_printf("WARNING. initialize called twice. Ignoring\n"); 156 return SYS_ERR_OK; 157 } 158 159 /* set the variables */ 160 st->flags = flags; 161 st->queue = q; 162 st->initialized = true; 163 st->waitset = get_default_waitset(); 164 165 /* associate the net state with the device queue */ 166 devq_set_state(st->queue, st); 167 168 /* create buffers and add them to the interface*/ 169 err = net_buf_pool_alloc(st->queue, NETWORKING_BUFFER_COUNT, 170 NETWORKING_BUFFER_SIZE, &st->pool); 171 if (err_is_fail(err)) { 172 //net_if_destroy(&st->netif); 173 goto out_err1; 174 } 175 176 deferred_event_init(&net_lwip_timer); 177 /* initialize the device queue */ 178 NETDEBUG("initializing LWIP...\n"); 179 lwip_init(); 180 181 /* create the LWIP network interface and initialize it */ 182 NETDEBUG("creating netif for LWIP...\n"); 183 err = net_if_init_devq(&st->netif, st->queue); 184 if (err_is_fail(err)) { 185 goto out_err1; 186 } 187 188 err = net_if_add(&st->netif, st); 189 if (err_is_fail(err)) { 190 goto out_err1; 191 } 192 193 if (!(flags & NET_FLAGS_NO_NET_FILTER) && st->hw_filter) { 194 NETDEBUG("initializing hw filter...\n"); 195 196 if (!capref_is_null(st->filter_ep)) { 197 debug_printf("Connecting to net filter interface using EP \n"); 198 err = net_filter_init_with_ep(&st->filter, st->filter_ep); 199 if (err_is_fail(err)) { 200 USER_PANIC("Init filter infrastructure failed: %s \n", err_getstring(err)); 201 } 202 } else { 203 debug_printf("Connecting to net filter interface using name \n"); 204 err = net_filter_init(&st->filter, st->cardname); 205 if (err_is_fail(err)) { 206 USER_PANIC("Init filter infrastructure failed: %s \n", err_getstring(err)); 207 } 208 } 209 } 210 211 NETDEBUG("setting default netif...\n"); 212 netif_set_default(&st->netif); 213 214 NETDEBUG("adding RX buffers\n"); 215 for (int i = 0; i < NETWORKING_BUFFER_RX_POPULATE; i++) { 216 struct pbuf *p = net_buf_alloc(st->pool); 217 if (p == NULL) { 218 NETDEBUG("net: WARNING there was no buffer\n"); 219 break; 220 } 221 err = net_if_add_rx_buf(&st->netif, p); 222 if (err_is_fail(err)) { 223 break; 224 } 225 } 226 227 if (flags & NET_FLAGS_DO_DHCP) { 228 err = dhcpd_start(flags); 229 if (err_is_fail(err)) { 230 DEBUG_ERR(err, "failed to start DHCP.\n"); 231 } 232 233 err = arp_service_start(); 234 if (err_is_fail(err)) { 235 DEBUG_ERR(err, "failed to start the ARP service\n"); 236 } 237 } else { 238 /* get static IP config */ 239 err = net_config_static_ip_query(flags); 240 if (err_is_fail(err)) { 241 DEBUG_ERR(err, "failed to set IP.\n"); 242 } 243 244 err = arp_service_subscribe(); 245 if (err_is_fail(err)) { 246 DEBUG_ERR(err, "failed to subscribte the ARP service\n"); 247 } 248 } 249 250 waitset_chanstate_init(&net_loopback_poll_channel, CHANTYPE_OTHER); 251 net_loopback_poll_channel.persistent = true; 252 err = waitset_chan_register(get_default_waitset(), &net_loopback_poll_channel, 253 MKCLOSURE(net_loopback_poll, NULL)); 254 255 NETDEBUG("initialization complete.\n"); 256 257 return SYS_ERR_OK; 258 259 out_err1: 260 st->initialized = false; 261 262 return err; 263 264} 265 266/** 267 * @brief initializes the networking library 268 * 269 * @param st the networking state to be initalized 270 * @param nic the nic to use with the networking library 271 * @param ep endpoint to the nic, ignored if NULL 272 * @param flags flags to use to initialize the networking library 273 * 274 * @return SYS_ERR_OK on success, errval on failure 275 */ 276static errval_t networking_init_st(struct net_state *st, const char *nic, net_flags_t flags) 277{ 278 errval_t err; 279 280 NETDEBUG("initializing networking with nic=%s, flags=%" PRIx32 "...\n", nic, 281 flags); 282 283 if(st->initialized) { 284 NETDEBUG("WARNING. initialize called twice. Ignoring\n"); 285 return SYS_ERR_OK; 286 } 287 288 st->cardname = nic; 289 st->flags = flags; 290 291 // default no hw filters 292 st->hw_filter = false; 293 294 // if the NIC has a net_sockets_server prependend -> connect to net_socket server 295 // ontop of a nic 296 if (strncmp("net_sockets_server", nic, strlen("net_sockets_server")) == 0) { 297 return net_sockets_init_with_card(nic); 298 } else { 299 /* create the queue wit the given nic and card name */ 300 err = networking_create_queue(nic, NULL, &st->queueid, &st->filter_ep, &st->queue); 301 if (err_is_fail(err)) { 302 return err; 303 } 304 305 assert(st->queue != NULL); 306 307 err = networking_init_with_queue_st(st, st->queue, flags); 308 if (err_is_fail(err)) { 309 // devq_destroy(st->queue); 310 } 311 312 return err; 313 } 314} 315 316/** 317 * @brief initializes the networking with the defaults 318 * 319 * @param st the networking state to be initialized 320 * 321 * @return SYS_ERR_OK on sucess, errval on failure 322 */ 323static errval_t networking_init_default_st(struct net_state *st) 324{ 325 errval_t err; 326 327 NETDEBUG("initializing networking with default options...\n"); 328 329 if(st->initialized) { 330 NETDEBUG("WARNING. initialize called twice. Ignoring\n"); 331 return SYS_ERR_OK; 332 } 333 334 // obtain the settings to create the queue 335 err = networking_get_defaults(&st->queueid, &st->cardname, &st->flags); 336 if (err_is_fail(err)) { 337 return err; 338 } 339 340 return networking_init_st(st, st->cardname, st->flags); 341} 342 343 344 345/* 346 * =========================================================================== 347 * Public interface 348 * =========================================================================== 349 */ 350 351/** 352 * @brief initializes the networking library with a given device queue 353 * 354 * @param q the device queue to initialize the networking on 355 * @param flags supplied initialization flags 356 * 357 * @return SYS_ERR_OK on success, errval on failure 358 */ 359errval_t networking_init_with_queue(struct devq *q, net_flags_t flags) 360{ 361 struct net_state *st = get_default_net_state(); 362 return networking_init_with_queue_st(st, q, flags); 363} 364 365/** 366 * @brief initializes the networking library 367 * 368 * @param nic the nic to use with the networking library 369 * @param flags flags to use to initialize the networking library 370 * 371 * @return SYS_ERR_OK on success, errval on failure 372 */ 373errval_t networking_init_with_nic(const char *nic, net_flags_t flags) 374{ 375 struct net_state *st = get_default_net_state(); 376 return networking_init_st(st, nic, flags); 377} 378 379/** 380 * @brief initializes the networking library 381 * 382 * @param nic the nic to use with the networking library 383 * @param ep endpoint to the nic 384 * @param flags flags to use to initialize the networking library 385 * 386 * @return SYS_ERR_OK on success, errval on failure 387 */ 388errval_t networking_init_with_ep(const char *nic, struct capref ep, 389 net_flags_t flags) 390{ 391 errval_t err; 392 393 struct net_state *st = get_default_net_state(); 394 st->flags = flags; 395 st->cardname = nic; 396 397 /* create the queue wit the given nic and card name */ 398 err = networking_create_queue(nic, &ep, &st->queueid, &st->filter_ep, 399 &st->queue); 400 if (err_is_fail(err)) { 401 return err; 402 } 403 404 return networking_init_with_queue_st(st, st->queue, flags); 405} 406 407 408/** 409 * @brief initializes the networking with the defaults 410 * 411 * @return SYS_ERR_OK on success, errval on failure 412 */ 413errval_t networking_init_default(void) 414{ 415 struct net_state *st = get_default_net_state(); 416 if (!st->initialized) { 417 return networking_init_default_st(st); 418 } 419 return SYS_ERR_OK; 420} 421 422 423/** 424 * @brief polls the network for new packets 425 * 426 * @return SYS_ERR_OK on success, errval on failure 427 */ 428errval_t networking_poll(void) 429{ 430 //return net_if_poll_all(); 431 struct net_state *st = &state; 432 return networking_poll_st(st); 433} 434 435 436/** 437 * @brief Install L3/L4 filter 438 * 439 * @param tcp should TCP packets be filtered or UPD 440 * @param src_ip source ip of the filter, 0 for wildcard 441 * @param src_port source port of the filter, 0 for wildcard 442 * @param dst_port destination port fo the filter 443 * 444 * @return SYS_ERR_OK on success, NET_FILTER_ERR_* on failure 445 */ 446errval_t networking_install_ip_filter(bool tcp, struct in_addr *src, 447 uint16_t src_port, uint16_t dst_port) 448{ 449 errval_t err; 450 if (!state.hw_filter) { 451 debug_printf("Not adding filter as there are no HW filters"); 452 return SYS_ERR_OK; 453 } 454 455 if (state.filter == NULL) { 456 return NET_FILTER_ERR_NOT_INITIALIZED; 457 } 458 459 struct net_filter_state *st = state.filter; 460 461 // get current config 462 struct in_addr dst_ip; 463 err = netif_get_ipconfig(&dst_ip, NULL, NULL); 464 if (err_is_fail(err)) { 465 return err; 466 } 467 468 struct net_filter_ip ip = { 469 .qid = state.queueid, 470 .ip_src = (uint32_t) src->s_addr, 471 .ip_dst = (uint32_t) dst_ip.s_addr, 472 .port_dst = dst_port, 473 .port_src = src_port, 474 }; 475 476 if (tcp) { 477 ip.type = NET_FILTER_TCP; 478 } else { 479 ip.type = NET_FILTER_UDP; 480 } 481 482 return net_filter_ip_install(st, &ip); 483} 484 485/** 486 * @brief Remove L3/L4 filter 487 * 488 * @param tcp should TCP packets be filtered or UPD 489 * @param src_ip source ip of the filter, 0 for wildcard 490 * @param src_port source port of the filter, 0 for wildcard 491 * @param dst_port destination port fo the filter 492 * 493 * @return SYS_ERR_OK on success, NET_FILTER_ERR_* on failure 494 */ 495errval_t networking_remove_ip_filter(bool tcp, struct in_addr *src, 496 uint16_t src_port, uint16_t dst_port) 497{ 498 499 errval_t err; 500 if (!state.hw_filter) { 501 debug_printf("Not removing filter as there are no HW filters"); 502 return SYS_ERR_OK; 503 } 504 505 if (state.filter == NULL) { 506 return NET_FILTER_ERR_NOT_INITIALIZED; 507 } 508 509 struct net_filter_state *st = state.filter; 510 511 // get current config 512 struct in_addr dst_ip; 513 err = netif_get_ipconfig(&dst_ip, NULL, NULL); 514 if (err_is_fail(err)) { 515 return err; 516 } 517 518 struct net_filter_ip ip = { 519 .qid = state.queueid, 520 .ip_src = (uint32_t) src->s_addr, 521 .ip_dst = (uint32_t) dst_ip.s_addr, 522 .port_dst = dst_port, 523 .port_src = src_port, 524 }; 525 526 if (tcp) { 527 ip.type = NET_FILTER_TCP; 528 } else { 529 ip.type = NET_FILTER_UDP; 530 } 531 532 return net_filter_ip_remove(st, &ip); 533} 534