Frame statistics in 'ethercat master' output.
authorFlorian Pose <fp@igh-essen.com>
Sun, 07 Mar 2010 23:55:51 +0100
changeset 1851 a56bd34e20a1
parent 1850 fa112b8a371b
child 1852 1ec9f781f3ef
Frame statistics in 'ethercat master' output.
master/cdev.c
master/device.c
master/device.h
master/globals.h
master/ioctl.h
tool/CommandMaster.cpp
--- a/master/cdev.c	Sun Mar 07 23:12:30 2010 +0100
+++ b/master/cdev.c	Sun Mar 07 23:55:51 2010 +0100
@@ -184,6 +184,7 @@
         )
 {
     ec_ioctl_master_t data;
+    unsigned int i;
 
     if (down_interruptible(&master->master_sem))
         return -EINTR;
@@ -211,6 +212,10 @@
     data.devices[0].link_state = master->main_device.link_state ? 1 : 0;
     data.devices[0].tx_count = master->main_device.tx_count;
     data.devices[0].rx_count = master->main_device.rx_count;
+    for (i = 0; i < EC_RATE_COUNT; i++) {
+        data.devices[0].tx_rates[i] = master->main_device.tx_rates[i];
+        data.devices[0].loss_rates[i] = master->main_device.loss_rates[i];
+    }
 
     if (master->backup_device.dev) {
         memcpy(data.devices[1].address,
@@ -222,6 +227,10 @@
     data.devices[1].link_state = master->backup_device.link_state ? 1 : 0;
     data.devices[1].tx_count = master->backup_device.tx_count;
     data.devices[1].rx_count = master->backup_device.rx_count;
+    for (i = 0; i < EC_RATE_COUNT; i++) {
+        data.devices[1].tx_rates[i] = master->backup_device.tx_rates[i];
+        data.devices[1].loss_rates[i] = master->backup_device.loss_rates[i];
+    }
 
     up(&master->device_sem);
 
--- a/master/device.c	Sun Mar 07 23:12:30 2010 +0100
+++ b/master/device.c	Sun Mar 07 23:55:51 2010 +0100
@@ -54,6 +54,10 @@
     } while (0)
 #endif
 
+static const unsigned int rate_intervals[] = {
+    1, 10, 60
+};
+
 /*****************************************************************************/
 
 /** Constructor.
@@ -196,6 +200,13 @@
     device->link_state = 0; // down
     device->tx_count = 0;
     device->rx_count = 0;
+    device->last_tx_count = 0;
+    device->last_loss = 0;
+    for (i = 0; i < EC_RATE_COUNT; i++) {
+        device->tx_rates[i] = 0;
+        device->loss_rates[i] = 0;
+    }
+    device->stats_jiffies = 0;
     for (i = 0; i < EC_TX_RING_SIZE; i++)
         device->tx_skb[i]->dev = NULL;
 }
@@ -211,6 +222,7 @@
         )
 {
     int ret;
+    unsigned int i;
 
     if (!device->dev) {
         EC_ERR("No net_device to open!\n");
@@ -225,6 +237,13 @@
     device->link_state = 0;
     device->tx_count = 0;
     device->rx_count = 0;
+    device->last_tx_count = 0;
+    device->last_loss = 0;
+    for (i = 0; i < EC_RATE_COUNT; i++) {
+        device->tx_rates[i] = 0;
+        device->loss_rates[i] = 0;
+    }
+    device->stats_jiffies = 0;
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
     ret = device->dev->netdev_ops->ndo_open(device->dev);
@@ -302,6 +321,26 @@
 {
     struct sk_buff *skb = device->tx_skb[device->tx_ring_index];
 
+    // frame statistics
+    if (unlikely(jiffies - device->stats_jiffies >= HZ)) {
+        unsigned int i;
+        unsigned int tx_rate = device->tx_count - device->last_tx_count;
+        int loss = device->tx_count - device->rx_count;
+        int loss_rate = (loss - device->last_loss) * 1000;
+        for (i = 0; i < EC_RATE_COUNT; i++) {
+            unsigned int n = rate_intervals[i];
+            device->tx_rates[i] =
+                device->tx_rates[i] * (n - 1) +
+                tx_rate * n;
+            device->loss_rates[i] =
+                device->loss_rates[i] * (n - 1) +
+                loss_rate * n;
+        }
+        device->last_tx_count = device->tx_count;
+        device->last_loss = loss;
+        device->stats_jiffies += HZ;
+    }
+
     if (unlikely(!device->link_state)) // Link down
         return;
 
--- a/master/device.h	Sun Mar 07 23:12:30 2010 +0100
+++ b/master/device.h	Sun Mar 07 23:55:51 2010 +0100
@@ -98,6 +98,11 @@
     unsigned long jiffies_poll; /**< jiffies of last poll */
     unsigned int tx_count; /**< number of frames sent */
     unsigned int rx_count; /**< number of frames received */
+    unsigned int last_tx_count;
+    unsigned int tx_rates[EC_RATE_COUNT];
+    int last_loss; /**< Tx/Rx difference of last cycle. */
+    int loss_rates[EC_RATE_COUNT];
+    unsigned long stats_jiffies;
 #ifdef EC_DEBUG_IF
     ec_debug_t dbg; /**< debug device */
 #endif
--- a/master/globals.h	Sun Mar 07 23:12:30 2010 +0100
+++ b/master/globals.h	Sun Mar 07 23:55:51 2010 +0100
@@ -70,6 +70,9 @@
 /** Maximum SII size in words, to avoid infinite reading. */
 #define EC_MAX_SII_SIZE 4096
 
+/** Number of statistic rate intervals to maintain. */
+#define EC_RATE_COUNT 3
+
 /******************************************************************************
  * EtherCAT protocol
  *****************************************************************************/
--- a/master/ioctl.h	Sun Mar 07 23:12:30 2010 +0100
+++ b/master/ioctl.h	Sun Mar 07 23:55:51 2010 +0100
@@ -56,7 +56,7 @@
  *
  * Increment this when changing the ioctl interface!
  */
-#define EC_IOCTL_VERSION_MAGIC 3
+#define EC_IOCTL_VERSION_MAGIC 4
 
 // Command-line tool
 #define EC_IOCTL_MODULE                EC_IOR(0x00, ec_ioctl_module_t)
@@ -163,6 +163,8 @@
         uint8_t link_state;
         uint32_t tx_count;
         uint32_t rx_count;
+        uint32_t tx_rates[EC_RATE_COUNT];
+        int32_t loss_rates[EC_RATE_COUNT];
     } devices[2];
     uint64_t app_time;
     uint16_t ref_clock;
--- a/tool/CommandMaster.cpp	Sun Mar 07 23:12:30 2010 +0100
+++ b/tool/CommandMaster.cpp	Sun Mar 07 23:55:51 2010 +0100
@@ -69,7 +69,7 @@
 {
     ec_ioctl_master_t data;
     stringstream err;
-    unsigned int i;
+    unsigned int i, j;
     time_t epoch;
     char time_str[MAX_TIME_STR_SIZE + 1];
     size_t time_str_size;
@@ -130,7 +130,36 @@
                     << "      Link: "
                     << (data.devices[i].link_state ? "UP" : "DOWN") << endl
                     << "      Tx count: " << data.devices[i].tx_count << endl
-                    << "      Rx count: " << data.devices[i].rx_count;
+                    << "      Rx count: " << data.devices[i].rx_count << endl
+                    << "      Tx rates: ";
+                for (j = 0; j < EC_RATE_COUNT; j++) {
+                    cout << data.devices[i].tx_rates[j] / 1000;
+                    if (j < EC_RATE_COUNT - 1) {
+                        cout << " ";
+                    }
+                }
+                cout << endl
+                    << "      Loss rates: ";
+                for (j = 0; j < EC_RATE_COUNT; j++) {
+                    cout << data.devices[i].loss_rates[j] / 1000;
+                    if (j < EC_RATE_COUNT - 1) {
+                        cout << " ";
+                    }
+                }
+                cout << endl
+                    << "      Loss percentages: " << setprecision(1);
+                for (j = 0; j < EC_RATE_COUNT; j++) {
+                    double perc = 0.0;
+                    if (data.devices[i].tx_rates[j]) {
+                        perc = 100.0 * data.devices[i].loss_rates[j] /
+                            data.devices[i].tx_rates[j];
+                    }
+                    cout << perc;
+                    if (j < EC_RATE_COUNT - 1) {
+                        cout << " ";
+                    }
+                }
+                cout << setprecision(0) << endl;
             }
             cout << endl;
         }