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.
12 // barrelfish includes
15 #include "lwip/init.h"
16 #include "lwip/netif.h"
18 #include "lwip/dhcp.h"
19 #include "lwip/prot/ethernet.h"
21 #include <barrelfish/barrelfish.h>
22 #include <barrelfish/deferred.h>
24 #include <net/net_filter.h>
25 #include <net_interfaces/flags.h>
26 #include "networking_internal.h"
28 struct net_state state = {0};
30 #define NETWORKING_DEFAULT_QUEUE_ID 0
31 #define NETWORKING_BUFFER_COUNT (4096 * 3)
32 #define NETWORKING_BUFFER_RX_POPULATE (4096 - 10)
33 #define NETWORKING_BUFFER_SIZE 2048
36 #define NETDEBUG_SUBSYSTEM "net"
39 * @brief obtains the default setting for initializaion of the driver
41 * @param queue returns the queue to be used
42 * @param cardname returns the card name to be used
44 * @return SYS_ERR_OK on success, SKB_ERR_* on failure
46 errval_t networking_get_defaults(uint64_t *queue, const char **cardname, uint32_t *flags)
48 /* TODO: get the values from the SKB */
50 *queue = NETWORKING_DEFAULT_QUEUE_ID;
52 *cardname = "sfn5122f";
53 *flags = NET_FLAGS_POLLING | NET_FLAGS_BLOCKING_INIT;
54 //*flags = NET_FLAGS_POLLING;
59 static void int_handler(void* args)
61 struct net_state *st = devq_get_state(args);
63 net_if_poll(&st->netif);
66 static errval_t create_loopback_queue (struct net_state *st, uint64_t* queueid,
67 struct devq **retqueue)
71 debug_printf("net: creating loopback queue.\n");
74 err = loopback_queue_create((struct loopback_queue **)retqueue);
75 if (err_is_fail(err)) {
82 static errval_t create_driver_queue (struct net_state *st, uint64_t* queueid,
83 struct devq **retqueue)
90 static errval_t create_e10k_queue (struct net_state *st, uint64_t* queueid,
91 struct devq **retqueue)
94 err = e10k_queue_create((struct e10k_queue**)retqueue, int_handler,
95 false /*virtual functions*/,
96 !(st->flags & NET_FLAGS_POLLING) /* user interrupts*/);
97 *queueid = e10k_queue_get_id((struct e10k_queue*)*retqueue);
101 static errval_t create_sfn5122f_queue (struct net_state *st, uint64_t* queueid,
102 struct devq **retqueue)
105 err = sfn5122f_queue_create((struct sfn5122f_queue**)retqueue, int_handler,
106 false /*userlevel network feature*/,
107 !(st->flags & NET_FLAGS_POLLING) /* user interrupts*/,
108 (st->flags & NET_FLAGS_DEFAULT_QUEUE));
109 *queueid = sfn5122f_queue_get_id((struct sfn5122f_queue*)*retqueue);
114 typedef errval_t (*queue_create_fn)(struct net_state *, uint64_t*, struct devq **);
115 struct networking_card
118 queue_create_fn createfn;
119 } networking_cards [] = {
120 { "loopback", create_loopback_queue},
121 { "e1000", create_driver_queue},
122 { "e10k", create_e10k_queue},
123 { "sfn5122f", create_sfn5122f_queue},
129 * @brief creates a queue to the given card and the queueid
131 * @param cardname network card to create the queue for
132 * @param queueid queueid of the network card
133 * @param retqueue returns the pointer to the queue
135 * @return SYS_ERR_OK on success, errval on failure
137 static errval_t net_create_queue(struct net_state *st, const char *cardname,
138 uint64_t* queueid, struct devq **retqueue)
140 debug_printf("net: creating queue for card='%s'...\n",
143 struct networking_card *nc = networking_cards;
144 while(nc->cardname != NULL) {
145 if (strncmp(cardname, nc->cardname, strlen(nc->cardname)) == 0) {
146 return nc->createfn(st, queueid, retqueue);
151 debug_printf("net: ERROR unknown queue. card='%s', queueid=%" PRIu64 "\n",
158 * @brief creates a queue to the given card and the queueid
160 * @param cardname network card to create the queue for
161 * @param queueid queueid of the network card
162 * @param retqueue returns the pointer to the queue
164 * @return SYS_ERR_OK on success, errval on failure
166 errval_t networking_create_queue(const char *cardname, uint64_t* queueid,
167 struct devq **retqueue)
169 struct net_state *st = get_default_net_state();
171 return net_create_queue(st, cardname, queueid, retqueue);
176 static errval_t networking_poll_st(struct net_state *st)
178 event_dispatch_non_block(get_default_waitset());
179 if (st->flags & NET_FLAGS_POLLING) {
180 return net_if_poll(&st->netif);
182 return event_dispatch_non_block(get_default_waitset());
190 * @brief initializes the networking library with a given device queue
192 * @param st the networking state to initialize
193 * @param q the device queue to initialize the networking on
194 * @param flags supplied initialization flags
196 * @return SYS_ERR_OK on success, errval on failure
198 static errval_t networking_init_with_queue_st(struct net_state *st,struct devq *q,
203 NETDEBUG("initializing networking with devq=%p, flags=%" PRIx32 "...\n", q,
206 if(st->initialized) {
207 debug_printf("WARNING. initialize called twice. Ignoring\n");
211 /* set the variables */
214 st->initialized = true;
215 st->waitset = get_default_waitset();
217 /* associate the net state with the device queue */
218 devq_set_state(st->queue, st);
221 /* initialize the device queue */
222 NETDEBUG("initializing LWIP...\n");
225 /* create the LWIP network interface and initialize it */
226 NETDEBUG("creating netif for LWIP...\n");
227 err = net_if_init_devq(&st->netif, st->queue);
228 if (err_is_fail(err)) {
232 err = net_if_add(&st->netif, st);
233 if (err_is_fail(err)) {
238 NETDEBUG("initializing hw filter...\n");
240 err = net_filter_init(&st->filter, st->cardname);
241 if (err_is_fail(err)) {
242 USER_PANIC("Init filter infrastructure failed: %s \n", err_getstring(err));
245 NETDEBUG("setting default netif...\n");
246 // netif_set_default(&st->netif);
248 /* create buffers and add them to the interface*/
249 err = net_buf_pool_alloc(st->queue, NETWORKING_BUFFER_COUNT,
250 NETWORKING_BUFFER_SIZE, &st->pool);
251 if (err_is_fail(err)) {
252 //net_if_destroy(&st->netif);
256 NETDEBUG("adding RX buffers\n");
257 for (int i = 0; i < NETWORKING_BUFFER_RX_POPULATE; i++) {
258 struct pbuf *p = net_buf_alloc(st->pool);
260 NETDEBUG("net: WARNING there was no buffer\n");
263 err = net_if_add_rx_buf(&st->netif, p);
264 if (err_is_fail(err)) {
269 if (flags & NET_FLAGS_DO_DHCP) {
270 err = dhcpd_start(flags);
271 if (err_is_fail(err)) {
272 DEBUG_ERR(err, "failed to start DHCP.\n");
275 err = arp_service_start();
276 if (err_is_fail(err)) {
277 DEBUG_ERR(err, "failed to start the ARP service\n");
280 /* get IP from dhcpd */
281 err = dhcpd_query(flags);
282 if (err_is_fail(err)) {
283 DEBUG_ERR(err, "failed to start DHCP.\n");
286 err = arp_service_subscribe();
287 if (err_is_fail(err)) {
288 DEBUG_ERR(err, "failed to subscribte the ARP service\n");
292 NETDEBUG("initialization complete.\n");
297 st->initialized = false;
304 * @brief initializes the networking library
306 * @param st the networking state to be initalized
307 * @param nic the nic to use with the networking library
308 * @param flags flags to use to initialize the networking library
310 * @return SYS_ERR_OK on success, errval on failure
312 static errval_t networking_init_st(struct net_state *st, const char *nic,
317 NETDEBUG("initializing networking with nic=%s, flags=%" PRIx32 "...\n", nic,
320 if(st->initialized) {
321 NETDEBUG("WARNING. initialize called twice. Ignoring\n");
328 /* create the queue wit the given nic and card name */
329 err = networking_create_queue(st->cardname, &st->queueid, &st->queue);
330 if (err_is_fail(err)) {
334 err = networking_init_with_queue_st(st, st->queue, flags);
335 if (err_is_fail(err)) {
336 // devq_destroy(st->queue);
343 * @brief initializes the networking with the defaults
345 * @param st the networking state to be initialized
347 * @return SYS_ERR_OK on sucess, errval on failure
349 static errval_t networking_init_default_st(struct net_state *st)
353 NETDEBUG("initializing networking with default options...\n");
355 if(st->initialized) {
356 NETDEBUG("WARNING. initialize called twice. Ignoring\n");
360 // obtain the settings to create the queue
361 err = networking_get_defaults(&st->queueid, &st->cardname, &st->flags);
362 if (err_is_fail(err)) {
366 return networking_init_st(st, st->cardname, st->flags);
372 * ===========================================================================
374 * ===========================================================================
378 * @brief initializes the networking library with a given device queue
380 * @param q the device queue to initialize the networking on
381 * @param flags supplied initialization flags
383 * @return SYS_ERR_OK on success, errval on failure
385 errval_t networking_init_with_queue(struct devq *q, net_flags_t flags)
387 struct net_state *st = get_default_net_state();
388 return networking_init_with_queue_st(st, q, flags);
392 * @brief initializes the networking library
394 * @param nic the nic to use with the networking library
395 * @param flags flags to use to initialize the networking library
397 * @return SYS_ERR_OK on success, errval on failure
399 errval_t networking_init(const char *nic, net_flags_t flags)
401 struct net_state *st = get_default_net_state();
402 return networking_init_st(st, nic, flags);
407 * @brief initializes the networking with the defaults
409 * @return SYS_ERR_OK on success, errval on failure
411 errval_t networking_init_default(void)
413 struct net_state *st = get_default_net_state();
414 return networking_init_default_st(st);
419 * @brief polls the network for new packets
421 * @return SYS_ERR_OK on success, errval on failure
423 errval_t networking_poll(void)
425 struct net_state *st = &state;
426 return networking_poll_st(st);
431 * @brief Install L3/L4 filter
433 * @param tcp should TCP packets be filtered or UPD
434 * @param src_ip source ip of the filter, 0 for wildcard
435 * @param src_port source port of the filter, 0 for wildcard
436 * @param dst_port destination port fo the filter
438 * @return SYS_ERR_OK on success, NET_FILTER_ERR_* on failure
440 errval_t networking_install_ip_filter(bool tcp, ip_addr_t* src,
441 uint16_t src_port, uint16_t dst_port)
444 if (state.filter == NULL) {
445 return NET_FILTER_ERR_NOT_INITIALIZED;
448 struct net_filter_state *st = state.filter;
450 // get current config
452 err = dhcpd_get_ipconfig(&dst_ip, NULL, NULL);
453 if (err_is_fail(err)) {
457 struct net_filter_ip ip = {
458 .qid = state.queueid,
459 .ip_src = (uint32_t) src->addr,
460 .ip_dst = (uint32_t) dst_ip.addr,
461 .port_dst = dst_port,
462 .port_src = src_port,
466 ip.type = NET_FILTER_TCP;
468 ip.type = NET_FILTER_UDP;
471 return net_filter_ip_install(st, &ip);
475 * @brief Remove L3/L4 filter
477 * @param tcp should TCP packets be filtered or UPD
478 * @param src_ip source ip of the filter, 0 for wildcard
479 * @param src_port source port of the filter, 0 for wildcard
480 * @param dst_port destination port fo the filter
482 * @return SYS_ERR_OK on success, NET_FILTER_ERR_* on failure
484 errval_t networking_remove_ip_filter(bool tcp, ip_addr_t* src,
485 uint16_t src_port, uint16_t dst_port)
489 if (state.filter == NULL) {
490 return NET_FILTER_ERR_NOT_INITIALIZED;
493 struct net_filter_state *st = state.filter;
495 // get current config
497 err = dhcpd_get_ipconfig(&dst_ip, NULL, NULL);
498 if (err_is_fail(err)) {
502 struct net_filter_ip ip = {
503 .qid = state.queueid,
504 .ip_src = (uint32_t) src->addr,
505 .ip_dst = (uint32_t) dst_ip.addr,
506 .port_dst = dst_port,
507 .port_src = src_port,
511 ip.type = NET_FILTER_TCP;
513 ip.type = NET_FILTER_UDP;
516 return net_filter_ip_remove(st, &ip);