miniflow_clone_inline(), miniflow_destroy(), miniflow_expand(),
miniflow_get(), miniflow_equal(), minimask_init(), minimask_clone(),
minimask_move(), minimask_destroy(), minimask_expand(),
minimask_expand, minimask_get(), minimask_equal(),
minimask_has_extra(), minimatch_init(), minimatch_clone(),
minimatch_move, minimatch_destroy(), minimatch_expand(),
minimatch_equal(), and minimatch_matches_flow() are inlined.  Many of
these call each other, so inlining could be beneficial.

miniflow_equal_in_minimask() is moved to lib/classifier, which is the
sole user of it.

miniflow_equal_flow_in_minimask() is moved to tests/test-classifier,
which is the only user of it.

Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com>
---
 lib/classifier-private.h |   18 ++++
 lib/flow.c               |  186 ----------------------------------------
 lib/flow.h               |  213 +++++++++++++++++++++++++++++++++++++++-------
 lib/match.c              |   76 -----------------
 lib/match.h              |   97 +++++++++++++++++++--
 tests/test-classifier.c  |   19 +++++
 6 files changed, 307 insertions(+), 302 deletions(-)

diff --git a/lib/classifier-private.h b/lib/classifier-private.h
index b498eea..abefb06 100644
--- a/lib/classifier-private.h
+++ b/lib/classifier-private.h
@@ -100,6 +100,24 @@ struct trie_node {
  * These are only used by the classifier, so place them here to allow
  * for better optimization. */
 
+/* Returns true if 'a' and 'b' are equal at the places where there are 1-bits
+ * in 'mask', false if they differ. */
+static inline bool
+miniflow_equal_in_minimask(const struct miniflow *a, const struct miniflow *b,
+                           const struct minimask *mask)
+{
+    const uint32_t *p = miniflow_get_u32_values(&mask->masks);
+    int idx;
+
+    MAP_FOR_EACH_INDEX(idx, mask->masks.map) {
+        if ((miniflow_get(a, idx) ^ miniflow_get(b, idx)) & *p++) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
 static inline uint64_t
 miniflow_get_map_in_range(const struct miniflow *miniflow,
                           uint8_t start, uint8_t end, unsigned int *offset)
diff --git a/lib/flow.c b/lib/flow.c
index 40fa867..8a98ad6 100644
--- a/lib/flow.c
+++ b/lib/flow.c
@@ -1915,18 +1915,6 @@ miniflow_clone(struct miniflow *dst, const struct 
miniflow *src)
     memcpy(values, miniflow_get_values(src), size);
 }
 
-/* Initializes 'dst' as a copy of 'src'.  The caller must have allocated
- * 'dst' to have inline space all data in 'src'. */
-void
-miniflow_clone_inline(struct miniflow *dst, const struct miniflow *src,
-                      size_t n_values)
-{
-    dst->values_inline = true;
-    dst->map = src->map;
-    memcpy(dst->inline_values, miniflow_get_values(src),
-           MINIFLOW_VALUES_SIZE(n_values));
-}
-
 /* Initializes 'dst' with the data in 'src', destroying 'src'.
  * The caller must eventually free 'dst' with miniflow_destroy().
  * 'dst' must be regularly sized miniflow, but 'src' can have
@@ -1952,122 +1940,7 @@ miniflow_move(struct miniflow *dst, struct miniflow 
*src)
         dst->offline_values = src->offline_values;
     }
 }
-
-/* Frees any memory owned by 'flow'.  Does not free the storage in which 'flow'
- * itself resides; the caller is responsible for that. */
-void
-miniflow_destroy(struct miniflow *flow)
-{
-    if (!flow->values_inline) {
-        free(flow->offline_values);
-    }
-}
-
-/* Initializes 'dst' as a copy of 'src'. */
-void
-miniflow_expand(const struct miniflow *src, struct flow *dst)
-{
-    memset(dst, 0, sizeof *dst);
-    flow_union_with_miniflow(dst, src);
-}
-
-/* Returns the uint32_t that would be at byte offset '4 * u32_ofs' if 'flow'
- * were expanded into a "struct flow". */
-static uint32_t
-miniflow_get(const struct miniflow *flow, unsigned int u32_ofs)
-{
-    return flow->map & (UINT64_C(1) << u32_ofs)
-        ? MINIFLOW_GET__(flow, u32_ofs) : 0;
-}
-
-/* Returns true if 'a' and 'b' are the equal miniflow, false otherwise. */
-bool
-miniflow_equal(const struct miniflow *a, const struct miniflow *b)
-{
-    const uint32_t *ap = miniflow_get_u32_values(a);
-    const uint32_t *bp = miniflow_get_u32_values(b);
-
-    if (OVS_LIKELY(a->map == b->map)) {
-        int count = miniflow_n_values(a);
-
-        return !memcmp(ap, bp, count * sizeof *ap);
-    } else {
-        int idx;
-
-        MAP_FOR_EACH_INDEX(idx, a->map | b->map) {
-            uint64_t bit = UINT64_C(1) << idx;
-
-            if ((a->map & bit ? *ap++ : 0) != (b->map & bit ? *bp++ : 0)) {
-                return false;
-            }
-        }
-    }
-
-    return true;
-}
-
-/* Returns false if 'a' and 'b' differ at the places where there are 1-bits
- * in 'mask', true otherwise. */
-bool
-miniflow_equal_in_minimask(const struct miniflow *a, const struct miniflow *b,
-                           const struct minimask *mask)
-{
-    const uint32_t *p = miniflow_get_u32_values(&mask->masks);
-    int idx;
-
-    MAP_FOR_EACH_INDEX(idx, mask->masks.map) {
-        if ((miniflow_get(a, idx) ^ miniflow_get(b, idx)) & *p++) {
-            return false;
-        }
-    }
-
-    return true;
-}
-
-/* Returns true if 'a' and 'b' are equal at the places where there are 1-bits
- * in 'mask', false if they differ. */
-bool
-miniflow_equal_flow_in_minimask(const struct miniflow *a, const struct flow *b,
-                                const struct minimask *mask)
-{
-    const uint32_t *b_u32 = (const uint32_t *) b;
-    const uint32_t *p = miniflow_get_u32_values(&mask->masks);
-    int idx;
-
-    MAP_FOR_EACH_INDEX(idx, mask->masks.map) {
-        if ((miniflow_get(a, idx) ^ b_u32[idx]) & *p++) {
-            return false;
-        }
-    }
-
-    return true;
-}
-
 
-/* Initializes 'dst' as a copy of 'src'.  The caller must eventually free 'dst'
- * with minimask_destroy(). */
-void
-minimask_init(struct minimask *mask, const struct flow_wildcards *wc)
-{
-    miniflow_init(&mask->masks, &wc->masks);
-}
-
-/* Initializes 'dst' as a copy of 'src'.  The caller must eventually free 'dst'
- * with minimask_destroy(). */
-void
-minimask_clone(struct minimask *dst, const struct minimask *src)
-{
-    miniflow_clone(&dst->masks, &src->masks);
-}
-
-/* Initializes 'dst' with the data in 'src', destroying 'src'.
- * The caller must eventually free 'dst' with minimask_destroy(). */
-void
-minimask_move(struct minimask *dst, struct minimask *src)
-{
-    miniflow_move(&dst->masks, &src->masks);
-}
-
 /* Initializes 'dst_' as the bit-wise "and" of 'a_' and 'b_'.
  *
  * The caller must provide room for FLOW_U32S "uint32_t"s in 'storage', for use
@@ -2097,62 +1970,3 @@ minimask_combine(struct minimask *dst_,
         }
     }
 }
-
-/* Frees any memory owned by 'mask'.  Does not free the storage in which 'mask'
- * itself resides; the caller is responsible for that. */
-void
-minimask_destroy(struct minimask *mask)
-{
-    miniflow_destroy(&mask->masks);
-}
-
-/* Initializes 'dst' as a copy of 'src'. */
-void
-minimask_expand(const struct minimask *mask, struct flow_wildcards *wc)
-{
-    miniflow_expand(&mask->masks, &wc->masks);
-}
-
-/* Returns the uint32_t that would be at byte offset '4 * u32_ofs' if 'mask'
- * were expanded into a "struct flow_wildcards". */
-uint32_t
-minimask_get(const struct minimask *mask, unsigned int u32_ofs)
-{
-    return miniflow_get(&mask->masks, u32_ofs);
-}
-
-/* Returns true if 'a' and 'b' are the same flow mask, false otherwise.
- * Minimasks may not have zero data values, so for the minimasks to be the
- * same, they need to have the same map and the same data values. */
-bool
-minimask_equal(const struct minimask *a, const struct minimask *b)
-{
-    return a->masks.map == b->masks.map &&
-        !memcmp(miniflow_get_u32_values(&a->masks),
-                miniflow_get_u32_values(&b->masks),
-                count_1bits(a->masks.map) * sizeof *a->masks.inline_values);
-}
-
-/* Returns true if at least one bit matched by 'b' is wildcarded by 'a',
- * false otherwise. */
-bool
-minimask_has_extra(const struct minimask *a, const struct minimask *b)
-{
-    const uint32_t *ap = miniflow_get_u32_values(&a->masks);
-    const uint32_t *bp = miniflow_get_u32_values(&b->masks);
-    int idx;
-
-    MAP_FOR_EACH_INDEX(idx, b->masks.map) {
-        uint32_t b_u32 = *bp++;
-
-        /* 'b_u32' is non-zero, check if the data in 'a' is either zero
-         * or misses some of the bits in 'b_u32'. */
-        if (!(a->masks.map & (UINT64_C(1) << idx))
-            || ((MINIFLOW_VALUES_GET__(ap, a->masks.map, idx) & b_u32)
-                != b_u32)) {
-            return true; /* 'a' wildcards some bits 'b' doesn't. */
-        }
-    }
-
-    return false;
-}
diff --git a/lib/flow.h b/lib/flow.h
index 2a0d390..9e2e561 100644
--- a/lib/flow.h
+++ b/lib/flow.h
@@ -465,12 +465,13 @@ void miniflow_init(struct miniflow *, const struct flow 
*);
 void miniflow_init_with_minimask(struct miniflow *, const struct flow *,
                                  const struct minimask *);
 void miniflow_clone(struct miniflow *, const struct miniflow *);
-void miniflow_clone_inline(struct miniflow *, const struct miniflow *,
-                           size_t n_values);
+static inline void miniflow_clone_inline(struct miniflow *,
+                                         const struct miniflow *,
+                                         size_t n_values);
 void miniflow_move(struct miniflow *dst, struct miniflow *);
-void miniflow_destroy(struct miniflow *);
+static inline void miniflow_destroy(struct miniflow *);
 
-void miniflow_expand(const struct miniflow *, struct flow *);
+static inline void miniflow_expand(const struct miniflow *, struct flow *);
 
 static inline uint32_t flow_u32_value(const struct flow *flow, size_t index)
 {
@@ -583,13 +584,9 @@ static inline uint16_t miniflow_get_vid(const struct 
miniflow *);
 static inline uint16_t miniflow_get_tcp_flags(const struct miniflow *);
 static inline ovs_be64 miniflow_get_metadata(const struct miniflow *);
 
-bool miniflow_equal(const struct miniflow *a, const struct miniflow *b);
-bool miniflow_equal_in_minimask(const struct miniflow *a,
-                                const struct miniflow *b,
-                                const struct minimask *);
-bool miniflow_equal_flow_in_minimask(const struct miniflow *a,
-                                     const struct flow *b,
-                                     const struct minimask *);
+static inline bool miniflow_equal(const struct miniflow *a,
+                                  const struct miniflow *b);
+
 uint32_t miniflow_hash_5tuple(const struct miniflow *flow, uint32_t basis);
 
 
@@ -605,24 +602,188 @@ struct minimask {
     struct miniflow masks;
 };
 
-void minimask_init(struct minimask *, const struct flow_wildcards *);
-void minimask_clone(struct minimask *, const struct minimask *);
-void minimask_move(struct minimask *dst, struct minimask *src);
+static inline void minimask_init(struct minimask *,
+                                 const struct flow_wildcards *);
+static inline void minimask_clone(struct minimask *, const struct minimask *);
+static inline void minimask_move(struct minimask *dst, struct minimask *src);
 void minimask_combine(struct minimask *dst,
                       const struct minimask *a, const struct minimask *b,
                       uint32_t storage[FLOW_U32S]);
-void minimask_destroy(struct minimask *);
+static inline void minimask_destroy(struct minimask *);
 
-void minimask_expand(const struct minimask *, struct flow_wildcards *);
+static inline void minimask_expand(const struct minimask *,
+                                   struct flow_wildcards *);
 
-uint32_t minimask_get(const struct minimask *, unsigned int u32_ofs);
+static inline uint32_t minimask_get(const struct minimask *,
+                                    unsigned int u32_ofs);
 static inline uint16_t minimask_get_vid_mask(const struct minimask *);
 static inline ovs_be64 minimask_get_metadata_mask(const struct minimask *);
 
-bool minimask_equal(const struct minimask *a, const struct minimask *b);
-bool minimask_has_extra(const struct minimask *, const struct minimask *);
+static inline bool minimask_equal(const struct minimask *a,
+                                  const struct minimask *b);
+static inline bool minimask_has_extra(const struct minimask *,
+                                      const struct minimask *);
 
 
+/* Perform a bitwise OR of miniflow 'src' flow data with the equivalent
+ * fields in 'dst', storing the result in 'dst'. */
+static inline void
+flow_union_with_miniflow(struct flow *dst, const struct miniflow *src)
+{
+    uint32_t *dst_u32 = (uint32_t *)dst;
+    const uint32_t *p = miniflow_get_u32_values(src);
+    int idx;
+
+    MAP_FOR_EACH_INDEX(idx, src->map) {
+        dst_u32[idx] |= *p++;
+    }
+}
+
+/* Returns the uint32_t that would be at byte offset '4 * u32_ofs' if 'flow'
+ * were expanded into a "struct flow". */
+static inline uint32_t
+miniflow_get(const struct miniflow *flow, unsigned int u32_ofs)
+{
+    return flow->map & (UINT64_C(1) << u32_ofs)
+        ? MINIFLOW_GET__(flow, u32_ofs) : 0;
+}
+
+/* Initializes 'dst' as a copy of 'src'.  The caller must have allocated
+ * 'dst' to have inline space all data in 'src'. */
+static inline void
+miniflow_clone_inline(struct miniflow *dst, const struct miniflow *src,
+                      size_t n_values)
+{
+    dst->values_inline = true;
+    dst->map = src->map;
+    memcpy(dst->inline_values, miniflow_get_values(src),
+           MINIFLOW_VALUES_SIZE(n_values));
+}
+
+/* Frees any memory owned by 'flow'.  Does not free the storage in which 'flow'
+ * itself resides; the caller is responsible for that. */
+static inline void
+miniflow_destroy(struct miniflow *flow)
+{
+    if (!flow->values_inline) {
+        free(flow->offline_values);
+    }
+}
+
+/* Initializes 'dst' as a copy of 'src'. */
+static inline void
+miniflow_expand(const struct miniflow *src, struct flow *dst)
+{
+    memset(dst, 0, sizeof *dst);
+    flow_union_with_miniflow(dst, src);
+}
+
+/* Returns true if 'a' and 'b' are the equal miniflow, false otherwise. */
+static inline bool
+miniflow_equal(const struct miniflow *a, const struct miniflow *b)
+{
+    const uint32_t *ap = miniflow_get_u32_values(a);
+    const uint32_t *bp = miniflow_get_u32_values(b);
+
+    if (OVS_LIKELY(a->map == b->map)) {
+        return !memcmp(ap, bp, count_1bits(a->map) * sizeof *ap);
+    } else {
+        int idx;
+
+        MAP_FOR_EACH_INDEX(idx, a->map | b->map) {
+            uint64_t bit = UINT64_C(1) << idx;
+
+            if ((a->map & bit ? *ap++ : 0) != (b->map & bit ? *bp++ : 0)) {
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+/* Initializes 'dst' as a copy of 'src'.  The caller must eventually free 'dst'
+ * with minimask_destroy(). */
+static inline void
+minimask_init(struct minimask *mask, const struct flow_wildcards *wc)
+{
+    miniflow_init(&mask->masks, &wc->masks);
+}
+
+/* Initializes 'dst' as a copy of 'src'.  The caller must eventually free 'dst'
+ * with minimask_destroy(). */
+static inline void
+minimask_clone(struct minimask *dst, const struct minimask *src)
+{
+    miniflow_clone(&dst->masks, &src->masks);
+}
+
+/* Initializes 'dst' with the data in 'src', destroying 'src'.
+ * The caller must eventually free 'dst' with minimask_destroy(). */
+static inline void
+minimask_move(struct minimask *dst, struct minimask *src)
+{
+    miniflow_move(&dst->masks, &src->masks);
+}
+
+/* Frees any memory owned by 'mask'.  Does not free the storage in which 'mask'
+ * itself resides; the caller is responsible for that. */
+static inline void
+minimask_destroy(struct minimask *mask)
+{
+    miniflow_destroy(&mask->masks);
+}
+
+/* Initializes 'dst' as a copy of 'src'. */
+static inline void
+minimask_expand(const struct minimask *mask, struct flow_wildcards *wc)
+{
+    miniflow_expand(&mask->masks, &wc->masks);
+}
+
+/* Returns the uint32_t that would be at byte offset '4 * u32_ofs' if 'mask'
+ * were expanded into a "struct flow_wildcards". */
+static inline uint32_t
+minimask_get(const struct minimask *mask, unsigned int u32_ofs)
+{
+    return miniflow_get(&mask->masks, u32_ofs);
+}
+
+/* Returns true if 'a' and 'b' are the same flow mask, false otherwise.
+ * Minimasks may not have zero data values, so for the minimasks to be the
+ * same, they need to have the same map and the same data values. */
+static inline bool
+minimask_equal(const struct minimask *a, const struct minimask *b)
+{
+    return a->masks.map == b->masks.map &&
+        !memcmp(miniflow_get_u32_values(&a->masks),
+                miniflow_get_u32_values(&b->masks),
+                count_1bits(a->masks.map) * sizeof *a->masks.inline_values);
+}
+
+/* Returns true if at least one bit matched by 'b' is wildcarded by 'a',
+ * false otherwise. */
+static inline bool
+minimask_has_extra(const struct minimask *a, const struct minimask *b)
+{
+    const uint32_t *ap = miniflow_get_u32_values(&a->masks);
+    const uint32_t *bp = miniflow_get_u32_values(&b->masks);
+    int idx;
+
+    MAP_FOR_EACH_INDEX(idx, b->masks.map) {
+        uint32_t b_u32 = *bp++;
+
+        /* 'b_u32' is non-zero, check if the data in 'a' is either zero
+         * or misses some of the bits in 'b_u32'. */
+        if (!(a->masks.map & (UINT64_C(1) << idx))
+            || ((MINIFLOW_VALUES_GET__(ap, a->masks.map, idx) & b_u32)
+                != b_u32)) {
+            return true; /* 'a' wildcards some bits 'b' doesn't. */
+        }
+    }
+
+    return false;
+}
+
 /* Returns true if 'mask' matches every packet, false if 'mask' fixes any bits
  * or fields. */
 static inline bool
@@ -690,20 +851,6 @@ minimask_get_metadata_mask(const struct minimask *mask)
     return miniflow_get_metadata(&mask->masks);
 }
 
-/* Perform a bitwise OR of miniflow 'src' flow data with the equivalent
- * fields in 'dst', storing the result in 'dst'. */
-static inline void
-flow_union_with_miniflow(struct flow *dst, const struct miniflow *src)
-{
-    uint32_t *dst_u32 = (uint32_t *) dst;
-    const uint32_t *p = miniflow_get_u32_values(src);
-    int idx;
-
-    MAP_FOR_EACH_INDEX(idx, src->map) {
-        dst_u32[idx] |= *p++;
-    }
-}
-
 static inline struct pkt_metadata
 pkt_metadata_from_flow(const struct flow *flow)
 {
diff --git a/lib/match.c b/lib/match.c
index 480b972..2e4d0c0 100644
--- a/lib/match.c
+++ b/lib/match.c
@@ -1138,82 +1138,6 @@ match_print(const struct match *match)
     free(s);
 }
 
-/* Initializes 'dst' as a copy of 'src'.  The caller must eventually free 'dst'
- * with minimatch_destroy(). */
-void
-minimatch_init(struct minimatch *dst, const struct match *src)
-{
-    minimask_init(&dst->mask, &src->wc);
-    miniflow_init_with_minimask(&dst->flow, &src->flow, &dst->mask);
-}
-
-/* Initializes 'dst' as a copy of 'src'.  The caller must eventually free 'dst'
- * with minimatch_destroy(). */
-void
-minimatch_clone(struct minimatch *dst, const struct minimatch *src)
-{
-    miniflow_clone(&dst->flow, &src->flow);
-    minimask_clone(&dst->mask, &src->mask);
-}
-
-/* Initializes 'dst' with the data in 'src', destroying 'src'.  The caller must
- * eventually free 'dst' with minimatch_destroy(). */
-void
-minimatch_move(struct minimatch *dst, struct minimatch *src)
-{
-    miniflow_move(&dst->flow, &src->flow);
-    minimask_move(&dst->mask, &src->mask);
-}
-
-/* Frees any memory owned by 'match'.  Does not free the storage in which
- * 'match' itself resides; the caller is responsible for that. */
-void
-minimatch_destroy(struct minimatch *match)
-{
-    miniflow_destroy(&match->flow);
-    minimask_destroy(&match->mask);
-}
-
-/* Initializes 'dst' as a copy of 'src'. */
-void
-minimatch_expand(const struct minimatch *src, struct match *dst)
-{
-    miniflow_expand(&src->flow, &dst->flow);
-    minimask_expand(&src->mask, &dst->wc);
-}
-
-/* Returns true if 'a' and 'b' match the same packets, false otherwise.  */
-bool
-minimatch_equal(const struct minimatch *a, const struct minimatch *b)
-{
-    return (miniflow_equal(&a->flow, &b->flow)
-            && minimask_equal(&a->mask, &b->mask));
-}
-
-/* Returns true if 'target' satisifies 'match', that is, if each bit for which
- * 'match' specifies a particular value has the correct value in 'target'.
- *
- * This function is equivalent to miniflow_equal_flow_in_minimask(&match->flow,
- * target, &match->mask) but it is faster because of the invariant that
- * match->flow.map and match->mask.map are the same. */
-bool
-minimatch_matches_flow(const struct minimatch *match,
-                       const struct flow *target)
-{
-    const uint32_t *target_u32 = (const uint32_t *) target;
-    const uint32_t *flowp = miniflow_get_u32_values(&match->flow);
-    const uint32_t *maskp = miniflow_get_u32_values(&match->mask.masks);
-    int idx;
-
-    MAP_FOR_EACH_INDEX(idx, match->flow.map) {
-        if ((*flowp++ ^ target_u32[idx]) & *maskp++) {
-            return false;
-        }
-    }
-
-    return true;
-}
-
 /* Appends a string representation of 'match' to 's'.  If 'priority' is
  * different from OFP_DEFAULT_PRIORITY, includes it in 's'. */
 void
diff --git a/lib/match.h b/lib/match.h
index a245bcf..a737ade 100644
--- a/lib/match.h
+++ b/lib/match.h
@@ -164,18 +164,101 @@ struct minimatch {
     struct minimask mask;
 };
 
-void minimatch_init(struct minimatch *, const struct match *);
-void minimatch_clone(struct minimatch *, const struct minimatch *);
-void minimatch_move(struct minimatch *dst, struct minimatch *src);
-void minimatch_destroy(struct minimatch *);
+static inline void minimatch_init(struct minimatch *, const struct match *);
+static inline void minimatch_clone(struct minimatch *,
+                                   const struct minimatch *);
+static inline void minimatch_move(struct minimatch *dst,
+                                  struct minimatch *src);
+static inline void minimatch_destroy(struct minimatch *);
 
-void minimatch_expand(const struct minimatch *, struct match *);
+static inline void minimatch_expand(const struct minimatch *, struct match *);
 
-bool minimatch_equal(const struct minimatch *a, const struct minimatch *b);
+static inline bool minimatch_equal(const struct minimatch *a,
+                                   const struct minimatch *b);
 
-bool minimatch_matches_flow(const struct minimatch *, const struct flow *);
+static inline bool minimatch_matches_flow(const struct minimatch *,
+                                          const struct flow *);
 
 void minimatch_format(const struct minimatch *, struct ds *, int priority);
 char *minimatch_to_string(const struct minimatch *, int priority);
 
+
+/* Inline implementations. */
+
+/* Initializes 'dst' as a copy of 'src'.  The caller must eventually free 'dst'
+ * with minimatch_destroy(). */
+static inline void
+minimatch_init(struct minimatch *dst, const struct match *src)
+{
+    minimask_init(&dst->mask, &src->wc);
+    miniflow_init_with_minimask(&dst->flow, &src->flow, &dst->mask);
+}
+
+/* Initializes 'dst' as a copy of 'src'.  The caller must eventually free 'dst'
+ * with minimatch_destroy(). */
+static inline void
+minimatch_clone(struct minimatch *dst, const struct minimatch *src)
+{
+    miniflow_clone(&dst->flow, &src->flow);
+    minimask_clone(&dst->mask, &src->mask);
+}
+
+/* Initializes 'dst' with the data in 'src', destroying 'src'.  The caller must
+ * eventually free 'dst' with minimatch_destroy(). */
+static inline void
+minimatch_move(struct minimatch *dst, struct minimatch *src)
+{
+    miniflow_move(&dst->flow, &src->flow);
+    minimask_move(&dst->mask, &src->mask);
+}
+
+/* Frees any memory owned by 'match'.  Does not free the storage in which
+ * 'match' itself resides; the caller is responsible for that. */
+static inline void
+minimatch_destroy(struct minimatch *match)
+{
+    miniflow_destroy(&match->flow);
+    minimask_destroy(&match->mask);
+}
+
+/* Initializes 'dst' as a copy of 'src'. */
+static inline void
+minimatch_expand(const struct minimatch *src, struct match *dst)
+{
+    miniflow_expand(&src->flow, &dst->flow);
+    minimask_expand(&src->mask, &dst->wc);
+}
+
+/* Returns true if 'a' and 'b' match the same packets, false otherwise.  */
+static inline bool
+minimatch_equal(const struct minimatch *a, const struct minimatch *b)
+{
+    return (miniflow_equal(&a->flow, &b->flow)
+            && minimask_equal(&a->mask, &b->mask));
+}
+
+/* Returns true if 'target' satisifies 'match', that is, if each bit for which
+ * 'match' specifies a particular value has the correct value in 'target'.
+ *
+ * This function is equivalent to miniflow_equal_flow_in_minimask(&match->flow,
+ * target, &match->mask) but it is faster because of the invariant that
+ * match->flow.map and match->mask.map are the same. */
+static inline bool
+minimatch_matches_flow(const struct minimatch *match,
+                       const struct flow *target)
+{
+    const uint32_t *target_u32 = (const uint32_t *) target;
+    const uint32_t *flowp = miniflow_get_u32_values(&match->flow);
+    const uint32_t *maskp = miniflow_get_u32_values(&match->mask.masks);
+    int idx;
+
+    MAP_FOR_EACH_INDEX(idx, match->flow.map) {
+        if ((*flowp++ ^ target_u32[idx]) & *maskp++) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
 #endif /* match.h */
diff --git a/tests/test-classifier.c b/tests/test-classifier.c
index e4eb0f4..fde050b 100644
--- a/tests/test-classifier.c
+++ b/tests/test-classifier.c
@@ -1251,6 +1251,25 @@ wildcard_extra_bits(struct flow_wildcards *mask)
     }
 }
 
+/* Returns true if 'a' and 'b' are equal at the places where there are 1-bits
+ * in 'mask', false if they differ. */
+static bool
+miniflow_equal_flow_in_minimask(const struct miniflow *a, const struct flow *b,
+                                const struct minimask *mask)
+{
+    const uint32_t *b_u32 = (const uint32_t *) b;
+    const uint32_t *p = miniflow_get_u32_values(&mask->masks);
+    int idx;
+
+    MAP_FOR_EACH_INDEX(idx, mask->masks.map) {
+        if ((miniflow_get(a, idx) ^ b_u32[idx]) & *p++) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
 static void
 test_miniflow(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
 {
-- 
1.7.10.4

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to