e10k: enabling requesting default queue
[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
21 #include <barrelfish/barrelfish.h>
22 #include <barrelfish/deferred.h>
23
24 #include <net/net_filter.h>
25 #include <net_interfaces/flags.h>
26 #include "networking_internal.h"
27
28 struct net_state state = {0};
29
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
34
35
36 #define NETDEBUG_SUBSYSTEM "net"
37
38 /**
39  * @brief obtains the default setting for initializaion of the driver
40  *
41  * @param queue     returns the queue to be used
42  * @param cardname  returns the card name to be used
43  *
44  * @return SYS_ERR_OK on success, SKB_ERR_* on failure
45  */
46 errval_t networking_get_defaults(uint64_t *queue, const char **cardname, uint32_t *flags)
47 {
48     /* TODO: get the values from the SKB */
49
50     *queue = NETWORKING_DEFAULT_QUEUE_ID;
51     //*cardname = "e10k";
52     *cardname = "sfn5122f";
53     *flags = NET_FLAGS_POLLING | NET_FLAGS_BLOCKING_INIT;
54     //*flags = NET_FLAGS_POLLING;
55
56     return SYS_ERR_OK;
57 }
58
59 static void int_handler(void* args)
60 {
61     struct net_state *st = devq_get_state(args);
62
63     net_if_poll(&st->netif);
64 }
65
66 static errval_t create_loopback_queue (struct net_state *st, uint64_t* queueid,
67                                        struct devq **retqueue)
68 {
69     errval_t err;
70
71     debug_printf("net: creating loopback queue.\n");
72
73     *queueid = 0;
74     err = loopback_queue_create((struct loopback_queue **)retqueue);
75     if (err_is_fail(err)) {
76         return err;
77     }
78
79     return SYS_ERR_OK;
80 }
81
82 static errval_t create_driver_queue (struct net_state *st, uint64_t* queueid,
83                                      struct devq **retqueue)
84 {
85     *queueid = 0;
86     return SYS_ERR_OK;
87 }
88
89
90 static errval_t create_e10k_queue (struct net_state *st, uint64_t* queueid,
91                                    struct devq **retqueue)
92 {
93     errval_t err;
94     err = e10k_queue_create((struct e10k_queue**)retqueue, int_handler,
95                             false /*virtual functions*/,
96                             !(st->flags & NET_FLAGS_POLLING), /* user interrupts*/
97                             (st->flags & NET_FLAGS_DEFAULT_QUEUE));
98     *queueid = e10k_queue_get_id((struct e10k_queue*)*retqueue);
99     return err;
100 }
101
102 static errval_t create_sfn5122f_queue (struct net_state *st, uint64_t* queueid, 
103                                        struct devq **retqueue)
104 {
105     errval_t err;
106     err = sfn5122f_queue_create((struct sfn5122f_queue**)retqueue, int_handler,
107                                 false /*userlevel network feature*/,
108                                 !(st->flags & NET_FLAGS_POLLING) /* user interrupts*/,
109                                 (st->flags & NET_FLAGS_DEFAULT_QUEUE));
110     *queueid = sfn5122f_queue_get_id((struct sfn5122f_queue*)*retqueue);
111     return err;
112 }
113
114
115 typedef errval_t (*queue_create_fn)(struct net_state *, uint64_t*, struct devq **);
116 struct networking_card
117 {
118     char *cardname;
119     queue_create_fn createfn;
120 } networking_cards [] = {
121     { "loopback", create_loopback_queue},
122     { "e1000", create_driver_queue},
123     { "e10k", create_e10k_queue},
124     { "sfn5122f", create_sfn5122f_queue},
125     { NULL, NULL}
126 };
127
128
129 /**
130  * @brief creates a queue to the given card and the queueid
131  *
132  * @param cardname  network card to create the queue for
133  * @param queueid   queueid of the network card
134  * @param retqueue  returns the pointer to the queue
135  *
136  * @return SYS_ERR_OK on success, errval on failure
137  */
138 static errval_t net_create_queue(struct net_state *st, const char *cardname,
139                                  uint64_t* queueid, struct devq **retqueue)
140 {
141     debug_printf("net: creating queue for card='%s'...\n",
142                   cardname);
143
144     struct networking_card *nc = networking_cards;
145     while(nc->cardname != NULL) {
146         if (strncmp(cardname, nc->cardname, strlen(nc->cardname)) == 0) {
147             return nc->createfn(st, queueid, retqueue);
148         }
149         nc++;
150     }
151
152     debug_printf("net: ERROR unknown queue. card='%s', queueid=%" PRIu64 "\n",
153                   cardname, *queueid);
154
155     return -1;
156 }
157
158 /**
159  * @brief creates a queue to the given card and the queueid
160  *
161  * @param cardname  network card to create the queue for
162  * @param queueid   queueid of the network card
163  * @param retqueue  returns the pointer to the queue
164  *
165  * @return SYS_ERR_OK on success, errval on failure
166  */
167 errval_t networking_create_queue(const char *cardname, uint64_t* queueid,
168                                  struct devq **retqueue)
169 {
170     struct net_state *st = get_default_net_state();
171
172     return net_create_queue(st, cardname, queueid, retqueue);
173 }
174
175
176
177 static errval_t networking_poll_st(struct net_state *st)
178 {
179     event_dispatch_non_block(get_default_waitset());
180     if (st->flags & NET_FLAGS_POLLING) {
181         return net_if_poll(&st->netif);
182     } else {
183         return event_dispatch_non_block(get_default_waitset());
184     }
185 }
186
187
188
189
190 /**
191  * @brief initializes the networking library with a given device queue
192  *
193  * @param st        the networking state to initialize
194  * @param q         the device queue to initialize the networking on
195  * @param flags     supplied initialization flags
196  *
197  * @return SYS_ERR_OK on success, errval on failure
198  */
199 static errval_t networking_init_with_queue_st(struct net_state *st,struct devq *q,
200                                               net_flags_t flags)
201 {
202     errval_t err;
203
204     NETDEBUG("initializing networking with devq=%p, flags=%" PRIx32 "...\n", q,
205              flags);
206
207     if(st->initialized) {
208         debug_printf("WARNING. initialize called twice. Ignoring\n");
209         return SYS_ERR_OK;
210     }
211
212     /* set the variables */
213     st->flags = flags;
214     st->queue = q;
215     st->initialized = true;
216     st->waitset = get_default_waitset();
217
218     /* associate the net state with the device queue */
219     devq_set_state(st->queue, st);
220
221
222     /* initialize the device queue */
223     NETDEBUG("initializing LWIP...\n");
224     lwip_init();
225
226     /* create the LWIP network interface and initialize it */
227     NETDEBUG("creating netif for LWIP...\n");
228     err = net_if_init_devq(&st->netif, st->queue);
229     if (err_is_fail(err)) {
230         goto out_err1;
231     }
232
233     err = net_if_add(&st->netif, st);
234     if (err_is_fail(err)) {
235         goto out_err1;
236     }
237
238
239     NETDEBUG("initializing hw filter...\n");
240
241     err = net_filter_init(&st->filter, st->cardname);
242     if (err_is_fail(err)) {
243         USER_PANIC("Init filter infrastructure failed: %s \n", err_getstring(err));
244     }
245
246     NETDEBUG("setting default netif...\n");
247    // netif_set_default(&st->netif);
248
249     /* create buffers and add them to the interface*/
250     err = net_buf_pool_alloc(st->queue, NETWORKING_BUFFER_COUNT,
251                              NETWORKING_BUFFER_SIZE, &st->pool);
252     if (err_is_fail(err)) {
253         //net_if_destroy(&st->netif);
254         goto out_err1;
255     }
256
257     NETDEBUG("adding RX buffers\n");
258     for (int i = 0; i < NETWORKING_BUFFER_RX_POPULATE; i++) {
259         struct pbuf *p = net_buf_alloc(st->pool);
260         if (p == NULL) {
261             NETDEBUG("net: WARNING there was no buffer\n");
262             break;
263         }
264         err = net_if_add_rx_buf(&st->netif, p);
265         if (err_is_fail(err)) {
266             break;
267         }
268     }
269
270     if (flags & NET_FLAGS_DO_DHCP) {
271         err = dhcpd_start(flags);
272         if (err_is_fail(err)) {
273             DEBUG_ERR(err, "failed to start DHCP.\n");
274         }
275
276         err = arp_service_start();
277         if (err_is_fail(err)) {
278             DEBUG_ERR(err,  "failed to start the ARP service\n");
279         }
280     } else {
281         /* get IP from dhcpd */
282         err = dhcpd_query(flags);
283         if (err_is_fail(err)) {
284             DEBUG_ERR(err, "failed to start DHCP.\n");
285         }
286
287         err = arp_service_subscribe();
288         if (err_is_fail(err)) {
289             DEBUG_ERR(err, "failed to subscribte the ARP service\n");
290         }
291     }
292
293     NETDEBUG("initialization complete.\n");
294
295     return SYS_ERR_OK;
296
297     out_err1:
298     st->initialized = false;
299
300     return err;
301
302 }
303
304 /**
305  * @brief initializes the networking library
306  *
307  * @param st        the networking state to be initalized
308  * @param nic       the nic to use with the networking library
309  * @param flags     flags to use to initialize the networking library
310  *
311  * @return SYS_ERR_OK on success, errval on failure
312  */
313 static errval_t networking_init_st(struct net_state *st, const char *nic,
314                                    net_flags_t flags)
315 {
316     errval_t err;
317
318     NETDEBUG("initializing networking with nic=%s, flags=%" PRIx32 "...\n", nic,
319              flags);
320
321     if(st->initialized) {
322         NETDEBUG("WARNING. initialize called twice. Ignoring\n");
323         return SYS_ERR_OK;
324     }
325
326     st->cardname = nic;
327     st->flags = flags;
328
329     /* create the queue wit the given nic and card name */
330     err = networking_create_queue(st->cardname, &st->queueid, &st->queue);
331     if (err_is_fail(err)) {
332         return err;
333     }
334
335     err = networking_init_with_queue_st(st, st->queue, flags);
336     if (err_is_fail(err)) {
337        // devq_destroy(st->queue);
338     }
339
340     return err;
341 }
342
343 /**
344  * @brief initializes the networking with the defaults
345  *
346  * @param st    the networking state to be initialized
347  *
348  * @return SYS_ERR_OK on sucess, errval on failure
349  */
350 static errval_t networking_init_default_st(struct net_state *st)
351 {
352     errval_t err;
353
354     NETDEBUG("initializing networking with default options...\n");
355
356     if(st->initialized) {
357         NETDEBUG("WARNING. initialize called twice. Ignoring\n");
358         return SYS_ERR_OK;
359     }
360
361     // obtain the settings to create the queue
362     err = networking_get_defaults(&st->queueid, &st->cardname, &st->flags);
363     if (err_is_fail(err)) {
364         return err;
365     }
366
367     return networking_init_st(st, st->cardname, st->flags);
368 }
369
370
371
372 /*
373  * ===========================================================================
374  * Public interface
375  * ===========================================================================
376  */
377
378 /**
379  * @brief initializes the networking library with a given device queue
380  *
381  * @param q         the device queue to initialize the networking on
382  * @param flags     supplied initialization flags
383  *
384  * @return SYS_ERR_OK on success, errval on failure
385  */
386 errval_t networking_init_with_queue(struct devq *q, net_flags_t flags)
387 {
388     struct net_state *st = get_default_net_state();
389     return networking_init_with_queue_st(st, q, flags);
390 }
391
392 /**
393  * @brief initializes the networking library
394  *
395  * @param nic       the nic to use with the networking library
396  * @param flags     flags to use to initialize the networking library
397  *
398  * @return SYS_ERR_OK on success, errval on failure
399  */
400 errval_t networking_init(const char *nic, net_flags_t flags)
401 {
402     struct net_state *st = get_default_net_state();
403     return networking_init_st(st, nic, flags);
404 }
405
406
407 /**
408  * @brief initializes the networking with the defaults
409  *
410  * @return SYS_ERR_OK on success, errval on failure
411  */
412 errval_t networking_init_default(void)
413 {
414     struct net_state *st = get_default_net_state();
415     return networking_init_default_st(st);
416 }
417
418
419 /**
420  * @brief polls the network for new packets
421  *
422  * @return SYS_ERR_OK on success, errval on failure
423  */
424 errval_t networking_poll(void)
425 {
426     struct net_state *st = &state;
427     return networking_poll_st(st);
428 }
429
430
431 /**
432  * @brief Install L3/L4 filter
433  *
434  * @param tcp       should TCP packets be filtered or UPD
435  * @param src_ip    source ip of the filter, 0 for wildcard
436  * @param src_port  source port of the filter, 0 for wildcard
437  * @param dst_port  destination port fo the filter       
438  *
439  * @return SYS_ERR_OK on success, NET_FILTER_ERR_* on failure
440  */
441 errval_t networking_install_ip_filter(bool tcp, ip_addr_t* src, 
442                                       uint16_t src_port, uint16_t dst_port)
443 {
444     errval_t err;
445     if (state.filter == NULL) {
446         return NET_FILTER_ERR_NOT_INITIALIZED;
447     }
448
449     struct net_filter_state *st = state.filter;
450
451     // get current config
452     ip_addr_t dst_ip;
453     err = dhcpd_get_ipconfig(&dst_ip, NULL, NULL);
454     if (err_is_fail(err)) {
455         return err;
456     }
457     
458     struct net_filter_ip ip = {
459         .qid = state.queueid,
460         .ip_src = (uint32_t) src->addr,
461         .ip_dst = (uint32_t) dst_ip.addr,
462         .port_dst = dst_port,
463         .port_src = src_port,
464     };
465
466     if (tcp) {
467         ip.type = NET_FILTER_TCP;
468     } else {
469         ip.type = NET_FILTER_UDP;
470     }
471     
472     return net_filter_ip_install(st, &ip);
473 }
474
475 /**
476  * @brief Remove L3/L4 filter
477  *
478  * @param tcp       should TCP packets be filtered or UPD
479  * @param src_ip    source ip of the filter, 0 for wildcard
480  * @param src_port  source port of the filter, 0 for wildcard
481  * @param dst_port  destination port fo the filter       
482  *
483  * @return SYS_ERR_OK on success, NET_FILTER_ERR_* on failure
484  */
485 errval_t networking_remove_ip_filter(bool tcp, ip_addr_t* src, 
486                                      uint16_t src_port, uint16_t dst_port)
487 {
488
489     errval_t err;
490     if (state.filter == NULL) {
491         return NET_FILTER_ERR_NOT_INITIALIZED;
492     }
493
494     struct net_filter_state *st = state.filter;
495
496     // get current config
497     ip_addr_t dst_ip;
498     err = dhcpd_get_ipconfig(&dst_ip, NULL, NULL);
499     if (err_is_fail(err)) {
500         return err;
501     }
502     
503     struct net_filter_ip ip = {
504         .qid = state.queueid,
505         .ip_src = (uint32_t) src->addr,
506         .ip_dst = (uint32_t) dst_ip.addr,
507         .port_dst = dst_port,
508         .port_src = src_port,
509     };
510
511     if (tcp) {
512         ip.type = NET_FILTER_TCP;
513     } else {
514         ip.type = NET_FILTER_UDP;
515     }
516     
517     return net_filter_ip_remove(st, &ip);
518 }