From 032aa6a3543621213f133aff3e31021dfd4bef43 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Thu, 28 Apr 2011 13:02:15 -0700 Subject: [PATCH] ovs-dpctl: Add -s option to print packet and byte counters. --- ChangeLog | 2 ++ lib/dpif-linux.c | 12 ++++++++ lib/dpif.c | 1 + lib/dpif.h | 3 +- utilities/ovs-dpctl.8.in | 9 ++++-- utilities/ovs-dpctl.c | 62 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 86 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 18f92280..bd0c40da 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ post v1.1.0 ------------------------ + - The new "-s" option for "ovs-dpctl show" prints packet and byte + counters for each port. - Feature removals: - Dropped support for "tun_id_from_cookie" OpenFlow extension. (Use the extensible match extensions instead.) diff --git a/lib/dpif-linux.c b/lib/dpif-linux.c index 7b367091..0aad8671 100644 --- a/lib/dpif-linux.c +++ b/lib/dpif-linux.c @@ -35,6 +35,7 @@ #include "bitmap.h" #include "dpif-provider.h" #include "netdev.h" +#include "netdev-linux.h" #include "netdev-vport.h" #include "netlink-socket.h" #include "netlink.h" @@ -431,6 +432,12 @@ dpif_linux_port_query__(const struct dpif *dpif, uint32_t port_no, dpif_port->name = xstrdup(reply.name); dpif_port->type = xstrdup(netdev_vport_get_netdev_type(&reply)); dpif_port->port_no = reply.port_no; + if (reply.stats) { + netdev_stats_from_rtnl_link_stats64(&dpif_port->stats, + reply.stats); + } else { + memset(&dpif_port->stats, 0xff, sizeof dpif_port->stats); + } ofpbuf_delete(buf); } return error; @@ -526,6 +533,11 @@ dpif_linux_port_dump_next(const struct dpif *dpif OVS_UNUSED, void *state_, dpif_port->name = (char *) vport.name; dpif_port->type = (char *) netdev_vport_get_netdev_type(&vport); dpif_port->port_no = vport.port_no; + if (vport.stats) { + netdev_stats_from_rtnl_link_stats64(&dpif_port->stats, vport.stats); + } else { + memset(&dpif_port->stats, 0xff, sizeof dpif_port->stats); + } return 0; } diff --git a/lib/dpif.c b/lib/dpif.c index 81e180fb..630bcade 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -472,6 +472,7 @@ dpif_port_clone(struct dpif_port *dst, const struct dpif_port *src) dst->name = xstrdup(src->name); dst->type = xstrdup(src->type); dst->port_no = src->port_no; + dst->stats = src->stats; } /* Frees memory allocated to members of 'dpif_port'. diff --git a/lib/dpif.h b/lib/dpif.h index 0e0f407c..a039f113 100644 --- a/lib/dpif.h +++ b/lib/dpif.h @@ -23,6 +23,7 @@ #include #include "openflow/openflow.h" #include "openvswitch/datapath-protocol.h" +#include "netdev.h" #include "util.h" #ifdef __cplusplus @@ -31,7 +32,6 @@ extern "C" { struct dpif; struct ds; -struct netdev; struct nlattr; struct ofpbuf; struct sset; @@ -71,6 +71,7 @@ struct dpif_port { char *name; /* Network device name, e.g. "eth0". */ char *type; /* Network device type, e.g. "system". */ uint32_t port_no; /* Port number within datapath. */ + struct netdev_stats stats; /* Port statistics. */ }; void dpif_port_clone(struct dpif_port *, const struct dpif_port *); void dpif_port_destroy(struct dpif_port *); diff --git a/utilities/ovs-dpctl.8.in b/utilities/ovs-dpctl.8.in index 58b3ea0e..5b5941be 100644 --- a/utilities/ovs-dpctl.8.in +++ b/utilities/ovs-dpctl.8.in @@ -78,10 +78,12 @@ Removes each \fInetdev\fR from the list of network devices datapath Prints the name of each configured datapath on a separate line. . .TP -\fBshow \fR[\fIdp\fR...] +[\fB\-s\fR | \fB\-\-statistics\fR] \fBshow \fR[\fIdp\fR...] Prints a summary of configured datapaths, including their datapath numbers and a list of ports connected to each datapath. (The local -port is identified as port 0.) +port is identified as port 0.) If \fB\-s\fR or \fB\-\-statistics\fR +is specified, then packet and byte counters are also printed for each +port. .IP If one or more datapaths are specified, information on only those datapaths are displayed. Otherwise, \fBovs\-dpctl\fR displays information @@ -104,6 +106,9 @@ not OpenFlow flow entries. By deleting them, the process that set them up may be confused about their disappearance. . .SH OPTIONS +.IP "\fB\-s\fR, \fB\-\-statistics\fR" +Causes the \fBshow\fR command to print packet and byte counters for +each port within the datapaths that it shows. .TP \fB\-t\fR, \fB\-\-timeout=\fIsecs\fR Limits \fBovs\-dpctl\fR runtime to approximately \fIsecs\fR seconds. If diff --git a/utilities/ovs-dpctl.c b/utilities/ovs-dpctl.c index 9d6bf985..40048b44 100644 --- a/utilities/ovs-dpctl.c +++ b/utilities/ovs-dpctl.c @@ -45,6 +45,9 @@ VLOG_DEFINE_THIS_MODULE(dpctl); +/* -s, --statistics: Print port statistics? */ +bool print_statistics; + static const struct command all_commands[]; static void usage(void) NO_RETURN; @@ -68,6 +71,7 @@ parse_options(int argc, char *argv[]) VLOG_OPTION_ENUMS }; static struct option long_options[] = { + {"statistics", no_argument, 0, 's'}, {"timeout", required_argument, 0, 't'}, {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, @@ -86,6 +90,10 @@ parse_options(int argc, char *argv[]) } switch (c) { + case 's': + print_statistics = true; + break; + case 't': timeout = strtoul(optarg, NULL, 10); if (timeout <= 0) { @@ -320,6 +328,33 @@ do_del_if(int argc OVS_UNUSED, char *argv[]) } } +static void +print_stat(const char *leader, uint64_t value) +{ + fputs(leader, stdout); + if (value != UINT64_MAX) { + printf("%"PRIu64, value); + } else { + putchar('?'); + } +} + +static void +print_human_size(uint64_t value) +{ + if (value == UINT64_MAX) { + /* Nothing to do. */ + } else if (value >= 1024ULL * 1024 * 1024 * 1024) { + printf(" (%.1f TiB)", value / (1024.0 * 1024 * 1024 * 1024)); + } else if (value >= 1024ULL * 1024 * 1024) { + printf(" (%.1f GiB)", value / (1024.0 * 1024 * 1024)); + } else if (value >= 1024ULL * 1024) { + printf(" (%.1f MiB)", value / (1024.0 * 1024)); + } else if (value >= 1024) { + printf(" (%.1f KiB)", value / 1024.0); + } +} + static void show_dpif(struct dpif *dpif) { @@ -371,6 +406,33 @@ show_dpif(struct dpif *dpif) putchar(')'); } putchar('\n'); + + if (print_statistics) { + const struct netdev_stats *s = &dpif_port.stats; + + print_stat("\t\tRX packets:", s->rx_packets); + print_stat(" errors:", s->rx_errors); + print_stat(" dropped:", s->rx_dropped); + print_stat(" overruns:", s->rx_over_errors); + print_stat(" frame:", s->rx_frame_errors); + printf("\n"); + + print_stat("\t\tTX packets:", s->tx_packets); + print_stat(" errors:", s->tx_errors); + print_stat(" dropped:", s->tx_dropped); + print_stat(" aborted:", s->tx_aborted_errors); + print_stat(" carrier:", s->tx_carrier_errors); + printf("\n"); + + print_stat("\t\tcollisions:", s->collisions); + printf("\n"); + + print_stat("\t\tRX bytes:", s->rx_bytes); + print_human_size(s->rx_bytes); + print_stat(" TX bytes:", s->tx_bytes); + print_human_size(s->tx_bytes); + printf("\n"); + } } dpif_close(dpif); } -- 2.30.2