[ovs-dev] [PATCH 04/12] ofp-msgs: Open Flow 1.1 and 1.2 Queue Status Messages
Simon Horman
horms at verge.net.au
Mon Sep 17 00:26:51 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>
---
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
* No change
v5
* Initial Post
---
lib/ofp-msgs.h | 14 +++--
lib/ofp-print.c | 41 +++++++++-----
lib/ofp-util.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++++
lib/ofp-util.h | 11 ++++
ofproto/ofproto.c | 36 +++++++++----
tests/ofp-print.at | 78 ++++++++++++++++++++++++++-
utilities/ovs-ofctl.c | 2 +-
7 files changed, 294 insertions(+), 32 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 25aa9b9..8166ab1 100644
--- a/lib/ofp-print.c
+++ b/lib/ofp-print.c
@@ -1077,12 +1077,6 @@ static void ofp_print_port_stat(struct ds *string, const char *leader,
}
}
-static void print_port_stat(struct ds *string, const char *leader,
- const ovs_32aligned_be64 *statp, int more)
-{
- ofp_print_port_stat(string, leader, get_32aligned_be64(statp), more);
-}
-
static void
ofp_print_ofpst_port_request(struct ds *string, const struct ofp_header *oh)
{
@@ -1325,10 +1319,18 @@ 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);
+ uint16_t port_no;
+ const struct ofp11_queue_stats_request *qsr;
+ struct ofp11_queue_stats_request qsr_storage;
+
+ qsr = ofptutil_decode_queue_stat_request(oh, &qsr_storage);
+ if (ofputil_port_from_ofp11(qsr->port_no, &port_no)) {
+ ds_put_cstr(string, "*** parse error: invalid port ***\n");
+ return;
+ }
ds_put_cstr(string, "port=");
- ofputil_format_port(ntohs(qsr->port_no), string);
+ ofputil_format_port(port_no, string);
ds_put_cstr(string, " queue=");
ofp_print_queue_name(string, ntohl(qsr->queue_id));
@@ -1338,13 +1340,16 @@ static void
ofp_print_ofpst_queue_reply(struct ds *string, const struct ofp_header *oh,
int verbosity)
{
- struct ofp10_queue_stats *qs;
+ const struct ofp11_queue_stats *qs;
struct ofpbuf b;
size_t n;
ofpbuf_use_const(&b, oh, ntohs(oh->length));
ofpraw_pull_assert(&b);
+ /* This calculation is correct because
+ * struct ofp10_queue_stats and struct ofp11_queue_stats
+ * are the same size. */
n = b.size / sizeof *qs;
ds_put_format(string, " %zu queues\n", n);
if (verbosity < 1) {
@@ -1352,20 +1357,28 @@ ofp_print_ofpst_queue_reply(struct ds *string, const struct ofp_header *oh,
}
for (;;) {
- qs = ofpbuf_try_pull(&b, sizeof *qs);
+ struct ofp11_queue_stats qs_storage;
+ uint16_t port_no;
+ enum ofperr error;
+
+ qs = ofptutil_decode_queue_stat(oh->version, &b, &qs_storage);
if (!qs) {
return;
}
+ error = ofputil_port_from_ofp11(qs->port_no, &port_no);
+ if (error) {
+ return;
+ }
ds_put_cstr(string, " port ");
- ofputil_format_port(ntohs(qs->port_no), string);
+ ofputil_format_port(port_no, string);
ds_put_cstr(string, " queue ");
ofp_print_queue_name(string, ntohl(qs->queue_id));
ds_put_cstr(string, ": ");
- print_port_stat(string, "bytes=", &qs->tx_bytes, 1);
- print_port_stat(string, "pkts=", &qs->tx_packets, 1);
- print_port_stat(string, "errors=", &qs->tx_errors, 0);
+ ofp_print_port_stat(string, "bytes=", qs->tx_bytes, 1);
+ ofp_print_port_stat(string, "pkts=", qs->tx_packets, 1);
+ ofp_print_port_stat(string, "errors=", qs->tx_errors, 0);
}
}
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index 5a19c09..54ae709 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -4111,3 +4111,147 @@ ofptutil_decode_port_stats_request(const struct ofp_header *request)
NOT_REACHED();
}
}
+
+/* Convert a struct ofp10_queue_stats to a struct ofp11_queue_stats.
+ * The latter may be used as a neutral format as is able to
+ * encode both ofp*_queue_stats variants. */
+static void
+oqs10_to_oqs11(const struct ofp10_queue_stats *in,
+ struct ofp11_queue_stats *out)
+{
+ out->port_no = ofputil_port_to_ofp11(ntohs(in->port_no));
+ out->queue_id = in->queue_id;
+ out->tx_bytes = get_32aligned_be64(&in->tx_bytes);
+ out->tx_packets = get_32aligned_be64(&in->tx_packets);
+ out->tx_errors = get_32aligned_be64(&in->tx_errors);
+}
+
+/* Convert a struct ofp11_queue_stats to a struct ofp10_queue_stats.
+ * The former may be used as a neutral format as is able to
+ * encode both ofp*_queue_stats variants.
+ * Returns 0 success, an enum ofperr on error */
+static enum ofperr
+oqs11_to_oqs10(const struct ofp11_queue_stats *in,
+ struct ofp10_queue_stats *out)
+{
+ enum ofperr error;
+ uint16_t ofp10_port;
+
+ error = ofputil_port_from_ofp11(in->port_no, &ofp10_port);
+ if (error) {
+ return error;
+ }
+ out->port_no = htons(ofp10_port);
+ memset(out->pad, 0, sizeof out->pad);
+ out->queue_id = in->queue_id;
+ put_32aligned_be64(&out->tx_bytes, in->tx_bytes);
+ put_32aligned_be64(&out->tx_packets, in->tx_packets);
+ put_32aligned_be64(&out->tx_errors, in->tx_errors);
+ return 0;
+}
+
+/* Parse a struct one element of a port status reply message into a struct
+ * ofp11_queue_stats. struct ofp11_queue_stats is used as a neutral format
+ * as is able to encode both ofp*_queue_stats variants. qs_storage shuold
+ * point to memory for a struct ofp11_queue_stats. Returns pointer to
+ * struct ofp11_queue_stats on success, NULL otherwise. */
+const struct ofp11_queue_stats *
+ofptutil_decode_queue_stat(enum ofp_version ofp_version,
+ struct ofpbuf *openflow,
+ struct ofp11_queue_stats *qs_storage)
+{
+ switch (ofp_version) {
+ case OFP12_VERSION:
+ case OFP11_VERSION:
+ return ofpbuf_try_pull(openflow, sizeof *qs_storage);
+
+ case OFP10_VERSION: {
+ struct ofp10_queue_stats *qs10;
+
+ qs10 = ofpbuf_try_pull(openflow, sizeof *qs10);
+ if (!qs10) {
+ return NULL;
+ }
+ oqs10_to_oqs11(qs10, qs_storage);
+ return qs_storage;
+ }
+
+ default:
+ NOT_REACHED();
+ }
+}
+
+/* Encode a queue status 'oqs' and append to to 'replies'
+ * The encoded message will be fore Open Flow version 'ofp_version'.
+ * Returns 0 success, an enum ofperr on error */
+enum ofperr
+ofputil_append_queue_stat(struct list *replies,
+ struct ofp11_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;
+
+ reply = ofpmp_append(replies, sizeof *reply);
+ memcpy(reply, &oqs, sizeof reply);
+ break;
+ }
+
+ case OFP10_VERSION: {
+ struct ofp10_queue_stats *reply;
+
+ reply = ofpmp_append(replies, sizeof *reply);
+ return oqs11_to_oqs10(oqs, reply);
+ }
+
+ default:
+ NOT_REACHED();
+ }
+
+ return 0;
+}
+
+/* Convert a struct ofp10_queue_stats_request to a struct
+ * ofp11_queue_stats_request.
+ * The latter may be used as a neutral format as is able to
+ * encode both ofp*_queue_stats_request variants. */
+static void
+oqsr10_to_oqsr11(const struct ofp10_queue_stats_request *in,
+ struct ofp11_queue_stats_request *out)
+{
+ out->port_no = ofputil_port_to_ofp11(ntohs(in->port_no));
+ out->queue_id = in->queue_id;
+}
+
+/* Parse a struct one element of a port status request message into a
+ * struct ofp11_queue_stats_request. struct ofp11_queue_stats_request is
+ * used as a neutral format as is able to encode both
+ * ofp*_queue_stats_request variants. qsr_storage shuold point to memory
+ * for a struct ofp11_queue_stats_request. Returns pointer to struct
+ * ofp11_queue_stats_request on success, NULL otherwise. */
+const struct ofp11_queue_stats_request *
+ofptutil_decode_queue_stat_request(const struct ofp_header *oh,
+ struct ofp11_queue_stats_request
+ *qsr_storage)
+{
+ switch ((enum ofp_version)oh->version) {
+ case OFP12_VERSION:
+ case OFP11_VERSION:
+ return ofpmsg_body(oh);
+
+ case OFP10_VERSION: {
+ const struct ofp10_queue_stats_request *qsr10;
+
+ qsr10 = ofpmsg_body(oh);;
+ oqsr10_to_oqsr11(qsr10, qsr_storage);
+ return qsr_storage;
+ }
+
+ default:
+ NOT_REACHED();
+ }
+}
diff --git a/lib/ofp-util.h b/lib/ofp-util.h
index 8600744..3036e47 100644
--- a/lib/ofp-util.h
+++ b/lib/ofp-util.h
@@ -633,4 +633,15 @@ ofptutil_decode_one_port_reply(enum ofp_version ofp_version,
struct ofpbuf *openflow,
struct ofp11_port_stats *ps_storage);
ovs_be32 ofptutil_decode_port_stats_request(const struct ofp_header *request);
+
+const struct ofp11_queue_stats *
+ofptutil_decode_queue_stat(enum ofp_version ofp_version,
+ struct ofpbuf *openflow,
+ struct ofp11_queue_stats *qs_storage);
+enum ofperr ofputil_append_queue_stat(struct list *replies,
+ struct ofp11_queue_stats *ofqs11);
+const struct ofp11_queue_stats_request *
+ofptutil_decode_queue_stat_request(const struct ofp_header *oh,
+ struct ofp11_queue_stats_request
+ *qsr_storage);
#endif /* ofp-util.h */
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index cf7be02..d328818 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -2790,6 +2790,18 @@ handle_aggregate_stats_request(struct ofconn *ofconn,
return 0;
}
+static void
+collate_queue_stat(uint16_t port_no, uint32_t queue_id,
+ const struct netdev_queue_stats *stats,
+ struct ofp11_queue_stats *reply)
+{
+ reply->port_no = htonl(port_no);
+ reply->queue_id = htonl(queue_id);
+ reply->tx_bytes = htonll(stats->tx_bytes);
+ reply->tx_packets = htonll(stats->tx_packets);
+ reply->tx_errors = htonll(stats->tx_errors);
+}
+
struct queue_stats_cbdata {
struct ofport *ofport;
struct list replies;
@@ -2799,15 +2811,11 @@ 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 ofp11_queue_stats ofqs11;
+
+ collate_queue_stat(cbdata->ofport->pp.port_no, queue_id, stats, &ofqs11);
+ assert(!ofputil_append_queue_stat(&cbdata->replies, &ofqs11));
}
static void
@@ -2845,19 +2853,25 @@ 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;
+ uint16_t port_no;
struct ofport *port;
uint32_t queue_id;
enum ofperr error;
+ const struct ofp11_queue_stats_request *qsr;
+ struct ofp11_queue_stats_request qsr_storage;
COVERAGE_INC(ofproto_queue_req);
ofpmp_init(&cbdata.replies, rq);
- port_no = ntohs(qsr->port_no);
+ qsr = ofptutil_decode_queue_stat_request(rq, &qsr_storage);
+ error = ofputil_port_from_ofp11(qsr->port_no, &port_no);
+ if (error) {
+ return error;
+ }
queue_id = ntohl(qsr->queue_id);
+
if (port_no == OFPP_ALL) {
error = OFPERR_OFPQOFC_BAD_QUEUE;
HMAP_FOR_EACH (port, hmap_node, &ofproto->ports) {
diff --git a/tests/ofp-print.at b/tests/ofp-print.at
index f214aa8..7c4604d 100644
--- a/tests/ofp-print.at
+++ b/tests/ofp-print.at
@@ -993,7 +993,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 \
@@ -1003,7 +1003,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 \
@@ -1037,6 +1057,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 4a95c42..bb261e0 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -975,7 +975,7 @@ ofctl_queue_stats(int argc, char *argv[])
struct vconn *vconn;
open_vconn(argv[1], &vconn);
- request = ofpraw_alloc(OFPRAW_OFPST_QUEUE_REQUEST,
+ request = ofpraw_alloc(OFPRAW_OFPST10_QUEUE_REQUEST,
vconn_get_version(vconn), 0);
req = ofpbuf_put_zeros(request, sizeof *req);
--
1.7.10.4
More information about the dev
mailing list