2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-30 22:05:19 +00:00

ofp-msgs: Open Flow 1.1 and 1.2 Queue Status Messages

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@verge.net.au>
Signed-off-by: Ben Pfaff <blp@nicira.com>
This commit is contained in:
Simon Horman
2012-10-12 13:03:04 +09:00
committed by Ben Pfaff
parent ad4c35fe2d
commit 6462697510
7 changed files with 365 additions and 57 deletions

View File

@@ -4179,3 +4179,210 @@ 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 ofp10_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();
}
}