freetdm: Manually merged relay code from branch jz.smg_ss7 (based on releases.3.3)

- Added relay and other misc commands
        - Misc fixes in hardware blocks, hw alarm etc
	- Fix crash on shutdown in relay
This commit is contained in:
Moises Silva 2011-09-21 15:15:19 -04:00
parent 8bf6312a0e
commit 4c64d53efb
6 changed files with 898 additions and 238 deletions

View File

@ -1643,8 +1643,8 @@ ftdm_status_t handle_ubl_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
ftdm_mutex_lock(ftdmchan->mutex);
/* check if the channel is blocked */
if (!(sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX))) {
SS7_WARN("Received UBL on circuit that is not blocked!\n");
if (!(sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) && !sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX)) {
SS7_WARN("Received UBL on circuit that is not blocked! span= %d, chan= %d , flag = %x \n", g_ftdm_sngss7_data.cfg.isupCkt[circuit].span, g_ftdm_sngss7_data.cfg.isupCkt[circuit].chan,sngss7_info->blk_flags );
}
/* throw the unblock flag */
@ -1652,6 +1652,8 @@ ftdm_status_t handle_ubl_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/* clear the block flag */
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX);
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX);
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX_DN);
/* set the channel to suspended state */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
@ -1692,14 +1694,6 @@ ftdm_status_t handle_ubl_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ
DECODE_LCC_EVENT(evntType));
}
/* lock the channel */
ftdm_mutex_lock(ftdmchan->mutex);
/* KONRAD FIX ME */
/* unlock the channel again before we exit */
ftdm_mutex_unlock(ftdmchan->mutex);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return FTDM_SUCCESS;
}
@ -2453,6 +2447,8 @@ ftdm_status_t handle_cgu_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/**********************************************************************/
case 0: /* maintenance oriented */
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX);
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX);
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX_DN);
break;
/**********************************************************************/
case 1: /* hardware failure oriented */

View File

@ -486,47 +486,47 @@ void sngss7_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint
g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic);
}
x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1;
x = (g_ftdm_sngss7_data.cfg.procId * MAX_CIC_MAP_LENGTH) + 1;
while ((g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) &&
(g_ftdm_sngss7_data.cfg.isupCkt[x].id < ((g_ftdm_sngss7_data.cfg.procId +1) * 1000))) {
/**********************************************************************/
(g_ftdm_sngss7_data.cfg.isupCkt[x].id < ((g_ftdm_sngss7_data.cfg.procId + 1) * MAX_CIC_MAP_LENGTH))) {
/**********************************************************************/
/* confirm this is a voice channel and not a gap/sig (no ftdmchan there) */
if (g_ftdm_sngss7_data.cfg.isupCkt[x].type != SNG_CKT_VOICE) goto move_along;
if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) {
/* compare the intfIds */
if (g_ftdm_sngss7_data.cfg.isupCkt[x].infId == intfId) {
/* we have a match, setup the pointers to the correct values */
circuit = x;
/* compare the intfIds */
if (g_ftdm_sngss7_data.cfg.isupCkt[x].infId == intfId) {
/* we have a match, setup the pointers to the correct values */
circuit = x;
/* confirm that the circuit is active on our side otherwise move to the next circuit */
if (!sngss7_test_flag(&g_ftdm_sngss7_data.cfg.isupCkt[circuit], SNGSS7_ACTIVE)) {
SS7_DEBUG("[CIC:%d]Rx %s but circuit is not active yet, skipping!\n",
g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic,
DECODE_LCC_EVENT(evntType));
x++;
continue;
}
/* confirm that the circuit is active on our side otherwise move to the next circuit */
if (!sngss7_test_flag(&g_ftdm_sngss7_data.cfg.isupCkt[circuit], SNGSS7_ACTIVE)) {
SS7_DEBUG("[CIC:%d]Rx %s but circuit is not active yet, skipping!\n",
g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic,
DECODE_LCC_EVENT(evntType));
continue;
}
if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return;
if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
/* bounce out of the loop */
break;
}
}
/* bounce out of the loop */
break;
} /* if (g_ftdm_sngss7_data.cfg.isupCkt[x].intfId == intfId) */
move_along:
/* move along ... nothing to see here */
x++;
/**********************************************************************/
} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) */
/**********************************************************************/
}
/* check if we found any circuits that are on the intfId, drop the message
* if none are found
*/
if (ftdmchan == NULL) goto sta_ind_end;
* if none are found */
if (!ftdmchan) {
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
break;
/**************************************************************************/
@ -544,7 +544,6 @@ move_along:
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
break;
/**************************************************************************/
} /* switch (evntType) */
@ -571,9 +570,6 @@ move_along:
/* enqueue this event */
ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->signal_data)->event_queue, sngss7_event);
sta_ind_end:
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
}
/******************************************************************************/

View File

@ -31,6 +31,7 @@
* SOFTWARE|EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* INCLUDE ********************************************************************/
#include "ftmod_sangoma_ss7_main.h"
/******************************************************************************/
@ -353,6 +354,8 @@ void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta)
char buf[50];
int x = 1;
SS7_RELAY_DBG_FUN(handle_sng_mtp3_alarm);
memset(buf, '\0', sizeof(buf));
switch (sta->hdr.elmId.elmnt) {
@ -492,6 +495,8 @@ void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta)
char tmp[25];
char *p = NULL;
int x = 0;
SS7_RELAY_DBG_FUN(handle_sng_isup_alarm);
/* initalize the msg variable to NULLs */
memset(&msg[0], '\0', sizeof(&msg));
@ -502,7 +507,6 @@ void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta)
return;
}
/* point p to the first spot in msg */
p = &msg[0];
@ -742,6 +746,7 @@ void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta)
void handle_sng_cc_alarm(Pst *pst, CcMngmt *sta)
{
SS7_RELAY_DBG_FUN(handle_sng_cc_alarm);
return;
} /* handle_cc_alarm */
@ -749,6 +754,7 @@ void handle_sng_cc_alarm(Pst *pst, CcMngmt *sta)
void handle_sng_relay_alarm(Pst *pst, RyMngmt *sta)
{
SS7_RELAY_DBG_FUN(handle_sng_relay_alarm);
switch (sta->hdr.elmId.elmnt) {
/**************************************************************************/

View File

@ -60,6 +60,7 @@ static ftdm_status_t ftdm_sangoma_ss7_stop (ftdm_span_t * span);
static ftdm_status_t ftdm_sangoma_ss7_start (ftdm_span_t * span);
/******************************************************************************/
/* STATE MAP ******************************************************************/
ftdm_state_map_t sangoma_ss7_state_map = {
{
@ -281,7 +282,37 @@ ftdm_state_map_t sangoma_ss7_state_map = {
}
};
/******************************************************************************/
static void handle_hw_alarm(ftdm_event_t *e)
{
sngss7_chan_data_t *ss7_info = NULL;
ftdm_channel_t *ftdmchan = NULL;
int x = 0;
ftdm_assert(e != NULL, "Null event!\n");
for (x = (g_ftdm_sngss7_data.cfg.procId * MAX_CIC_MAP_LENGTH) + 1; g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0; x++) {
if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) {
ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
ftdmchan = ss7_info->ftdmchan;
if (e->channel->span_id == ftdmchan->physical_span_id &&
e->channel->chan_id == ftdmchan->physical_chan_id) {
if (e->enum_id == FTDM_OOB_ALARM_TRAP) {
sngss7_set_ckt_blk_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX);
if (ftdmchan->state != FTDM_CHANNEL_STATE_SUSPENDED) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
}
} else {
sngss7_set_ckt_blk_flag(ss7_info, FLAG_GRP_HW_UNBLK_TX);
sngss7_clear_ckt_blk_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX);
if (ftdmchan->state != FTDM_CHANNEL_STATE_SUSPENDED) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
}
}
}
}
}
}
/* MONITIOR THREADS ***********************************************************/
static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
@ -293,6 +324,9 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
sngss7_event_data_t *sngss7_event = NULL;
sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data;
int b_alarm_test = 1;
sngss7_chan_data_t *ss7_info=NULL;
ftdm_log (FTDM_LOG_INFO, "ftmod_sangoma_ss7 monitor thread for span=%u started.\n", ftdmspan->span_id);
/* set IN_THREAD flag so that we know this thread is running */
@ -311,6 +345,30 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
}
while (ftdm_running () && !(ftdm_test_flag (ftdmspan, FTDM_SPAN_STOP_THREAD))) {
int x = 0;
if (b_alarm_test) {
b_alarm_test = 0;
for (x = (g_ftdm_sngss7_data.cfg.procId * MAX_CIC_MAP_LENGTH) + 1;
g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0; x++) {
if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == SNG_CKT_VOICE) {
ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
ftdmchan = ss7_info->ftdmchan;
if (!ftdmchan) {
continue;
}
if (ftdmchan->alarm_flags != 0) { /* we'll send out block */
sngss7_set_ckt_blk_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX );
} else { /* we'll send out reset */
sngss7_clear_ckt_blk_flag( ss7_info, FLAG_GRP_HW_BLOCK_TX );
sngss7_clear_ckt_blk_flag( ss7_info, FLAG_GRP_HW_BLOCK_TX_DN );
sngss7_set_ckt_blk_flag (ss7_info, FLAG_GRP_HW_UNBLK_TX);
}
}
usleep(50);
}
ftdmchan = NULL;
}
/* check the channel state queue for an event*/
switch ((ftdm_interrupt_multiple_wait(ftdm_sangoma_ss7_int, 2, 100))) {
@ -388,7 +446,11 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
switch (ftdm_span_poll_event(ftdmspan, 0, NULL)) {
/**********************************************************************/
case FTDM_SUCCESS:
while (ftdm_span_next_event(ftdmspan, &event) == FTDM_SUCCESS);
while (ftdm_span_next_event(ftdmspan, &event) == FTDM_SUCCESS) {
if (event->e_type == FTDM_EVENT_OOB) {
handle_hw_alarm(event);
}
}
break;
/**********************************************************************/
case FTDM_TIMEOUT:
@ -1106,16 +1168,97 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* clear the unblock flag */
sngss7_clear_ckt_blk_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX);
/* bring the sig status up */
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP);
/* not bring the cic up if there is a hardware block */
if( !sngss7_test_ckt_blk_flag(sngss7_info, (FLAG_GRP_HW_BLOCK_TX | FLAG_GRP_HW_BLOCK_TX_DN) ) ) {
/* bring the sig status up */
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP);
/* send a uba */
ft_to_sngss7_uba (ftdmchan);
/* send a uba */
ft_to_sngss7_uba (ftdmchan);
}
/* check the last state and return to it to allow the call to finish */
goto suspend_goto_last;
}
/**********************************************************************/
/* hardware block/unblock tx */
if (sngss7_test_ckt_blk_flag (sngss7_info, FLAG_GRP_HW_BLOCK_TX ) &&
!sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX_DN )) {
SS7_DEBUG_CHAN(ftdmchan, "Processing FLAG_GRP_HW_BLOCK_TX flag %s\n", "");
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN);
/* dont send block again if the channel is already blocked by maintenance */
if( !sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX) &&
!sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX_DN)
) {
ft_to_sngss7_blo(ftdmchan);
}
sngss7_set_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX_DN);
goto suspend_goto_last;
}
if (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_UNBLK_TX)) {
SS7_DEBUG_CHAN(ftdmchan, "Processing FLAG_GRP_HW_UNBLK_TX flag %s\n", "");
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX);
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX_DN);
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_UNBLK_TX);
/* do not set the channel up if it's blocked by blo/cgb command OR blocked by receiving blo/cgb */
if (!sngss7_test_ckt_blk_flag(sngss7_info, ( FLAG_CKT_MN_BLOCK_TX
| FLAG_CKT_MN_BLOCK_TX
| FLAG_GRP_MN_BLOCK_TX
| FLAG_GRP_MN_BLOCK_TX_DN
| FLAG_CKT_MN_BLOCK_RX
| FLAG_CKT_MN_BLOCK_RX_DN
| FLAG_GRP_MN_BLOCK_RX
| FLAG_GRP_MN_BLOCK_RX_DN
)
)
) {
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP);
ft_to_sngss7_ubl(ftdmchan);
}
goto suspend_goto_last;
}
#if 0
//jz: there is no such thing of "remote hw block". for receiver, there are only block and unblock
/**********************************************************************/
// jz: hardware block/unblock rx
if (sngss7_test_ckt_blk_flag (sngss7_info, FLAG_GRP_HW_BLOCK_RX ) &&
!sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX_DN )) {
SS7_DEBUG_CHAN(ftdmchan, "Processing FLAG_GRP_HW_BLOCK_RX flag %s\n", "");
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN);
ft_to_sngss7_bla(ftdmchan);
sngss7_set_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX_DN);
goto suspend_goto_last;
}
if (sngss7_test_ckt_blk_flag (sngss7_info, FLAG_GRP_HW_UNBLK_RX )){
SS7_DEBUG_CHAN(ftdmchan, "Processing FLAG_GRP_HW_UNBLK_RX flag %s\n", "");
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX);
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX_DN);
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_UNBLK_RX);
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP);
ft_to_sngss7_uba(ftdmchan);
goto suspend_goto_last;
}
#endif
/**********************************************************************/
if (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX) &&
!sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX_DN)) {
@ -1146,11 +1289,14 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* clear the unblock flag */
sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_UNBLK_TX);
/* bring the sig status up */
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP);
/* not bring the cic up if there is a hardware block */
if (!sngss7_test_ckt_blk_flag(sngss7_info, (FLAG_GRP_HW_BLOCK_TX | FLAG_GRP_HW_BLOCK_TX_DN))) {
/* bring the sig status up */
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP);
/* send a ubl */
ft_to_sngss7_ubl (ftdmchan);
/* send a ubl */
ft_to_sngss7_ubl(ftdmchan);
}
/* check the last state and return to it to allow the call to finish */
goto suspend_goto_last;
@ -1628,6 +1774,7 @@ static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_ss7_unload)
ftdm_log (FTDM_LOG_INFO, "Starting ftmod_sangoma_ss7 unload...\n");
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC_STARTED)) {
sng_isup_free_cc();
sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC_STARTED);
@ -1666,13 +1813,15 @@ static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_ss7_unload)
/* send the specific configuration */
if (ftmod_ss7_disable_relay_channel(x)) {
SS7_CRITICAL("Relay Channel %d disable failed!\n", x);
return 1;
/* jz: dont leave like this
* return 1;
* */
} else {
SS7_INFO("Relay Channel %d disable DONE!\n", x);
}
/* set the SNGSS7_CONFIGURED flag */
g_ftdm_sngss7_data.cfg.relay[x].flags &= !SNGSS7_CONFIGURED;
g_ftdm_sngss7_data.cfg.relay[x].flags &= ~(SNGSS7_CONFIGURED);
} /* if !SNGSS7_CONFIGURED */
x++;
} /* while (x < (MAX_RELAY_CHANNELS)) */
@ -1682,6 +1831,7 @@ static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_ss7_unload)
sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY_STARTED);
}
if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_SM_STARTED)) {
sng_isup_free_sm();
sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_SM_STARTED);

View File

@ -64,12 +64,10 @@
(switchtype == LSI_SW_ANS92) || \
(switchtype == LSI_SW_ANS95)
typedef struct ftdm2trillium
{
typedef struct ftdm2trillium {
uint8_t ftdm_val;
uint8_t trillium_val;
}ftdm2trillium_t;
} ftdm2trillium_t;
typedef enum {
SNGSS7_CON_IND_EVENT = 0,
@ -609,22 +607,20 @@ typedef enum {
"TX CKT BLK DN", \
"TX CKT UNBLK", \
"TX CKT UNBLK DN", \
"RX GRP MN BLK", \
"RX GRP MN BLK DN", \
"RX GRP MN UNBLK", \
"RX GRP MN UNBLK DN", \
"TX GRP MN BLK", \
"TX GRP MN BLK DN", \
"TX GRP MN UNBLK", \
"TX GRP MN UNBLK DN", \
"RX GRP HW BLK", \
"RX GRP HW BLK DN", \
"RX GRP HW UNBLK", \
"RX GRP HW UNBLK DN", \
"TX GRP HW BLK", \
"TX GRP HW BLK DN", \
"RX GRP MN BLK", \
"RX GRP MN BLK DN", \
"TX GRP MN BLK", \
"TX GRP MN BLK DN", \
"TX GRP HW UNBLK", \
"TX GRP HW UNBLK DN"
"TX GRP HW UNBLK DN", \
"TX GRP MN UNBLK", \
"TX GRP MN UNBLK DN", \
"RX GRP HW UNBLK", \
"RX GRP HW UNBLK DN"
FTDM_STR2ENUM_P(ftmod_ss7_blk_state2flag, ftmod_ss7_blk_flag2str, sng_ckt_block_flag_t)
/* valid for every cfg array except circuits */
@ -1042,13 +1038,12 @@ if (ftdmchan->state == new_state) { \
#define sngss7_set_options(obj, option) ((obj)->options |= (option))
#ifdef SS7_PRODUCTION
# define SS7_ASSERT \
SS7_INFO_CHAN(ftdmchan,"Production Mode, continuing%s\n", "");
#ifdef SMG_RELAY_DBG
#define SS7_RELAY_DBG(a,...) printf(a"\n", ##__VA_ARGS__)
#define SS7_RELAY_DBG_FUN(a) printf(#a"\n")
#else
# define SS7_ASSERT \
SS7_ERROR_CHAN(ftdmchan, "Debugging Mode, ending%s\n", ""); \
*(int*)0=0;
#define SS7_RELAY_DBG(a, ...)
#define SS7_RELAY_DBG_FUN(a)
#endif
/******************************************************************************/