Added new interface statistics.
authorJustin Pettit <jpettit@nicira.com>
Fri, 15 Aug 2008 06:12:37 +0000 (23:12 -0700)
committerJustin Pettit <jpettit@nicira.com>
Fri, 15 Aug 2008 06:12:37 +0000 (23:12 -0700)
datapath/datapath.c
include/openflow.h
lib/ofp-print.c
switch/datapath.c

index 2b40e3caa43778418aa0962e5c8007c8d146484a..5b5967605f923195d67220a436394e1d5558a021 100644 (file)
@@ -554,7 +554,7 @@ int dp_output_port(struct datapath *dp, struct sk_buff *skb, int out_port)
        case OFPP_IN_PORT:
                /* Send it out the port it came in on, which is already set in
                 * the skb. */
-        if (!skb->dev) {
+               if (!skb->dev) {
                        if (net_ratelimit())
                                printk("skb device not set forwarding to in_port\n");
                        kfree(skb);
@@ -1299,10 +1299,18 @@ static int port_stats_dump(struct datapath *dp, void *state,
                stats = p->dev->get_stats(p->dev);
                ops->port_no = htons(p->port_no);
                memset(ops->pad, 0, sizeof ops->pad);
-               ops->rx_count = cpu_to_be64(stats->rx_packets);
-               ops->tx_count = cpu_to_be64(stats->tx_packets);
-               ops->drop_count = cpu_to_be64(stats->rx_dropped
-                                             + stats->tx_dropped);
+               ops->rx_packets   = cpu_to_be64(stats->rx_packets);
+               ops->tx_packets   = cpu_to_be64(stats->tx_packets);
+               ops->rx_bytes     = cpu_to_be64(stats->rx_bytes);
+               ops->tx_bytes     = cpu_to_be64(stats->tx_bytes);
+               ops->rx_dropped   = cpu_to_be64(stats->rx_dropped);
+               ops->tx_dropped   = cpu_to_be64(stats->tx_dropped);
+               ops->rx_errors    = cpu_to_be64(stats->rx_errors);
+               ops->tx_errors    = cpu_to_be64(stats->tx_errors);
+               ops->rx_frame_err = cpu_to_be64(stats->rx_frame_errors);
+               ops->rx_over_err  = cpu_to_be64(stats->rx_over_errors);
+               ops->rx_crc_err   = cpu_to_be64(stats->rx_crc_errors);
+               ops->collisions   = cpu_to_be64(stats->collisions);
                n_ports++;
                ops++;
        }
index e5d600fac4d6e3e7fe261a5a54e56a7802253806..ba25687b5ecbbbc77fafce2612cfea045616e89f 100644 (file)
@@ -68,7 +68,7 @@
 /* The most significant bit being set in the version field indicates an
  * experimental OpenFlow version.  
  */
-#define OFP_VERSION   0x87
+#define OFP_VERSION   0x88
 
 #define OFP_MAX_TABLE_NAME_LEN 32
 #define OFP_MAX_PORT_NAME_LEN  16
@@ -522,14 +522,27 @@ struct ofp_table_stats {
 };
 OFP_ASSERT(sizeof(struct ofp_table_stats) == 56);
 
-/* Statistics about a particular port */
+/* Statistics about a particular port.  If a counter is unsupported, set
+ * the field to all ones. */
 struct ofp_port_stats {
     uint16_t port_no;
-    uint8_t pad[6];          /* Align to 64-bits */
-    uint64_t rx_count;       /* Number of received packets */
-    uint64_t tx_count;       /* Number of transmitted packets */
-    uint64_t drop_count;     /* Number of packets dropped by interface */
-};
-OFP_ASSERT(sizeof(struct ofp_port_stats) == 32);
+    uint8_t pad[6];          /* Align to 64-bits. */
+    uint64_t rx_packets;     /* Number of received packets. */
+    uint64_t tx_packets;     /* Number of transmitted packets. */
+    uint64_t rx_bytes;       /* Number of received bytes. */
+    uint64_t tx_bytes;       /* Number of transmitted bytes. */
+    uint64_t rx_dropped;     /* Number of packets dropped by RX. */ 
+    uint64_t tx_dropped;     /* Number of packets dropped by TX. */ 
+    uint64_t rx_errors;      /* Number of receive errors.  This is a super-set
+                                of receive errors and should be great than or
+                                equal to the sum of al rx_*_err values. */
+    uint64_t tx_errors;      /* Number of transmit errors.  This is a super-set
+                                of transmit errors. */
+    uint64_t rx_frame_err;   /* Number of frame alignment errors. */ 
+    uint64_t rx_over_err;    /* Number of packets with RX overrun. */ 
+    uint64_t rx_crc_err;     /* Number of CRC errors. */ 
+    uint64_t collisions;     /* Number of collisions. */ 
+};
+OFP_ASSERT(sizeof(struct ofp_port_stats) == 104);
 
 #endif /* openflow.h */
index 7e46999a5447099dc3dbb37bed8b40a5dcf00849..01e49b78ce4606cf53ca5167fb7782bf00232240 100644 (file)
@@ -656,6 +656,22 @@ ofp_aggregate_stats_reply(struct ds *string, const void *body_, size_t len,
     ds_put_format(string, " flow_count=%"PRIu32, ntohl(asr->flow_count));
 }
 
+static void print_port_stat(struct ds *string, const char *leader, 
+                            uint64_t stat, int more)
+{
+    ds_put_cstr(string, leader);
+    if (stat != -1) {
+        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
 ofp_port_stats_reply(struct ds *string, const void *body, size_t len,
                      int verbosity)
@@ -668,10 +684,23 @@ ofp_port_stats_reply(struct ds *string, const void *body, size_t len,
     }
 
     for (; n--; ps++) {
-        ds_put_format(string, "  port %"PRIu16": ", ntohs(ps->port_no));
-        ds_put_format(string, "rx %"PRIu64", ", ntohll(ps->rx_count));
-        ds_put_format(string, "tx %"PRIu64", ", ntohll(ps->tx_count));
-        ds_put_format(string, "dropped %"PRIu64"\n", ntohll(ps->drop_count));
+        ds_put_format(string, "  port %2"PRIu16": ", ntohs(ps->port_no));
+
+        ds_put_cstr(string, "rx ");
+        print_port_stat(string, "pkts=", ntohll(ps->rx_packets), 1);
+        print_port_stat(string, "bytes=", ntohll(ps->rx_bytes), 1);
+        print_port_stat(string, "drop=", ntohll(ps->rx_dropped), 1);
+        print_port_stat(string, "errs=", ntohll(ps->rx_errors), 1);
+        print_port_stat(string, "frame=", ntohll(ps->rx_frame_err), 1);
+        print_port_stat(string, "over=", ntohll(ps->rx_over_err), 1);
+        print_port_stat(string, "crc=", ntohll(ps->rx_crc_err), 0);
+
+        ds_put_cstr(string, "           tx ");
+        print_port_stat(string, "pkts=", ntohll(ps->tx_packets), 1);
+        print_port_stat(string, "bytes=", ntohll(ps->tx_bytes), 1);
+        print_port_stat(string, "drop=", ntohll(ps->tx_dropped), 1);
+        print_port_stat(string, "errs=", ntohll(ps->tx_errors), 1);
+        print_port_stat(string, "coll=", ntohll(ps->collisions), 0);
     }
 }
 
index e98106395baeda5489e3b5f486e20006a3a300a7..4e7b6256bfb775ec4c5c85fd06e885f69212282f 100644 (file)
@@ -77,7 +77,9 @@ struct sw_port {
     struct datapath *dp;
     struct netdev *netdev;
     struct list node; /* Element in datapath.ports. */
-    unsigned long long int rx_count, tx_count, drop_count;
+    unsigned long long int rx_packets, tx_packets;
+    unsigned long long int rx_bytes, tx_bytes;
+    unsigned long long int tx_dropped;
 };
 
 /* The origin of a received OpenFlow message, to enable sending a reply. */
@@ -249,11 +251,10 @@ dp_add_port(struct datapath *dp, const char *name)
         }
     }
 
+    memset(p, '\0', sizeof *p);
+
     p->dp = dp;
     p->netdev = netdev;
-    p->tx_count = 0;
-    p->rx_count = 0;
-    p->drop_count = 0;
     list_push_back(&dp->port_list, &p->node);
 
     /* Notify the ctlpath that this port has been added */
@@ -306,7 +307,8 @@ dp_run(struct datapath *dp)
         }
         error = netdev_recv(p->netdev, buffer);
         if (!error) {
-            p->rx_count++;
+            p->rx_packets++;
+            p->rx_bytes += buffer->size;
             fwd_port_input(dp, buffer, port_no(dp, p));
             buffer = NULL;
         } else if (error != EAGAIN) {
@@ -525,9 +527,10 @@ output_packet(struct datapath *dp, struct buffer *buffer, int out_port)
         struct sw_port *p = &dp->ports[out_port];
         if (p->netdev != NULL) {
             if (!netdev_send(p->netdev, buffer)) {
-                p->tx_count++;
+                p->tx_packets++;
+                p->tx_bytes += buffer->size;
             } else {
-                p->drop_count++;
+                p->tx_dropped++;
             }
             return;
         }
@@ -1323,9 +1326,18 @@ static int port_stats_dump(struct datapath *dp, void *state,
         ops = buffer_put_uninit(buffer, sizeof *ops);
         ops->port_no = htons(port_no(dp, p));
         memset(ops->pad, 0, sizeof ops->pad);
-        ops->rx_count = htonll(p->rx_count);
-        ops->tx_count = htonll(p->tx_count);
-        ops->drop_count = htonll(p->drop_count);
+        ops->rx_packets   = htonll(p->rx_packets);
+        ops->tx_packets   = htonll(p->tx_packets);
+        ops->rx_bytes     = htonll(p->rx_bytes);
+        ops->tx_bytes     = htonll(p->tx_bytes);
+        ops->rx_dropped   = htonll(-1);
+        ops->tx_dropped   = htonll(p->tx_dropped);
+        ops->rx_errors    = htonll(-1);
+        ops->tx_errors    = htonll(-1);
+        ops->rx_frame_err = htonll(-1);
+        ops->rx_over_err  = htonll(-1);
+        ops->rx_crc_err   = htonll(-1);
+        ops->collisions   = htonll(-1);
         ops++;
     }
     s->port = i;