libnet: added functionality to request ARP lookup sent from default q
authorRoni Häcki <roni.haecki@inf.ethz.ch>
Wed, 30 Aug 2017 12:58:02 +0000 (14:58 +0200)
committerRoni Häcki <roni.haecki@inf.ethz.ch>
Wed, 30 Aug 2017 12:58:02 +0000 (14:58 +0200)
In some cases we require the need to look up a MAC address from
another core than where the default networking queue is running.
This sends a message to the network stack started by the driver
and forces an ARP lookup request and waits for its completion
using Octopus.

Signed-off-by: Roni Häcki <roni.haecki@inf.ethz.ch>

if/net_ARP.if
include/net/arp.h
lib/net/Hakefile
lib/net/arp.c
lib/net/networking_internal.h

index 5dd32a6..d231962 100644 (file)
@@ -21,5 +21,6 @@ interface net_ARP "ARP Table" {
                     in bool force,
                     out errval err,
                     out uint64 mac);
+    message arp_force_lookup(ipv4addr ip);
 };
 
index 4ec4fe2..9e6c05b 100644 (file)
@@ -21,4 +21,6 @@ errval_t arp_service_start(void);
 
 errval_t arp_service_subscribe(void);
 
+errval_t arp_service_get_mac(uint32_t ip, uint64_t* mac);
+
 #endif /* LIB_NET_INCLUDE_NETWORKING_ARP_H_ */
index 0aa276e..cc08ca1 100644 (file)
@@ -14,8 +14,8 @@
     target       = "net",
     cFiles       = [ "net.c", "netbufs.c",  "netif.c", "pbuf.c", "dhcp.c",
                      "net_filter.c", "arp.c", "net_queue.c"],
-    flounderBindings = [ "net_filter"],
-    flounderDefs = [ "net_filter", "octopus" ],
+    flounderBindings = [ "net_filter", "net_ARP"],
+    flounderDefs = [ "net_filter", "octopus", "net_ARP" ],
     flounderExtraDefs = [ ("net_filter",["rpcclient"]) ],
     addLibraries = libDeps [ "lwip2", "devif", "devif_backend_idc",
                              "devif_backend_solarflare", "devif_backend_e10k",
index 0e01eb9..38c032f 100644 (file)
 
 
 #include <barrelfish/barrelfish.h>
+#include <barrelfish/nameservice_client.h>
 
 
-#include <lwip/opt.h>
+#include <lwip/opt.h>       
 #include <lwip/netif.h>
 #include <lwip/timeouts.h>
 #include <net/netif.h>
@@ -25,6 +26,7 @@
 #include <netif/etharp.h>
 
 #include <if/octopus_defs.h>
+#include <if/net_ARP_defs.h>
 #include <octopus/octopus.h>
 #include <octopus/trigger.h>
 
 
 #define ARP_ENTRY_REGEX "r'net\\.arp\\.[0-9]+' { mac: _, ip: _}"
 
+
+// Reuse existing Flounder interface
+static void arp_force_lookup(struct net_ARP_binding *b,
+                                 uint32_t ip)
+{
+    errval_t err;
+    struct net_state *sta = (struct net_state*) b->st;
+
+    // send it multiple times 
+    // (TODO deferred event instead of sending multiple times)
+    err = etharp_request(&sta->netif, (ip4_addr_t*) &ip);
+    assert(err_is_ok(err));
+
+    err = etharp_request(&sta->netif, (ip4_addr_t*) &ip);
+    assert(err_is_ok(err));
+
+    err = etharp_request(&sta->netif, (ip4_addr_t*) &ip);
+    assert(err_is_ok(err));
+
+} // end function: ARP_resolve_request
+
+
+static struct net_ARP_rx_vtbl rx_arp_vtbl = {
+    .arp_force_lookup = arp_force_lookup,
+};
+
+/*****************************************************************
+* Dealing with new connections
+*****************************************************************/
+static errval_t connect_ARP_cb(void *st, struct net_ARP_binding *b)
+{   
+    b->st = st;
+    b->rx_vtbl = rx_arp_vtbl;
+    return SYS_ERR_OK;
+} 
+
+/*****************************************************************
+* exporting service
+*****************************************************************/
+
+static void export_ARP_cb(void *st, errval_t err, iref_t iref)
+{
+    struct net_state *sta = st;
+
+    if (err_is_fail(err)) {
+        DEBUG_ERR(err, "service export failed");
+    }
+
+    // register this iref with the name service
+    err = nameservice_register("libnet_arp", iref);
+    if (err_is_fail(err)) {
+        DEBUG_ERR(err, "nameservice_register failed for [libnet_arp]");
+        abort(); // FIXME: Do I need abort after DEBUG_ERR?
+    }
+    sta->arp_running = true;
+}
+
 struct netif *arp_filter_netif(struct pbuf *p, struct netif *netif, uint16_t type)
 {
     if (type != ETHTYPE_ARP) {
@@ -111,6 +170,12 @@ static errval_t arp_service_start_st(struct net_state *st)
         return err;
     }
 
+    err = net_ARP_export(st, export_ARP_cb, connect_ARP_cb,
+                         get_default_waitset(), IDC_EXPORT_FLAGS_DEFAULT);
+    if (err_is_fail(err)) {
+        return err;
+    }
+
     st->arp_running = true;
 
     return SYS_ERR_OK;
@@ -148,6 +213,8 @@ static  void arp_change_event(octopus_mode_t mode, const char* record, void* st)
     }
 }
 
+
+
 static errval_t arp_service_subscribe_st(struct net_state *st)
 {
     NETDEBUG("subscribing to ARP updates..\n");
@@ -169,3 +236,82 @@ errval_t arp_service_subscribe(void)
     struct net_state *st = get_default_net_state();
     return arp_service_subscribe_st(st);
 }
+
+
+
+static void bind_cb(void *st, errval_t err, struct net_ARP_binding *b)
+{
+    assert(err_is_ok(err));
+    struct net_state* sta = (struct net_state*) st;
+
+    sta->arp = b;
+    sta->arp_connected = true;
+}
+
+static errval_t arp_connect(struct net_state* st)
+{
+    errval_t err;
+    if (!st->arp_connected) {
+        iref_t iref;
+        err = nameservice_blocking_lookup("libnet_arp", &iref);
+        if (err_is_fail(err)) {
+            return err;
+        }
+
+        err = net_ARP_bind(iref, bind_cb, st, get_default_waitset(), 
+                           IDC_BIND_FLAGS_DEFAULT);
+        if (err_is_fail(err)) {
+            return err;
+        }
+    
+        while(!st->arp_connected) {
+            event_dispatch(get_default_waitset());
+        }
+    }
+    return SYS_ERR_OK;
+}
+
+errval_t arp_service_get_mac(uint32_t ip, uint64_t* mac)
+{
+    errval_t err;
+
+    err = oct_init();
+    if (err_is_fail(err)) {
+        return err;
+    }
+    
+    char* record = NULL;
+    char query[256] ;
+
+    sprintf(query, "net.arp.%d {mac: _ , ip: %d }", ip, ip);
+    err = oct_get(&record, query);
+    if (err_no(err) == OCT_ERR_NO_RECORD) {
+        struct net_state *st = get_default_net_state();
+        err = arp_connect(st);
+        if (err_is_fail(err)) {
+            return err;
+        }       
+
+        err = st->arp->tx_vtbl.arp_force_lookup(st->arp, NOP_CONT, ip);
+        if (err_is_fail(err)) {
+            return err;
+        }
+
+        err = oct_wait_for(&record, query);
+        if (err_is_fail(err)) {
+            return err;
+        }
+    } else if (err_is_fail(err)) {
+        DEBUG_ERR(err, "cannot get mac address\n");
+        return err;
+    }
+
+    uint64_t ip_adr;
+    err = oct_read(record, "_" ARP_ENTRY_FIELDS, mac, &ip_adr);
+    if (err_is_fail(err)) {
+        DEBUG_ERR(err, "failed to read the entrie\n");
+    }
+
+    return SYS_ERR_OK;
+}
+
index e874882..beaf170 100644 (file)
@@ -35,6 +35,8 @@
 #include <net/dhcp.h>
 #include <net/arp.h>
 
+#include <if/net_ARP_defs.h>
+
 #include "debug.h"
 
 // enable benchmarking
@@ -62,7 +64,9 @@ struct net_state {
     bool dhcp_running;
 
     bool arp_running;
+    bool arp_connected;
     uint64_t arp_triggerid;
+    struct net_ARP_binding* arp;
 
     struct waitset *waitset;