X-Git-Url: http://git.barrelfish.org/?p=barrelfish;a=blobdiff_plain;f=lib%2Fnet%2Farp.c;h=38c032fe6c4a84f5da4947f7112da5e0bc8d08cb;hp=0e01eb9dde4cc5bef56ec9fc6d55bce026b2748a;hb=ed85cbd3fa3180b6b64e6e6a27b4a73827be9bc6;hpb=209f045021ebac76cfc2fc028894fd7caccde879 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; +} +