From ed85cbd3fa3180b6b64e6e6a27b4a73827be9bc6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Roni=20H=C3=A4cki?= Date: Wed, 30 Aug 2017 14:58:02 +0200 Subject: [PATCH] libnet: added functionality to request ARP lookup sent from default q MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 --- if/net_ARP.if | 1 + include/net/arp.h | 2 + lib/net/Hakefile | 4 +- lib/net/arp.c | 148 ++++++++++++++++++++++++++++++++++++++++- lib/net/networking_internal.h | 4 + 5 files changed, 156 insertions(+), 3 deletions(-) diff --git a/if/net_ARP.if b/if/net_ARP.if index 5dd32a6..d231962 100644 --- a/if/net_ARP.if +++ b/if/net_ARP.if @@ -21,5 +21,6 @@ interface net_ARP "ARP Table" { in bool force, out errval err, out uint64 mac); + message arp_force_lookup(ipv4addr ip); }; diff --git a/include/net/arp.h b/include/net/arp.h index 4ec4fe2..9e6c05b 100644 --- a/include/net/arp.h +++ b/include/net/arp.h @@ -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_ */ diff --git a/lib/net/Hakefile b/lib/net/Hakefile index 0aa276e..cc08ca1 100644 --- a/lib/net/Hakefile +++ b/lib/net/Hakefile @@ -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", diff --git a/lib/net/arp.c b/lib/net/arp.c index 0e01eb9..38c032f 100644 --- a/lib/net/arp.c +++ b/lib/net/arp.c @@ -15,9 +15,10 @@ #include +#include -#include +#include #include #include #include @@ -25,6 +26,7 @@ #include #include +#include #include #include @@ -40,6 +42,63 @@ #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; +} + diff --git a/lib/net/networking_internal.h b/lib/net/networking_internal.h index e874882..beaf170 100644 --- a/lib/net/networking_internal.h +++ b/lib/net/networking_internal.h @@ -35,6 +35,8 @@ #include #include +#include + #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; -- 1.7.2.5