]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
freetdm: allow IO statistics access to users
authorMoises Silva <moy@sangoma.com>
Sat, 30 Jul 2011 21:39:29 +0000 (17:39 -0400)
committerMoises Silva <moy@sangoma.com>
Sat, 30 Jul 2011 21:40:32 +0000 (17:40 -0400)
         added ftdm iostats command

libs/freetdm/mod_freetdm/mod_freetdm.c
libs/freetdm/src/ftdm_io.c
libs/freetdm/src/include/freetdm.h
libs/freetdm/src/include/private/ftdm_core.h

index 9b181d545c235e872b591dccfafd436afeaf861b..4e23fd74f5004a601536f60b658c3bc7ee3d6830 100755 (executable)
@@ -4346,6 +4346,76 @@ end:
        return SWITCH_STATUS_SUCCESS;
 }
 
+static void exec_io_command(const char *cmd, switch_stream_handle_t *stream, ftdm_channel_t *fchan)
+{
+       int enable = 0;
+       ftdm_channel_iostats_t stats;
+       if (!strcasecmp("enable", cmd)) {
+               enable = 1;
+               ftdm_channel_command(fchan, FTDM_COMMAND_SWITCH_IOSTATS, &enable);
+       } else if (!strcasecmp("disable", cmd)) {
+               enable = 0;
+               ftdm_channel_command(fchan, FTDM_COMMAND_SWITCH_IOSTATS, &enable);
+       } else if (!strcasecmp("flush", cmd)) {
+               ftdm_channel_command(fchan, FTDM_COMMAND_FLUSH_IOSTATS, NULL);
+       } else {
+               ftdm_channel_command(fchan, FTDM_COMMAND_GET_IOSTATS, &stats);
+               stream->write_function(stream, "-- IO statistics for channel %d:%d --\n", 
+                               ftdm_channel_get_span_id(fchan), ftdm_channel_get_id(fchan));
+               stream->write_function(stream, "Rx errors: %u\n", stats.rx.errors);
+               stream->write_function(stream, "Rx queue size: %u\n", stats.rx.queue_size);
+               stream->write_function(stream, "Rx queue len: %u\n", stats.rx.queue_len);
+               stream->write_function(stream, "Rx count: %lu\n", stats.rx.packets);
+
+               stream->write_function(stream, "Tx errors: %u\n", stats.tx.errors);
+               stream->write_function(stream, "Tx queue len: %u\n", stats.tx.queue_len);
+               stream->write_function(stream, "Tx queue len: %u\n", stats.tx.queue_len);
+               stream->write_function(stream, "Tx count: %lu\n", stats.tx.packets);
+               stream->write_function(stream, "Tx idle: %u\n", stats.tx.idle_packets);
+       }
+}
+
+static switch_status_t ftdm_cmd_iostats(const char *cmd, switch_core_session_t *session,
+                             switch_stream_handle_t *stream, int argc, char *argv[])
+{
+       uint32_t chan_id = 0;
+       ftdm_channel_t *chan;
+       ftdm_iterator_t *iter = NULL;
+       ftdm_iterator_t *curr = NULL;
+       ftdm_span_t *span = NULL;
+
+       if (argc < 3) {
+               stream->write_function(stream, "-ERR Usage: ftdm iostats enable|disable|flush|print <span_id> [<chan_id>]\n");
+               goto end;
+       }
+
+       ftdm_span_find_by_name(argv[2], &span);
+       if (!span) {
+               stream->write_function(stream, "-ERR invalid span\n");
+               goto end;
+       }
+
+       if (argc > 3) {
+               chan_id = atoi(argv[3]);
+               if (chan_id > ftdm_span_get_chan_count(span)) {
+                       stream->write_function(stream, "-ERR invalid chan\n");
+                       goto end;
+               }
+               chan = ftdm_span_get_channel(span, chan_id);
+               exec_io_command(argv[1], stream, chan);
+       } else {
+               iter = ftdm_span_get_chan_iterator(span, NULL);
+               for (curr  = iter; curr; curr = ftdm_iterator_next(curr)) {
+                       chan = ftdm_iterator_current(curr);
+                       exec_io_command(argv[1], stream, chan);
+               }
+               ftdm_iterator_free(iter);
+       }
+       stream->write_function(stream, "+OK\n");
+end:
+       return SWITCH_STATUS_SUCCESS;
+}
+
 typedef switch_status_t (*ftdm_cli_function_t)(const char *cmd, switch_core_session_t *session,
                                               switch_stream_handle_t *stream, int argc, char *argv[]);
 typedef struct ftdm_cli_entry {
@@ -4368,6 +4438,7 @@ static ftdm_cli_entry_t ftdm_cli_options[] =
        { "gains", "<rxgain> <txgain> <span_id|span_name> [<chan_id>]", "", ftdm_cmd_gains },
        { "dtmf", "on|off <span_id|span_name> [<chan_id>]", "::[on:off", ftdm_cmd_dtmf },
        { "queuesize", "<rxsize> <txsize> <span_id|span_name> [<chan_id>]", "", ftdm_cmd_queuesize },
+       { "iostats", "enable|disable|flush|print <span_id|span_name> <chan_id>", "::[enable:disable:flush:print", ftdm_cmd_iostats },
        { "voice_detect", "[on|off] <span_id|span_name> [<chan_id>]", "::[on:off", ftdm_cmd_voice_detect },
 
        /* Fake handlers as they are handled within freetdm library,
index 1e7c682e02f89bd5f01f0596623452d6d4ec98b5..805c525269c591ac8104885ad7cdae6396f72970 100644 (file)
@@ -2825,9 +2825,9 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co
        ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "No channel\n");
        ftdm_assert_return(ftdmchan->fio != NULL, FTDM_FAIL, "No IO attached to channel\n");
 
-       ftdm_mutex_lock(ftdmchan->mutex);
+       ftdm_channel_lock(ftdmchan);
 
-       switch(command) {
+       switch (command) {
 
        case FTDM_COMMAND_ENABLE_CALLERID_DETECT:
                {
@@ -3278,12 +3278,31 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co
                        GOTO_STATUS(done, FTDM_SUCCESS);
                }
                break;
+       case FTDM_COMMAND_GET_IOSTATS:
+               {
+                       if (!obj) {
+                               GOTO_STATUS(done, FTDM_EINVAL);
+                       }
+                       memcpy(obj, &ftdmchan->iostats, sizeof(ftdmchan->iostats));
+                       GOTO_STATUS(done, FTDM_SUCCESS);
+               }
+               break;
+       case FTDM_COMMAND_SWITCH_IOSTATS:
+               {
+                       ftdm_bool_t enable = *(ftdm_bool_t *)obj;
+                       if (enable) {
+                               ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS);
+                       } else {
+                               ftdm_channel_clear_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS);
+                       }
+                       GOTO_STATUS(done, FTDM_SUCCESS);
+               }
+               break;
        default:
                break;
        }
 
        if (!ftdmchan->fio->command) {
-               snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "method not implemented");
                ftdm_log(FTDM_LOG_ERROR, "no command function defined by the I/O freetdm module!\n");   
                GOTO_STATUS(done, FTDM_FAIL);
        }
@@ -3291,11 +3310,12 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co
        status = ftdmchan->fio->command(ftdmchan, command, obj);
 
        if (status == FTDM_NOTIMPL) {
-               snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "I/O command %d not implemented in backend", command);
                ftdm_log(FTDM_LOG_ERROR, "I/O backend does not support command %d!\n", command);        
        }
+
 done:
-       ftdm_mutex_unlock(ftdmchan->mutex);
+       ftdm_channel_unlock(ftdmchan);
+
        return status;
 
 }
index ca16219e49ff5a6f1d38f213ad0673c4ae6d3d21..96ffdce62c162b2a15f2663c1f811bc838ab16bf 100755 (executable)
@@ -707,7 +707,10 @@ typedef enum {
        FTDM_COMMAND_FLUSH_TX_BUFFERS = 45,
        FTDM_COMMAND_FLUSH_RX_BUFFERS = 46,
        FTDM_COMMAND_FLUSH_BUFFERS = 47,
+
+       /*!< Flush IO statistics */
        FTDM_COMMAND_FLUSH_IOSTATS = 48,
+
        FTDM_COMMAND_SET_PRE_BUFFER_SIZE = 49,
        FTDM_COMMAND_SET_LINK_STATUS = 50,
        FTDM_COMMAND_GET_LINK_STATUS = 51,
@@ -719,6 +722,11 @@ typedef enum {
        FTDM_COMMAND_START_MF_PLAYBACK = 57,
        FTDM_COMMAND_STOP_MF_PLAYBACK = 58,
 
+       /*!< Get a copy of the current IO stats */
+       FTDM_COMMAND_GET_IOSTATS = 59,
+       /*!< Enable/disable IO stats in the channel */
+       FTDM_COMMAND_SWITCH_IOSTATS =  60,
+
        FTDM_COMMAND_COUNT,
 } ftdm_command_t;
 
@@ -903,6 +911,37 @@ typedef enum {
        FTDM_MF_DIRECTION_BACKWARD = (1 << 9)
 } ftdm_mf_direction_flag_t;
 
+/*! \brief IO Error statistics */
+typedef enum {
+       FTDM_IOSTATS_ERROR_CRC          = (1 << 0),
+       FTDM_IOSTATS_ERROR_FRAME        = (1 << 1),
+       FTDM_IOSTATS_ERROR_ABORT        = (1 << 2),
+       FTDM_IOSTATS_ERROR_FIFO         = (1 << 3),
+       FTDM_IOSTATS_ERROR_DMA          = (1 << 4),
+       FTDM_IOSTATS_ERROR_QUEUE_THRES  = (1 << 5), /* Queue reached high threshold */
+       FTDM_IOSTATS_ERROR_QUEUE_FULL   = (1 << 6), /* Queue is full */
+} ftdm_iostats_error_type_t;
+
+/*! \brief IO statistics */
+typedef struct {
+       struct {
+               uint32_t errors;
+               uint16_t flags;
+               uint8_t  queue_size;    /*!< max queue size configured */
+               uint8_t  queue_len;     /*!< Current number of elements in queue */
+               uint64_t packets;
+       } rx;
+
+       struct {
+               uint32_t errors;
+               uint16_t flags;
+               uint8_t  idle_packets;
+               uint8_t  queue_size;    /*!< max queue size configured */
+               uint8_t  queue_len;     /*!< Current number of elements in queue */
+               uint64_t packets;
+       } tx;
+} ftdm_channel_iostats_t;
+
 /*! \brief Override the default queue handler */
 FT_DECLARE(ftdm_status_t) ftdm_global_set_queue_handler(ftdm_queue_handler_t *handler);
 
index e4be27ce400a29b8487d191ad5df1cf04036bef3..9c5c9ad4686bf82b012de6fa3b80011afebbbc60 100644 (file)
@@ -359,35 +359,6 @@ typedef struct {
        ftdm_mutex_t *mutex;
 } ftdm_dtmf_debug_t;
 
-typedef enum {
-       FTDM_IOSTATS_ERROR_CRC          = (1 << 0),
-       FTDM_IOSTATS_ERROR_FRAME        = (1 << 1),
-       FTDM_IOSTATS_ERROR_ABORT        = (1 << 2),
-       FTDM_IOSTATS_ERROR_FIFO         = (1 << 3),
-       FTDM_IOSTATS_ERROR_DMA          = (1 << 4),
-       FTDM_IOSTATS_ERROR_QUEUE_THRES  = (1 << 5), /* Queue reached high threshold */
-       FTDM_IOSTATS_ERROR_QUEUE_FULL   = (1 << 6), /* Queue is full */
-} ftdm_iostats_error_type_t;
-
-typedef struct {
-       struct {
-               uint32_t errors;
-               uint16_t flags;
-               uint8_t  queue_size;    /* max queue size configured */
-               uint8_t  queue_len;     /* Current number of elements in queue */
-               uint64_t packets;
-       } rx;
-
-       struct {
-               uint32_t errors;
-               uint16_t flags;
-               uint8_t  idle_packets;
-               uint8_t  queue_size;    /* max queue size configured */
-               uint8_t  queue_len;     /* Current number of elements in queue */
-               uint64_t packets;
-       } tx;
-} ftdm_channel_iostats_t;
-
 /* 2^8 table size, one for each byte (sample) value */
 #define FTDM_GAINS_TABLE_SIZE 256
 struct ftdm_channel {