From patchwork Sat Jun 16 00:06:56 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 930285 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ovn.org Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 416yN05jkdz9s01 for ; Sat, 16 Jun 2018 10:07:12 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 94F1FCE8; Sat, 16 Jun 2018 00:07:09 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 3F957CE4 for ; Sat, 16 Jun 2018 00:07:08 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 8A67E680 for ; Sat, 16 Jun 2018 00:07:03 +0000 (UTC) X-Originating-IP: 208.91.3.26 Received: from sigabrt.benpfaff.org (unknown [208.91.3.26]) (Authenticated sender: blp@ovn.org) by relay8-d.mail.gandi.net (Postfix) with ESMTPSA id F38741BF207; Sat, 16 Jun 2018 00:07:07 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Fri, 15 Jun 2018 17:06:56 -0700 Message-Id: <20180616000656.3862-1-blp@ovn.org> X-Mailer: git-send-email 2.16.1 X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: Ben Pfaff Subject: [ovs-dev] [PATCH v2] ofp-print: Move significant formatting code into more specific .c files. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Signed-off-by: Ben Pfaff --- v1->v2: Rebase due to changes on master. include/openvswitch/ofp-bundle.h | 11 +- include/openvswitch/ofp-connection.h | 18 +- include/openvswitch/ofp-ipfix.h | 5 + include/openvswitch/ofp-match.h | 9 +- include/openvswitch/ofp-meter.h | 12 + include/openvswitch/ofp-monitor.h | 4 + include/openvswitch/ofp-port.h | 3 + include/openvswitch/ofp-queue.h | 14 + include/openvswitch/ofp-table.h | 6 + lib/ofp-bundle.c | 70 +++ lib/ofp-connection.c | 197 +++++++ lib/ofp-ipfix.c | 51 ++ lib/ofp-match.c | 59 +++ lib/ofp-meter.c | 178 +++++++ lib/ofp-monitor.c | 27 + lib/ofp-port.c | 145 ++++++ lib/ofp-print.c | 976 ++--------------------------------- lib/ofp-queue.c | 196 +++++++ lib/ofp-table.c | 35 ++ 19 files changed, 1080 insertions(+), 936 deletions(-) diff --git a/include/openvswitch/ofp-bundle.h b/include/openvswitch/ofp-bundle.h index 78a44d6f0088..b4c29c0d9c43 100644 --- a/include/openvswitch/ofp-bundle.h +++ b/include/openvswitch/ofp-bundle.h @@ -36,9 +36,11 @@ struct ofputil_bundle_ctrl_msg { enum ofperr ofputil_decode_bundle_ctrl(const struct ofp_header *, struct ofputil_bundle_ctrl_msg *); - struct ofpbuf *ofputil_encode_bundle_ctrl_request( enum ofp_version, struct ofputil_bundle_ctrl_msg *); +void ofputil_format_bundle_ctrl_request( + struct ds *, const struct ofputil_bundle_ctrl_msg *); + struct ofpbuf *ofputil_encode_bundle_ctrl_reply( const struct ofp_header *, struct ofputil_bundle_ctrl_msg *); @@ -51,10 +53,15 @@ struct ofputil_bundle_add_msg { struct ofpbuf *ofputil_encode_bundle_add(enum ofp_version, struct ofputil_bundle_add_msg *); - enum ofperr ofputil_decode_bundle_add(const struct ofp_header *, struct ofputil_bundle_add_msg *, enum ofptype *); +void ofputil_format_bundle_add(struct ds *, + const struct ofputil_bundle_add_msg *, + const struct ofputil_port_map *, + const struct ofputil_table_map *, + int verbosity); + /* Bundle message as produced by ofp-parse. */ struct ofputil_bundle_msg { diff --git a/include/openvswitch/ofp-connection.h b/include/openvswitch/ofp-connection.h index 540ce9ed9b21..5fb143157d23 100644 --- a/include/openvswitch/ofp-connection.h +++ b/include/openvswitch/ofp-connection.h @@ -31,22 +31,26 @@ struct ofputil_role_request { uint64_t generation_id; }; +enum ofperr ofputil_decode_role_message(const struct ofp_header *, + struct ofputil_role_request *); +void ofputil_format_role_message(struct ds *, + const struct ofputil_role_request *); +struct ofpbuf *ofputil_encode_role_reply(const struct ofp_header *, + const struct ofputil_role_request *); + +/* Abstract OFPT_ROLE_STATUS. */ struct ofputil_role_status { enum ofp12_controller_role role; enum ofp14_controller_role_reason reason; uint64_t generation_id; }; -enum ofperr ofputil_decode_role_message(const struct ofp_header *, - struct ofputil_role_request *); -struct ofpbuf *ofputil_encode_role_reply(const struct ofp_header *, - const struct ofputil_role_request *); - struct ofpbuf *ofputil_encode_role_status(const struct ofputil_role_status *, enum ofputil_protocol); - enum ofperr ofputil_decode_role_status(const struct ofp_header *, struct ofputil_role_status *); +void ofputil_format_role_status(struct ds *, + const struct ofputil_role_status *); enum ofputil_async_msg_type { /* Standard asynchronous messages. */ @@ -79,6 +83,8 @@ struct ofpbuf *ofputil_encode_get_async_reply( const struct ofp_header *, const struct ofputil_async_cfg *); struct ofpbuf *ofputil_encode_set_async_config( const struct ofputil_async_cfg *, uint32_t oams, enum ofp_version); +void ofputil_format_set_async_config(struct ds *, + const struct ofputil_async_cfg *); struct ofputil_async_cfg ofputil_async_cfg_default(enum ofp_version); diff --git a/include/openvswitch/ofp-ipfix.h b/include/openvswitch/ofp-ipfix.h index 75eefc005877..34ff2b9b20bf 100644 --- a/include/openvswitch/ofp-ipfix.h +++ b/include/openvswitch/ofp-ipfix.h @@ -19,6 +19,7 @@ #include "openflow/openflow.h" +struct ds; struct ofpbuf; struct ovs_list; @@ -44,6 +45,10 @@ void ofputil_append_ipfix_stat(struct ovs_list *replies, const struct ofputil_ipfix_stats *); size_t ofputil_count_ipfix_stats(const struct ofp_header *); int ofputil_pull_ipfix_stats(struct ofputil_ipfix_stats *, struct ofpbuf *msg); +void ofputil_format_ipfix_stats_bridge(struct ds *, + const struct ofputil_ipfix_stats *); +void ofputil_format_ipfix_stats_flow(struct ds *, + const struct ofputil_ipfix_stats *); #ifdef __cplusplus } diff --git a/include/openvswitch/ofp-match.h b/include/openvswitch/ofp-match.h index 6ed373e2bf4d..f279d46611f9 100644 --- a/include/openvswitch/ofp-match.h +++ b/include/openvswitch/ofp-match.h @@ -79,9 +79,12 @@ struct ofputil_tlv_table_reply { }; struct ofpbuf *ofputil_encode_tlv_table_mod(enum ofp_version ofp_version, - struct ofputil_tlv_table_mod *); -enum ofperr ofputil_decode_tlv_table_mod(const struct ofp_header *, struct ofputil_tlv_table_mod *); +enum ofperr ofputil_decode_tlv_table_mod(const struct ofp_header *, + struct ofputil_tlv_table_mod *); +void ofputil_format_tlv_table_mod(struct ds *, + const struct ofputil_tlv_table_mod *); + struct ofpbuf *ofputil_encode_tlv_table_reply( const struct ofp_header *, struct ofputil_tlv_table_reply *); enum ofperr ofputil_decode_tlv_table_reply( @@ -90,6 +93,8 @@ char *parse_ofp_tlv_table_mod_str(struct ofputil_tlv_table_mod *, uint16_t command, const char *string, enum ofputil_protocol *usable_protocols) OVS_WARN_UNUSED_RESULT; +void ofputil_format_tlv_table_reply(struct ds *, + const struct ofputil_tlv_table_reply *); void ofputil_uninit_tlv_table(struct ovs_list *mappings); diff --git a/include/openvswitch/ofp-meter.h b/include/openvswitch/ofp-meter.h index 18267a6fa260..6776eae87e26 100644 --- a/include/openvswitch/ofp-meter.h +++ b/include/openvswitch/ofp-meter.h @@ -30,6 +30,8 @@ extern "C" { /* Type for meter_id in ofproto provider interface, UINT32_MAX if invalid. */ typedef struct { uint32_t uint32; } ofproto_meter_id; +void ofputil_format_meter_id(struct ds *s, uint32_t meter_id, char separator); + /* Meter band configuration for all supported band types. */ struct ofputil_meter_band { uint16_t type; @@ -38,6 +40,9 @@ struct ofputil_meter_band { uint32_t burst_size; }; +void ofputil_format_meter_band(struct ds *, enum ofp13_meter_flags, + const struct ofputil_meter_band *); + struct ofputil_meter_band_stats { uint64_t packet_count; uint64_t byte_count; @@ -55,6 +60,8 @@ void ofputil_append_meter_config(struct ovs_list *replies, int ofputil_decode_meter_config(struct ofpbuf *, struct ofputil_meter_config *, struct ofpbuf *bands); +void ofputil_format_meter_config(struct ds *, + const struct ofputil_meter_config *); struct ofputil_meter_mod { uint16_t command; @@ -70,6 +77,7 @@ char *parse_ofp_meter_mod_str(struct ofputil_meter_mod *, const char *string, int command, enum ofputil_protocol *usable_protocols) OVS_WARN_UNUSED_RESULT; +void ofputil_format_meter_mod(struct ds *, const struct ofputil_meter_mod *); struct ofputil_meter_stats { uint32_t meter_id; @@ -87,6 +95,8 @@ void ofputil_append_meter_stats(struct ovs_list *replies, int ofputil_decode_meter_stats(struct ofpbuf *, struct ofputil_meter_stats *, struct ofpbuf *bands); +void ofputil_format_meter_stats(struct ds *, + const struct ofputil_meter_stats *); struct ofputil_meter_features { uint32_t max_meters; /* Maximum number of meters. */ @@ -102,6 +112,8 @@ struct ofpbuf *ofputil_encode_meter_features_reply(const struct ofputil_meter_features *, const struct ofp_header * request); +void ofputil_format_meter_features(struct ds *, + const struct ofputil_meter_features *); enum ofputil_meter_request_type { OFPUTIL_METER_FEATURES, diff --git a/include/openvswitch/ofp-monitor.h b/include/openvswitch/ofp-monitor.h index 47d0d0e89548..3edaeb53a16c 100644 --- a/include/openvswitch/ofp-monitor.h +++ b/include/openvswitch/ofp-monitor.h @@ -133,6 +133,10 @@ struct ofpbuf *ofputil_encode_requestforward( const struct ofputil_requestforward *, enum ofputil_protocol); enum ofperr ofputil_decode_requestforward(const struct ofp_header *, struct ofputil_requestforward *); +void ofputil_format_requestforward(struct ds *, enum ofp_version, + const struct ofputil_requestforward *, + const struct ofputil_port_map *, + const struct ofputil_table_map *); void ofputil_destroy_requestforward(struct ofputil_requestforward *); #ifdef __cplusplus diff --git a/include/openvswitch/ofp-port.h b/include/openvswitch/ofp-port.h index 4286ba19d693..f1f36bf9c08a 100644 --- a/include/openvswitch/ofp-port.h +++ b/include/openvswitch/ofp-port.h @@ -169,6 +169,9 @@ void ofputil_append_port_stat(struct ovs_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); +void ofputil_format_port_stats(struct ds *, const struct ofputil_port_stats *, + const struct ofputil_port_map *); + enum ofperr ofputil_decode_port_stats_request(const struct ofp_header *request, ofp_port_t *ofp10_port); diff --git a/include/openvswitch/ofp-queue.h b/include/openvswitch/ofp-queue.h index b0229685ba6d..51b98cda4cc7 100644 --- a/include/openvswitch/ofp-queue.h +++ b/include/openvswitch/ofp-queue.h @@ -19,7 +19,9 @@ #include "openflow/openflow.h" +struct ds; struct ofpbuf; +struct ofputil_port_map; struct ovs_list; #ifdef __cplusplus @@ -45,6 +47,8 @@ void ofputil_append_queue_get_config_reply( int ofputil_pull_queue_get_config_reply(struct ofpbuf *reply, struct ofputil_queue_config *); +enum ofperr ofputil_queue_get_config_reply_format( + struct ds *, const struct ofp_header *, const struct ofputil_port_map *); struct ofputil_queue_stats_request { ofp_port_t port_no; /* OFPP_ANY means "all ports". */ @@ -55,6 +59,9 @@ enum ofperr ofputil_decode_queue_stats_request( const struct ofp_header *, struct ofputil_queue_stats_request *); struct ofpbuf *ofputil_encode_queue_stats_request( enum ofp_version, const struct ofputil_queue_stats_request *); +enum ofperr ofputil_queue_stats_request_format( + struct ds *, const struct ofp_header *, + const struct ofputil_port_map *); struct ofputil_queue_stats { ofp_port_t port_no; @@ -74,6 +81,10 @@ size_t ofputil_count_queue_stats(const struct ofp_header *); int ofputil_decode_queue_stats(struct ofputil_queue_stats *, struct ofpbuf *); void ofputil_append_queue_stat(struct ovs_list *replies, const struct ofputil_queue_stats *); +enum ofperr ofputil_queue_stats_reply_format(struct ds *, + const struct ofp_header *, + const struct ofputil_port_map *, + int verbosity); /* Queue configuration request. */ struct ofpbuf *ofputil_encode_queue_get_config_request(enum ofp_version, @@ -82,6 +93,9 @@ struct ofpbuf *ofputil_encode_queue_get_config_request(enum ofp_version, enum ofperr ofputil_decode_queue_get_config_request(const struct ofp_header *, ofp_port_t *port, uint32_t *queue); +enum ofperr ofputil_queue_get_config_request_format( + struct ds *, const struct ofp_header *, + const struct ofputil_port_map *); #ifdef __cplusplus } diff --git a/include/openvswitch/ofp-table.h b/include/openvswitch/ofp-table.h index e8260657f486..d06ccf5ce9e3 100644 --- a/include/openvswitch/ofp-table.h +++ b/include/openvswitch/ofp-table.h @@ -309,10 +309,16 @@ struct ofputil_table_status { struct ofputil_table_desc desc; /* New table config. */ }; +const char *ofp_table_reason_to_string(enum ofp14_table_reason, + char *reasonbuf, size_t bufsize); + enum ofperr ofputil_decode_table_status(const struct ofp_header *, struct ofputil_table_status *); struct ofpbuf *ofputil_encode_table_status(const struct ofputil_table_status *, enum ofputil_protocol); +void ofputil_format_table_status(struct ds *, + const struct ofputil_table_status *, + const struct ofputil_table_map *); #ifdef __cplusplus } diff --git a/lib/ofp-bundle.c b/lib/ofp-bundle.c index 8f07a30c51f7..0e9b46b2f224 100644 --- a/lib/ofp-bundle.c +++ b/lib/ofp-bundle.c @@ -19,6 +19,7 @@ #include #include #include "openvswitch/ofp-parse.h" +#include "openvswitch/ofp-print.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/vlog.h" #include "util.h" @@ -128,6 +129,57 @@ ofputil_encode_bundle_ctrl_request(enum ofp_version ofp_version, return request; } +static const char * +bundle_flags_to_name(uint32_t bit) +{ + switch (bit) { + case OFPBF_ATOMIC: + return "atomic"; + case OFPBF_ORDERED: + return "ordered"; + default: + return NULL; + } +} + +void +ofputil_format_bundle_ctrl_request(struct ds *s, + const struct ofputil_bundle_ctrl_msg *bctrl) +{ + ds_put_char(s, '\n'); + ds_put_format(s, " bundle_id=%#"PRIx32" type=", bctrl->bundle_id); + switch (bctrl->type) { + case OFPBCT_OPEN_REQUEST: + ds_put_cstr(s, "OPEN_REQUEST"); + break; + case OFPBCT_OPEN_REPLY: + ds_put_cstr(s, "OPEN_REPLY"); + break; + case OFPBCT_CLOSE_REQUEST: + ds_put_cstr(s, "CLOSE_REQUEST"); + break; + case OFPBCT_CLOSE_REPLY: + ds_put_cstr(s, "CLOSE_REPLY"); + break; + case OFPBCT_COMMIT_REQUEST: + ds_put_cstr(s, "COMMIT_REQUEST"); + break; + case OFPBCT_COMMIT_REPLY: + ds_put_cstr(s, "COMMIT_REPLY"); + break; + case OFPBCT_DISCARD_REQUEST: + ds_put_cstr(s, "DISCARD_REQUEST"); + break; + case OFPBCT_DISCARD_REPLY: + ds_put_cstr(s, "DISCARD_REPLY"); + break; + } + + ds_put_cstr(s, " flags="); + ofp_print_bit_names(s, bctrl->flags, bundle_flags_to_name, ' '); +} + + struct ofpbuf * ofputil_encode_bundle_ctrl_reply(const struct ofp_header *oh, struct ofputil_bundle_ctrl_msg *msg) @@ -430,3 +482,21 @@ parse_ofp_bundle_file(const char *file_name, } return NULL; } + +void +ofputil_format_bundle_add(struct ds *s, + const struct ofputil_bundle_add_msg *badd, + const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map, + int verbosity) +{ + ds_put_char(s, '\n'); + ds_put_format(s, " bundle_id=%#"PRIx32, badd->bundle_id); + ds_put_cstr(s, " flags="); + ofp_print_bit_names(s, badd->flags, bundle_flags_to_name, ' '); + + ds_put_char(s, '\n'); + char *msg = ofp_to_string(badd->msg, ntohs(badd->msg->length), port_map, + table_map, verbosity); + ds_put_and_free_cstr(s, msg); +} diff --git a/lib/ofp-connection.c b/lib/ofp-connection.c index 3e114ba77660..23b80ff39dc4 100644 --- a/lib/ofp-connection.c +++ b/lib/ofp-connection.c @@ -19,9 +19,13 @@ #include "byte-order.h" #include "openflow/nicira-ext.h" #include "openvswitch/ofp-errors.h" +#include "openvswitch/ofp-monitor.h" #include "openvswitch/ofp-msgs.h" +#include "openvswitch/ofp-packet.h" #include "openvswitch/ofp-prop.h" +#include "openvswitch/ofp-table.h" #include "openvswitch/ofpbuf.h" +#include "openvswitch/type-props.h" #include "openvswitch/vlog.h" #include "util.h" @@ -83,6 +87,43 @@ ofputil_decode_role_message(const struct ofp_header *oh, return 0; } +static void +format_role_generic(struct ds *string, enum ofp12_controller_role role, + uint64_t generation_id) +{ + ds_put_cstr(string, " role="); + + switch (role) { + case OFPCR12_ROLE_NOCHANGE: + ds_put_cstr(string, "nochange"); + break; + case OFPCR12_ROLE_EQUAL: + ds_put_cstr(string, "equal"); /* OF 1.2 wording */ + break; + case OFPCR12_ROLE_MASTER: + ds_put_cstr(string, "master"); + break; + case OFPCR12_ROLE_SLAVE: + ds_put_cstr(string, "slave"); + break; + default: + OVS_NOT_REACHED(); + } + + if (generation_id != UINT64_MAX) { + ds_put_format(string, " generation_id=%"PRIu64, generation_id); + } +} + +void +ofputil_format_role_message(struct ds *string, + const struct ofputil_role_request *rr) +{ + format_role_generic(string, rr->role, (rr->have_generation_id + ? rr->generation_id + : UINT64_MAX)); +} + /* Returns an encoded form of a role reply suitable for the "request" in a * buffer owned by the caller. */ struct ofpbuf * @@ -167,6 +208,31 @@ ofputil_decode_role_status(const struct ofp_header *oh, return 0; } + +void +ofputil_format_role_status(struct ds *string, + const struct ofputil_role_status *rs) +{ + format_role_generic(string, rs->role, rs->generation_id); + + ds_put_cstr(string, " reason="); + + switch (rs->reason) { + case OFPCRR_MASTER_REQUEST: + ds_put_cstr(string, "master_request"); + break; + case OFPCRR_CONFIG: + ds_put_cstr(string, "configuration_changed"); + break; + case OFPCRR_EXPERIMENTER: + ds_put_cstr(string, "experimenter_data_changed"); + break; + case OFPCRR_N_REASONS: + default: + ds_put_cstr(string, "(unknown)"); + break; + } +} const char * ofputil_async_msg_type_to_string(enum ofputil_async_msg_type type) @@ -493,6 +559,137 @@ ofputil_encode_set_async_config(const struct ofputil_async_cfg *ac, return request; } +/* Returns a string form of 'reason'. The return value is either a statically + * allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'. + * 'bufsize' should be at least OFP_PORT_REASON_BUFSIZE. */ +#define OFP_PORT_REASON_BUFSIZE (INT_STRLEN(int) + 1) +static const char * +ofp_port_reason_to_string(enum ofp_port_reason reason, + char *reasonbuf, size_t bufsize) +{ + switch (reason) { + case OFPPR_ADD: + return "add"; + + case OFPPR_DELETE: + return "delete"; + + case OFPPR_MODIFY: + return "modify"; + + case OFPPR_N_REASONS: + default: + snprintf(reasonbuf, bufsize, "%d", (int) reason); + return reasonbuf; + } +} + +/* Returns a string form of 'reason'. The return value is either a statically + * allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'. + * 'bufsize' should be at least OFP_ASYNC_CONFIG_REASON_BUFSIZE. */ +static const char* +ofp_role_reason_to_string(enum ofp14_controller_role_reason reason, + char *reasonbuf, size_t bufsize) +{ + switch (reason) { + case OFPCRR_MASTER_REQUEST: + return "master_request"; + + case OFPCRR_CONFIG: + return "configuration_changed"; + + case OFPCRR_EXPERIMENTER: + return "experimenter_data_changed"; + + case OFPCRR_N_REASONS: + default: + snprintf(reasonbuf, bufsize, "%d", (int) reason); + return reasonbuf; + } +} + +/* Returns a string form of 'reason'. The return value is either a statically + * allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'. + * 'bufsize' should be at least OFP_ASYNC_CONFIG_REASON_BUFSIZE. */ +static const char* +ofp_requestforward_reason_to_string(enum ofp14_requestforward_reason reason, + char *reasonbuf, size_t bufsize) +{ + switch (reason) { + case OFPRFR_GROUP_MOD: + return "group_mod_request"; + + case OFPRFR_METER_MOD: + return "meter_mod_request"; + + case OFPRFR_N_REASONS: + default: + snprintf(reasonbuf, bufsize, "%d", (int) reason); + return reasonbuf; + } +} + +static const char * +ofp_async_config_reason_to_string(uint32_t reason, + enum ofputil_async_msg_type type, + char *reasonbuf, size_t bufsize) +{ + switch (type) { + case OAM_PACKET_IN: + return ofputil_packet_in_reason_to_string(reason, reasonbuf, bufsize); + + case OAM_PORT_STATUS: + return ofp_port_reason_to_string(reason, reasonbuf, bufsize); + + case OAM_FLOW_REMOVED: + return ofp_flow_removed_reason_to_string(reason, reasonbuf, bufsize); + + case OAM_ROLE_STATUS: + return ofp_role_reason_to_string(reason, reasonbuf, bufsize); + + case OAM_TABLE_STATUS: + return ofp_table_reason_to_string(reason, reasonbuf, bufsize); + + case OAM_REQUESTFORWARD: + return ofp_requestforward_reason_to_string(reason, reasonbuf, bufsize); + + case OAM_N_TYPES: + default: + return "Unknown asynchronous configuration message type"; + } +} + +void +ofputil_format_set_async_config(struct ds *string, + const struct ofputil_async_cfg *ac) +{ + for (int i = 0; i < 2; i++) { + ds_put_format(string, "\n %s:\n", i == 0 ? "master" : "slave"); + for (uint32_t type = 0; type < OAM_N_TYPES; type++) { + ds_put_format(string, "%16s:", + ofputil_async_msg_type_to_string(type)); + + uint32_t role = i == 0 ? ac->master[type] : ac->slave[type]; + for (int j = 0; j < 32; j++) { + if (role & (1u << j)) { + char reasonbuf[INT_STRLEN(int) + 1]; + const char *reason; + + reason = ofp_async_config_reason_to_string( + j, type, reasonbuf, sizeof reasonbuf); + if (reason[0]) { + ds_put_format(string, " %s", reason); + } + } + } + if (!role) { + ds_put_cstr(string, " (off)"); + } + ds_put_char(string, '\n'); + } + } +} + struct ofputil_async_cfg ofputil_async_cfg_default(enum ofp_version version) { diff --git a/lib/ofp-ipfix.c b/lib/ofp-ipfix.c index d710b5a4b225..0ffc4d9365fc 100644 --- a/lib/ofp-ipfix.c +++ b/lib/ofp-ipfix.c @@ -109,3 +109,54 @@ ofputil_count_ipfix_stats(const struct ofp_header *oh) return b.size / sizeof(struct ofputil_ipfix_stats); } + +static void +print_ipfix_stat(struct ds *string, const char *leader, uint64_t stat, + int more) +{ + ds_put_cstr(string, leader); + if (stat != UINT64_MAX) { + ds_put_format(string, "%"PRIu64, stat); + } else { + ds_put_char(string, '?'); + } + if (more) { + ds_put_cstr(string, ", "); + } else { + ds_put_cstr(string, "\n"); + } +} + +static void +format_ipfix_stats(struct ds *string, const struct ofputil_ipfix_stats *is, + int indent) +{ + print_ipfix_stat(string, "flows=", is->total_flows, 1); + print_ipfix_stat(string, "current flows=", is->current_flows, 1); + print_ipfix_stat(string, "sampled pkts=", is->pkts, 1); + print_ipfix_stat(string, "ipv4 ok=", is->ipv4_pkts, 1); + print_ipfix_stat(string, "ipv6 ok=", is->ipv6_pkts, 1); + print_ipfix_stat(string, "tx pkts=", is->tx_pkts, 0); + ds_put_char_multiple(string, ' ', indent); + print_ipfix_stat(string, "pkts errs=", is->error_pkts, 1); + print_ipfix_stat(string, "ipv4 errs=", is->ipv4_error_pkts, 1); + print_ipfix_stat(string, "ipv6 errs=", is->ipv6_error_pkts, 1); + print_ipfix_stat(string, "tx errs=", is->tx_errors, 0); +} + +void +ofputil_format_ipfix_stats_bridge(struct ds *string, + const struct ofputil_ipfix_stats *is) +{ + ds_put_cstr(string, "\n bridge ipfix: "); + format_ipfix_stats(string, is, 16); +} + +void +ofputil_format_ipfix_stats_flow(struct ds *string, + const struct ofputil_ipfix_stats *is) +{ + ds_put_cstr(string, " id"); + ds_put_format(string, " %3"PRIuSIZE": ", (size_t) is->collector_set_id); + format_ipfix_stats(string, is, 10); +} diff --git a/lib/ofp-match.c b/lib/ofp-match.c index 3a46b397885f..e83fa9086b8d 100644 --- a/lib/ofp-match.c +++ b/lib/ofp-match.c @@ -724,6 +724,46 @@ ofputil_decode_tlv_table_mod(const struct ofp_header *oh, &ttm->mappings); } +static void +print_tlv_table(struct ds *s, const struct ovs_list *mappings) +{ + struct ofputil_tlv_map *map; + + ds_put_cstr(s, " mapping table:\n"); + ds_put_cstr(s, " class type length match field\n"); + ds_put_cstr(s, " ------ ---- ------ --------------"); + + LIST_FOR_EACH (map, list_node, mappings) { + ds_put_format(s, "\n %#6"PRIx16" %#4"PRIx8" %6"PRIu8" " + "tun_metadata%"PRIu16, + map->option_class, map->option_type, map->option_len, + map->index); + } +} + +void +ofputil_format_tlv_table_mod(struct ds *s, + const struct ofputil_tlv_table_mod *ttm) +{ + ds_put_cstr(s, "\n "); + + switch (ttm->command) { + case NXTTMC_ADD: + ds_put_cstr(s, "ADD"); + break; + case NXTTMC_DELETE: + ds_put_cstr(s, "DEL"); + break; + case NXTTMC_CLEAR: + ds_put_cstr(s, "CLEAR"); + break; + } + + if (ttm->command != NXTTMC_CLEAR) { + print_tlv_table(s, &ttm->mappings); + } +} + struct ofpbuf * ofputil_encode_tlv_table_reply(const struct ofp_header *oh, struct ofputil_tlv_table_reply *ttr) @@ -795,6 +835,25 @@ parse_ofp_tlv_table_mod_str(struct ofputil_tlv_table_mod *ttm, return NULL; } +void +ofputil_format_tlv_table_reply(struct ds *s, + const struct ofputil_tlv_table_reply *ttr) +{ + ds_put_char(s, '\n'); + + const struct ofputil_tlv_map *map; + int allocated_space = 0; + LIST_FOR_EACH (map, list_node, &ttr->mappings) { + allocated_space += map->option_len; + } + + ds_put_format(s, " max option space=%"PRIu32" max fields=%"PRIu16"\n", + ttr->max_option_space, ttr->max_fields); + ds_put_format(s, " allocated option space=%d\n", allocated_space); + ds_put_char(s, '\n'); + print_tlv_table(s, &ttr->mappings); +} + void ofputil_uninit_tlv_table(struct ovs_list *mappings) { diff --git a/lib/ofp-meter.c b/lib/ofp-meter.c index 4f77f508d396..6395c0daa4ae 100644 --- a/lib/ofp-meter.c +++ b/lib/ofp-meter.c @@ -21,6 +21,7 @@ #include "openvswitch/ofp-errors.h" #include "openvswitch/ofp-msgs.h" #include "openvswitch/ofp-parse.h" +#include "openvswitch/ofp-print.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/vlog.h" @@ -28,6 +29,56 @@ VLOG_DEFINE_THIS_MODULE(ofp_meter); static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); +void +ofputil_format_meter_id(struct ds *s, uint32_t meter_id, char separator) +{ + if (meter_id <= OFPM13_MAX) { + ds_put_format(s, "meter%c%"PRIu32, separator, meter_id); + } else { + const char *name; + switch (meter_id) { + case OFPM13_SLOWPATH: + name = "slowpath"; + break; + case OFPM13_CONTROLLER: + name = "controller"; + break; + case OFPM13_ALL: + name = "all"; + break; + default: + name = "unknown"; + } + ds_put_format(s, "meter%c%s", separator, name); + } +} + +void +ofputil_format_meter_band(struct ds *s, enum ofp13_meter_flags flags, + const struct ofputil_meter_band *mb) +{ + ds_put_cstr(s, "\ntype="); + switch (mb->type) { + case OFPMBT13_DROP: + ds_put_cstr(s, "drop"); + break; + case OFPMBT13_DSCP_REMARK: + ds_put_cstr(s, "dscp_remark"); + break; + default: + ds_put_format(s, "%u", mb->type); + } + + ds_put_format(s, " rate=%"PRIu32, mb->rate); + + if (flags & OFPMF13_BURST) { + ds_put_format(s, " burst_size=%"PRIu32, mb->burst_size); + } + if (mb->type == OFPMBT13_DSCP_REMARK) { + ds_put_format(s, " prec_level=%"PRIu8, mb->prec_level); + } +} + static enum ofperr ofputil_pull_bands(struct ofpbuf *msg, size_t len, uint16_t *n_bands, struct ofpbuf *bands) @@ -268,6 +319,46 @@ ofputil_decode_meter_config(struct ofpbuf *msg, return 0; } +static void +ofp_print_meter_flags(struct ds *s, enum ofp13_meter_flags flags) +{ + if (flags & OFPMF13_KBPS) { + ds_put_cstr(s, "kbps "); + } + if (flags & OFPMF13_PKTPS) { + ds_put_cstr(s, "pktps "); + } + if (flags & OFPMF13_BURST) { + ds_put_cstr(s, "burst "); + } + if (flags & OFPMF13_STATS) { + ds_put_cstr(s, "stats "); + } + + flags &= ~(OFPMF13_KBPS | OFPMF13_PKTPS | OFPMF13_BURST | OFPMF13_STATS); + if (flags) { + ds_put_format(s, "flags:0x%"PRIx16" ", flags); + } +} + +void +ofputil_format_meter_config(struct ds *s, + const struct ofputil_meter_config *mc) +{ + uint16_t i; + + ofputil_format_meter_id(s, mc->meter_id, '='); + ds_put_char(s, ' '); + + ofp_print_meter_flags(s, mc->flags); + + ds_put_cstr(s, "bands="); + for (i = 0; i < mc->n_bands; ++i) { + ofputil_format_meter_band(s, mc->flags, &mc->bands[i]); + } + ds_put_char(s, '\n'); +} + static enum ofperr ofputil_pull_band_stats(struct ofpbuf *msg, size_t len, uint16_t *n_bands, struct ofpbuf *bands) @@ -347,6 +438,28 @@ ofputil_decode_meter_stats(struct ofpbuf *msg, return 0; } +void +ofputil_format_meter_stats(struct ds *s, const struct ofputil_meter_stats *ms) +{ + uint16_t i; + + ofputil_format_meter_id(s, ms->meter_id, ':'); + ds_put_char(s, ' '); + ds_put_format(s, "flow_count:%"PRIu32" ", ms->flow_count); + ds_put_format(s, "packet_in_count:%"PRIu64" ", ms->packet_in_count); + ds_put_format(s, "byte_in_count:%"PRIu64" ", ms->byte_in_count); + ds_put_cstr(s, "duration:"); + ofp_print_duration(s, ms->duration_sec, ms->duration_nsec); + ds_put_char(s, ' '); + + ds_put_cstr(s, "bands:\n"); + for (i = 0; i < ms->n_bands; ++i) { + ds_put_format(s, "%d: ", i); + ds_put_format(s, "packet_count:%"PRIu64" ", ms->bands[i].packet_count); + ds_put_format(s, "byte_count:%"PRIu64"\n", ms->bands[i].byte_count); + } +} + void ofputil_decode_meter_features(const struct ofp_header *oh, struct ofputil_meter_features *mf) @@ -379,6 +492,51 @@ ofputil_encode_meter_features_reply(const struct ofputil_meter_features *mf, return reply; } +static const char * +ofputil_meter_band_types_to_name(uint32_t bit) +{ + switch (bit) { + case 1 << OFPMBT13_DROP: return "drop"; + case 1 << OFPMBT13_DSCP_REMARK: return "dscp_remark"; + } + + return NULL; +} + +static const char * +ofputil_meter_capabilities_to_name(uint32_t bit) +{ + enum ofp13_meter_flags flag = bit; + + switch (flag) { + case OFPMF13_KBPS: return "kbps"; + case OFPMF13_PKTPS: return "pktps"; + case OFPMF13_BURST: return "burst"; + case OFPMF13_STATS: return "stats"; + } + + return NULL; +} + +void +ofputil_format_meter_features(struct ds *s, + const struct ofputil_meter_features *mf) +{ + ds_put_format(s, "\nmax_meter:%"PRIu32, mf->max_meters); + ds_put_format(s, " max_bands:%"PRIu8, mf->max_bands); + ds_put_format(s, " max_color:%"PRIu8"\n", mf->max_color); + + ds_put_cstr(s, "band_types: "); + ofp_print_bit_names(s, mf->band_types, + ofputil_meter_band_types_to_name, ' '); + ds_put_char(s, '\n'); + + ds_put_cstr(s, "capabilities: "); + ofp_print_bit_names(s, mf->capabilities, + ofputil_meter_capabilities_to_name, ' '); + ds_put_char(s, '\n'); +} + struct ofpbuf * ofputil_encode_meter_mod(enum ofp_version ofp_version, const struct ofputil_meter_mod *mm) @@ -628,3 +786,23 @@ parse_ofp_meter_mod_str(struct ofputil_meter_mod *mm, const char *str_, return error; } + +void +ofputil_format_meter_mod(struct ds *s, const struct ofputil_meter_mod *mm) +{ + switch (mm->command) { + case OFPMC13_ADD: + ds_put_cstr(s, " ADD "); + break; + case OFPMC13_MODIFY: + ds_put_cstr(s, " MOD "); + break; + case OFPMC13_DELETE: + ds_put_cstr(s, " DEL "); + break; + default: + ds_put_format(s, " cmd:%d ", mm->command); + } + + ofputil_format_meter_config(s, &mm->meter); +} diff --git a/lib/ofp-monitor.c b/lib/ofp-monitor.c index 3d117cae8d11..3e02834a26a0 100644 --- a/lib/ofp-monitor.c +++ b/lib/ofp-monitor.c @@ -880,6 +880,33 @@ ofputil_decode_requestforward(const struct ofp_header *outer, return 0; } +void +ofputil_format_requestforward(struct ds *string, + enum ofp_version ofp_version, + const struct ofputil_requestforward *rf, + const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map) +{ + ds_put_cstr(string, " reason="); + + switch (rf->reason) { + case OFPRFR_GROUP_MOD: + ds_put_cstr(string, "group_mod"); + ofputil_group_mod_format__(string, ofp_version, rf->group_mod, + port_map, table_map); + break; + + case OFPRFR_METER_MOD: + ds_put_cstr(string, "meter_mod"); + ofputil_format_meter_mod(string, rf->meter_mod); + break; + + case OFPRFR_N_REASONS: + OVS_NOT_REACHED(); + } +} + + /* Frees the content of 'rf', which should have been initialized through a * successful call to ofputil_decode_requestforward(). */ void diff --git a/lib/ofp-port.c b/lib/ofp-port.c index 4d39299ed7f5..eb5b910293b1 100644 --- a/lib/ofp-port.c +++ b/lib/ofp-port.c @@ -1815,6 +1815,151 @@ ofputil_decode_port_stats(struct ofputil_port_stats *ps, struct ofpbuf *msg) return OFPERR_OFPBRC_BAD_LEN; } +static void +print_port_stat(struct ds *string, const char *leader, uint64_t stat, int more) +{ + ds_put_cstr(string, leader); + if (stat != UINT64_MAX) { + ds_put_format(string, "%"PRIu64, stat); + } else { + ds_put_char(string, '?'); + } + if (more) { + ds_put_cstr(string, ", "); + } else { + ds_put_cstr(string, "\n"); + } +} + +static void +print_port_stat_cond(struct ds *string, const char *leader, uint64_t stat) +{ + if (stat != UINT64_MAX) { + ds_put_format(string, "%s%"PRIu64", ", leader, stat); + } +} + +void +ofputil_format_port_stats(struct ds *string, + const struct ofputil_port_stats *ps, + const struct ofputil_port_map *port_map) +{ + ds_put_cstr(string, " port "); + if (ofp_to_u16(ps->port_no) < 10) { + ds_put_char(string, ' '); + } + ofputil_format_port(ps->port_no, port_map, string); + + 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->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); + + if (ps->duration_sec != UINT32_MAX) { + ds_put_cstr(string, " duration="); + ofp_print_duration(string, ps->duration_sec, ps->duration_nsec); + ds_put_char(string, '\n'); + } + struct ds string_ext_stats = DS_EMPTY_INITIALIZER; + + ds_init(&string_ext_stats); + + print_port_stat_cond(&string_ext_stats, "1_to_64_packets=", + ps->stats.rx_1_to_64_packets); + print_port_stat_cond(&string_ext_stats, "65_to_127_packets=", + ps->stats.rx_65_to_127_packets); + print_port_stat_cond(&string_ext_stats, "128_to_255_packets=", + ps->stats.rx_128_to_255_packets); + print_port_stat_cond(&string_ext_stats, "256_to_511_packets=", + ps->stats.rx_256_to_511_packets); + print_port_stat_cond(&string_ext_stats, "512_to_1023_packets=", + ps->stats.rx_512_to_1023_packets); + print_port_stat_cond(&string_ext_stats, "1024_to_1522_packets=", + ps->stats.rx_1024_to_1522_packets); + print_port_stat_cond(&string_ext_stats, "1523_to_max_packets=", + ps->stats.rx_1523_to_max_packets); + print_port_stat_cond(&string_ext_stats, "broadcast_packets=", + ps->stats.rx_broadcast_packets); + print_port_stat_cond(&string_ext_stats, "undersized_errors=", + ps->stats.rx_undersized_errors); + print_port_stat_cond(&string_ext_stats, "oversize_errors=", + ps->stats.rx_oversize_errors); + print_port_stat_cond(&string_ext_stats, "rx_fragmented_errors=", + ps->stats.rx_fragmented_errors); + print_port_stat_cond(&string_ext_stats, "rx_jabber_errors=", + ps->stats.rx_jabber_errors); + + if (string_ext_stats.length != 0) { + /* If at least one statistics counter is reported: */ + ds_put_cstr(string, " rx rfc2819 "); + ds_put_buffer(string, string_ext_stats.string, + string_ext_stats.length); + ds_put_cstr(string, "\n"); + ds_destroy(&string_ext_stats); + } + + ds_init(&string_ext_stats); + + print_port_stat_cond(&string_ext_stats, "1_to_64_packets=", + ps->stats.tx_1_to_64_packets); + print_port_stat_cond(&string_ext_stats, "65_to_127_packets=", + ps->stats.tx_65_to_127_packets); + print_port_stat_cond(&string_ext_stats, "128_to_255_packets=", + ps->stats.tx_128_to_255_packets); + print_port_stat_cond(&string_ext_stats, "256_to_511_packets=", + ps->stats.tx_256_to_511_packets); + print_port_stat_cond(&string_ext_stats, "512_to_1023_packets=", + ps->stats.tx_512_to_1023_packets); + print_port_stat_cond(&string_ext_stats, "1024_to_1522_packets=", + ps->stats.tx_1024_to_1522_packets); + print_port_stat_cond(&string_ext_stats, "1523_to_max_packets=", + ps->stats.tx_1523_to_max_packets); + print_port_stat_cond(&string_ext_stats, "multicast_packets=", + ps->stats.tx_multicast_packets); + print_port_stat_cond(&string_ext_stats, "broadcast_packets=", + ps->stats.tx_broadcast_packets); + + if (string_ext_stats.length != 0) { + /* If at least one statistics counter is reported: */ + ds_put_cstr(string, " tx rfc2819 "); + ds_put_buffer(string, string_ext_stats.string, + string_ext_stats.length); + ds_put_cstr(string, "\n"); + ds_destroy(&string_ext_stats); + } + + if (ps->custom_stats.size) { + ds_put_cstr(string, " CUSTOM Statistics"); + for (int i = 0; i < ps->custom_stats.size; i++) { + /* 3 counters in the row */ + if (ps->custom_stats.counters[i].name[0]) { + if (i % 3 == 0) { + ds_put_cstr(string, "\n"); + ds_put_cstr(string, " "); + } else { + ds_put_char(string, ' '); + } + ds_put_format(string, "%s=%"PRIu64",", + ps->custom_stats.counters[i].name, + ps->custom_stats.counters[i].value); + } + } + ds_put_cstr(string, "\n"); + } +} + + /* 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. */ diff --git a/lib/ofp-print.c b/lib/ofp-print.c index 05a39c22bd0d..cf93d2e2cb38 100644 --- a/lib/ofp-print.c +++ b/lib/ofp-print.c @@ -64,7 +64,6 @@ #include "util.h" #include "uuid.h" -static void ofp_print_queue_name(struct ds *string, uint32_t port); static void ofp_print_error(struct ds *, enum ofperr); /* Returns a string that represents the contents of the Ethernet frame in the @@ -320,256 +319,11 @@ ofp_print_table_status_message(struct ds *string, const struct ofp_header *oh, const struct ofputil_table_map *table_map) { struct ofputil_table_status ts; - enum ofperr error; - - error = ofputil_decode_table_status(oh, &ts); - if (error) { - return error; - } - - if (ts.reason == OFPTR_VACANCY_DOWN) { - ds_put_format(string, " reason=VACANCY_DOWN"); - } else if (ts.reason == OFPTR_VACANCY_UP) { - ds_put_format(string, " reason=VACANCY_UP"); - } - - ds_put_format(string, "\ntable_desc:-"); - ofputil_table_desc_format(string, &ts.desc, table_map); - - return 0; -} - -static enum ofperr -ofp_print_queue_get_config_request(struct ds *string, - const struct ofp_header *oh, - const struct ofputil_port_map *port_map) -{ - enum ofperr error; - ofp_port_t port; - uint32_t queue; - - error = ofputil_decode_queue_get_config_request(oh, &port, &queue); - if (error) { - return error; - } - - ds_put_cstr(string, " port="); - ofputil_format_port(port, port_map, string); - - if (queue != OFPQ_ALL) { - ds_put_cstr(string, " queue="); - ofp_print_queue_name(string, queue); - } - - return 0; -} - -static void -print_queue_rate(struct ds *string, const char *name, unsigned int rate) -{ - if (rate <= 1000) { - ds_put_format(string, " %s:%u.%u%%", name, rate / 10, rate % 10); - } else if (rate < UINT16_MAX) { - ds_put_format(string, " %s:(disabled)", name); - } -} - -/* qsort comparison function. */ -static int -compare_queues(const void *a_, const void *b_) -{ - const struct ofputil_queue_config *a = a_; - const struct ofputil_queue_config *b = b_; - - uint16_t ap = ofp_to_u16(a->port); - uint16_t bp = ofp_to_u16(b->port); - if (ap != bp) { - return ap < bp ? -1 : 1; - } - - uint32_t aq = a->queue; - uint32_t bq = b->queue; - return aq < bq ? -1 : aq > bq; -} - -static enum ofperr -ofp_print_queue_get_config_reply(struct ds *string, - const struct ofp_header *oh, - const struct ofputil_port_map *port_map) -{ - struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); - - struct ofputil_queue_config *queues = NULL; - size_t allocated_queues = 0; - size_t n = 0; - - int retval = 0; - for (;;) { - if (n >= allocated_queues) { - queues = x2nrealloc(queues, &allocated_queues, sizeof *queues); - } - retval = ofputil_pull_queue_get_config_reply(&b, &queues[n]); - if (retval) { - break; - } - n++; - } - - qsort(queues, n, sizeof *queues, compare_queues); - - ds_put_char(string, ' '); - - ofp_port_t port = 0; - for (const struct ofputil_queue_config *q = queues; q < &queues[n]; q++) { - if (q->port != port) { - port = q->port; - - ds_put_cstr(string, "port="); - ofputil_format_port(port, port_map, string); - ds_put_char(string, '\n'); - } - - ds_put_format(string, "queue %"PRIu32":", q->queue); - print_queue_rate(string, "min_rate", q->min_rate); - print_queue_rate(string, "max_rate", q->max_rate); - ds_put_char(string, '\n'); - } - - ds_chomp(string, ' '); - free(queues); - - return retval != EOF ? retval : 0; -} - -static void -ofp_print_meter_flags(struct ds *s, uint16_t flags) -{ - if (flags & OFPMF13_KBPS) { - ds_put_cstr(s, "kbps "); - } - if (flags & OFPMF13_PKTPS) { - ds_put_cstr(s, "pktps "); - } - if (flags & OFPMF13_BURST) { - ds_put_cstr(s, "burst "); - } - if (flags & OFPMF13_STATS) { - ds_put_cstr(s, "stats "); - } - - flags &= ~(OFPMF13_KBPS | OFPMF13_PKTPS | OFPMF13_BURST | OFPMF13_STATS); - if (flags) { - ds_put_format(s, "flags:0x%"PRIx16" ", flags); - } -} - -static void -ofp_print_meter_band(struct ds *s, uint16_t flags, - const struct ofputil_meter_band *mb) -{ - ds_put_cstr(s, "\ntype="); - switch (mb->type) { - case OFPMBT13_DROP: - ds_put_cstr(s, "drop"); - break; - case OFPMBT13_DSCP_REMARK: - ds_put_cstr(s, "dscp_remark"); - break; - default: - ds_put_format(s, "%u", mb->type); - } - - ds_put_format(s, " rate=%"PRIu32, mb->rate); - - if (flags & OFPMF13_BURST) { - ds_put_format(s, " burst_size=%"PRIu32, mb->burst_size); - } - if (mb->type == OFPMBT13_DSCP_REMARK) { - ds_put_format(s, " prec_level=%"PRIu8, mb->prec_level); - } -} - -static void -ofp_print_meter_id(struct ds *s, uint32_t meter_id, char seperator) -{ - if (meter_id <= OFPM13_MAX) { - ds_put_format(s, "meter%c%"PRIu32, seperator, meter_id); - } else { - const char *name; - switch (meter_id) { - case OFPM13_SLOWPATH: - name = "slowpath"; - break; - case OFPM13_CONTROLLER: - name = "controller"; - break; - case OFPM13_ALL: - name = "all"; - break; - default: - name = "unknown"; - } - ds_put_format(s, "meter%c%s", seperator, name); - } -} - -static void -ofp_print_meter_stats(struct ds *s, const struct ofputil_meter_stats *ms) -{ - uint16_t i; - - ofp_print_meter_id(s, ms->meter_id, ':'); - ds_put_char(s, ' '); - ds_put_format(s, "flow_count:%"PRIu32" ", ms->flow_count); - ds_put_format(s, "packet_in_count:%"PRIu64" ", ms->packet_in_count); - ds_put_format(s, "byte_in_count:%"PRIu64" ", ms->byte_in_count); - ds_put_cstr(s, "duration:"); - ofp_print_duration(s, ms->duration_sec, ms->duration_nsec); - ds_put_char(s, ' '); - - ds_put_cstr(s, "bands:\n"); - for (i = 0; i < ms->n_bands; ++i) { - ds_put_format(s, "%d: ", i); - ds_put_format(s, "packet_count:%"PRIu64" ", ms->bands[i].packet_count); - ds_put_format(s, "byte_count:%"PRIu64"\n", ms->bands[i].byte_count); - } -} - -static void -ofp_print_meter_config(struct ds *s, const struct ofputil_meter_config *mc) -{ - uint16_t i; - - ofp_print_meter_id(s, mc->meter_id, '='); - ds_put_char(s, ' '); - - ofp_print_meter_flags(s, mc->flags); - - ds_put_cstr(s, "bands="); - for (i = 0; i < mc->n_bands; ++i) { - ofp_print_meter_band(s, mc->flags, &mc->bands[i]); - } - ds_put_char(s, '\n'); -} - -static void -ofp_print_meter_mod__(struct ds *s, const struct ofputil_meter_mod *mm) -{ - switch (mm->command) { - case OFPMC13_ADD: - ds_put_cstr(s, " ADD "); - break; - case OFPMC13_MODIFY: - ds_put_cstr(s, " MOD "); - break; - case OFPMC13_DELETE: - ds_put_cstr(s, " DEL "); - break; - default: - ds_put_format(s, " cmd:%d ", mm->command); + enum ofperr error = ofputil_decode_table_status(oh, &ts); + if (!error) { + ofputil_format_table_status(string, &ts, table_map); } - - ofp_print_meter_config(s, &mm->meter); + return error; } static enum ofperr @@ -577,12 +331,11 @@ ofp_print_meter_mod(struct ds *s, const struct ofp_header *oh) { struct ofputil_meter_mod mm; struct ofpbuf bands; - enum ofperr error; ofpbuf_init(&bands, 64); - error = ofputil_decode_meter_mod(oh, &mm, &bands); + enum ofperr error = ofputil_decode_meter_mod(oh, &mm, &bands); if (!error) { - ofp_print_meter_mod__(s, &mm); + ofputil_format_meter_mod(s, &mm); } ofpbuf_uninit(&bands); @@ -597,58 +350,17 @@ ofp_print_meter_stats_request(struct ds *s, const struct ofp_header *oh) ofputil_decode_meter_request(oh, &meter_id); ds_put_char(s, ' '); - ofp_print_meter_id(s, meter_id, '='); + ofputil_format_meter_id(s, meter_id, '='); return 0; } -static const char * -ofputil_meter_capabilities_to_name(uint32_t bit) -{ - enum ofp13_meter_flags flag = bit; - - switch (flag) { - case OFPMF13_KBPS: return "kbps"; - case OFPMF13_PKTPS: return "pktps"; - case OFPMF13_BURST: return "burst"; - case OFPMF13_STATS: return "stats"; - } - - return NULL; -} - -static const char * -ofputil_meter_band_types_to_name(uint32_t bit) -{ - switch (bit) { - case 1 << OFPMBT13_DROP: return "drop"; - case 1 << OFPMBT13_DSCP_REMARK: return "dscp_remark"; - } - - return NULL; -} - static enum ofperr ofp_print_meter_features_reply(struct ds *s, const struct ofp_header *oh) { struct ofputil_meter_features mf; - ofputil_decode_meter_features(oh, &mf); - - ds_put_format(s, "\nmax_meter:%"PRIu32, mf.max_meters); - ds_put_format(s, " max_bands:%"PRIu8, mf.max_bands); - ds_put_format(s, " max_color:%"PRIu8"\n", mf.max_color); - - ds_put_cstr(s, "band_types: "); - ofp_print_bit_names(s, mf.band_types, - ofputil_meter_band_types_to_name, ' '); - ds_put_char(s, '\n'); - - ds_put_cstr(s, "capabilities: "); - ofp_print_bit_names(s, mf.capabilities, - ofputil_meter_capabilities_to_name, ' '); - ds_put_char(s, '\n'); - + ofputil_format_meter_features(s, &mf); return 0; } @@ -668,7 +380,7 @@ ofp_print_meter_config_reply(struct ds *s, const struct ofp_header *oh) break; } ds_put_char(s, '\n'); - ofp_print_meter_config(s, &mc); + ofputil_format_meter_config(s, &mc); } ofpbuf_uninit(&bands); @@ -691,7 +403,7 @@ ofp_print_meter_stats_reply(struct ds *s, const struct ofp_header *oh) break; } ds_put_char(s, '\n'); - ofp_print_meter_stats(s, &ms); + ofputil_format_meter_stats(s, &ms); } ofpbuf_uninit(&bands); @@ -810,30 +522,6 @@ ofp_print_aggregate_stats_reply(struct ds *string, const struct ofp_header *oh) return error; } -static void -print_port_stat(struct ds *string, const char *leader, uint64_t stat, int more) -{ - ds_put_cstr(string, leader); - if (stat != UINT64_MAX) { - ds_put_format(string, "%"PRIu64, stat); - } else { - ds_put_char(string, '?'); - } - if (more) { - ds_put_cstr(string, ", "); - } else { - ds_put_cstr(string, "\n"); - } -} - -static void -print_port_stat_cond(struct ds *string, const char *leader, uint64_t stat) -{ - if (stat != UINT64_MAX) { - ds_put_format(string, "%s%"PRIu64", ", leader, stat); - } -} - static enum ofperr ofp_print_ofpst_port_request(struct ds *string, const struct ofp_header *oh, const struct ofputil_port_map *port_map) @@ -857,8 +545,8 @@ ofp_print_ofpst_port_reply(struct ds *string, const struct ofp_header *oh, const struct ofputil_port_map *port_map, int verbosity) { - uint32_t i; - ds_put_format(string, " %"PRIuSIZE" ports\n", ofputil_count_port_stats(oh)); + ds_put_format(string, " %"PRIuSIZE" ports\n", + ofputil_count_port_stats(oh)); if (verbosity < 1) { return 0; } @@ -872,120 +560,7 @@ ofp_print_ofpst_port_reply(struct ds *string, const struct ofp_header *oh, if (retval) { return retval != EOF ? retval : 0; } - - ds_put_cstr(string, " port "); - if (ofp_to_u16(ps.port_no) < 10) { - ds_put_char(string, ' '); - } - ofputil_format_port(ps.port_no, port_map, string); - - 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.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); - - if (ps.duration_sec != UINT32_MAX) { - ds_put_cstr(string, " duration="); - ofp_print_duration(string, ps.duration_sec, ps.duration_nsec); - ds_put_char(string, '\n'); - } - struct ds string_ext_stats = DS_EMPTY_INITIALIZER; - - ds_init(&string_ext_stats); - - print_port_stat_cond(&string_ext_stats, "1_to_64_packets=", - ps.stats.rx_1_to_64_packets); - print_port_stat_cond(&string_ext_stats, "65_to_127_packets=", - ps.stats.rx_65_to_127_packets); - print_port_stat_cond(&string_ext_stats, "128_to_255_packets=", - ps.stats.rx_128_to_255_packets); - print_port_stat_cond(&string_ext_stats, "256_to_511_packets=", - ps.stats.rx_256_to_511_packets); - print_port_stat_cond(&string_ext_stats, "512_to_1023_packets=", - ps.stats.rx_512_to_1023_packets); - print_port_stat_cond(&string_ext_stats, "1024_to_1522_packets=", - ps.stats.rx_1024_to_1522_packets); - print_port_stat_cond(&string_ext_stats, "1523_to_max_packets=", - ps.stats.rx_1523_to_max_packets); - print_port_stat_cond(&string_ext_stats, "broadcast_packets=", - ps.stats.rx_broadcast_packets); - print_port_stat_cond(&string_ext_stats, "undersized_errors=", - ps.stats.rx_undersized_errors); - print_port_stat_cond(&string_ext_stats, "oversize_errors=", - ps.stats.rx_oversize_errors); - print_port_stat_cond(&string_ext_stats, "rx_fragmented_errors=", - ps.stats.rx_fragmented_errors); - print_port_stat_cond(&string_ext_stats, "rx_jabber_errors=", - ps.stats.rx_jabber_errors); - - if (string_ext_stats.length != 0) { - /* If at least one statistics counter is reported: */ - ds_put_cstr(string, " rx rfc2819 "); - ds_put_buffer(string, string_ext_stats.string, - string_ext_stats.length); - ds_put_cstr(string, "\n"); - ds_destroy(&string_ext_stats); - } - - ds_init(&string_ext_stats); - - print_port_stat_cond(&string_ext_stats, "1_to_64_packets=", - ps.stats.tx_1_to_64_packets); - print_port_stat_cond(&string_ext_stats, "65_to_127_packets=", - ps.stats.tx_65_to_127_packets); - print_port_stat_cond(&string_ext_stats, "128_to_255_packets=", - ps.stats.tx_128_to_255_packets); - print_port_stat_cond(&string_ext_stats, "256_to_511_packets=", - ps.stats.tx_256_to_511_packets); - print_port_stat_cond(&string_ext_stats, "512_to_1023_packets=", - ps.stats.tx_512_to_1023_packets); - print_port_stat_cond(&string_ext_stats, "1024_to_1522_packets=", - ps.stats.tx_1024_to_1522_packets); - print_port_stat_cond(&string_ext_stats, "1523_to_max_packets=", - ps.stats.tx_1523_to_max_packets); - print_port_stat_cond(&string_ext_stats, "multicast_packets=", - ps.stats.tx_multicast_packets); - print_port_stat_cond(&string_ext_stats, "broadcast_packets=", - ps.stats.tx_broadcast_packets); - - if (string_ext_stats.length != 0) { - /* If at least one statistics counter is reported: */ - ds_put_cstr(string, " tx rfc2819 "); - ds_put_buffer(string, string_ext_stats.string, - string_ext_stats.length); - ds_put_cstr(string, "\n"); - ds_destroy(&string_ext_stats); - } - - if (ps.custom_stats.size) { - ds_put_cstr(string, " CUSTOM Statistics"); - for (i = 0; i < ps.custom_stats.size; i++) { - /* 3 counters in the row */ - if (ps.custom_stats.counters[i].name[0]) { - if (i % 3 == 0) { - ds_put_cstr(string, "\n"); - ds_put_cstr(string, " "); - } else { - ds_put_char(string, ' '); - } - ds_put_format(string, "%s=%"PRIu64",", - ps.custom_stats.counters[i].name, - ps.custom_stats.counters[i].value); - } - } - ds_put_cstr(string, "\n"); - } + ofputil_format_port_stats(string, &ps, port_map); } } @@ -1018,77 +593,6 @@ ofp_print_table_stats_reply(struct ds *string, const struct ofp_header *oh, } } -static void -ofp_print_queue_name(struct ds *string, uint32_t queue_id) -{ - if (queue_id == OFPQ_ALL) { - ds_put_cstr(string, "ALL"); - } else { - ds_put_format(string, "%"PRIu32, queue_id); - } -} - -static enum ofperr -ofp_print_ofpst_queue_request(struct ds *string, const struct ofp_header *oh, - const struct ofputil_port_map *port_map) -{ - struct ofputil_queue_stats_request oqsr; - enum ofperr error; - - error = ofputil_decode_queue_stats_request(oh, &oqsr); - if (error) { - return error; - } - - ds_put_cstr(string, " port="); - ofputil_format_port(oqsr.port_no, port_map, string); - - ds_put_cstr(string, " queue="); - ofp_print_queue_name(string, oqsr.queue_id); - - return 0; -} - -static enum ofperr -ofp_print_ofpst_queue_reply(struct ds *string, const struct ofp_header *oh, - const struct ofputil_port_map *port_map, - int verbosity) -{ - ds_put_format(string, " %"PRIuSIZE" queues\n", ofputil_count_queue_stats(oh)); - if (verbosity < 1) { - return 0; - } - - struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); - for (;;) { - struct ofputil_queue_stats qs; - int retval; - - retval = ofputil_decode_queue_stats(&qs, &b); - if (retval) { - return retval != EOF ? retval : 0; - } - - ds_put_cstr(string, " port "); - ofputil_format_port(qs.port_no, port_map, string); - ds_put_cstr(string, " queue "); - ofp_print_queue_name(string, 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, 1); - - ds_put_cstr(string, "duration="); - if (qs.duration_sec != UINT32_MAX) { - ofp_print_duration(string, qs.duration_sec, qs.duration_nsec); - } else { - ds_put_char(string, '?'); - } - ds_put_char(string, '\n'); - } -} - static enum ofperr ofp_print_ofpst_port_desc_request(struct ds *string, const struct ofp_header *oh, @@ -1150,82 +654,26 @@ ofp_print_echo(struct ds *string, const struct ofp_header *oh, int verbosity) return 0; } -static void -ofp_print_role_generic(struct ds *string, enum ofp12_controller_role role, - uint64_t generation_id) -{ - ds_put_cstr(string, " role="); - - switch (role) { - case OFPCR12_ROLE_NOCHANGE: - ds_put_cstr(string, "nochange"); - break; - case OFPCR12_ROLE_EQUAL: - ds_put_cstr(string, "equal"); /* OF 1.2 wording */ - break; - case OFPCR12_ROLE_MASTER: - ds_put_cstr(string, "master"); - break; - case OFPCR12_ROLE_SLAVE: - ds_put_cstr(string, "slave"); - break; - default: - OVS_NOT_REACHED(); - } - - if (generation_id != UINT64_MAX) { - ds_put_format(string, " generation_id=%"PRIu64, generation_id); - } -} - static enum ofperr ofp_print_role_message(struct ds *string, const struct ofp_header *oh) { struct ofputil_role_request rr; - enum ofperr error; - - error = ofputil_decode_role_message(oh, &rr); - if (error) { - return error; + enum ofperr error = ofputil_decode_role_message(oh, &rr); + if (!error) { + ofputil_format_role_message(string, &rr); } - - ofp_print_role_generic(string, rr.role, rr.have_generation_id ? rr.generation_id : UINT64_MAX); - - return 0; + return error; } static enum ofperr ofp_print_role_status_message(struct ds *string, const struct ofp_header *oh) { struct ofputil_role_status rs; - enum ofperr error; - - error = ofputil_decode_role_status(oh, &rs); - if (error) { - return error; - } - - ofp_print_role_generic(string, rs.role, rs.generation_id); - - ds_put_cstr(string, " reason="); - - switch (rs.reason) { - case OFPCRR_MASTER_REQUEST: - ds_put_cstr(string, "master_request"); - break; - case OFPCRR_CONFIG: - ds_put_cstr(string, "configuration_changed"); - break; - case OFPCRR_EXPERIMENTER: - ds_put_cstr(string, "experimenter_data_changed"); - break; - case OFPCRR_N_REASONS: - default: - ds_put_cstr(string, "(unknown)"); - break; + enum ofperr error = ofputil_decode_role_status(oh, &rs); + if (!error) { + ofputil_format_role_status(string, &rs); } - - return 0; + return error; } static enum ofperr @@ -1260,128 +708,6 @@ ofp_print_nxt_set_packet_in_format(struct ds *string, return error; } -/* Returns a string form of 'reason'. The return value is either a statically - * allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'. - * 'bufsize' should be at least OFP_PORT_REASON_BUFSIZE. */ -#define OFP_PORT_REASON_BUFSIZE (INT_STRLEN(int) + 1) -static const char * -ofp_port_reason_to_string(enum ofp_port_reason reason, - char *reasonbuf, size_t bufsize) -{ - switch (reason) { - case OFPPR_ADD: - return "add"; - - case OFPPR_DELETE: - return "delete"; - - case OFPPR_MODIFY: - return "modify"; - - case OFPPR_N_REASONS: - default: - snprintf(reasonbuf, bufsize, "%d", (int) reason); - return reasonbuf; - } -} - -/* Returns a string form of 'reason'. The return value is either a statically - * allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'. - * 'bufsize' should be at least OFP_ASYNC_CONFIG_REASON_BUFSIZE. */ -static const char* -ofp_role_reason_to_string(enum ofp14_controller_role_reason reason, - char *reasonbuf, size_t bufsize) -{ - switch (reason) { - case OFPCRR_MASTER_REQUEST: - return "master_request"; - - case OFPCRR_CONFIG: - return "configuration_changed"; - - case OFPCRR_EXPERIMENTER: - return "experimenter_data_changed"; - - case OFPCRR_N_REASONS: - default: - snprintf(reasonbuf, bufsize, "%d", (int) reason); - return reasonbuf; - } -} - -/* Returns a string form of 'reason'. The return value is either a statically - * allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'. - * 'bufsize' should be at least OFP_ASYNC_CONFIG_REASON_BUFSIZE. */ -static const char* -ofp_table_reason_to_string(enum ofp14_table_reason reason, - char *reasonbuf, size_t bufsize) -{ - switch (reason) { - case OFPTR_VACANCY_DOWN: - return "vacancy_down"; - - case OFPTR_VACANCY_UP: - return "vacancy_up"; - - default: - snprintf(reasonbuf, bufsize, "%d", (int) reason); - return reasonbuf; - } -} - -/* Returns a string form of 'reason'. The return value is either a statically - * allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'. - * 'bufsize' should be at least OFP_ASYNC_CONFIG_REASON_BUFSIZE. */ -static const char* -ofp_requestforward_reason_to_string(enum ofp14_requestforward_reason reason, - char *reasonbuf, size_t bufsize) -{ - switch (reason) { - case OFPRFR_GROUP_MOD: - return "group_mod_request"; - - case OFPRFR_METER_MOD: - return "meter_mod_request"; - - case OFPRFR_N_REASONS: - default: - snprintf(reasonbuf, bufsize, "%d", (int) reason); - return reasonbuf; - } -} - -static const char * -ofp_async_config_reason_to_string(uint32_t reason, - enum ofputil_async_msg_type type, - char *reasonbuf, size_t bufsize) -{ - switch (type) { - case OAM_PACKET_IN: - return ofputil_packet_in_reason_to_string(reason, reasonbuf, bufsize); - - case OAM_PORT_STATUS: - return ofp_port_reason_to_string(reason, reasonbuf, bufsize); - - case OAM_FLOW_REMOVED: - return ofp_flow_removed_reason_to_string(reason, reasonbuf, bufsize); - - case OAM_ROLE_STATUS: - return ofp_role_reason_to_string(reason, reasonbuf, bufsize); - - case OAM_TABLE_STATUS: - return ofp_table_reason_to_string(reason, reasonbuf, bufsize); - - case OAM_REQUESTFORWARD: - return ofp_requestforward_reason_to_string(reason, reasonbuf, bufsize); - - case OAM_N_TYPES: - default: - return "Unknown asynchronous configuration message type"; - } -} - - -#define OFP_ASYNC_CONFIG_REASON_BUFSIZE (INT_STRLEN(int) + 1) static enum ofperr ofp_print_set_async_config(struct ds *string, const struct ofp_header *oh, enum ofptype ofptype) @@ -1395,33 +721,7 @@ ofp_print_set_async_config(struct ds *string, const struct ofp_header *oh, if (error) { return error; } - - for (int i = 0; i < 2; i++) { - ds_put_format(string, "\n %s:\n", i == 0 ? "master" : "slave"); - for (uint32_t type = 0; type < OAM_N_TYPES; type++) { - ds_put_format(string, "%16s:", - ofputil_async_msg_type_to_string(type)); - - uint32_t role = i == 0 ? ac.master[type] : ac.slave[type]; - for (int j = 0; j < 32; j++) { - if (role & (1u << j)) { - char reasonbuf[OFP_ASYNC_CONFIG_REASON_BUFSIZE]; - const char *reason; - - reason = ofp_async_config_reason_to_string( - j, type, reasonbuf, sizeof reasonbuf); - if (reason[0]) { - ds_put_format(string, " %s", reason); - } - } - } - if (!role) { - ds_put_cstr(string, " (off)"); - } - ds_put_char(string, '\n'); - } - } - + ofputil_format_set_async_config(string, &ac); return 0; } @@ -1541,19 +841,6 @@ ofp_print_table_desc_reply(struct ds *s, const struct ofp_header *oh, } } -static const char * -bundle_flags_to_name(uint32_t bit) -{ - switch (bit) { - case OFPBF_ATOMIC: - return "atomic"; - case OFPBF_ORDERED: - return "ordered"; - default: - return NULL; - } -} - static enum ofperr ofp_print_bundle_ctrl(struct ds *s, const struct ofp_header *oh) { @@ -1564,40 +851,7 @@ ofp_print_bundle_ctrl(struct ds *s, const struct ofp_header *oh) if (error) { return error; } - - ds_put_char(s, '\n'); - - ds_put_format(s, " bundle_id=%#"PRIx32" type=", bctrl.bundle_id); - switch (bctrl.type) { - case OFPBCT_OPEN_REQUEST: - ds_put_cstr(s, "OPEN_REQUEST"); - break; - case OFPBCT_OPEN_REPLY: - ds_put_cstr(s, "OPEN_REPLY"); - break; - case OFPBCT_CLOSE_REQUEST: - ds_put_cstr(s, "CLOSE_REQUEST"); - break; - case OFPBCT_CLOSE_REPLY: - ds_put_cstr(s, "CLOSE_REPLY"); - break; - case OFPBCT_COMMIT_REQUEST: - ds_put_cstr(s, "COMMIT_REQUEST"); - break; - case OFPBCT_COMMIT_REPLY: - ds_put_cstr(s, "COMMIT_REPLY"); - break; - case OFPBCT_DISCARD_REQUEST: - ds_put_cstr(s, "DISCARD_REQUEST"); - break; - case OFPBCT_DISCARD_REPLY: - ds_put_cstr(s, "DISCARD_REPLY"); - break; - } - - ds_put_cstr(s, " flags="); - ofp_print_bit_names(s, bctrl.flags, bundle_flags_to_name, ' '); - + ofputil_format_bundle_ctrl_request(s, &bctrl); return 0; } @@ -1607,106 +861,36 @@ ofp_print_bundle_add(struct ds *s, const struct ofp_header *oh, const struct ofputil_table_map *table_map, int verbosity) { - int error; struct ofputil_bundle_add_msg badd; - - error = ofputil_decode_bundle_add(oh, &badd, NULL); - if (error) { - return error; - } - - ds_put_char(s, '\n'); - ds_put_format(s, " bundle_id=%#"PRIx32, badd.bundle_id); - ds_put_cstr(s, " flags="); - ofp_print_bit_names(s, badd.flags, bundle_flags_to_name, ' '); - - ds_put_char(s, '\n'); - char *msg = ofp_to_string(badd.msg, ntohs(badd.msg->length), port_map, - table_map, verbosity); - ds_put_and_free_cstr(s, msg); - - return 0; -} - -static void -print_tlv_table(struct ds *s, struct ovs_list *mappings) -{ - struct ofputil_tlv_map *map; - - ds_put_cstr(s, " mapping table:\n"); - ds_put_cstr(s, " class type length match field\n"); - ds_put_cstr(s, " ------ ---- ------ --------------"); - - LIST_FOR_EACH (map, list_node, mappings) { - ds_put_format(s, "\n %#6"PRIx16" %#4"PRIx8" %6"PRIu8" " - "tun_metadata%"PRIu16, - map->option_class, map->option_type, map->option_len, - map->index); + int error = ofputil_decode_bundle_add(oh, &badd, NULL); + if (!error) { + ofputil_format_bundle_add(s, &badd, port_map, table_map, verbosity); } + return error; } static enum ofperr ofp_print_tlv_table_mod(struct ds *s, const struct ofp_header *oh) { - int error; struct ofputil_tlv_table_mod ttm; - - error = ofputil_decode_tlv_table_mod(oh, &ttm); - if (error) { - return error; - } - - ds_put_cstr(s, "\n "); - - switch (ttm.command) { - case NXTTMC_ADD: - ds_put_cstr(s, "ADD"); - break; - case NXTTMC_DELETE: - ds_put_cstr(s, "DEL"); - break; - case NXTTMC_CLEAR: - ds_put_cstr(s, "CLEAR"); - break; - } - - if (ttm.command != NXTTMC_CLEAR) { - print_tlv_table(s, &ttm.mappings); + int error = ofputil_decode_tlv_table_mod(oh, &ttm); + if (!error) { + ofputil_format_tlv_table_mod(s, &ttm); + ofputil_uninit_tlv_table(&ttm.mappings); } - - ofputil_uninit_tlv_table(&ttm.mappings); - - return 0; + return error; } static enum ofperr ofp_print_tlv_table_reply(struct ds *s, const struct ofp_header *oh) { - int error; struct ofputil_tlv_table_reply ttr; - struct ofputil_tlv_map *map; - int allocated_space = 0; - - error = ofputil_decode_tlv_table_reply(oh, &ttr); - if (error) { - return error; - } - - ds_put_char(s, '\n'); - - LIST_FOR_EACH (map, list_node, &ttr.mappings) { - allocated_space += map->option_len; + int error = ofputil_decode_tlv_table_reply(oh, &ttr); + if (!error) { + ofputil_format_tlv_table_reply(s, &ttr); + ofputil_uninit_tlv_table(&ttr.mappings); } - - ds_put_format(s, " max option space=%"PRIu32" max fields=%"PRIu16"\n", - ttr.max_option_space, ttr.max_fields); - ds_put_format(s, " allocated option space=%d\n", allocated_space); - ds_put_char(s, '\n'); - print_tlv_table(s, &ttr.mappings); - - ofputil_uninit_tlv_table(&ttr.mappings); - - return 0; + return error; } /* This function will print the request forward message. The reason for @@ -1717,49 +901,13 @@ ofp_print_requestforward(struct ds *string, const struct ofp_header *oh, const struct ofputil_table_map *table_map) { struct ofputil_requestforward rf; - enum ofperr error; - - error = ofputil_decode_requestforward(oh, &rf); - if (error) { - return error; - } - - ds_put_cstr(string, " reason="); - - switch (rf.reason) { - case OFPRFR_GROUP_MOD: - ds_put_cstr(string, "group_mod"); - ofputil_group_mod_format__(string, oh->version, rf.group_mod, port_map, - table_map); - break; - - case OFPRFR_METER_MOD: - ds_put_cstr(string, "meter_mod"); - ofp_print_meter_mod__(string, rf.meter_mod); - break; - - case OFPRFR_N_REASONS: - OVS_NOT_REACHED(); - } - ofputil_destroy_requestforward(&rf); - - return 0; -} - -static void -print_ipfix_stat(struct ds *string, const char *leader, uint64_t stat, int more) -{ - ds_put_cstr(string, leader); - if (stat != UINT64_MAX) { - ds_put_format(string, "%"PRIu64, stat); - } else { - ds_put_char(string, '?'); - } - if (more) { - ds_put_cstr(string, ", "); - } else { - ds_put_cstr(string, "\n"); + enum ofperr error = ofputil_decode_requestforward(oh, &rf); + if (!error) { + ofputil_format_requestforward(string, oh->version, + &rf, port_map, table_map); + ofputil_destroy_requestforward(&rf); } + return error; } static enum ofperr @@ -1774,19 +922,7 @@ ofp_print_nxst_ipfix_bridge_reply(struct ds *string, const struct ofp_header *oh if (retval) { return retval != EOF ? retval : 0; } - - ds_put_cstr(string, "\n bridge ipfix: "); - print_ipfix_stat(string, "flows=", is.total_flows, 1); - print_ipfix_stat(string, "current flows=", is.current_flows, 1); - print_ipfix_stat(string, "sampled pkts=", is.pkts, 1); - print_ipfix_stat(string, "ipv4 ok=", is.ipv4_pkts, 1); - print_ipfix_stat(string, "ipv6 ok=", is.ipv6_pkts, 1); - print_ipfix_stat(string, "tx pkts=", is.tx_pkts, 0); - ds_put_cstr(string, " "); - print_ipfix_stat(string, "pkts errs=", is.error_pkts, 1); - print_ipfix_stat(string, "ipv4 errs=", is.ipv4_error_pkts, 1); - print_ipfix_stat(string, "ipv6 errs=", is.ipv6_error_pkts, 1); - print_ipfix_stat(string, "tx errs=", is.tx_errors, 0); + ofputil_format_ipfix_stats_bridge(string, &is); } } @@ -1804,20 +940,7 @@ ofp_print_nxst_ipfix_flow_reply(struct ds *string, const struct ofp_header *oh) if (retval) { return retval != EOF ? retval : 0; } - - ds_put_cstr(string, " id"); - ds_put_format(string, " %3"PRIuSIZE": ", (size_t) is.collector_set_id); - print_ipfix_stat(string, "flows=", is.total_flows, 1); - print_ipfix_stat(string, "current flows=", is.current_flows, 1); - print_ipfix_stat(string, "sampled pkts=", is.pkts, 1); - print_ipfix_stat(string, "ipv4 ok=", is.ipv4_pkts, 1); - print_ipfix_stat(string, "ipv6 ok=", is.ipv6_pkts, 1); - print_ipfix_stat(string, "tx pkts=", is.tx_pkts, 0); - ds_put_cstr(string, " "); - print_ipfix_stat(string, "pkts errs=", is.error_pkts, 1); - print_ipfix_stat(string, "ipv4 errs=", is.ipv4_error_pkts, 1); - print_ipfix_stat(string, "ipv6 errs=", is.ipv6_error_pkts, 1); - print_ipfix_stat(string, "tx errs=", is.tx_errors, 0); + ofputil_format_ipfix_stats_flow(string, &is); } } @@ -1926,10 +1049,10 @@ ofp_to_string__(const struct ofp_header *oh, break; case OFPTYPE_QUEUE_GET_CONFIG_REQUEST: - return ofp_print_queue_get_config_request(string, oh, port_map); + return ofputil_queue_get_config_request_format(string, oh, port_map); case OFPTYPE_QUEUE_GET_CONFIG_REPLY: - return ofp_print_queue_get_config_reply(string, oh, port_map); + return ofputil_queue_get_config_reply_format(string, oh, port_map); case OFPTYPE_ROLE_REQUEST: case OFPTYPE_ROLE_REPLY: @@ -1971,7 +1094,7 @@ ofp_to_string__(const struct ofp_header *oh, return ofp_print_ofpst_port_request(string, oh, port_map); case OFPTYPE_QUEUE_STATS_REQUEST: - return ofp_print_ofpst_queue_request(string, oh, port_map); + return ofputil_queue_stats_request_format(string, oh, port_map); case OFPTYPE_DESC_STATS_REPLY: return ofp_print_ofpst_desc_reply(string, oh); @@ -1980,7 +1103,8 @@ ofp_to_string__(const struct ofp_header *oh, return ofp_print_flow_stats_reply(string, oh, port_map, table_map); case OFPTYPE_QUEUE_STATS_REPLY: - return ofp_print_ofpst_queue_reply(string, oh, port_map, verbosity); + return ofputil_queue_stats_reply_format(string, oh, port_map, + verbosity); case OFPTYPE_PORT_STATS_REPLY: return ofp_print_ofpst_port_reply(string, oh, port_map, verbosity); diff --git a/lib/ofp-queue.c b/lib/ofp-queue.c index b3f681b0d7bc..1c939878ec3e 100644 --- a/lib/ofp-queue.c +++ b/lib/ofp-queue.c @@ -19,6 +19,7 @@ #include "byte-order.h" #include "flow.h" #include "openvswitch/ofp-msgs.h" +#include "openvswitch/ofp-print.h" #include "openvswitch/ofp-port.h" #include "openvswitch/ofp-prop.h" #include "openvswitch/ofpbuf.h" @@ -29,6 +30,18 @@ VLOG_DEFINE_THIS_MODULE(ofp_queue); static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); +static void +ofp_print_queue_name(struct ds *string, uint32_t queue_id) +{ + if (queue_id == OFPQ_ALL) { + ds_put_cstr(string, "ALL"); + } else { + ds_put_format(string, "%"PRIu32, queue_id); + } +} + +/* OFPT_QUEUE_GET_CONFIG request and reply. */ + /* Constructs and returns an OFPT_QUEUE_GET_CONFIG request for the specified * 'port' and 'queue', suitable for OpenFlow version 'version'. * @@ -111,6 +124,31 @@ ofputil_decode_queue_get_config_request(const struct ofp_header *oh, : OFPERR_OFPQOFC_BAD_PORT); } +enum ofperr +ofputil_queue_get_config_request_format( + struct ds *string, const struct ofp_header *oh, + const struct ofputil_port_map *port_map) +{ + enum ofperr error; + ofp_port_t port; + uint32_t queue; + + error = ofputil_decode_queue_get_config_request(oh, &port, &queue); + if (error) { + return error; + } + + ds_put_cstr(string, " port="); + ofputil_format_port(port, port_map, string); + + if (queue != OFPQ_ALL) { + ds_put_cstr(string, " queue="); + ofp_print_queue_name(string, queue); + } + + return 0; +} + /* Constructs and returns the beginning of a reply to * OFPT_QUEUE_GET_CONFIG_REQUEST or OFPMP_QUEUE_DESC request 'oh'. The caller * may append information about individual queues with @@ -419,6 +457,83 @@ ofputil_pull_queue_get_config_reply(struct ofpbuf *msg, return ofputil_pull_queue_get_config_reply10(msg, queue); } } + +static void +print_queue_rate(struct ds *string, const char *name, unsigned int rate) +{ + if (rate <= 1000) { + ds_put_format(string, " %s:%u.%u%%", name, rate / 10, rate % 10); + } else if (rate < UINT16_MAX) { + ds_put_format(string, " %s:(disabled)", name); + } +} + +/* qsort comparison function. */ +static int +compare_queues(const void *a_, const void *b_) +{ + const struct ofputil_queue_config *a = a_; + const struct ofputil_queue_config *b = b_; + + uint16_t ap = ofp_to_u16(a->port); + uint16_t bp = ofp_to_u16(b->port); + if (ap != bp) { + return ap < bp ? -1 : 1; + } + + uint32_t aq = a->queue; + uint32_t bq = b->queue; + return aq < bq ? -1 : aq > bq; +} + +enum ofperr +ofputil_queue_get_config_reply_format(struct ds *string, + const struct ofp_header *oh, + const struct ofputil_port_map *port_map) +{ + struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); + + struct ofputil_queue_config *queues = NULL; + size_t allocated_queues = 0; + size_t n = 0; + + int retval = 0; + for (;;) { + if (n >= allocated_queues) { + queues = x2nrealloc(queues, &allocated_queues, sizeof *queues); + } + retval = ofputil_pull_queue_get_config_reply(&b, &queues[n]); + if (retval) { + break; + } + n++; + } + + qsort(queues, n, sizeof *queues, compare_queues); + + ds_put_char(string, ' '); + + ofp_port_t port = 0; + for (const struct ofputil_queue_config *q = queues; q < &queues[n]; q++) { + if (q->port != port) { + port = q->port; + + ds_put_cstr(string, "port="); + ofputil_format_port(port, port_map, string); + ds_put_char(string, '\n'); + } + + ds_put_format(string, "queue %"PRIu32":", q->queue); + print_queue_rate(string, "min_rate", q->min_rate); + print_queue_rate(string, "max_rate", q->max_rate); + ds_put_char(string, '\n'); + } + + ds_chomp(string, ' '); + free(queues); + + return retval != EOF ? retval : 0; +} /* Parse a queue status request message into 'oqsr'. * Returns 0 if successful, otherwise an OFPERR_* number. */ @@ -495,6 +610,28 @@ ofputil_encode_queue_stats_request( return request; } +enum ofperr +ofputil_queue_stats_request_format(struct ds *string, + const struct ofp_header *oh, + const struct ofputil_port_map *port_map) +{ + struct ofputil_queue_stats_request oqsr; + enum ofperr error; + + error = ofputil_decode_queue_stats_request(oh, &oqsr); + if (error) { + return error; + } + + ds_put_cstr(string, " port="); + ofputil_format_port(oqsr.port_no, port_map, string); + + ds_put_cstr(string, " queue="); + ofp_print_queue_name(string, oqsr.queue_id); + + return 0; +} + /* Returns the number of queue stats elements in OFPTYPE_QUEUE_STATS_REPLY * message 'oh'. */ size_t @@ -726,3 +863,62 @@ ofputil_append_queue_stat(struct ovs_list *replies, } } +static void +print_queue_stat(struct ds *string, const char *leader, uint64_t stat, + int more) +{ + ds_put_cstr(string, leader); + if (stat != UINT64_MAX) { + ds_put_format(string, "%"PRIu64, stat); + } else { + ds_put_char(string, '?'); + } + if (more) { + ds_put_cstr(string, ", "); + } else { + ds_put_cstr(string, "\n"); + } +} + +enum ofperr +ofputil_queue_stats_reply_format(struct ds *string, + const struct ofp_header *oh, + const struct ofputil_port_map *port_map, + int verbosity) +{ + ds_put_format(string, " %"PRIuSIZE" queues\n", + ofputil_count_queue_stats(oh)); + if (verbosity < 1) { + return 0; + } + + struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); + for (;;) { + struct ofputil_queue_stats qs; + int retval; + + retval = ofputil_decode_queue_stats(&qs, &b); + if (retval) { + return retval != EOF ? retval : 0; + } + + ds_put_cstr(string, " port "); + ofputil_format_port(qs.port_no, port_map, string); + ds_put_cstr(string, " queue "); + 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, 1); + + ds_put_cstr(string, "duration="); + if (qs.duration_sec != UINT32_MAX) { + ofp_print_duration(string, qs.duration_sec, qs.duration_nsec); + } else { + ds_put_char(string, '?'); + } + ds_put_char(string, '\n'); + } +} + diff --git a/lib/ofp-table.c b/lib/ofp-table.c index 595a4384ddfa..5f14fcc3a9f3 100644 --- a/lib/ofp-table.c +++ b/lib/ofp-table.c @@ -1912,6 +1912,26 @@ ofputil_decode_table_stats_reply(struct ofpbuf *msg, } } +/* Returns a string form of 'reason'. The return value is either a statically + * allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'. + * 'bufsize' should be at least OFP_ASYNC_CONFIG_REASON_BUFSIZE. */ +const char * +ofp_table_reason_to_string(enum ofp14_table_reason reason, + char *reasonbuf, size_t bufsize) +{ + switch (reason) { + case OFPTR_VACANCY_DOWN: + return "vacancy_down"; + + case OFPTR_VACANCY_UP: + return "vacancy_up"; + + default: + snprintf(reasonbuf, bufsize, "%d", (int) reason); + return reasonbuf; + } +} + static void ofputil_put_ofp14_table_desc(const struct ofputil_table_desc *td, struct ofpbuf *b, enum ofp_version version) @@ -1997,3 +2017,18 @@ ofputil_decode_table_status(const struct ofp_header *oh, return 0; } + +void +ofputil_format_table_status(struct ds *string, + const struct ofputil_table_status *ts, + const struct ofputil_table_map *table_map) +{ + if (ts->reason == OFPTR_VACANCY_DOWN) { + ds_put_format(string, " reason=VACANCY_DOWN"); + } else if (ts->reason == OFPTR_VACANCY_UP) { + ds_put_format(string, " reason=VACANCY_UP"); + } + + ds_put_format(string, "\ntable_desc:-"); + ofputil_table_desc_format(string, &ts->desc, table_map); +}