libnet: integrating arp service to library and adding test domains
authorReto Achermann <reto.achermann@inf.ethz.ch>
Tue, 11 Apr 2017 18:51:16 +0000 (20:51 +0200)
committerReto Achermann <reto.achermann@inf.ethz.ch>
Tue, 11 Apr 2017 18:51:16 +0000 (20:51 +0200)
Signed-off-by: Reto Achermann <reto.achermann@inf.ethz.ch>

lib/net/Hakefile
lib/net/arp.c
lib/net/include/net/arp.h [new file with mode: 0644]
lib/net/net.c
lib/net/networking_internal.h
lib/net/test/arp.c [new file with mode: 0644]
lib/net/test/dhcp.c [new file with mode: 0644]

index bd0e192..8eb30a3 100644 (file)
@@ -13,7 +13,7 @@
 [ build library { 
     target       = "net",
     cFiles       = [ "net.c", "netbufs.c",  "netif.c", "pbuf.c", "dhcp.c",
-                     "net_filter.c" ],
+                     "net_filter.c", "arp.c" ],
     addIncludes  = [ "include", "/lib/lwip-2.0.2/src/include/" ],
     flounderBindings = [ "net_filter"],
     flounderExtraBindings = [ ("net_filter", ["rpcclient"])],
     cFiles       = [ "test/udp_ping.c" ],
     addIncludes  = [ "include", "/lib/lwip-2.0.2/src/include/" ],
     addLibraries = libDeps [ "net" ]
+  },
+  build application {
+    target       = "net_dhcp",
+    cFiles       = [ "test/dhcp.c" ],
+    addIncludes  = [ "include", "/lib/lwip-2.0.2/src/include/" ],
+    addLibraries = libDeps [ "net" ]
+  },
+    build application {
+    target       = "net_arp",
+    cFiles       = [ "test/arp.c" ],
+    addIncludes  = [ "include", "/lib/lwip-2.0.2/src/include/" ],
+    addLibraries = libDeps [ "net" ]
   }  
 ]
index 9610c2d..01f931b 100644 (file)
  * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
  */
 
-#define LWIP_ARP_FILTER_NETIF_FN(p, netif, type) arp_filter_netif(p, netif, type)
 
-#if LWIP_ARP_FILTER_NETIF
-  netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, lwip_htons(type));
-#endif /* LWIP_ARP_FILTER_NETIF*/
+#include <barrelfish/barrelfish.h>
 
-#if 0
-  err_t etharp_add_static_entry(const ip4_addr_t *ipaddr, struct eth_addr *ethaddr);
-  err_t etharp_remove_static_entry(const ip4_addr_t *ipaddr);
-#endif
 
-#define ARP_ENTRY "net.arp.%d {mac: %d}"
+#include <lwip/opt.h>
+#include <lwip/netif.h>
+#include <lwip/timeouts.h>
+#include "include/net/netif.h"
 
-#define ARP_ENTRY_REGEX "r'net\\.arp\\.[0-9]+' { mac: _ }"
+#include <netif/etharp.h>
+
+#include <octopus/octopus.h>
+
+
+#include "networking_internal.h"
+
+///< the debug subsystem
+#define NETDEBUG_SUBSYSTEM "arpd"
+
+
+#define ARP_ENTRY_FIELDS "{mac: %d, ip: %d}"
+#define ARP_ENTRY "net.arp.%d {mac: %lu, ip: %d}"
+
+#define ARP_ENTRY_REGEX "r'net\\.arp\\.[0-9]+' { mac: _, ip: _}"
 
 struct netif *arp_filter_netif(struct pbuf *p, struct netif *netif, uint16_t type)
 {
-    debug_printf("arp_filter_netif");
-
     if (type != ETHTYPE_ARP) {
         return netif;
     }
 
+    struct net_state *st = netif->state;
+
+    if (!st->arp_running) {
+        return netif;
+    }
+
+    if (p->len < SIZEOF_ETH_HDR || pbuf_header(p, (s16_t)-SIZEOF_ETH_HDR)) {
+        NETDEBUG("wrong packet size received\n");
+        return netif;
+    }
+
     struct etharp_hdr *hdr = (struct etharp_hdr *)p->payload;
 
+    pbuf_header(p, (s16_t)SIZEOF_ETH_HDR);
+
     /* RFC 826 "Packet Reception": */
     if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) ||
         (hdr->hwlen != ETH_HWADDR_LEN) ||
@@ -49,43 +70,95 @@ struct netif *arp_filter_netif(struct pbuf *p, struct netif *netif, uint16_t typ
       return netif;
     }
 
+    ip_addr_t ip;
+    IPADDR2_COPY(&ip, &hdr->sipaddr);
+
+    uint64_t hwaddr = 0;
+    if (etharp_find_addr(netif, &ip, (struct eth_addr **)&hwaddr,
+                         (const ip4_addr_t **)&hwaddr) != -1) {
+        return netif;
+    }
 
     /*
      * If already exists, return
      */
 
-    uint64_t hwaddr = 0;
-    SMEMCPY(&hwaddr, hdr->shwaddr, sizeof(hdr->shwaddr));
-    oct_publish(ARP_ENTRY, hdr->sipaddr, hdr->shwaddr);
+    hwaddr = 0;
+    SMEMCPY(&hwaddr, hdr->shwaddr.addr, sizeof(hdr->shwaddr));
 
-    etharp_add_static_entry(hdr->sipaddr, hdr->shwaddr);
+    NETDEBUG("set " ARP_ENTRY "\n", ip.addr, hwaddr, ip.addr);
+
+    oct_set(ARP_ENTRY, ip.addr, hwaddr, ip.addr);
+
+    etharp_add_static_entry(&ip, &hdr->shwaddr);
 
     return netif;
 }
 
-static  void handle_arp_entry(octopus_mode_t mode, const char* record, void* state)
+static errval_t arp_service_start_st(struct net_state *st)
 {
+    errval_t err;
+
+    err = oct_init();
+    if (err_is_fail(err)) {
+        return err;
+    }
+
+    st->arp_running = true;
 
-    uint64_t ip,hwaddr;
-    oct_read(record, ARP_ENTRY, &ip, &hwaddr);
+    return SYS_ERR_OK;
+}
+
+errval_t arp_service_start(void)
+{
+    return arp_service_start_st(get_default_net_state());
+}
+
+static  void arp_change_event(octopus_mode_t mode, const char* record, void* st)
+{
+    errval_t err;
+
+    uint64_t ip, hwaddr;
+    err = oct_read(record, "_" ARP_ENTRY_FIELDS, &hwaddr, &ip);
+    if (err_is_fail(err)) {
+        DEBUG_ERR(err, "failed to read the entrie\n");
+    }
 
     ip_addr_t ipaddr;
     ipaddr.addr = (uint32_t)ip;
 
     if (mode & OCT_ON_SET) {
 
+        NETDEBUG("adding ARP entries: ip=%u, mac=%lx\n", ipaddr.addr, hwaddr);
+
         struct eth_addr mac;
         SMEMCPY(mac.addr, &hwaddr, sizeof(mac));
 
         etharp_add_static_entry(&ipaddr, &mac);
     } else if (mode & OCT_ON_DEL) {
+        NETDEBUG("deleting ARP entries: ip=%u, mac=%lx\n", ipaddr.addr, hwaddr);
         etharp_remove_static_entry(&ipaddr);
     }
 }
 
-errval_t arp_filter_subscribe(void)
+static errval_t arp_service_subscribe_st(struct net_state *st)
+{
+    NETDEBUG("subscribing to ARP updates..\n");
+
+    errval_t err;
+    err = oct_init();
+    if (err_is_fail(err)) {
+        return err;
+    }
+
+    st->arp_running = false;
+
+    return oct_trigger_existing_and_watch(ARP_ENTRY_REGEX, arp_change_event,
+                                             st, &st->arp_triggerid);
+}
+
+errval_t arp_service_subscribe(void)
 {
     struct net_state *st = get_default_net_state();
-    subscription_t sub;
-    return  oct_subscribe(handle_arp_entry, st, &sub, ARP_ENTRY_REGEX);
+    return arp_service_subscribe_st(st);
 }
diff --git a/lib/net/include/net/arp.h b/lib/net/include/net/arp.h
new file mode 100644 (file)
index 0000000..4ec4fe2
--- /dev/null
@@ -0,0 +1,24 @@
+/**
+ * @brief 
+ *  net.h
+ */
+
+/*
+ * Copyright (c) 2017, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+
+#ifndef LIB_NET_INCLUDE_NETWORKING_ARP_H_
+#define LIB_NET_INCLUDE_NETWORKING_ARP_H_
+
+
+errval_t arp_service_start(void);
+
+errval_t arp_service_subscribe(void);
+
+#endif /* LIB_NET_INCLUDE_NETWORKING_ARP_H_ */
index 6f14cbd..272ea48 100644 (file)
@@ -181,6 +181,7 @@ errval_t networking_get_mac(struct devq *q, uint8_t *hwaddr, uint8_t hwaddrlen)
 
 static errval_t networking_poll_st(struct net_state *st)
 {
+    event_dispatch_non_block(get_default_waitset());
     if (st->flags & NET_FLAGS_POLLING) {
         return net_if_poll(&st->netif);
     } else {
@@ -276,12 +277,22 @@ static errval_t networking_init_with_queue_st(struct net_state *st,struct devq *
         if (err_is_fail(err)) {
             DEBUG_ERR(err, "failed to start DHCP.\n");
         }
+
+        err = arp_service_start();
+        if (err_is_fail(err)) {
+            DEBUG_ERR(err,  "failed to start the ARP service\n");
+        }
     } else {
         /* get IP from dhcpd */
         err = dhcpd_query(flags);
         if (err_is_fail(err)) {
             DEBUG_ERR(err, "failed to start DHCP.\n");
         }
+
+        err = arp_service_subscribe();
+        if (err_is_fail(err)) {
+            DEBUG_ERR(err, "failed to subscribte the ARP service\n");
+        }
     }
 
     NETDEBUG("initialization complete.\n");
index 33dbdf2..877ccaa 100644 (file)
@@ -30,6 +30,7 @@
 #include <net/netbufs.h>
 #include <net/netif.h>
 #include <net/dhcp.h>
+#include <net/arp.h>
 
 #include "debug.h"
 
@@ -58,6 +59,9 @@ struct net_state {
     bool dhcp_done;
     bool dhcp_running;
 
+    bool arp_running;
+    uint64_t arp_triggerid;
+
     struct waitset *waitset;
 
     struct devq *queue;
diff --git a/lib/net/test/arp.c b/lib/net/test/arp.c
new file mode 100644 (file)
index 0000000..55dfc4f
--- /dev/null
@@ -0,0 +1,128 @@
+/**
+ * \file ping.c
+ * \brief 
+ */
+
+
+/*
+ * Copyright (c) 2017 ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+
+#include <barrelfish/barrelfish.h>
+#include <barrelfish/deferred.h>
+
+#include <lwip/ip.h>
+#include <lwip/udp.h>
+#include <lwip/pbuf.h>
+
+#include <lwip/mem.h>
+#include <lwip/raw.h>
+#include <lwip/icmp.h>
+#include <lwip/netif.h>
+#include <lwip/sys.h>
+#include <lwip/timeouts.h>
+#include <lwip/ip_addr.h>
+#include <lwip/prot/ip4.h>
+
+#include <net/net.h>
+#include <net/arp.h>
+
+#include <octopus/octopus.h>
+#include <octopus/getset.h>
+
+ip_addr_t ip;
+ip_addr_t nm;
+ip_addr_t gw;
+
+uint8_t counter = 0;
+
+static int client_main(int argc, char *argv[])
+{
+    errval_t err;
+
+    debug_printf("ARP client main.\n");
+
+    err = arp_service_subscribe();
+    assert(err_is_ok(err));
+
+    while(1) {
+        event_dispatch(get_default_waitset());
+    }
+}
+
+#define ARP_ENTRY "net.arp.%d {mac: %lu, ip: %d}"
+
+static void timer_callback(void *data)
+{
+    errval_t err;
+
+    if (++counter == 0) {
+        ++counter;
+    }
+
+    IP_ADDR4(&ip, 192,168,1,counter);
+
+
+
+    debug_printf("ARP server timer. set ip to %s\n", ip4addr_ntoa(&ip));
+
+    uint64_t mac = 0xaabbccddeeffUL;
+
+    debug_printf("oct_set net.arp.%d {mac: %lu (%lx)}\n", ip.addr, mac,mac);
+
+    err = oct_set(ARP_ENTRY, ip.addr, mac, ip.addr);
+    if (err_is_fail(err)) {
+        DEBUG_ERR(err, "failed to set the DHCP record\n");
+    }
+}
+
+static int server_main(int argc, char *argv[])
+{
+    errval_t err;
+
+    debug_printf("ARP server main.\n");
+
+    IP_ADDR4(&ip, 192,168,1,0);
+    IP_ADDR4(&nm, 255,255,255,0);
+    IP_ADDR4(&gw, 192,168,1,0);
+
+    struct periodic_event ptimer;
+
+    /* DHCP fine timer */
+    err = periodic_event_create(&ptimer, get_default_waitset(), (5000 * 1000),
+                                MKCLOSURE(timer_callback, NULL));
+    assert(err_is_ok(err));
+
+    while(1) {
+        event_dispatch(get_default_waitset());
+    }
+}
+
+int main(int argc, char *argv[])
+{
+    debug_printf("ARP started.\n");
+
+    oct_init();
+
+    /* parse ip */
+
+    if (argc == 2) {
+        if (strncmp("server", argv[1], strlen("server")) == 0) {
+            return server_main(argc, argv);
+        } else if (strncmp("client", argv[1], strlen("client")) == 0) {
+            return client_main(argc, argv);
+        } else {
+            USER_PANIC("invalid argument supplied: %s\n", argv[1])
+        }
+    }
+
+    return client_main(argc, argv);
+}
+
+
diff --git a/lib/net/test/dhcp.c b/lib/net/test/dhcp.c
new file mode 100644 (file)
index 0000000..c8c1001
--- /dev/null
@@ -0,0 +1,124 @@
+/**
+ * \file ping.c
+ * \brief 
+ */
+
+
+/*
+ * Copyright (c) 2017 ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+
+#include <barrelfish/barrelfish.h>
+#include <barrelfish/deferred.h>
+
+#include <lwip/ip.h>
+#include <lwip/udp.h>
+#include <lwip/pbuf.h>
+
+#include <lwip/mem.h>
+#include <lwip/raw.h>
+#include <lwip/icmp.h>
+#include <lwip/netif.h>
+#include <lwip/sys.h>
+#include <lwip/timeouts.h>
+#include <lwip/ip_addr.h>
+#include <lwip/prot/ip4.h>
+
+#include <net/net.h>
+#include <net/dhcp.h>
+
+#include <octopus/octopus.h>
+#include <octopus/getset.h>
+
+ip_addr_t ip;
+ip_addr_t nm;
+ip_addr_t gw;
+
+uint8_t counter = 0;
+
+static int client_main(int argc, char *argv[])
+{
+    errval_t err;
+
+    debug_printf("DHCP client main.\n");
+
+    err = dhcpd_query(0);
+    assert(err_is_ok(err));
+
+    debug_printf("DHCP client query init\n");
+
+    while(1) {
+        event_dispatch(get_default_waitset());
+    }
+}
+
+#define DHCP_RECORD_FIELDS "{ ip: %d, gw: %d, netmask: %d }"
+#define DHCP_RECORD_FORMAT "net.ipconfig " DHCP_RECORD_FIELDS
+
+static void timer_callback(void *data)
+{
+    errval_t err;
+
+    if (++counter == 0) {
+        ++counter;
+    }
+    IP_ADDR4(&ip, 192,168,1,counter);
+
+    debug_printf("DHCP server timer. set ip to %s\n", ip4addr_ntoa(&ip));
+
+    err = oct_set(DHCP_RECORD_FORMAT,ip.addr, gw.addr, nm.addr);
+    if (err_is_fail(err)) {
+        DEBUG_ERR(err, "failed to set the DHCP record\n");
+    }
+}
+
+static int server_main(int argc, char *argv[])
+{
+    errval_t err;
+
+    debug_printf("DHCP server main.\n");
+
+    IP_ADDR4(&ip, 192,168,1,0);
+    IP_ADDR4(&nm, 255,255,255,0);
+    IP_ADDR4(&gw, 192,168,1,0);
+
+    struct periodic_event ptimer;
+
+    /* DHCP fine timer */
+    err = periodic_event_create(&ptimer, get_default_waitset(), (5000 * 1000),
+                                MKCLOSURE(timer_callback, NULL));
+    assert(err_is_ok(err));
+
+    while(1) {
+        event_dispatch(get_default_waitset());
+    }
+}
+
+int main(int argc, char *argv[])
+{
+    debug_printf("DHCP started.\n");
+
+    oct_init();
+
+    /* parse ip */
+
+    if (argc == 2) {
+        if (strncmp("server", argv[1], strlen("server")) == 0) {
+            return server_main(argc, argv);
+        } else if (strncmp("client", argv[1], strlen("client")) == 0) {
+            return client_main(argc, argv);
+        } else {
+            USER_PANIC("invalid argument supplied: %s\n", argv[1])
+        }
+    }
+
+    return client_main(argc, argv);
+}
+
+