/* Stores a miniflow with inline values */
struct netdev_flow_key {
- uint32_t hash; /* hash function differs for different users. */
- uint32_t len;
+ uint32_t hash; /* Hash function differs for different users. */
+ uint32_t len; /* Length of the following miniflow (incl. map). */
struct miniflow mf;
uint32_t buf[FLOW_MAX_PACKET_U32S - MINI_N_INLINE];
};
{
int i;
+ BUILD_ASSERT(offsetof(struct miniflow, inline_values) == sizeof(uint64_t));
+
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 = 0;
+ flow_cache->entries[i].key.len
+ = offsetof(struct miniflow, inline_values);
miniflow_initialize(&flow_cache->entries[i].key.mf,
flow_cache->entries[i].key.buf);
}
== sizeof(uint64_t));
/* Given the number of bits set in the miniflow map, returns the size of the
- * netdev_flow key */
+ * 'netdev_flow_key.mf' */
static inline uint32_t
netdev_flow_key_size(uint32_t flow_u32s)
{
- return offsetof(struct netdev_flow_key, mf.inline_values) +
+ return offsetof(struct miniflow, inline_values) +
MINIFLOW_VALUES_SIZE(flow_u32s);
}
netdev_flow_key_equal(const struct netdev_flow_key *a,
const struct netdev_flow_key *b)
{
- /* 'b's size and hash may be not set yet. */
- return !memcmp(a, b, a->len);
+ /* 'b->len' may be not set yet. */
+ return a->hash == b->hash && !memcmp(&a->mf, &b->mf, a->len);
}
/* Used to compare 'netdev_flow_key' in the exact match cache to a miniflow.
netdev_flow_key_equal_mf(const struct netdev_flow_key *key,
const struct miniflow *mf)
{
- return !memcmp(&key->mf, mf,
- key->len - offsetof(struct netdev_flow_key, mf));
+ return !memcmp(&key->mf, mf, key->len);
}
static inline void
netdev_flow_key_clone(struct netdev_flow_key *dst,
const struct netdev_flow_key *src)
{
- memcpy(dst, src, src->len);
+ memcpy(dst, src,
+ offsetof(struct netdev_flow_key, mf) + src->len);
}
/* Slow. */
ovs_assert(!(mask.mf.map & (MINIFLOW_MAP(metadata) | MINIFLOW_MAP(regs))));
/* Do not allocate extra space. */
- flow = xmalloc(sizeof *flow - sizeof flow->cr.flow + mask.len);
+ flow = xmalloc(sizeof *flow - sizeof flow->cr.flow.mf + mask.len);
flow->dead = false;
*CONST_CAST(struct flow *, &flow->flow) = match->flow;
ovs_refcount_init(&flow->ref_cnt);
}
ovs_mutex_unlock(&dp->flow_mutex);
- /* EMC uses different hash. */
- keys[i].hash = dpif_packet_get_dp_hash(packets[i]);
emc_insert(flow_cache, &keys[i], netdev_flow);
}
}
flow = dp_netdev_flow_cast(rules[i]);
- keys[i].hash = dpif_packet_get_dp_hash(packet);
emc_insert(flow_cache, &keys[i], flow);
dp_netdev_queue_batches(packet, flow, &keys[i].mf, batches,
&n_batches, ARRAY_SIZE(batches));
struct dpcls_subtable *subtable;
/* Need to add one. */
- subtable = xmalloc(sizeof *subtable - sizeof subtable->mask + mask->len);
+ subtable = xmalloc(sizeof *subtable
+ - sizeof subtable->mask.mf + mask->len);
cmap_init(&subtable->rules);
netdev_flow_key_clone(&subtable->mask, mask);
cmap_insert(&cls->subtables_map, &subtable->cmap_node, mask->hash);