It's easier to make up stats replies if you don't have to accurately
predict the number of bytes that will be necessary.

This immediately allows us to rewrite ofputil_append_flow_stats_reply()
without using NXM_MAX_LEN, which in turn allows us to deleted NXM_MAX_LEN
entirely, which is nice since keeping it up-to-date is error-prone.

An upcoming commit will introduce a second user.

Signed-off-by: Ben Pfaff <b...@nicira.com>
---
 lib/nx-match.h |   40 ----------------------------------------
 lib/ofp-util.c |   45 +++++++++++++++++++++++++++++++++++++--------
 lib/ofp-util.h |    1 +
 3 files changed, 38 insertions(+), 48 deletions(-)

diff --git a/lib/nx-match.h b/lib/nx-match.h
index c814275..2b34804 100644
--- a/lib/nx-match.h
+++ b/lib/nx-match.h
@@ -90,46 +90,6 @@ void nxm_decode(struct mf_subfield *, ovs_be32 header, 
ovs_be16 ofs_nbits);
 void nxm_decode_discrete(struct mf_subfield *, ovs_be32 header,
                          ovs_be16 ofs, ovs_be16 n_bits);
 
-BUILD_ASSERT_DECL(FLOW_WC_SEQ == 12);
-/* Upper bound on the length of an nx_match.  The longest nx_match (an
- * IPV6 neighbor discovery message using all the registers) would be:
- *
- *                   header  value  mask  total
- *                   ------  -----  ----  -----
- *  NXM_OF_IN_PORT      4       2    --      6
- *  NXM_OF_ETH_DST_W    4       6     6     16
- *  NXM_OF_ETH_SRC_W    4       6     6     16
- *  NXM_OF_ETH_TYPE     4       2    --      6
- *  NXM_OF_VLAN_TCI     4       2     2      8
- *  NXM_OF_IP_TOS       4       1    --      5
- *  NXM_NX_IP_ECN       4       1    --      5
- *  NXM_OF_IP_TTL       4       1    --      5
- *  NXM_NX_IP_FRAG      4       1     1      8
- *  NXM_OF_IP_PROTO     4       2    --      6
- *  NXM_OF_IPV6_SRC_W   4      16    16     36
- *  NXM_OF_IPV6_DST_W   4      16    16     36
- *  NXM_OF_IPV6_LABEL   4       4    --      8
- *  NXM_OF_ICMP_TYPE    4       1    --      5
- *  NXM_OF_ICMP_CODE    4       1    --      5
- *  NXM_NX_ND_TARGET    4      16    16     36
- *  NXM_NX_ND_SLL       4       6    --     10
- *  NXM_NX_REG_W(0)     4       4     4     12
- *  NXM_NX_REG_W(1)     4       4     4     12
- *  NXM_NX_REG_W(2)     4       4     4     12
- *  NXM_NX_REG_W(3)     4       4     4     12
- *  NXM_NX_REG_W(4)     4       4     4     12
- *  NXM_NX_REG_W(5)     4       4     4     12
- *  NXM_NX_REG_W(6)     4       4     4     12
- *  NXM_NX_REG_W(7)     4       4     4     12
- *  NXM_NX_TUN_ID_W     4       8     8     20
- *  OXM_OF_METADATA     4       8     8     20
- *  -------------------------------------------
- *  total                                  353
- *
- * So this value is conservative.
- */
-#define NXM_MAX_LEN 400
-
 /* This is my guess at the length of a "typical" nx_match, for use in
  * predicting space requirements. */
 #define NXM_TYPICAL_LEN 64
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index 60d0cfd..2c1dd47 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -2146,14 +2146,18 @@ ofputil_append_flow_stats_reply(const struct 
ofputil_flow_stats *fs,
         memcpy(ofs->actions, fs->actions, act_len);
     } else if (osm->type == htons(OFPST_VENDOR)) {
         struct nx_flow_stats *nfs;
+        unsigned int match_len;
         struct ofpbuf *msg;
-        size_t start_len;
+        size_t start_ofs;
 
-        msg = ofputil_reserve_stats_reply(
-            sizeof *nfs + NXM_MAX_LEN + act_len, replies);
-        start_len = msg->size;
+        msg = ofpbuf_from_list(list_back(replies));
+        start_ofs = msg->size;
 
-        nfs = ofpbuf_put_uninit(msg, sizeof *nfs);
+        ofpbuf_put_uninit(msg, sizeof *nfs);
+        match_len = nx_put_match(msg, false, &fs->rule, 0, 0);
+        ofpbuf_put(msg, fs->actions, act_len);
+
+        nfs = ofpbuf_at_assert(msg, start_ofs, sizeof *nfs);
         nfs->table_id = fs->table_id;
         nfs->pad = 0;
         nfs->duration_sec = htonl(fs->duration_sec);
@@ -2167,12 +2171,13 @@ ofputil_append_flow_stats_reply(const struct 
ofputil_flow_stats *fs,
         nfs->hard_age = htons(fs->hard_age < 0 ? 0
                               : fs->hard_age < UINT16_MAX ? fs->hard_age + 1
                               : UINT16_MAX);
-        nfs->match_len = htons(nx_put_match(msg, false, &fs->rule, 0, 0));
+        nfs->match_len = htons(match_len);
         nfs->cookie = fs->cookie;
         nfs->packet_count = htonll(fs->packet_count);
         nfs->byte_count = htonll(fs->byte_count);
-        ofpbuf_put(msg, fs->actions, act_len);
-        nfs->length = htons(msg->size - start_len);
+        nfs->length = htons(msg->size - start_ofs);
+
+        ofputil_postappend_stats_reply(start_ofs, replies);
     } else {
         NOT_REACHED();
     }
@@ -3362,6 +3367,30 @@ ofputil_append_stats_reply(size_t len, struct list 
*replies)
     return ofpbuf_put_uninit(ofputil_reserve_stats_reply(len, replies), len);
 }
 
+/* Sometimes, when composing stats replies, it's difficult to predict how long
+ * an individual reply chunk will be before actually encoding it into the reply
+ * buffer.  This function allows easy handling of this case: just encode the
+ * reply, then use this function to break the message into two pieces if it
+ * exceeds the OpenFlow message limit.
+ *
+ * In detail, if the final stats message in 'replies' is too long for OpenFlow,
+ * this function breaks it into two separate stats replies, the first one with
+ * the first 'start_ofs' bytes, the second one containing the bytes from that
+ * offset onward. */
+void
+ofputil_postappend_stats_reply(size_t start_ofs, struct list *replies)
+{
+    struct ofpbuf *msg = ofpbuf_from_list(list_back(replies));
+
+    assert(start_ofs <= UINT16_MAX);
+    if (msg->size > UINT16_MAX) {
+        size_t len = msg->size - start_ofs;
+        memcpy(ofputil_append_stats_reply(len, replies),
+               (const uint8_t *) msg->data + start_ofs, len);
+        msg->size = start_ofs;
+    }
+}
+
 /* Returns the first byte past the ofp_stats_msg header in 'oh'. */
 const void *
 ofputil_stats_body(const struct ofp_header *oh)
diff --git a/lib/ofp-util.h b/lib/ofp-util.h
index aaab83c..b177c9e 100644
--- a/lib/ofp-util.h
+++ b/lib/ofp-util.h
@@ -531,6 +531,7 @@ void ofputil_start_stats_reply(const struct ofp_stats_msg 
*request,
                                struct list *);
 struct ofpbuf *ofputil_reserve_stats_reply(size_t len, struct list *);
 void *ofputil_append_stats_reply(size_t len, struct list *);
+void ofputil_postappend_stats_reply(size_t start_ofs, struct list *);
 
 void ofputil_append_port_desc_stats_reply(uint8_t ofp_version,
                                           const struct ofputil_phy_port *pp,
-- 
1.7.2.5

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to