mirror of
https://github.com/openvswitch/ovs
synced 2025-08-31 14:25:26 +00:00
ofp-msgs: Open Flow 1.1 and 1.2 Port Status Messages
This allows for encoding and decoding Open Flow 1.1 and 1.2 Port Stats Request and Reply message Signed-off-by: Simon Horman <horms@verge.net.au> [blp@nicira.com added ofputil_count_port_stas(), simplified interface of ofputil_decode_port_stats(), style changes] Signed-off-by: Ben Pfaff <blp@nicira.com>
This commit is contained in:
@@ -216,10 +216,14 @@ enum ofpraw {
|
||||
OFPRAW_OFPST12_TABLE_REPLY,
|
||||
|
||||
/* OFPST 1.0 (4): struct ofp10_port_stats_request. */
|
||||
OFPRAW_OFPST_PORT_REQUEST,
|
||||
OFPRAW_OFPST10_PORT_REQUEST,
|
||||
/* OFPST 1.1+ (4): struct ofp11_port_stats_request. */
|
||||
OFPRAW_OFPST11_PORT_REQUEST,
|
||||
|
||||
/* OFPST 1.0 (4): struct ofp10_port_stats[]. */
|
||||
OFPRAW_OFPST_PORT_REPLY,
|
||||
OFPRAW_OFPST10_PORT_REPLY,
|
||||
/* OFPST 1.1+ (4): struct ofp11_port_stats[]. */
|
||||
OFPRAW_OFPST11_PORT_REPLY,
|
||||
|
||||
/* OFPST 1.0 (5): struct ofp10_queue_stats_request. */
|
||||
OFPRAW_OFPST_QUEUE_REQUEST,
|
||||
@@ -382,8 +386,10 @@ enum ofptype {
|
||||
OFPTYPE_TABLE_STATS_REPLY, /* OFPRAW_OFPST10_TABLE_REPLY.
|
||||
* OFPRAW_OFPST11_TABLE_REPLY.
|
||||
* OFPRAW_OFPST12_TABLE_REPLY. */
|
||||
OFPTYPE_PORT_STATS_REQUEST, /* OFPRAW_OFPST_PORT_REQUEST. */
|
||||
OFPTYPE_PORT_STATS_REPLY, /* OFPRAW_OFPST_PORT_REPLY. */
|
||||
OFPTYPE_PORT_STATS_REQUEST, /* OFPRAW_OFPST10_PORT_REQUEST.
|
||||
* 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_PORT_DESC_STATS_REQUEST, /* OFPRAW_OFPST_PORT_DESC_REQUEST. */
|
||||
|
@@ -1065,11 +1065,9 @@ ofp_print_aggregate_stats_reply(struct ds *string, const struct ofp_header *oh)
|
||||
ds_put_format(string, " flow_count=%"PRIu32, as.flow_count);
|
||||
}
|
||||
|
||||
static void print_port_stat(struct ds *string, const char *leader,
|
||||
const ovs_32aligned_be64 *statp, int more)
|
||||
static void
|
||||
print_port_stat(struct ds *string, const char *leader, uint64_t stat, int more)
|
||||
{
|
||||
uint64_t stat = ntohll(get_32aligned_be64(statp));
|
||||
|
||||
ds_put_cstr(string, leader);
|
||||
if (stat != UINT64_MAX) {
|
||||
ds_put_format(string, "%"PRIu64, stat);
|
||||
@@ -1086,50 +1084,59 @@ static void print_port_stat(struct ds *string, const char *leader,
|
||||
static void
|
||||
ofp_print_ofpst_port_request(struct ds *string, const struct ofp_header *oh)
|
||||
{
|
||||
const struct ofp10_port_stats_request *psr = ofpmsg_body(oh);
|
||||
ds_put_format(string, " port_no=%"PRIu16, ntohs(psr->port_no));
|
||||
uint16_t ofp10_port;
|
||||
enum ofperr error;
|
||||
|
||||
error = ofputil_decode_port_stats_request(oh, &ofp10_port);
|
||||
if (error) {
|
||||
ofp_print_error(string, error);
|
||||
return;
|
||||
}
|
||||
|
||||
ds_put_format(string, " port_no=%2"PRIu16, ofp10_port);
|
||||
}
|
||||
|
||||
static void
|
||||
ofp_print_ofpst_port_reply(struct ds *string, const struct ofp_header *oh,
|
||||
int verbosity)
|
||||
{
|
||||
struct ofp10_port_stats *ps;
|
||||
struct ofpbuf b;
|
||||
size_t n;
|
||||
|
||||
ofpbuf_use_const(&b, oh, ntohs(oh->length));
|
||||
ofpraw_pull_assert(&b);
|
||||
|
||||
n = b.size / sizeof *ps;
|
||||
ds_put_format(string, " %zu ports\n", n);
|
||||
ds_put_format(string, " %zu ports\n", ofputil_count_port_stats(oh));
|
||||
if (verbosity < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
ofpbuf_use_const(&b, oh, ntohs(oh->length));
|
||||
for (;;) {
|
||||
ps = ofpbuf_try_pull(&b, sizeof *ps);
|
||||
if (!ps) {
|
||||
struct ofputil_port_stats ps;
|
||||
int retval;
|
||||
|
||||
retval = ofputil_decode_port_stats(&ps, &b);
|
||||
if (retval) {
|
||||
if (retval != EOF) {
|
||||
ds_put_cstr(string, " ***parse error***");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ds_put_format(string, " port %2"PRIu16": ", ntohs(ps->port_no));
|
||||
ds_put_format(string, " port %2"PRIu16, ps.port_no);
|
||||
|
||||
ds_put_cstr(string, "rx ");
|
||||
print_port_stat(string, "pkts=", &ps->rx_packets, 1);
|
||||
print_port_stat(string, "bytes=", &ps->rx_bytes, 1);
|
||||
print_port_stat(string, "drop=", &ps->rx_dropped, 1);
|
||||
print_port_stat(string, "errs=", &ps->rx_errors, 1);
|
||||
print_port_stat(string, "frame=", &ps->rx_frame_err, 1);
|
||||
print_port_stat(string, "over=", &ps->rx_over_err, 1);
|
||||
print_port_stat(string, "crc=", &ps->rx_crc_err, 0);
|
||||
ds_put_cstr(string, ": rx ");
|
||||
print_port_stat(string, "pkts=", ps.stats.rx_packets, 1);
|
||||
print_port_stat(string, "bytes=", ps.stats.rx_bytes, 1);
|
||||
print_port_stat(string, "drop=", ps.stats.rx_dropped, 1);
|
||||
print_port_stat(string, "errs=", ps.stats.rx_errors, 1);
|
||||
print_port_stat(string, "frame=", ps.stats.rx_frame_errors, 1);
|
||||
print_port_stat(string, "over=", ps.stats.rx_over_errors, 1);
|
||||
print_port_stat(string, "crc=", ps.stats.rx_crc_errors, 0);
|
||||
|
||||
ds_put_cstr(string, " tx ");
|
||||
print_port_stat(string, "pkts=", &ps->tx_packets, 1);
|
||||
print_port_stat(string, "bytes=", &ps->tx_bytes, 1);
|
||||
print_port_stat(string, "drop=", &ps->tx_dropped, 1);
|
||||
print_port_stat(string, "errs=", &ps->tx_errors, 1);
|
||||
print_port_stat(string, "coll=", &ps->collisions, 0);
|
||||
print_port_stat(string, "pkts=", ps.stats.tx_packets, 1);
|
||||
print_port_stat(string, "bytes=", ps.stats.tx_bytes, 1);
|
||||
print_port_stat(string, "drop=", ps.stats.tx_dropped, 1);
|
||||
print_port_stat(string, "errs=", ps.stats.tx_errors, 1);
|
||||
print_port_stat(string, "coll=", ps.stats.collisions, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1328,6 +1335,13 @@ ofp_print_ofpst_queue_request(struct ds *string, const struct ofp_header *oh)
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
ofp_print_ofpst_queue_reply(struct ds *string, const struct ofp_header *oh,
|
||||
int verbosity)
|
||||
@@ -1357,9 +1371,9 @@ ofp_print_ofpst_queue_reply(struct ds *string, const struct ofp_header *oh,
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
242
lib/ofp-util.c
242
lib/ofp-util.c
@@ -3938,3 +3938,245 @@ ofputil_parse_key_value(char **stringp, char **keyp, char **valuep)
|
||||
*valuep = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Encode a dump ports request for 'port', 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_dump_ports_request(enum ofp_version ofp_version, int16_t port)
|
||||
{
|
||||
struct ofpbuf *request;
|
||||
|
||||
switch (ofp_version) {
|
||||
case OFP10_VERSION: {
|
||||
struct ofp10_port_stats_request *req;
|
||||
request = ofpraw_alloc(OFPRAW_OFPST10_PORT_REQUEST, ofp_version, 0);
|
||||
req = ofpbuf_put_zeros(request, sizeof *req);
|
||||
req->port_no = htons(port);
|
||||
break;
|
||||
}
|
||||
case OFP11_VERSION:
|
||||
case OFP12_VERSION: {
|
||||
struct ofp11_port_stats_request *req;
|
||||
request = ofpraw_alloc(OFPRAW_OFPST11_PORT_REQUEST, ofp_version, 0);
|
||||
req = ofpbuf_put_zeros(request, sizeof *req);
|
||||
req->port_no = ofputil_port_to_ofp11(port);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
NOT_REACHED();
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
static void
|
||||
ofputil_port_stats_to_ofp10(const struct ofputil_port_stats *ops,
|
||||
struct ofp10_port_stats *ps10)
|
||||
{
|
||||
ps10->port_no = htons(ops->port_no);
|
||||
memset(ps10->pad, 0, sizeof ps10->pad);
|
||||
put_32aligned_be64(&ps10->rx_packets, htonll(ops->stats.rx_packets));
|
||||
put_32aligned_be64(&ps10->tx_packets, htonll(ops->stats.tx_packets));
|
||||
put_32aligned_be64(&ps10->rx_bytes, htonll(ops->stats.rx_bytes));
|
||||
put_32aligned_be64(&ps10->tx_bytes, htonll(ops->stats.tx_bytes));
|
||||
put_32aligned_be64(&ps10->rx_dropped, htonll(ops->stats.rx_dropped));
|
||||
put_32aligned_be64(&ps10->tx_dropped, htonll(ops->stats.tx_dropped));
|
||||
put_32aligned_be64(&ps10->rx_errors, htonll(ops->stats.rx_errors));
|
||||
put_32aligned_be64(&ps10->tx_errors, htonll(ops->stats.tx_errors));
|
||||
put_32aligned_be64(&ps10->rx_frame_err, htonll(ops->stats.rx_frame_errors));
|
||||
put_32aligned_be64(&ps10->rx_over_err, htonll(ops->stats.rx_over_errors));
|
||||
put_32aligned_be64(&ps10->rx_crc_err, htonll(ops->stats.rx_crc_errors));
|
||||
put_32aligned_be64(&ps10->collisions, htonll(ops->stats.collisions));
|
||||
}
|
||||
|
||||
static void
|
||||
ofputil_port_stats_to_ofp11(const struct ofputil_port_stats *ops,
|
||||
struct ofp11_port_stats *ps11)
|
||||
{
|
||||
ps11->port_no = ofputil_port_to_ofp11(ops->port_no);
|
||||
memset(ps11->pad, 0, sizeof ps11->pad);
|
||||
ps11->rx_packets = htonll(ops->stats.rx_packets);
|
||||
ps11->tx_packets = htonll(ops->stats.tx_packets);
|
||||
ps11->rx_bytes = htonll(ops->stats.rx_bytes);
|
||||
ps11->tx_bytes = htonll(ops->stats.tx_bytes);
|
||||
ps11->rx_dropped = htonll(ops->stats.rx_dropped);
|
||||
ps11->tx_dropped = htonll(ops->stats.tx_dropped);
|
||||
ps11->rx_errors = htonll(ops->stats.rx_errors);
|
||||
ps11->tx_errors = htonll(ops->stats.tx_errors);
|
||||
ps11->rx_frame_err = htonll(ops->stats.rx_frame_errors);
|
||||
ps11->rx_over_err = htonll(ops->stats.rx_over_errors);
|
||||
ps11->rx_crc_err = htonll(ops->stats.rx_crc_errors);
|
||||
ps11->collisions = htonll(ops->stats.collisions);
|
||||
}
|
||||
|
||||
/* Encode a ports stat for 'opes' and append it to 'replies'.
|
||||
* The encoded message will be for Open Flow version 'ofp_version'. */
|
||||
void
|
||||
ofputil_append_port_stat(struct list *replies,
|
||||
const struct ofputil_port_stats *ops)
|
||||
{
|
||||
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_port_stats *reply = ofpmp_append(replies, sizeof *reply);
|
||||
ofputil_port_stats_to_ofp11(ops, reply);
|
||||
break;
|
||||
}
|
||||
|
||||
case OFP10_VERSION: {
|
||||
struct ofp10_port_stats *reply = ofpmp_append(replies, sizeof *reply);
|
||||
ofputil_port_stats_to_ofp10(ops, reply);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
static enum ofperr
|
||||
ofputil_port_stats_from_ofp10(struct ofputil_port_stats *ops,
|
||||
const struct ofp10_port_stats *ps10)
|
||||
{
|
||||
memset(ops, 0, sizeof *ops);
|
||||
|
||||
ops->port_no = ntohs(ps10->port_no);
|
||||
ops->stats.rx_packets = ntohll(get_32aligned_be64(&ps10->rx_packets));
|
||||
ops->stats.tx_packets = ntohll(get_32aligned_be64(&ps10->tx_packets));
|
||||
ops->stats.rx_bytes = ntohll(get_32aligned_be64(&ps10->rx_bytes));
|
||||
ops->stats.tx_bytes = ntohll(get_32aligned_be64(&ps10->tx_bytes));
|
||||
ops->stats.rx_dropped = ntohll(get_32aligned_be64(&ps10->rx_dropped));
|
||||
ops->stats.tx_dropped = ntohll(get_32aligned_be64(&ps10->tx_dropped));
|
||||
ops->stats.rx_errors = ntohll(get_32aligned_be64(&ps10->rx_errors));
|
||||
ops->stats.tx_errors = ntohll(get_32aligned_be64(&ps10->tx_errors));
|
||||
ops->stats.rx_frame_errors =
|
||||
ntohll(get_32aligned_be64(&ps10->rx_frame_err));
|
||||
ops->stats.rx_over_errors = ntohll(get_32aligned_be64(&ps10->rx_over_err));
|
||||
ops->stats.rx_crc_errors = ntohll(get_32aligned_be64(&ps10->rx_crc_err));
|
||||
ops->stats.collisions = ntohll(get_32aligned_be64(&ps10->collisions));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum ofperr
|
||||
ofputil_port_stats_from_ofp11(struct ofputil_port_stats *ops,
|
||||
const struct ofp11_port_stats *ps11)
|
||||
{
|
||||
enum ofperr error;
|
||||
|
||||
memset(ops, 0, sizeof *ops);
|
||||
error = ofputil_port_from_ofp11(ps11->port_no, &ops->port_no);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
ops->stats.rx_packets = ntohll(ps11->rx_packets);
|
||||
ops->stats.tx_packets = ntohll(ps11->tx_packets);
|
||||
ops->stats.rx_bytes = ntohll(ps11->rx_bytes);
|
||||
ops->stats.tx_bytes = ntohll(ps11->tx_bytes);
|
||||
ops->stats.rx_dropped = ntohll(ps11->rx_dropped);
|
||||
ops->stats.tx_dropped = ntohll(ps11->tx_dropped);
|
||||
ops->stats.rx_errors = ntohll(ps11->rx_errors);
|
||||
ops->stats.tx_errors = ntohll(ps11->tx_errors);
|
||||
ops->stats.rx_frame_errors = ntohll(ps11->rx_frame_err);
|
||||
ops->stats.rx_over_errors = ntohll(ps11->rx_over_err);
|
||||
ops->stats.rx_crc_errors = ntohll(ps11->rx_crc_err);
|
||||
ops->stats.collisions = ntohll(ps11->collisions);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns the number of port stats elements in OFPTYPE_PORT_STATS_REPLY
|
||||
* message 'oh'. */
|
||||
size_t
|
||||
ofputil_count_port_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_port_stats) ==
|
||||
sizeof(struct ofp11_port_stats));
|
||||
return b.size / sizeof(struct ofp10_port_stats);
|
||||
}
|
||||
|
||||
/* Converts an OFPST_PORT_STATS reply in 'msg' into an abstract
|
||||
* ofputil_port_stats in 'ps'.
|
||||
*
|
||||
* Multiple OFPST_PORT_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_port_stats(struct ofputil_port_stats *ps, 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_PORT_REPLY) {
|
||||
const struct ofp11_port_stats *ps11;
|
||||
|
||||
ps11 = ofpbuf_try_pull(msg, sizeof *ps11);
|
||||
if (!ps11) {
|
||||
VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_PORT reply has %zu leftover "
|
||||
"bytes at end", msg->size);
|
||||
return OFPERR_OFPBRC_BAD_LEN;
|
||||
}
|
||||
return ofputil_port_stats_from_ofp11(ps, ps11);
|
||||
} else if (raw == OFPRAW_OFPST10_PORT_REPLY) {
|
||||
const struct ofp10_port_stats *ps10;
|
||||
|
||||
ps10 = ofpbuf_try_pull(msg, sizeof *ps10);
|
||||
if (!ps10) {
|
||||
VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_PORT reply has %zu leftover "
|
||||
"bytes at end", msg->size);
|
||||
return OFPERR_OFPBRC_BAD_LEN;
|
||||
}
|
||||
return ofputil_port_stats_from_ofp10(ps, ps10);
|
||||
} else {
|
||||
NOT_REACHED();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Parse a port status request message into a 16 bit OpenFlow 1.0
|
||||
* port number and stores the latter in '*ofp10_port'.
|
||||
* Returns 0 if successful, otherwise an OFPERR_* number. */
|
||||
enum ofperr
|
||||
ofputil_decode_port_stats_request(const struct ofp_header *request,
|
||||
uint16_t *ofp10_port)
|
||||
{
|
||||
switch ((enum ofp_version)request->version) {
|
||||
case OFP12_VERSION:
|
||||
case OFP11_VERSION: {
|
||||
const struct ofp11_port_stats_request *psr11 = ofpmsg_body(request);
|
||||
return ofputil_port_from_ofp11(psr11->port_no, ofp10_port);
|
||||
}
|
||||
|
||||
case OFP10_VERSION: {
|
||||
const struct ofp10_port_stats_request *psr10 = ofpmsg_body(request);
|
||||
*ofp10_port = ntohs(psr10->port_no);
|
||||
return 0;
|
||||
}
|
||||
|
||||
default:
|
||||
NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
@@ -620,4 +620,19 @@ union ofp_action *ofputil_actions_clone(const union ofp_action *, size_t n);
|
||||
/* Handy utility for parsing flows and actions. */
|
||||
bool ofputil_parse_key_value(char **stringp, char **keyp, char **valuep);
|
||||
|
||||
struct ofpbuf *ofputlil_dump_ports(enum ofp_version ofp_version, int16_t port);
|
||||
|
||||
struct ofputil_port_stats {
|
||||
uint16_t port_no;
|
||||
struct netdev_stats stats;
|
||||
};
|
||||
|
||||
struct ofpbuf *ofputil_encode_dump_ports_request(enum ofp_version ofp_version,
|
||||
int16_t port);
|
||||
void ofputil_append_port_stat(struct list *replies,
|
||||
const struct ofputil_port_stats *ops);
|
||||
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);
|
||||
#endif /* ofp-util.h */
|
||||
|
@@ -2295,29 +2295,14 @@ handle_table_stats_request(struct ofconn *ofconn,
|
||||
static void
|
||||
append_port_stat(struct ofport *port, struct list *replies)
|
||||
{
|
||||
struct netdev_stats stats;
|
||||
struct ofp10_port_stats *ops;
|
||||
struct ofputil_port_stats ops = { .port_no = port->pp.port_no };
|
||||
|
||||
/* Intentionally ignore return value, since errors will set
|
||||
* 'stats' to all-1s, which is correct for OpenFlow, and
|
||||
* netdev_get_stats() will log errors. */
|
||||
ofproto_port_get_stats(port, &stats);
|
||||
ofproto_port_get_stats(port, &ops.stats);
|
||||
|
||||
ops = ofpmp_append(replies, sizeof *ops);
|
||||
ops->port_no = htons(port->pp.port_no);
|
||||
memset(ops->pad, 0, sizeof ops->pad);
|
||||
put_32aligned_be64(&ops->rx_packets, htonll(stats.rx_packets));
|
||||
put_32aligned_be64(&ops->tx_packets, htonll(stats.tx_packets));
|
||||
put_32aligned_be64(&ops->rx_bytes, htonll(stats.rx_bytes));
|
||||
put_32aligned_be64(&ops->tx_bytes, htonll(stats.tx_bytes));
|
||||
put_32aligned_be64(&ops->rx_dropped, htonll(stats.rx_dropped));
|
||||
put_32aligned_be64(&ops->tx_dropped, htonll(stats.tx_dropped));
|
||||
put_32aligned_be64(&ops->rx_errors, htonll(stats.rx_errors));
|
||||
put_32aligned_be64(&ops->tx_errors, htonll(stats.tx_errors));
|
||||
put_32aligned_be64(&ops->rx_frame_err, htonll(stats.rx_frame_errors));
|
||||
put_32aligned_be64(&ops->rx_over_err, htonll(stats.rx_over_errors));
|
||||
put_32aligned_be64(&ops->rx_crc_err, htonll(stats.rx_crc_errors));
|
||||
put_32aligned_be64(&ops->collisions, htonll(stats.collisions));
|
||||
ofputil_append_port_stat(replies, &ops);
|
||||
}
|
||||
|
||||
static enum ofperr
|
||||
@@ -2325,13 +2310,19 @@ handle_port_stats_request(struct ofconn *ofconn,
|
||||
const struct ofp_header *request)
|
||||
{
|
||||
struct ofproto *p = ofconn_get_ofproto(ofconn);
|
||||
const struct ofp10_port_stats_request *psr = ofpmsg_body(request);
|
||||
struct ofport *port;
|
||||
struct list replies;
|
||||
uint16_t port_no;
|
||||
enum ofperr error;
|
||||
|
||||
error = ofputil_decode_port_stats_request(request, &port_no);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
ofpmp_init(&replies, request);
|
||||
if (psr->port_no != htons(OFPP_NONE)) {
|
||||
port = ofproto_get_port(p, ntohs(psr->port_no));
|
||||
if (port_no != OFPP_NONE) {
|
||||
port = ofproto_get_port(p, port_no);
|
||||
if (port) {
|
||||
append_port_stat(port, &replies);
|
||||
}
|
||||
|
@@ -949,7 +949,7 @@ AT_KEYWORDS([ofp-print OFPT_STATS_REPLY])
|
||||
AT_CHECK([ovs-ofctl ofp-print "$(cat in)"], [0], [expout])
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([OFPST_PORT request])
|
||||
AT_SETUP([OFPST_PORT request - 1.0])
|
||||
AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST])
|
||||
AT_CHECK([ovs-ofctl ofp-print "\
|
||||
01 10 00 14 00 00 00 01 00 04 00 00 ff ff 00 00 \
|
||||
@@ -959,7 +959,27 @@ OFPST_PORT request (xid=0x1): port_no=65535
|
||||
])
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([OFPST_PORT reply])
|
||||
AT_SETUP([OFPST_PORT request - 1.1])
|
||||
AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST])
|
||||
AT_CHECK([ovs-ofctl ofp-print "\
|
||||
02 12 00 18 00 00 00 02 00 04 00 00 00 00 00 00 \
|
||||
ff ff ff ff 00 00 00 00 \
|
||||
"], [0], [dnl
|
||||
OFPST_PORT request (OF1.1) (xid=0x2): port_no=65535
|
||||
])
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([OFPST_PORT request - 1.2])
|
||||
AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST])
|
||||
AT_CHECK([ovs-ofctl ofp-print "\
|
||||
03 12 00 18 00 00 00 02 00 04 00 00 00 00 00 00 \
|
||||
ff ff ff ff 00 00 00 00 \
|
||||
"], [0], [dnl
|
||||
OFPST_PORT request (OF1.2) (xid=0x2): port_no=65535
|
||||
])
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([OFPST_PORT reply - OF1.0])
|
||||
AT_KEYWORDS([ofp-print OFPT_STATS_REPLY])
|
||||
AT_CHECK([ovs-ofctl ofp-print "\
|
||||
01 11 01 ac 00 00 00 01 00 04 00 00 00 03 00 00 \
|
||||
@@ -1002,6 +1022,41 @@ OFPST_PORT reply (xid=0x1): 4 ports
|
||||
])
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([OFPST_PORT reply - OF1.2])
|
||||
AT_KEYWORDS([ofp-print OFPT_STATS_REPLY])
|
||||
AT_CHECK([ovs-ofctl ofp-print "\
|
||||
03 13 01 48 00 00 00 02 00 04 00 00 00 00 00 00 \
|
||||
00 00 00 02 00 00 00 00 00 00 00 00 00 01 95 56 \
|
||||
00 00 00 00 00 00 00 88 00 00 00 00 02 5d 08 98 \
|
||||
00 00 00 00 00 00 2c f8 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 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 00 00 \
|
||||
00 00 00 00 00 00 00 00 ff ff ff fe 00 00 00 00 \
|
||||
00 00 00 00 00 00 00 44 00 00 00 00 00 00 9d 2c \
|
||||
00 00 00 00 00 00 16 7c 00 00 00 00 01 1e 36 44 \
|
||||
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 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 00 00 00 00 00 00 00 00 00 00 \
|
||||
00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 44 \
|
||||
00 00 00 00 00 00 9d 2c 00 00 00 00 00 00 16 7c \
|
||||
00 00 00 00 01 1e 36 44 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 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 00 00 \
|
||||
00 00 00 00 00 00 00 00 \
|
||||
"], [0], [dnl
|
||||
OFPST_PORT reply (OF1.2) (xid=0x2): 3 ports
|
||||
port 2: rx pkts=103766, bytes=39651480, drop=0, errs=0, frame=0, over=0, crc=0
|
||||
tx pkts=136, bytes=11512, drop=0, errs=0, coll=0
|
||||
port 65534: rx pkts=68, bytes=5756, drop=0, errs=0, frame=0, over=0, crc=0
|
||||
tx pkts=40236, bytes=18757188, drop=0, errs=0, coll=0
|
||||
port 1: rx pkts=68, bytes=5756, drop=0, errs=0, frame=0, over=0, crc=0
|
||||
tx pkts=40236, bytes=18757188, drop=0, errs=0, coll=0
|
||||
])
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([OFPST_QUEUE request])
|
||||
AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST])
|
||||
AT_CHECK([ovs-ofctl ofp-print "\
|
||||
|
@@ -1418,17 +1418,13 @@ ofctl_snoop(int argc OVS_UNUSED, char *argv[])
|
||||
static void
|
||||
ofctl_dump_ports(int argc, char *argv[])
|
||||
{
|
||||
struct ofp10_port_stats_request *req;
|
||||
struct ofpbuf *request;
|
||||
struct vconn *vconn;
|
||||
uint16_t port;
|
||||
|
||||
open_vconn(argv[1], &vconn);
|
||||
request = ofpraw_alloc(OFPRAW_OFPST_PORT_REQUEST,
|
||||
vconn_get_version(vconn), 0);
|
||||
req = ofpbuf_put_zeros(request, sizeof *req);
|
||||
port = argc > 2 ? str_to_port_no(argv[1], argv[2]) : OFPP_NONE;
|
||||
req->port_no = htons(port);
|
||||
request = ofputil_encode_dump_ports_request(vconn_get_version(vconn), port);
|
||||
dump_stats_transaction(vconn, request);
|
||||
vconn_close(vconn);
|
||||
}
|
||||
|
Reference in New Issue
Block a user