Adjusted frame statistics for the use with two devices.

This commit is contained in:
Florian Pose 2011-11-09 14:53:33 +01:00
parent 6127a95283
commit ed7f9885b2
7 changed files with 316 additions and 64 deletions

View File

@ -213,13 +213,17 @@ int ec_cdev_ioctl_master(
data.devices[0].tx_count = master->main_device.tx_count;
data.devices[0].rx_count = master->main_device.rx_count;
data.devices[0].tx_bytes = master->main_device.tx_bytes;
data.devices[0].rx_bytes = master->main_device.rx_bytes;
data.devices[0].tx_errors = master->main_device.tx_errors;
for (i = 0; i < EC_RATE_COUNT; i++) {
data.devices[0].tx_frame_rates[i] =
master->main_device.tx_frame_rates[i];
data.devices[0].rx_frame_rates[i] =
master->main_device.rx_frame_rates[i];
data.devices[0].tx_byte_rates[i] =
master->main_device.tx_byte_rates[i];
data.devices[0].loss_rates[i] = master->main_device.loss_rates[i];
data.devices[0].rx_byte_rates[i] =
master->main_device.rx_byte_rates[i];
}
if (master->backup_device.dev) {
@ -233,13 +237,34 @@ int ec_cdev_ioctl_master(
data.devices[1].tx_count = master->backup_device.tx_count;
data.devices[1].rx_count = master->backup_device.rx_count;
data.devices[1].tx_bytes = master->backup_device.tx_bytes;
data.devices[1].rx_bytes = master->backup_device.rx_bytes;
data.devices[1].tx_errors = master->backup_device.tx_errors;
for (i = 0; i < EC_RATE_COUNT; i++) {
data.devices[1].tx_frame_rates[i] =
master->backup_device.tx_frame_rates[i];
data.devices[1].rx_frame_rates[i] =
master->backup_device.rx_frame_rates[i];
data.devices[1].tx_byte_rates[i] =
master->backup_device.tx_byte_rates[i];
data.devices[1].loss_rates[i] = master->backup_device.loss_rates[i];
data.devices[1].rx_byte_rates[i] =
master->backup_device.rx_byte_rates[i];
}
data.tx_count = master->device_stats.tx_count;
data.rx_count = master->device_stats.rx_count;
data.tx_bytes = master->device_stats.tx_bytes;
data.rx_bytes = master->device_stats.rx_bytes;
for (i = 0; i < EC_RATE_COUNT; i++) {
data.tx_frame_rates[i] =
master->device_stats.tx_frame_rates[i];
data.rx_frame_rates[i] =
master->device_stats.rx_frame_rates[i];
data.tx_byte_rates[i] =
master->device_stats.tx_byte_rates[i];
data.rx_byte_rates[i] =
master->device_stats.rx_byte_rates[i];
data.loss_rates[i] =
master->device_stats.loss_rates[i];
}
up(&master->device_sem);

View File

@ -54,12 +54,6 @@
} while (0)
#endif
/** List of intervals for frame statistics [s].
*/
static const unsigned int rate_intervals[] = {
1, 10, 60
};
/*****************************************************************************/
/** Constructor.
@ -309,30 +303,6 @@ 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;
u32 tx_frame_rate =
(u32) (device->tx_count - device->last_tx_count) * 1000;
u32 tx_byte_rate =
(device->tx_bytes - device->last_tx_bytes);
u64 loss = device->tx_count - device->rx_count;
s32 loss_rate = (s32) (loss - device->last_loss) * 1000;
for (i = 0; i < EC_RATE_COUNT; i++) {
unsigned int n = rate_intervals[i];
device->tx_frame_rates[i] =
(device->tx_frame_rates[i] * (n - 1) + tx_frame_rate) / n;
device->tx_byte_rates[i] =
(device->tx_byte_rates[i] * (n - 1) + tx_byte_rate) / n;
device->loss_rates[i] =
(device->loss_rates[i] * (n - 1) + loss_rate) / n;
}
device->last_tx_count = device->tx_count;
device->last_tx_bytes = device->tx_bytes;
device->last_loss = loss;
device->stats_jiffies = jiffies;
}
// set the right length for the data
skb->len = ETH_HLEN + size;
@ -350,7 +320,9 @@ void ec_device_send(
#endif
{
device->tx_count++;
device->master->device_stats.tx_count++;
device->tx_bytes += ETH_HLEN + size;
device->master->device_stats.tx_bytes += ETH_HLEN + size;
#ifdef EC_DEBUG_IF
ec_debug_send(&device->dbg, skb->data, ETH_HLEN + size);
#endif
@ -375,16 +347,20 @@ void ec_device_clear_stats(
// zero frame statistics
device->tx_count = 0;
device->rx_count = 0;
device->tx_errors = 0;
device->tx_bytes = 0;
device->last_tx_count = 0;
device->rx_count = 0;
device->last_rx_count = 0;
device->tx_bytes = 0;
device->last_tx_bytes = 0;
device->last_loss = 0;
device->rx_bytes = 0;
device->last_rx_bytes = 0;
device->tx_errors = 0;
for (i = 0; i < EC_RATE_COUNT; i++) {
device->tx_frame_rates[i] = 0;
device->rx_frame_rates[i] = 0;
device->tx_byte_rates[i] = 0;
device->loss_rates[i] = 0;
device->rx_byte_rates[i] = 0;
}
}
@ -479,6 +455,43 @@ void ec_device_poll(
device->poll(device->dev);
}
/*****************************************************************************/
/** Update device statistics.
*/
void ec_device_update_stats(
ec_device_t *device /**< EtherCAT device */
)
{
unsigned int i;
u32 tx_frame_rate =
(u32) (device->tx_count - device->last_tx_count) * 1000;
u32 rx_frame_rate =
(u32) (device->rx_count - device->last_rx_count) * 1000;
u32 tx_byte_rate =
(device->tx_bytes - device->last_tx_bytes);
u32 rx_byte_rate =
(device->rx_bytes - device->last_rx_bytes);
for (i = 0; i < EC_RATE_COUNT; i++) {
unsigned int n = rate_intervals[i];
device->tx_frame_rates[i] =
(device->tx_frame_rates[i] * (n - 1) + tx_frame_rate) / n;
device->rx_frame_rates[i] =
(device->rx_frame_rates[i] * (n - 1) + rx_frame_rate) / n;
device->tx_byte_rates[i] =
(device->tx_byte_rates[i] * (n - 1) + tx_byte_rate) / n;
device->rx_byte_rates[i] =
(device->rx_byte_rates[i] * (n - 1) + rx_byte_rate) / n;
}
device->last_tx_count = device->tx_count;
device->last_rx_count = device->rx_count;
device->last_tx_bytes = device->tx_bytes;
device->last_rx_bytes = device->rx_bytes;
}
/******************************************************************************
* Device interface
*****************************************************************************/
@ -593,6 +606,9 @@ void ecdev_receive(
}
device->rx_count++;
device->master->device_stats.rx_count++;
device->rx_bytes += size;
device->master->device_stats.rx_bytes += size;
if (unlikely(device->master->debug_level > 1)) {
EC_MASTER_DBG(device->master, 2, "Received frame:\n");

View File

@ -101,19 +101,26 @@ struct ec_device
u64 tx_count; /**< Number of frames sent. */
u64 last_tx_count; /**< Number of frames sent of last statistics cycle. */
u64 rx_count; /**< Number of frames received. */
u64 tx_bytes; /**< Number of frames sent. */
u64 last_rx_count; /**< Number of frames received of last statistics
cycle. */
u64 tx_bytes; /**< Number of bytes sent. */
u64 last_tx_bytes; /**< Number of bytes sent of last statistics cycle. */
u64 rx_bytes; /**< Number of bytes received. */
u64 last_rx_bytes; /**< Number of bytes received of last statistics cycle.
*/
u64 tx_errors; /**< Number of transmit errors. */
u64 last_loss; /**< Tx/Rx difference of last statistics cycle. */
unsigned int tx_frame_rates[EC_RATE_COUNT]; /**< Transmit rates in
frames/s for different
statistics cycle periods. */
unsigned int rx_frame_rates[EC_RATE_COUNT]; /**< Receive rates in
frames/s for different
statistics cycle periods. */
unsigned int tx_byte_rates[EC_RATE_COUNT]; /**< Transmit rates in byte/s
for different statistics
cycle periods. */
int loss_rates[EC_RATE_COUNT]; /**< Frame loss rates for different
statistics cycle periods. */
unsigned long stats_jiffies; /**< Jiffies of last statistic cycle. */
unsigned int rx_byte_rates[EC_RATE_COUNT]; /**< Receive rates in byte/s
for different statistics
cycle periods. */
#ifdef EC_DEBUG_IF
ec_debug_t dbg; /**< debug device */
@ -141,6 +148,7 @@ void ec_device_poll(ec_device_t *);
uint8_t *ec_device_tx_data(ec_device_t *);
void ec_device_send(ec_device_t *, size_t);
void ec_device_clear_stats(ec_device_t *);
void ec_device_update_stats(ec_device_t *);
#ifdef EC_DEBUG_RING
void ec_device_debug_ring_append(ec_device_t *, ec_debug_frame_dir_t,

View File

@ -56,7 +56,7 @@
*
* Increment this when changing the ioctl interface!
*/
#define EC_IOCTL_VERSION_MAGIC 12
#define EC_IOCTL_VERSION_MAGIC 14
// Command-line tool
#define EC_IOCTL_MODULE EC_IOR(0x00, ec_ioctl_module_t)
@ -168,11 +168,22 @@ typedef struct {
uint64_t tx_count;
uint64_t rx_count;
uint64_t tx_bytes;
uint64_t rx_bytes;
uint64_t tx_errors;
uint32_t tx_frame_rates[EC_RATE_COUNT];
uint32_t rx_frame_rates[EC_RATE_COUNT];
uint32_t tx_byte_rates[EC_RATE_COUNT];
int32_t loss_rates[EC_RATE_COUNT];
uint32_t rx_byte_rates[EC_RATE_COUNT];
} devices[2];
uint64_t tx_count;
uint64_t rx_count;
uint64_t tx_bytes;
uint64_t rx_bytes;
uint32_t tx_frame_rates[EC_RATE_COUNT];
uint32_t rx_frame_rates[EC_RATE_COUNT];
uint32_t tx_byte_rates[EC_RATE_COUNT];
uint32_t rx_byte_rates[EC_RATE_COUNT];
int32_t loss_rates[EC_RATE_COUNT];
uint64_t app_time;
uint16_t ref_clock;
} ec_ioctl_master_t;

View File

@ -82,6 +82,12 @@ static unsigned long ext_injection_timeout_jiffies;
#endif
/** List of intervals for statistics [s].
*/
const unsigned int rate_intervals[] = {
1, 10, 60
};
/*****************************************************************************/
void ec_master_clear_slave_configs(ec_master_t *);
@ -92,6 +98,8 @@ static int ec_master_operation_thread(void *);
static int ec_master_eoe_thread(void *);
#endif
void ec_master_find_dc_ref_clock(ec_master_t *);
void ec_master_clear_device_stats(ec_master_t *);
void ec_master_update_device_stats(ec_master_t *);
/*****************************************************************************/
@ -134,6 +142,7 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
master->main_mac = main_mac;
master->backup_mac = backup_mac;
ec_master_clear_device_stats(master);
sema_init(&master->device_sem, 1);
@ -1148,6 +1157,84 @@ void ec_master_output_stats(ec_master_t *master /**< EtherCAT master */)
}
}
/*****************************************************************************/
/** Clears the common device statistics.
*/
void ec_master_clear_device_stats(
ec_master_t *master /**< EtherCAT master */
)
{
unsigned int i;
// zero frame statistics
master->device_stats.tx_count = 0;
master->device_stats.last_tx_count = 0;
master->device_stats.rx_count = 0;
master->device_stats.last_rx_count = 0;
master->device_stats.tx_bytes = 0;
master->device_stats.last_tx_bytes = 0;
master->device_stats.rx_bytes = 0;
master->device_stats.last_rx_bytes = 0;
master->device_stats.last_loss = 0;
for (i = 0; i < EC_RATE_COUNT; i++) {
master->device_stats.tx_frame_rates[i] = 0;
master->device_stats.tx_byte_rates[i] = 0;
master->device_stats.loss_rates[i] = 0;
}
}
/*****************************************************************************/
/** Updates the common device statistics.
*/
void ec_master_update_device_stats(
ec_master_t *master /**< EtherCAT master */
)
{
ec_device_stats_t *s = &master->device_stats;
u32 tx_frame_rate, rx_frame_rate, tx_byte_rate, rx_byte_rate;
u64 loss;
s32 loss_rate;
unsigned int i;
// frame statistics
if (likely(jiffies - s->jiffies < HZ)) {
return;
}
tx_frame_rate = (u32) (s->tx_count - s->last_tx_count) * 1000;
rx_frame_rate = (u32) (s->rx_count - s->last_rx_count) * 1000;
tx_byte_rate = (s->tx_bytes - s->last_tx_bytes);
rx_byte_rate = (s->rx_bytes - s->last_rx_bytes);
loss = s->tx_count - s->rx_count;
loss_rate = (s32) (loss - s->last_loss) * 1000;
for (i = 0; i < EC_RATE_COUNT; i++) {
unsigned int n = rate_intervals[i];
s->tx_frame_rates[i] =
(s->tx_frame_rates[i] * (n - 1) + tx_frame_rate) / n;
s->rx_frame_rates[i] =
(s->rx_frame_rates[i] * (n - 1) + rx_frame_rate) / n;
s->tx_byte_rates[i] =
(s->tx_byte_rates[i] * (n - 1) + tx_byte_rate) / n;
s->rx_byte_rates[i] =
(s->rx_byte_rates[i] * (n - 1) + rx_byte_rate) / n;
s->loss_rates[i] =
(s->loss_rates[i] * (n - 1) + loss_rate) / n;
}
s->last_tx_count = s->tx_count;
s->last_rx_count = s->rx_count;
s->last_tx_bytes = s->tx_bytes;
s->last_rx_bytes = s->rx_bytes;
ec_device_update_stats(&master->main_device);
ec_device_update_stats(&master->backup_device);
s->jiffies = jiffies;
}
/*****************************************************************************/
@ -2129,6 +2216,7 @@ void ecrt_master_receive(ec_master_t *master)
if (master->backup_device.dev) {
ec_device_poll(&master->backup_device);
}
ec_master_update_device_stats(master);
// dequeue all datagrams that timed out
list_for_each_entry_safe(datagram, next, &master->datagram_queue, queue) {

View File

@ -137,6 +137,39 @@ typedef struct {
/*****************************************************************************/
/** Device statistics.
*/
typedef struct {
u64 tx_count; /**< Number of frames sent. */
u64 last_tx_count; /**< Number of frames sent of last statistics cycle. */
u64 rx_count; /**< Number of frames received. */
u64 last_rx_count; /**< Number of frames received of last statistics
cycle. */
u64 tx_bytes; /**< Number of bytes sent. */
u64 last_tx_bytes; /**< Number of bytes sent of last statistics cycle. */
u64 rx_bytes; /**< Number of bytes received. */
u64 last_rx_bytes; /**< Number of bytes received of last statistics cycle.
*/
u64 last_loss; /**< Tx/Rx difference of last statistics cycle. */
unsigned int tx_frame_rates[EC_RATE_COUNT]; /**< Transmit rates in
frames/s for different
statistics cycle periods. */
unsigned int rx_frame_rates[EC_RATE_COUNT]; /**< Receive rates in
frames/s for different
statistics cycle periods. */
unsigned int tx_byte_rates[EC_RATE_COUNT]; /**< Transmit rates in byte/s
for different statistics
cycle periods. */
unsigned int rx_byte_rates[EC_RATE_COUNT]; /**< Receive rates in byte/s
for different statistics
cycle periods. */
int loss_rates[EC_RATE_COUNT]; /**< Frame loss rates for different
statistics cycle periods. */
unsigned long jiffies; /**< Jiffies of last statistic cycle. */
} ec_device_stats_t;
/*****************************************************************************/
/** EtherCAT master.
*
* Manages slaves, domains and IO.
@ -159,6 +192,7 @@ struct ec_master {
ec_device_t backup_device; /**< EtherCAT backup device. */
const uint8_t *backup_mac; /**< MAC address of backup device. */
struct semaphore device_sem; /**< Device semaphore. */
ec_device_stats_t device_stats; /**< Device statistics. */
ec_fsm_master_t fsm; /**< Master state machine. */
ec_datagram_t fsm_datagram; /**< Datagram used for state machines. */
@ -309,6 +343,8 @@ void ec_master_request_op(ec_master_t *);
void ec_master_internal_send_cb(void *);
void ec_master_internal_receive_cb(void *);
extern const unsigned int rate_intervals[EC_RATE_COUNT]; // see master.c
/*****************************************************************************/
#endif

View File

@ -114,12 +114,6 @@ void CommandMaster::execute(const StringVector &args)
&& data.devices[i].address[5] == 0x00) {
cout << "None.";
} else {
unsigned int lost =
data.devices[i].tx_count - data.devices[i].rx_count;
if (lost == 1) {
// allow one frame travelling
lost = 0;
}
cout << hex << setfill('0')
<< setw(2) << (unsigned int) data.devices[i].address[0]
<< ":"
@ -139,11 +133,12 @@ void CommandMaster::execute(const StringVector &args)
<< (data.devices[i].link_state ? "UP" : "DOWN") << endl
<< " Tx frames: "
<< data.devices[i].tx_count << endl
<< " Rx frames: "
<< data.devices[i].rx_count << endl
<< " Lost frames: " << lost << endl
<< " Tx bytes: "
<< data.devices[i].tx_bytes << endl
<< " Rx frames: "
<< data.devices[i].rx_count << endl
<< " Rx bytes: "
<< data.devices[i].rx_bytes << endl
<< " Tx errors: "
<< data.devices[i].tx_errors << endl
<< " Tx frame rate [1/s]: "
@ -166,33 +161,106 @@ void CommandMaster::execute(const StringVector &args)
}
}
cout << endl
<< " Loss rate [1/s]: "
<< setprecision(0) << fixed;
<< " Rx frame rate [1/s]: "
<< setfill(' ') << setprecision(0) << fixed;
for (j = 0; j < EC_RATE_COUNT; j++) {
cout << setw(ColWidth)
<< data.devices[i].loss_rates[j] / 1000.0;
<< data.devices[i].rx_frame_rates[j] / 1000.0;
if (j < EC_RATE_COUNT - 1) {
cout << " ";
}
}
cout << endl
<< " Frame loss [%]: "
<< " Rx rate [KByte/s]: "
<< setprecision(1) << fixed;
for (j = 0; j < EC_RATE_COUNT; j++) {
double perc = 0.0;
if (data.devices[i].tx_frame_rates[j]) {
perc = 100.0 * data.devices[i].loss_rates[j] /
data.devices[i].tx_frame_rates[j];
}
cout << setw(ColWidth) << perc;
cout << setw(ColWidth)
<< data.devices[i].rx_byte_rates[j] / 1024.0;
if (j < EC_RATE_COUNT - 1) {
cout << " ";
}
}
cout << setprecision(0) << endl;
}
cout << endl;
}
unsigned int lost = data.tx_count - data.rx_count;
if (lost == 1) {
// allow one frame travelling
lost = 0;
}
cout << " Common:" << endl
<< " Tx frames: "
<< data.tx_count << endl
<< " Tx bytes: "
<< data.tx_bytes << endl
<< " Rx frames: "
<< data.rx_count << endl
<< " Rx bytes: "
<< data.rx_bytes << endl
<< " Lost frames: " << lost << endl
<< " Tx frame rate [1/s]: "
<< setfill(' ') << setprecision(0) << fixed;
for (j = 0; j < EC_RATE_COUNT; j++) {
cout << setw(ColWidth)
<< data.tx_frame_rates[j] / 1000.0;
if (j < EC_RATE_COUNT - 1) {
cout << " ";
}
}
cout << endl
<< " Tx rate [KByte/s]: "
<< setprecision(1) << fixed;
for (j = 0; j < EC_RATE_COUNT; j++) {
cout << setw(ColWidth)
<< data.tx_byte_rates[j] / 1024.0;
if (j < EC_RATE_COUNT - 1) {
cout << " ";
}
}
cout << endl
<< " Rx frame rate [1/s]: "
<< setfill(' ') << setprecision(0) << fixed;
for (j = 0; j < EC_RATE_COUNT; j++) {
cout << setw(ColWidth)
<< data.rx_frame_rates[j] / 1000.0;
if (j < EC_RATE_COUNT - 1) {
cout << " ";
}
}
cout << endl
<< " Rx rate [KByte/s]: "
<< setprecision(1) << fixed;
for (j = 0; j < EC_RATE_COUNT; j++) {
cout << setw(ColWidth)
<< data.rx_byte_rates[j] / 1024.0;
if (j < EC_RATE_COUNT - 1) {
cout << " ";
}
}
cout << endl
<< " Loss rate [1/s]: "
<< setprecision(0) << fixed;
for (j = 0; j < EC_RATE_COUNT; j++) {
cout << setw(ColWidth)
<< data.loss_rates[j] / 1000.0;
if (j < EC_RATE_COUNT - 1) {
cout << " ";
}
}
cout << endl
<< " Frame loss [%]: "
<< setprecision(1) << fixed;
for (j = 0; j < EC_RATE_COUNT; j++) {
double perc = 0.0;
if (data.tx_frame_rates[j]) {
perc = 100.0 * data.loss_rates[j] / data.tx_frame_rates[j];
}
cout << setw(ColWidth) << perc;
if (j < EC_RATE_COUNT - 1) {
cout << " ";
}
}
cout << setprecision(0) << endl;
cout << " Distributed clocks:" << endl
<< " Reference clock: ";