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"
20 #include "lwip/timeouts.h"
22 #include <barrelfish/barrelfish.h>
23 #include <barrelfish/deferred.h>
24 #include <barrelfish/waitset.h>
25 #include <barrelfish/waitset_chan.h>
27 #include <net/net_filter.h>
28 #include <net_interfaces/flags.h>
29 #include "networking_internal.h"
30 #include "net_queue_internal.h"
32 struct net_state state = {0};
33 struct waitset_chanstate net_loopback_poll_channel;
34 struct deferred_event net_lwip_timer;
36 #define NETWORKING_DEFAULT_QUEUE_ID 0
37 #define NETWORKING_BUFFER_COUNT (4096 * 3)
38 #define NETWORKING_BUFFER_RX_POPULATE (4096 - 10)
39 #define NETWORKING_BUFFER_SIZE 2048
42 #define NETDEBUG_SUBSYSTEM "net"
45 * @brief obtains the default setting for initializaion of the driver
47 * @param queue returns the queue to be used
48 * @param cardname returns the card name to be used
50 * @return SYS_ERR_OK on success, SKB_ERR_* on failure
52 errval_t networking_get_defaults(uint64_t *queue, const char **cardname, uint32_t *flags)
54 /* TODO: get the values from the SKB */
56 *queue = NETWORKING_DEFAULT_QUEUE_ID;
58 *cardname = "sfn5122f";
59 *flags = NET_FLAGS_POLLING | NET_FLAGS_BLOCKING_INIT;
60 //*flags = NET_FLAGS_POLLING;
65 static void int_handler(void* args)
67 struct net_state *st = devq_get_state(args);
69 net_if_poll(&st->netif);
73 static void net_loopback_poll(void *arg)
79 void net_if_trigger_loopback(void)
83 err = waitset_chan_trigger(&net_loopback_poll_channel);
84 assert(err_is_ok(err));
87 void net_lwip_timeout(void)
92 deferred_event_cancel(&net_lwip_timer);
93 uint32_t delay = sys_timeouts_sleeptime();
94 if (delay != 0xffffffff) {
95 err = deferred_event_register(&net_lwip_timer, get_default_waitset(),
96 delay * 1000, MKCLOSURE((void (*)(void *))net_lwip_timeout, NULL));
97 assert(err_is_ok(err));
102 * @brief creates a queue to the given card and the queueid
104 * @param cardname network card to create the queue for
105 * @param queueid queueid of the network card
106 * @param retqueue returns the pointer to the queue
108 * @return SYS_ERR_OK on success, errval on failure
110 errval_t networking_create_queue(const char *cardname, uint64_t* queueid,
111 struct devq **retqueue)
113 struct net_state *st = get_default_net_state();
114 bool poll = st->flags & NET_FLAGS_POLLING;
115 bool default_q = st->flags & NET_FLAGS_DEFAULT_QUEUE;
116 return net_queue_internal_create(int_handler, cardname, queueid, default_q,
121 static errval_t networking_poll_st(struct net_state *st)
123 event_dispatch_non_block(get_default_waitset());
124 if (st->flags & NET_FLAGS_POLLING) {
125 return net_if_poll(&st->netif);
127 return event_dispatch(get_default_waitset());
132 * @brief initializes the networking library with a given device queue
134 * @param st the networking state to initialize
135 * @param q the device queue to initialize the networking on
136 * @param flags supplied initialization flags
138 * @return SYS_ERR_OK on success, errval on failure
140 static errval_t networking_init_with_queue_st(struct net_state *st, struct devq *q,
145 NETDEBUG("initializing networking with devq=%p, flags=%" PRIx32 "...\n", q,
148 if (st->initialized) {
149 debug_printf("WARNING. initialize called twice. Ignoring\n");
153 /* set the variables */
156 st->initialized = true;
157 st->waitset = get_default_waitset();
159 /* associate the net state with the device queue */
160 devq_set_state(st->queue, st);
162 /* create buffers and add them to the interface*/
163 err = net_buf_pool_alloc(st->queue, NETWORKING_BUFFER_COUNT,
164 NETWORKING_BUFFER_SIZE, &st->pool);
165 if (err_is_fail(err)) {
166 //net_if_destroy(&st->netif);
170 deferred_event_init(&net_lwip_timer);
171 /* initialize the device queue */
172 NETDEBUG("initializing LWIP...\n");
175 /* create the LWIP network interface and initialize it */
176 NETDEBUG("creating netif for LWIP...\n");
177 err = net_if_init_devq(&st->netif, st->queue);
178 if (err_is_fail(err)) {
182 err = net_if_add(&st->netif, st);
183 if (err_is_fail(err)) {
187 if (!(flags & NET_FLAGS_NO_NET_FILTER) && st->hw_filter) {
188 NETDEBUG("initializing hw filter...\n");
190 err = net_filter_init(&st->filter, st->cardname);
191 if (err_is_fail(err)) {
192 USER_PANIC("Init filter infrastructure failed: %s \n", err_getstring(err));
196 NETDEBUG("setting default netif...\n");
197 netif_set_default(&st->netif);
199 NETDEBUG("adding RX buffers\n");
200 for (int i = 0; i < NETWORKING_BUFFER_RX_POPULATE; i++) {
201 struct pbuf *p = net_buf_alloc(st->pool);
203 NETDEBUG("net: WARNING there was no buffer\n");
206 err = net_if_add_rx_buf(&st->netif, p);
207 if (err_is_fail(err)) {
212 if (flags & NET_FLAGS_DO_DHCP) {
213 err = dhcpd_start(flags);
214 if (err_is_fail(err)) {
215 DEBUG_ERR(err, "failed to start DHCP.\n");
218 err = arp_service_start();
219 if (err_is_fail(err)) {
220 DEBUG_ERR(err, "failed to start the ARP service\n");
223 /* get static IP config */
224 err = net_config_static_ip_query(flags);
225 if (err_is_fail(err)) {
226 DEBUG_ERR(err, "failed to set IP.\n");
229 err = arp_service_subscribe();
230 if (err_is_fail(err)) {
231 DEBUG_ERR(err, "failed to subscribte the ARP service\n");
235 waitset_chanstate_init(&net_loopback_poll_channel, CHANTYPE_OTHER);
236 net_loopback_poll_channel.persistent = true;
237 err = waitset_chan_register(get_default_waitset(), &net_loopback_poll_channel,
238 MKCLOSURE(net_loopback_poll, NULL));
240 NETDEBUG("initialization complete.\n");
245 st->initialized = false;
252 * @brief initializes the networking library
254 * @param st the networking state to be initalized
255 * @param nic the nic to use with the networking library
256 * @param flags flags to use to initialize the networking library
258 * @return SYS_ERR_OK on success, errval on failure
260 static errval_t networking_init_st(struct net_state *st, const char *nic,
265 NETDEBUG("initializing networking with nic=%s, flags=%" PRIx32 "...\n", nic,
268 if(st->initialized) {
269 NETDEBUG("WARNING. initialize called twice. Ignoring\n");
275 // default no hw filters
276 st->hw_filter = false;
278 /* create the queue wit the given nic and card name */
279 err = networking_create_queue(nic, &st->queueid, &st->queue);
280 if (err_is_fail(err)) {
284 assert(st->queue != NULL);
286 err = networking_init_with_queue_st(st, st->queue, flags);
287 if (err_is_fail(err)) {
288 // devq_destroy(st->queue);
295 * @brief initializes the networking with the defaults
297 * @param st the networking state to be initialized
299 * @return SYS_ERR_OK on sucess, errval on failure
301 static errval_t networking_init_default_st(struct net_state *st)
305 NETDEBUG("initializing networking with default options...\n");
307 if(st->initialized) {
308 NETDEBUG("WARNING. initialize called twice. Ignoring\n");
312 // obtain the settings to create the queue
313 err = networking_get_defaults(&st->queueid, &st->cardname, &st->flags);
314 if (err_is_fail(err)) {
318 return networking_init_st(st, st->cardname, st->flags);
324 * ===========================================================================
326 * ===========================================================================
330 * @brief initializes the networking library with a given device queue
332 * @param q the device queue to initialize the networking on
333 * @param flags supplied initialization flags
335 * @return SYS_ERR_OK on success, errval on failure
337 errval_t networking_init_with_queue(struct devq *q, net_flags_t flags)
339 struct net_state *st = get_default_net_state();
340 return networking_init_with_queue_st(st, q, flags);
344 * @brief initializes the networking library
346 * @param nic the nic to use with the networking library
347 * @param flags flags to use to initialize the networking library
349 * @return SYS_ERR_OK on success, errval on failure
351 errval_t networking_init(const char *nic, net_flags_t flags)
353 struct net_state *st = get_default_net_state();
354 return networking_init_st(st, nic, flags);
359 * @brief initializes the networking with the defaults
361 * @return SYS_ERR_OK on success, errval on failure
363 errval_t networking_init_default(void)
365 struct net_state *st = get_default_net_state();
366 return networking_init_default_st(st);
371 * @brief polls the network for new packets
373 * @return SYS_ERR_OK on success, errval on failure
375 errval_t networking_poll(void)
377 struct net_state *st = &state;
378 return networking_poll_st(st);
383 * @brief Install L3/L4 filter
385 * @param tcp should TCP packets be filtered or UPD
386 * @param src_ip source ip of the filter, 0 for wildcard
387 * @param src_port source port of the filter, 0 for wildcard
388 * @param dst_port destination port fo the filter
390 * @return SYS_ERR_OK on success, NET_FILTER_ERR_* on failure
392 errval_t networking_install_ip_filter(bool tcp, struct in_addr *src,
393 uint16_t src_port, uint16_t dst_port)
396 if (state.filter == NULL) {
397 return NET_FILTER_ERR_NOT_INITIALIZED;
400 struct net_filter_state *st = state.filter;
402 // get current config
403 struct in_addr dst_ip;
404 err = netif_get_ipconfig(&dst_ip, NULL, NULL);
405 if (err_is_fail(err)) {
409 struct net_filter_ip ip = {
410 .qid = state.queueid,
411 .ip_src = (uint32_t) src->s_addr,
412 .ip_dst = (uint32_t) dst_ip.s_addr,
413 .port_dst = dst_port,
414 .port_src = src_port,
418 ip.type = NET_FILTER_TCP;
420 ip.type = NET_FILTER_UDP;
423 return net_filter_ip_install(st, &ip);
427 * @brief Remove L3/L4 filter
429 * @param tcp should TCP packets be filtered or UPD
430 * @param src_ip source ip of the filter, 0 for wildcard
431 * @param src_port source port of the filter, 0 for wildcard
432 * @param dst_port destination port fo the filter
434 * @return SYS_ERR_OK on success, NET_FILTER_ERR_* on failure
436 errval_t networking_remove_ip_filter(bool tcp, struct in_addr *src,
437 uint16_t src_port, uint16_t dst_port)
441 if (state.filter == NULL) {
442 return NET_FILTER_ERR_NOT_INITIALIZED;
445 struct net_filter_state *st = state.filter;
447 // get current config
448 struct in_addr dst_ip;
449 err = netif_get_ipconfig(&dst_ip, NULL, NULL);
450 if (err_is_fail(err)) {
454 struct net_filter_ip ip = {
455 .qid = state.queueid,
456 .ip_src = (uint32_t) src->s_addr,
457 .ip_dst = (uint32_t) dst_ip.s_addr,
458 .port_dst = dst_port,
459 .port_src = src_port,
463 ip.type = NET_FILTER_TCP;
465 ip.type = NET_FILTER_UDP;
468 return net_filter_ip_remove(st, &ip);