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