libnet: ARP resending more robust with periodic events
[barrelfish] / lib / net / arp.c
1 /**
2  * \file arp.c
3  * \brief
4  */
5
6
7 /*
8  * Copyright (c) 2017 ETH Zurich.
9  * All rights reserved.
10  *
11  * This file is distributed under the terms in the attached LICENSE file.
12  * If you do not find this file, copies can be found by writing to:
13  * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
14  */
15
16
17 #include <barrelfish/barrelfish.h>
18 #include <barrelfish/nameservice_client.h>
19 #include <collections/list.h>
20
21
22 #include <lwip/opt.h>       
23 #include <lwip/netif.h>
24 #include <lwip/timeouts.h>
25 #include <net/netif.h>
26
27 #include <netif/etharp.h>
28
29 #include <if/octopus_defs.h>
30 #include <if/net_ARP_defs.h>
31 #include <octopus/octopus.h>
32 #include <octopus/trigger.h>
33
34
35 #include "networking_internal.h"
36
37 ///< the debug subsystem
38 #define NETDEBUG_SUBSYSTEM "arpd"
39
40
41 #define ARP_ENTRY_FIELDS "{mac: %d, ip: %d}"
42 #define ARP_ENTRY "net.arp.%d {mac: %lu, ip: %d}"
43
44 #define ARP_ENTRY_REGEX "r'net\\.arp\\.[0-9]+' { mac: _, ip: _}"
45 #define ARP_RESEND_FREQ 500*1000
46
47 struct arp_request {
48     uint32_t ip;
49 };
50
51 static void arp_timer_callback(void *data)
52 {
53     errval_t err;
54     char* record;
55     char query[128];
56
57     struct net_state *st = (struct net_state*) data;
58
59     // remove all the outstanding ARPs that are finished
60     for (int i = 0; i < collections_list_size(st->outstanding_arp) ; i++) {
61         struct arp_request* req = (struct arp_request*) collections_list_get_ith_item(st->outstanding_arp, i);
62         sprintf(query, "net.arp.%d {mac: _ , ip: %d }", req->ip, req->ip);
63         err = oct_get(&record, query);
64         if (err_is_ok(err)) {
65             // remove from outstanding arps
66             collections_list_remove_ith_item(st->outstanding_arp, i);
67         }
68     }
69     
70     // no outstanding ARPs
71     if (collections_list_size(st->outstanding_arp) == 0) {
72         NETDEBUG("Stopping ARP periodic event \n");
73         err = periodic_event_cancel(&st->arp_send);
74         assert(err_is_ok(err));
75         return;
76     }
77
78     // Resend all other outstanding ARPs
79     for (int i = 0; i < collections_list_size(st->outstanding_arp) ; i++) {
80         struct arp_request* req = (struct arp_request*) collections_list_get_ith_item(st->outstanding_arp, i);
81         NETDEBUG("Starting ARP for ip %u \n", req->ip);
82         err = etharp_request(&st->netif, (ip4_addr_t*) &req->ip);
83         assert(err_is_ok(err));
84     }
85 }
86
87 static void arp_request_free(void *data)
88 {
89     free(data);
90 }
91
92 // Reuse existing Flounder interface
93 static void arp_force_lookup(struct net_ARP_binding *b,
94                              uint32_t ip)
95 {
96     errval_t err;
97     struct net_state *sta = (struct net_state*) b->st;
98
99     if (sta->outstanding_arp == NULL) {
100        collections_list_create(&sta->outstanding_arp, arp_request_free);
101        assert(sta->outstanding_arp != NULL); 
102     }    
103
104     if (collections_list_size(sta->outstanding_arp) == 0) {
105         NETDEBUG("Starting ARP periodic event\n");
106         err = periodic_event_create(&sta->arp_send, get_default_waitset(),
107                                     ARP_RESEND_FREQ, MKCLOSURE(arp_timer_callback, sta));
108         assert(err_is_ok(err));
109     }
110
111     struct arp_request* new_arp = malloc(sizeof(struct arp_request));
112     collections_list_insert(sta->outstanding_arp, new_arp);
113
114     // send one but if it fails, periodic event will call it again
115     err = etharp_request(&sta->netif, (ip4_addr_t*) &ip);
116     assert(err_is_ok(err));
117 } // end function: ARP_resolve_request
118
119
120 static struct net_ARP_rx_vtbl rx_arp_vtbl = {
121     .arp_force_lookup = arp_force_lookup,
122 };
123
124 /*****************************************************************
125 * Dealing with new connections
126 *****************************************************************/
127 static errval_t connect_ARP_cb(void *st, struct net_ARP_binding *b)
128 {   
129     b->st = st;
130     b->rx_vtbl = rx_arp_vtbl;
131     return SYS_ERR_OK;
132
133
134 /*****************************************************************
135 * exporting service
136 *****************************************************************/
137
138 static void export_ARP_cb(void *st, errval_t err, iref_t iref)
139 {
140     struct net_state *sta = st;
141
142     if (err_is_fail(err)) {
143         DEBUG_ERR(err, "service export failed");
144     }
145
146     // register this iref with the name service
147     err = nameservice_register("libnet_arp", iref);
148     if (err_is_fail(err)) {
149         DEBUG_ERR(err, "nameservice_register failed for [libnet_arp]");
150         abort(); // FIXME: Do I need abort after DEBUG_ERR?
151     }
152     sta->arp_running = true;
153 }
154
155 struct netif *arp_filter_netif(struct pbuf *p, struct netif *netif, uint16_t type)
156 {
157     if (type != ETHTYPE_ARP) {
158         return netif;
159     }
160
161     struct net_state *st = netif->state;
162
163     if (!st->arp_running) {
164         return netif;
165     }
166
167     if (p->len < SIZEOF_ETH_HDR || pbuf_header(p, (s16_t)-SIZEOF_ETH_HDR)) {
168         NETDEBUG("wrong packet size received\n");
169         return netif;
170     }
171
172     struct etharp_hdr *hdr = (struct etharp_hdr *)p->payload;
173
174     pbuf_header(p, (s16_t)SIZEOF_ETH_HDR);
175
176     /* RFC 826 "Packet Reception": */
177     if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) ||
178         (hdr->hwlen != ETH_HWADDR_LEN) ||
179         (hdr->protolen != sizeof(ip4_addr_t)) ||
180         (hdr->proto != PP_HTONS(ETHTYPE_IP)))  {
181       LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
182         ("etharp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",
183         hdr->hwtype, (u16_t)hdr->hwlen, hdr->proto, (u16_t)hdr->protolen));
184       return netif;
185     }
186
187     ip_addr_t ip;
188     IPADDR2_COPY(&ip, &hdr->sipaddr);
189
190     /* don't store any IPs */
191     if (ip_addr_cmp(&st->netif.ip_addr, IP_ADDR_ANY)) {
192         return netif;
193     }
194
195     uint64_t hwaddr = 0;
196     if (etharp_find_addr(netif, &ip, (struct eth_addr **)&hwaddr,
197                          (const ip4_addr_t **)&hwaddr) != -1) {
198         return netif;
199     }
200
201     /*
202      * If already exists, return
203      */
204
205     hwaddr = 0;
206     SMEMCPY(&hwaddr, hdr->shwaddr.addr, sizeof(hdr->shwaddr));
207
208     NETDEBUG("set " ARP_ENTRY "\n", ip.addr, hwaddr, ip.addr);
209
210     oct_set(ARP_ENTRY, ip.addr, hwaddr, ip.addr);
211
212     etharp_add_static_entry(&ip, &hdr->shwaddr);
213
214     return netif;
215 }
216
217 static errval_t arp_service_start_st(struct net_state *st)
218 {
219     errval_t err;
220
221     err = oct_init();
222     if (err_is_fail(err)) {
223         return err;
224     }
225
226     err = net_ARP_export(st, export_ARP_cb, connect_ARP_cb,
227                          get_default_waitset(), IDC_EXPORT_FLAGS_DEFAULT);
228     if (err_is_fail(err)) {
229         return err;
230     }
231
232     st->arp_running = true;
233
234     return SYS_ERR_OK;
235 }
236
237 errval_t arp_service_start(void)
238 {
239     return arp_service_start_st(get_default_net_state());
240 }
241
242 static  void arp_change_event(octopus_mode_t mode, const char* record, void* st)
243 {
244     errval_t err;
245
246     uint64_t ip, hwaddr;
247     err = oct_read(record, "_" ARP_ENTRY_FIELDS, &hwaddr, &ip);
248     if (err_is_fail(err)) {
249         DEBUG_ERR(err, "failed to read the entrie\n");
250     }
251
252     ip_addr_t ipaddr;
253     ipaddr.addr = (uint32_t)ip;
254
255     if (mode & OCT_ON_SET) {
256
257         NETDEBUG("adding ARP entries: ip=%u, mac=%lx\n", ipaddr.addr, hwaddr);
258
259         struct eth_addr mac;
260         SMEMCPY(mac.addr, &hwaddr, sizeof(mac));
261
262         etharp_add_static_entry(&ipaddr, &mac);
263     } else if (mode & OCT_ON_DEL) {
264         NETDEBUG("deleting ARP entries: ip=%u, mac=%lx\n", ipaddr.addr, hwaddr);
265         etharp_remove_static_entry(&ipaddr);
266     }
267 }
268
269
270
271 static errval_t arp_service_subscribe_st(struct net_state *st)
272 {
273     NETDEBUG("subscribing to ARP updates..\n");
274
275     errval_t err;
276     err = oct_init();
277     if (err_is_fail(err)) {
278         return err;
279     }
280
281     st->arp_running = false;
282
283     return oct_trigger_existing_and_watch(ARP_ENTRY_REGEX, arp_change_event,
284                                              st, &st->arp_triggerid);
285 }
286
287 errval_t arp_service_subscribe(void)
288 {
289     struct net_state *st = get_default_net_state();
290     return arp_service_subscribe_st(st);
291 }
292
293
294
295 static void bind_cb(void *st, errval_t err, struct net_ARP_binding *b)
296 {
297     assert(err_is_ok(err));
298     struct net_state* sta = (struct net_state*) st;
299
300     sta->arp = b;
301     sta->arp_connected = true;
302 }
303
304 static errval_t arp_connect(struct net_state* st)
305 {
306     errval_t err;
307     if (!st->arp_connected) {
308         iref_t iref;
309         err = nameservice_blocking_lookup("libnet_arp", &iref);
310         if (err_is_fail(err)) {
311             return err;
312         }
313
314         err = net_ARP_bind(iref, bind_cb, st, get_default_waitset(), 
315                            IDC_BIND_FLAGS_DEFAULT);
316         if (err_is_fail(err)) {
317             return err;
318         }
319     
320         while(!st->arp_connected) {
321             event_dispatch(get_default_waitset());
322         }
323     }
324     return SYS_ERR_OK;
325 }
326
327 errval_t arp_service_get_mac(uint32_t ip, uint64_t* mac)
328 {
329     errval_t err;
330
331     err = oct_init();
332     if (err_is_fail(err)) {
333         return err;
334     }
335     
336     char* record = NULL;
337     char query[256] ;
338
339     sprintf(query, "net.arp.%d {mac: _ , ip: %d }", ip, ip);
340     err = oct_get(&record, query);
341     if (err_no(err) == OCT_ERR_NO_RECORD) {
342         struct net_state *st = get_default_net_state();
343         err = arp_connect(st);
344         if (err_is_fail(err)) {
345             return err;
346         }       
347
348         err = st->arp->tx_vtbl.arp_force_lookup(st->arp, NOP_CONT, ip);
349         if (err_is_fail(err)) {
350             return err;
351         }
352
353         err = oct_wait_for(&record, query);
354         if (err_is_fail(err)) {
355             return err;
356         }
357     } else if (err_is_fail(err)) {
358         DEBUG_ERR(err, "cannot get mac address\n");
359         return err;
360     }
361
362     uint64_t ip_adr;
363     err = oct_read(record, "_" ARP_ENTRY_FIELDS, mac, &ip_adr);
364     if (err_is_fail(err)) {
365         DEBUG_ERR(err, "failed to read the entrie\n");
366     }
367
368     return SYS_ERR_OK;
369 }
370