This allows for encoding and decoding Open Flow 1.1 and 1.2 Port Stats Request and Reply message
Signed-off-by: Simon Horman <ho...@verge.net.au> --- v14 * Manual rebase v13 * Merge the following patches - ofp-msgs: Split OFPRAW_OFPST_PORT_{REQUEST,REPLY} - ovs-ofctl: Teach dump-ports about Open Flow 1.1 & 1.2 - ofp-util: Allow encoding of Open Flow 1.1 & 1.2 Port Statistics Reply Messages - ofp-print: Allow printing of Open Flow 1.1 & 1.2 Port Reply Messages - ofp-util: Allow decoding of Open Flow 1.1 & 1.2 Port Status Request Messages - ofp-print: Allow printing of Open Flow 1.1 & 1.2 Port Status Request Messages * Move encoding and decoding into a helper functions v12 * No change v11 * No change v10 * No change v9 * Update description - this only prepares for both encoding and decoding * Add ofp-print test * Make use of enum ofp_version * Correct printing of port number for Open Flow 1.0 * Replace UINT64_MAX with htonll(UINT64_MAX) in ofp_print_port_stat() to correct byte-order problem detected by sparse v8 * Manual rebase * Make use of enum ofp_version * Add ofp-print test v7 * Omitted v6 * No change v5 * No change v4 * Initial post --- lib/ofp-msgs.h | 14 +++- lib/ofp-print.c | 58 +++++++------ lib/ofp-util.c | 215 ++++++++++++++++++++++++++++++++++++++++++++++++- lib/ofp-util.h | 10 +++ ofproto/ofproto.c | 53 +++++++----- tests/ofp-print.at | 59 +++++++++++++- utilities/ovs-ofctl.c | 6 +- 7 files changed, 359 insertions(+), 56 deletions(-) diff --git a/lib/ofp-msgs.h b/lib/ofp-msgs.h index 752d12c..6420c5d 100644 --- a/lib/ofp-msgs.h +++ b/lib/ofp-msgs.h @@ -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. */ diff --git a/lib/ofp-print.c b/lib/ofp-print.c index 6789625..25aa9b9 100644 --- a/lib/ofp-print.c +++ b/lib/ofp-print.c @@ -1061,14 +1061,12 @@ 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 ofp_print_port_stat(struct ds *string, const char *leader, + ovs_be64 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); + if (stat != htonll(UINT64_MAX)) { + ds_put_format(string, "%"PRIu64, ntohll(stat)); } else { ds_put_char(string, '?'); } @@ -1079,24 +1077,34 @@ static void 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) { - const struct ofp10_port_stats_request *psr = ofpmsg_body(oh); - ds_put_format(string, " port_no=%"PRIu16, ntohs(psr->port_no)); + ovs_be32 ofp11_port = ofptutil_decode_port_stats_request(oh); + + ds_put_cstr(string, " port_no="); + assert(!ofputil_format_raw_port(oh->version, ofp11_port, string)); } static void ofp_print_ofpst_port_reply(struct ds *string, const struct ofp_header *oh, int verbosity) { - struct ofp10_port_stats *ps; + struct ofp11_port_stats *ps; struct ofpbuf b; size_t n; ofpbuf_use_const(&b, oh, ntohs(oh->length)); ofpraw_pull_assert(&b); + /* struct ofp10_port_stats and struct ofp11_port_stats are the + * same size. */ n = b.size / sizeof *ps; ds_put_format(string, " %zu ports\n", n); if (verbosity < 1) { @@ -1104,28 +1112,30 @@ ofp_print_ofpst_port_reply(struct ds *string, const struct ofp_header *oh, } for (;;) { - ps = ofpbuf_try_pull(&b, sizeof *ps); + struct ofp11_port_stats ps_storage; + ps = ofptutil_decode_one_port_reply(oh->version, &b, &ps_storage); if (!ps) { return; } - ds_put_format(string, " port %2"PRIu16": ", ntohs(ps->port_no)); + ds_put_cstr(string, " port "); + assert(!ofputil_format_raw_port(oh->version, ps->port_no, string)); - 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 "); + ofp_print_port_stat(string, "pkts=", ps->rx_packets, 1); + ofp_print_port_stat(string, "bytes=", ps->rx_bytes, 1); + ofp_print_port_stat(string, "drop=", ps->rx_dropped, 1); + ofp_print_port_stat(string, "errs=", ps->rx_errors, 1); + ofp_print_port_stat(string, "frame=", ps->rx_frame_err, 1); + ofp_print_port_stat(string, "over=", ps->rx_over_err, 1); + ofp_print_port_stat(string, "crc=", ps->rx_crc_err, 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); + ofp_print_port_stat(string, "pkts=", ps->tx_packets, 1); + ofp_print_port_stat(string, "bytes=", ps->tx_bytes, 1); + ofp_print_port_stat(string, "drop=", ps->tx_dropped, 1); + ofp_print_port_stat(string, "errs=", ps->tx_errors, 1); + ofp_print_port_stat(string, "coll=", ps->collisions, 0); } } diff --git a/lib/ofp-util.c b/lib/ofp-util.c index fc98894..e3c4d42 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -3624,6 +3624,42 @@ ofputil_format_port(uint16_t port, struct ds *s) ds_put_cstr(s, name); } +/* Appends to 's' a numeric string representation of the OpenFlow port + * number 'port'. + * If ofp_version indicates Open Flow 1.0, + * then convert 'ofp_port' to an OpenFlow 1.0 using + * ofputil_port_from_ofp11(). This converts 'ofp11_port' to + * a 16 bit port. + * Else if ofp_version indicates Open Flow 1.1, + * all 32 bits of ofp11_port are used + * Returns 0 if successful, otherwise an OFPERR_* number. */ +enum ofperr +ofputil_format_raw_port(enum ofp_version ofp_version, ovs_be32 ofp11_port, + struct ds *s) +{ + switch (ofp_version) { + case OFP12_VERSION: + case OFP11_VERSION: + ds_put_format(s, "%2"PRIu32, ntohl(ofp11_port)); + break; + + case OFP10_VERSION: { + uint16_t ofp10_port; + enum ofperr error = ofputil_port_from_ofp11(ofp11_port, &ofp10_port); + if (error) { + return error; + } + ds_put_format(s, "%2"PRIu16, ofp10_port); + break; + } + + default: + NOT_REACHED(); + } + + return 0; +} + /* Given a buffer 'b' that contains an array of OpenFlow ports of type * 'ofp_version', tries to pull the first element from the array. If * successful, initializes '*pp' with an abstract representation of the @@ -3913,8 +3949,7 @@ ofputil_parse_key_value(char **stringp, char **keyp, char **valuep) level = 0; break; - case '(': - level++; + case '(':level++; break; case ')': @@ -3936,3 +3971,179 @@ 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 * +ofputlil_dump_ports(enum ofp_version ofp_version, int16_t port) +{ + struct ofpbuf *request; + enum ofpraw raw; + + switch (ofp_version) { + case OFP10_VERSION: + raw = OFPRAW_OFPST10_PORT_REQUEST; + break; + case OFP11_VERSION: + case OFP12_VERSION: + raw = OFPRAW_OFPST11_PORT_REQUEST; + break; + default: + NOT_REACHED(); + } + + request = ofpraw_alloc(raw, ofp_version, 0); + + switch (ofp_version) { + case OFP10_VERSION: { + struct ofp10_port_stats_request *req; + 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; + req = ofpbuf_put_zeros(request, sizeof *req); + req->port_no = ofputil_port_to_ofp11(port); + break; + } + default: + NOT_REACHED(); + } + + return request; +} + +/* Convert a struct ofp10_port_stats to a struct ofp11_port_stats. + * The latter may be used as a neutral format as is able to + * encode both ofp*_port_stats variants. */ +static void +ops10_to_ops11(const struct ofp10_port_stats *in, + struct ofp11_port_stats *out) +{ + /* struct ofp11_port_stats and struct ofp10_port_stats are + * the same size and the elements after port_no and pad + * are the same */ + OFP_ASSERT(sizeof *in == sizeof *out); + memcpy(out, in, sizeof *in); + + out->port_no = ofputil_port_to_ofp11(ntohs(in->port_no)); + memset(out->pad, 0, sizeof out->pad); +} + +/* Convert a struct ofp11_port_stats to a struct ofp10_port_stats. + * The former may be used as a neutral format as is able to + * encode both ofp*_port_stats variants. + * Returns 0 on success, an enum ofperr value on error */ +static enum ofperr +ops11_to_ops10(const struct ofp11_port_stats *in, struct ofp10_port_stats *out) +{ + uint16_t ofp10_port; + enum ofperr error; + + /* struct ofp11_port_stats and struct ofp10_port_stats are + * the same size and the elements after port_no and pad + * are the same */ + OFP_ASSERT(sizeof *in == sizeof *out); + memcpy(out, in, sizeof *in); + + 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); + return 0; +} + +/* Encode a ports stat for 'opes' and append it to 'replies'. + * The encoded message will be fore Open Flow version 'ofp_version'. + * Returns 0 on success, an enum ofperr value on error */ +enum ofperr +ofputil_append_port_stat(struct list *replies, + const struct ofp11_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; + + reply = ofpmp_append(replies, sizeof *reply); + memcpy(reply, ops, sizeof *reply); + break; + } + + case OFP10_VERSION: { + struct ofp10_port_stats *reply; + + reply = ofpmp_append(replies, sizeof *reply); + return ops11_to_ops10(ops, reply); + } + + default: + NOT_REACHED(); + } + + return 0; +} + +/* Parse a struct one element of a port status reply message into a struct + * ofp11_port_stats. struct ofp11_port_status is used as a neutral format + * as is able to encode both ofp*_port_stats variants. ps_storage shuold + * point to memory for a struct ofp11_port_stats. Returns pointer to + * struct ofp11_port_status on success, NULL otherwise. */ +struct ofp11_port_stats * +ofptutil_decode_one_port_reply(enum ofp_version ofp_version, + struct ofpbuf *openflow, + struct ofp11_port_stats *ps_storage) +{ + switch (ofp_version) { + case OFP12_VERSION: + case OFP11_VERSION: + return ofpbuf_try_pull(openflow, sizeof *ps_storage); + + case OFP10_VERSION: { + struct ofp10_port_stats *ps10; + + ps10 = ofpbuf_try_pull(openflow, sizeof *ps10); + if (!ps10) { + return NULL; + } + ops10_to_ops11(ps10, ps_storage); + return ps_storage; + } + + default: + NOT_REACHED(); + } +} + +/* Parse a port status request message into a 32 bit port number + * This preserves all the bits of the port number in the message. + * In the case of Open Flow 1.0 the 16 bit port number is returned + * in the least significant bits. Open Flow 1.1+ port numbers are 32 bits. + * Returns port number. */ +ovs_be32 +ofptutil_decode_port_stats_request(const struct ofp_header *request) +{ + switch ((enum ofp_version)request->version) { + case OFP12_VERSION: + case OFP11_VERSION: { + const struct ofp11_port_stats_request *psr = ofpmsg_body(request); + return psr->port_no; + } + + case OFP10_VERSION: { + const struct ofp10_port_stats_request *psr = ofpmsg_body(request); + return ofputil_port_to_ofp11(ntohs(psr->port_no)); + } + + default: + NOT_REACHED(); + } +} diff --git a/lib/ofp-util.h b/lib/ofp-util.h index 4e9f946..f28d0a3 100644 --- a/lib/ofp-util.h +++ b/lib/ofp-util.h @@ -38,6 +38,8 @@ ovs_be32 ofputil_port_to_ofp11(uint16_t ofp10_port); enum ofperr ofputil_check_output_port(uint16_t ofp_port, int max_ports); uint16_t ofputil_port_from_string(const char *); void ofputil_format_port(uint16_t port, struct ds *); +enum ofperr ofputil_format_raw_port(enum ofp_version ofp_version, + ovs_be32 ofp11_port, struct ds *s); /* Converting OFPFW10_NW_SRC_MASK and OFPFW10_NW_DST_MASK wildcard bit counts * to and from IP bitmasks. */ @@ -623,4 +625,12 @@ 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); +enum ofperr ofputil_append_port_stat(struct list *replies, + const struct ofp11_port_stats *ops); +struct ofp11_port_stats * +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); #endif /* ofp-util.h */ diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 47cf22b..cf7be02 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -2293,31 +2293,38 @@ handle_table_stats_request(struct ofconn *ofconn, } static void +collate_port_stat(struct ofport *port, struct netdev_stats *stats, + struct ofp11_port_stats *ops) +{ + ops->port_no = ofputil_port_to_ofp11(port->pp.port_no); + memset(ops->pad, 0, sizeof ops->pad); + ops->rx_packets = htonll(stats->rx_packets); + ops->tx_packets = htonll(stats->tx_packets); + ops->rx_bytes = htonll(stats->rx_bytes); + ops->tx_bytes = htonll(stats->tx_bytes); + ops->rx_dropped = htonll(stats->rx_dropped); + ops->tx_dropped = htonll(stats->tx_dropped); + ops->rx_errors = htonll(stats->rx_errors); + ops->tx_errors = htonll(stats->tx_errors); + ops->rx_frame_err = htonll(stats->rx_frame_errors); + ops->rx_over_err = htonll(stats->rx_over_errors); + ops->rx_crc_err = htonll(stats->rx_crc_errors); + ops->collisions = htonll(stats->collisions); +} + +static void append_port_stat(struct ofport *port, struct list *replies) { struct netdev_stats stats; - struct ofp10_port_stats *ops; + struct ofp11_port_stats ops; /* 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); - 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)); + collate_port_stat(port, &stats, &ops); + assert(!ofputil_append_port_stat(replies, &ops)); } static enum ofperr @@ -2325,13 +2332,21 @@ 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; + ovs_be32 ofp11_port; + uint16_t port_no; + enum ofperr error; + + ofp11_port = ofptutil_decode_port_stats_request(request); + error = ofputil_port_from_ofp11(ofp11_port, &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); } diff --git a/tests/ofp-print.at b/tests/ofp-print.at index a8ace84..f214aa8 100644 --- a/tests/ofp-print.at +++ b/tests/ofp-print.at @@ -885,7 +885,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 \ @@ -895,7 +895,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 00 00 00 00 00 00 \ +"], [0], [dnl +OFPST_PORT request (OF1.1) (xid=0x2): port_no=4294901760 +]) +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 00 00 00 00 00 00 \ +"], [0], [dnl +OFPST_PORT request (OF1.2) (xid=0x2): port_no=4294901760 +]) +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 \ @@ -938,6 +958,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 4294967294: 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 "\ diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index dea8878..0bfdd02 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -1414,17 +1414,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 = ofputlil_dump_ports(vconn_get_version(vconn), port); dump_stats_transaction(vconn, request); vconn_close(vconn); } -- 1.7.10.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev