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)
89 // cardname - "e1000:vendor:deviceid:bus:device:function"
90 static errval_t create_e1000_queue(struct net_state *st, uint64_t *queueid,
91 struct devq **retqueue)
93 if (st->cardname[5] != ':') {
96 uint32_t vendor, deviceid, bus, device, function;
97 unsigned parsed = sscanf(st->cardname + 6, "%x:%x:%x:%x:%x", &vendor,
98 &deviceid, &bus, &device, &function);
103 return e1000_queue_create((struct e1000_queue**)retqueue, vendor, deviceid,
104 bus, device, function, 1, int_handler);
107 static errval_t create_e10k_queue (struct net_state *st, uint64_t* queueid,
108 struct devq **retqueue)
111 err = e10k_queue_create((struct e10k_queue**)retqueue, int_handler,
112 false /*virtual functions*/,
113 !(st->flags & NET_FLAGS_POLLING), /* user interrupts*/
114 (st->flags & NET_FLAGS_DEFAULT_QUEUE));
115 *queueid = e10k_queue_get_id((struct e10k_queue*)*retqueue);
119 static errval_t create_sfn5122f_queue (struct net_state *st, uint64_t* queueid,
120 struct devq **retqueue)
123 err = sfn5122f_queue_create((struct sfn5122f_queue**)retqueue, int_handler,
124 false /*userlevel network feature*/,
125 !(st->flags & NET_FLAGS_POLLING) /* user interrupts*/,
126 (st->flags & NET_FLAGS_DEFAULT_QUEUE));
127 *queueid = sfn5122f_queue_get_id((struct sfn5122f_queue*)*retqueue);
132 typedef errval_t (*queue_create_fn)(struct net_state *, uint64_t*, struct devq **);
133 struct networking_card
136 queue_create_fn createfn;
137 } networking_cards [] = {
138 { "loopback", create_loopback_queue},
139 { "driver", create_driver_queue},
140 { "e1000", create_e1000_queue},
141 { "e10k", create_e10k_queue},
142 { "sfn5122f", create_sfn5122f_queue},
148 * @brief creates a queue to the given card and the queueid
150 * @param cardname network card to create the queue for
151 * @param queueid queueid of the network card
152 * @param retqueue returns the pointer to the queue
154 * @return SYS_ERR_OK on success, errval on failure
156 static errval_t net_create_queue(struct net_state *st, const char *cardname,
157 uint64_t* queueid, struct devq **retqueue)
159 debug_printf("net: creating queue for card='%s'...\n",
162 struct networking_card *nc = networking_cards;
163 while(nc->cardname != NULL) {
164 if (strncmp(cardname, nc->cardname, strlen(nc->cardname)) == 0) {
165 return nc->createfn(st, queueid, retqueue);
170 debug_printf("net: ERROR unknown queue. card='%s', queueid=%" PRIu64 "\n",
177 * @brief creates a queue to the given card and the queueid
179 * @param cardname network card to create the queue for
180 * @param queueid queueid of the network card
181 * @param retqueue returns the pointer to the queue
183 * @return SYS_ERR_OK on success, errval on failure
185 errval_t networking_create_queue(const char *cardname, uint64_t* queueid,
186 struct devq **retqueue)
188 struct net_state *st = get_default_net_state();
190 return net_create_queue(st, cardname, queueid, retqueue);
195 static errval_t networking_poll_st(struct net_state *st)
197 event_dispatch_non_block(get_default_waitset());
198 if (st->flags & NET_FLAGS_POLLING) {
199 return net_if_poll(&st->netif);
201 return event_dispatch_non_block(get_default_waitset());
209 * @brief initializes the networking library with a given device queue
211 * @param st the networking state to initialize
212 * @param q the device queue to initialize the networking on
213 * @param flags supplied initialization flags
215 * @return SYS_ERR_OK on success, errval on failure
217 static errval_t networking_init_with_queue_st(struct net_state *st, struct devq *q,
222 NETDEBUG("initializing networking with devq=%p, flags=%" PRIx32 "...\n", q,
225 if (st->initialized) {
226 debug_printf("WARNING. initialize called twice. Ignoring\n");
230 /* set the variables */
233 st->initialized = true;
234 st->waitset = get_default_waitset();
236 /* associate the net state with the device queue */
237 devq_set_state(st->queue, st);
239 /* create buffers and add them to the interface*/
240 err = net_buf_pool_alloc(st->queue, NETWORKING_BUFFER_COUNT,
241 NETWORKING_BUFFER_SIZE, &st->pool);
242 if (err_is_fail(err)) {
243 //net_if_destroy(&st->netif);
247 /* initialize the device queue */
248 NETDEBUG("initializing LWIP...\n");
251 /* create the LWIP network interface and initialize it */
252 NETDEBUG("creating netif for LWIP...\n");
253 err = net_if_init_devq(&st->netif, st->queue);
254 if (err_is_fail(err)) {
258 err = net_if_add(&st->netif, st);
259 if (err_is_fail(err)) {
263 if (!(flags & NET_FLAGS_NO_NET_FILTER)) {
264 NETDEBUG("initializing hw filter...\n");
266 err = net_filter_init(&st->filter, st->cardname);
267 if (err_is_fail(err)) {
268 USER_PANIC("Init filter infrastructure failed: %s \n", err_getstring(err));
272 NETDEBUG("setting default netif...\n");
273 netif_set_default(&st->netif);
275 NETDEBUG("adding RX buffers\n");
276 for (int i = 0; i < NETWORKING_BUFFER_RX_POPULATE; i++) {
277 struct pbuf *p = net_buf_alloc(st->pool);
279 NETDEBUG("net: WARNING there was no buffer\n");
282 err = net_if_add_rx_buf(&st->netif, p);
283 if (err_is_fail(err)) {
288 if (flags & NET_FLAGS_DO_DHCP) {
289 err = dhcpd_start(flags);
290 if (err_is_fail(err)) {
291 DEBUG_ERR(err, "failed to start DHCP.\n");
294 err = arp_service_start();
295 if (err_is_fail(err)) {
296 DEBUG_ERR(err, "failed to start the ARP service\n");
299 /* get static IP config */
300 err = net_config_static_ip_query(flags);
301 if (err_is_fail(err)) {
302 DEBUG_ERR(err, "failed to set IP.\n");
305 err = arp_service_subscribe();
306 if (err_is_fail(err)) {
307 DEBUG_ERR(err, "failed to subscribte the ARP service\n");
311 NETDEBUG("initialization complete.\n");
316 st->initialized = false;
323 * @brief initializes the networking library
325 * @param st the networking state to be initalized
326 * @param nic the nic to use with the networking library
327 * @param flags flags to use to initialize the networking library
329 * @return SYS_ERR_OK on success, errval on failure
331 static errval_t networking_init_st(struct net_state *st, const char *nic,
336 NETDEBUG("initializing networking with nic=%s, flags=%" PRIx32 "...\n", nic,
339 if(st->initialized) {
340 NETDEBUG("WARNING. initialize called twice. Ignoring\n");
347 /* create the queue wit the given nic and card name */
348 err = networking_create_queue(st->cardname, &st->queueid, &st->queue);
349 if (err_is_fail(err)) {
353 err = networking_init_with_queue_st(st, st->queue, flags);
354 if (err_is_fail(err)) {
355 // devq_destroy(st->queue);
362 * @brief initializes the networking with the defaults
364 * @param st the networking state to be initialized
366 * @return SYS_ERR_OK on sucess, errval on failure
368 static errval_t networking_init_default_st(struct net_state *st)
372 NETDEBUG("initializing networking with default options...\n");
374 if(st->initialized) {
375 NETDEBUG("WARNING. initialize called twice. Ignoring\n");
379 // obtain the settings to create the queue
380 err = networking_get_defaults(&st->queueid, &st->cardname, &st->flags);
381 if (err_is_fail(err)) {
385 return networking_init_st(st, st->cardname, st->flags);
391 * ===========================================================================
393 * ===========================================================================
397 * @brief initializes the networking library with a given device queue
399 * @param q the device queue to initialize the networking on
400 * @param flags supplied initialization flags
402 * @return SYS_ERR_OK on success, errval on failure
404 errval_t networking_init_with_queue(struct devq *q, net_flags_t flags)
406 struct net_state *st = get_default_net_state();
407 return networking_init_with_queue_st(st, q, flags);
411 * @brief initializes the networking library
413 * @param nic the nic to use with the networking library
414 * @param flags flags to use to initialize the networking library
416 * @return SYS_ERR_OK on success, errval on failure
418 errval_t networking_init(const char *nic, net_flags_t flags)
420 struct net_state *st = get_default_net_state();
421 return networking_init_st(st, nic, flags);
426 * @brief initializes the networking with the defaults
428 * @return SYS_ERR_OK on success, errval on failure
430 errval_t networking_init_default(void)
432 struct net_state *st = get_default_net_state();
433 return networking_init_default_st(st);
438 * @brief polls the network for new packets
440 * @return SYS_ERR_OK on success, errval on failure
442 errval_t networking_poll(void)
444 struct net_state *st = &state;
445 return networking_poll_st(st);
450 * @brief Install L3/L4 filter
452 * @param tcp should TCP packets be filtered or UPD
453 * @param src_ip source ip of the filter, 0 for wildcard
454 * @param src_port source port of the filter, 0 for wildcard
455 * @param dst_port destination port fo the filter
457 * @return SYS_ERR_OK on success, NET_FILTER_ERR_* on failure
459 errval_t networking_install_ip_filter(bool tcp, struct in_addr *src,
460 uint16_t src_port, uint16_t dst_port)
463 if (state.filter == NULL) {
464 return NET_FILTER_ERR_NOT_INITIALIZED;
467 struct net_filter_state *st = state.filter;
469 // get current config
470 struct in_addr dst_ip;
471 err = netif_get_ipconfig(&dst_ip, NULL, NULL);
472 if (err_is_fail(err)) {
476 struct net_filter_ip ip = {
477 .qid = state.queueid,
478 .ip_src = (uint32_t) src->s_addr,
479 .ip_dst = (uint32_t) dst_ip.s_addr,
480 .port_dst = dst_port,
481 .port_src = src_port,
485 ip.type = NET_FILTER_TCP;
487 ip.type = NET_FILTER_UDP;
490 return net_filter_ip_install(st, &ip);
494 * @brief Remove L3/L4 filter
496 * @param tcp should TCP packets be filtered or UPD
497 * @param src_ip source ip of the filter, 0 for wildcard
498 * @param src_port source port of the filter, 0 for wildcard
499 * @param dst_port destination port fo the filter
501 * @return SYS_ERR_OK on success, NET_FILTER_ERR_* on failure
503 errval_t networking_remove_ip_filter(bool tcp, struct in_addr *src,
504 uint16_t src_port, uint16_t dst_port)
508 if (state.filter == NULL) {
509 return NET_FILTER_ERR_NOT_INITIALIZED;
512 struct net_filter_state *st = state.filter;
514 // get current config
515 struct in_addr dst_ip;
516 err = netif_get_ipconfig(&dst_ip, NULL, NULL);
517 if (err_is_fail(err)) {
521 struct net_filter_ip ip = {
522 .qid = state.queueid,
523 .ip_src = (uint32_t) src->s_addr,
524 .ip_dst = (uint32_t) dst_ip.s_addr,
525 .port_dst = dst_port,
526 .port_src = src_port,
530 ip.type = NET_FILTER_TCP;
532 ip.type = NET_FILTER_UDP;
535 return net_filter_ip_remove(st, &ip);