Skip to content

Commit

Permalink
flow.c: Improve minimask_equal() and minimask_has_extra().
Browse files Browse the repository at this point in the history
minimask_equal() and minimask_has_extra() can take benefit from the
fact that minimasks have no zero data.

Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
  • Loading branch information
Jarno Rajahalme committed Nov 26, 2014
1 parent 03690eb commit f4d335e
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 11 deletions.
27 changes: 18 additions & 9 deletions lib/flow.c
Expand Up @@ -2131,27 +2131,36 @@ 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',
* false otherwise. */
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. */
}
}

Expand Down
11 changes: 9 additions & 2 deletions lib/flow.h
Expand Up @@ -551,13 +551,20 @@ mf_get_next_in_map(struct mf_for_each_in_map_aux *aux, uint32_t *value)
mf_get_next_in_map(&aux__, &(VALUE)); \
)

/* This can be used when it is known that 'u32_idx' is set in 'map'. */
static inline uint32_t
miniflow_values_get__(const uint32_t *values, uint64_t map, int u32_idx)
{
return values[count_1bits(map & ((UINT64_C(1) << u32_idx) - 1))];
}

/* This can be used when it is known that 'u32_idx' is set in
* the map of 'mf'. */
static inline uint32_t
miniflow_get__(const struct miniflow *mf, int u32_idx)
{
return miniflow_get_u32_values(mf)
[count_1bits(mf->map & ((UINT64_C(1) << u32_idx) - 1))];
return 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
Expand Down

0 comments on commit f4d335e

Please sign in to comment.