This reduces the need to keep counting the bits in the map.

Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com>
---
 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
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to