flow_hash_in_minimask(const struct flow *flow, const struct minimask *mask,
uint32_t basis)
{
- const uint64_t *mask_values = mask->masks.values;
+ const uint64_t *mask_values = miniflow_get_values(&mask->masks);
const uint64_t *flow_u64 = (const uint64_t *)flow;
const uint64_t *p = mask_values;
uint32_t hash;
miniflow_hash_in_minimask(const struct miniflow *flow,
const struct minimask *mask, uint32_t basis)
{
- const uint64_t *mask_values = mask->masks.values;
+ const uint64_t *mask_values = miniflow_get_values(&mask->masks);
const uint64_t *p = mask_values;
uint32_t hash = basis;
uint64_t flow_u64;
const struct minimask *mask,
uint8_t start, uint8_t end, uint32_t *basis)
{
- const uint64_t *mask_values = mask->masks.values;
+ const uint64_t *mask_values = miniflow_get_values(&mask->masks);
const uint64_t *flow_u64 = (const uint64_t *)flow;
unsigned int offset;
uint64_t map;
const struct minimask *mask,
uint8_t start, uint8_t end)
{
+ const uint64_t *p = miniflow_get_values(&mask->masks);
uint64_t *dst_u64 = (uint64_t *)&wc->masks;
unsigned int offset;
uint64_t map;
- const uint64_t *p;
int idx;
map = miniflow_get_map_in_range(&mask->masks, start, end, &offset);
- p = mask->masks.values + offset;
+ p += offset;
MAP_FOR_EACH_INDEX(idx, map) {
dst_u64[idx] |= *p++;
}
static inline uint32_t
miniflow_hash(const struct miniflow *flow, uint32_t basis)
{
- const uint64_t *values = flow->values;
+ const uint64_t *values = miniflow_get_values(flow);
const uint64_t *p = values;
uint32_t hash = basis;
uint64_t hash_map = 0;
minimatch_hash_range(const struct minimatch *match, uint8_t start, uint8_t end,
uint32_t *basis)
{
+ const uint64_t *p = miniflow_get_values(match->flow);
+ const uint64_t *q = miniflow_get_values(&match->mask->masks);
unsigned int offset;
- const uint64_t *p, *q;
uint32_t hash = *basis;
int n, i;
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;
+ q += offset;
+ p += offset;
for (i = 0; i < n; i++) {
hash = hash_add64(hash, p[i] & q[i]);
const struct minimask *mask,
const struct flow *target)
{
- const uint64_t *flowp = flow->values;
- const uint64_t *maskp = mask->masks.values;
+ const uint64_t *flowp = miniflow_get_values(flow);
+ const uint64_t *maskp = miniflow_get_values(&mask->masks);
int idx;
MAP_FOR_EACH_INDEX(idx, mask->masks.map) {
const struct flow *target,
struct flow_wildcards *wc)
{
- const uint64_t *flowp = flow->values;
- const uint64_t *maskp = mask->masks.values;
+ const uint64_t *flowp = miniflow_get_values(flow);
+ const uint64_t *maskp = miniflow_get_values(&mask->masks);
int idx;
MAP_FOR_EACH_INDEX(idx, mask->masks.map) {
minimatch_get_prefix(const struct minimatch *match, const struct mf_field *mf)
{
return (OVS_FORCE const ovs_be32 *)
- (match->flow->values
+ (miniflow_get_values(match->flow)
+ count_1bits(match->flow->map &
((UINT64_C(1) << mf->flow_be32ofs / 2) - 1)))
+ (mf->flow_be32ofs & 1);
{
int i;
- BUILD_ASSERT(offsetof(struct miniflow, values) == sizeof(uint64_t));
+ BUILD_ASSERT(sizeof(struct miniflow) == sizeof(uint64_t));
flow_cache->sweep_idx = 0;
for (i = 0; i < ARRAY_SIZE(flow_cache->entries); i++) {
flow_cache->entries[i].flow = NULL;
flow_cache->entries[i].key.hash = 0;
- flow_cache->entries[i].key.len
- = offsetof(struct miniflow, values);
+ flow_cache->entries[i].key.len = sizeof(struct miniflow);
flow_cache->entries[i].key.mf.map = 0;
}
}
* The following assertions make sure that what we're doing with miniflow is
* safe
*/
-BUILD_ASSERT_DECL(offsetof(struct miniflow, values) == sizeof(uint64_t));
+BUILD_ASSERT_DECL(sizeof(struct miniflow) == sizeof(uint64_t));
/* Given the number of bits set in the miniflow map, returns the size of the
* 'netdev_flow_key.mf' */
static inline uint32_t
netdev_flow_key_size(uint32_t flow_u32s)
{
- return offsetof(struct miniflow, values) + MINIFLOW_VALUES_SIZE(flow_u32s);
+ return sizeof(struct miniflow) + MINIFLOW_VALUES_SIZE(flow_u32s);
}
static inline bool
const struct match *match)
{
const uint64_t *mask_u64 = (const uint64_t *) &match->wc.masks;
- uint64_t *dst = mask->mf.values;
+ uint64_t *dst = miniflow_values(&mask->mf);
uint64_t map, mask_map = 0;
uint32_t hash = 0;
int n;
hash = hash_add64(hash, mask_map);
- n = dst - mask->mf.values;
+ n = dst - miniflow_get_values(&mask->mf);
mask->hash = hash_finish(hash, n * 8);
mask->len = netdev_flow_key_size(n);
const struct flow *flow,
const struct netdev_flow_key *mask)
{
- uint64_t *dst_u64 = dst->mf.values;
- const uint64_t *mask_u64 = mask->mf.values;
+ uint64_t *dst_u64 = miniflow_values(&dst->mf);
+ const uint64_t *mask_u64 = miniflow_get_values(&mask->mf);
uint32_t hash = 0;
uint64_t value;
*dst_u64 = value & *mask_u64++;
hash = hash_add64(hash, *dst_u64++);
}
- dst->hash = hash_finish(hash, (dst_u64 - dst->mf.values) * 8);
+ dst->hash = hash_finish(hash,
+ (dst_u64 - miniflow_get_values(&dst->mf)) * 8);
}
/* Iterate through all netdev_flow_key u64 values specified by 'MAP' */
-#define NETDEV_FLOW_KEY_FOR_EACH_IN_MAP(VALUE, KEY, MAP) \
- for (struct mf_for_each_in_map_aux aux__ \
- = { (KEY)->mf.values, (KEY)->mf.map, MAP }; \
- mf_get_next_in_map(&aux__, &(VALUE)); \
+#define NETDEV_FLOW_KEY_FOR_EACH_IN_MAP(VALUE, KEY, MAP) \
+ for (struct mf_for_each_in_map_aux aux__ \
+ = { miniflow_get_values(&(KEY)->mf), (KEY)->mf.map, MAP }; \
+ mf_get_next_in_map(&aux__, &(VALUE)); \
)
/* Returns a hash value for the bits of 'key' where there are 1-bits in
netdev_flow_key_hash_in_mask(const struct netdev_flow_key *key,
const struct netdev_flow_key *mask)
{
- const uint64_t *p = mask->mf.values;
+ const uint64_t *p = miniflow_get_values(&mask->mf);
uint32_t hash = 0;
uint64_t key_u64;
hash = hash_add64(hash, key_u64 & *p++);
}
- return hash_finish(hash, (p - mask->mf.values) * 8);
+ return hash_finish(hash, (p - miniflow_get_values(&mask->mf)) * 8);
}
static inline bool
dpcls_rule_matches_key(const struct dpcls_rule *rule,
const struct netdev_flow_key *target)
{
- const uint64_t *keyp = rule->flow.mf.values;
- const uint64_t *maskp = rule->mask->mf.values;
+ const uint64_t *keyp = miniflow_get_values(&rule->flow.mf);
+ const uint64_t *maskp = miniflow_get_values(&rule->mask->mf);
uint64_t target_u64;
NETDEV_FLOW_KEY_FOR_EACH_IN_MAP(target_u64, target, rule->flow.mf.map) {
const struct pkt_metadata *md = &packet->md;
const void *data = dp_packet_data(packet);
size_t size = dp_packet_size(packet);
- uint64_t *values = dst->values;
+ uint64_t *values = miniflow_values(dst);
struct mf_ctx mf = { 0, values, values + FLOW_U64S };
const char *l2;
ovs_be16 dl_type;
miniflow_init(struct miniflow *dst, const struct flow *src)
{
const uint64_t *src_u64 = (const uint64_t *) src;
- uint64_t *dst_u64 = dst->values;
+ uint64_t *dst_u64 = miniflow_values(dst);
int idx;
MAP_FOR_EACH_INDEX(idx, dst->map) {
size_t n_values)
{
dst->map = src->map;
- memcpy(dst->values, src->values, MINIFLOW_VALUES_SIZE(n_values));
+ memcpy(miniflow_values(dst), miniflow_get_values(src),
+ MINIFLOW_VALUES_SIZE(n_values));
}
/* Initializes 'dst' as a copy of 'src'. */
bool
miniflow_equal(const struct miniflow *a, const struct miniflow *b)
{
- const uint64_t *ap = a->values;
- const uint64_t *bp = b->values;
+ const uint64_t *ap = miniflow_get_values(a);
+ const uint64_t *bp = miniflow_get_values(b);
if (OVS_LIKELY(a->map == b->map)) {
int count = miniflow_n_values(a);
miniflow_equal_in_minimask(const struct miniflow *a, const struct miniflow *b,
const struct minimask *mask)
{
- const uint64_t *p = mask->masks.values;
+ const uint64_t *p = miniflow_get_values(&mask->masks);
int idx;
MAP_FOR_EACH_INDEX(idx, mask->masks.map) {
const struct minimask *mask)
{
const uint64_t *b_u64 = (const uint64_t *) b;
- const uint64_t *p = mask->masks.values;
+ const uint64_t *p = miniflow_get_values(&mask->masks);
int idx;
MAP_FOR_EACH_INDEX(idx, mask->masks.map) {
minimask_equal(const struct minimask *a, const struct minimask *b)
{
return a->masks.map == b->masks.map &&
- !memcmp(a->masks.values, b->masks.values,
- count_1bits(a->masks.map) * sizeof *a->masks.values);
+ !memcmp(miniflow_get_values(&a->masks), miniflow_get_values(&b->masks),
+ MINIFLOW_VALUES_SIZE(count_1bits(a->masks.map)));
}
/* Returns true if at least one bit matched by 'b' is wildcarded by 'a',
bool
minimask_has_extra(const struct minimask *a, const struct minimask *b)
{
- const uint64_t *ap = a->masks.values;
- const uint64_t *bp = b->masks.values;
+ const uint64_t *ap = miniflow_get_values(&a->masks);
+ const uint64_t *bp = miniflow_get_values(&b->masks);
int idx;
MAP_FOR_EACH_INDEX(idx, b->masks.map) {
* 0-bit indicates that the corresponding uint64_t is zero, each 1-bit that it
* *may* be nonzero (see below how this applies to minimasks).
*
+ * The values indicated by 'map' always follow the 'map' in memory. The user
+ * of the miniflow is responsible for always having enough storage after 'map'
+ * corresponding to the number of 1-bits in 'map'.
+
* Elements in values array 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. This allowance applies only to a miniflow
- * that is not a mask. That is, a minimask may NOT have zero elements in
- * its 'values'.
+ * that is not a mask. That is, a minimask may NOT have zero elements in its
+ * 'values'.
*
* A miniflow is always dynamically allocated so that the 'values' array has as
* many elements as there are 1-bits in 'map'. */
struct miniflow {
uint64_t map;
- uint64_t values[0];
+ /* uint64_t values[]; Storage follows 'map' in memory. */
};
BUILD_ASSERT_DECL(sizeof(struct miniflow) == sizeof(uint64_t));
#define MINIFLOW_VALUES_SIZE(COUNT) ((COUNT) * sizeof(uint64_t))
+static inline uint64_t *miniflow_values(struct miniflow *mf)
+{
+ return (uint64_t *)(mf + 1);
+}
+
+static inline const uint64_t *miniflow_get_values(const struct miniflow *mf)
+{
+ return (const uint64_t *)(mf + 1);
+}
+
struct pkt_metadata;
/* The 'dst' must follow with buffer space for FLOW_U64S 64-bit units.
/* Iterate through all miniflow u64 values specified by 'MAP'. */
#define MINIFLOW_FOR_EACH_IN_MAP(VALUE, FLOW, MAP) \
for (struct mf_for_each_in_map_aux aux__ \
- = { (FLOW)->values, (FLOW)->map, MAP }; \
+ = { miniflow_get_values(FLOW), (FLOW)->map, MAP }; \
mf_get_next_in_map(&aux__, &(VALUE)); \
)
static inline uint64_t
miniflow_get__(const struct miniflow *mf, int u64_idx)
{
- return miniflow_values_get__(mf->values, mf->map, u64_idx);
+ return miniflow_values_get__(miniflow_get_values(mf), mf->map, u64_idx);
}
/* Get the value of 'FIELD' of an up to 8 byte wide integer type 'TYPE' of
#define MINIFLOW_GET_TYPE(MF, TYPE, OFS) \
(((MF)->map & (UINT64_C(1) << (OFS) / sizeof(uint64_t))) \
? ((OVS_FORCE const TYPE *) \
- ((MF)->values \
+ (miniflow_get_values(MF) \
+ count_1bits((MF)->map & \
((UINT64_C(1) << (OFS) / sizeof(uint64_t)) - 1)))) \
[(OFS) % sizeof(uint64_t) / sizeof(TYPE)] \
flow_union_with_miniflow(struct flow *dst, const struct miniflow *src)
{
uint64_t *dst_u64 = (uint64_t *) dst;
- const uint64_t *p = src->values;
+ const uint64_t *p = miniflow_get_values(src);
int idx;
MAP_FOR_EACH_INDEX(idx, src->map) {
/* Allocate two consecutive miniflows. */
size_t data_size = miniflow_alloc(dst->flows, 2, &src->mask->masks);
- memcpy(dst->flow->values, src->flow->values, data_size);
- memcpy(dst->mask->masks.values, src->mask->masks.values, data_size);
+ memcpy(miniflow_values(dst->flow),
+ miniflow_get_values(src->flow), data_size);
+ memcpy(miniflow_values(&dst->mask->masks),
+ miniflow_get_values(&src->mask->masks), data_size);
}
/* Initializes 'dst' with the data in 'src', destroying 'src'. The caller must
const struct flow *target)
{
const uint64_t *target_u64 = (const uint64_t *) target;
- const uint64_t *flowp = match->flow->values;
- const uint64_t *maskp = match->mask->masks.values;
+ const uint64_t *flowp = miniflow_get_values(match->flow);
+ const uint64_t *maskp = miniflow_get_values(&match->mask->masks);
int idx;
MAP_FOR_EACH_INDEX(idx, match->flow->map) {