[ovs-dev] [PATCH v15] ofp-msgs: Open Flow 1.1 and 1.2 Queue Status Messages

Simon Horman horms at verge.net.au
Fri Oct 12 04:03:04 UTC 2012


This allows for encoding and decoding Open Flow 1.1 and 1.2 Queue Stats
Request and Reply messages.

Signed-off-by: Simon Horman <horms at verge.net.au>

---

[ N.B: Versions prior to 15 were part of a series,
       this patch was introduced in version 5 of that series ]

v15
* Merge with "ovs-ofpctl: Enable queue-stats for Open Flow 1.1 & 1.2"
* Rework to use host-byte order structures
  - This new implementation is based on the implementation
    of Port Stats which has been merged

v14
* No change

v13
* Merged the following patches
  - ofp-msgs: Split OFPRAW_OFPST_QUEUE_{REQUEST,REPLY}
  - ofp-print: Enable display of Open Flow 1.1 & 1.2 Queue Status Reply Messages
  - ofp-util: Allow encoding of Open Flow 1.1 & 1.2 Queue Stats Reply Messages
  - ofp-util: Allow decoding of Open Flow 1.1 & 1.2 Queue Stats Request Messages
  - ovs-print: Enable display of Open Flow 1.1 & 1.2 Queue Stats Request
* Move ofp_print_ofpst_queue_reply() decode code into a helper function
* Move put_queue_stats() encode code into helper functions
* Move ofp_print_ofpst_queue_request parse code to helper functions
* Merged revision history of above patches follows

v12
* No change

v11
* No change

v10
* Manual rebase
* Make use of enum ofp_version
* Change subject name from "ovs-print: Enable display of Open Flow 1.1 &
  1.2 Queue Stats Response" to "ovs-print: Enable display of Open Flow 1.1
  & 1.2 Queue Stats Request"
* Add ofp-print test
* Use ofputil_port_from_ofp11 to decode port number

v9
* Omitted

v8
* Omitted

v7
* Omitted

v6
* The queue_id variable in do_dump_aggregate() should be uint32_t not
  uint16_t.

v5
* Initial Post

---
 lib/ofp-msgs.h        |   14 +++-
 lib/ofp-print.c       |   49 ++++++------
 lib/ofp-util.c        |  206 +++++++++++++++++++++++++++++++++++++++++++++++++
 lib/ofp-util.h        |   24 ++++++
 ofproto/ofproto.c     |   33 ++++----
 tests/ofp-print.at    |   78 ++++++++++++++++++-
 utilities/ovs-ofctl.c |   16 ++--
 7 files changed, 363 insertions(+), 57 deletions(-)

diff --git a/lib/ofp-msgs.h b/lib/ofp-msgs.h
index 6420c5d..ceb3fc3 100644
--- a/lib/ofp-msgs.h
+++ b/lib/ofp-msgs.h
@@ -226,10 +226,14 @@ enum ofpraw {
     OFPRAW_OFPST11_PORT_REPLY,
 
     /* OFPST 1.0 (5): struct ofp10_queue_stats_request. */
-    OFPRAW_OFPST_QUEUE_REQUEST,
+    OFPRAW_OFPST10_QUEUE_REQUEST,
+    /* OFPST 1.1+ (5): struct ofp11_queue_stats_request. */
+    OFPRAW_OFPST11_QUEUE_REQUEST,
 
     /* OFPST 1.0 (5): struct ofp10_queue_stats[]. */
-    OFPRAW_OFPST_QUEUE_REPLY,
+    OFPRAW_OFPST10_QUEUE_REPLY,
+    /* OFPST 1.1+ (5): struct ofp11_queue_stats[]. */
+    OFPRAW_OFPST11_QUEUE_REPLY,
 
     /* OFPST 1.0 (13): void. */
     OFPRAW_OFPST_PORT_DESC_REQUEST,
@@ -390,8 +394,10 @@ enum ofptype {
                                       * OFPRAW_OFPST11_PORT_REQUEST. */
     OFPTYPE_PORT_STATS_REPLY,        /* OFPRAW_OFPST10_PORT_REPLY.
                                       * OFPRAW_OFPST11_PORT_REPLY. */
-    OFPTYPE_QUEUE_STATS_REQUEST,     /* OFPRAW_OFPST_QUEUE_REQUEST. */
-    OFPTYPE_QUEUE_STATS_REPLY,       /* OFPRAW_OFPST_QUEUE_REPLY. */
+    OFPTYPE_QUEUE_STATS_REQUEST,     /* OFPRAW_OFPST10_QUEUE_REQUEST.
+                                      * OFPRAW_OFPST11_QUEUE_REQUEST. */
+    OFPTYPE_QUEUE_STATS_REPLY,       /* OFPRAW_OFPST10_QUEUE_REPLY.
+                                      * OFPRAW_OFPST11_QUEUE_REPLY. */
     OFPTYPE_PORT_DESC_STATS_REQUEST, /* OFPRAW_OFPST_PORT_DESC_REQUEST. */
     OFPTYPE_PORT_DESC_STATS_REPLY,   /* OFPRAW_OFPST_PORT_DESC_REPLY. */
 
diff --git a/lib/ofp-print.c b/lib/ofp-print.c
index 8eb5de4..0970a92 100644
--- a/lib/ofp-print.c
+++ b/lib/ofp-print.c
@@ -1326,54 +1326,55 @@ ofp_print_queue_name(struct ds *string, uint32_t queue_id)
 static void
 ofp_print_ofpst_queue_request(struct ds *string, const struct ofp_header *oh)
 {
-    const struct ofp10_queue_stats_request *qsr = ofpmsg_body(oh);
+    struct ofputil_queue_stats_request oqsr;
+    enum ofperr error;
+
+    error = ofputil_decode_queue_stats_request(oh, &oqsr);
+    if (error) {
+        ds_put_format(string, "***decode error: %s***\n", ofperr_get_name(error));
+        return;
+    }
 
     ds_put_cstr(string, "port=");
-    ofputil_format_port(ntohs(qsr->port_no), string);
+    ofputil_format_port(oqsr.port_no, string);
 
     ds_put_cstr(string, " queue=");
-    ofp_print_queue_name(string, ntohl(qsr->queue_id));
-}
-
-static void
-print_queue_stat(struct ds *string, const char *leader,
-                 const ovs_32aligned_be64 *statp, int more)
-{
-    print_port_stat(string, leader, ntohll(get_32aligned_be64(statp)), more);
+    ofp_print_queue_name(string, oqsr.queue_id);
 }
 
 static void
 ofp_print_ofpst_queue_reply(struct ds *string, const struct ofp_header *oh,
                             int verbosity)
 {
-    struct ofp10_queue_stats *qs;
     struct ofpbuf b;
-    size_t n;
 
-    ofpbuf_use_const(&b, oh, ntohs(oh->length));
-    ofpraw_pull_assert(&b);
-
-    n = b.size / sizeof *qs;
-    ds_put_format(string, " %zu queues\n", n);
+    ds_put_format(string, " %zu queues\n", ofputil_count_queue_stats(oh));
     if (verbosity < 1) {
         return;
     }
 
+    ofpbuf_use_const(&b, oh, ntohs(oh->length));
     for (;;) {
-        qs = ofpbuf_try_pull(&b, sizeof *qs);
-        if (!qs) {
+        struct ofputil_queue_stats qs;
+        int retval;
+
+        retval = ofputil_decode_queue_stats(&qs, &b);
+        if (retval) {
+            if (retval != EOF) {
+                ds_put_cstr(string, " ***parse error***");
+            }
             return;
         }
 
         ds_put_cstr(string, "  port ");
-        ofputil_format_port(ntohs(qs->port_no), string);
+        ofputil_format_port(qs.port_no, string);
         ds_put_cstr(string, " queue ");
-        ofp_print_queue_name(string, ntohl(qs->queue_id));
+        ofp_print_queue_name(string, qs.queue_id);
         ds_put_cstr(string, ": ");
 
-        print_queue_stat(string, "bytes=", &qs->tx_bytes, 1);
-        print_queue_stat(string, "pkts=", &qs->tx_packets, 1);
-        print_queue_stat(string, "errors=", &qs->tx_errors, 0);
+        print_port_stat(string, "bytes=", qs.stats.tx_bytes, 1);
+        print_port_stat(string, "pkts=", qs.stats.tx_packets, 1);
+        print_port_stat(string, "errors=", qs.stats.tx_errors, 0);
     }
 }
 
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index c6d979e..07773df 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -4180,3 +4180,209 @@ ofputil_decode_port_stats_request(const struct ofp_header *request,
         NOT_REACHED();
     }
 }
+
+/* Parse a queue status request message into 'oqsr'.
+ * Returns 0 if successful, otherwise an OFPERR_* number. */
+enum ofperr
+ofputil_decode_queue_stats_request(const struct ofp_header *request,
+                                   struct ofputil_queue_stats_request *oqsr)
+{
+    switch ((enum ofp_version)request->version) {
+    case OFP12_VERSION:
+    case OFP11_VERSION: {
+        const struct ofp11_queue_stats_request *qsr11 = ofpmsg_body(request);
+        oqsr->queue_id = ntohl(qsr11->queue_id);
+        return ofputil_port_from_ofp11(qsr11->port_no, &oqsr->port_no);
+    }
+
+    case OFP10_VERSION: {
+        const struct ofp11_queue_stats_request *qsr11 = ofpmsg_body(request);
+        oqsr->queue_id = ntohl(qsr11->queue_id);
+        oqsr->port_no = ntohs(qsr11->port_no);
+        return 0;
+    }
+
+    default:
+        NOT_REACHED();
+    }
+}
+
+/* Encode a queue statsrequest for 'oqsr', the encoded message
+ * will be fore Open Flow version 'ofp_version'. Returns message
+ * as a struct ofpbuf. Returns encoded message on success, NULL on error */
+struct ofpbuf *
+ofputil_encode_queue_stats_request(enum ofp_version ofp_version,
+                                   const struct ofputil_queue_stats_request *oqsr)
+{
+    struct ofpbuf *request;
+
+    switch (ofp_version) {
+    case OFP11_VERSION:
+    case OFP12_VERSION: {
+        struct ofp11_queue_stats_request *req;
+        request = ofpraw_alloc(OFPRAW_OFPST11_QUEUE_REQUEST, ofp_version, 0);
+        req = ofpbuf_put_zeros(request, sizeof *req);
+        req->port_no = ofputil_port_to_ofp11(oqsr->port_no);
+        req->queue_id = htonl(oqsr->queue_id);
+        break;
+    }
+    case OFP10_VERSION: {
+        struct ofp10_queue_stats_request *req;
+        request = ofpraw_alloc(OFPRAW_OFPST10_QUEUE_REQUEST, ofp_version, 0);
+        req = ofpbuf_put_zeros(request, sizeof *req);
+        req->port_no = htons(oqsr->port_no);
+        req->queue_id = htonl(oqsr->queue_id);
+        break;
+    }
+    default:
+        NOT_REACHED();
+    }
+
+    return request;
+}
+
+/* Returns the number of queue stats elements in OFPTYPE_QUEUE_STATS_REPLY
+ * message 'oh'. */
+size_t
+ofputil_count_queue_stats(const struct ofp_header *oh)
+{
+    struct ofpbuf b;
+
+    ofpbuf_use_const(&b, oh, ntohs(oh->length));
+    ofpraw_pull_assert(&b);
+
+    BUILD_ASSERT(sizeof(struct ofp10_queue_stats) ==
+                 sizeof(struct ofp11_queue_stats));
+    return b.size / sizeof(struct ofp10_queue_stats);
+}
+static enum ofperr
+ofputil_queue_stats_from_ofp10(struct ofputil_queue_stats *oqs,
+                               const struct ofp10_queue_stats *qs10)
+{
+    oqs->port_no = ntohs(qs10->port_no);
+    oqs->queue_id = ntohl(qs10->queue_id);
+    oqs->stats.tx_bytes = ntohll(get_32aligned_be64(&qs10->tx_bytes));
+    oqs->stats.tx_packets = ntohll(get_32aligned_be64(&qs10->tx_packets));
+    oqs->stats.tx_errors = ntohll(get_32aligned_be64(&qs10->tx_errors));
+
+    return 0;
+}
+
+static enum ofperr
+ofputil_queue_stats_from_ofp11(struct ofputil_queue_stats *oqs,
+                               const struct ofp11_queue_stats *qs11)
+{
+    enum ofperr error;
+
+    error = ofputil_port_from_ofp11(qs11->port_no, &oqs->port_no);
+    if (error) {
+        return error;
+    }
+
+    oqs->queue_id = ntohl(qs11->queue_id);
+    oqs->stats.tx_bytes = ntohll(qs11->tx_bytes);
+    oqs->stats.tx_packets = ntohll(qs11->tx_packets);
+    oqs->stats.tx_errors = ntohll(qs11->tx_errors);
+
+    return 0;
+}
+
+/* Converts an OFPST_QUEUE_STATS reply in 'msg' into an abstract
+ * ofputil_queue_stats in 'qs'.
+ *
+ * Multiple OFPST_QUEUE_STATS replies can be packed into a single OpenFlow
+ * message.  Calling this function multiple times for a single 'msg' iterates
+ * through the replies.  The caller must initially leave 'msg''s layer pointers
+ * null and not modify them between calls.
+ *
+ * Returns 0 if successful, EOF if no replies were left in this 'msg',
+ * otherwise a positive errno value. */
+int
+ofputil_decode_queue_stats(struct ofputil_queue_stats *qs, struct ofpbuf *msg)
+{
+    enum ofperr error;
+    enum ofpraw raw;
+
+    error = (msg->l2
+             ? ofpraw_decode(&raw, msg->l2)
+             : ofpraw_pull(&raw, msg));
+    if (error) {
+        return error;
+    }
+
+    if (!msg->size) {
+        return EOF;
+    } else if (raw == OFPRAW_OFPST11_QUEUE_REPLY) {
+        const struct ofp11_queue_stats *qs11;
+
+        qs11 = ofpbuf_try_pull(msg, sizeof *qs11);
+        if (!qs11) {
+            VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_QUEUE reply has %zu leftover "
+                         "bytes at end", msg->size);
+            return OFPERR_OFPBRC_BAD_LEN;
+        }
+        return ofputil_queue_stats_from_ofp11(qs, qs11);
+    } else if (raw == OFPRAW_OFPST10_QUEUE_REPLY) {
+        const struct ofp10_queue_stats *qs10;
+
+        qs10 = ofpbuf_try_pull(msg, sizeof *qs10);
+        if (!qs10) {
+            VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_QUEUE reply has %zu leftover "
+                         "bytes at end", msg->size);
+            return OFPERR_OFPBRC_BAD_LEN;
+        }
+        return ofputil_queue_stats_from_ofp10(qs, qs10);
+    } else {
+        NOT_REACHED();
+    }
+}
+
+static void
+ofputil_queue_stats_to_ofp10(const struct ofputil_queue_stats *oqs,
+                             struct ofp10_queue_stats *qs10)
+{
+    qs10->port_no = htons(oqs->port_no);
+    memset(qs10->pad, 0, sizeof qs10->pad);
+    qs10->queue_id = htonl(oqs->queue_id);
+    put_32aligned_be64(&qs10->tx_bytes, htonll(oqs->stats.tx_bytes));
+    put_32aligned_be64(&qs10->tx_packets, htonll(oqs->stats.tx_packets));
+    put_32aligned_be64(&qs10->tx_errors, htonll(oqs->stats.tx_errors));
+}
+
+static void
+ofputil_queue_stats_to_ofp11(const struct ofputil_queue_stats *oqs,
+                             struct ofp11_queue_stats *qs11)
+{
+    qs11->port_no = ofputil_port_to_ofp11(oqs->port_no);
+    qs11->queue_id = htonl(oqs->queue_id);
+    qs11->tx_bytes = htonll(oqs->stats.tx_bytes);
+    qs11->tx_packets = htonll(oqs->stats.tx_packets);
+    qs11->tx_errors = htonll(oqs->stats.tx_errors);
+}
+
+/* Encode a queue stat for 'oqs' and append it to 'replies'. */
+void
+ofputil_append_queue_stat(struct list *replies,
+                          const struct ofputil_queue_stats *oqs)
+{
+    struct ofpbuf *msg = ofpbuf_from_list(list_back(replies));
+    struct ofp_header *oh = msg->data;
+
+    switch ((enum ofp_version)oh->version) {
+    case OFP12_VERSION:
+    case OFP11_VERSION: {
+        struct ofp11_queue_stats *reply = ofpmp_append(replies, sizeof *reply);;
+        ofputil_queue_stats_to_ofp11(oqs, reply);
+        break;
+    }
+
+    case OFP10_VERSION: {
+        struct ofp10_queue_stats *reply = ofpmp_append(replies, sizeof *reply);;
+        ofputil_queue_stats_to_ofp10(oqs, reply);
+        break;
+    }
+
+    default:
+        NOT_REACHED();
+    }
+}
diff --git a/lib/ofp-util.h b/lib/ofp-util.h
index edfe076..2f73ec2 100644
--- a/lib/ofp-util.h
+++ b/lib/ofp-util.h
@@ -635,4 +635,28 @@ size_t ofputil_count_port_stats(const struct ofp_header *);
 int ofputil_decode_port_stats(struct ofputil_port_stats *, struct ofpbuf *msg);
 enum ofperr ofputil_decode_port_stats_request(const struct ofp_header *request,
                                               uint16_t *ofp10_port);
+
+struct ofputil_queue_stats_request {
+    uint16_t port_no;
+    uint32_t queue_id;
+};
+
+enum ofperr
+ofputil_decode_queue_stats_request(const struct ofp_header *request,
+                                   struct ofputil_queue_stats_request *oqsr);
+struct ofpbuf *
+ofputil_encode_queue_stats_request(enum ofp_version ofp_version,
+                                   const struct ofputil_queue_stats_request *oqsr);
+
+struct ofputil_queue_stats {
+    uint16_t port_no;
+    uint32_t queue_id;
+    struct netdev_queue_stats stats;
+};
+
+size_t ofputil_count_queue_stats(const struct ofp_header *);
+int ofputil_decode_queue_stats(struct ofputil_queue_stats *qs, struct ofpbuf *msg);
+void ofputil_append_queue_stat(struct list *replies,
+                               const struct ofputil_queue_stats *oqs);
+
 #endif /* ofp-util.h */
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 97e00ab..a128a6d 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -2775,15 +2775,13 @@ static void
 put_queue_stats(struct queue_stats_cbdata *cbdata, uint32_t queue_id,
                 const struct netdev_queue_stats *stats)
 {
-    struct ofp10_queue_stats *reply;
 
-    reply = ofpmp_append(&cbdata->replies, sizeof *reply);
-    reply->port_no = htons(cbdata->ofport->pp.port_no);
-    memset(reply->pad, 0, sizeof reply->pad);
-    reply->queue_id = htonl(queue_id);
-    put_32aligned_be64(&reply->tx_bytes, htonll(stats->tx_bytes));
-    put_32aligned_be64(&reply->tx_packets, htonll(stats->tx_packets));
-    put_32aligned_be64(&reply->tx_errors, htonll(stats->tx_errors));
+    struct ofputil_queue_stats oqs = {
+        .port_no = cbdata->ofport->pp.port_no,
+        .queue_id = queue_id,
+        .stats = *stats,
+    };
+    ofputil_append_queue_stat(&cbdata->replies, &oqs);
 }
 
 static void
@@ -2821,30 +2819,31 @@ handle_queue_stats_request(struct ofconn *ofconn,
                            const struct ofp_header *rq)
 {
     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
-    const struct ofp10_queue_stats_request *qsr = ofpmsg_body(rq);
     struct queue_stats_cbdata cbdata;
-    unsigned int port_no;
     struct ofport *port;
-    uint32_t queue_id;
     enum ofperr error;
+    struct ofputil_queue_stats_request oqsr;
 
     COVERAGE_INC(ofproto_queue_req);
 
     ofpmp_init(&cbdata.replies, rq);
 
-    port_no = ntohs(qsr->port_no);
-    queue_id = ntohl(qsr->queue_id);
-    if (port_no == OFPP_ALL) {
+    error = ofputil_decode_queue_stats_request(rq, &oqsr);
+    if (error) {
+        return error;
+    }
+
+    if (oqsr.port_no == OFPP_ALL) {
         error = OFPERR_OFPQOFC_BAD_QUEUE;
         HMAP_FOR_EACH (port, hmap_node, &ofproto->ports) {
-            if (!handle_queue_stats_for_port(port, queue_id, &cbdata)) {
+            if (!handle_queue_stats_for_port(port, oqsr.queue_id, &cbdata)) {
                 error = 0;
             }
         }
     } else {
-        port = ofproto_get_port(ofproto, port_no);
+        port = ofproto_get_port(ofproto, oqsr.port_no);
         error = (port
-                 ? handle_queue_stats_for_port(port, queue_id, &cbdata)
+                 ? handle_queue_stats_for_port(port, oqsr.queue_id, &cbdata)
                  : OFPERR_OFPQOFC_BAD_PORT);
     }
     if (!error) {
diff --git a/tests/ofp-print.at b/tests/ofp-print.at
index ad36617..f1fdefb 100644
--- a/tests/ofp-print.at
+++ b/tests/ofp-print.at
@@ -1057,7 +1057,7 @@ OFPST_PORT reply (OF1.2) (xid=0x2): 3 ports
 ])
 AT_CLEANUP
 
-AT_SETUP([OFPST_QUEUE request])
+AT_SETUP([OFPST_QUEUE request - OF1.0])
 AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST])
 AT_CHECK([ovs-ofctl ofp-print "\
 01 10 00 14 00 00 00 01 00 05 00 00 ff fc 00 00 \
@@ -1067,7 +1067,27 @@ OFPST_QUEUE request (xid=0x1):port=ALL queue=ALL
 ])
 AT_CLEANUP
 
-AT_SETUP([OFPST_QUEUE reply])
+AT_SETUP([OFPST_QUEUE request - OF1.1])
+AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST])
+AT_CHECK([ovs-ofctl ofp-print "\
+02 12 00 18 00 00 00 02 00 05 00 00 00 00 00 00 \
+ff ff ff fc ff ff ff ff \
+"], [0], [dnl
+OFPST_QUEUE request (OF1.1) (xid=0x2):port=ALL queue=ALL
+])
+AT_CLEANUP
+
+AT_SETUP([OFPST_QUEUE request - OF1.2])
+AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST])
+AT_CHECK([ovs-ofctl ofp-print "\
+03 12 00 18 00 00 00 02 00 05 00 00 00 00 00 00 \
+ff ff ff fc ff ff ff ff \
+"], [0], [dnl
+OFPST_QUEUE request (OF1.2) (xid=0x2):port=ALL queue=ALL
+])
+AT_CLEANUP
+
+AT_SETUP([OFPST_QUEUE reply - OF1.0])
 AT_KEYWORDS([ofp-print OFPT_STATS_REPLY])
 AT_CHECK([ovs-ofctl ofp-print "\
 01 11 00 cc 00 00 00 01 00 05 00 00 00 03 00 00 \
@@ -1101,6 +1121,60 @@ OFPST_PORT_DESC request (xid=0x1):
 ])
 AT_CLEANUP
 
+AT_SETUP([OFPST_QUEUE reply - OF1.1])
+AT_KEYWORDS([ofp-print OFPT_STATS_REPLY])
+AT_CHECK([ovs-ofctl ofp-print "\
+02 13 00 d0 00 00 00 01 00 05 00 00 00 00 00 00 \
+00 00 00 03 00 00 00 01 00 00 00 00 00 00 01 2e \
+00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 \
+00 00 00 03 00 00 00 02 00 00 00 00 00 00 00 00 \
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
+00 00 00 02 00 00 00 01 00 00 00 00 00 00 08 34 \
+00 00 00 00 00 00 00 14 00 00 00 00 00 00 00 00 \
+00 00 00 02 00 00 00 02 00 00 00 00 00 00 00 00 \
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
+00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 \
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
+00 00 00 01 00 00 00 02 00 00 00 00 00 00 00 00 \
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
+"], [0], [dnl
+OFPST_QUEUE reply (OF1.1) (xid=0x1): 6 queues
+  port 3 queue 1: bytes=302, pkts=1, errors=0
+  port 3 queue 2: bytes=0, pkts=0, errors=0
+  port 2 queue 1: bytes=2100, pkts=20, errors=0
+  port 2 queue 2: bytes=0, pkts=0, errors=0
+  port 1 queue 1: bytes=0, pkts=0, errors=0
+  port 1 queue 2: bytes=0, pkts=0, errors=0
+])
+AT_CLEANUP
+
+AT_SETUP([OFPST_QUEUE reply - OF1.2])
+AT_KEYWORDS([ofp-print OFPT_STATS_REPLY])
+AT_CHECK([ovs-ofctl ofp-print "\
+03 13 00 d0 00 00 00 01 00 05 00 00 00 00 00 00 \
+00 00 00 03 00 00 00 01 00 00 00 00 00 00 01 2e \
+00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 \
+00 00 00 03 00 00 00 02 00 00 00 00 00 00 00 00 \
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
+00 00 00 02 00 00 00 01 00 00 00 00 00 00 08 34 \
+00 00 00 00 00 00 00 14 00 00 00 00 00 00 00 00 \
+00 00 00 02 00 00 00 02 00 00 00 00 00 00 00 00 \
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
+00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 \
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
+00 00 00 01 00 00 00 02 00 00 00 00 00 00 00 00 \
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
+"], [0], [dnl
+OFPST_QUEUE reply (OF1.2) (xid=0x1): 6 queues
+  port 3 queue 1: bytes=302, pkts=1, errors=0
+  port 3 queue 2: bytes=0, pkts=0, errors=0
+  port 2 queue 1: bytes=2100, pkts=20, errors=0
+  port 2 queue 2: bytes=0, pkts=0, errors=0
+  port 1 queue 1: bytes=0, pkts=0, errors=0
+  port 1 queue 2: bytes=0, pkts=0, errors=0
+])
+AT_CLEANUP
+
 AT_SETUP([OFPST_PORT_DESC reply - OF1.0])
 AT_KEYWORDS([ofp-print OFPT_STATS_REPLY])
 AT_CHECK([ovs-ofctl ofp-print "\
diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
index 5a1f106..a0b7079 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -948,28 +948,24 @@ ofctl_dump_aggregate(int argc, char *argv[])
 static void
 ofctl_queue_stats(int argc, char *argv[])
 {
-    struct ofp10_queue_stats_request *req;
     struct ofpbuf *request;
     struct vconn *vconn;
+    struct ofputil_queue_stats_request oqs;
 
     open_vconn(argv[1], &vconn);
-    request = ofpraw_alloc(OFPRAW_OFPST_QUEUE_REQUEST,
-                           vconn_get_version(vconn), 0);
-    req = ofpbuf_put_zeros(request, sizeof *req);
 
     if (argc > 2 && argv[2][0] && strcasecmp(argv[2], "all")) {
-        req->port_no = htons(str_to_port_no(argv[1], argv[2]));
+        oqs.port_no = str_to_port_no(argv[1], argv[2]);
     } else {
-        req->port_no = htons(OFPP_ALL);
+        oqs.port_no = OFPP_ALL;
     }
     if (argc > 3 && argv[3][0] && strcasecmp(argv[3], "all")) {
-        req->queue_id = htonl(atoi(argv[3]));
+        oqs.queue_id = atoi(argv[3]);
     } else {
-        req->queue_id = htonl(OFPQ_ALL);
+        oqs.queue_id = OFPQ_ALL;
     }
 
-    memset(req->pad, 0, sizeof req->pad);
-
+    request = ofputil_encode_queue_stats_request(vconn_get_version(vconn), &oqs);
     dump_stats_transaction(vconn, request);
     vconn_close(vconn);
 }
-- 
1.7.10.4



More information about the dev mailing list