ovs-dpctl: Add -s option to print packet and byte counters.
authorBen Pfaff <blp@nicira.com>
Thu, 28 Apr 2011 20:02:15 +0000 (13:02 -0700)
committerBen Pfaff <blp@nicira.com>
Mon, 2 May 2011 16:33:12 +0000 (09:33 -0700)
ChangeLog
lib/dpif-linux.c
lib/dpif.c
lib/dpif.h
utilities/ovs-dpctl.8.in
utilities/ovs-dpctl.c

index 18f9228089073489d561782877cc9a1176178660..bd0c40da1c5068a8afe287665c282850994dad4b 100644 (file)
--- 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.)
index 7b36709109403ec051b39755c6061bc2c1e6f633..0aad8671ec8e0d311714b3231e96795b77c75233 100644 (file)
@@ -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;
 }
 
index 81e180fbb2af887772b5abe2e659b9d0971cae1c..630bcade6411e92f6b512abd6180f502be64aedc 100644 (file)
@@ -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'.
index 0e0f407c3244f8abdac5478744874e5630cefdff..a039f1134668bb54af14baa9c1a5754e1524817c 100644 (file)
@@ -23,6 +23,7 @@
 #include <stdint.h>
 #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 *);
index 58b3ea0ea94815c45d782ad0509ab558f6c28e75..5b5941bedf403c22b4d934892fb34a399ceacc4a 100644 (file)
@@ -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
index 9d6bf98520def196206c0b552aa87ca0649a4cf1..40048b445cd17a5a225c28b4934ae304f673b706 100644 (file)
@@ -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);
 }