[ovs-dev] [PATCH v3] rename tnl-arp-cache module and functions to tnl-neigh-cache

Thadeu Lima de Souza Cascardo cascardo at redhat.com
Mon Nov 30 18:24:49 UTC 2015


Since we don't distinguish between IPv4 and IPv6 lookups, consolidate ARP and ND
cache into neighbor cache. Other references to ARP related to the ARP cache but
that are not really about ARP have been renamed as well. tnl_arp_lookup is kept
for lookups using IPv4 instead of IPv4-mapped addresses, but that is going to be
removed in a later patch.

Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo at redhat.com>
---

v3: in fact, v2 for this particular patch

Rebased on top of latest changes to tnl-arp-cache.c

---
 lib/automake.mk                 |   4 +-
 lib/dpif-netdev.c               |   4 +-
 lib/dpif.c                      |   4 +-
 lib/tnl-arp-cache.c             | 318 --------------------------------------
 lib/tnl-arp-cache.h             |  45 ------
 lib/tnl-neigh-cache.c           | 333 ++++++++++++++++++++++++++++++++++++++++
 lib/tnl-neigh-cache.h           |  43 ++++++
 ofproto/ofproto-dpif-xlate.c    |  27 ++--
 ofproto/ofproto-tnl-unixctl.man |   3 +
 ofproto/tunnel.c                |   1 -
 tests/ofproto-macros.at         |   2 +-
 tests/tunnel-push-pop.at        |   2 +-
 12 files changed, 400 insertions(+), 386 deletions(-)
 delete mode 100644 lib/tnl-arp-cache.c
 delete mode 100644 lib/tnl-arp-cache.h
 create mode 100644 lib/tnl-neigh-cache.c
 create mode 100644 lib/tnl-neigh-cache.h

diff --git a/lib/automake.mk b/lib/automake.mk
index d8c00da..b27a717 100644
--- a/lib/automake.mk
+++ b/lib/automake.mk
@@ -250,8 +250,8 @@ lib_libopenvswitch_la_SOURCES = \
 	lib/timer.h \
 	lib/timeval.c \
 	lib/timeval.h \
-	lib/tnl-arp-cache.c \
-	lib/tnl-arp-cache.h \
+	lib/tnl-neigh-cache.c \
+	lib/tnl-neigh-cache.h \
 	lib/tnl-ports.c \
 	lib/tnl-ports.h \
 	lib/token-bucket.c \
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 4dcfded..a67ef05 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -64,7 +64,7 @@
 #include "shash.h"
 #include "sset.h"
 #include "timeval.h"
-#include "tnl-arp-cache.h"
+#include "tnl-neigh-cache.h"
 #include "tnl-ports.h"
 #include "unixctl.h"
 #include "util.h"
@@ -2555,7 +2555,7 @@ dpif_netdev_run(struct dpif *dpif)
     ovs_mutex_unlock(&dp->non_pmd_mutex);
     dp_netdev_pmd_unref(non_pmd);
 
-    tnl_arp_cache_run();
+    tnl_neigh_cache_run();
     tnl_port_map_run();
     new_tnl_seq = seq_read(tnl_conf_seq);
 
diff --git a/lib/dpif.c b/lib/dpif.c
index 3d6ac6e..bcc407a 100644
--- a/lib/dpif.c
+++ b/lib/dpif.c
@@ -44,7 +44,7 @@
 #include "shash.h"
 #include "sset.h"
 #include "timeval.h"
-#include "tnl-arp-cache.h"
+#include "tnl-neigh-cache.h"
 #include "tnl-ports.h"
 #include "util.h"
 #include "uuid.h"
@@ -122,7 +122,7 @@ dp_initialize(void)
         tnl_conf_seq = seq_create();
         dpctl_unixctl_register();
         tnl_port_map_init();
-        tnl_arp_cache_init();
+        tnl_neigh_cache_init();
         route_table_init();
 
         for (i = 0; i < ARRAY_SIZE(base_dpif_classes); i++) {
diff --git a/lib/tnl-arp-cache.c b/lib/tnl-arp-cache.c
deleted file mode 100644
index 75a6314..0000000
--- a/lib/tnl-arp-cache.c
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Copyright (c) 2014, 2015 Nicira, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <config.h>
-
-#include "tnl-arp-cache.h"
-
-#include <inttypes.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <netinet/icmp6.h>
-#include <stdlib.h>
-
-#include "bitmap.h"
-#include "cmap.h"
-#include "coverage.h"
-#include "dpif-netdev.h"
-#include "dynamic-string.h"
-#include "errno.h"
-#include "flow.h"
-#include "netdev.h"
-#include "ovs-thread.h"
-#include "packets.h"
-#include "poll-loop.h"
-#include "seq.h"
-#include "socket-util.h"
-#include "timeval.h"
-#include "unaligned.h"
-#include "unixctl.h"
-#include "util.h"
-#include "openvswitch/vlog.h"
-
-
-/* In seconds */
-#define ARP_ENTRY_DEFAULT_IDLE_TIME  (15 * 60)
-
-struct tnl_arp_entry {
-    struct cmap_node cmap_node;
-    struct in6_addr ip;
-    struct eth_addr mac;
-    time_t expires;             /* Expiration time. */
-    char br_name[IFNAMSIZ];
-};
-
-static struct cmap table;
-static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER;
-
-static uint32_t
-tnl_arp_hash(const struct in6_addr *ip)
-{
-    return hash_bytes(ip->s6_addr, 16, 0);
-}
-
-static struct tnl_arp_entry *
-tnl_arp_lookup__(const char br_name[IFNAMSIZ], const struct in6_addr *dst)
-{
-    struct tnl_arp_entry *arp;
-    uint32_t hash;
-
-    hash = tnl_arp_hash(dst);
-    CMAP_FOR_EACH_WITH_HASH (arp, cmap_node, hash, &table) {
-        if (ipv6_addr_equals(&arp->ip, dst) && !strcmp(arp->br_name, br_name)) {
-            arp->expires = time_now() + ARP_ENTRY_DEFAULT_IDLE_TIME;
-            return arp;
-        }
-    }
-    return NULL;
-}
-
-int
-tnl_arp_lookup(const char br_name[IFNAMSIZ], ovs_be32 dst,
-               struct eth_addr *mac)
-{
-    struct tnl_arp_entry *arp;
-    int res = ENOENT;
-    struct in6_addr dst6;
-
-    in6_addr_set_mapped_ipv4(&dst6, dst);
-
-    arp = tnl_arp_lookup__(br_name, &dst6);
-    if (arp) {
-        *mac = arp->mac;
-        res = 0;
-    }
-
-    return res;
-}
-
-int
-tnl_nd_lookup(const char br_name[IFNAMSIZ], const struct in6_addr *dst,
-              struct eth_addr *mac)
-{
-    struct tnl_arp_entry *arp;
-    int res = ENOENT;
-
-    arp = tnl_arp_lookup__(br_name, dst);
-    if (arp) {
-        *mac = arp->mac;
-        res = 0;
-    }
-    return res;
-}
-
-static void
-arp_entry_free(struct tnl_arp_entry *arp)
-{
-    free(arp);
-}
-
-static void
-tnl_arp_delete(struct tnl_arp_entry *arp)
-{
-    uint32_t hash = tnl_arp_hash(&arp->ip);
-    cmap_remove(&table, &arp->cmap_node, hash);
-    ovsrcu_postpone(arp_entry_free, arp);
-}
-
-static void
-tnl_arp_set__(const char name[IFNAMSIZ], const struct in6_addr *dst,
-              const struct eth_addr mac)
-{
-    ovs_mutex_lock(&mutex);
-    struct tnl_arp_entry *arp = tnl_arp_lookup__(name, dst);
-    if (arp) {
-        if (eth_addr_equals(arp->mac, mac)) {
-            arp->expires = time_now() + ARP_ENTRY_DEFAULT_IDLE_TIME;
-            ovs_mutex_unlock(&mutex);
-            return;
-        }
-        tnl_arp_delete(arp);
-        seq_change(tnl_conf_seq);
-    }
-
-    arp = xmalloc(sizeof *arp);
-
-    arp->ip = *dst;
-    arp->mac = mac;
-    arp->expires = time_now() + ARP_ENTRY_DEFAULT_IDLE_TIME;
-    ovs_strlcpy(arp->br_name, name, sizeof arp->br_name);
-    cmap_insert(&table, &arp->cmap_node, tnl_arp_hash(&arp->ip));
-    ovs_mutex_unlock(&mutex);
-}
-
-static void
-tnl_arp_set(const char name[IFNAMSIZ], ovs_be32 dst,
-            const struct eth_addr mac)
-{
-    struct in6_addr dst6;
-
-    in6_addr_set_mapped_ipv4(&dst6, dst);
-    tnl_arp_set__(name, &dst6, mac);
-}
-
-int
-tnl_arp_snoop(const struct flow *flow, struct flow_wildcards *wc,
-              const char name[IFNAMSIZ])
-{
-    if (flow->dl_type != htons(ETH_TYPE_ARP)) {
-        return EINVAL;
-    }
-
-    /* Exact Match on all ARP flows. */
-    memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto);
-    memset(&wc->masks.nw_src, 0xff, sizeof wc->masks.nw_src);
-    memset(&wc->masks.arp_sha, 0xff, sizeof wc->masks.arp_sha);
-
-    tnl_arp_set(name, flow->nw_src, flow->arp_sha);
-    return 0;
-}
-
-int
-tnl_nd_snoop(const struct flow *flow, struct flow_wildcards *wc,
-              const char name[IFNAMSIZ])
-{
-    if (flow->dl_type != htons(ETH_TYPE_IPV6) ||
-        flow->nw_proto != IPPROTO_ICMPV6 ||
-        flow->tp_dst != htons(0) ||
-        flow->tp_src != htons(ND_NEIGHBOR_ADVERT)) {
-        return EINVAL;
-    }
-
-    memset(&wc->masks.ipv6_src, 0xff, sizeof wc->masks.ipv6_src);
-    memset(&wc->masks.ipv6_dst, 0xff, sizeof wc->masks.ipv6_dst);
-    memset(&wc->masks.nd_target, 0xff, sizeof wc->masks.nd_target);
-    memset(&wc->masks.arp_tha, 0xff, sizeof wc->masks.arp_tha);
-
-    tnl_arp_set__(name, &flow->nd_target, flow->arp_tha);
-    return 0;
-}
-
-void
-tnl_arp_cache_run(void)
-{
-    struct tnl_arp_entry *arp;
-    bool changed = false;
-
-    ovs_mutex_lock(&mutex);
-    CMAP_FOR_EACH(arp, cmap_node, &table) {
-        if (arp->expires <= time_now()) {
-            tnl_arp_delete(arp);
-            changed = true;
-        }
-    }
-    ovs_mutex_unlock(&mutex);
-
-    if (changed) {
-        seq_change(tnl_conf_seq);
-    }
-}
-
-static void
-tnl_arp_cache_flush(struct unixctl_conn *conn, int argc OVS_UNUSED,
-                    const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
-{
-    struct tnl_arp_entry *arp;
-    bool changed = false;
-
-    ovs_mutex_lock(&mutex);
-    CMAP_FOR_EACH(arp, cmap_node, &table) {
-        tnl_arp_delete(arp);
-        changed = true;
-    }
-    ovs_mutex_unlock(&mutex);
-    if (changed) {
-        seq_change(tnl_conf_seq);
-    }
-    unixctl_command_reply(conn, "OK");
-}
-
-static int
-lookup_any(const char *host_name, struct in6_addr *address)
-{
-    if (addr_is_ipv6(host_name)) {
-        return lookup_ipv6(host_name, address);
-    } else {
-        int r;
-        struct in_addr ip;
-        r = lookup_ip(host_name, &ip);
-        if (r == 0) {
-            in6_addr_set_mapped_ipv4(address, ip.s_addr);
-        }
-        return r;
-    }
-    return ENOENT;
-}
-
-static void
-tnl_arp_cache_add(struct unixctl_conn *conn, int argc OVS_UNUSED,
-                  const char *argv[], void *aux OVS_UNUSED)
-{
-    const char *br_name = argv[1];
-    struct eth_addr mac;
-    struct in6_addr ip6;
-
-    if (lookup_any(argv[2], &ip6) != 0) {
-        unixctl_command_reply_error(conn, "bad IP address");
-        return;
-    }
-
-    if (!eth_addr_from_string(argv[3], &mac)) {
-        unixctl_command_reply_error(conn, "bad MAC address");
-        return;
-    }
-
-    tnl_arp_set__(br_name, &ip6, mac);
-    unixctl_command_reply(conn, "OK");
-}
-
-static void
-tnl_arp_cache_show(struct unixctl_conn *conn, int argc OVS_UNUSED,
-                   const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
-{
-    struct ds ds = DS_EMPTY_INITIALIZER;
-    struct tnl_arp_entry *arp;
-
-    ds_put_cstr(&ds, "IP                                            MAC                 Bridge\n");
-    ds_put_cstr(&ds, "==========================================================================\n");
-    ovs_mutex_lock(&mutex);
-    CMAP_FOR_EACH(arp, cmap_node, &table) {
-        int start_len, need_ws;
-
-        start_len = ds.length;
-        ipv6_format_mapped(&arp->ip, &ds);
-
-        need_ws = INET6_ADDRSTRLEN - (ds.length - start_len);
-        ds_put_char_multiple(&ds, ' ', need_ws);
-
-        ds_put_format(&ds, ETH_ADDR_FMT"   %s\n",
-                      ETH_ADDR_ARGS(arp->mac), arp->br_name);
-
-    }
-    ovs_mutex_unlock(&mutex);
-    unixctl_command_reply(conn, ds_cstr(&ds));
-    ds_destroy(&ds);
-}
-
-void
-tnl_arp_cache_init(void)
-{
-    cmap_init(&table);
-
-    unixctl_command_register("tnl/arp/show", "", 0, 0, tnl_arp_cache_show, NULL);
-    unixctl_command_register("tnl/arp/set", "BRIDGE IP MAC", 3, 3, tnl_arp_cache_add, NULL);
-    unixctl_command_register("tnl/arp/flush", "", 0, 0, tnl_arp_cache_flush, NULL);
-}
diff --git a/lib/tnl-arp-cache.h b/lib/tnl-arp-cache.h
deleted file mode 100644
index 7620c15..0000000
--- a/lib/tnl-arp-cache.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2014 Nicira, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef TNL_ARP_CACHE_H
-#define TNL_ARP_CACHE_H 1
-
-#include <errno.h>
-
-#include <inttypes.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <string.h>
-#include <net/if.h>
-#include <sys/socket.h>
-
-#include "flow.h"
-#include "netdev.h"
-#include "packets.h"
-#include "util.h"
-
-int tnl_arp_snoop(const struct flow *flow, struct flow_wildcards *wc,
-                  const char dev_name[]);
-int tnl_arp_lookup(const char dev_name[], ovs_be32 dst, struct eth_addr *mac);
-void tnl_arp_cache_init(void);
-void tnl_arp_cache_run(void);
-
-int tnl_nd_snoop(const struct flow *flow, struct flow_wildcards *wc,
-                 const char dev_name[]);
-int tnl_nd_lookup(const char dev_name[], const struct in6_addr *dst,
-                  struct eth_addr *mac);
-
-#endif
diff --git a/lib/tnl-neigh-cache.c b/lib/tnl-neigh-cache.c
new file mode 100644
index 0000000..cf4082c
--- /dev/null
+++ b/lib/tnl-neigh-cache.c
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 2014, 2015 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <config.h>
+
+#include "tnl-neigh-cache.h"
+
+#include <inttypes.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netinet/icmp6.h>
+#include <stdlib.h>
+
+#include "bitmap.h"
+#include "cmap.h"
+#include "coverage.h"
+#include "dpif-netdev.h"
+#include "dynamic-string.h"
+#include "errno.h"
+#include "flow.h"
+#include "netdev.h"
+#include "ovs-thread.h"
+#include "packets.h"
+#include "poll-loop.h"
+#include "seq.h"
+#include "socket-util.h"
+#include "timeval.h"
+#include "unaligned.h"
+#include "unixctl.h"
+#include "util.h"
+#include "openvswitch/vlog.h"
+
+
+/* In seconds */
+#define NEIGH_ENTRY_DEFAULT_IDLE_TIME  (15 * 60)
+
+struct tnl_neigh_entry {
+    struct cmap_node cmap_node;
+    struct in6_addr ip;
+    struct eth_addr mac;
+    time_t expires;             /* Expiration time. */
+    char br_name[IFNAMSIZ];
+};
+
+static struct cmap table;
+static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER;
+
+static uint32_t
+tnl_neigh_hash(const struct in6_addr *ip)
+{
+    return hash_bytes(ip->s6_addr, 16, 0);
+}
+
+static struct tnl_neigh_entry *
+tnl_neigh_lookup__(const char br_name[IFNAMSIZ], const struct in6_addr *dst)
+{
+    struct tnl_neigh_entry *neigh;
+    uint32_t hash;
+
+    hash = tnl_neigh_hash(dst);
+    CMAP_FOR_EACH_WITH_HASH (neigh, cmap_node, hash, &table) {
+        if (ipv6_addr_equals(&neigh->ip, dst) && !strcmp(neigh->br_name, br_name)) {
+            neigh->expires = time_now() + NEIGH_ENTRY_DEFAULT_IDLE_TIME;
+            return neigh;
+        }
+    }
+    return NULL;
+}
+
+int
+tnl_arp_lookup(const char br_name[IFNAMSIZ], ovs_be32 dst,
+               struct eth_addr *mac)
+{
+    struct tnl_neigh_entry *neigh;
+    int res = ENOENT;
+    struct in6_addr dst6;
+
+    in6_addr_set_mapped_ipv4(&dst6, dst);
+
+    neigh = tnl_neigh_lookup__(br_name, &dst6);
+    if (neigh) {
+        *mac = neigh->mac;
+        res = 0;
+    }
+
+    return res;
+}
+
+int
+tnl_neigh_lookup(const char br_name[IFNAMSIZ], const struct in6_addr *dst,
+                 struct eth_addr *mac)
+{
+    struct tnl_neigh_entry *neigh;
+    int res = ENOENT;
+
+    neigh = tnl_neigh_lookup__(br_name, dst);
+    if (neigh) {
+        *mac = neigh->mac;
+        res = 0;
+    }
+    return res;
+}
+
+static void
+neigh_entry_free(struct tnl_neigh_entry *neigh)
+{
+    free(neigh);
+}
+
+static void
+tnl_neigh_delete(struct tnl_neigh_entry *neigh)
+{
+    uint32_t hash = tnl_neigh_hash(&neigh->ip);
+    cmap_remove(&table, &neigh->cmap_node, hash);
+    ovsrcu_postpone(neigh_entry_free, neigh);
+}
+
+static void
+tnl_neigh_set__(const char name[IFNAMSIZ], const struct in6_addr *dst,
+              const struct eth_addr mac)
+{
+    ovs_mutex_lock(&mutex);
+    struct tnl_neigh_entry *neigh = tnl_neigh_lookup__(name, dst);
+    if (neigh) {
+        if (eth_addr_equals(neigh->mac, mac)) {
+            neigh->expires = time_now() + NEIGH_ENTRY_DEFAULT_IDLE_TIME;
+            ovs_mutex_unlock(&mutex);
+            return;
+        }
+        tnl_neigh_delete(neigh);
+        seq_change(tnl_conf_seq);
+    }
+
+    neigh = xmalloc(sizeof *neigh);
+
+    neigh->ip = *dst;
+    neigh->mac = mac;
+    neigh->expires = time_now() + NEIGH_ENTRY_DEFAULT_IDLE_TIME;
+    ovs_strlcpy(neigh->br_name, name, sizeof neigh->br_name);
+    cmap_insert(&table, &neigh->cmap_node, tnl_neigh_hash(&neigh->ip));
+    ovs_mutex_unlock(&mutex);
+}
+
+static void
+tnl_arp_set(const char name[IFNAMSIZ], ovs_be32 dst,
+            const struct eth_addr mac)
+{
+    struct in6_addr dst6;
+
+    in6_addr_set_mapped_ipv4(&dst6, dst);
+    tnl_neigh_set__(name, &dst6, mac);
+}
+
+static int
+tnl_arp_snoop(const struct flow *flow, struct flow_wildcards *wc,
+              const char name[IFNAMSIZ])
+{
+    if (flow->dl_type != htons(ETH_TYPE_ARP)) {
+        return EINVAL;
+    }
+
+    /* Exact Match on all ARP flows. */
+    memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto);
+    memset(&wc->masks.nw_src, 0xff, sizeof wc->masks.nw_src);
+    memset(&wc->masks.arp_sha, 0xff, sizeof wc->masks.arp_sha);
+
+    tnl_arp_set(name, flow->nw_src, flow->arp_sha);
+    return 0;
+}
+
+static int
+tnl_nd_snoop(const struct flow *flow, struct flow_wildcards *wc,
+              const char name[IFNAMSIZ])
+{
+    if (flow->dl_type != htons(ETH_TYPE_IPV6) ||
+        flow->nw_proto != IPPROTO_ICMPV6 ||
+        flow->tp_dst != htons(0) ||
+        flow->tp_src != htons(ND_NEIGHBOR_ADVERT)) {
+        return EINVAL;
+    }
+
+    memset(&wc->masks.ipv6_src, 0xff, sizeof wc->masks.ipv6_src);
+    memset(&wc->masks.ipv6_dst, 0xff, sizeof wc->masks.ipv6_dst);
+    memset(&wc->masks.nd_target, 0xff, sizeof wc->masks.nd_target);
+    memset(&wc->masks.arp_tha, 0xff, sizeof wc->masks.arp_tha);
+
+    tnl_neigh_set__(name, &flow->nd_target, flow->arp_tha);
+    return 0;
+}
+
+int
+tnl_neigh_snoop(const struct flow *flow, struct flow_wildcards *wc,
+                const char name[IFNAMSIZ])
+{
+    int res;
+    res = tnl_arp_snoop(flow, wc, name);
+    if (res != EINVAL) {
+        return res;
+    }
+    return tnl_nd_snoop(flow, wc, name);
+}
+
+void
+tnl_neigh_cache_run(void)
+{
+    struct tnl_neigh_entry *neigh;
+    bool changed = false;
+
+    ovs_mutex_lock(&mutex);
+    CMAP_FOR_EACH(neigh, cmap_node, &table) {
+        if (neigh->expires <= time_now()) {
+            tnl_neigh_delete(neigh);
+            changed = true;
+        }
+    }
+    ovs_mutex_unlock(&mutex);
+
+    if (changed) {
+        seq_change(tnl_conf_seq);
+    }
+}
+
+static void
+tnl_neigh_cache_flush(struct unixctl_conn *conn, int argc OVS_UNUSED,
+                    const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
+{
+    struct tnl_neigh_entry *neigh;
+    bool changed = false;
+
+    ovs_mutex_lock(&mutex);
+    CMAP_FOR_EACH(neigh, cmap_node, &table) {
+        tnl_neigh_delete(neigh);
+        changed = true;
+    }
+    ovs_mutex_unlock(&mutex);
+    if (changed) {
+        seq_change(tnl_conf_seq);
+    }
+    unixctl_command_reply(conn, "OK");
+}
+
+static int
+lookup_any(const char *host_name, struct in6_addr *address)
+{
+    if (addr_is_ipv6(host_name)) {
+        return lookup_ipv6(host_name, address);
+    } else {
+        int r;
+        struct in_addr ip;
+        r = lookup_ip(host_name, &ip);
+        if (r == 0) {
+            in6_addr_set_mapped_ipv4(address, ip.s_addr);
+        }
+        return r;
+    }
+    return ENOENT;
+}
+
+static void
+tnl_neigh_cache_add(struct unixctl_conn *conn, int argc OVS_UNUSED,
+                    const char *argv[], void *aux OVS_UNUSED)
+{
+    const char *br_name = argv[1];
+    struct eth_addr mac;
+    struct in6_addr ip6;
+
+    if (lookup_any(argv[2], &ip6) != 0) {
+        unixctl_command_reply_error(conn, "bad IP address");
+        return;
+    }
+
+    if (!eth_addr_from_string(argv[3], &mac)) {
+        unixctl_command_reply_error(conn, "bad MAC address");
+        return;
+    }
+
+    tnl_neigh_set__(br_name, &ip6, mac);
+    unixctl_command_reply(conn, "OK");
+}
+
+static void
+tnl_neigh_cache_show(struct unixctl_conn *conn, int argc OVS_UNUSED,
+                     const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
+{
+    struct ds ds = DS_EMPTY_INITIALIZER;
+    struct tnl_neigh_entry *neigh;
+
+    ds_put_cstr(&ds, "IP                                            MAC                 Bridge\n");
+    ds_put_cstr(&ds, "==========================================================================\n");
+    ovs_mutex_lock(&mutex);
+    CMAP_FOR_EACH(neigh, cmap_node, &table) {
+        int start_len, need_ws;
+
+        start_len = ds.length;
+        ipv6_format_mapped(&neigh->ip, &ds);
+
+        need_ws = INET6_ADDRSTRLEN - (ds.length - start_len);
+        ds_put_char_multiple(&ds, ' ', need_ws);
+
+        ds_put_format(&ds, ETH_ADDR_FMT"   %s\n",
+                      ETH_ADDR_ARGS(neigh->mac), neigh->br_name);
+
+    }
+    ovs_mutex_unlock(&mutex);
+    unixctl_command_reply(conn, ds_cstr(&ds));
+    ds_destroy(&ds);
+}
+
+void
+tnl_neigh_cache_init(void)
+{
+    cmap_init(&table);
+
+    unixctl_command_register("tnl/arp/show", "", 0, 0, tnl_neigh_cache_show, NULL);
+    unixctl_command_register("tnl/arp/set", "BRIDGE IP MAC", 3, 3, tnl_neigh_cache_add, NULL);
+    unixctl_command_register("tnl/arp/flush", "", 0, 0, tnl_neigh_cache_flush, NULL);
+    unixctl_command_register("tnl/neigh/show", "", 0, 0, tnl_neigh_cache_show, NULL);
+    unixctl_command_register("tnl/neigh/set", "BRIDGE IP MAC", 3, 3, tnl_neigh_cache_add, NULL);
+    unixctl_command_register("tnl/neigh/flush", "", 0, 0, tnl_neigh_cache_flush, NULL);
+}
diff --git a/lib/tnl-neigh-cache.h b/lib/tnl-neigh-cache.h
new file mode 100644
index 0000000..a9acd9e
--- /dev/null
+++ b/lib/tnl-neigh-cache.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TNL_NEIGH_CACHE_H
+#define TNL_NEIGH_CACHE_H 1
+
+#include <errno.h>
+
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <net/if.h>
+#include <sys/socket.h>
+
+#include "flow.h"
+#include "netdev.h"
+#include "packets.h"
+#include "util.h"
+
+int tnl_neigh_snoop(const struct flow *flow, struct flow_wildcards *wc,
+                    const char dev_name[]);
+int tnl_neigh_lookup(const char dev_name[], const struct in6_addr *dst,
+                     struct eth_addr *mac);
+void tnl_neigh_cache_init(void);
+void tnl_neigh_cache_run(void);
+
+int tnl_arp_lookup(const char dev_name[], ovs_be32 dst, struct eth_addr *mac);
+
+#endif
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index 74ad26c..dd98d6e 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -22,7 +22,7 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 
-#include "tnl-arp-cache.h"
+#include "tnl-neigh-cache.h"
 #include "bfd.h"
 #include "bitmap.h"
 #include "bond.h"
@@ -399,7 +399,7 @@ enum xc_type {
     XC_NORMAL,
     XC_FIN_TIMEOUT,
     XC_GROUP,
-    XC_TNL_ARP,
+    XC_TNL_NEIGH,
 };
 
 /* xlate_cache entries hold enough information to perform the side effects of
@@ -452,7 +452,7 @@ struct xc_entry {
         struct {
             char br_name[IFNAMSIZ];
             ovs_be32 d_ip;
-        } tnl_arp_cache;
+        } tnl_neigh_cache;
     } u;
 };
 
@@ -2810,10 +2810,10 @@ build_tunnel_send(struct xlate_ctx *ctx, const struct xport *xport,
     if (ctx->xin->xcache) {
         struct xc_entry *entry;
 
-        entry = xlate_cache_add_entry(ctx->xin->xcache, XC_TNL_ARP);
-        ovs_strlcpy(entry->u.tnl_arp_cache.br_name, out_dev->xbridge->name,
-                    sizeof entry->u.tnl_arp_cache.br_name);
-        entry->u.tnl_arp_cache.d_ip = d_ip;
+        entry = xlate_cache_add_entry(ctx->xin->xcache, XC_TNL_NEIGH);
+        ovs_strlcpy(entry->u.tnl_neigh_cache.br_name, out_dev->xbridge->name,
+                    sizeof entry->u.tnl_neigh_cache.br_name);
+        entry->u.tnl_neigh_cache.d_ip = d_ip;
     }
 
     xlate_report(ctx, "tunneling from "ETH_ADDR_FMT" "IP_FMT
@@ -4356,8 +4356,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
     const struct ofpact *a;
 
     if (ovs_native_tunneling_is_on(ctx->xbridge->ofproto)) {
-        tnl_arp_snoop(flow, wc, ctx->xbridge->name);
-        tnl_nd_snoop(flow, wc, ctx->xbridge->name);
+        tnl_neigh_snoop(flow, wc, ctx->xbridge->name);
     }
     /* dl_type already in the mask, not set below. */
 
@@ -5485,10 +5484,10 @@ xlate_push_stats(struct xlate_cache *xcache,
             group_dpif_credit_stats(entry->u.group.group, entry->u.group.bucket,
                                     stats);
             break;
-        case XC_TNL_ARP:
-            /* Lookup arp to avoid arp timeout. */
-            tnl_arp_lookup(entry->u.tnl_arp_cache.br_name,
-                           entry->u.tnl_arp_cache.d_ip, &dmac);
+        case XC_TNL_NEIGH:
+            /* Lookup neighbor to avoid timeout. */
+            tnl_arp_lookup(entry->u.tnl_neigh_cache.br_name,
+                           entry->u.tnl_neigh_cache.d_ip, &dmac);
             break;
         default:
             OVS_NOT_REACHED();
@@ -5560,7 +5559,7 @@ xlate_cache_clear(struct xlate_cache *xcache)
         case XC_GROUP:
             group_dpif_unref(entry->u.group.group);
             break;
-        case XC_TNL_ARP:
+        case XC_TNL_NEIGH:
             break;
         default:
             OVS_NOT_REACHED();
diff --git a/ofproto/ofproto-tnl-unixctl.man b/ofproto/ofproto-tnl-unixctl.man
index f9eb354..fa14b87 100644
--- a/ofproto/ofproto-tnl-unixctl.man
+++ b/ofproto/ofproto-tnl-unixctl.man
@@ -14,14 +14,17 @@ from system routing table and user configured routes.
 .IP "\fBovs/route/del ipv4_address/plen\fR"
 Delete ipv4_address/plen route from OVS routing table.
 .
+.IP "\fBtnl/neigh/show\fR"
 .IP "\fBtnl/arp/show\fR"
 OVS builds ARP cache by snooping are messages. This command shows
 ARP cache table.
 .
+.IP "\fBtnl/neigh/set \fIbridge ip mac\fR"
 .IP "\fBtnl/arp/set \fIbridge ip mac\fR"
 Adds or modifies an ARP cache entry in \fIbridge\fR, mapping \fIip\fR
 to \fImac\fR.
 .
+.IP "\fBtnl/neigh/flush\fR"
 .IP "\fBtnl/arp/flush\fR"
 Flush ARP table.
 .
diff --git a/ofproto/tunnel.c b/ofproto/tunnel.c
index bd4e1dc..d1cf4bd 100644
--- a/ofproto/tunnel.c
+++ b/ofproto/tunnel.c
@@ -33,7 +33,6 @@
 #include "seq.h"
 #include "smap.h"
 #include "socket-util.h"
-#include "tnl-arp-cache.h"
 #include "tnl-ports.h"
 #include "tunnel.h"
 #include "openvswitch/vlog.h"
diff --git a/tests/ofproto-macros.at b/tests/ofproto-macros.at
index 9b52cae..bace0f5 100644
--- a/tests/ofproto-macros.at
+++ b/tests/ofproto-macros.at
@@ -225,7 +225,7 @@ ovn_populate_arp() {
         for e2 in $arp_table; do
             set `echo $e2 | sed 's/,/ /g'`; sb2=$1 br2=$2
             if test $sb1,$br1 != $sb2,$br2; then
-                as $sb2 ovs-appctl tnl/arp/set $br2 $ip $mac
+                as $sb2 ovs-appctl tnl/neigh/set $br2 $ip $mac
             fi
         done
     done
diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at
index 507d4df..618950f 100644
--- a/tests/tunnel-push-pop.at
+++ b/tests/tunnel-push-pop.at
@@ -40,7 +40,7 @@ dnl Check ARP Snoop
 AT_CHECK([ovs-appctl netdev-dummy/receive br0 'recirc_id(0),in_port(100),eth(src=f8:bc:12:44:34:b6,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=1.1.2.92,tip=1.1.2.88,op=1,sha=f8:bc:12:44:34:b6,tha=00:00:00:00:00:00)'])
 AT_CHECK([ovs-appctl netdev-dummy/receive br0 'recirc_id(0),in_port(100),eth(src=f8:bc:12:44:34:b7,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=1.1.2.93,tip=1.1.2.88,op=1,sha=f8:bc:12:44:34:b7,tha=00:00:00:00:00:00)'])
 
-AT_CHECK([ovs-appctl tnl/arp/show], [0], [dnl
+AT_CHECK([ovs-appctl tnl/neigh/show], [0], [dnl
 IP                                            MAC                 Bridge
 ==========================================================================
 1.1.2.92                                      f8:bc:12:44:34:b6   br0
-- 
2.5.0




More information about the dev mailing list