libnet: adding switch for turning on interrupts
[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/deferred.h>
22
23
24 #include <net_interfaces/flags.h>
25 #include "networking_internal.h"
26
27 struct net_state state = {0};
28
29 #define NETWORKING_DEFAULT_QUEUE_ID 0
30 #define NETWORKING_BUFFER_COUNT (4096 * 3)
31 #define NETWORKING_BUFFER_RX_POPULATE (4096 - 10)
32 #define NETWORKING_BUFFER_SIZE  2048
33
34
35 #define NET_USE_INTERRUPTS 1
36
37
38 #define NETDEBUG_SUBSYSTEM "net"
39
40 /**
41  * @brief obtains the default setting for initializaion of the driver
42  *
43  * @param queue     returns the queue to be used
44  * @param cardname  returns the card name to be used
45  *
46  * @return SYS_ERR_OK on success, SKB_ERR_* on failure
47  */
48 errval_t networking_get_defaults(uint64_t *queue, char **cardname)
49 {
50     /* TODO: get the values from the SKB */
51
52     *queue = NETWORKING_DEFAULT_QUEUE_ID;
53     *cardname = "sfn5122f";
54
55     return SYS_ERR_OK;
56 }
57
58 static void int_handler(void* args)
59 {
60     struct net_state *st = devq_get_state(args);
61
62     net_if_poll(&st->netif);
63 }
64
65 static errval_t create_loopback_queue (uint64_t queueid, struct devq **retqueue)
66 {
67     errval_t err;
68
69     debug_printf("net: creating loopback queue.\n");
70
71     err = loopback_queue_create((struct loopback_queue **)retqueue);
72     if (err_is_fail(err)) {
73         return err;
74     }
75
76     return SYS_ERR_OK;
77 }
78
79 static errval_t create_driver_queue (uint64_t queueid, struct devq **retqueue)
80 {
81     return SYS_ERR_OK;
82 }
83
84
85 static errval_t create_e10k_queue (uint64_t queueid, struct devq **retqueue)
86 {
87     return SYS_ERR_OK;
88 }
89
90 static errval_t create_sfn5122f_queue (uint64_t queueid, struct devq **retqueue)
91 {
92
93     return sfn5122f_queue_create((struct sfn5122f_queue**)retqueue, int_handler,
94                                 false /*userlevel network feature*/,
95                                 NET_USE_INTERRUPTS /* user interrupts*/);
96 }
97
98
99 typedef errval_t (*queue_create_fn)(uint64_t queueid, struct devq **retqueue);
100 struct networking_card
101 {
102     char *cardname;
103     queue_create_fn createfn;
104 } networking_cards [] = {
105     { "loopback", create_loopback_queue},
106     { "e1000", create_driver_queue},
107     { "e10k", create_e10k_queue},
108     { "sfn5122f", create_sfn5122f_queue},
109     { NULL, NULL}
110 };
111
112
113 /**
114  * @brief creates a queue to the given card and the queueid
115  *
116  * @param cardname  network card to create the queue for
117  * @param queueid   queueid of the network card
118  * @param retqueue  returns the pointer to the queue
119  *
120  * @return SYS_ERR_OK on success, errval on failure
121  */
122 errval_t networking_create_queue(const char *cardname, uint64_t queueid,
123                                  struct devq **retqueue)
124 {
125     debug_printf("net: creating queue for card='%s', queueid=%" PRIu64 "...\n",
126                   cardname, queueid);
127
128     struct networking_card *nc = networking_cards;
129     while(nc->cardname != NULL) {
130         if (strncmp(cardname, nc->cardname, strlen(nc->cardname)) == 0) {
131             return nc->createfn(queueid, retqueue);
132         }
133         nc++;
134     }
135
136     debug_printf("net: ERROR unknown queue. card='%s', queueid=%" PRIu64 "\n",
137                   cardname, queueid);
138
139     return -1;
140 }
141
142 errval_t networking_get_mac(struct devq *q, uint8_t *hwaddr, uint8_t hwaddrlen) {
143     debug_printf("net: obtaining MAC address for card.\n");
144     errval_t err;
145
146     uint64_t card_mac;
147     err = devq_control(q, 0, 0, &card_mac);
148     if (err_is_fail(err)) {
149         return err;
150     }
151
152     memcpy(hwaddr, &card_mac, hwaddrlen);
153
154     SMEMCPY(hwaddr, &card_mac, hwaddrlen);
155
156     debug_printf("got mac: %x:%x:%x:%x:%x:%x\n",
157                  hwaddr[0], hwaddr[1],hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
158
159     return SYS_ERR_OK;
160 }
161
162 errval_t networking_poll(void)
163 {
164
165 #if NET_USE_INTERRUPTS
166     return event_dispatch_non_block(get_default_waitset());
167 #else
168     struct net_state *st = &state;
169     return net_if_poll(&st->netif);
170 #endif
171 }
172
173 static void timer_callback(void *data)
174 {
175
176     void (*lwip_callback) (void) = data;
177   //  NETD_DEBUG("timer_callback: triggering %p\n", lwip_callback);
178 //    wrapper_perform_lwip_work();
179     lwip_callback();
180
181 //    NETD_DEBUG("timer_callback: terminated\n");
182 }
183
184 /**
185  * @brief
186  * @return
187  */
188 errval_t networking_init_default(void) {
189     errval_t err;
190
191     struct net_state *st = &state;
192
193     if(st->initialized) {
194         debug_printf("WARNING. initialize called twice. Ignoring\n");
195         return SYS_ERR_OK;
196     }
197
198     NETDEBUG("initializing networking...\n");
199
200     // obtain the settings to create the queue
201     err = networking_get_defaults(&st->queueid, &st->cardname);
202     if (err_is_fail(err)) {
203         return err;
204     }
205
206     // create the queue
207     err = networking_create_queue(st->cardname, st->queueid, &st->queue);
208     if (err_is_fail(err)) {
209         return err;
210     }
211
212     devq_set_state(st->queue, st);
213
214     // initialize LWIP
215     NETDEBUG("initializing LWIP...\n");
216     lwip_init();
217
218     /* create buffers */
219     err = net_buf_init(st->queue, NETWORKING_BUFFER_COUNT,
220                                  NETWORKING_BUFFER_SIZE, &st->pool);
221     if (err_is_fail(err)) {
222         goto out_err1;
223     }
224
225     NETDEBUG("creating netif for LWIP...\n");
226     err = net_if_init_devq(&st->netif, st->queue);
227     if (err_is_fail(err)) {
228         goto out_err2;
229     }
230
231     err = net_if_add(&st->netif, st);
232     if (err_is_fail(err)) {
233         goto out_err2;
234     }
235
236     NETDEBUG("setting default netif...\n");
237    // netif_set_default(&st->netif);
238
239
240     NETDEBUG("adding RX buffers\n");
241
242     for (int i = 0; i < NETWORKING_BUFFER_RX_POPULATE; i++) {
243         struct pbuf *p = net_buf_alloc(st->pool);
244         if (p == NULL) {
245             NETDEBUG("net: WARNING there was no buffer\n");
246             break;
247         }
248         err = net_if_add_rx_buf(&st->netif, p);
249         if (err_is_fail(err)) {
250             break;
251         }
252     }
253
254
255     NETDEBUG("starting DHCP...\n");
256     err_t lwip_err = dhcp_start(&st->netif);
257     if(lwip_err != ERR_OK) {
258         printf("ERRRRRR dhcp start: %i\n", lwip_err);
259     }
260
261     static struct periodic_event dhcp_fine_timer;
262     static struct periodic_event dhcp_coarse_timer;
263
264     /* DHCP fine timer */
265     err = periodic_event_create(&dhcp_fine_timer, get_default_waitset(),
266                                 (DHCP_FINE_TIMER_MSECS * 1000),
267                                 MKCLOSURE(timer_callback, dhcp_fine_tmr));
268     assert(err_is_ok(err));
269
270     /* DHCP coarse timer */
271     err = periodic_event_create(&dhcp_coarse_timer, get_default_waitset(),
272                                 (DHCP_COARSE_TIMER_MSECS * 1000),
273                                 MKCLOSURE(timer_callback, dhcp_coarse_tmr));
274     assert(err_is_ok(err));
275
276
277     printf("waiting for DHCP to complete");
278     while(ip_addr_cmp(&st->netif.ip_addr, IP_ADDR_ANY)) {
279         event_dispatch_non_block(get_default_waitset());
280         networking_poll();
281
282     }
283     printf("OK\nDHCP completed.\n");
284
285     NETDEBUG("initialization complete.\n");
286
287     return SYS_ERR_OK;
288
289     out_err2:
290         // TODO: clear buffers
291
292     out_err1:
293         // TODO: cleanup queue
294
295
296
297     return err;
298 }
299