FreeTDM - ISDN fix for BRI lines with Q.921 layer going idle

This commit is contained in:
David Yat Sin 2012-04-03 16:48:14 -04:00
parent d730df77e4
commit be4512be03
7 changed files with 76 additions and 29 deletions

View File

@ -682,16 +682,26 @@ static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdm
break; break;
case FTDM_CHANNEL_STATE_DIALING: /* outgoing call request */ case FTDM_CHANNEL_STATE_DIALING: /* outgoing call request */
{ {
if (FTDM_SPAN_IS_BRI(ftdmchan->span) && if (FTDM_SPAN_IS_BRI(ftdmchan->span) && ftdm_test_flag(ftdmchan->span, FTDM_SPAN_PWR_SAVING)) {
ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM) && ftdm_signaling_status_t sigstatus;
ftdm_test_flag(ftdmchan->span, FTDM_SPAN_PWR_SAVING)) { ftdm_span_get_sig_status(ftdmchan->span, &sigstatus);
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM)) {
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)ftdmchan->span->signal_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Requesting Physical Line activation\n");
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 if (sigstatus == FTDM_SIG_STATE_DOWN) {
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"); ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Requesting Q.921 Line activation\n");
sngisdn_set_flag(sngisdn_info, FLAG_ACTIVATING); sngisdn_set_flag(sngisdn_info, FLAG_ACTIVATING);
ftdm_sangoma_isdn_wakeup_phy(ftdmchan); sngisdn_snd_info_req(ftdmchan);
ftdm_sched_timer(signal_data->sched, "timer_t3", signal_data->timer_t3*1000, sngisdn_t3_timeout, (void*) sngisdn_info, NULL); 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);
}
} else { } else {
sngisdn_snd_setup(ftdmchan); sngisdn_snd_setup(ftdmchan);
} }

View File

@ -49,6 +49,16 @@ void sngisdn_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status
sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sig.ev_data.sigstatus.status = status; sig.ev_data.sigstatus.status = status;
ftdm_span_send_signal(ftdmchan->span, &sig); ftdm_span_send_signal(ftdmchan->span, &sig);
if (FTDM_SPAN_IS_BRI(ftdmchan->span)) {
sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)ftdmchan->span->signal_data;
if (ftdm_test_flag(sngisdn_info, FLAG_ACTIVATING)) {
ftdm_clear_flag(sngisdn_info, FLAG_ACTIVATING);
ftdm_sched_timer(signal_data->sched, "delayed_setup", 1000, sngisdn_delayed_setup, (void*) sngisdn_info, NULL);
}
}
return; return;
} }

View File

@ -972,8 +972,19 @@ ftdm_status_t sngisdn_stack_cfg_q931_lce(ftdm_span_t *span)
cfg.t.cfg.s.inLCe.sapId = signal_data->dchan_id; cfg.t.cfg.s.inLCe.sapId = signal_data->dchan_id;
cfg.t.cfg.s.inLCe.lnkUpDwnInd = TRUE; cfg.t.cfg.s.inLCe.lnkUpDwnInd = TRUE;
cfg.t.cfg.s.inLCe.tCon.enb = TRUE;
cfg.t.cfg.s.inLCe.tCon.val = 35; if (FTDM_SPAN_IS_BRI(span)) {
/* tCon Timer causes unwanted hangup on BRI links
where the Q.921 link goes into disconnected
state when idle. */
cfg.t.cfg.s.inLCe.tCon.enb = FALSE;
cfg.t.cfg.s.inLCe.tCon.val = 0;
} else {
cfg.t.cfg.s.inLCe.tCon.enb = TRUE;
cfg.t.cfg.s.inLCe.tCon.val = 35;
}
cfg.t.cfg.s.inLCe.tDisc.enb = TRUE; cfg.t.cfg.s.inLCe.tDisc.enb = TRUE;
cfg.t.cfg.s.inLCe.tDisc.val = 35; cfg.t.cfg.s.inLCe.tDisc.val = 35;
cfg.t.cfg.s.inLCe.t314.enb = FALSE; /* if segmentation enabled, set to TRUE */ cfg.t.cfg.s.inLCe.t314.enb = FALSE; /* if segmentation enabled, set to TRUE */

View File

@ -1169,6 +1169,7 @@ static ftdm_status_t sngisdn_bring_down(ftdm_channel_t *ftdmchan)
void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event) void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event)
{ {
ftdm_signaling_status_t sigstatus;
int16_t suId = sngisdn_event->suId; int16_t suId = sngisdn_event->suId;
int16_t dChan = sngisdn_event->dChan; int16_t dChan = sngisdn_event->dChan;
uint8_t ces = sngisdn_event->ces; uint8_t ces = sngisdn_event->ces;
@ -1214,22 +1215,25 @@ void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event)
} }
} }
if (chan_no) { /* For a single channel */ ftdm_span_get_sig_status(signal_data->ftdm_span, &sigstatus);
if (chan_no > ftdm_span_get_chan_count(signal_data->ftdm_span)) { if (sigstatus == FTDM_SIG_STATE_DOWN) {
ftdm_log(FTDM_LOG_CRIT, "Received RESTART on invalid channel:%d\n", chan_no); if (chan_no) { /* For a single channel */
} else { if (chan_no > ftdm_span_get_chan_count(signal_data->ftdm_span)) {
ftdm_channel_t *ftdmchan = ftdm_span_get_channel(signal_data->ftdm_span, chan_no); ftdm_log(FTDM_LOG_CRIT, "Received RESTART on invalid channel:%d\n", chan_no);
sngisdn_bring_down(ftdmchan); } else {
} ftdm_channel_t *ftdmchan = ftdm_span_get_channel(signal_data->ftdm_span, chan_no);
} else { /* for all channels */ sngisdn_bring_down(ftdmchan);
ftdm_iterator_t *chaniter = NULL; }
ftdm_iterator_t *curr = NULL; } else { /* for all channels */
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL); chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
sngisdn_bring_down((ftdm_channel_t*)ftdm_iterator_current(curr)); sngisdn_bring_down((ftdm_channel_t*)ftdm_iterator_current(curr));
}
ftdm_iterator_free(chaniter);
} }
ftdm_iterator_free(chaniter);
} }
ftdm_log(FTDM_LOG_DEBUG, "Processing RESTART CFM (suId:%u dChan:%d ces:%d type:%d)\n", suId, dChan, ces, evntType); ftdm_log(FTDM_LOG_DEBUG, "Processing RESTART CFM (suId:%u dChan:%d ces:%d type:%d)\n", suId, dChan, ces, evntType);

View File

@ -305,6 +305,7 @@ void sngisdn_snd_fac_req(ftdm_channel_t *ftdmchan)
return; return;
} }
/* This is used to request Q.921 to initiate link establishment */
void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan) void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan)
{ {
CnStEvnt cnStEvnt; CnStEvnt cnStEvnt;

View File

@ -689,6 +689,17 @@ void sngisdn_rcv_q921_ind(BdMngmt *status)
DECODE_LCM_CATEGORY(status->t.usta.alarm.category), DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
DECODE_LLD_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event, DECODE_LLD_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
DECODE_LLD_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause); DECODE_LLD_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
if (FTDM_SPAN_IS_BRI(ftdmspan) && (status->t.usta.alarm.event == PROT_ST_DN)) {
/* Q.921 link is down - This is a line where the Q.921 stops transmitting
after the line goes idle.
Do not drop current calls, but set sigstatus do down so that we
can try to re-initialize link before trying new outbound calls */
sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_DOWN);
sngisdn_set_span_avail_rate(ftdmspan, SNGISDN_AVAIL_PWR_SAVING);
}
break; break;
default: default:
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] %s: %s: %s(%d): %s(%d)\n", ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] %s: %s: %s(%d): %s(%d)\n",

View File

@ -112,7 +112,7 @@ uint8_t get_bits(uint8_t octet, uint8_t bitLo, uint8_t bitHi)
void sngisdn_trace_interpreted_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len) void sngisdn_trace_interpreted_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len)
{ {
char *data_str = ftdm_calloc(1,200); /* TODO Find a proper size */ char *data_str = ftdm_calloc(1,500); /* TODO Find a proper size */
sngisdn_decode_q921(data_str, data, data_len); sngisdn_decode_q921(data_str, data, data_len);
ftdm_log(FTDM_LOG_DEBUG, "[SNGISDN Q921] %s FRAME %s:\n%s\n", signal_data->ftdm_span->name, ftdm_trace_dir2str(dir), data_str); ftdm_log(FTDM_LOG_DEBUG, "[SNGISDN Q921] %s FRAME %s:\n%s\n", signal_data->ftdm_span->name, ftdm_trace_dir2str(dir), data_str);
ftdm_safe_free(data_str); ftdm_safe_free(data_str);