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)) {
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));
271 NETDEBUG("setting default netif...\n");
272 // netif_set_default(&st->netif);
274 NETDEBUG("adding RX buffers\n");
275 for (int i = 0; i < NETWORKING_BUFFER_RX_POPULATE; i++) {
276 struct pbuf *p = net_buf_alloc(st->pool);
278 NETDEBUG("net: WARNING there was no buffer\n");
281 err = net_if_add_rx_buf(&st->netif, p);
282 if (err_is_fail(err)) {
287 if (flags & NET_FLAGS_DO_DHCP) {
288 err = dhcpd_start(flags);
289 if (err_is_fail(err)) {
290 DEBUG_ERR(err, "failed to start DHCP.\n");
293 err = arp_service_start();
294 if (err_is_fail(err)) {
295 DEBUG_ERR(err, "failed to start the ARP service\n");
298 /* get IP from dhcpd */
299 err = dhcpd_query(flags);
300 if (err_is_fail(err)) {
301 DEBUG_ERR(err, "failed to start DHCP.\n");
304 err = arp_service_subscribe();
305 if (err_is_fail(err)) {
306 DEBUG_ERR(err, "failed to subscribte the ARP service\n");
310 NETDEBUG("initialization complete.\n");
315 st->initialized = false;
322 * @brief initializes the networking library
324 * @param st the networking state to be initalized
325 * @param nic the nic to use with the networking library
326 * @param flags flags to use to initialize the networking library
328 * @return SYS_ERR_OK on success, errval on failure
330 static errval_t networking_init_st(struct net_state *st, const char *nic,
335 NETDEBUG("initializing networking with nic=%s, flags=%" PRIx32 "...\n", nic,
338 if(st->initialized) {
339 NETDEBUG("WARNING. initialize called twice. Ignoring\n");
346 /* create the queue wit the given nic and card name */
347 err = networking_create_queue(st->cardname, &st->queueid, &st->queue);
348 if (err_is_fail(err)) {
352 err = networking_init_with_queue_st(st, st->queue, flags);
353 if (err_is_fail(err)) {
354 // devq_destroy(st->queue);
361 * @brief initializes the networking with the defaults
363 * @param st the networking state to be initialized
365 * @return SYS_ERR_OK on sucess, errval on failure
367 static errval_t networking_init_default_st(struct net_state *st)
371 NETDEBUG("initializing networking with default options...\n");
373 if(st->initialized) {
374 NETDEBUG("WARNING. initialize called twice. Ignoring\n");
378 // obtain the settings to create the queue
379 err = networking_get_defaults(&st->queueid, &st->cardname, &st->flags);
380 if (err_is_fail(err)) {
384 return networking_init_st(st, st->cardname, st->flags);
390 * ===========================================================================
392 * ===========================================================================
396 * @brief initializes the networking library with a given device queue
398 * @param q the device queue to initialize the networking on
399 * @param flags supplied initialization flags
401 * @return SYS_ERR_OK on success, errval on failure
403 errval_t networking_init_with_queue(struct devq *q, net_flags_t flags)
405 struct net_state *st = get_default_net_state();
406 return networking_init_with_queue_st(st, q, flags);
410 * @brief initializes the networking library
412 * @param nic the nic to use with the networking library
413 * @param flags flags to use to initialize the networking library
415 * @return SYS_ERR_OK on success, errval on failure
417 errval_t networking_init(const char *nic, net_flags_t flags)
419 struct net_state *st = get_default_net_state();
420 return networking_init_st(st, nic, flags);
425 * @brief initializes the networking with the defaults
427 * @return SYS_ERR_OK on success, errval on failure
429 errval_t networking_init_default(void)
431 struct net_state *st = get_default_net_state();
432 return networking_init_default_st(st);
437 * @brief polls the network for new packets
439 * @return SYS_ERR_OK on success, errval on failure
441 errval_t networking_poll(void)
443 struct net_state *st = &state;
444 return networking_poll_st(st);
449 * @brief Install L3/L4 filter
451 * @param tcp should TCP packets be filtered or UPD
452 * @param src_ip source ip of the filter, 0 for wildcard
453 * @param src_port source port of the filter, 0 for wildcard
454 * @param dst_port destination port fo the filter
456 * @return SYS_ERR_OK on success, NET_FILTER_ERR_* on failure
458 errval_t networking_install_ip_filter(bool tcp, struct in_addr *src,
459 uint16_t src_port, uint16_t dst_port)
462 if (state.filter == NULL) {
463 return NET_FILTER_ERR_NOT_INITIALIZED;
466 struct net_filter_state *st = state.filter;
468 // get current config
469 struct in_addr dst_ip;
470 err = dhcpd_get_ipconfig(&dst_ip, NULL, NULL);
471 if (err_is_fail(err)) {
475 struct net_filter_ip ip = {
476 .qid = state.queueid,
477 .ip_src = (uint32_t) src->s_addr,
478 .ip_dst = (uint32_t) dst_ip.s_addr,
479 .port_dst = dst_port,
480 .port_src = src_port,
484 ip.type = NET_FILTER_TCP;
486 ip.type = NET_FILTER_UDP;
489 return net_filter_ip_install(st, &ip);
493 * @brief Remove L3/L4 filter
495 * @param tcp should TCP packets be filtered or UPD
496 * @param src_ip source ip of the filter, 0 for wildcard
497 * @param src_port source port of the filter, 0 for wildcard
498 * @param dst_port destination port fo the filter
500 * @return SYS_ERR_OK on success, NET_FILTER_ERR_* on failure
502 errval_t networking_remove_ip_filter(bool tcp, struct in_addr *src,
503 uint16_t src_port, uint16_t dst_port)
507 if (state.filter == NULL) {
508 return NET_FILTER_ERR_NOT_INITIALIZED;
511 struct net_filter_state *st = state.filter;
513 // get current config
514 struct in_addr dst_ip;
515 err = dhcpd_get_ipconfig(&dst_ip, NULL, NULL);
516 if (err_is_fail(err)) {
520 struct net_filter_ip ip = {
521 .qid = state.queueid,
522 .ip_src = (uint32_t) src->s_addr,
523 .ip_dst = (uint32_t) dst_ip.s_addr,
524 .port_dst = dst_port,
525 .port_src = src_port,
529 ip.type = NET_FILTER_TCP;
531 ip.type = NET_FILTER_UDP;
534 return net_filter_ip_remove(st, &ip);