We allow zero 'values' in a miniflow for it to have the same map
as the corresponding minimask. Minimasks themselves never have
zero data values, though. Document this and optimize the code
accordingly.
v2:
- Made miniflow_get_map_in_range() to return data offset instead of
a pointer via the last parameter.
- Simplified minimatch_hash_in_range() by removing pointer arithmetic.
Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
flow_union_with_miniflow(&wc->masks, &mask->masks);
}
flow_union_with_miniflow(&wc->masks, &mask->masks);
}
miniflow_get_map_in_range(const struct miniflow *miniflow,
miniflow_get_map_in_range(const struct miniflow *miniflow,
- uint8_t start, uint8_t end, const uint32_t **data)
+ uint8_t start, uint8_t end, unsigned int *offset)
{
uint64_t map = miniflow->map;
{
uint64_t map = miniflow->map;
- uint32_t *p = miniflow->values;
if (start > 0) {
uint64_t msk = (UINT64_C(1) << start) - 1; /* 'start' LSBs set */
if (start > 0) {
uint64_t msk = (UINT64_C(1) << start) - 1; /* 'start' LSBs set */
- p += count_1bits(map & msk); /* Skip to start. */
+ *offset = count_1bits(map & msk);
map &= ~msk;
}
if (end < FLOW_U32S) {
uint64_t msk = (UINT64_C(1) << end) - 1; /* 'end' LSBs set */
map &= msk;
}
map &= ~msk;
}
if (end < FLOW_U32S) {
uint64_t msk = (UINT64_C(1) << end) - 1; /* 'end' LSBs set */
map &= msk;
}
uint8_t start, uint8_t end)
{
uint32_t *dst_u32 = (uint32_t *)&wc->masks;
uint8_t start, uint8_t end)
{
uint32_t *dst_u32 = (uint32_t *)&wc->masks;
- const uint32_t *p;
- uint64_t map = miniflow_get_map_in_range(&mask->masks, start, end, &p);
+ unsigned int offset;
+ uint64_t map = miniflow_get_map_in_range(&mask->masks, start, end,
+ &offset);
+ const uint32_t *p = mask->masks.values + offset;
for (; map; map = zero_rightmost_1bit(map)) {
dst_u32[raw_ctz(map)] |= *p++;
for (; map; map = zero_rightmost_1bit(map)) {
dst_u32[raw_ctz(map)] |= *p++;
hash = basis;
for (map = mask->masks.map; map; map = zero_rightmost_1bit(map)) {
hash = basis;
for (map = mask->masks.map; map; map = zero_rightmost_1bit(map)) {
- if (*p) {
- int ofs = raw_ctz(map);
- hash = mhash_add(hash, miniflow_get(flow, ofs) & *p);
- }
- p++;
+ hash = mhash_add(hash, miniflow_get(flow, raw_ctz(map)) & *p++);
}
return mhash_finish(hash, (p - mask->masks.values) * 4);
}
return mhash_finish(hash, (p - mask->masks.values) * 4);
hash = basis;
for (map = mask->masks.map; map; map = zero_rightmost_1bit(map)) {
hash = basis;
for (map = mask->masks.map; map; map = zero_rightmost_1bit(map)) {
- if (*p) {
- hash = mhash_add(hash, flow_u32[raw_ctz(map)] & *p);
- }
- p++;
+ hash = mhash_add(hash, flow_u32[raw_ctz(map)] & *p++);
}
return mhash_finish(hash, (p - mask->masks.values) * 4);
}
return mhash_finish(hash, (p - mask->masks.values) * 4);
uint8_t start, uint8_t end, uint32_t *basis)
{
const uint32_t *flow_u32 = (const uint32_t *)flow;
uint8_t start, uint8_t end, uint32_t *basis)
{
const uint32_t *flow_u32 = (const uint32_t *)flow;
- const uint32_t *p;
- uint64_t map = miniflow_get_map_in_range(&mask->masks, start, end, &p);
+ unsigned int offset;
+ uint64_t map = miniflow_get_map_in_range(&mask->masks, start, end,
+ &offset);
+ const uint32_t *p = mask->masks.values + offset;
uint32_t hash = *basis;
for (; map; map = zero_rightmost_1bit(map)) {
uint32_t hash = *basis;
for (; map; map = zero_rightmost_1bit(map)) {
- if (*p) {
- hash = mhash_add(hash, flow_u32[raw_ctz(map)] & *p);
- }
- p++;
+ hash = mhash_add(hash, flow_u32[raw_ctz(map)] & *p++);
}
*basis = hash; /* Allow continuation from the unfinished value. */
}
*basis = hash; /* Allow continuation from the unfinished value. */
*
* Elements in 'values' are allowed to be zero. This is useful for "struct
* minimatch", for which ensuring that the miniflow and minimask members have
*
* Elements in 'values' are allowed to be zero. This is useful for "struct
* minimatch", for which ensuring that the miniflow and minimask members have
- * same 'map' allows optimization .
+ * same 'map' allows optimization. This allowance applies only to a miniflow
+ * that is not a mask. That is, a minimask may NOT have zero elements in
+ * its 'values'.
*/
struct miniflow {
uint64_t map;
*/
struct miniflow {
uint64_t map;
uint32_t miniflow_hash(const struct miniflow *, uint32_t basis);
uint32_t miniflow_hash_in_minimask(const struct miniflow *,
const struct minimask *, uint32_t basis);
uint32_t miniflow_hash(const struct miniflow *, uint32_t basis);
uint32_t miniflow_hash_in_minimask(const struct miniflow *,
const struct minimask *, uint32_t basis);
-uint64_t miniflow_get_map_in_range(const struct miniflow *, uint8_t start,
- uint8_t end, const uint32_t **data);
+uint64_t miniflow_get_map_in_range(const struct miniflow *miniflow,
+ uint8_t start, uint8_t end,
+ unsigned int *offset);
+
\f
/* Compressed flow wildcards. */
/* A sparse representation of a "struct flow_wildcards".
*
\f
/* Compressed flow wildcards. */
/* A sparse representation of a "struct flow_wildcards".
*
- * See the large comment on struct miniflow for details. */
+ * See the large comment on struct miniflow for details.
+ *
+ * Note: While miniflow can have zero data for a 1-bit in the map,
+ * a minimask may not! We rely on this in the implementation. */
struct minimask {
struct miniflow masks;
};
struct minimask {
struct miniflow masks;
};
minimatch_hash_range(const struct minimatch *match, uint8_t start, uint8_t end,
uint32_t *basis)
{
minimatch_hash_range(const struct minimatch *match, uint8_t start, uint8_t end,
uint32_t *basis)
{
- const uint32_t *p;
- uint64_t map = miniflow_get_map_in_range(&match->mask.masks, start, end,
- &p);
- const ptrdiff_t df = match->mask.masks.values - match->flow.values;
+ unsigned int offset;
+ const uint32_t *p, *q;
- for (; map; map = zero_rightmost_1bit(map)) {
- if (*p) {
- hash = mhash_add(hash, *(p - df) & *p);
- }
- p++;
+ n = count_1bits(miniflow_get_map_in_range(&match->mask.masks, start, end,
+ &offset));
+ q = match->mask.masks.values + offset;
+ p = match->flow.values + offset;
+
+ for (i = 0; i < n; i++) {
+ hash = mhash_add(hash, p[i] & q[i]);
}
*basis = hash; /* Allow continuation from the unfinished value. */
}
*basis = hash; /* Allow continuation from the unfinished value. */
- return mhash_finish(hash, (p - match->mask.masks.values) * 4);
+ return mhash_finish(hash, (offset + n) * 4);
}
/* Appends a string representation of 'match' to 's'. If 'priority' is
}
/* Appends a string representation of 'match' to 's'. If 'priority' is