For some time, Open vSwitch has combined both ofp_stats_msg and
the data that follows it into single structures, because we found
that this is usually easier to handle.than having them separated.
But OpenFlow 1.1+ has a different stats message header (it has 4
extra bytes of padding) whereas many of the bodies are the same
or similar and so this approach falls down there.  Therefore, this
commit switches back to separated header and body for stats
messages.

Signed-off-by: Ben Pfaff <b...@nicira.com>
---
 include/openflow/nicira-ext.h      |    9 +--
 include/openflow/openflow-1.0.h    |   17 ++---
 include/openflow/openflow-1.1.h    |   21 ++---
 include/openflow/openflow-1.2.h    |    6 +-
 include/openflow/openflow-common.h |   18 ++--
 lib/ofp-print.c                    |   95 +++++++++++++------
 lib/ofp-util.c                     |  174 ++++++++++++++++++-----------------
 lib/ofp-util.h                     |   24 +++---
 ofproto/ofproto.c                  |   32 ++++---
 utilities/ovs-ofctl.c              |   41 ++++-----
 10 files changed, 227 insertions(+), 210 deletions(-)

diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h
index 2f46311..3ac893f 100644
--- a/include/openflow/nicira-ext.h
+++ b/include/openflow/nicira-ext.h
@@ -1838,7 +1838,6 @@ OFP_ASSERT(sizeof(struct nx_flow_removed) == 56);
  * NXM_NX_COOKIE and NXM_NX_COOKIE_W matches.
  */
 struct nx_flow_stats_request {
-    struct nicira_stats_msg nsm;
     ovs_be16 out_port;        /* Require matching entries to include this
                                  as an output port.  A value of OFPP_NONE
                                  indicates no restriction. */
@@ -1853,7 +1852,7 @@ struct nx_flow_stats_request {
      *     message.
      */
 };
-OFP_ASSERT(sizeof(struct nx_flow_stats_request) == 32);
+OFP_ASSERT(sizeof(struct nx_flow_stats_request) == 8);
 
 /* Body for Nicira vendor stats reply of type NXST_FLOW (analogous to
  * OFPST_FLOW reply).
@@ -1907,7 +1906,6 @@ OFP_ASSERT(sizeof(struct nx_flow_stats) == 48);
 /* Nicira vendor stats request of type NXST_AGGREGATE (analogous to
  * OFPST_AGGREGATE request). */
 struct nx_aggregate_stats_request {
-    struct nicira_stats_msg nsm;
     ovs_be16 out_port;        /* Require matching entries to include this
                                  as an output port.  A value of OFPP_NONE
                                  indicates no restriction. */
@@ -1922,18 +1920,17 @@ struct nx_aggregate_stats_request {
      *     message.
      */
 };
-OFP_ASSERT(sizeof(struct nx_aggregate_stats_request) == 32);
+OFP_ASSERT(sizeof(struct nx_aggregate_stats_request) == 8);
 
 /* Body for nicira_stats_msg reply of type NXST_AGGREGATE (analogous to
  * OFPST_AGGREGATE reply). */
 struct nx_aggregate_stats_reply {
-    struct nicira_stats_msg nsm;
     ovs_be64 packet_count;     /* Number of packets, UINT64_MAX if unknown. */
     ovs_be64 byte_count;       /* Number of bytes, UINT64_MAX if unknown. */
     ovs_be32 flow_count;       /* Number of flows. */
     uint8_t pad[4];            /* Align to 64 bits. */
 };
-OFP_ASSERT(sizeof(struct nx_aggregate_stats_reply) == 48);
+OFP_ASSERT(sizeof(struct nx_aggregate_stats_reply) == 24);
 
 /* NXT_SET_CONTROLLER_ID.
  *
diff --git a/include/openflow/openflow-1.0.h b/include/openflow/openflow-1.0.h
index 831f6a9..8cafd0b 100644
--- a/include/openflow/openflow-1.0.h
+++ b/include/openflow/openflow-1.0.h
@@ -531,10 +531,9 @@ enum ofp_stats_reply_flags {
 
 #define DESC_STR_LEN   256
 #define SERIAL_NUM_LEN 32
-/* Reply to OFPST_DESC request.  Each entry is a NULL-terminated ASCII
+/* Body of reply to OFPST_DESC request.  Each entry is a NULL-terminated ASCII
  * string. */
 struct ofp_desc_stats {
-    struct ofp_stats_msg osm;
     char mfr_desc[DESC_STR_LEN];       /* Manufacturer description. */
     char hw_desc[DESC_STR_LEN];        /* Hardware description. */
     char sw_desc[DESC_STR_LEN];        /* Software description. */
@@ -542,11 +541,10 @@ struct ofp_desc_stats {
     char dp_desc[DESC_STR_LEN];        /* Human readable description of
                                           the datapath. */
 };
-OFP_ASSERT(sizeof(struct ofp_desc_stats) == 1068);
+OFP_ASSERT(sizeof(struct ofp_desc_stats) == 1056);
 
 /* Stats request of type OFPST_AGGREGATE or OFPST_FLOW. */
 struct ofp_flow_stats_request {
-    struct ofp_stats_msg osm;
     struct ofp10_match match; /* Fields to match. */
     uint8_t table_id;         /* ID of table to read (from ofp_table_stats)
                                  or 0xff for all tables. */
@@ -555,7 +553,7 @@ struct ofp_flow_stats_request {
                                  as an output port.  A value of OFPP_NONE
                                  indicates no restriction. */
 };
-OFP_ASSERT(sizeof(struct ofp_flow_stats_request) == 56);
+OFP_ASSERT(sizeof(struct ofp_flow_stats_request) == 44);
 
 /* Body of reply to OFPST_FLOW request. */
 struct ofp_flow_stats {
@@ -580,13 +578,12 @@ OFP_ASSERT(sizeof(struct ofp_flow_stats) == 88);
 
 /* Reply to OFPST_AGGREGATE request. */
 struct ofp_aggregate_stats_reply {
-    struct ofp_stats_msg osm;
     ovs_32aligned_be64 packet_count; /* Number of packets in flows. */
     ovs_32aligned_be64 byte_count;   /* Number of bytes in flows. */
     ovs_be32 flow_count;      /* Number of flows. */
     uint8_t pad[4];           /* Align to 64 bits. */
 };
-OFP_ASSERT(sizeof(struct ofp_aggregate_stats_reply) == 36);
+OFP_ASSERT(sizeof(struct ofp_aggregate_stats_reply) == 24);
 
 /* Body of reply to OFPST_TABLE request. */
 struct ofp_table_stats {
@@ -605,13 +602,12 @@ OFP_ASSERT(sizeof(struct ofp_table_stats) == 64);
 
 /* Stats request of type OFPST_PORT. */
 struct ofp_port_stats_request {
-    struct ofp_stats_msg osm;
     ovs_be16 port_no;        /* OFPST_PORT message may request statistics
                                 for a single port (specified with port_no)
                                 or for all ports (port_no == OFPP_NONE). */
     uint8_t pad[6];
 };
-OFP_ASSERT(sizeof(struct ofp_port_stats_request) == 20);
+OFP_ASSERT(sizeof(struct ofp_port_stats_request) == 8);
 
 /* Body of reply to OFPST_PORT request. If a counter is unsupported, set
  * the field to all ones. */
@@ -642,12 +638,11 @@ OFP_ASSERT(sizeof(struct ofp_port_stats) == 104);
 
 /* Body for stats request of type OFPST_QUEUE. */
 struct ofp_queue_stats_request {
-    struct ofp_stats_msg osm;
     ovs_be16 port_no;        /* All ports if OFPP_ALL. */
     uint8_t pad[2];          /* Align to 32-bits. */
     ovs_be32 queue_id;       /* All queues if OFPQ_ALL. */
 };
-OFP_ASSERT(sizeof(struct ofp_queue_stats_request) == 20);
+OFP_ASSERT(sizeof(struct ofp_queue_stats_request) == 8);
 
 /* Body for stats reply of type OFPST_QUEUE consists of an array of this
  * structure type. */
diff --git a/include/openflow/openflow-1.1.h b/include/openflow/openflow-1.1.h
index 7d6e016..f23620c 100644
--- a/include/openflow/openflow-1.1.h
+++ b/include/openflow/openflow-1.1.h
@@ -529,7 +529,6 @@ OFP_ASSERT(sizeof(struct ofp11_stats_msg) == 16);
 
 /* Stats request of type OFPST_FLOW. */
 struct ofp11_flow_stats_request {
-    struct ofp11_stats_msg osm;
     uint8_t table_id;         /* ID of table to read (from ofp_table_stats),
                                  0xff for all tables. */
     uint8_t pad[3];           /* Align to 64 bits. */
@@ -547,7 +546,7 @@ struct ofp11_flow_stats_request {
                                  no restriction. */
     struct ofp11_match match; /* Fields to match. */
 };
-OFP_ASSERT(sizeof(struct ofp11_flow_stats_request) == 136);
+OFP_ASSERT(sizeof(struct ofp11_flow_stats_request) == 120);
 
 /* Body of reply to OFPST_FLOW request. */
 struct ofp11_flow_stats {
@@ -575,7 +574,6 @@ OFP_ASSERT(sizeof(struct ofp11_flow_stats) == 48);
 
 /* Body of reply to OFPST_TABLE request. */
 struct ofp11_table_stats {
-    struct ofp11_stats_msg osm;
     uint8_t table_id;        /* Identifier of table. Lower numbered tables
                                 are consulted first. */
     uint8_t pad[7];          /* Align to 64-bits. */
@@ -595,23 +593,21 @@ struct ofp11_table_stats {
     ovs_be64 lookup_count;   /* Number of packets looked up in table. */
     ovs_be64 matched_count;  /* Number of packets that hit table. */
 };
-OFP_ASSERT(sizeof(struct ofp11_table_stats) == 104);
+OFP_ASSERT(sizeof(struct ofp11_table_stats) == 88);
 
 /* Body for ofp_stats_request of type OFPST_PORT. */
 struct ofp11_port_stats_request {
-    struct ofp11_stats_msg osm;
     ovs_be32 port_no;        /* OFPST_PORT message must request statistics
                               * either for a single port (specified in
                               * port_no) or for all ports (if port_no ==
                               * OFPP_ANY). */
     uint8_t pad[4];
 };
-OFP_ASSERT(sizeof(struct ofp11_port_stats_request) == 24);
+OFP_ASSERT(sizeof(struct ofp11_port_stats_request) == 8);
 
 /* Body of reply to OFPST_PORT request. If a counter is unsupported, set
  * the field to all ones. */
 struct ofp11_port_stats {
-    struct ofp11_stats_msg osm;
     ovs_be32 port_no;
     uint8_t pad[4];           /* Align to 64-bits. */
     ovs_be64 rx_packets;      /* Number of received packets. */
@@ -631,31 +627,28 @@ struct ofp11_port_stats {
     ovs_be64 rx_crc_err;      /* Number of CRC errors. */
     ovs_be64 collisions;      /* Number of collisions. */
 };
-OFP_ASSERT(sizeof(struct ofp11_port_stats) == 120);
+OFP_ASSERT(sizeof(struct ofp11_port_stats) == 104);
 
 struct ofp11_queue_stats_request {
-    struct ofp11_stats_msg osm;
     ovs_be32 port_no;         /* All ports if OFPP_ANY. */
     ovs_be32 queue_id;        /* All queues if OFPQ_ALL. */
 };
-OFP_ASSERT(sizeof(struct ofp11_queue_stats_request) == 24);
+OFP_ASSERT(sizeof(struct ofp11_queue_stats_request) == 8);
 
 struct ofp11_queue_stats {
-    struct ofp11_stats_msg osm;
     ovs_be32 port_no;
     ovs_be32 queue_id;         /* Queue id. */
     ovs_be64 tx_bytes;         /* Number of transmitted bytes. */
     ovs_be64 tx_packets;       /* Number of transmitted packets. */
     ovs_be64 tx_errors;        /* # of packets dropped due to overrun. */
 };
-OFP_ASSERT(sizeof(struct ofp11_queue_stats) == 48);
+OFP_ASSERT(sizeof(struct ofp11_queue_stats) == 32);
 
 struct ofp11_group_stats_request {
-    struct ofp11_stats_msg osm;
     ovs_be32 group_id;         /* All groups if OFPG_ALL. */
     uint8_t pad[4];            /* Align to 64 bits. */
 };
-OFP_ASSERT(sizeof(struct ofp11_group_stats_request) == 24);
+OFP_ASSERT(sizeof(struct ofp11_group_stats_request) == 8);
 
 /* Body of reply to OFPST11_GROUP request */
 struct ofp11_group_stats {
diff --git a/include/openflow/openflow-1.2.h b/include/openflow/openflow-1.2.h
index bb55881..daa8d34 100644
--- a/include/openflow/openflow-1.2.h
+++ b/include/openflow/openflow-1.2.h
@@ -264,7 +264,6 @@ enum ofp12_queue_properties {
 
 /* Body of reply to OFPST_TABLE request. */
 struct ofp12_table_stats {
-    struct ofp11_stats_msg osm;
     uint8_t table_id;        /* Identifier of table.  Lower numbered tables
                                 are consulted first. */
     uint8_t pad[7];          /* Align to 64-bits. */
@@ -290,17 +289,16 @@ struct ofp12_table_stats {
     ovs_be64 lookup_count;   /* Number of packets looked up in table. */
     ovs_be64 matched_count;  /* Number of packets that hit table. */
 };
-OFP_ASSERT(sizeof(struct ofp12_table_stats) == 144);
+OFP_ASSERT(sizeof(struct ofp12_table_stats) == 128);
 
 /* Body of reply to OFPST12_GROUP_FEATURES request. Group features. */
 struct ofp12_group_features_stats {
-    struct ofp11_stats_msg osm;
     ovs_be32  types;           /* Bitmap of OFPGT_* values supported. */
     ovs_be32  capabilities;    /* Bitmap of OFPGFC12_* capability supported. */
     ovs_be32  max_groups[4];   /* Maximum number of groups for each type. */
     ovs_be32  actions[4];      /* Bitmaps of OFPAT_* that are supported. */
 };
-OFP_ASSERT(sizeof(struct ofp12_group_features_stats) == 56);
+OFP_ASSERT(sizeof(struct ofp12_group_features_stats) == 40);
 
 /* Group configuration flags */
 enum ofp12_group_capabilities {
diff --git a/include/openflow/openflow-common.h 
b/include/openflow/openflow-common.h
index 3dc76cc..833737f 100644
--- a/include/openflow/openflow-common.h
+++ b/include/openflow/openflow-common.h
@@ -244,39 +244,39 @@ OFP_ASSERT(sizeof(struct ofp_port_status) == 16);
 
 enum ofp_stats_types {
     /* Description of this OpenFlow switch. (OFPMP_DESC)
-     * The OF1.0 request is struct ofp_stats_msg.
-     * The OF1.0 reply is struct ofp_desc_stats. */
+     * The OF1.0 request body is empty.
+     * The OF1.0 reply body is struct ofp_desc_stats. */
     OFPST_DESC = 0,
 
     /* Individual flow statistics. (OFPMP_FLOW)
-     * The OF1.0 request is struct ofp_flow_stats_request.
+     * The OF1.0 request body is struct ofp_flow_stats_request.
      * The OF1.0 reply body is an array of struct ofp_flow_stats. */
     OFPST_FLOW = 1,
 
     /* Aggregate flow statistics. (OFPMP_AGGREGATE)
-     * The OF1.0 request is struct ofp_flow_stats_request.
-     * The OF1.0 reply is struct ofp_aggregate_stats_reply. */
+     * The OF1.0 request body is struct ofp_flow_stats_request.
+     * The OF1.0 reply body is struct ofp_aggregate_stats_reply. */
     OFPST_AGGREGATE = 2,
 
     /* Flow table statistics. (OFPMP_TABLE)
-     * The OF1.0 request is struct ofp_stats_msg.
+     * The OF1.0 request body is struct ofp_stats_msg.
      * The OF1.0 reply body is an array of struct ofp_table_stats. */
     OFPST_TABLE = 3,
 
     /* Physical port statistics. (OFPMP_PORT_STATS)
-     * The OF1.0 request is struct ofp_port_stats_request.
+     * The OF1.0 request body is struct ofp_port_stats_request.
      * The OF1.0 reply body is an array of struct ofp_port_stats. */
     OFPST_PORT = 4,
 
     /* Queue statistics for a port. (OFPMP_QUEUE)
-     * The OF1.0 request is struct ofp_stats_msg.
+     * The OF1.0 request body is empty.
      * The OF1.0 reply body is an array of struct ofp_queue_stats. */
     OFPST_QUEUE = 5,
 
     /* Port description. (OFPMP_PORT_DESC)
      * This was introduced as part of OF1.3, but is useful for bridges
      * with many ports, so we support it with OF1.0, too.
-     * The OF1.0 request is struct ofp_stats_msg.
+     * The OF1.0 request body is empty.
      * The OF1.0 reply body is an array of struct ofp10_phy_port. */
     OFPST_PORT_DESC = 13,
 
diff --git a/lib/ofp-print.c b/lib/ofp-print.c
index e3807f2..52fe39e 100644
--- a/lib/ofp-print.c
+++ b/lib/ofp-print.c
@@ -920,8 +920,10 @@ ofp_print_port_status(struct ds *string, const struct 
ofp_port_status *ops)
 }
 
 static void
-ofp_print_ofpst_desc_reply(struct ds *string, const struct ofp_desc_stats *ods)
+ofp_print_ofpst_desc_reply(struct ds *string, const struct ofp_header *oh)
 {
+    const struct ofp_desc_stats *ods = ofputil_stats_msg_body(oh);
+
     ds_put_char(string, '\n');
     ds_put_format(string, "Manufacturer: %.*s\n",
             (int) sizeof ods->mfr_desc, ods->mfr_desc);
@@ -936,13 +938,12 @@ ofp_print_ofpst_desc_reply(struct ds *string, const 
struct ofp_desc_stats *ods)
 }
 
 static void
-ofp_print_flow_stats_request(struct ds *string,
-                             const struct ofp_stats_msg *osm)
+ofp_print_flow_stats_request(struct ds *string, const struct ofp_header *oh)
 {
     struct ofputil_flow_stats_request fsr;
     enum ofperr error;
 
-    error = ofputil_decode_flow_stats_request(&fsr, &osm->header);
+    error = ofputil_decode_flow_stats_request(&fsr, oh);
     if (error) {
         ofp_print_error(string, error);
         return;
@@ -1016,9 +1017,10 @@ ofp_print_flow_stats_reply(struct ds *string, const 
struct ofp_header *oh)
 }
 
 static void
-ofp_print_ofpst_aggregate_reply(struct ds *string,
-                                const struct ofp_aggregate_stats_reply *asr)
+ofp_print_ofpst_aggregate_reply(struct ds *string, const struct ofp_header *oh)
 {
+    const struct ofp_aggregate_stats_reply *asr = ofputil_stats_msg_body(oh);
+
     ds_put_format(string, " packet_count=%"PRIu64,
                   ntohll(get_32aligned_be64(&asr->packet_count)));
     ds_put_format(string, " byte_count=%"PRIu64,
@@ -1027,9 +1029,10 @@ ofp_print_ofpst_aggregate_reply(struct ds *string,
 }
 
 static void
-ofp_print_nxst_aggregate_reply(struct ds *string,
-                               const struct nx_aggregate_stats_reply *nasr)
+ofp_print_nxst_aggregate_reply(struct ds *string, const struct ofp_header *oh)
 {
+    const struct nx_aggregate_stats_reply *nasr = ofputil_stats_msg_body(oh);
+
     ds_put_format(string, " packet_count=%"PRIu64, ntohll(nasr->packet_count));
     ds_put_format(string, " byte_count=%"PRIu64, ntohll(nasr->byte_count));
     ds_put_format(string, " flow_count=%"PRIu32, ntohl(nasr->flow_count));
@@ -1054,9 +1057,9 @@ static void print_port_stat(struct ds *string, const char 
*leader,
 }
 
 static void
-ofp_print_ofpst_port_request(struct ds *string,
-                             const struct ofp_port_stats_request *psr)
+ofp_print_ofpst_port_request(struct ds *string, const struct ofp_header *oh)
 {
+    const struct ofp_port_stats_request *psr = ofputil_stats_msg_body(oh);
     ds_put_format(string, " port_no=%"PRIu16, ntohs(psr->port_no));
 }
 
@@ -1064,14 +1067,25 @@ static void
 ofp_print_ofpst_port_reply(struct ds *string, const struct ofp_header *oh,
                            int verbosity)
 {
-    const struct ofp_port_stats *ps = ofputil_stats_body(oh);
-    size_t n = ofputil_stats_body_len(oh) / sizeof *ps;
+    struct ofp_port_stats *ps;
+    struct ofpbuf b;
+    size_t n;
+
+    ofpbuf_use_const(&b, oh, ntohs(oh->length));
+    ofputil_pull_stats_msg(&b);
+
+    n = b.size / sizeof *ps;
     ds_put_format(string, " %zu ports\n", n);
     if (verbosity < 1) {
         return;
     }
 
-    for (; n--; ps++) {
+    for (;;) {
+        ps = ofpbuf_try_pull(&b, sizeof *ps);
+        if (!ps) {
+            return;
+        }
+
         ds_put_format(string, "  port %2"PRIu16": ", ntohs(ps->port_no));
 
         ds_put_cstr(string, "rx ");
@@ -1096,15 +1110,27 @@ static void
 ofp_print_ofpst_table_reply(struct ds *string, const struct ofp_header *oh,
                             int verbosity)
 {
-    const struct ofp_table_stats *ts = ofputil_stats_body(oh);
-    size_t n = ofputil_stats_body_len(oh) / sizeof *ts;
+    struct ofp_table_stats *ts;
+    struct ofpbuf b;
+    size_t n;
+
+    ofpbuf_use_const(&b, oh, ntohs(oh->length));
+    ofputil_pull_stats_msg(&b);
+
+    n = b.size / sizeof *ts;
     ds_put_format(string, " %zu tables\n", n);
     if (verbosity < 1) {
         return;
     }
 
-    for (; n--; ts++) {
+    for (;;) {
         char name[OFP_MAX_TABLE_NAME_LEN + 1];
+
+        ts = ofpbuf_try_pull(&b, sizeof *ts);
+        if (!ts) {
+            return;
+        }
+
         ovs_strlcpy(name, ts->name, sizeof name);
 
         ds_put_format(string, "  %d: %-8s: ", ts->table_id, name);
@@ -1130,9 +1156,10 @@ ofp_print_queue_name(struct ds *string, uint32_t 
queue_id)
 }
 
 static void
-ofp_print_ofpst_queue_request(struct ds *string,
-                              const struct ofp_queue_stats_request *qsr)
+ofp_print_ofpst_queue_request(struct ds *string, const struct ofp_header *oh)
 {
+    const struct ofp_queue_stats_request *qsr = ofputil_stats_msg_body(oh);
+
     ds_put_cstr(string, "port=");
     ofputil_format_port(ntohs(qsr->port_no), string);
 
@@ -1144,14 +1171,25 @@ static void
 ofp_print_ofpst_queue_reply(struct ds *string, const struct ofp_header *oh,
                             int verbosity)
 {
-    const struct ofp_queue_stats *qs = ofputil_stats_body(oh);
-    size_t n = ofputil_stats_body_len(oh) / sizeof *qs;
+    struct ofp_queue_stats *qs;
+    struct ofpbuf b;
+    size_t n;
+
+    ofpbuf_use_const(&b, oh, ntohs(oh->length));
+    ofputil_pull_stats_msg(&b);
+
+    n = b.size / sizeof *qs;
     ds_put_format(string, " %zu queues\n", n);
     if (verbosity < 1) {
         return;
     }
 
-    for (; n--; qs++) {
+    for (;;) {
+        qs = ofpbuf_try_pull(&b, sizeof *qs);
+        if (!qs) {
+            return;
+        }
+
         ds_put_cstr(string, "  port ");
         ofputil_format_port(ntohs(qs->port_no), string);
         ds_put_cstr(string, " queue ");
@@ -1171,7 +1209,7 @@ ofp_print_ofpst_port_desc_reply(struct ds *string,
     struct ofpbuf b;
 
     ofpbuf_use_const(&b, oh, ntohs(oh->length));
-    ofpbuf_pull(&b, sizeof(struct ofp_stats_msg));
+    ofputil_pull_stats_msg(&b);
     ds_put_char(string, '\n');
     ofp_print_phy_ports(string, oh->version, &b);
 }
@@ -1179,22 +1217,19 @@ ofp_print_ofpst_port_desc_reply(struct ds *string,
 static void
 ofp_print_stats_request(struct ds *string, const struct ofp_header *oh)
 {
-    const struct ofp_stats_msg *srq = (const struct ofp_stats_msg *) oh;
+    uint16_t flags = ofputil_decode_stats_msg_flags(oh);
 
-    if (srq->flags) {
-        ds_put_format(string, " ***unknown flags 0x%04"PRIx16"***",
-                      ntohs(srq->flags));
+    if (flags) {
+        ds_put_format(string, " ***unknown flags 0x%04"PRIx16"***", flags);
     }
 }
 
 static void
 ofp_print_stats_reply(struct ds *string, const struct ofp_header *oh)
 {
-    const struct ofp_stats_msg *srp = (const struct ofp_stats_msg *) oh;
-
-    if (srp->flags) {
-        uint16_t flags = ntohs(srp->flags);
+    uint16_t flags = ofputil_decode_stats_msg_flags(oh);
 
+    if (flags) {
         ds_put_cstr(string, " flags=");
         if (flags & OFPSF_REPLY_MORE) {
             ds_put_cstr(string, "[more]");
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index e80fe18..02be8f9 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -755,11 +755,13 @@ ofputil_decode_nxst_request(const struct ofp_header *oh, 
size_t length,
     static const struct ofputil_msg_type nxst_requests[] = {
         { OFPUTIL_NXST_FLOW_REQUEST, OFP10_VERSION,
           NXST_FLOW, "NXST_FLOW request",
-          sizeof(struct nx_flow_stats_request), 8 },
+          sizeof(struct nicira_stats_msg) + sizeof(struct 
nx_flow_stats_request),
+          8 },
 
         { OFPUTIL_NXST_AGGREGATE_REQUEST, OFP10_VERSION,
           NXST_AGGREGATE, "NXST_AGGREGATE request",
-          sizeof(struct nx_aggregate_stats_request), 8 },
+          sizeof(struct nicira_stats_msg) + sizeof(struct 
nx_aggregate_stats_request),
+          8 },
     };
 
     static const struct ofputil_msg_category nxst_request_category = {
@@ -792,7 +794,8 @@ ofputil_decode_nxst_reply(const struct ofp_header *oh, 
size_t length,
 
         { OFPUTIL_NXST_AGGREGATE_REPLY, OFP10_VERSION,
           NXST_AGGREGATE, "NXST_AGGREGATE reply",
-          sizeof(struct nx_aggregate_stats_reply), 0 },
+          sizeof(struct nicira_stats_msg) + sizeof(struct 
nx_aggregate_stats_reply),
+          0 },
     };
 
     static const struct ofputil_msg_category nxst_reply_category = {
@@ -838,11 +841,13 @@ ofputil_decode_ofpst_request(const struct ofp_header *oh, 
size_t length,
 
         { OFPUTIL_OFPST_FLOW_REQUEST, OFP10_VERSION,
           OFPST_FLOW, "OFPST_FLOW request",
-          sizeof(struct ofp_flow_stats_request), 0 },
+          sizeof(struct ofp_stats_msg) + sizeof(struct ofp_flow_stats_request),
+          0 },
 
         { OFPUTIL_OFPST_AGGREGATE_REQUEST, OFP10_VERSION,
           OFPST_AGGREGATE, "OFPST_AGGREGATE request",
-          sizeof(struct ofp_flow_stats_request), 0 },
+          sizeof(struct ofp_stats_msg) + sizeof(struct ofp_flow_stats_request),
+          0 },
 
         { OFPUTIL_OFPST_TABLE_REQUEST, OFP10_VERSION,
           OFPST_TABLE, "OFPST_TABLE request",
@@ -850,11 +855,13 @@ ofputil_decode_ofpst_request(const struct ofp_header *oh, 
size_t length,
 
         { OFPUTIL_OFPST_PORT_REQUEST, OFP10_VERSION,
           OFPST_PORT, "OFPST_PORT request",
-          sizeof(struct ofp_port_stats_request), 0 },
+          sizeof(struct ofp_stats_msg) + sizeof(struct ofp_port_stats_request),
+          0 },
 
         { OFPUTIL_OFPST_QUEUE_REQUEST, OFP10_VERSION,
           OFPST_QUEUE, "OFPST_QUEUE request",
-          sizeof(struct ofp_queue_stats_request), 0 },
+          sizeof(struct ofp_stats_msg) + sizeof(struct 
ofp_queue_stats_request),
+          0 },
 
         { OFPUTIL_OFPST_PORT_DESC_REQUEST, OFP10_VERSION,
           OFPST_PORT_DESC, "OFPST_PORT_DESC request",
@@ -895,7 +902,7 @@ ofputil_decode_ofpst_reply(const struct ofp_header *oh, 
size_t length,
     static const struct ofputil_msg_type ofpst_replies[] = {
         { OFPUTIL_OFPST_DESC_REPLY, OFP10_VERSION,
           OFPST_DESC, "OFPST_DESC reply",
-          sizeof(struct ofp_desc_stats), 0 },
+          sizeof(struct ofp_stats_msg) + sizeof(struct ofp_desc_stats), 0 },
 
         { OFPUTIL_OFPST_FLOW_REPLY, OFP10_VERSION,
           OFPST_FLOW, "OFPST_FLOW reply",
@@ -903,7 +910,8 @@ ofputil_decode_ofpst_reply(const struct ofp_header *oh, 
size_t length,
 
         { OFPUTIL_OFPST_AGGREGATE_REPLY, OFP10_VERSION,
           OFPST_AGGREGATE, "OFPST_AGGREGATE reply",
-          sizeof(struct ofp_aggregate_stats_reply), 0 },
+          sizeof(struct ofp_stats_msg) + sizeof(struct 
ofp_aggregate_stats_reply),
+          0 },
 
         { OFPUTIL_OFPST_TABLE_REPLY, OFP10_VERSION,
           OFPST_TABLE, "OFPST_TABLE reply",
@@ -1839,12 +1847,9 @@ ofputil_flow_mod_usable_protocols(const struct 
ofputil_flow_mod *fms,
 
 static enum ofperr
 ofputil_decode_ofpst_flow_request(struct ofputil_flow_stats_request *fsr,
-                                  const struct ofp_header *oh,
+                                  const struct ofp_flow_stats_request *ofsr,
                                   bool aggregate)
 {
-    const struct ofp_flow_stats_request *ofsr =
-        (const struct ofp_flow_stats_request *) oh;
-
     fsr->aggregate = aggregate;
     ofputil_cls_rule_from_ofp10_match(&ofsr->match, 0, &fsr->match);
     fsr->out_port = ntohs(ofsr->out_port);
@@ -1856,22 +1861,18 @@ ofputil_decode_ofpst_flow_request(struct 
ofputil_flow_stats_request *fsr,
 
 static enum ofperr
 ofputil_decode_nxst_flow_request(struct ofputil_flow_stats_request *fsr,
-                                 const struct ofp_header *oh,
-                                 bool aggregate)
+                                 struct ofpbuf *b, bool aggregate)
 {
     const struct nx_flow_stats_request *nfsr;
-    struct ofpbuf b;
     enum ofperr error;
 
-    ofpbuf_use_const(&b, oh, ntohs(oh->length));
-
-    nfsr = ofpbuf_pull(&b, sizeof *nfsr);
-    error = nx_pull_match(&b, ntohs(nfsr->match_len), 0, &fsr->match,
+    nfsr = ofpbuf_pull(b, sizeof *nfsr);
+    error = nx_pull_match(b, ntohs(nfsr->match_len), 0, &fsr->match,
                           &fsr->cookie, &fsr->cookie_mask);
     if (error) {
         return error;
     }
-    if (b.size) {
+    if (b->size) {
         return OFPERR_OFPBRC_BAD_LEN;
     }
 
@@ -1894,21 +1895,22 @@ ofputil_decode_flow_stats_request(struct 
ofputil_flow_stats_request *fsr,
     int code;
 
     ofpbuf_use_const(&b, oh, ntohs(oh->length));
+    ofputil_pull_stats_msg(&b);
 
     ofputil_decode_msg_type(oh, &type);
     code = ofputil_msg_type_code(type);
     switch (code) {
     case OFPUTIL_OFPST_FLOW_REQUEST:
-        return ofputil_decode_ofpst_flow_request(fsr, oh, false);
+        return ofputil_decode_ofpst_flow_request(fsr, b.data, false);
 
     case OFPUTIL_OFPST_AGGREGATE_REQUEST:
-        return ofputil_decode_ofpst_flow_request(fsr, oh, true);
+        return ofputil_decode_ofpst_flow_request(fsr, b.data, true);
 
     case OFPUTIL_NXST_FLOW_REQUEST:
-        return ofputil_decode_nxst_flow_request(fsr, oh, false);
+        return ofputil_decode_nxst_flow_request(fsr, &b, false);
 
     case OFPUTIL_NXST_AGGREGATE_REQUEST:
-        return ofputil_decode_nxst_flow_request(fsr, oh, true);
+        return ofputil_decode_nxst_flow_request(fsr, &b, true);
 
     default:
         /* Hey, the caller lied. */
@@ -1950,7 +1952,7 @@ ofputil_encode_flow_stats_request(const struct 
ofputil_flow_stats_request *fsr,
         match_len = nx_put_match(msg, false, &fsr->match,
                                  fsr->cookie, fsr->cookie_mask);
 
-        nfsr = msg->data;
+        nfsr = ofputil_stats_msg_body(msg->data);
         nfsr->out_port = htons(fsr->out_port);
         nfsr->match_len = htons(match_len);
         nfsr->table_id = fsr->table_id;
@@ -2014,13 +2016,7 @@ ofputil_decode_flow_stats_reply(struct 
ofputil_flow_stats *fs,
     code = ofputil_msg_type_code(type);
     if (!msg->l2) {
         msg->l2 = msg->data;
-        if (code == OFPUTIL_OFPST_FLOW_REPLY) {
-            ofpbuf_pull(msg, sizeof(struct ofp_stats_msg));
-        } else if (code == OFPUTIL_NXST_FLOW_REPLY) {
-            ofpbuf_pull(msg, sizeof(struct nicira_stats_msg));
-        } else {
-            NOT_REACHED();
-        }
+        ofputil_pull_stats_msg(msg);
     }
 
     if (!msg->size) {
@@ -2195,11 +2191,15 @@ ofputil_append_flow_stats_reply(const struct 
ofputil_flow_stats *fs,
 struct ofpbuf *
 ofputil_encode_aggregate_stats_reply(
     const struct ofputil_aggregate_stats *stats,
-    const struct ofp_stats_msg *request)
+    const struct ofp_header *request)
 {
+    const struct ofputil_msg_type *type;
+    enum ofputil_msg_code code;
     struct ofpbuf *msg;
 
-    if (request->type == htons(OFPST_AGGREGATE)) {
+    ofputil_decode_msg_type(request, &type);
+    code = ofputil_msg_type_code(type);
+    if (code == OFPUTIL_OFPST_AGGREGATE_REQUEST) {
         struct ofp_aggregate_stats_reply *asr;
 
         asr = ofputil_make_stats_reply(sizeof *asr, request, &msg);
@@ -2208,11 +2208,10 @@ ofputil_encode_aggregate_stats_reply(
         put_32aligned_be64(&asr->byte_count,
                            htonll(unknown_to_zero(stats->byte_count)));
         asr->flow_count = htonl(stats->flow_count);
-    } else if (request->type == htons(OFPST_VENDOR)) {
+    } else if (code == OFPUTIL_NXST_AGGREGATE_REQUEST) {
         struct nx_aggregate_stats_reply *nasr;
 
         nasr = ofputil_make_stats_reply(sizeof *nasr, request, &msg);
-        assert(nasr->nsm.subtype == htonl(NXST_AGGREGATE));
         nasr->packet_count = htonll(stats->packet_count);
         nasr->byte_count = htonll(stats->byte_count);
         nasr->flow_count = htonl(stats->flow_count);
@@ -3274,61 +3273,59 @@ put_stats__(ovs_be32 xid, uint8_t ofp_type,
     }
 }
 
-/* Creates a statistics request message with total length 'openflow_len'
- * (including all headers) and the given 'ofpst_type', and stores the buffer
- * containing the new message in '*bufferp'.  If 'ofpst_type' is OFPST_VENDOR
- * then 'nxst_subtype' is used as the Nicira vendor extension statistics
- * subtype (otherwise 'nxst_subtype' is ignored).
+/* Creates a statistics request message with the given 'ofpst_type', and stores
+ * the buffer containing the new message in '*bufferp'.  If 'ofpst_type' is
+ * OFPST_VENDOR then 'nxst_subtype' is used as the Nicira vendor extension
+ * statistics subtype (otherwise 'nxst_subtype' is ignored).
  *
- * Initializes bytes following the headers to all-bits-zero.
- *
- * Returns the first byte of the new message. */
+ * Appends 'body_len' bytes of zeroes to the reply as the body and returns the
+ * first byte of the body. */
 void *
-ofputil_make_stats_request(size_t openflow_len, uint16_t ofpst_type,
+ofputil_make_stats_request(size_t body_len, uint16_t ofpst_type,
                            uint32_t nxst_subtype, struct ofpbuf **bufferp)
 {
     struct ofpbuf *msg;
 
-    msg = *bufferp = ofpbuf_new(openflow_len);
+    msg = *bufferp = ofpbuf_new(24 + body_len);
     put_stats__(alloc_xid(), OFPT10_STATS_REQUEST,
                 htons(ofpst_type), htonl(nxst_subtype), msg);
-    ofpbuf_padto(msg, openflow_len);
 
-    return msg->data;
+    return ofpbuf_put_zeros(msg, body_len);
 }
 
 static void
-put_stats_reply__(const struct ofp_stats_msg *request, struct ofpbuf *msg)
+put_stats_reply__(const struct ofp_header *request, struct ofpbuf *msg)
 {
-    assert(request->header.type == OFPT10_STATS_REQUEST ||
-           request->header.type == OFPT10_STATS_REPLY);
-    put_stats__(request->header.xid, OFPT10_STATS_REPLY, request->type,
-                (request->type != htons(OFPST_VENDOR)
+    const struct ofp_stats_msg *osm;
+
+    assert(request->type == OFPT10_STATS_REQUEST ||
+           request->type == OFPT10_STATS_REPLY);
+
+    osm = (const struct ofp_stats_msg *) request;
+    put_stats__(request->xid, OFPT10_STATS_REPLY, osm->type,
+                (osm->type != htons(OFPST_VENDOR)
                  ? htonl(0)
                  : ((const struct nicira_stats_msg *) request)->subtype),
                 msg);
 }
 
-/* Creates a statistics reply message with total length 'openflow_len'
- * (including all headers) and the same type (either a standard OpenFlow
- * statistics type or a Nicira extension type and subtype) as 'request', and
- * stores the buffer containing the new message in '*bufferp'.
+/* Creates a statistics reply message with the same type (either a standard
+ * OpenFlow statistics type or a Nicira extension type and subtype) as
+ * 'request', and stores the buffer containing the new message in '*bufferp'.
  *
- * Initializes bytes following the headers to all-bits-zero.
- *
- * Returns the first byte of the new message. */
+ * Appends 'body_len' bytes of zeroes to the reply as the body and returns the
+ * first byte of the body. */
 void *
-ofputil_make_stats_reply(size_t openflow_len,
-                         const struct ofp_stats_msg *request,
+ofputil_make_stats_reply(size_t body_len,
+                         const struct ofp_header *request,
                          struct ofpbuf **bufferp)
 {
     struct ofpbuf *msg;
 
-    msg = *bufferp = ofpbuf_new(openflow_len);
+    msg = *bufferp = ofpbuf_new(24 + body_len);
     put_stats_reply__(request, msg);
-    ofpbuf_padto(msg, openflow_len);
 
-    return msg->data;
+    return ofpbuf_put_zeros(msg, body_len);
 }
 
 /* Initializes 'replies' as a list of ofpbufs that will contain a series of
@@ -3337,7 +3334,7 @@ ofputil_make_stats_reply(size_t openflow_len,
  * that has only a header.  The functions ofputil_reserve_stats_reply() and
  * ofputil_append_stats_reply() may be used to add to the reply. */
 void
-ofputil_start_stats_reply(const struct ofp_stats_msg *request,
+ofputil_start_stats_reply(const struct ofp_header *request,
                           struct list *replies)
 {
     struct ofpbuf *msg;
@@ -3366,7 +3363,7 @@ ofputil_reserve_stats_reply(size_t len, struct list 
*replies)
         osm->flags |= htons(OFPSF_REPLY_MORE);
 
         msg = ofpbuf_new(MAX(1024, sizeof(struct nicira_stats_msg) + len));
-        put_stats_reply__(osm, msg);
+        put_stats_reply__(&osm->header, msg);
         list_push_back(replies, &msg->list_node);
     }
     return msg;
@@ -3394,36 +3391,43 @@ ofputil_postappend_stats_reply(size_t start_ofs, struct 
list *replies)
     }
 }
 
-/* Returns the first byte past the ofp_stats_msg header in 'oh'. */
-const void *
-ofputil_stats_body(const struct ofp_header *oh)
+size_t
+ofputil_stats_msg_len(const struct ofp_header *oh)
 {
+    const struct ofp_stats_msg *osm;
+
     assert(oh->type == OFPT10_STATS_REQUEST || oh->type == OFPT10_STATS_REPLY);
-    return (const struct ofp_stats_msg *) oh + 1;
+
+    osm = (const struct ofp_stats_msg *) oh;
+    return (osm->type == htons(OFPST_VENDOR)
+            ? sizeof(struct nicira_stats_msg)
+            : sizeof(struct ofp_stats_msg));
 }
 
-/* Returns the number of bytes past the ofp_stats_msg header in 'oh'. */
-size_t
-ofputil_stats_body_len(const struct ofp_header *oh)
+void
+ofputil_pull_stats_msg(struct ofpbuf *msg)
 {
-    assert(oh->type == OFPT10_STATS_REQUEST || oh->type == OFPT10_STATS_REPLY);
-    return ntohs(oh->length) - sizeof(struct ofp_stats_msg);
+    ofpbuf_pull(msg, ofputil_stats_msg_len(msg->data));
+}
+
+void *
+ofputil_stats_msg_body(const struct ofp_header *oh)
+{
+    return (uint8_t *) oh + ofputil_stats_msg_len(oh);
 }
 
-/* Returns the first byte past the nicira_stats_msg header in 'oh'. */
-const void *
-ofputil_nxstats_body(const struct ofp_header *oh)
+uint16_t
+ofputil_decode_stats_msg_type(const struct ofp_header *oh)
 {
     assert(oh->type == OFPT10_STATS_REQUEST || oh->type == OFPT10_STATS_REPLY);
-    return ((const struct nicira_stats_msg *) oh) + 1;
+    return ntohs(((const struct ofp_stats_msg *) oh)->type);
 }
 
-/* Returns the number of bytes past the nicira_stats_msg header in 'oh'. */
-size_t
-ofputil_nxstats_body_len(const struct ofp_header *oh)
+uint16_t
+ofputil_decode_stats_msg_flags(const struct ofp_header *oh)
 {
     assert(oh->type == OFPT10_STATS_REQUEST || oh->type == OFPT10_STATS_REPLY);
-    return ntohs(oh->length) - sizeof(struct nicira_stats_msg);
+    return ntohs(((const struct ofp_stats_msg *) oh)->flags);
 }
 
 /* Creates and returns an OFPT_ECHO_REQUEST message with an empty payload. */
diff --git a/lib/ofp-util.h b/lib/ofp-util.h
index 30e04c4..2dbde05 100644
--- a/lib/ofp-util.h
+++ b/lib/ofp-util.h
@@ -301,7 +301,7 @@ struct ofputil_aggregate_stats {
 
 struct ofpbuf *ofputil_encode_aggregate_stats_reply(
     const struct ofputil_aggregate_stats *stats,
-    const struct ofp_stats_msg *request);
+    const struct ofp_header *request);
 
 /* Flow removed message, independent of protocol. */
 struct ofputil_flow_removed {
@@ -525,13 +525,14 @@ void *put_nxmsg_xid(size_t openflow_len, uint32_t 
subtype, ovs_be32 xid,
 
 void update_openflow_length(struct ofpbuf *);
 
-void *ofputil_make_stats_request(size_t openflow_len, uint16_t type,
+/* Encoding OpenFlow stats messages. */
+void *ofputil_make_stats_request(size_t body_len, uint16_t type,
                                  uint32_t subtype, struct ofpbuf **);
-void *ofputil_make_stats_reply(size_t openflow_len,
-                               const struct ofp_stats_msg *request,
+void *ofputil_make_stats_reply(size_t body_len,
+                               const struct ofp_header *request,
                                struct ofpbuf **);
 
-void ofputil_start_stats_reply(const struct ofp_stats_msg *request,
+void ofputil_start_stats_reply(const struct ofp_header *request,
                                struct list *);
 struct ofpbuf *ofputil_reserve_stats_reply(size_t len, struct list *);
 void *ofputil_append_stats_reply(size_t len, struct list *);
@@ -541,13 +542,14 @@ void ofputil_append_port_desc_stats_reply(uint8_t 
ofp_version,
                                           const struct ofputil_phy_port *pp,
                                           struct list *replies);
 
-const void *ofputil_stats_body(const struct ofp_header *);
-size_t ofputil_stats_body_len(const struct ofp_header *);
+/* Decoding OpenFlow stats messages. */
+size_t ofputil_stats_msg_len(const struct ofp_header *);
+void ofputil_pull_stats_msg(struct ofpbuf *msg);
+void *ofputil_stats_msg_body(const struct ofp_header *);
+uint16_t ofputil_decode_stats_msg_type(const struct ofp_header *);
+uint16_t ofputil_decode_stats_msg_flags(const struct ofp_header *);
 
-const void *ofputil_nxstats_body(const struct ofp_header *);
-size_t ofputil_nxstats_body_len(const struct ofp_header *);
-
-/*  */
+/* Encoding simple OpenFlow messages. */
 struct ofpbuf *make_echo_request(void);
 struct ofpbuf *make_echo_reply(const struct ofp_header *rq);
 
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index fe96403..ad88471 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -2101,7 +2101,7 @@ handle_port_mod(struct ofconn *ofconn, const struct 
ofp_header *oh)
 
 static enum ofperr
 handle_desc_stats_request(struct ofconn *ofconn,
-                          const struct ofp_stats_msg *request)
+                          const struct ofp_header *request)
 {
     struct ofproto *p = ofconn_get_ofproto(ofconn);
     struct ofp_desc_stats *ods;
@@ -2120,14 +2120,14 @@ handle_desc_stats_request(struct ofconn *ofconn,
 
 static enum ofperr
 handle_table_stats_request(struct ofconn *ofconn,
-                           const struct ofp_stats_msg *request)
+                           const struct ofp_header *request)
 {
     struct ofproto *p = ofconn_get_ofproto(ofconn);
     struct ofp_table_stats *ots;
     struct ofpbuf *msg;
     size_t i;
 
-    ofputil_make_stats_reply(sizeof(struct ofp_stats_msg), request, &msg);
+    ofputil_make_stats_reply(0, request, &msg);
 
     ots = ofpbuf_put_zeros(msg, sizeof *ots * p->n_tables);
     for (i = 0; i < p->n_tables; i++) {
@@ -2186,13 +2186,14 @@ append_port_stat(struct ofport *port, struct list 
*replies)
 
 static enum ofperr
 handle_port_stats_request(struct ofconn *ofconn,
-                          const struct ofp_port_stats_request *psr)
+                          const struct ofp_header *request)
 {
     struct ofproto *p = ofconn_get_ofproto(ofconn);
+    struct ofp_port_stats_request *psr = ofputil_stats_msg_body(request);
     struct ofport *port;
     struct list replies;
 
-    ofputil_start_stats_reply(&psr->osm, &replies);
+    ofputil_start_stats_reply(request, &replies);
     if (psr->port_no != htons(OFPP_NONE)) {
         port = ofproto_get_port(p, ntohs(psr->port_no));
         if (port) {
@@ -2210,13 +2211,13 @@ handle_port_stats_request(struct ofconn *ofconn,
 
 static enum ofperr
 handle_port_desc_stats_request(struct ofconn *ofconn,
-                               const struct ofp_stats_msg *osm)
+                               const struct ofp_header *request)
 {
     struct ofproto *p = ofconn_get_ofproto(ofconn);
     struct ofport *port;
     struct list replies;
 
-    ofputil_start_stats_reply(osm, &replies);
+    ofputil_start_stats_reply(request, &replies);
 
     HMAP_FOR_EACH (port, hmap_node, &p->ports) {
         ofputil_append_port_desc_stats_reply(ofconn_get_protocol(ofconn),
@@ -2404,7 +2405,7 @@ age_secs(long long int age_ms)
 
 static enum ofperr
 handle_flow_stats_request(struct ofconn *ofconn,
-                          const struct ofp_stats_msg *osm)
+                          const struct ofp_header *request)
 {
     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
     struct ofputil_flow_stats_request fsr;
@@ -2413,7 +2414,7 @@ handle_flow_stats_request(struct ofconn *ofconn,
     struct rule *rule;
     enum ofperr error;
 
-    error = ofputil_decode_flow_stats_request(&fsr, &osm->header);
+    error = ofputil_decode_flow_stats_request(&fsr, request);
     if (error) {
         return error;
     }
@@ -2425,7 +2426,7 @@ handle_flow_stats_request(struct ofconn *ofconn,
         return error;
     }
 
-    ofputil_start_stats_reply(osm, &replies);
+    ofputil_start_stats_reply(request, &replies);
     LIST_FOR_EACH (rule, ofproto_node, &rules) {
         long long int now = time_msec();
         struct ofputil_flow_stats fs;
@@ -2549,7 +2550,7 @@ ofproto_port_get_cfm_health(const struct ofproto 
*ofproto, uint16_t ofp_port)
 
 static enum ofperr
 handle_aggregate_stats_request(struct ofconn *ofconn,
-                               const struct ofp_stats_msg *osm)
+                               const struct ofp_header *oh)
 {
     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
     struct ofputil_flow_stats_request request;
@@ -2560,7 +2561,7 @@ handle_aggregate_stats_request(struct ofconn *ofconn,
     struct rule *rule;
     enum ofperr error;
 
-    error = ofputil_decode_flow_stats_request(&request, &osm->header);
+    error = ofputil_decode_flow_stats_request(&request, oh);
     if (error) {
         return error;
     }
@@ -2602,7 +2603,7 @@ handle_aggregate_stats_request(struct ofconn *ofconn,
         stats.byte_count = UINT64_MAX;
     }
 
-    reply = ofputil_encode_aggregate_stats_reply(&stats, osm);
+    reply = ofputil_encode_aggregate_stats_reply(&stats, oh);
     ofconn_send_reply(ofconn, reply);
 
     return 0;
@@ -2657,9 +2658,10 @@ handle_queue_stats_for_port(struct ofport *port, 
uint32_t queue_id,
 
 static enum ofperr
 handle_queue_stats_request(struct ofconn *ofconn,
-                           const struct ofp_queue_stats_request *qsr)
+                           const struct ofp_header *rq)
 {
     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
+    const struct ofp_queue_stats_request *qsr = ofputil_stats_msg_body(rq);
     struct queue_stats_cbdata cbdata;
     struct ofport *port;
     unsigned int port_no;
@@ -2667,7 +2669,7 @@ handle_queue_stats_request(struct ofconn *ofconn,
 
     COVERAGE_INC(ofproto_queue_req);
 
-    ofputil_start_stats_reply(&qsr->osm, &cbdata.replies);
+    ofputil_start_stats_reply(rq, &cbdata.replies);
 
     port_no = ntohs(qsr->port_no);
     queue_id = ntohl(qsr->queue_id);
diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
index 630e457..e6d10a4 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -336,17 +336,6 @@ open_vconn(const char *name, struct vconn **vconnp)
     return open_vconn__(name, "mgmt", vconnp);
 }
 
-static void *
-alloc_stats_request(size_t rq_len, uint16_t type, struct ofpbuf **bufferp)
-{
-    struct ofp_stats_msg *rq;
-
-    rq = make_openflow(rq_len, OFPT10_STATS_REQUEST, bufferp);
-    rq->type = htons(type);
-    rq->flags = htons(0);
-    return rq;
-}
-
 static void
 send_openflow_buffer(struct vconn *vconn, struct ofpbuf *buffer)
 {
@@ -411,7 +400,8 @@ static void
 dump_trivial_stats_transaction(const char *vconn_name, uint8_t stats_type)
 {
     struct ofpbuf *request;
-    alloc_stats_request(sizeof(struct ofp_stats_msg), stats_type, &request);
+
+    ofputil_make_stats_request(0, stats_type, 0, &request);
     dump_stats_transaction(vconn_name, request);
 }
 
@@ -597,8 +587,7 @@ fetch_port_by_stats(const char *vconn_name,
     bool done = false;
     bool found = false;
 
-    alloc_stats_request(sizeof(struct ofp_stats_msg), OFPST_PORT_DESC,
-                        &request);
+    ofputil_make_stats_request(0, OFPST_PORT_DESC, 0, &request);
     send_xid = ((struct ofp_header *) request->data)->xid;
 
     open_vconn(vconn_name, &vconn);
@@ -611,7 +600,8 @@ fetch_port_by_stats(const char *vconn_name,
         recv_xid = ((struct ofp_header *) reply->data)->xid;
         if (send_xid == recv_xid) {
             const struct ofputil_msg_type *type;
-            struct ofp_stats_msg *osm;
+            struct ofp_header *oh;
+            uint16_t flags;
 
             ofputil_decode_msg_type(reply->data, &type);
             if (ofputil_msg_type_code(type) != OFPUTIL_OFPST_PORT_DESC_REPLY) {
@@ -620,8 +610,9 @@ fetch_port_by_stats(const char *vconn_name,
                                         verbosity + 1));
             }
 
-            osm = ofpbuf_at_assert(reply, 0, sizeof *osm);
-            done = !(ntohs(osm->flags) & OFPSF_REPLY_MORE);
+            oh = reply->data;
+            flags = ofputil_decode_stats_msg_flags(oh);
+            done = !(flags & OFPSF_REPLY_MORE);
 
             if (found) {
                 /* We've already found the port, but we need to drain
@@ -629,10 +620,10 @@ fetch_port_by_stats(const char *vconn_name,
                 continue;
             }
 
-            ofpbuf_use_const(&b, &osm->header, ntohs(osm->header.length));
-            ofpbuf_pull(&b, sizeof(struct ofp_stats_msg));
+            ofpbuf_use_const(&b, oh, ntohs(oh->length));
+            ofputil_pull_stats_msg(&b);
 
-            while (!ofputil_pull_phy_port(osm->header.version, &b, pp)) {
+            while (!ofputil_pull_phy_port(oh->version, &b, pp)) {
                 if (port_no != UINT_MAX ? port_no == pp->port_no
                                         : !strcmp(pp->name, port_name)) {
                     found = true;
@@ -789,7 +780,7 @@ do_queue_stats(int argc, char *argv[])
     struct ofp_queue_stats_request *req;
     struct ofpbuf *request;
 
-    req = alloc_stats_request(sizeof *req, OFPST_QUEUE, &request);
+    req = ofputil_make_stats_request(sizeof *req, OFPST_QUEUE, 0, &request);
 
     if (argc > 2 && argv[2][0] && strcasecmp(argv[2], "all")) {
         req->port_no = htons(str_to_port_no(argv[1], argv[2]));
@@ -1200,7 +1191,7 @@ do_dump_ports(int argc, char *argv[])
     struct ofpbuf *request;
     uint16_t port;
 
-    req = alloc_stats_request(sizeof *req, OFPST_PORT, &request);
+    req = ofputil_make_stats_request(sizeof *req, OFPST_PORT, 0, &request);
     port = argc > 2 ? str_to_port_no(argv[1], argv[2]) : OFPP_NONE;
     req->port_no = htons(port);
     dump_stats_transaction(argv[1], request);
@@ -1664,8 +1655,8 @@ read_flows_from_switch(struct vconn *vconn,
         recv_xid = ((struct ofp_header *) reply->data)->xid;
         if (send_xid == recv_xid) {
             const struct ofputil_msg_type *type;
-            const struct ofp_stats_msg *osm;
             enum ofputil_msg_code code;
+            uint16_t flags;
 
             ofputil_decode_msg_type(reply->data, &type);
             code = ofputil_msg_type_code(type);
@@ -1676,8 +1667,8 @@ read_flows_from_switch(struct vconn *vconn,
                                         verbosity + 1));
             }
 
-            osm = reply->data;
-            if (!(osm->flags & htons(OFPSF_REPLY_MORE))) {
+            flags = ofputil_decode_stats_msg_flags(reply->data);
+            if (!(flags & OFPSF_REPLY_MORE)) {
                 done = true;
             }
 
-- 
1.7.2.5

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

Reply via email to