6f2268971f7d0e20d508f8f6a572f651ab7d832b
[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 // 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)
92 {
93     if (st->cardname[5] != ':') {
94         return SYS_ERR_OK;
95     }
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);
99     if (parsed != 5) {
100         return SYS_ERR_OK;
101     }
102
103     return e1000_queue_create((struct e1000_queue**)retqueue, vendor, deviceid,
104                               bus, device, function, 1, int_handler);
105 }
106
107 static errval_t create_e10k_queue (struct net_state *st, uint64_t* queueid,
108                                    struct devq **retqueue)
109 {
110     errval_t err;
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);
116     return err;
117 }
118
119 static errval_t create_sfn5122f_queue (struct net_state *st, uint64_t* queueid,
120                                        struct devq **retqueue)
121 {
122     errval_t err;
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);
128     return err;
129 }
130
131
132 typedef errval_t (*queue_create_fn)(struct net_state *, uint64_t*, struct devq **);
133 struct networking_card
134 {
135     char *cardname;
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},
143     { NULL, NULL}
144 };
145
146
147 /**
148  * @brief creates a queue to the given card and the queueid
149  *
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
153  *
154  * @return SYS_ERR_OK on success, errval on failure
155  */
156 static errval_t net_create_queue(struct net_state *st, const char *cardname,
157                                  uint64_t* queueid, struct devq **retqueue)
158 {
159     debug_printf("net: creating queue for card='%s'...\n",
160                   cardname);
161
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);
166         }
167         nc++;
168     }
169
170     debug_printf("net: ERROR unknown queue. card='%s', queueid=%" PRIu64 "\n",
171                   cardname, *queueid);
172
173     return -1;
174 }
175
176 /**
177  * @brief creates a queue to the given card and the queueid
178  *
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
182  *
183  * @return SYS_ERR_OK on success, errval on failure
184  */
185 errval_t networking_create_queue(const char *cardname, uint64_t* queueid,
186                                  struct devq **retqueue)
187 {
188     struct net_state *st = get_default_net_state();
189
190     return net_create_queue(st, cardname, queueid, retqueue);
191 }
192
193
194
195 static errval_t networking_poll_st(struct net_state *st)
196 {
197     event_dispatch_non_block(get_default_waitset());
198     if (st->flags & NET_FLAGS_POLLING) {
199         return net_if_poll(&st->netif);
200     } else {
201         return event_dispatch_non_block(get_default_waitset());
202     }
203 }
204
205
206
207
208 /**
209  * @brief initializes the networking library with a given device queue
210  *
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
214  *
215  * @return SYS_ERR_OK on success, errval on failure
216  */
217 static errval_t networking_init_with_queue_st(struct net_state *st,struct devq *q,
218                                               net_flags_t flags)
219 {
220     errval_t err;
221
222     NETDEBUG("initializing networking with devq=%p, flags=%" PRIx32 "...\n", q,
223              flags);
224
225     if (st->initialized) {
226         debug_printf("WARNING. initialize called twice. Ignoring\n");
227         return SYS_ERR_OK;
228     }
229
230     /* set the variables */
231     st->flags = flags;
232     st->queue = q;
233     st->initialized = true;
234     st->waitset = get_default_waitset();
235
236     /* associate the net state with the device queue */
237     devq_set_state(st->queue, st);
238
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);
244         goto out_err1;
245     }
246
247     /* initialize the device queue */
248     NETDEBUG("initializing LWIP...\n");
249     lwip_init();
250
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)) {
255         goto out_err1;
256     }
257
258     err = net_if_add(&st->netif, st);
259     if (err_is_fail(err)) {
260         goto out_err1;
261     }
262
263
264     NETDEBUG("initializing hw filter...\n");
265
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));
269     // }
270
271     NETDEBUG("setting default netif...\n");
272    // netif_set_default(&st->netif);
273
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);
277         if (p == NULL) {
278             NETDEBUG("net: WARNING there was no buffer\n");
279             break;
280         }
281         err = net_if_add_rx_buf(&st->netif, p);
282         if (err_is_fail(err)) {
283             break;
284         }
285     }
286
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");
291         }
292
293         err = arp_service_start();
294         if (err_is_fail(err)) {
295             DEBUG_ERR(err,  "failed to start the ARP service\n");
296         }
297     } else {
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");
302         }
303
304         err = arp_service_subscribe();
305         if (err_is_fail(err)) {
306             DEBUG_ERR(err, "failed to subscribte the ARP service\n");
307         }
308     }
309
310     NETDEBUG("initialization complete.\n");
311
312     return SYS_ERR_OK;
313
314     out_err1:
315     st->initialized = false;
316
317     return err;
318
319 }
320
321 /**
322  * @brief initializes the networking library
323  *
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
327  *
328  * @return SYS_ERR_OK on success, errval on failure
329  */
330 static errval_t networking_init_st(struct net_state *st, const char *nic,
331                                    net_flags_t flags)
332 {
333     errval_t err;
334
335     NETDEBUG("initializing networking with nic=%s, flags=%" PRIx32 "...\n", nic,
336              flags);
337
338     if(st->initialized) {
339         NETDEBUG("WARNING. initialize called twice. Ignoring\n");
340         return SYS_ERR_OK;
341     }
342
343     st->cardname = nic;
344     st->flags = flags;
345
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)) {
349         return err;
350     }
351
352     err = networking_init_with_queue_st(st, st->queue, flags);
353     if (err_is_fail(err)) {
354        // devq_destroy(st->queue);
355     }
356
357     return err;
358 }
359
360 /**
361  * @brief initializes the networking with the defaults
362  *
363  * @param st    the networking state to be initialized
364  *
365  * @return SYS_ERR_OK on sucess, errval on failure
366  */
367 static errval_t networking_init_default_st(struct net_state *st)
368 {
369     errval_t err;
370
371     NETDEBUG("initializing networking with default options...\n");
372
373     if(st->initialized) {
374         NETDEBUG("WARNING. initialize called twice. Ignoring\n");
375         return SYS_ERR_OK;
376     }
377
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)) {
381         return err;
382     }
383
384     return networking_init_st(st, st->cardname, st->flags);
385 }
386
387
388
389 /*
390  * ===========================================================================
391  * Public interface
392  * ===========================================================================
393  */
394
395 /**
396  * @brief initializes the networking library with a given device queue
397  *
398  * @param q         the device queue to initialize the networking on
399  * @param flags     supplied initialization flags
400  *
401  * @return SYS_ERR_OK on success, errval on failure
402  */
403 errval_t networking_init_with_queue(struct devq *q, net_flags_t flags)
404 {
405     struct net_state *st = get_default_net_state();
406     return networking_init_with_queue_st(st, q, flags);
407 }
408
409 /**
410  * @brief initializes the networking library
411  *
412  * @param nic       the nic to use with the networking library
413  * @param flags     flags to use to initialize the networking library
414  *
415  * @return SYS_ERR_OK on success, errval on failure
416  */
417 errval_t networking_init(const char *nic, net_flags_t flags)
418 {
419     struct net_state *st = get_default_net_state();
420     return networking_init_st(st, nic, flags);
421 }
422
423
424 /**
425  * @brief initializes the networking with the defaults
426  *
427  * @return SYS_ERR_OK on success, errval on failure
428  */
429 errval_t networking_init_default(void)
430 {
431     struct net_state *st = get_default_net_state();
432     return networking_init_default_st(st);
433 }
434
435
436 /**
437  * @brief polls the network for new packets
438  *
439  * @return SYS_ERR_OK on success, errval on failure
440  */
441 errval_t networking_poll(void)
442 {
443     struct net_state *st = &state;
444     return networking_poll_st(st);
445 }
446
447
448 /**
449  * @brief Install L3/L4 filter
450  *
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
455  *
456  * @return SYS_ERR_OK on success, NET_FILTER_ERR_* on failure
457  */
458 errval_t networking_install_ip_filter(bool tcp, struct in_addr *src,
459                                       uint16_t src_port, uint16_t dst_port)
460 {
461     errval_t err;
462     if (state.filter == NULL) {
463         return NET_FILTER_ERR_NOT_INITIALIZED;
464     }
465
466     struct net_filter_state *st = state.filter;
467
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)) {
472         return err;
473     }
474     
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,
481     };
482
483     if (tcp) {
484         ip.type = NET_FILTER_TCP;
485     } else {
486         ip.type = NET_FILTER_UDP;
487     }
488     
489     return net_filter_ip_install(st, &ip);
490 }
491
492 /**
493  * @brief Remove L3/L4 filter
494  *
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
499  *
500  * @return SYS_ERR_OK on success, NET_FILTER_ERR_* on failure
501  */
502 errval_t networking_remove_ip_filter(bool tcp, struct in_addr *src,
503                                      uint16_t src_port, uint16_t dst_port)
504 {
505
506     errval_t err;
507     if (state.filter == NULL) {
508         return NET_FILTER_ERR_NOT_INITIALIZED;
509     }
510
511     struct net_filter_state *st = state.filter;
512
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)) {
517         return err;
518     }
519     
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,
526     };
527
528     if (tcp) {
529         ip.type = NET_FILTER_TCP;
530     } else {
531         ip.type = NET_FILTER_UDP;
532     }
533     
534     return net_filter_ip_remove(st, &ip);
535 }