libnet: HW filter disable/enable on queue creation
[barrelfish] / lib / net / net.c
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_interfaces/flags.h>
29 #include "networking_internal.h"
30 #include "net_queue_internal.h"
31
32 struct net_state state = {0};
33 struct waitset_chanstate net_loopback_poll_channel;
34 struct deferred_event net_lwip_timer;
35
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
40
41
42 #define NETDEBUG_SUBSYSTEM "net"
43
44 /**
45  * @brief obtains the default setting for initializaion of the driver
46  *
47  * @param queue     returns the queue to be used
48  * @param cardname  returns the card name to be used
49  *
50  * @return SYS_ERR_OK on success, SKB_ERR_* on failure
51  */
52 errval_t networking_get_defaults(uint64_t *queue, const char **cardname, uint32_t *flags)
53 {
54     /* TODO: get the values from the SKB */
55
56     *queue = NETWORKING_DEFAULT_QUEUE_ID;
57     //*cardname = "e10k";
58     *cardname = "sfn5122f";
59     *flags = NET_FLAGS_POLLING | NET_FLAGS_BLOCKING_INIT;
60     //*flags = NET_FLAGS_POLLING;
61
62     return SYS_ERR_OK;
63 }
64
65 static void int_handler(void* args)
66 {
67     struct net_state *st = devq_get_state(args);
68
69     net_if_poll(&st->netif);
70     net_lwip_timeout();
71 }
72
73 static void net_loopback_poll(void *arg)
74 {
75     netif_poll_all();
76     net_lwip_timeout();
77 }
78
79 void net_if_trigger_loopback(void)
80 {
81     errval_t err;
82     
83     err = waitset_chan_trigger(&net_loopback_poll_channel);
84     assert(err_is_ok(err));
85 }
86
87 void net_lwip_timeout(void)
88 {
89     errval_t err;
90
91     sys_check_timeouts();
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));
98     }
99 }
100
101 /**
102  * @brief creates a queue to the given card and the queueid
103  *
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
107  *
108  * @return SYS_ERR_OK on success, errval on failure
109  */
110 errval_t networking_create_queue(const char *cardname, uint64_t* queueid,
111                                  struct devq **retqueue)
112 {
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,
117                                      poll, retqueue); 
118 }
119
120
121 static errval_t networking_poll_st(struct net_state *st)
122 {
123     event_dispatch_non_block(get_default_waitset());
124     if (st->flags & NET_FLAGS_POLLING) {
125         return net_if_poll(&st->netif);
126     } else {
127         return event_dispatch_non_block(get_default_waitset());
128     }
129 }
130
131 /**
132  * @brief initializes the networking library with a given device queue
133  *
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
137  *
138  * @return SYS_ERR_OK on success, errval on failure
139  */
140 static errval_t networking_init_with_queue_st(struct net_state *st, struct devq *q,
141                                               net_flags_t flags)
142 {
143     errval_t err;
144
145     NETDEBUG("initializing networking with devq=%p, flags=%" PRIx32 "...\n", q,
146              flags);
147
148     if (st->initialized) {
149         debug_printf("WARNING. initialize called twice. Ignoring\n");
150         return SYS_ERR_OK;
151     }
152
153     /* set the variables */
154     st->flags = flags;
155     st->queue = q;
156     st->initialized = true;
157     st->waitset = get_default_waitset();
158
159     /* associate the net state with the device queue */
160     devq_set_state(st->queue, st);
161
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);
167         goto out_err1;
168     }
169
170     deferred_event_init(&net_lwip_timer);
171     /* initialize the device queue */
172     NETDEBUG("initializing LWIP...\n");
173     lwip_init();
174
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)) {
179         goto out_err1;
180     }
181
182     err = net_if_add(&st->netif, st);
183     if (err_is_fail(err)) {
184         goto out_err1;
185     }
186
187     if (!(flags & NET_FLAGS_NO_NET_FILTER) || !st->hw_filter) {
188         NETDEBUG("initializing hw filter...\n");
189
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));
193         }
194     }
195
196     NETDEBUG("setting default netif...\n");
197     netif_set_default(&st->netif);
198
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);
202         if (p == NULL) {
203             NETDEBUG("net: WARNING there was no buffer\n");
204             break;
205         }
206         err = net_if_add_rx_buf(&st->netif, p);
207         if (err_is_fail(err)) {
208             break;
209         }
210     }
211
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");
216         }
217
218         err = arp_service_start();
219         if (err_is_fail(err)) {
220             DEBUG_ERR(err,  "failed to start the ARP service\n");
221         }
222     } else {
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");
227         }
228
229         err = arp_service_subscribe();
230         if (err_is_fail(err)) {
231             DEBUG_ERR(err, "failed to subscribte the ARP service\n");
232         }
233     }
234
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));
239
240     NETDEBUG("initialization complete.\n");
241
242     return SYS_ERR_OK;
243
244     out_err1:
245     st->initialized = false;
246
247     return err;
248
249 }
250
251 /**
252  * @brief initializes the networking library
253  *
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
257  *
258  * @return SYS_ERR_OK on success, errval on failure
259  */
260 static errval_t networking_init_st(struct net_state *st, const char *nic,
261                                    net_flags_t flags)
262 {
263     errval_t err;
264
265     NETDEBUG("initializing networking with nic=%s, flags=%" PRIx32 "...\n", nic,
266              flags);
267
268     if(st->initialized) {
269         NETDEBUG("WARNING. initialize called twice. Ignoring\n");
270         return SYS_ERR_OK;
271     }
272
273     st->cardname = nic;
274     st->flags = flags;
275     // default no hw filters
276     st->hw_filter = false;
277
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)) {
281         return err;
282     }
283
284     assert(st->queue != NULL);
285
286     err = networking_init_with_queue_st(st, st->queue, flags);
287     if (err_is_fail(err)) {
288        // devq_destroy(st->queue);
289     }
290
291     return err;
292 }
293
294 /**
295  * @brief initializes the networking with the defaults
296  *
297  * @param st    the networking state to be initialized
298  *
299  * @return SYS_ERR_OK on sucess, errval on failure
300  */
301 static errval_t networking_init_default_st(struct net_state *st)
302 {
303     errval_t err;
304
305     NETDEBUG("initializing networking with default options...\n");
306
307     if(st->initialized) {
308         NETDEBUG("WARNING. initialize called twice. Ignoring\n");
309         return SYS_ERR_OK;
310     }
311
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)) {
315         return err;
316     }
317
318     return networking_init_st(st, st->cardname, st->flags);
319 }
320
321
322
323 /*
324  * ===========================================================================
325  * Public interface
326  * ===========================================================================
327  */
328
329 /**
330  * @brief initializes the networking library with a given device queue
331  *
332  * @param q         the device queue to initialize the networking on
333  * @param flags     supplied initialization flags
334  *
335  * @return SYS_ERR_OK on success, errval on failure
336  */
337 errval_t networking_init_with_queue(struct devq *q, net_flags_t flags)
338 {
339     struct net_state *st = get_default_net_state();
340     return networking_init_with_queue_st(st, q, flags);
341 }
342
343 /**
344  * @brief initializes the networking library
345  *
346  * @param nic       the nic to use with the networking library
347  * @param flags     flags to use to initialize the networking library
348  *
349  * @return SYS_ERR_OK on success, errval on failure
350  */
351 errval_t networking_init(const char *nic, net_flags_t flags)
352 {
353     struct net_state *st = get_default_net_state();
354     return networking_init_st(st, nic, flags);
355 }
356
357
358 /**
359  * @brief initializes the networking with the defaults
360  *
361  * @return SYS_ERR_OK on success, errval on failure
362  */
363 errval_t networking_init_default(void)
364 {
365     struct net_state *st = get_default_net_state();
366     return networking_init_default_st(st);
367 }
368
369
370 /**
371  * @brief polls the network for new packets
372  *
373  * @return SYS_ERR_OK on success, errval on failure
374  */
375 errval_t networking_poll(void)
376 {
377     struct net_state *st = &state;
378     return networking_poll_st(st);
379 }
380
381
382 /**
383  * @brief Install L3/L4 filter
384  *
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
389  *
390  * @return SYS_ERR_OK on success, NET_FILTER_ERR_* on failure
391  */
392 errval_t networking_install_ip_filter(bool tcp, struct in_addr *src,
393                                       uint16_t src_port, uint16_t dst_port)
394 {
395     errval_t err;
396     if (state.filter == NULL) {
397         return NET_FILTER_ERR_NOT_INITIALIZED;
398     }
399
400     struct net_filter_state *st = state.filter;
401
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)) {
406         return err;
407     }
408     
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,
415     };
416
417     if (tcp) {
418         ip.type = NET_FILTER_TCP;
419     } else {
420         ip.type = NET_FILTER_UDP;
421     }
422     
423     return net_filter_ip_install(st, &ip);
424 }
425
426 /**
427  * @brief Remove L3/L4 filter
428  *
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
433  *
434  * @return SYS_ERR_OK on success, NET_FILTER_ERR_* on failure
435  */
436 errval_t networking_remove_ip_filter(bool tcp, struct in_addr *src,
437                                      uint16_t src_port, uint16_t dst_port)
438 {
439
440     errval_t err;
441     if (state.filter == NULL) {
442         return NET_FILTER_ERR_NOT_INITIALIZED;
443     }
444
445     struct net_filter_state *st = state.filter;
446
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)) {
451         return err;
452     }
453     
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,
460     };
461
462     if (tcp) {
463         ip.type = NET_FILTER_TCP;
464     } else {
465         ip.type = NET_FILTER_UDP;
466     }
467     
468     return net_filter_ip_remove(st, &ip);
469 }