[ovs-dev] [PATCH 03/10] flow.c: Improve minimask_equal() and minimask_has_extra().
Jarno Rajahalme
jrajahalme at nicira.com
Fri Nov 21 00:42:50 UTC 2014
minimask_equal() and minimask_has_extra() can take benefit from the
fact that minimasks have no zero data.
Signed-off-by: Jarno Rajahalme <jrajahalme at nicira.com>
---
lib/flow.c | 27 ++++++++++++++++++---------
lib/flow.h | 5 +++--
2 files changed, 21 insertions(+), 11 deletions(-)
diff --git a/lib/flow.c b/lib/flow.c
index f1bcad6..141c3d8 100644
--- a/lib/flow.c
+++ b/lib/flow.c
@@ -2131,11 +2131,16 @@ 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. */
+/* 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 miniflow_equal(&a->masks, &b->masks);
+ 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',
@@ -2143,15 +2148,19 @@ minimask_equal(const struct minimask *a, const struct minimask *b)
bool
minimask_has_extra(const struct minimask *a, const struct minimask *b)
{
- const uint32_t *p = miniflow_get_u32_values(&b->masks);
- uint64_t map;
+ const uint32_t *ap = miniflow_get_u32_values(&a->masks);
+ const uint32_t *bp = miniflow_get_u32_values(&b->masks);
+ int idx;
- for (map = b->masks.map; map; map = zero_rightmost_1bit(map)) {
- uint32_t a_u32 = minimask_get(a, raw_ctz(map));
- uint32_t b_u32 = *p++;
+ MAP_FOR_EACH_INDEX(idx, b->masks.map) {
+ uint32_t b_u32 = *bp++;
- if ((a_u32 & b_u32) != b_u32) {
- return true;
+ /* '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. */
}
}
diff --git a/lib/flow.h b/lib/flow.h
index 3e0ac28..2ef5c7b 100644
--- a/lib/flow.h
+++ b/lib/flow.h
@@ -553,9 +553,10 @@ mf_get_next_in_map(struct mf_for_each_in_map_aux *aux, uint32_t *value)
/* This macro can be used when it is known that the 'U32_IDX' is set in the
* map of 'MF'. */
+#define MINIFLOW_VALUES_GET__(VALUES, MAP, U32_IDX) \
+ ((VALUES)[count_1bits((MAP) & ((UINT64_C(1) << (U32_IDX)) - 1))])
#define MINIFLOW_GET__(MF, U32_IDX) \
- (miniflow_get_u32_values(MF) \
- [count_1bits((MF)->map & ((UINT64_C(1) << (U32_IDX)) - 1))])
+ MINIFLOW_VALUES_GET__(miniflow_get_u32_values(MF), (MF)->map, U32_IDX)
/* Get the value of 'FIELD' of an up to 4 byte wide integer type 'TYPE' of
* a miniflow. */
--
1.7.10.4
More information about the dev
mailing list