From af3285ab61bca7fb5f8db1b53d53ddf3d4944bb0 Mon Sep 17 00:00:00 2001 From: Konrad Hammel Date: Thu, 2 Sep 2010 17:33:17 -0400 Subject: [PATCH] freetdm: ss7 - added cli support to send GRS and RSC --- .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c | 194 +++++++++++++++++- .../ftmod_sangoma_ss7_handle.c | 22 +- .../ftmod_sangoma_ss7_main.c | 23 ++- .../ftmod_sangoma_ss7_main.h | 3 +- .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c | 63 +++--- 5 files changed, 245 insertions(+), 60 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c index 7d0488ce7d..edb15604e5 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c @@ -60,6 +60,9 @@ static ftdm_status_t handle_show_flags(ftdm_stream_handle_t *stream, int span, i static ftdm_status_t handle_show_blocks(ftdm_stream_handle_t *stream, int span, int chan, int verbose); static ftdm_status_t handle_show_status(ftdm_stream_handle_t *stream, int span, int chan, int verbose); +static ftdm_status_t handle_tx_rsc(ftdm_stream_handle_t *stream, int span, int chan, int verbose); +static ftdm_status_t handle_tx_grs(ftdm_stream_handle_t *stream, int span, int chan, int range, int verbose); + static ftdm_status_t handle_status_link(ftdm_stream_handle_t *stream, char *name); static ftdm_status_t handle_status_linkset(ftdm_stream_handle_t *stream, char *name); @@ -72,13 +75,14 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha { char *mycmd = NULL; char *argv[10] = { 0 }; - int argc = 0; - int span = 0; - int chan = 0; - int trace = 0; - int trace_level = 7; - int verbose = 1; - int c = 0; + int argc = 0; + int span = 0; + int chan = 0; + int range = 0; + int trace = 0; + int trace_level = 7; + int verbose = 1; + int c = 0; if (data) { mycmd = ftdm_strdup(data); @@ -332,6 +336,61 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha /**********************************************************************/ } /**************************************************************************/ + } else if (!strcasecmp(argv[c], "rsc")) { + /**************************************************************************/ + if (check_arg_count(argc, 2)) goto handle_cli_error_argc; + c++; + + if (!strcasecmp(argv[c], "span")) { + /**********************************************************************/ + if (check_arg_count(argc, 5)) goto handle_cli_error_argc; + + if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; + + handle_tx_rsc(stream, span, chan, verbose); + /**********************************************************************/ + } else { + /**********************************************************************/ + stream->write_function(stream, "Unknown \"rsc\" command\n"); + goto handle_cli_error; + /**********************************************************************/ + } + /**************************************************************************/ + } else if (!strcasecmp(argv[c], "grs")) { + /**************************************************************************/ + if (check_arg_count(argc, 2)) goto handle_cli_error_argc; + c++; + + if (!strcasecmp(argv[c], "span")) { + /**********************************************************************/ + if (check_arg_count(argc, 5)) goto handle_cli_error_argc; + + if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; + c = c + 4; + + if (check_arg_count(argc, 7)) goto handle_cli_error_argc; + + if (!strcasecmp(argv[c], "range")) { + /******************************************************************/ + c++; + range = atoi(argv[c]); + /******************************************************************/ + } else { + /******************************************************************/ + stream->write_function(stream, "Unknown \"grs range\" command\n"); + goto handle_cli_error; + /******************************************************************/ + } + + handle_tx_grs(stream, span, chan, range, verbose); + /**********************************************************************/ + } else { + /**********************************************************************/ + stream->write_function(stream, "Unknown \"grs\" command\n"); + goto handle_cli_error; + /**********************************************************************/ + } + /**************************************************************************/ } else { /**************************************************************************/ goto handle_cli_error; @@ -376,6 +435,8 @@ static ftdm_status_t handle_print_usuage(ftdm_stream_handle_t *stream) stream->write_function(stream, "Ftmod_sangoma_ss7 circuit control:\n"); stream->write_function(stream, "ftdm ss7 block span X chan Y\n"); stream->write_function(stream, "ftdm ss7 unblk span X chan Y\n"); + stream->write_function(stream, "ftdm ss7 rsc span X chan Y\n"); + stream->write_function(stream, "ftdm ss7 grs span X chan Y range Z\n"); stream->write_function(stream, "\n"); return FTDM_SUCCESS; @@ -1090,6 +1151,125 @@ static ftdm_status_t handle_set_uninhibit(ftdm_stream_handle_t *stream, char *na return FTDM_SUCCESS; } +/******************************************************************************/ +static ftdm_status_t handle_tx_rsc(ftdm_stream_handle_t *stream, int span, int chan, int verbose) +{ + int x; + sngss7_chan_data_t *ss7_info; + ftdm_channel_t *ftdmchan; + int lspan; + int lchan; + + x=1; + while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { + if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) { + ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; + ftdmchan = ss7_info->ftdmchan; + + /* if span == 0 then all spans should be printed */ + if (span == 0) { + lspan = ftdmchan->physical_span_id; + } else { + lspan = span; + } + + /* if chan == 0 then all chans should be printed */ + if (chan == 0) { + lchan = ftdmchan->physical_chan_id; + } else { + lchan = chan; + } + + if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) { + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change|give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", ss7_info->circuit->cic); + SS7_ASSERT; + } else { + /* throw the ckt block flag */ + sngss7_set_flag(ss7_info, FLAG_RESET_TX); + + /* set the channel to suspended state */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + } + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + } /* if ( span and chan) */ + + } /* if ( cic != 0) */ + + /* go the next circuit */ + x++; + } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */ + + + return FTDM_SUCCESS; +} + +/******************************************************************************/ +static ftdm_status_t handle_tx_grs(ftdm_stream_handle_t *stream, int span, int chan, int range, int verbose) +{ + int x; + sngss7_chan_data_t *sngss7_info; + ftdm_channel_t *ftdmchan; + sngss7_span_data_t *sngss7_span; + + if (range > 31) { + stream->write_function(stream, "Invalid range value %d", range); + return FTDM_SUCCESS; + } + + x=1; + while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { + if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) { + + sngss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; + ftdmchan = sngss7_info->ftdmchan; + sngss7_span = ftdmchan->span->mod_data; + + if ((ftdmchan->physical_span_id == span) && + ((ftdmchan->physical_chan_id >= chan) && (ftdmchan->physical_chan_id < (chan+range)))) { + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change|give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + SS7_ASSERT; + } else { + /* throw the grp reset flag */ + sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX); + if (ftdmchan->physical_chan_id == chan) { + sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_BASE); + sngss7_span->tx_grs.circuit = sngss7_info->circuit->id; + sngss7_span->tx_grs.range = range-1; + } + + /* set the channel to suspended state */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + + } + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + } /* if ( span and chan) */ + + } /* if ( cic != 0) */ + + /* go the next circuit */ + x++; + } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */ + + + return FTDM_SUCCESS; +} + /******************************************************************************/ static ftdm_status_t extract_span_chan(char *argv[10], int pos, int *span, int *chan) { diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c index a9735c9b62..99b9fe9bc3 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c @@ -99,7 +99,7 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ SS7_ASSERT; }; - if (sngss7_info->glare.spInstId > 0) { + if (sngss7_test_flag(sngss7_info, FLAG_GLARE)) { SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx IAM (glare detected on circuit)\n"); } else { SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx IAM\n"); @@ -569,10 +569,6 @@ ftdm_status_t handle_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ /**************************************************************************/ default: - /* fill in the channels SS7 Stack information */ - sngss7_info->suInstId = get_unique_id(); - sngss7_info->spInstId = spInstId; - /* throw the reset flag */ sngss7_set_flag(sngss7_info, FLAG_RESET_RX); @@ -1685,9 +1681,9 @@ ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ { SS7_FUNC_TRACE_ENTER(__FUNCTION__); - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - sngss7_span_data_t *span = NULL; + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_span_data_t *sngss7_span = NULL; int range; int x; @@ -1725,11 +1721,11 @@ ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ }; /* fill in the span structure for this circuit */ - span = ftdmchan->span->mod_data; - span->grs.circuit = circuit; - span->grs.range = range; + sngss7_span = ftdmchan->span->mod_data; + sngss7_span->rx_grs.circuit = circuit; + sngss7_span->rx_grs.range = range; - SS7_DEBUG_CHAN(ftdmchan, "Rx GRS (%d:%d)\n", + SS7_INFO_CHAN(ftdmchan, "Rx GRS (%d:%d)\n", g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, (g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic + range)); @@ -1800,7 +1796,7 @@ ftdm_status_t handle_grs_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ SS7_ASSERT; }; - SS7_DEBUG_CHAN(ftdmchan, "Rx GRA (%d:%d)\n", + SS7_INFO_CHAN(ftdmchan, "Rx GRA (%d:%d)\n", g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, (g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic + range)); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c index da90d34b48..6d31ac55ad 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c @@ -345,12 +345,12 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj) sngss7_span = (sngss7_span_data_t *)ftdmspan->mod_data; /* check if there is a GRS being processed on the span */ - if (sngss7_span->grs.range > 0) { + if (sngss7_span->rx_grs.range > 0) { ftdm_log(FTDM_LOG_DEBUG, "Found Rx GRS on span %d...checking circuits\n", ftdmspan->span_id); /*SS7_DEBUG("Found Rx GRS on span %d...checking circuits\n", ftdmspan->span_id);*/ /* check all the circuits in the range to see if they are done resetting */ - for ( i = sngss7_span->grs.circuit; i < (sngss7_span->grs.circuit + sngss7_span->grs.range + 1); i++) { + for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) { /* extract the channel in question */ if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { @@ -375,11 +375,11 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj) } /* for ( i = circuit; i < (circuit + range + 1); i++) */ SS7_DEBUG("All circuits out of reset for GRS: circuit=%d, range=%d\n", - sngss7_span->grs.circuit, - sngss7_span->grs.range); + sngss7_span->rx_grs.circuit, + sngss7_span->rx_grs.range); /* check all the circuits in the range to see if they are done resetting */ - for ( i = sngss7_span->grs.circuit; i < (sngss7_span->grs.circuit + sngss7_span->grs.range + 1); i++) { + for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) { /* extract the channel in question */ if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { @@ -396,7 +396,7 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj) } /* for ( i = circuit; i < (circuit + range + 1); i++) */ GRS_UNLOCK_ALL: - for ( i = sngss7_span->grs.circuit; i < (sngss7_span->grs.circuit + sngss7_span->grs.range + 1); i++) { + for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) { /* extract the channel in question */ if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i); @@ -801,14 +801,14 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) * we insure that this is the last circuit to have the state change queued */ sngss7_span_data_t *span = ftdmchan->span->mod_data; - if (span->grs.circuit == sngss7_info->circuit->id) { + if (span->rx_grs.circuit == sngss7_info->circuit->id) { /* send out the GRA */ ft_to_sngss7_gra(ftdmchan); /* clean out the spans GRS structure */ sngss7_span_data_t *span = ftdmchan->span->mod_data; - span->grs.circuit = 0; - span->grs.range = 0; + span->rx_grs.circuit = 0; + span->rx_grs.range = 0; } /* clear the grp reset flag */ @@ -822,6 +822,7 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) if (sngss7_test_flag(sngss7_info, FLAG_RESET_TX_RSP)) { /* clear the reset flag */ sngss7_clear_flag(sngss7_info, FLAG_RESET_TX_RSP); + sngss7_clear_flag(sngss7_info, FLAG_RESET_SENT); sngss7_clear_flag(sngss7_info, FLAG_RESET_TX); } @@ -1295,6 +1296,7 @@ static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t * span) { ftdm_channel_t *ftdmchan = NULL; sngss7_chan_data_t *sngss7_info = NULL; + sngss7_span_data_t *sngss7_span = NULL; int x; @@ -1305,6 +1307,7 @@ static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t * span) /* extract the channel structure and sngss7 channel data */ ftdmchan = span->channels[x]; sngss7_info = ftdmchan->call_data; + sngss7_span = ftdmchan->span->mod_data; /* lock the channel */ ftdm_mutex_lock(ftdmchan->mutex); @@ -1316,6 +1319,8 @@ static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t * span) sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX); if (x == 1) { sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_BASE); + sngss7_span->tx_grs.circuit = sngss7_info->circuit->id; + sngss7_span->tx_grs.range = span->chan_count -1; } /* throw the channel to suspend */ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h index 45cf4957b6..050f59e00e 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h @@ -346,7 +346,8 @@ typedef struct sngss7_chan_data { typedef struct sngss7_span_data { ftdm_sched_t *sched; - sngss7_group_data_t grs; + sngss7_group_data_t rx_grs; + sngss7_group_data_t tx_grs; ftdm_queue_t *event_queue; }sngss7_span_data_t; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c index 600a52910c..28ff6bd4cd 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c @@ -415,7 +415,7 @@ void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan) { SS7_FUNC_TRACE_ENTER (__FUNCTION__); - sngss7_span_data_t *span = ftdmchan->span->mod_data; + sngss7_span_data_t *sngss7_span = ftdmchan->span->mod_data; sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; SiStaEvnt gra; @@ -426,11 +426,11 @@ void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan) /* fill in the range */ gra.rangStat.range.pres = PRSNT_NODEF; - gra.rangStat.range.val = span->grs.range; + gra.rangStat.range.val = sngss7_span->rx_grs.range; /* fill in the status */ gra.rangStat.status.pres = PRSNT_NODEF; - gra.rangStat.status.len = ((span->grs.range + 1) >> 3) + (((span->grs.range + 1) & 0x07) ? 1 : 0); + gra.rangStat.status.len = ((sngss7_span->rx_grs.range + 1) >> 3) + (((sngss7_span->rx_grs.range + 1) & 0x07) ? 1 : 0); /* the status field should be 1 if blocked for maintenace reasons * and 0 is not blocked....since we memset the struct nothing to do @@ -440,12 +440,14 @@ void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan) sng_cc_sta_request (1, 0, 0, - span->grs.circuit, + sngss7_span->rx_grs.circuit, 0, SIT_STA_GRSRSP, &gra); - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx GRA\n"); + SS7_INFO_CHAN(ftdmchan, "Tx GRA (%d:%d)\n", + sngss7_info->circuit->cic, + (sngss7_info->circuit->cic + sngss7_span->rx_grs.range)); SS7_FUNC_TRACE_EXIT (__FUNCTION__); return; @@ -454,31 +456,32 @@ void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan) /******************************************************************************/ void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan) { -SS7_FUNC_TRACE_ENTER (__FUNCTION__); - -sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; -ftdm_span_t *span = ftdmchan->span; - -SiStaEvnt grs; - -memset (&grs, 0x0, sizeof (grs)); - -grs.rangStat.eh.pres = PRSNT_NODEF; -grs.rangStat.range.pres = PRSNT_NODEF; -grs.rangStat.range.val = span->chan_count-1; - -sng_cc_sta_request (1, - 0, - 0, - sngss7_info->circuit->id, - 0, - SIT_STA_GRSREQ, - &grs); - - -SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx GRS\n"); - -SS7_FUNC_TRACE_EXIT (__FUNCTION__); + SS7_FUNC_TRACE_ENTER (__FUNCTION__); + + sngss7_span_data_t *sngss7_span = ftdmchan->span->mod_data; + sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; + + SiStaEvnt grs; + + memset (&grs, 0x0, sizeof (grs)); + + grs.rangStat.eh.pres = PRSNT_NODEF; + grs.rangStat.range.pres = PRSNT_NODEF; + grs.rangStat.range.val = sngss7_span->tx_grs.range; + + sng_cc_sta_request (1, + 0, + 0, + sngss7_span->tx_grs.circuit, + 0, + SIT_STA_GRSREQ, + &grs); + + SS7_INFO_CHAN(ftdmchan, "Tx GRS (%d:%d)\n", + sngss7_info->circuit->cic, + (sngss7_info->circuit->cic + sngss7_span->tx_grs.range)); + + SS7_FUNC_TRACE_EXIT (__FUNCTION__); return; }