freetdm: improve IO stats (cherry picked from R2 branch)

This commit is contained in:
Moises Silva 2010-11-26 15:49:18 -05:00
parent 0b7a2d4c92
commit 7a7a387f55
3 changed files with 132 additions and 57 deletions

View file

@ -655,32 +655,32 @@ void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len)
memcpy(&l1_frame.data, data, len); memcpy(&l1_frame.data, data, len);
if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_CRC)) { if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_CRC)) {
l1_frame.flags |= SNG_L1FRAME_ERROR_CRC; l1_frame.flags |= SNG_L1FRAME_ERROR_CRC;
} }
if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_FRAME)) { if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_FRAME)) {
l1_frame.flags |= SNG_L1FRAME_ERROR_FRAME; l1_frame.flags |= SNG_L1FRAME_ERROR_FRAME;
} }
if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_ABORT)) { if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_ABORT)) {
l1_frame.flags |= SNG_L1FRAME_ERROR_ABORT; l1_frame.flags |= SNG_L1FRAME_ERROR_ABORT;
} }
if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_FIFO)) { if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_FIFO)) {
l1_frame.flags |= SNG_L1FRAME_ERROR_FIFO; l1_frame.flags |= SNG_L1FRAME_ERROR_FIFO;
} }
if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_DMA)) { if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_DMA)) {
l1_frame.flags |= SNG_L1FRAME_ERROR_DMA; l1_frame.flags |= SNG_L1FRAME_ERROR_DMA;
} }
if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)) { if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)) {
/* Should we trigger congestion here? */ /* Should we trigger congestion here? */
l1_frame.flags |= SNG_L1FRAME_QUEUE_THRES; l1_frame.flags |= SNG_L1FRAME_QUEUE_THRES;
} }
if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL)) { if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL)) {
/* Should we trigger congestion here? */ /* Should we trigger congestion here? */
l1_frame.flags |= SNG_L1FRAME_QUEUE_FULL; l1_frame.flags |= SNG_L1FRAME_QUEUE_FULL;
} }

View file

@ -513,7 +513,10 @@ static FIO_OPEN_FUNCTION(wanpipe_open)
wanpipe_tdm_api_t tdm_api; wanpipe_tdm_api_t tdm_api;
memset(&tdm_api,0,sizeof(tdm_api)); memset(&tdm_api,0,sizeof(tdm_api));
sangoma_tdm_flush_bufs(ftdmchan->sockfd, &tdm_api); sangoma_tdm_flush_bufs(ftdmchan->sockfd, &tdm_api);
sangoma_flush_stats(ftdmchan->sockfd, &tdm_api);
memset(&ftdmchan->iostats, 0, sizeof(ftdmchan->iostats));
if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921 || ftdmchan->type == FTDM_CHAN_TYPE_DQ931) { if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921 || ftdmchan->type == FTDM_CHAN_TYPE_DQ931) {
ftdmchan->native_codec = ftdmchan->effective_codec = FTDM_CODEC_NONE; ftdmchan->native_codec = ftdmchan->effective_codec = FTDM_CODEC_NONE;
@ -750,6 +753,7 @@ static FIO_COMMAND_FUNCTION(wanpipe_command)
case FTDM_COMMAND_FLUSH_IOSTATS: case FTDM_COMMAND_FLUSH_IOSTATS:
{ {
err = sangoma_flush_stats(ftdmchan->sockfd, &tdm_api); err = sangoma_flush_stats(ftdmchan->sockfd, &tdm_api);
memset(&ftdmchan->iostats, 0, sizeof(ftdmchan->iostats));
} }
break; break;
case FTDM_COMMAND_SET_RX_QUEUE_SIZE: case FTDM_COMMAND_SET_RX_QUEUE_SIZE:
@ -777,44 +781,110 @@ static FIO_COMMAND_FUNCTION(wanpipe_command)
return FTDM_SUCCESS; return FTDM_SUCCESS;
} }
static void wanpipe_write_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_tx_hdr_t *tx_stats)
{
ftdmchan->iostats.tx.errors = tx_stats->wp_api_tx_hdr_errors;
ftdmchan->iostats.tx.queue_size = tx_stats->wp_api_tx_hdr_max_queue_length;
ftdmchan->iostats.tx.queue_len = tx_stats->wp_api_tx_hdr_number_of_frames_in_queue;
if (ftdmchan->iostats.tx.queue_len >= (0.8 * ftdmchan->iostats.tx.queue_size)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Tx Queue length exceeded 80% threshold (%d/%d)\n",
ftdmchan->iostats.tx.queue_len, ftdmchan->iostats.tx.queue_size);
ftdm_set_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_THRES);
} else if (ftdm_test_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_THRES)){
ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Tx Queue length reduced 80% threshold (%d/%d)\n",
ftdmchan->iostats.tx.queue_len, ftdmchan->iostats.tx.queue_size);
ftdm_clear_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_THRES);
}
if (ftdmchan->iostats.tx.queue_len >= ftdmchan->iostats.rx.queue_size) {
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Tx Queue Full (%d/%d)\n",
ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size);
ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL);
} else if (ftdm_test_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_FULL)){
ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Tx Queue no longer full (%d/%d)\n",
ftdmchan->iostats.tx.queue_len, ftdmchan->iostats.tx.queue_size);
ftdm_clear_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_FULL);
}
if (ftdmchan->iostats.tx.idle_packets < tx_stats->wp_api_tx_hdr_number_of_frames_in_queue) {
ftdmchan->iostats.tx.idle_packets = tx_stats->wp_api_tx_hdr_tx_idle_packets;
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Tx idle: %d\n", ftdmchan->iostats.tx.idle_packets);
}
if (!ftdmchan->iostats.tx.packets) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "First packet write stats: Tx queue len: %d, Tx queue size: %d, Tx idle: %d\n",
ftdmchan->iostats.tx.queue_len,
ftdmchan->iostats.tx.queue_size,
ftdmchan->iostats.tx.idle_packets);
}
ftdmchan->iostats.tx.packets++;
}
static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx_stats) static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx_stats)
{ {
ftdmchan->iostats.stats.rx.flags = 0; ftdmchan->iostats.rx.errors = rx_stats->wp_api_rx_hdr_errors;
ftdmchan->iostats.rx.queue_size = rx_stats->wp_api_rx_hdr_max_queue_length;
ftdmchan->iostats.rx.queue_len = rx_stats->wp_api_rx_hdr_number_of_frames_in_queue;
ftdmchan->iostats.stats.rx.errors = rx_stats->wp_api_rx_hdr_errors; if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_ABORT_ERROR_BIT))) {
ftdmchan->iostats.stats.rx.rx_queue_size = rx_stats->wp_api_rx_hdr_max_queue_length; ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_ABORT);
ftdmchan->iostats.stats.rx.rx_queue_len = rx_stats->wp_api_rx_hdr_number_of_frames_in_queue; } else {
ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_ABORT);
if (rx_stats->wp_api_rx_hdr_error_map & (1<<WP_ABORT_ERROR_BIT)) {
ftdm_set_flag(&(ftdmchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_ABORT);
}
if (rx_stats->wp_api_rx_hdr_error_map & (1<<WP_DMA_ERROR_BIT)) {
ftdm_set_flag(&(ftdmchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_DMA);
}
if (rx_stats->wp_api_rx_hdr_error_map & (1<<WP_FIFO_ERROR_BIT)) {
ftdm_set_flag(&(ftdmchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_FIFO);
}
if (rx_stats->wp_api_rx_hdr_error_map & (1<<WP_CRC_ERROR_BIT)) {
ftdm_set_flag(&(ftdmchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_CRC);
}
if (rx_stats->wp_api_rx_hdr_error_map & (1<<WP_FRAME_ERROR_BIT)) {
ftdm_set_flag(&(ftdmchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_FRAME);
} }
if (ftdmchan->iostats.stats.rx.rx_queue_len >= (0.8*ftdmchan->iostats.stats.rx.rx_queue_size)) { if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_DMA_ERROR_BIT))) {
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Rx Queue length exceeded threshold (%d/%d)\n", ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_DMA);
ftdmchan->iostats.stats.rx.rx_queue_len, ftdmchan->iostats.stats.rx.rx_queue_size); } else {
ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_DMA);
ftdm_set_flag(&(ftdmchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES);
} }
if (ftdmchan->iostats.stats.rx.rx_queue_len >= ftdmchan->iostats.stats.rx.rx_queue_size) { if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_FIFO_ERROR_BIT))) {
ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FIFO);
} else {
ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FIFO);
}
if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_CRC_ERROR_BIT))) {
ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_CRC);
} else {
ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_CRC);
}
if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_FRAME_ERROR_BIT))) {
ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FRAME);
} else {
ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FRAME);
}
if (ftdmchan->iostats.rx.queue_len >= (0.8 * ftdmchan->iostats.rx.queue_size)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Rx Queue length exceeded 80% threshold (%d/%d)\n",
ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size);
ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES);
} else if (ftdm_test_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)){
/* any reason we have wanpipe_tdm_api_iface.h in ftmod_wanpipe/ dir? */
ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Rx Queue length reduced 80% threshold (%d/%d)\n",
ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size);
ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES);
}
if (ftdmchan->iostats.rx.queue_len >= ftdmchan->iostats.rx.queue_size) {
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Rx Queue Full (%d/%d)\n", ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Rx Queue Full (%d/%d)\n",
ftdmchan->iostats.stats.rx.rx_queue_len, ftdmchan->iostats.stats.rx.rx_queue_size); ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size);
ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL);
ftdm_set_flag(&(ftdmchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL); } else if (ftdm_test_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL)){
ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Rx Queue no longer full (%d/%d)\n",
ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size);
ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL);
} }
return;
if (!ftdmchan->iostats.rx.packets) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "First packet read stats: Rx queue len: %d, Rx queue size: %d\n",
ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size);
}
ftdmchan->iostats.rx.packets++;
} }
/** /**
@ -875,6 +945,9 @@ static FIO_WRITE_FUNCTION(wanpipe_write)
/* should we be checking if bsent == *datalen here? */ /* should we be checking if bsent == *datalen here? */
if (bsent > 0) { if (bsent > 0) {
*datalen = bsent; *datalen = bsent;
if (ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS)) {
wanpipe_write_stats(ftdmchan, &hdrframe);
}
return FTDM_SUCCESS; return FTDM_SUCCESS;
} }

View file

@ -368,30 +368,32 @@ typedef struct {
} ftdm_channel_history_entry_t; } ftdm_channel_history_entry_t;
typedef enum { typedef enum {
FTDM_IOSTATS_ERROR_CRC = (1<<0), FTDM_IOSTATS_ERROR_CRC = (1 << 0),
FTDM_IOSTATS_ERROR_FRAME = (1<<1), FTDM_IOSTATS_ERROR_FRAME = (1 << 1),
FTDM_IOSTATS_ERROR_ABORT = (1<<2), FTDM_IOSTATS_ERROR_ABORT = (1 << 2),
FTDM_IOSTATS_ERROR_FIFO = (1<<3), FTDM_IOSTATS_ERROR_FIFO = (1 << 3),
FTDM_IOSTATS_ERROR_DMA = (1<<4), FTDM_IOSTATS_ERROR_DMA = (1 << 4),
FTDM_IOSTATS_ERROR_QUEUE_THRES = (1<<5), /* Queue reached high threshold */ FTDM_IOSTATS_ERROR_QUEUE_THRES = (1 << 5), /* Queue reached high threshold */
FTDM_IOSTATS_ERROR_QUEUE_FULL = (1<<6), /* Queue is full */ FTDM_IOSTATS_ERROR_QUEUE_FULL = (1 << 6), /* Queue is full */
} ftdm_iostats_error_type_t; } ftdm_iostats_error_type_t;
typedef struct { typedef struct {
union { struct {
struct { uint32_t errors;
uint32_t errors; uint16_t flags;
uint16_t flags; uint8_t queue_size; /* max queue size configured */
uint8_t rx_queue_size; /* max queue size configured */ uint8_t queue_len; /* Current number of elements in queue */
uint8_t rx_queue_len; /* Current number of elements in queue */ uint64_t packets;
} rx; } rx;
struct {
uint32_t errors; struct {
uint16_t flags; uint32_t errors;
uint8_t tx_queue_size; /* max queue size configured */ uint16_t flags;
uint8_t tx_queue_len; /* Current number of elements in queue */ uint8_t idle_packets;
} tx; uint8_t queue_size; /* max queue size configured */
} stats; uint8_t queue_len; /* Current number of elements in queue */
uint64_t packets;
} tx;
} ftdm_channel_iostats_t; } ftdm_channel_iostats_t;
/* 2^8 table size, one for each byte (sample) value */ /* 2^8 table size, one for each byte (sample) value */