diff --git a/master/cdev.c b/master/cdev.c index 42014dd2645090e44d526b7765216f0692f72804..90d07fdcbdd6912721270569175193b87a923b1c 100644 --- a/master/cdev.c +++ b/master/cdev.c @@ -184,6 +184,7 @@ int ec_cdev_ioctl_master( ) { ec_ioctl_master_t data; + unsigned int i; if (down_interruptible(&master->master_sem)) return -EINTR; @@ -211,6 +212,10 @@ int ec_cdev_ioctl_master( 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 @@ int ec_cdev_ioctl_master( 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); diff --git a/master/device.c b/master/device.c index d639d0c7feed67bf743ec99ecdfd5565bf041f6d..daf7cca1ea76bea1b7d443387be52d4d938c035e 100644 --- a/master/device.c +++ b/master/device.c @@ -54,6 +54,10 @@ } while (0) #endif +static const unsigned int rate_intervals[] = { + 1, 10, 60 +}; + /*****************************************************************************/ /** Constructor. @@ -196,6 +200,13 @@ void ec_device_detach( 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 ec_device_open( ) { int ret; + unsigned int i; if (!device->dev) { EC_ERR("No net_device to open!\n"); @@ -225,6 +237,13 @@ int ec_device_open( 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 @@ void ec_device_send( { 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; diff --git a/master/device.h b/master/device.h index ebc7609d83eb15712228fed50fb9cc342de2de9d..c5c8882b979e76cbffb510b77a17362c595887a1 100644 --- a/master/device.h +++ b/master/device.h @@ -98,6 +98,11 @@ struct ec_device 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 diff --git a/master/globals.h b/master/globals.h index fdb34f678b809b040794ef72dbd9303d3e5daeb0..e17a7547023a09da2bd3d67c3e867cf8d7794ed0 100644 --- a/master/globals.h +++ b/master/globals.h @@ -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 *****************************************************************************/ diff --git a/master/ioctl.h b/master/ioctl.h index 84831b57454a9ed80e2e13d3e48418923b2c2460..25e0771b7e045372d52926d6e6138a0da47314d3 100644 --- a/master/ioctl.h +++ b/master/ioctl.h @@ -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 @@ typedef struct { 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; diff --git a/tool/CommandMaster.cpp b/tool/CommandMaster.cpp index c8ed982589bfdfa1f2f9e74874680ca7ad60bacf..28c42967c05a92b8769045fb1eb29b9db0896873 100644 --- a/tool/CommandMaster.cpp +++ b/tool/CommandMaster.cpp @@ -69,7 +69,7 @@ void CommandMaster::execute(const StringVector &args) { 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 @@ void CommandMaster::execute(const StringVector &args) << " 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; }