This reduces the need to keep counting the bits in the map.
Signed-off-by: Jarno Rajahalme <[email protected]>
---
lib/classifier.c | 11 ++++-------
lib/dpif-netdev.c | 11 +++--------
lib/flow.c | 36 ++++++++++++++++++------------------
lib/flow.h | 29 +++++++++++++++++++++--------
4 files changed, 46 insertions(+), 41 deletions(-)
diff --git a/lib/classifier.c b/lib/classifier.c
index ae03251..84381ed 100644
--- a/lib/classifier.c
+++ b/lib/classifier.c
@@ -99,14 +99,12 @@ struct cls_match {
static struct cls_match *
cls_match_alloc(struct cls_rule *rule)
{
- int count = count_1bits(rule->match.flow.map);
-
struct cls_match *cls_match
= xmalloc(sizeof *cls_match - sizeof cls_match->flow.inline_values
- + MINIFLOW_VALUES_SIZE(count));
+ + MINIFLOW_VALUES_SIZE(rule->match.flow.count));
cls_match->cls_rule = rule;
- miniflow_clone_inline(&cls_match->flow, &rule->match.flow, count);
+ miniflow_clone_inline(&cls_match->flow, &rule->match.flow);
cls_match->priority = rule->priority;
rule->cls_match = cls_match;
@@ -1326,12 +1324,11 @@ insert_subtable(struct classifier *cls, const struct
minimask *mask)
int i, index = 0;
struct flow_wildcards old, new;
uint8_t prev;
- int count = count_1bits(mask->masks.map);
subtable = xzalloc(sizeof *subtable - sizeof mask->masks.inline_values
- + MINIFLOW_VALUES_SIZE(count));
+ + MINIFLOW_VALUES_SIZE(mask->masks.count));
cmap_init(&subtable->rules);
- miniflow_clone_inline(&subtable->mask.masks, &mask->masks, count);
+ miniflow_clone_inline(&subtable->mask.masks, &mask->masks);
/* Init indices for segmented lookup, if any. */
flow_wildcards_init_catchall(&new);
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 072ed5d..26ed052 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -90,15 +90,10 @@ static struct vlog_rate_limit upcall_rl =
VLOG_RATE_LIMIT_INIT(600, 600);
/* Stores a miniflow */
/* There are fields in the flow structure that we never use. Therefore we can
- * save a few words of memory */
-#define NETDEV_KEY_BUF_SIZE_U32 (FLOW_U32S \
- - MINI_N_INLINE \
- - FLOW_U32_SIZE(regs) \
- - FLOW_U32_SIZE(metadata) \
- )
+ * save a few words of memory. */
struct netdev_flow_key {
struct miniflow flow;
- uint32_t buf[NETDEV_KEY_BUF_SIZE_U32];
+ uint32_t buf[FLOW_MAX_PACKET_U32S - MINI_N_INLINE];
};
/* Exact match cache for frequently used flows
@@ -1163,7 +1158,7 @@ emc_change_entry(struct emc_entry *ce, struct
dp_netdev_flow *flow,
}
}
if (mf) {
- miniflow_clone_inline(&ce->mf.flow, mf, count_1bits(mf->map));
+ miniflow_clone_inline(&ce->mf.flow, mf);
ce->hash = hash;
}
}
diff --git a/lib/flow.c b/lib/flow.c
index b9f1820..79dd832 100644
--- a/lib/flow.c
+++ b/lib/flow.c
@@ -635,6 +635,7 @@ miniflow_extract(struct ofpbuf *packet, const struct
pkt_metadata *md,
miniflow_push_uint32_check(mf, dp_hash, md->dp_hash);
}
out:
+ dst->count = mf.data - values;
dst->map = mf.map;
}
@@ -1602,16 +1603,10 @@ flow_compose(struct ofpbuf *b, const struct flow *flow)
/* Compressed flow. */
-static int
-miniflow_n_values(const struct miniflow *flow)
-{
- return count_1bits(flow->map);
-}
-
static uint32_t *
-miniflow_alloc_values(struct miniflow *flow, int n)
+miniflow_alloc_values(struct miniflow *flow)
{
- int size = MINIFLOW_VALUES_SIZE(n);
+ int size = MINIFLOW_VALUES_SIZE(flow->count);
if (size <= sizeof flow->inline_values) {
flow->values_inline = true;
@@ -1637,10 +1632,10 @@ miniflow_alloc_values(struct miniflow *flow, int n)
* malloc() otherwise) and copies the uint32_t elements of 'src' indicated by
* 'dst->map' into it. */
static void
-miniflow_init__(struct miniflow *dst, const struct flow *src, int n)
+miniflow_init__(struct miniflow *dst, const struct flow *src)
{
const uint32_t *src_u32 = (const uint32_t *) src;
- uint32_t *dst_u32 = miniflow_alloc_values(dst, n);
+ uint32_t *dst_u32 = miniflow_alloc_values(dst);
uint64_t map;
for (map = dst->map; map; map = zero_rightmost_1bit(map)) {
@@ -1669,7 +1664,8 @@ miniflow_init(struct miniflow *dst, const struct flow
*src)
}
}
- miniflow_init__(dst, src, n);
+ dst->count = n;
+ miniflow_init__(dst, src);
}
/* Initializes 'dst' as a copy of 'src', using 'mask->map' as 'dst''s map. The
@@ -1678,8 +1674,9 @@ void
miniflow_init_with_minimask(struct miniflow *dst, const struct flow *src,
const struct minimask *mask)
{
+ dst->count = mask->masks.count;
dst->map = mask->masks.map;
- miniflow_init__(dst, src, miniflow_n_values(dst));
+ miniflow_init__(dst, src);
}
/* Initializes 'dst' as a copy of 'src'. The caller must eventually free 'dst'
@@ -1687,9 +1684,10 @@ miniflow_init_with_minimask(struct miniflow *dst, const
struct flow *src,
void
miniflow_clone(struct miniflow *dst, const struct miniflow *src)
{
- int size = MINIFLOW_VALUES_SIZE(miniflow_n_values(src));
+ int size = MINIFLOW_VALUES_SIZE(src->count);
uint32_t *values;
+ dst->count = src->count;
dst->map = src->map;
if (size <= sizeof dst->inline_values) {
dst->values_inline = true;
@@ -1706,13 +1704,13 @@ miniflow_clone(struct miniflow *dst, const struct
miniflow *src)
/* Initializes 'dst' as a copy of 'src'. The caller must have allocated
* 'dst' to have inline space all data in 'src'. */
void
-miniflow_clone_inline(struct miniflow *dst, const struct miniflow *src,
- size_t n_values)
+miniflow_clone_inline(struct miniflow *dst, const struct miniflow *src)
{
+ dst->count = src->count;
dst->values_inline = true;
dst->map = src->map;
memcpy(dst->inline_values, miniflow_get_values(src),
- MINIFLOW_VALUES_SIZE(n_values));
+ MINIFLOW_VALUES_SIZE(src->count));
}
/* Initializes 'dst' with the data in 'src', destroying 'src'.
@@ -1723,8 +1721,9 @@ miniflow_clone_inline(struct miniflow *dst, const struct
miniflow *src,
void
miniflow_move(struct miniflow *dst, struct miniflow *src)
{
- int size = MINIFLOW_VALUES_SIZE(miniflow_n_values(src));
+ int size = MINIFLOW_VALUES_SIZE(src->count);
+ dst->count = src->count;
dst->map = src->map;
if (size <= sizeof dst->inline_values) {
dst->values_inline = true;
@@ -1780,7 +1779,7 @@ miniflow_equal(const struct miniflow *a, const struct
miniflow *b)
const uint64_t b_map = b->map;
if (OVS_LIKELY(a_map == b_map)) {
- int count = miniflow_n_values(a);
+ int count = a->count;
return !memcmp(ap, bp, count * sizeof *ap);
} else {
@@ -1895,6 +1894,7 @@ minimask_combine(struct minimask *dst_,
dst_values[n++] = mask;
}
}
+ dst->count = n;
}
/* Frees any memory owned by 'mask'. Does not free the storage in which 'mask'
diff --git a/lib/flow.h b/lib/flow.h
index e4c3b34..0e01a6e 100644
--- a/lib/flow.h
+++ b/lib/flow.h
@@ -138,6 +138,21 @@ BUILD_ASSERT_DECL(sizeof(struct flow) % 4 == 0);
#define FLOW_U32S (sizeof(struct flow) / 4)
+#define FLOW_U32_SIZE(FIELD) \
+ DIV_ROUND_UP(sizeof(((struct flow *)0)->FIELD), sizeof(uint32_t))
+
+/* Some flow fields are mutually exclusive or only appear within the flow
+ * pipeline. IPv6 headers are bigger than IPv4, and IPv6 ND packets are bigger
+ * than IPv6 TCP packets. */
+#define FLOW_MAX_PACKET_U32S (FLOW_U32S - \
+ - FLOW_U32_SIZE(regs) \
+ - FLOW_U32_SIZE(metadata) \
+ - FLOW_U32_SIZE(nw_src) \
+ - FLOW_U32_SIZE(nw_dst) \
+ - FLOW_U32_SIZE(tcp_flags) /* incl. pad. */ \
+ - FLOW_U32_SIZE(tp_src) /* incl. tp_dst. */ \
+ )
+
/* Remember to update FLOW_WC_SEQ when changing 'struct flow'. */
BUILD_ASSERT_DECL(offsetof(struct flow, dp_hash) + sizeof(uint32_t)
== sizeof(struct flow_tnl) + 176
@@ -352,7 +367,7 @@ bool flow_equal_except(const struct flow *a, const struct
flow *b,
#define MINI_N_INLINE 8
/* Maximum number of 32-bit words supported. */
-BUILD_ASSERT_DECL(FLOW_U32S <= 63);
+BUILD_ASSERT_DECL(FLOW_U32S <= 55);
/* A sparse representation of a "struct flow".
*
@@ -384,8 +399,9 @@ BUILD_ASSERT_DECL(FLOW_U32S <= 63);
* its 'values'.
*/
struct miniflow {
- uint64_t map:63;
+ uint64_t map:55;
uint64_t values_inline:1;
+ uint64_t count:8;
union {
uint32_t *offline_values;
uint32_t inline_values[MINI_N_INLINE]; /* Minimum inline size. */
@@ -422,8 +438,9 @@ static inline const ovs_be32
*miniflow_get_be32_values(const struct miniflow *mf
static inline void miniflow_initialize(struct miniflow *mf,
uint32_t buf[FLOW_U32S])
{
- mf->map = 0;
+ mf->count = 0;
mf->values_inline = (buf == (uint32_t *)(mf + 1));
+ mf->map = 0;
if (!mf->values_inline) {
mf->offline_values = buf;
}
@@ -440,8 +457,7 @@ void miniflow_init(struct miniflow *, const struct flow *);
void miniflow_init_with_minimask(struct miniflow *, const struct flow *,
const struct minimask *);
void miniflow_clone(struct miniflow *, const struct miniflow *);
-void miniflow_clone_inline(struct miniflow *, const struct miniflow *,
- size_t n_values);
+void miniflow_clone_inline(struct miniflow *, const struct miniflow *);
void miniflow_move(struct miniflow *dst, struct miniflow *);
void miniflow_destroy(struct miniflow *);
@@ -479,9 +495,6 @@ flow_get_next_in_map(const struct flow *flow, uint64_t map,
uint32_t *value)
((U32IDX) = ctz64(map__)) < FLOW_U32S; \
map__ = zero_rightmost_1bit(map__))
-#define FLOW_U32_SIZE(FIELD) \
- DIV_ROUND_UP(sizeof(((struct flow *)0)->FIELD), sizeof(uint32_t))
-
#define MINIFLOW_MAP(FIELD) \
(((UINT64_C(1) << FLOW_U32_SIZE(FIELD)) - 1) \
<< (offsetof(struct flow, FIELD) / 4))
--
1.7.10.4
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev