From patchwork Fri Oct 9 12:49:33 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Weglicki, MichalX" X-Patchwork-Id: 528211 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from archives.nicira.com (li376-54.members.linode.com [96.126.127.54]) by ozlabs.org (Postfix) with ESMTP id D7E8B14010F for ; Fri, 9 Oct 2015 23:49:55 +1100 (AEDT) Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id 2033710A69; Fri, 9 Oct 2015 05:49:54 -0700 (PDT) X-Original-To: dev@openvswitch.org Delivered-To: dev@openvswitch.org Received: from mx3v1.cudamail.com (mx3.cudamail.com [64.34.241.5]) by archives.nicira.com (Postfix) with ESMTPS id 9474310A67 for ; Fri, 9 Oct 2015 05:49:52 -0700 (PDT) Received: from bar4.cudamail.com (bar2 [192.168.15.2]) by mx3v1.cudamail.com (Postfix) with ESMTP id 3AB13618BAE for ; Fri, 9 Oct 2015 06:49:50 -0600 (MDT) X-ASG-Debug-ID: 1444394988-03dc213abe4dec0001-byXFYA Received: from mx3-pf2.cudamail.com ([192.168.14.1]) by bar4.cudamail.com with ESMTP id 7zvCM55LvTmiXyud (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Fri, 09 Oct 2015 06:49:48 -0600 (MDT) X-Barracuda-Envelope-From: mweglicx@ecsmtp.ir.intel.com X-Barracuda-RBL-Trusted-Forwarder: 192.168.14.1 Received: from unknown (HELO mga03.intel.com) (134.134.136.65) by mx3-pf2.cudamail.com with SMTP; 9 Oct 2015 12:49:40 -0000 Received-SPF: none (mx3-pf2.cudamail.com: domain at ecsmtp.ir.intel.com does not designate permitted sender hosts) X-Barracuda-Apparent-Source-IP: 134.134.136.65 X-Barracuda-RBL-IP: 134.134.136.65 Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga103.jf.intel.com with ESMTP; 09 Oct 2015 05:49:42 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.17,657,1437462000"; d="scan'208";a="807235065" Received: from irvmail001.ir.intel.com ([163.33.26.43]) by fmsmga001.fm.intel.com with ESMTP; 09 Oct 2015 05:49:39 -0700 Received: from sivswdev01.ir.intel.com (sivswdev01.ir.intel.com [10.237.217.45]) by irvmail001.ir.intel.com (8.14.3/8.13.6/MailSET/Hub) with ESMTP id t99CncbS030648; Fri, 9 Oct 2015 13:49:39 +0100 Received: from sivswdev01.ir.intel.com (localhost [127.0.0.1]) by sivswdev01.ir.intel.com with ESMTP id t99CncRj013498; Fri, 9 Oct 2015 13:49:38 +0100 Received: (from mweglicx@localhost) by sivswdev01.ir.intel.com with id t99Cncox013494; Fri, 9 Oct 2015 13:49:38 +0100 X-CudaMail-Envelope-Sender: mweglicx@ecsmtp.ir.intel.com From: mweglicx To: dev@openvswitch.org X-CudaMail-MID: CM-V2-1008009894 X-CudaMail-DTE: 100915 X-CudaMail-Originating-IP: 134.134.136.65 Date: Fri, 9 Oct 2015 13:49:33 +0100 X-ASG-Orig-Subj: [##CM-V2-1008009894##][PATCH RFC] ofproto: RFC extended statistics patch Message-Id: <1444394973-13395-1-git-send-email-michalx.weglicki@intel.com> X-Mailer: git-send-email 1.7.4.1 X-GBUdb-Analysis: 0, 134.134.136.65, Ugly c=0 p=0 Source New X-MessageSniffer-Rules: 0-0-0-32767-c X-Barracuda-Connect: UNKNOWN[192.168.14.1] X-Barracuda-Start-Time: 1444394988 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://web.cudamail.com:443/cgi-mod/mark.cgi X-Barracuda-BRTS-Status: 1 X-Virus-Scanned: by bsmtpd at cudamail.com X-Barracuda-Spam-Score: 1.10 X-Barracuda-Spam-Status: No, SCORE=1.10 using per-user scores of TAG_LEVEL=3.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=3.0 tests=BSF_RULE7568M, BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.23334 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.50 BSF_RULE7568M Custom Rule 7568M 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Subject: [ovs-dev] [PATCH RFC] ofproto: RFC extended statistics patch X-BeenThere: dev@openvswitch.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dev-bounces@openvswitch.org Sender: "dev" Implementation of new statistics extension: - new counters definition based on RFC2819, - new command line option for ovs-ofctl: port-dump-ext, - new message definition has been created in nicira-ext.h, - new raw types OFPRAW_NXST_PORT_REQUEST, OFPRAW_NXST_PORT_REPLY have been created. - new extended statistics calculation is implemented only for dpdk-vhost-enabled ports. Please note that this is just feature proposal, final patch will include all relevant counters based on RFC2863, RFC3635 and RFC2819 in nx_port_stats (defined in nicira-ext.h). Signed-off-by: Michal Weglicki Signed-off-by: Timo Puha --- include/openflow/nicira-ext.h | 29 ++++++++ lib/netdev-bsd.c | 14 ++++ lib/netdev-dpdk.c | 44 +++++++++-- lib/netdev-dummy.c | 14 +++- lib/netdev-linux.c | 19 +++++ lib/netdev-vport.c | 13 ++++ lib/netdev.h | 8 ++ lib/ofp-msgs.h | 12 ++- lib/ofp-print.c | 60 ++++++++++----- lib/ofp-util.c | 166 ++++++++++++++++++++++++++++++++---------- lib/ofp-util.h | 2 + utilities/ovs-ofctl.c | 69 ++++++++++++++---- vswitchd/bridge.c | 30 +++++--- 13 files changed, 386 insertions(+), 94 deletions(-) diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h index efb40fa..1cf45cb 100644 --- a/include/openflow/nicira-ext.h +++ b/include/openflow/nicira-ext.h @@ -576,6 +576,35 @@ struct nx_flow_removed { }; OFP_ASSERT(sizeof(struct nx_flow_removed) == 40); +/* Nicira vendor stats request of type NXST_PORT (analogous to OFPST_PORT + * request). */ +struct nx_port_stats_request { + ovs_be32 port_no; /* OFPST_PORT message must request statistics + * either for a single port (specified in + * port_no) or for all ports (if port_no == + * OFPP_ANY). */ + uint8_t pad[4]; /* Align to 64-bits. */ +}; + +OFP_ASSERT(sizeof (struct nx_port_stats_request) == 8); + +/* Body of reply to NXST_PORT request (analogous to OFPST_PORT reply). + * If a counter is unsupported, set the field to all ones. */ +struct nx_port_stats { + ovs_be32 port_no; + uint8_t pad[4]; /* Align to 64-bits. */ + /* Below counters are just example used in RFC patch based on RFC2819. + * Final statistics extension should contain more counters based on + * RFC2819, RFC2863 and RFC3635. */ + ovs_be64 rx_64_packets; + ovs_be64 rx_65_to_127_packets; + ovs_be64 rx_128_to_255_packets; + ovs_be64 rx_256_to_511_packets; + ovs_be64 rx_512_to_1023_packets; + ovs_be64 rx_1024_to_1518_packets; +}; +OFP_ASSERT(sizeof(struct nx_port_stats) == 56); + /* Nicira vendor stats request of type NXST_FLOW (analogous to OFPST_FLOW * request). * diff --git a/lib/netdev-bsd.c b/lib/netdev-bsd.c index 60e5615..153687a 100644 --- a/lib/netdev-bsd.c +++ b/lib/netdev-bsd.c @@ -896,6 +896,18 @@ netdev_bsd_get_carrier(const struct netdev *netdev_, bool *carrier) return error; } +/* Initializes unused statistics to default values. */ +static void +netdev_bsd_set_unused_stats(struct netdev_stats *dst) +{ + dst->rx_1024_to_1518_packets = UINT64_MAX; + dst->rx_512_to_1023_packets = UINT64_MAX; + dst->rx_256_to_511_packets = UINT64_MAX; + dst->rx_128_to_255_packets = UINT64_MAX; + dst->rx_65_to_127_packets = UINT64_MAX; + dst->rx_64_packets = UINT64_MAX; +} + static void convert_stats_system(struct netdev_stats *stats, const struct if_data *ifd) { @@ -923,6 +935,7 @@ convert_stats_system(struct netdev_stats *stats, const struct if_data *ifd) stats->tx_fifo_errors = UINT64_MAX; stats->tx_heartbeat_errors = UINT64_MAX; stats->tx_window_errors = UINT64_MAX; + netdev_bsd_set_unused_stats(stats); } static void @@ -957,6 +970,7 @@ convert_stats_tap(struct netdev_stats *stats, const struct if_data *ifd) stats->tx_fifo_errors = UINT64_MAX; stats->tx_heartbeat_errors = UINT64_MAX; stats->tx_window_errors = UINT64_MAX; + netdev_bsd_set_unused_stats(stats); } static void diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c index 93b0589..2b4f07e 100644 --- a/lib/netdev-dpdk.c +++ b/lib/netdev-dpdk.c @@ -950,13 +950,15 @@ netdev_dpdk_vhost_update_rx_counters(struct netdev_stats *stats, struct dp_packet **packets, int count) { int i; + unsigned size; struct dp_packet *packet; stats->rx_packets += count; for (i = 0; i < count; i++) { packet = packets[i]; + size = dp_packet_size(packet); - if (OVS_UNLIKELY(dp_packet_size(packet) < ETH_HEADER_LEN)) { + if (OVS_UNLIKELY(size < ETH_HEADER_LEN)) { /* This only protects the following multicast counting from * too short packets, but it does not stop the packet from * further processing. */ @@ -965,12 +967,32 @@ netdev_dpdk_vhost_update_rx_counters(struct netdev_stats *stats, continue; } + /* Hard-coded binary search for the size bucket. */ + if (size < 256) { + if (size >= 128) { + stats->rx_128_to_255_packets++; + } else if (size <= 64) { + stats->rx_64_packets++; + } else { + stats->rx_65_to_127_packets++; + } + } else { + if (size >= 1024) { + stats->rx_1024_to_1518_packets++; + } else if (size < 512) { + stats->rx_256_to_511_packets++; + } else { + stats->rx_512_to_1023_packets++; + } + } + struct eth_header *eh = (struct eth_header *) dp_packet_data(packet); + if (OVS_UNLIKELY(eth_addr_is_multicast(eh->eth_dst))) { stats->multicast++; } - stats->rx_bytes += dp_packet_size(packet); + stats->rx_bytes += size; } } @@ -1412,7 +1434,6 @@ netdev_dpdk_vhost_get_stats(const struct netdev *netdev, struct netdev_dpdk *dev = netdev_dpdk_cast(netdev); ovs_mutex_lock(&dev->mutex); - memset(stats, 0, sizeof(*stats)); /* Unsupported Stats */ stats->collisions = UINT64_MAX; stats->rx_crc_errors = UINT64_MAX; @@ -1438,6 +1459,14 @@ netdev_dpdk_vhost_get_stats(const struct netdev *netdev, stats->tx_bytes = dev->stats.tx_bytes; stats->rx_errors = dev->stats.rx_errors; stats->rx_length_errors = dev->stats.rx_length_errors; + + stats->rx_64_packets = dev->stats.rx_64_packets; + stats->rx_65_to_127_packets = dev->stats.rx_65_to_127_packets; + stats->rx_128_to_255_packets = dev->stats.rx_128_to_255_packets; + stats->rx_256_to_511_packets = dev->stats.rx_256_to_511_packets; + stats->rx_512_to_1023_packets = dev->stats.rx_512_to_1023_packets; + stats->rx_1024_to_1518_packets = dev->stats.rx_1024_to_1518_packets; + rte_spinlock_unlock(&dev->stats_lock); ovs_mutex_unlock(&dev->mutex); @@ -1456,8 +1485,6 @@ netdev_dpdk_get_stats(const struct netdev *netdev, struct netdev_stats *stats) ovs_mutex_lock(&dev->mutex); rte_eth_stats_get(dev->port_id, &rte_stats); - memset(stats, 0, sizeof(*stats)); - stats->rx_packets = rte_stats.ipackets; stats->tx_packets = rte_stats.opackets; stats->rx_bytes = rte_stats.ibytes; @@ -1491,6 +1518,13 @@ netdev_dpdk_get_stats(const struct netdev *netdev, struct netdev_stats *stats) ovs_mutex_unlock(&dev->mutex); + stats->rx_64_packets = UINT64_MAX; + stats->rx_65_to_127_packets = UINT64_MAX; + stats->rx_128_to_255_packets = UINT64_MAX; + stats->rx_256_to_511_packets = UINT64_MAX; + stats->rx_512_to_1023_packets = UINT64_MAX; + stats->rx_1024_to_1518_packets = UINT64_MAX; + return 0; } diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c index 76815c2..b055abf 100644 --- a/lib/netdev-dummy.c +++ b/lib/netdev-dummy.c @@ -1020,6 +1020,18 @@ netdev_dummy_set_mtu(const struct netdev *netdev, int mtu) return 0; } +/* Initializes unused statistics to default values. */ +static void +netdev_dummy_set_unused_stats(struct netdev_stats *dst) +{ + dst->rx_1024_to_1518_packets = UINT64_MAX; + dst->rx_512_to_1023_packets = UINT64_MAX; + dst->rx_256_to_511_packets = UINT64_MAX; + dst->rx_128_to_255_packets = UINT64_MAX; + dst->rx_65_to_127_packets = UINT64_MAX; + dst->rx_64_packets = UINT64_MAX; +} + static int netdev_dummy_get_stats(const struct netdev *netdev, struct netdev_stats *stats) { @@ -1028,7 +1040,7 @@ netdev_dummy_get_stats(const struct netdev *netdev, struct netdev_stats *stats) ovs_mutex_lock(&dev->mutex); *stats = dev->stats; ovs_mutex_unlock(&dev->mutex); - + netdev_dummy_set_unused_stats(stats); return 0; } diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c index 584e804..d892517 100644 --- a/lib/netdev-linux.c +++ b/lib/netdev-linux.c @@ -1550,6 +1550,18 @@ swap_uint64(uint64_t *a, uint64_t *b) *b = tmp; } +/* Initializes unused statistics to default values. */ +static void +netdev_linux_set_unused_stats(struct netdev_stats *dst) +{ + dst->rx_1024_to_1518_packets = UINT64_MAX; + dst->rx_512_to_1023_packets = UINT64_MAX; + dst->rx_256_to_511_packets = UINT64_MAX; + dst->rx_128_to_255_packets = UINT64_MAX; + dst->rx_65_to_127_packets = UINT64_MAX; + dst->rx_64_packets = UINT64_MAX; +} + /* Copies 'src' into 'dst', performing format conversion in the process. * * 'src' is allowed to be misaligned. */ @@ -1580,6 +1592,7 @@ netdev_stats_from_ovs_vport_stats(struct netdev_stats *dst, dst->tx_window_errors = 0; } + static int get_stats_via_vport__(const struct netdev *netdev, struct netdev_stats *stats) { @@ -1671,6 +1684,8 @@ netdev_linux_get_stats(const struct netdev *netdev_, } ovs_mutex_unlock(&netdev->mutex); + netdev_linux_set_unused_stats(stats); + return error; } @@ -1733,6 +1748,8 @@ netdev_tap_get_stats(const struct netdev *netdev_, struct netdev_stats *stats) } ovs_mutex_unlock(&netdev->mutex); + netdev_linux_set_unused_stats(stats); + return error; } @@ -1748,6 +1765,8 @@ netdev_internal_get_stats(const struct netdev *netdev_, error = netdev->vport_stats_error; ovs_mutex_unlock(&netdev->mutex); + netdev_linux_set_unused_stats(stats); + return error; } diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c index ff50563..c1ecad1 100644 --- a/lib/netdev-vport.c +++ b/lib/netdev-vport.c @@ -812,6 +812,18 @@ set_patch_config(struct netdev *dev_, const struct smap *args) return 0; } +/* Initializes unused statistics to default values. */ +static void +netdev_vport_set_unused_stats(struct netdev_stats *dst) +{ + dst->rx_1024_to_1518_packets = UINT64_MAX; + dst->rx_512_to_1023_packets = UINT64_MAX; + dst->rx_256_to_511_packets = UINT64_MAX; + dst->rx_128_to_255_packets = UINT64_MAX; + dst->rx_65_to_127_packets = UINT64_MAX; + dst->rx_64_packets = UINT64_MAX; +} + static int get_stats(const struct netdev *netdev, struct netdev_stats *stats) { @@ -820,6 +832,7 @@ get_stats(const struct netdev *netdev, struct netdev_stats *stats) ovs_mutex_lock(&dev->mutex); *stats = dev->stats; ovs_mutex_unlock(&dev->mutex); + netdev_vport_set_unused_stats(stats); return 0; } diff --git a/lib/netdev.h b/lib/netdev.h index 0fbcb65..107e81e 100644 --- a/lib/netdev.h +++ b/lib/netdev.h @@ -102,6 +102,14 @@ struct netdev_stats { uint64_t tx_fifo_errors; uint64_t tx_heartbeat_errors; uint64_t tx_window_errors; + + /* Size bucket statistics. Based on RFC2819. */ + uint64_t rx_64_packets; + uint64_t rx_65_to_127_packets; + uint64_t rx_128_to_255_packets; + uint64_t rx_256_to_511_packets; + uint64_t rx_512_to_1023_packets; + uint64_t rx_1024_to_1518_packets; }; /* Configuration specific to tunnels. */ diff --git a/lib/ofp-msgs.h b/lib/ofp-msgs.h index bce5283..4335ccd 100644 --- a/lib/ofp-msgs.h +++ b/lib/ofp-msgs.h @@ -443,6 +443,12 @@ enum ofpraw { /* NXT 1.0+ (26): struct nx_geneve_table_reply, struct nx_geneve_map[]. */ OFPRAW_NXT_GENEVE_TABLE_REPLY, + + /* NXST 1.0+ (3): struct nx_port_stats_request. */ + OFPRAW_NXST_PORT_REQUEST, + + /* NXST 1.0+ (3): struct nx_port_stats[]. */ + OFPRAW_NXST_PORT_REPLY }; /* Decoding messages into OFPRAW_* values. */ @@ -590,11 +596,13 @@ enum ofptype { * OFPRAW_OFPST12_TABLE_REPLY. * OFPRAW_OFPST13_TABLE_REPLY. */ OFPTYPE_PORT_STATS_REQUEST, /* OFPRAW_OFPST10_PORT_REQUEST. - * OFPRAW_OFPST11_PORT_REQUEST. */ + * OFPRAW_OFPST11_PORT_REQUEST. + * OFPRAW_NXST_PORT_REQUEST. */ OFPTYPE_PORT_STATS_REPLY, /* OFPRAW_OFPST10_PORT_REPLY. * OFPRAW_OFPST11_PORT_REPLY. * OFPRAW_OFPST13_PORT_REPLY. - * OFPRAW_OFPST14_PORT_REPLY. */ + * OFPRAW_OFPST14_PORT_REPLY. + * OFPRAW_NXST_PORT_REPLY */ OFPTYPE_QUEUE_STATS_REQUEST, /* OFPRAW_OFPST10_QUEUE_REQUEST. * OFPRAW_OFPST11_QUEUE_REQUEST. */ OFPTYPE_QUEUE_STATS_REPLY, /* OFPRAW_OFPST10_QUEUE_REPLY. diff --git a/lib/ofp-print.c b/lib/ofp-print.c index d0c94ce..c7863e5 100644 --- a/lib/ofp-print.c +++ b/lib/ofp-print.c @@ -1565,6 +1565,7 @@ ofp_print_ofpst_port_reply(struct ds *string, const struct ofp_header *oh, int verbosity) { struct ofpbuf b; + enum ofpraw raw; ds_put_format(string, " %"PRIuSIZE" ports\n", ofputil_count_port_stats(oh)); if (verbosity < 1) { @@ -1590,26 +1591,45 @@ ofp_print_ofpst_port_reply(struct ds *string, const struct ofp_header *oh, } ofputil_format_port(ps.port_no, 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'); + if (!ofpraw_decode(&raw, b.header)) { + if (raw != OFPRAW_NXST_PORT_REPLY) { + 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'); + } + } else { + ds_put_cstr(string, ": rx "); + print_port_stat(string, "64_packets=", ps.stats.rx_64_packets, + 1); + print_port_stat(string, "65_to_127_packets=", + ps.stats.rx_65_to_127_packets, 1); + print_port_stat(string, "128_to_255_packets=", + ps.stats.rx_128_to_255_packets, 1); + print_port_stat(string, "256_to_511_packets=", + ps.stats.rx_256_to_511_packets, 1); + print_port_stat(string, "512_to_1023_packets=", + ps.stats.rx_512_to_1023_packets, 1); + print_port_stat(string, "1024_to_1518_packets=", + ps.stats.rx_1024_to_1518_packets, 0); + } } } } diff --git a/lib/ofp-util.c b/lib/ofp-util.c index b9dbcda..cae432a 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -6798,6 +6798,25 @@ ofputil_encode_dump_ports_request(enum ofp_version ofp_version, ofp_port_t port) return request; } +/* Encode a dump ports request for 'port', the encoded message + * will be for OpenFlow version 'ofp_version'. Returns message + * as a struct ofpbuf. Returns encoded message on success, NULL on error */ +struct ofpbuf * +ofputil_encode_dump_ports_ext_request(enum ofp_version ofp_version, + ofp_port_t port) +{ + struct ofpbuf *request; + struct nx_port_stats_request *npsr; + + request = + ofpraw_alloc(OFPRAW_NXST_PORT_REQUEST, ofp_version, NXM_TYPICAL_LEN); + ofpbuf_put_zeros(request, sizeof *npsr); + npsr = request->msg; + npsr->port_no = htons(ofp_to_u16(port)); + + return request; +} + static void ofputil_port_stats_to_ofp10(const struct ofputil_port_stats *ops, struct ofp10_port_stats *ps10) @@ -6819,6 +6838,20 @@ ofputil_port_stats_to_ofp10(const struct ofputil_port_stats *ops, } static void +ofputil_port_stats_to_nx10(const struct ofputil_port_stats *ops, + struct nx_port_stats *nx10stats) +{ + nx10stats->port_no = htons(ofp_to_u16(ops->port_no)); + memset(nx10stats->pad, 0, sizeof nx10stats->pad); + nx10stats->rx_64_packets = htonll(ops->stats.rx_64_packets); + nx10stats->rx_65_to_127_packets = htonll(ops->stats.rx_65_to_127_packets); + nx10stats->rx_128_to_255_packets = htonll(ops->stats.rx_128_to_255_packets); + nx10stats->rx_256_to_511_packets = htonll(ops->stats.rx_256_to_511_packets); + nx10stats->rx_512_to_1023_packets = htonll(ops->stats.rx_512_to_1023_packets); + nx10stats->rx_1024_to_1518_packets = htonll(ops->stats.rx_1024_to_1518_packets); +} + +static void ofputil_port_stats_to_ofp11(const struct ofputil_port_stats *ops, struct ofp11_port_stats *ps11) { @@ -6887,32 +6920,44 @@ void ofputil_append_port_stat(struct ovs_list *replies, const struct ofputil_port_stats *ops) { - switch (ofpmp_version(replies)) { - case OFP13_VERSION: { - struct ofp13_port_stats *reply = ofpmp_append(replies, sizeof *reply); - ofputil_port_stats_to_ofp13(ops, reply); - break; - } - case OFP12_VERSION: - case OFP11_VERSION: { - struct ofp11_port_stats *reply = ofpmp_append(replies, sizeof *reply); - ofputil_port_stats_to_ofp11(ops, reply); - break; - } + enum ofpraw raw = OFPRAW_OFPST10_PORT_REQUEST; - case OFP10_VERSION: { - struct ofp10_port_stats *reply = ofpmp_append(replies, sizeof *reply); - ofputil_port_stats_to_ofp10(ops, reply); - break; - } + raw = ofpmp_decode_raw(replies); - case OFP14_VERSION: - case OFP15_VERSION: - ofputil_append_ofp14_port_stats(ops, replies); - break; + if (OFPRAW_NXST_PORT_REPLY == raw) { + struct nx_port_stats *reply; - default: - OVS_NOT_REACHED(); + reply = ofpmp_append(replies, sizeof *reply); + ofputil_port_stats_to_nx10(ops, reply); + } else { + + switch (ofpmp_version(replies)) { + case OFP13_VERSION: { + struct ofp13_port_stats *reply = ofpmp_append(replies, sizeof *reply); + ofputil_port_stats_to_ofp13(ops, reply); + break; + } + case OFP12_VERSION: + case OFP11_VERSION: { + struct ofp11_port_stats *reply = ofpmp_append(replies, sizeof *reply); + ofputil_port_stats_to_ofp11(ops, reply); + break; + } + + case OFP10_VERSION: { + struct ofp10_port_stats *reply = ofpmp_append(replies, sizeof *reply); + ofputil_port_stats_to_ofp10(ops, reply); + break; + } + + case OFP14_VERSION: + case OFP15_VERSION: + ofputil_append_ofp14_port_stats(ops, replies); + break; + + default: + OVS_NOT_REACHED(); + } } } @@ -6942,6 +6987,27 @@ ofputil_port_stats_from_ofp10(struct ofputil_port_stats *ops, } static enum ofperr +ofputil_port_stats_from_nx10(struct ofputil_port_stats *ops, + const struct nx_port_stats *nx10stats) +{ + memset(ops, 0, sizeof *ops); + + ops->port_no = u16_to_ofp(ntohs(nx10stats->port_no)); + ops->stats.rx_64_packets = ntohll(nx10stats->rx_64_packets); + ops->stats.rx_65_to_127_packets = ntohll(nx10stats->rx_65_to_127_packets); + ops->stats.rx_128_to_255_packets = + ntohll(nx10stats->rx_128_to_255_packets); + ops->stats.rx_256_to_511_packets = + ntohll(nx10stats->rx_256_to_511_packets); + ops->stats.rx_512_to_1023_packets = + ntohll(nx10stats->rx_512_to_1023_packets); + ops->stats.rx_1024_to_1518_packets = + ntohll(nx10stats->rx_1024_to_1518_packets); + + return 0; +} + +static enum ofperr ofputil_port_stats_from_ofp11(struct ofputil_port_stats *ops, const struct ofp11_port_stats *ps11) { @@ -7115,13 +7181,13 @@ ofputil_decode_port_stats(struct ofputil_port_stats *ps, struct ofpbuf *msg) return ofputil_pull_ofp14_port_stats(ps, msg); } else if (raw == OFPRAW_OFPST13_PORT_REPLY) { const struct ofp13_port_stats *ps13; - ps13 = ofpbuf_try_pull(msg, sizeof *ps13); if (!ps13) { goto bad_len; } return ofputil_port_stats_from_ofp13(ps, ps13); } else if (raw == OFPRAW_OFPST11_PORT_REPLY) { + const struct ofp11_port_stats *ps11; ps11 = ofpbuf_try_pull(msg, sizeof *ps11); @@ -7137,6 +7203,15 @@ ofputil_decode_port_stats(struct ofputil_port_stats *ps, struct ofpbuf *msg) goto bad_len; } return ofputil_port_stats_from_ofp10(ps, ps10); + } else if (raw == OFPRAW_NXST_PORT_REPLY) { + const struct nx_port_stats *nxstats; + + nxstats = ofpbuf_try_pull(msg, sizeof *nxstats); + if (!nxstats) { + goto bad_len; + } + return ofputil_port_stats_from_nx10(ps, nxstats); + } else { OVS_NOT_REACHED(); } @@ -7154,24 +7229,35 @@ enum ofperr ofputil_decode_port_stats_request(const struct ofp_header *request, ofp_port_t *ofp10_port) { - switch ((enum ofp_version)request->version) { - case OFP15_VERSION: - case OFP14_VERSION: - case OFP13_VERSION: - case OFP12_VERSION: - case OFP11_VERSION: { - const struct ofp11_port_stats_request *psr11 = ofpmsg_body(request); - return ofputil_port_from_ofp11(psr11->port_no, ofp10_port); - } + enum ofpraw raw; + struct ofpbuf b; - case OFP10_VERSION: { - const struct ofp10_port_stats_request *psr10 = ofpmsg_body(request); - *ofp10_port = u16_to_ofp(ntohs(psr10->port_no)); - return 0; - } + ofpbuf_use_const(&b, request, ntohs(request->length)); + raw = ofpraw_pull_assert(&b); - default: - OVS_NOT_REACHED(); + if (OFPRAW_NXST_PORT_REQUEST == raw) { + const struct nx_port_stats_request *nxpsr = ofpmsg_body(request); + + *ofp10_port = u16_to_ofp(ntohs(nxpsr->port_no)); + return 0; + } else { + switch ((enum ofp_version)request->version) { + case OFP15_VERSION: + case OFP14_VERSION: + case OFP13_VERSION: + case OFP12_VERSION: + case OFP11_VERSION: { + const struct ofp11_port_stats_request *psr11 = ofpmsg_body(request); + return ofputil_port_from_ofp11(psr11->port_no, ofp10_port); + } + case OFP10_VERSION: { + const struct ofp10_port_stats_request *psr10 = ofpmsg_body(request); + *ofp10_port = u16_to_ofp(ntohs(psr10->port_no)); + return 0; + } + default: + OVS_NOT_REACHED(); + } } } diff --git a/lib/ofp-util.h b/lib/ofp-util.h index 8914342..3211c9e 100644 --- a/lib/ofp-util.h +++ b/lib/ofp-util.h @@ -999,6 +999,8 @@ struct ofputil_port_stats { struct ofpbuf *ofputil_encode_dump_ports_request(enum ofp_version ofp_version, ofp_port_t port); +struct ofpbuf *ofputil_encode_dump_ports_ext_request(enum ofp_version ofp_version, + ofp_port_t port); 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 *); diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index 0c315c1..2dd8783 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -349,6 +349,7 @@ usage(void) " set-frags SWITCH FRAG_MODE set fragment handling behavior\n" " FRAG_MODE: normal, drop, reassemble, nx-match\n" " dump-ports SWITCH [PORT] print port statistics\n" + " dump-ports-ext SWITCH [PORT] print port extended statistics\n" " dump-ports-desc SWITCH [PORT] print port descriptions\n" " dump-flows SWITCH print all flow entries\n" " dump-flows SWITCH FLOW print matching FLOWs\n" @@ -1036,12 +1037,28 @@ try_set_protocol(struct vconn *vconn, enum ofputil_protocol want, } } +static void +set_protocol_print_error(enum ofputil_protocol usable_protocols) +{ + char *usable_s; + + usable_s = ofputil_protocols_to_string(usable_protocols); + if (usable_protocols & allowed_protocols) { + ovs_fatal(0, "switch does not support any of the usable flow " + "formats (%s)", usable_s); + } else { + char *allowed_s = ofputil_protocols_to_string(allowed_protocols); + + ovs_fatal(0, "none of the usable flow formats (%s) is among the " + "allowed flow formats (%s)", usable_s, allowed_s); + } +} + static enum ofputil_protocol set_protocol_for_flow_dump(struct vconn *vconn, enum ofputil_protocol cur_protocol, enum ofputil_protocol usable_protocols) { - char *usable_s; int i; for (i = 0; i < ofputil_n_flow_dump_protocols; i++) { @@ -1052,15 +1069,8 @@ set_protocol_for_flow_dump(struct vconn *vconn, } } - usable_s = ofputil_protocols_to_string(usable_protocols); - if (usable_protocols & allowed_protocols) { - ovs_fatal(0, "switch does not support any of the usable flow " - "formats (%s)", usable_s); - } else { - char *allowed_s = ofputil_protocols_to_string(allowed_protocols); - ovs_fatal(0, "none of the usable flow formats (%s) is among the " - "allowed flow formats (%s)", usable_s, allowed_s); - } + set_protocol_print_error(usable_protocols); + return OFPUTIL_P_NONE; } static struct vconn * @@ -1782,21 +1792,50 @@ ofctl_snoop(struct ovs_cmdl_context *ctx) monitor_vconn(vconn, false); } +static struct vconn * +prepare_dump_ports(const char *name, ofp_port_t port, + struct ofpbuf **requestp, bool extended_stats) +{ + struct vconn *vconn; + + open_vconn(name, &vconn); + if (extended_stats) { + *requestp = + ofputil_encode_dump_ports_ext_request(vconn_get_version(vconn), + port); + } else { + *requestp = + ofputil_encode_dump_ports_request(vconn_get_version(vconn), port); + } + return vconn; +} + static void -ofctl_dump_ports(struct ovs_cmdl_context *ctx) +ofctl_dump_ports__(int argc, char *argv[], bool extended_stats) { struct ofpbuf *request; struct vconn *vconn; ofp_port_t port; - open_vconn(ctx->argv[1], &vconn); - port = ctx->argc > 2 ? str_to_port_no(ctx->argv[1], ctx->argv[2]) : OFPP_ANY; - request = ofputil_encode_dump_ports_request(vconn_get_version(vconn), port); + port = argc > 2 ? str_to_port_no(argv[1], argv[2]) : OFPP_ANY; + vconn = prepare_dump_ports(argv[1], port, &request, extended_stats); dump_stats_transaction(vconn, request); vconn_close(vconn); } static void +ofctl_dump_ports(struct ovs_cmdl_context *ctx) +{ + ofctl_dump_ports__(ctx->argc, ctx->argv, false); +} + +static void +ofctl_dump_ports_ext(struct ovs_cmdl_context *ctx) +{ + ofctl_dump_ports__(ctx->argc, ctx->argv, true); +} + +static void ofctl_dump_ports_desc(struct ovs_cmdl_context *ctx) { struct ofpbuf *request; @@ -3738,6 +3777,8 @@ static const struct ovs_cmdl_command all_commands[] = { 4, INT_MAX, ofctl_packet_out }, { "dump-ports", "switch [port]", 1, 2, ofctl_dump_ports }, + { "dump-ports-ext", "switch [port]", + 1, 2, ofctl_dump_ports_ext }, { "dump-ports-desc", "switch [port]", 1, 2, ofctl_dump_ports_desc }, { "mod-port", "switch iface act", diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 232a334..714c617 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -2335,18 +2335,24 @@ static void iface_refresh_stats(struct iface *iface) { #define IFACE_STATS \ - IFACE_STAT(rx_packets, "rx_packets") \ - IFACE_STAT(tx_packets, "tx_packets") \ - IFACE_STAT(rx_bytes, "rx_bytes") \ - IFACE_STAT(tx_bytes, "tx_bytes") \ - IFACE_STAT(rx_dropped, "rx_dropped") \ - IFACE_STAT(tx_dropped, "tx_dropped") \ - IFACE_STAT(rx_errors, "rx_errors") \ - IFACE_STAT(tx_errors, "tx_errors") \ - IFACE_STAT(rx_frame_errors, "rx_frame_err") \ - IFACE_STAT(rx_over_errors, "rx_over_err") \ - IFACE_STAT(rx_crc_errors, "rx_crc_err") \ - IFACE_STAT(collisions, "collisions") + IFACE_STAT(rx_packets, "rx_packets") \ + IFACE_STAT(tx_packets, "tx_packets") \ + IFACE_STAT(rx_bytes, "rx_bytes") \ + IFACE_STAT(tx_bytes, "tx_bytes") \ + IFACE_STAT(rx_dropped, "rx_dropped") \ + IFACE_STAT(tx_dropped, "tx_dropped") \ + IFACE_STAT(rx_errors, "rx_errors") \ + IFACE_STAT(tx_errors, "tx_errors") \ + IFACE_STAT(rx_frame_errors, "rx_frame_err") \ + IFACE_STAT(rx_over_errors, "rx_over_err") \ + IFACE_STAT(rx_crc_errors, "rx_crc_err") \ + IFACE_STAT(collisions, "collisions") \ + IFACE_STAT(rx_64_packets, "rx_64_packets") \ + IFACE_STAT(rx_65_to_127_packets, "rx_65_to_127_packets") \ + IFACE_STAT(rx_128_to_255_packets, "rx_128_to_255_packets") \ + IFACE_STAT(rx_256_to_511_packets, "rx_256_to_511_packets") \ + IFACE_STAT(rx_512_to_1023_packets, "rx_512_to_1023_packets") \ + IFACE_STAT(rx_1024_to_1518_packets, "rx_1024_to_1518_packets") #define IFACE_STAT(MEMBER, NAME) + 1 enum { N_IFACE_STATS = IFACE_STATS };