[ovs-dev] [PATCH] Move lib/cmap.h to include/openvswitch directory.

Yi-Hung Wei yihung.wei at gmail.com
Fri Feb 17 19:21:55 UTC 2017


Fixes: 04f48a68 ("ofp-actions: Fix variable length meta-flow OXMs.")
VMWare-BZ: 1815360
Signed-off-by: Yi-Hung Wei <yihung.wei at gmail.com>
---
 include/openvswitch/automake.mk |   1 +
 include/openvswitch/cmap.h      | 279 ++++++++++++++++++++++++++++++++++++++++
 include/openvswitch/meta-flow.h |   2 +-
 lib/automake.mk                 |   1 -
 lib/classifier-private.h        |   2 +-
 lib/classifier.h                |   2 +-
 lib/cmap.c                      |   4 +-
 lib/cmap.h                      | 279 ----------------------------------------
 lib/dpif-netdev.c               |   2 +-
 lib/netdev.c                    |   2 +-
 lib/tnl-neigh-cache.c           |   2 +-
 ofproto/ofproto-dpif-rid.h      |   2 +-
 ofproto/ofproto-dpif-upcall.c   |   2 +-
 tests/test-cmap.c               |   2 +-
 14 files changed, 291 insertions(+), 291 deletions(-)
 create mode 100644 include/openvswitch/cmap.h
 delete mode 100644 lib/cmap.h

diff --git a/include/openvswitch/automake.mk b/include/openvswitch/automake.mk
index c0e276f..d9025ff 100644
--- a/include/openvswitch/automake.mk
+++ b/include/openvswitch/automake.mk
@@ -1,5 +1,6 @@
 openvswitchincludedir = $(includedir)/openvswitch
 openvswitchinclude_HEADERS = \
+	include/openvswitch/cmap.h \
 	include/openvswitch/compiler.h \
 	include/openvswitch/dynamic-string.h \
 	include/openvswitch/hmap.h \
diff --git a/include/openvswitch/cmap.h b/include/openvswitch/cmap.h
new file mode 100644
index 0000000..18105c1
--- /dev/null
+++ b/include/openvswitch/cmap.h
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2014, 2016 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 OPENVSWITCH_CMAP_H
+#define OPENVSWITCH_CMAP_H 1
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "ovs-rcu.h"
+#include "util.h"
+
+/* Concurrent hash map
+ * ===================
+ *
+ * A single-writer, multiple-reader hash table that efficiently supports
+ * duplicates.
+ *
+ *
+ * Thread-safety
+ * =============
+ *
+ * The general rules are:
+ *
+ *    - Only a single thread may safely call into cmap_insert(),
+ *      cmap_remove(), or cmap_replace() at any given time.
+ *
+ *    - Any number of threads may use functions and macros that search or
+ *      iterate through a given cmap, even in parallel with other threads
+ *      calling cmap_insert(), cmap_remove(), or cmap_replace().
+ *
+ *      There is one exception: cmap_find_protected() is only safe if no thread
+ *      is currently calling cmap_insert(), cmap_remove(), or cmap_replace().
+ *      (Use ordinary cmap_find() if that is not guaranteed.)
+ *
+ *    - See "Iteration" below for additional thread safety rules.
+ *
+ * Writers must use special care to ensure that any elements that they remove
+ * do not get freed or reused until readers have finished with them.  This
+ * includes inserting the element back into its original cmap or a different
+ * one.  One correct way to do this is to free them from an RCU callback with
+ * ovsrcu_postpone().
+ */
+
+/* A concurrent hash map node, to be embedded inside the data structure being
+ * mapped.
+ *
+ * All nodes linked together on a chain have exactly the same hash value. */
+struct cmap_node {
+    OVSRCU_TYPE(struct cmap_node *) next; /* Next node with same hash. */
+};
+
+static inline struct cmap_node *
+cmap_node_next(const struct cmap_node *node)
+{
+    return ovsrcu_get(struct cmap_node *, &node->next);
+}
+
+static inline struct cmap_node *
+cmap_node_next_protected(const struct cmap_node *node)
+{
+    return ovsrcu_get_protected(struct cmap_node *, &node->next);
+}
+
+/* Concurrent hash map. */
+struct cmap {
+    OVSRCU_TYPE(struct cmap_impl *) impl;
+};
+
+/* Initializer for an empty cmap. */
+#define CMAP_INITIALIZER {                                              \
+        .impl = OVSRCU_INITIALIZER((struct cmap_impl *) &empty_cmap)    \
+    }
+extern OVS_ALIGNED_VAR(CACHE_LINE_SIZE) const struct cmap_impl empty_cmap;
+
+/* Initialization. */
+void cmap_init(struct cmap *);
+void cmap_destroy(struct cmap *);
+
+/* Count. */
+size_t cmap_count(const struct cmap *);
+bool cmap_is_empty(const struct cmap *);
+
+/* Insertion and deletion.  Return the current count after the operation. */
+size_t cmap_insert(struct cmap *, struct cmap_node *, uint32_t hash);
+static inline size_t cmap_remove(struct cmap *, struct cmap_node *,
+                                 uint32_t hash);
+size_t cmap_replace(struct cmap *, struct cmap_node *old_node,
+                    struct cmap_node *new_node, uint32_t hash);
+
+/* Search.
+ *
+ * These macros iterate NODE over all of the nodes in CMAP that have hash value
+ * equal to HASH.  MEMBER must be the name of the 'struct cmap_node' member
+ * within NODE.
+ *
+ * CMAP and HASH are evaluated only once.  NODE is evaluated many times.
+ *
+ *
+ * Thread-safety
+ * =============
+ *
+ * CMAP_NODE_FOR_EACH will reliably visit each of the nodes starting with
+ * CMAP_NODE, even with concurrent insertions and deletions.  (Of
+ * course, if nodes are being inserted or deleted, it might or might not visit
+ * the nodes actually being inserted or deleted.)
+ *
+ * CMAP_NODE_FOR_EACH_PROTECTED may only be used if the containing CMAP is
+ * guaranteed not to change during iteration.  It may be only slightly faster.
+ *
+ * CMAP_FOR_EACH_WITH_HASH will reliably visit each of the nodes with the
+ * specified hash in CMAP, even with concurrent insertions and deletions.  (Of
+ * course, if nodes with the given HASH are being inserted or deleted, it might
+ * or might not visit the nodes actually being inserted or deleted.)
+ *
+ * CMAP_FOR_EACH_WITH_HASH_PROTECTED may only be used if CMAP is guaranteed not
+ * to change during iteration.  It may be very slightly faster.
+ */
+#define CMAP_NODE_FOR_EACH(NODE, MEMBER, CMAP_NODE)                     \
+    for (INIT_CONTAINER(NODE, CMAP_NODE, MEMBER);                       \
+         (NODE) != OBJECT_CONTAINING(NULL, NODE, MEMBER);               \
+         ASSIGN_CONTAINER(NODE, cmap_node_next(&(NODE)->MEMBER), MEMBER))
+#define CMAP_NODE_FOR_EACH_PROTECTED(NODE, MEMBER, CMAP_NODE)           \
+    for (INIT_CONTAINER(NODE, CMAP_NODE, MEMBER);                       \
+         (NODE) != OBJECT_CONTAINING(NULL, NODE, MEMBER);               \
+         ASSIGN_CONTAINER(NODE, cmap_node_next_protected(&(NODE)->MEMBER), \
+                          MEMBER))
+#define CMAP_FOR_EACH_WITH_HASH(NODE, MEMBER, HASH, CMAP)   \
+    CMAP_NODE_FOR_EACH(NODE, MEMBER, cmap_find(CMAP, HASH))
+#define CMAP_FOR_EACH_WITH_HASH_PROTECTED(NODE, MEMBER, HASH, CMAP)     \
+    CMAP_NODE_FOR_EACH_PROTECTED(NODE, MEMBER, cmap_find_locked(CMAP, HASH))
+
+const struct cmap_node *cmap_find(const struct cmap *, uint32_t hash);
+struct cmap_node *cmap_find_protected(const struct cmap *, uint32_t hash);
+
+/* Looks up multiple 'hashes', when the corresponding bit in 'map' is 1,
+ * and sets the corresponding pointer in 'nodes', if the hash value was
+ * found from the 'cmap'.  In other cases the 'nodes' values are not changed,
+ * i.e., no NULL pointers are stored there.
+ * Returns a map where a bit is set to 1 if the corresponding 'nodes' pointer
+ * was stored, 0 otherwise.
+ * Generally, the caller wants to use CMAP_NODE_FOR_EACH to verify for
+ * hash collisions. */
+unsigned long cmap_find_batch(const struct cmap *cmap, unsigned long map,
+                              uint32_t hashes[],
+                              const struct cmap_node *nodes[]);
+
+/* Iteration.
+ *
+ *
+ * Thread-safety
+ * =============
+ *
+ * Iteration is safe even in a cmap that is changing concurrently.  However:
+ *
+ *     - In the presence of concurrent calls to cmap_insert(), any given
+ *       iteration might skip some nodes and might visit some nodes more than
+ *       once.  If this is a problem, then the iterating code should lock the
+ *       data structure (a rwlock can be used to allow multiple threads to
+ *       iterate in parallel).
+ *
+ *     - Concurrent calls to cmap_remove() don't have the same problem.  (A
+ *       node being deleted may be visited once or not at all.  Other nodes
+ *       will be visited once.)
+ *
+ *     - If the cmap is changing, it is not safe to quiesce while iterating.
+ *       Even if the changes are done by the same thread that's performing the
+ *       iteration (Corollary: it is not safe to call cmap_remove() and quiesce
+ *       in the loop body).
+ *
+ *
+ * Example
+ * =======
+ *
+ *     struct my_node {
+ *         struct cmap_node cmap_node;
+ *         int extra_data;
+ *     };
+ *
+ *     struct cmap_cursor cursor;
+ *     struct my_node *iter;
+ *     struct cmap my_map;
+ *
+ *     cmap_init(&cmap);
+ *     ...add data...
+ *     CMAP_FOR_EACH (my_node, cmap_node, &cursor, &cmap) {
+ *         ...operate on my_node...
+ *     }
+ *
+ * CMAP_FOR_EACH is "safe" in the sense of HMAP_FOR_EACH_SAFE.  That is, it is
+ * safe to free the current node before going on to the next iteration.  Most
+ * of the time, though, this doesn't matter for a cmap because node
+ * deallocation has to be postponed until the next grace period.  This means
+ * that this guarantee is useful only in deallocation code already executing at
+ * postponed time, when it is known that the RCU grace period has already
+ * expired.
+ */
+
+#define CMAP_CURSOR_FOR_EACH__(NODE, CURSOR, MEMBER)    \
+    ((CURSOR)->node                                     \
+     ? (INIT_CONTAINER(NODE, (CURSOR)->node, MEMBER),   \
+        cmap_cursor_advance(CURSOR),                    \
+        true)                                           \
+     : false)
+
+#define CMAP_CURSOR_FOR_EACH(NODE, MEMBER, CURSOR, CMAP)    \
+    for (*(CURSOR) = cmap_cursor_start(CMAP);               \
+         CMAP_CURSOR_FOR_EACH__(NODE, CURSOR, MEMBER);      \
+        )
+
+#define CMAP_CURSOR_FOR_EACH_CONTINUE(NODE, MEMBER, CURSOR)   \
+    while (CMAP_CURSOR_FOR_EACH__(NODE, CURSOR, MEMBER))
+
+struct cmap_cursor {
+    const struct cmap_impl *impl;
+    uint32_t bucket_idx;
+    int entry_idx;
+    struct cmap_node *node;
+};
+
+struct cmap_cursor cmap_cursor_start(const struct cmap *);
+void cmap_cursor_advance(struct cmap_cursor *);
+
+#define CMAP_FOR_EACH(NODE, MEMBER, CMAP)                       \
+    for (struct cmap_cursor cursor__ = cmap_cursor_start(CMAP); \
+         CMAP_CURSOR_FOR_EACH__(NODE, &cursor__, MEMBER);       \
+        )
+
+static inline struct cmap_node *cmap_first(const struct cmap *);
+
+/* Another, less preferred, form of iteration, for use in situations where it
+ * is difficult to maintain a pointer to a cmap_node. */
+struct cmap_position {
+    unsigned int bucket;
+    unsigned int entry;
+    unsigned int offset;
+};
+
+struct cmap_node *cmap_next_position(const struct cmap *,
+                                     struct cmap_position *);
+
+/* Returns the first node in 'cmap', in arbitrary order, or a null pointer if
+ * 'cmap' is empty. */
+static inline struct cmap_node *
+cmap_first(const struct cmap *cmap)
+{
+    struct cmap_position pos = { 0, 0, 0 };
+
+    return cmap_next_position(cmap, &pos);
+}
+
+/* Removes 'node' from 'cmap'.  The caller must ensure that 'cmap' cannot
+ * change concurrently (from another thread).
+ *
+ * 'node' must not be destroyed or modified or inserted back into 'cmap' or
+ * into any other concurrent hash map while any other thread might be accessing
+ * it.  One correct way to do this is to free it from an RCU callback with
+ * ovsrcu_postpone().
+ *
+ * Returns the current number of nodes in the cmap after the removal. */
+static inline size_t
+cmap_remove(struct cmap *cmap, struct cmap_node *node, uint32_t hash)
+{
+    return cmap_replace(cmap, node, NULL, hash);
+}
+
+#endif /* cmap.h */
diff --git a/include/openvswitch/meta-flow.h b/include/openvswitch/meta-flow.h
index d5c0971..60585aa 100644
--- a/include/openvswitch/meta-flow.h
+++ b/include/openvswitch/meta-flow.h
@@ -23,7 +23,7 @@
 #include <sys/types.h>
 #include <netinet/in.h>
 #include <netinet/ip6.h>
-#include "cmap.h"
+#include "openvswitch/cmap.h"
 #include "openvswitch/flow.h"
 #include "openvswitch/ofp-errors.h"
 #include "openvswitch/packets.h"
diff --git a/lib/automake.mk b/lib/automake.mk
index abc9d0d..318b5de 100644
--- a/lib/automake.mk
+++ b/lib/automake.mk
@@ -41,7 +41,6 @@ lib_libopenvswitch_la_SOURCES = \
 	lib/ccmap.c \
 	lib/ccmap.h \
 	lib/cmap.c \
-	lib/cmap.h \
 	lib/colors.c \
 	lib/colors.h \
 	lib/command-line.c \
diff --git a/lib/classifier-private.h b/lib/classifier-private.h
index 1d5ee00..a15535c 100644
--- a/lib/classifier-private.h
+++ b/lib/classifier-private.h
@@ -18,9 +18,9 @@
 #define CLASSIFIER_PRIVATE_H 1
 
 #include "ccmap.h"
-#include "cmap.h"
 #include "flow.h"
 #include "hash.h"
+#include "openvswitch/cmap.h"
 #include "rculist.h"
 
 /* Classifier internal definitions, subject to change at any time. */
diff --git a/lib/classifier.h b/lib/classifier.h
index c57fa6f..3931755 100644
--- a/lib/classifier.h
+++ b/lib/classifier.h
@@ -298,7 +298,7 @@
  * still be RCU postponed, as the rule's visibility attribute may be examined
  * parallel to the rule's removal. */
 
-#include "cmap.h"
+#include "openvswitch/cmap.h"
 #include "openvswitch/match.h"
 #include "openvswitch/meta-flow.h"
 #include "pvector.h"
diff --git a/lib/cmap.c b/lib/cmap.c
index 8c7312d..a4da41e 100644
--- a/lib/cmap.c
+++ b/lib/cmap.c
@@ -15,10 +15,10 @@
  */
 
 #include <config.h>
-#include "cmap.h"
-#include "coverage.h"
 #include "bitmap.h"
+#include "coverage.h"
 #include "hash.h"
+#include "openvswitch/cmap.h"
 #include "ovs-rcu.h"
 #include "random.h"
 #include "util.h"
diff --git a/lib/cmap.h b/lib/cmap.h
deleted file mode 100644
index d390923..0000000
--- a/lib/cmap.h
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (c) 2014, 2016 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 CMAP_H
-#define CMAP_H 1
-
-#include <stdbool.h>
-#include <stdint.h>
-#include "ovs-rcu.h"
-#include "util.h"
-
-/* Concurrent hash map
- * ===================
- *
- * A single-writer, multiple-reader hash table that efficiently supports
- * duplicates.
- *
- *
- * Thread-safety
- * =============
- *
- * The general rules are:
- *
- *    - Only a single thread may safely call into cmap_insert(),
- *      cmap_remove(), or cmap_replace() at any given time.
- *
- *    - Any number of threads may use functions and macros that search or
- *      iterate through a given cmap, even in parallel with other threads
- *      calling cmap_insert(), cmap_remove(), or cmap_replace().
- *
- *      There is one exception: cmap_find_protected() is only safe if no thread
- *      is currently calling cmap_insert(), cmap_remove(), or cmap_replace().
- *      (Use ordinary cmap_find() if that is not guaranteed.)
- *
- *    - See "Iteration" below for additional thread safety rules.
- *
- * Writers must use special care to ensure that any elements that they remove
- * do not get freed or reused until readers have finished with them.  This
- * includes inserting the element back into its original cmap or a different
- * one.  One correct way to do this is to free them from an RCU callback with
- * ovsrcu_postpone().
- */
-
-/* A concurrent hash map node, to be embedded inside the data structure being
- * mapped.
- *
- * All nodes linked together on a chain have exactly the same hash value. */
-struct cmap_node {
-    OVSRCU_TYPE(struct cmap_node *) next; /* Next node with same hash. */
-};
-
-static inline struct cmap_node *
-cmap_node_next(const struct cmap_node *node)
-{
-    return ovsrcu_get(struct cmap_node *, &node->next);
-}
-
-static inline struct cmap_node *
-cmap_node_next_protected(const struct cmap_node *node)
-{
-    return ovsrcu_get_protected(struct cmap_node *, &node->next);
-}
-
-/* Concurrent hash map. */
-struct cmap {
-    OVSRCU_TYPE(struct cmap_impl *) impl;
-};
-
-/* Initializer for an empty cmap. */
-#define CMAP_INITIALIZER {                                              \
-        .impl = OVSRCU_INITIALIZER((struct cmap_impl *) &empty_cmap)    \
-    }
-extern OVS_ALIGNED_VAR(CACHE_LINE_SIZE) const struct cmap_impl empty_cmap;
-
-/* Initialization. */
-void cmap_init(struct cmap *);
-void cmap_destroy(struct cmap *);
-
-/* Count. */
-size_t cmap_count(const struct cmap *);
-bool cmap_is_empty(const struct cmap *);
-
-/* Insertion and deletion.  Return the current count after the operation. */
-size_t cmap_insert(struct cmap *, struct cmap_node *, uint32_t hash);
-static inline size_t cmap_remove(struct cmap *, struct cmap_node *,
-                                 uint32_t hash);
-size_t cmap_replace(struct cmap *, struct cmap_node *old_node,
-                    struct cmap_node *new_node, uint32_t hash);
-
-/* Search.
- *
- * These macros iterate NODE over all of the nodes in CMAP that have hash value
- * equal to HASH.  MEMBER must be the name of the 'struct cmap_node' member
- * within NODE.
- *
- * CMAP and HASH are evaluated only once.  NODE is evaluated many times.
- *
- *
- * Thread-safety
- * =============
- *
- * CMAP_NODE_FOR_EACH will reliably visit each of the nodes starting with
- * CMAP_NODE, even with concurrent insertions and deletions.  (Of
- * course, if nodes are being inserted or deleted, it might or might not visit
- * the nodes actually being inserted or deleted.)
- *
- * CMAP_NODE_FOR_EACH_PROTECTED may only be used if the containing CMAP is
- * guaranteed not to change during iteration.  It may be only slightly faster.
- *
- * CMAP_FOR_EACH_WITH_HASH will reliably visit each of the nodes with the
- * specified hash in CMAP, even with concurrent insertions and deletions.  (Of
- * course, if nodes with the given HASH are being inserted or deleted, it might
- * or might not visit the nodes actually being inserted or deleted.)
- *
- * CMAP_FOR_EACH_WITH_HASH_PROTECTED may only be used if CMAP is guaranteed not
- * to change during iteration.  It may be very slightly faster.
- */
-#define CMAP_NODE_FOR_EACH(NODE, MEMBER, CMAP_NODE)                     \
-    for (INIT_CONTAINER(NODE, CMAP_NODE, MEMBER);                       \
-         (NODE) != OBJECT_CONTAINING(NULL, NODE, MEMBER);               \
-         ASSIGN_CONTAINER(NODE, cmap_node_next(&(NODE)->MEMBER), MEMBER))
-#define CMAP_NODE_FOR_EACH_PROTECTED(NODE, MEMBER, CMAP_NODE)           \
-    for (INIT_CONTAINER(NODE, CMAP_NODE, MEMBER);                       \
-         (NODE) != OBJECT_CONTAINING(NULL, NODE, MEMBER);               \
-         ASSIGN_CONTAINER(NODE, cmap_node_next_protected(&(NODE)->MEMBER), \
-                          MEMBER))
-#define CMAP_FOR_EACH_WITH_HASH(NODE, MEMBER, HASH, CMAP)   \
-    CMAP_NODE_FOR_EACH(NODE, MEMBER, cmap_find(CMAP, HASH))
-#define CMAP_FOR_EACH_WITH_HASH_PROTECTED(NODE, MEMBER, HASH, CMAP)     \
-    CMAP_NODE_FOR_EACH_PROTECTED(NODE, MEMBER, cmap_find_locked(CMAP, HASH))
-
-const struct cmap_node *cmap_find(const struct cmap *, uint32_t hash);
-struct cmap_node *cmap_find_protected(const struct cmap *, uint32_t hash);
-
-/* Looks up multiple 'hashes', when the corresponding bit in 'map' is 1,
- * and sets the corresponding pointer in 'nodes', if the hash value was
- * found from the 'cmap'.  In other cases the 'nodes' values are not changed,
- * i.e., no NULL pointers are stored there.
- * Returns a map where a bit is set to 1 if the corresponding 'nodes' pointer
- * was stored, 0 otherwise.
- * Generally, the caller wants to use CMAP_NODE_FOR_EACH to verify for
- * hash collisions. */
-unsigned long cmap_find_batch(const struct cmap *cmap, unsigned long map,
-                              uint32_t hashes[],
-                              const struct cmap_node *nodes[]);
-
-/* Iteration.
- *
- *
- * Thread-safety
- * =============
- *
- * Iteration is safe even in a cmap that is changing concurrently.  However:
- *
- *     - In the presence of concurrent calls to cmap_insert(), any given
- *       iteration might skip some nodes and might visit some nodes more than
- *       once.  If this is a problem, then the iterating code should lock the
- *       data structure (a rwlock can be used to allow multiple threads to
- *       iterate in parallel).
- *
- *     - Concurrent calls to cmap_remove() don't have the same problem.  (A
- *       node being deleted may be visited once or not at all.  Other nodes
- *       will be visited once.)
- *
- *     - If the cmap is changing, it is not safe to quiesce while iterating.
- *       Even if the changes are done by the same thread that's performing the
- *       iteration (Corollary: it is not safe to call cmap_remove() and quiesce
- *       in the loop body).
- *
- *
- * Example
- * =======
- *
- *     struct my_node {
- *         struct cmap_node cmap_node;
- *         int extra_data;
- *     };
- *
- *     struct cmap_cursor cursor;
- *     struct my_node *iter;
- *     struct cmap my_map;
- *
- *     cmap_init(&cmap);
- *     ...add data...
- *     CMAP_FOR_EACH (my_node, cmap_node, &cursor, &cmap) {
- *         ...operate on my_node...
- *     }
- *
- * CMAP_FOR_EACH is "safe" in the sense of HMAP_FOR_EACH_SAFE.  That is, it is
- * safe to free the current node before going on to the next iteration.  Most
- * of the time, though, this doesn't matter for a cmap because node
- * deallocation has to be postponed until the next grace period.  This means
- * that this guarantee is useful only in deallocation code already executing at
- * postponed time, when it is known that the RCU grace period has already
- * expired.
- */
-
-#define CMAP_CURSOR_FOR_EACH__(NODE, CURSOR, MEMBER)    \
-    ((CURSOR)->node                                     \
-     ? (INIT_CONTAINER(NODE, (CURSOR)->node, MEMBER),   \
-        cmap_cursor_advance(CURSOR),                    \
-        true)                                           \
-     : false)
-
-#define CMAP_CURSOR_FOR_EACH(NODE, MEMBER, CURSOR, CMAP)    \
-    for (*(CURSOR) = cmap_cursor_start(CMAP);               \
-         CMAP_CURSOR_FOR_EACH__(NODE, CURSOR, MEMBER);      \
-        )
-
-#define CMAP_CURSOR_FOR_EACH_CONTINUE(NODE, MEMBER, CURSOR)   \
-    while (CMAP_CURSOR_FOR_EACH__(NODE, CURSOR, MEMBER))
-
-struct cmap_cursor {
-    const struct cmap_impl *impl;
-    uint32_t bucket_idx;
-    int entry_idx;
-    struct cmap_node *node;
-};
-
-struct cmap_cursor cmap_cursor_start(const struct cmap *);
-void cmap_cursor_advance(struct cmap_cursor *);
-
-#define CMAP_FOR_EACH(NODE, MEMBER, CMAP)                       \
-    for (struct cmap_cursor cursor__ = cmap_cursor_start(CMAP); \
-         CMAP_CURSOR_FOR_EACH__(NODE, &cursor__, MEMBER);       \
-        )
-
-static inline struct cmap_node *cmap_first(const struct cmap *);
-
-/* Another, less preferred, form of iteration, for use in situations where it
- * is difficult to maintain a pointer to a cmap_node. */
-struct cmap_position {
-    unsigned int bucket;
-    unsigned int entry;
-    unsigned int offset;
-};
-
-struct cmap_node *cmap_next_position(const struct cmap *,
-                                     struct cmap_position *);
-
-/* Returns the first node in 'cmap', in arbitrary order, or a null pointer if
- * 'cmap' is empty. */
-static inline struct cmap_node *
-cmap_first(const struct cmap *cmap)
-{
-    struct cmap_position pos = { 0, 0, 0 };
-
-    return cmap_next_position(cmap, &pos);
-}
-
-/* Removes 'node' from 'cmap'.  The caller must ensure that 'cmap' cannot
- * change concurrently (from another thread).
- *
- * 'node' must not be destroyed or modified or inserted back into 'cmap' or
- * into any other concurrent hash map while any other thread might be accessing
- * it.  One correct way to do this is to free it from an RCU callback with
- * ovsrcu_postpone().
- *
- * Returns the current number of nodes in the cmap after the removal. */
-static inline size_t
-cmap_remove(struct cmap *cmap, struct cmap_node *node, uint32_t hash)
-{
-    return cmap_replace(cmap, node, NULL, hash);
-}
-
-#endif /* cmap.h */
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 30907b7..a8b9b90 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -36,7 +36,6 @@
 #endif
 
 #include "bitmap.h"
-#include "cmap.h"
 #include "conntrack.h"
 #include "coverage.h"
 #include "ct-dpif.h"
@@ -54,6 +53,7 @@
 #include "netlink.h"
 #include "odp-execute.h"
 #include "odp-util.h"
+#include "openvswitch/cmap.h"
 #include "openvswitch/dynamic-string.h"
 #include "openvswitch/list.h"
 #include "openvswitch/match.h"
diff --git a/lib/netdev.c b/lib/netdev.c
index a8d8eda..1e6e449 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -31,7 +31,6 @@
 #include <sys/types.h>
 #endif
 
-#include "cmap.h"
 #include "coverage.h"
 #include "dpif.h"
 #include "dp-packet.h"
@@ -47,6 +46,7 @@
 #include "packets.h"
 #include "poll-loop.h"
 #include "seq.h"
+#include "openvswitch/cmap.h"
 #include "openvswitch/shash.h"
 #include "smap.h"
 #include "sset.h"
diff --git a/lib/tnl-neigh-cache.c b/lib/tnl-neigh-cache.c
index a28ce1d..b0b0649 100644
--- a/lib/tnl-neigh-cache.c
+++ b/lib/tnl-neigh-cache.c
@@ -25,9 +25,9 @@
 #include <stdlib.h>
 
 #include "bitmap.h"
-#include "cmap.h"
 #include "coverage.h"
 #include "dpif-netdev.h"
+#include "openvswitch/cmap.h"
 #include "openvswitch/dynamic-string.h"
 #include "errno.h"
 #include "flow.h"
diff --git a/ofproto/ofproto-dpif-rid.h b/ofproto/ofproto-dpif-rid.h
index c357591..63f79a4 100644
--- a/ofproto/ofproto-dpif-rid.h
+++ b/ofproto/ofproto-dpif-rid.h
@@ -20,8 +20,8 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include "cmap.h"
 #include "ofproto-dpif-mirror.h"
+#include "openvswitch/cmap.h"
 #include "openvswitch/list.h"
 #include "openvswitch/ofp-actions.h"
 #include "ovs-thread.h"
diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c
index 660383f..599c78a 100644
--- a/ofproto/ofproto-dpif-upcall.c
+++ b/ofproto/ofproto-dpif-upcall.c
@@ -21,8 +21,8 @@
 
 #include "connmgr.h"
 #include "coverage.h"
-#include "cmap.h"
 #include "dpif.h"
+#include "openvswitch/cmap.h"
 #include "openvswitch/dynamic-string.h"
 #include "fail-open.h"
 #include "guarded-list.h"
diff --git a/tests/test-cmap.c b/tests/test-cmap.c
index e159a16..0f7bc10 100644
--- a/tests/test-cmap.c
+++ b/tests/test-cmap.c
@@ -19,7 +19,6 @@
 
 #include <config.h>
 #undef NDEBUG
-#include "cmap.h"
 #include <assert.h>
 #include <getopt.h>
 #include <string.h>
@@ -27,6 +26,7 @@
 #include "command-line.h"
 #include "fat-rwlock.h"
 #include "hash.h"
+#include "openvswitch/cmap.h"
 #include "openvswitch/hmap.h"
 #include "ovstest.h"
 #include "ovs-thread.h"
-- 
2.7.4



More information about the dev mailing list