freetdm:Changes for shared IO

This commit is contained in:
David Yat Sin 2010-11-15 19:16:09 -05:00
parent caacb24500
commit a2add13963
8 changed files with 153 additions and 53 deletions

View File

@ -51,6 +51,8 @@ static void ftdm_sangoma_isdn_poll_events(ftdm_span_t *span);
static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_event_t event);
static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan);
static void ftdm_sangoma_isdn_process_stack_event (ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event);
static void ftdm_sangoma_isdn_wakeup_phy(ftdm_channel_t *dchan);
static void ftdm_sangoma_isdn_dchan_set_queue_size(ftdm_channel_t *ftdmchan);
static ftdm_io_interface_t g_sngisdn_io_interface;
static sng_isdn_event_interface_t g_sngisdn_event_interface;
@ -241,8 +243,9 @@ static __inline__ void ftdm_sangoma_isdn_advance_chan_states(ftdm_channel_t *ftd
static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_event_t event)
{
sngisdn_snd_event(span, event);
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
sngisdn_snd_event(signal_data->dchan, event);
switch (event) {
/* Check if the span woke up from power-saving mode */
case FTDM_OOB_ALARM_CLEAR:
@ -251,8 +254,7 @@ static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_eve
sngisdn_chan_data_t *sngisdn_info;
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
chaniter = ftdm_span_get_chan_iterator(span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
@ -261,7 +263,7 @@ static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_eve
if (ftdm_test_flag(sngisdn_info, FLAG_ACTIVATING)) {
ftdm_clear_flag(sngisdn_info, FLAG_ACTIVATING);
ftdm_sched_timer(signal_data->sched, "delayed_setup", 1, sngisdn_delayed_setup, (void*) ftdmchan->call_data, NULL);
ftdm_sched_timer(signal_data->sched, "delayed_setup", 1000, sngisdn_delayed_setup, (void*) ftdmchan->call_data, NULL);
}
}
ftdm_iterator_free(chaniter);
@ -276,9 +278,7 @@ static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_eve
static void ftdm_sangoma_isdn_poll_events(ftdm_span_t *span)
{
ftdm_status_t ret_status;
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
ret_status = ftdm_span_poll_event(span, 0, NULL);
switch(ret_status) {
case FTDM_SUCCESS:
@ -297,6 +297,33 @@ static void ftdm_sangoma_isdn_poll_events(ftdm_span_t *span)
}
}
static void ftdm_sangoma_isdn_dchan_set_queue_size(ftdm_channel_t *dchan)
{
ftdm_status_t ret_status;
uint32_t queue_size;
queue_size = SNGISDN_DCHAN_QUEUE_LEN;
ret_status = ftdm_channel_command(dchan, FTDM_COMMAND_SET_RX_QUEUE_SIZE, &queue_size);
ftdm_assert(ret_status == FTDM_SUCCESS, "Failed to set Rx Queue size");
queue_size = SNGISDN_DCHAN_QUEUE_LEN;
ret_status = ftdm_channel_command(dchan, FTDM_COMMAND_SET_TX_QUEUE_SIZE, &queue_size);
ftdm_assert(ret_status == FTDM_SUCCESS, "Failed to set Tx Queue size");
RETVOID;
}
static void ftdm_sangoma_isdn_wakeup_phy(ftdm_channel_t *dchan)
{
ftdm_status_t ret_status;
ftdm_channel_hw_link_status_t status = FTDM_HW_LINK_CONNECTED;
ret_status = ftdm_channel_command(dchan, FTDM_COMMAND_SET_LINK_STATUS, &status);
if (ret_status != FTDM_SUCCESS) {
ftdm_log_chan_msg(dchan, FTDM_LOG_WARNING, "Failed to wake-up link\n");
}
return;
}
static void *ftdm_sangoma_isdn_dchan_run(ftdm_thread_t *me, void *obj)
{
uint8_t data[1000];
@ -306,7 +333,9 @@ static void *ftdm_sangoma_isdn_dchan_run(ftdm_thread_t *me, void *obj)
ftdm_channel_t *dchan = ((sngisdn_span_data_t*)span->signal_data)->dchan;
ftdm_size_t len = 0;
ftdm_channel_set_feature(dchan, FTDM_CHANNEL_FEATURE_IO_STATS);
ftdm_sangoma_isdn_dchan_set_queue_size(dchan);
ftdm_assert(dchan, "Span does not have a dchannel");
ftdm_channel_open_chan(dchan);
@ -597,8 +626,8 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Requesting Line activation\n");
sngisdn_set_flag(sngisdn_info, FLAG_ACTIVATING);
sngisdn_wake_up_phy(ftdmchan->span);
sngisdn_set_flag(sngisdn_info, FLAG_ACTIVATING);
ftdm_sangoma_isdn_wakeup_phy(ftdmchan);
ftdm_sched_timer(signal_data->sched, "timer_t3", signal_data->timer_t3*1000, sngisdn_t3_timeout, (void*) sngisdn_info, NULL);
} else {
sngisdn_snd_setup(ftdmchan);

View File

@ -60,6 +60,7 @@
#define SNGISDN_EVENT_QUEUE_SIZE 100
#define SNGISDN_EVENT_POLL_RATE 100
#define SNGISDN_NUM_LOCAL_NUMBERS 8
#define SNGISDN_DCHAN_QUEUE_LEN 200
/* TODO: rename all *_cc_* to *_an_* */
@ -294,7 +295,7 @@ void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan);
void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan);
void sngisdn_snd_status_enq(ftdm_channel_t *ftdmchan);
void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len);
void sngisdn_snd_event(ftdm_channel_t *span, sng_isdn_l1_event_t l1_event);
void sngisdn_snd_event(ftdm_channel_t *dchan, ftdm_oob_event_t event);
/* Inbound Call Control functions */
void sngisdn_rcv_con_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, int16_t dChan, uint8_t ces);
@ -314,7 +315,7 @@ void sngisdn_rcv_srv_ind(int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces)
void sngisdn_rcv_srv_cfm(int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces);
void sngisdn_rcv_rst_cfm(int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType);
void sngisdn_rcv_rst_ind(int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType);
int16_t sngisdn_rcv_l1_data_req(uint16_t spId, sng_isdn_l1_frame_t *l1_frame);
int16_t sngisdn_rcv_l1_data_req(uint16_t spId, sng_l1_frame_t *l1_frame);
int16_t sngisdn_rcv_l1_cmd_req(uint16_t spId, sng_l1_cmd_t *l1_cmd);

View File

@ -598,7 +598,7 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare)
/* We received an incoming frame on the d-channel, send data to the stack */
void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len)
{
l1_frame_t l1_frame;
sng_l1_frame_t l1_frame;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) dchan->span->signal_data;
memset(&l1_frame, 0, sizeof(l1_frame));
@ -606,32 +606,32 @@ void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len)
memcpy(&l1_frame.data, data, len);
if (ftdm_test_flag(&(dchan->iostats.s.rx), FTDM_IOSTATS_ERROR_CRC)) {
if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_CRC)) {
l1_frame.flags |= SNG_L1FRAME_ERROR_CRC;
}
if (ftdm_test_flag(&(dchan->iostats.s.rx), FTDM_IOSTATS_ERROR_FRAME)) {
if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_FRAME)) {
l1_frame.flags |= SNG_L1FRAME_ERROR_FRAME;
}
if (ftdm_test_flag(&(dchan->iostats.s.rx), FTDM_IOSTATS_ERROR_ABORT)) {
if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_ABORT)) {
l1_frame.flags |= SNG_L1FRAME_ERROR_ABORT;
}
if (ftdm_test_flag(&(dchan->iostats.s.rx), FTDM_IOSTATS_ERROR_FIFO)) {
if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_FIFO)) {
l1_frame.flags |= SNG_L1FRAME_ERROR_FIFO;
}
if (ftdm_test_flag(&(dchan->iostats.s.rx), FTDM_IOSTATS_ERROR_DMA)) {
if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_DMA)) {
l1_frame.flags |= SNG_L1FRAME_ERROR_DMA;
}
if (ftdm_test_flag(&(dchan->iostats.s.rx), FTDM_IOSTATS_QUEUE_THRES)) {
if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)) {
/* Should we trigger congestion here? */
l1_frame.flags |= SNG_L1FRAME_QUEUE_THRES;
}
if (ftdm_test_flag(&(dchan->iostats.s.rx), FTDM_IOSTATS_QUEUE_FULL)) {
if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL)) {
/* Should we trigger congestion here? */
l1_frame.flags |= SNG_L1FRAME_QUEUE_FULL;
}
@ -640,14 +640,20 @@ void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len)
}
void sngisdn_snd_event(ftdm_channel_t *dchan, ftdm_oob_event_t event)
{
{
sng_l1_event_t l1_event;
memset(&l1_event, 0, sizeof(l1_event));
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) dchan->span->signal_data;
switch(event) {
case FTDM_OOB_ALARM_CLEAR:
sng_isdn_event_ind(signal_data->link_id, SNG_L1EVENT_ALARM_OFF);
l1_event.type = SNG_L1EVENT_ALARM_OFF;
sng_isdn_event_ind(signal_data->link_id, &l1_event);
break;
case FTDM_OOB_ALARM_TRAP:
sng_isdn_event_ind(signal_data->link_id, SNG_L1EVENT_ALARM_ON);
l1_event.type = SNG_L1EVENT_ALARM_ON;
sng_isdn_event_ind(signal_data->link_id, &l1_event);
break;
default:
/* We do not care about the other OOB events for now */

View File

@ -866,13 +866,15 @@ end_of_trace:
return;
}
int16_t sngisdn_rcv_data_req(uint16_t spId, uint8_t *buff, uint32_t length)
/* The stacks is wants to transmit a frame */
int16_t sngisdn_rcv_l1_data_req(uint16_t spId, sng_l1_frame_t *l1_frame)
{
ftdm_status_t status;
ftdm_wait_flag_t flags = FTDM_WRITE;
sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[spId];
ftdm_assert(signal_data, "Received Data request on unconfigured span\n");
ftdm_size_t length = l1_frame->len;
do {
flags = FTDM_WRITE;
status = signal_data->dchan->fio->wait(signal_data->dchan, &flags, 1000);
@ -883,7 +885,7 @@ int16_t sngisdn_rcv_data_req(uint16_t spId, uint8_t *buff, uint32_t length)
if ((flags & FTDM_WRITE)) {
status = signal_data->dchan->fio->write(signal_data->dchan, buff, (ftdm_size_t*)&length);
status = signal_data->dchan->fio->write(signal_data->dchan, l1_frame->data, (ftdm_size_t*)&length);
if (status != FTDM_SUCCESS) {
ftdm_log_chan_msg(signal_data->dchan, FTDM_LOG_CRIT, "Failed to transmit frame\n");
return -1;
@ -900,6 +902,45 @@ int16_t sngisdn_rcv_data_req(uint16_t spId, uint8_t *buff, uint32_t length)
return 0;
}
int16_t sngisdn_rcv_l1_cmd_req(uint16_t spId, sng_l1_cmd_t *l1_cmd)
{
sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[spId];
ftdm_assert(signal_data, "Received Data request on unconfigured span\n");
switch(l1_cmd->type) {
case SNG_L1CMD_SET_LINK_STATUS:
{
ftdm_channel_hw_link_status_t status = FTDM_HW_LINK_CONNECTED;
ftdm_channel_command(signal_data->dchan, FTDM_COMMAND_SET_LINK_STATUS, &status);
}
break;
case SNG_L1CMD_GET_LINK_STATUS:
{
ftdm_channel_hw_link_status_t status = 0;
ftdm_channel_command(signal_data->dchan, FTDM_COMMAND_GET_LINK_STATUS, &status);
if (status == FTDM_HW_LINK_CONNECTED) {
l1_cmd->cmd.status = 1;
} else if (status == FTDM_HW_LINK_DISCONNECTED) {
l1_cmd->cmd.status = 0;
} else {
ftdm_log_chan(signal_data->dchan, FTDM_LOG_CRIT, "Invalid link status reported %d\n", status);
l1_cmd->cmd.status = 0;
}
}
break;
case SNG_L1CMD_FLUSH_STATS:
ftdm_channel_command(signal_data->dchan, FTDM_COMMAND_FLUSH_IOSTATS, NULL);
break;
case SNG_L1CMD_FLUSH_BUFFERS:
ftdm_channel_command(signal_data->dchan, FTDM_COMMAND_FLUSH_BUFFERS, NULL);
break;
default:
ftdm_log_chan(signal_data->dchan, FTDM_LOG_CRIT, "Unsupported channel command:%d\n", l1_cmd->type);
return -1;
}
return 0;
}
void sngisdn_rcv_sng_assert(char *message)
{
ftdm_assert(0, message);

View File

@ -746,6 +746,28 @@ static FIO_COMMAND_FUNCTION(wanpipe_command)
}
}
break;
case FTDM_COMMAND_FLUSH_BUFFERS:
{
err = sangoma_flush_bufs(ftdmchan->sockfd, &tdm_api);
}
break;
case FTDM_COMMAND_FLUSH_IOSTATS:
{
err = sangoma_flush_stats(ftdmchan->sockfd, &tdm_api);
}
break;
case FTDM_COMMAND_SET_RX_QUEUE_SIZE:
{
uint32_t queue_size = FTDM_COMMAND_OBJ_INT;
err = sangoma_set_rx_queue_sz(ftdmchan->sockfd, &tdm_api, queue_size);
}
break;
case FTDM_COMMAND_SET_TX_QUEUE_SIZE:
{
uint32_t queue_size = FTDM_COMMAND_OBJ_INT;
err = sangoma_set_tx_queue_sz(ftdmchan->sockfd, &tdm_api, queue_size);
}
break;
default:
break;
};
@ -759,45 +781,42 @@ static FIO_COMMAND_FUNCTION(wanpipe_command)
return FTDM_SUCCESS;
}
static void wanpipe_read_stats(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.s.rx.error_flags = 0;
if (rx_stats->rx_hdr_errors) {
wanpipe_reset_stats(ftdmchan);
ftdm_log_chan_msg_throttle(ftdmchan, "IO errors\n");
}
ftdmchan->iostats.stats.rx.flags = 0;
ftdmchan->iostats.s.rx_queue_size = rx_stats->rx_h.rx_h.max_rx_queue_length;
ftdmchan->iostats.s.rx_queue_len = rx_stats->rx_h.current_number_of_frames_in_rx_queue;
ftdmchan->iostats.stats.rx.errors = rx_stats->wp_api_rx_hdr_errors;
ftdmchan->iostats.stats.rx.rx_queue_size = rx_stats->wp_api_rx_hdr_max_queue_length;
ftdmchan->iostats.stats.rx.rx_queue_len = rx_stats->wp_api_rx_hdr_number_of_frames_in_queue;
if (rx_stats->rx_h.wp_api_rx_hdr_error_map & (1<<WP_ABORT_ERROR_BIT)) {
ftdm_set_flag(&(ftdmchan->iostats.s.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->rx_h.wp_api_rx_hdr_error_map & (1<<WP_DMA_ERROR_BIT)) {
ftdm_set_flag(&(ftdmchan->iostats.s.rx), FTDM_IOSTATS_ERROR_DMA);
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->rx_h.wp_api_rx_hdr_error_map & (1<<WP_FIFO_ERROR_BIT)) {
ftdm_set_flag(&(ftdmchan->iostats.s.rx), FTDM_IOSTATS_ERROR_FIFO);
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->rx_h.wp_api_rx_hdr_error_map & (1<<WP_CRC_ERROR_BIT)) {
ftdm_set_flag(&(ftdmchan->iostats.s.rx), FTDM_IOSTATS_ERROR_CRC);
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->rx_h.wp_api_rx_hdr_error_map & (1<<WP_FRAME_ERROR_BIT)) {
ftdm_set_flag(&(ftdmchan->iostats.s.rx), FTDM_IOSTATS_ERROR_FRAME);
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.s.rx_queue_len >= (0.8*ftdmchan->iostats.s.rx_queue_size)) {
if (ftdmchan->iostats.stats.rx.rx_queue_len >= (0.8*ftdmchan->iostats.stats.rx.rx_queue_size)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Rx Queue length exceeded threshold (%d/%d)\n",
ftdmchan->iostats.s.rx_queue_len, ftdmchan->iostats.s.rx_queue_size);
ftdmchan->iostats.stats.rx.rx_queue_len, ftdmchan->iostats.stats.rx.rx_queue_size);
ftdm_set_flag(&(ftdmchan->iostats.s.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES);
ftdm_set_flag(&(ftdmchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES);
}
if (ftdmchan->iostats.s.rx_queue_len >= ftdmchan->iostats.s.rx_queue_size) {
if (ftdmchan->iostats.stats.rx.rx_queue_len >= ftdmchan->iostats.stats.rx.rx_queue_size) {
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Rx Queue Full (%d/%d)\n",
ftdmchan->iostats.s.rx_queue_len, ftdmchan->iostats.s.rx_queue_size);
ftdmchan->iostats.stats.rx.rx_queue_len, ftdmchan->iostats.stats.rx.rx_queue_size);
ftdm_set_flag(&(ftdmchan->iostats.s.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL);
ftdm_set_flag(&(ftdmchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL);
}
return;
}

View File

@ -430,12 +430,15 @@ typedef enum {
FTDM_COMMAND_FLUSH_TX_BUFFERS,
FTDM_COMMAND_FLUSH_RX_BUFFERS,
FTDM_COMMAND_FLUSH_BUFFERS,
FTDM_COMMAND_FLUSH_IOSTATS,
FTDM_COMMAND_SET_PRE_BUFFER_SIZE,
FTDM_COMMAND_SET_LINK_STATUS,
FTDM_COMMAND_GET_LINK_STATUS,
FTDM_COMMAND_ENABLE_LOOP,
FTDM_COMMAND_DISABLE_LOOP,
FTDM_COMMAND_COUNT
FTDM_COMMAND_COUNT,
FTDM_COMMAND_SET_RX_QUEUE_SIZE,
FTDM_COMMAND_SET_TX_QUEUE_SIZE,
} ftdm_command_t;
/*! \brief Custom memory handler hooks. Not recommended to use unless you need memory allocation customizations */

View File

@ -391,7 +391,7 @@ typedef struct {
uint8_t tx_queue_size; /* max queue size configured */
uint8_t tx_queue_len; /* Current number of elements in queue */
} tx;
} s;
} stats;
} ftdm_channel_iostats_t;
/* 2^8 table size, one for each byte (sample) value */

View File

@ -194,6 +194,7 @@ typedef enum {
FTDM_CHANNEL_FEATURE_CALLWAITING = (1 << 6), /*!< Channel will allow call waiting (ie: FXS devices) (read/write) */
FTDM_CHANNEL_FEATURE_HWEC = (1<<7), /*!< Channel has a hardware echo canceller */
FTDM_CHANNEL_FEATURE_HWEC_DISABLED_ON_IDLE = (1<<8), /*!< hardware echo canceller is disabled when there are no calls on this channel */
FTDM_CHANNEL_FEATURE_IO_STATS = (1<<9), /*!< Channel supports IO statistics (HDLC channels only) */
} ftdm_channel_feature_t;
typedef enum {