From fa64d3954d0eac9667c63d992fac6b4364e8c912 Mon Sep 17 00:00:00 2001 From: James Zhang Date: Wed, 30 Nov 2011 19:11:33 -0500 Subject: [PATCH 1/3] Sigificant changes to the core state machine :) Visually status of channels will only be DOWN once all resets/blocks are cleared. Therefore if any reset/block is active on a channel, the channel state will be in RESTART not DOWN. Logic Change SUSPENDED -> Originally used as intermediate state. Purpose is to handle a condition from any state and go back to the previous state. Conditions: such as block/ucic. -> Updated logic is that SUSPEND will be smart enough not to go back to just any state. SUSPEND will only go back to UP - if call is still up RESTART - if for any reason singaling is not up due to blocks/resets/etc... DOWN - if signaling is UP - no resets/blocks In this case we avoid infinite loops due to state jumping from STATE->SUSPEND->STATE->SUSPEND HANGUP_COMPLETE -> If call is in use and a RESET comes on a call the RESTART state will first try the HANGUP_COMPLETE state. HANGUP_COMPLETE will Tx RSC and wait for it. Reset Response handle was updated if current state HANGUP/HANGUP_COMPLETE go back to RESTART state. Which will call HANGUP COMPLETE due to channel in usage and HANDLE_COMPLETE will clear RESET condition and go back to DOWN TERMINATING -> This state is used to hangup a call. Sends a signal to FS. -> Usually TERMINATING state stays in TERMINATING until FS comes back. -> I added a condition in case of RESET on the line though TERMINATING will go back to RESTART. This allows us to process RESET commands even though we are in the middle of hanging up. Block Handler If BLO is received on circuit is already blocked, we failed to trasmit BLA. We should always ack the BLO even though it was alrady in blocked state. Fixed & Tested S UP --> place call --> relay down --> hangup --> relay up--> Confirm that call is hungup properly. In this condition, on relay up the circuit is put into RESET. Since circuit is still in use, it will HANGUP first, then RESET then clear pending BLOCK. S UP --> place call -> Tx RSC on call. Used to cause infitie loop Confirm call is cleard properly Re-Tested S UP --> place call -> Rx RSC on call Confirm call is cleard properly S UP --> place call -> Rx BLO -> hangup -> place call Confirm call cannot be placed Tx UBL Confirm call can be placed S UP --> place call -> Rx BLO -> Tx BLO -> hangup -> place call Confirm call cannot be placed Tx UBL Confirm call cannot be placed Rx UBL Confirm call can be placed S UP --> place call -> relay down --> Rx BLO on channel from telco --> relay up Confirm that relay detects the BLO channels even though relay was down Tx AIS -> S Start -> Confirm HW block -> Tx AIS off -> Confirm hw block clear and UP S UP -> Tx AIS -> Confirm HW block -> Tx AIS off -> confirm hw block clear and UP S UP -> relay down -> Tx AIS -> relay up -> Tx AIS off -> confirm all back up -> In this condition BLO will not go out due to PAUSE S UP -> Tx AIS -> relay down -> Tx AIS off -> relay up -> confirm all back up -> In this condition UBL will not go out due to PAUSE --- .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c | 2 + .../ftmod_sangoma_ss7_handle.c | 4 +- .../ftmod_sangoma_ss7_main.c | 75 ++++++++++++------- .../ftmod_sangoma_ss7_main.h | 16 ++-- .../ftmod_sangoma_ss7_support.c | 3 + 5 files changed, 67 insertions(+), 33 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 9eb737a7f3..1b24b9f8da 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 @@ -1632,6 +1632,8 @@ static ftdm_status_t handle_tx_rsc(ftdm_stream_handle_t *stream, int span, int c ftdm_mutex_lock(ftdmchan->mutex); /* throw the reset flag */ + sngss7_set_ckt_flag (sngss7_info, FLAG_LOCAL_REL); + sngss7_clear_ckt_flag (sngss7_info, FLAG_REMOTE_REL); sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX); switch (ftdmchan->state) { 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 e61dc9426e..64c4c9252d 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 @@ -1646,10 +1646,12 @@ ftdm_status_t handle_blo_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ /* check if the circuit is already blocked or not */ if (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) { SS7_WARN("Received BLO on circuit that is already blocked!\n"); + sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX_DN); } /* throw the ckt block flag */ sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); + sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX_DN); /* set the channel to suspended state */ ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); @@ -1981,7 +1983,7 @@ ftdm_status_t handle_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX_RSP); /* go to DOWN */ - /*ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);*/ + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); break; /**********************************************************************/ 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 7350a478ef..1b7af43bc8 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 @@ -453,7 +453,7 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj) /* check each channel on the span to see if it needs to be reconfigured */ check_for_reconfig_flag(ftdmspan); - + /* Poll for events, e.g HW DTMF */ switch (ftdm_span_poll_event(ftdmspan, 0, NULL)) { /**********************************************************************/ @@ -825,6 +825,14 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) /*this state is set when the line is hanging up */ sngss7_send_signal(sngss7_info, FTDM_SIGEVENT_STOP); + + /* If the RESET flag is set, do not say in TERMINATING state. + Go back to RESTART state and wait for RESET Confirmation */ + if (sngss7_tx_reset_status_pending(sngss7_info)) { + SS7_DEBUG_CHAN(ftdmchan,"Reset pending in Terminating state!%s\n", ""); + state_flag = 0; + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + } break; /**************************************************************************/ @@ -880,9 +888,9 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) state_flag = 0; ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); } else { - /* go to RESTART State until RSCa is received */ - state_flag = 0; - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + /* Stay in hangup complete until RSC is received */ + /* Channel is in use if we go to RESTART we will + restart will just come back to HANGUP_COMPLETE */ } } else { /* if the hangup is from a rx RSC, rx GRS, or glare don't sent RLC */ @@ -901,6 +909,7 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) SS7_DEBUG_CHAN(ftdmchan,"Completing remotely requested hangup!%s\n", ""); } else if (sngss7_test_ckt_flag (sngss7_info, FLAG_LOCAL_REL)) { + /* if this hang up is do to a rx RESET we need to sit here till the RSP arrives */ if (sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_TX_RSP)) { @@ -923,10 +932,12 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) /**************************************************************************/ case FTDM_CHANNEL_STATE_DOWN: /*the call is finished and removed */ - - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); - break; + + if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { + if (!ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OPEN)) { + SS7_DEBUG_CHAN(ftdmchan,"Down came from SUSPEND - break %s\n", ""); + break; + } } /* check if there is a reset response that needs to be sent */ @@ -997,7 +1008,10 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) } /* if (!ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) */ } else { state_flag = 0; + SS7_DEBUG_CHAN(ftdmchan,"Down detected blocked flags go to SUSPEND %s\n", " "); ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + break; + } /* if !blocked */ } else { SS7_DEBUG_CHAN(ftdmchan,"Reset flags present (0x%X)\n", sngss7_info->ckt_flags); @@ -1029,6 +1043,7 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OPEN)) { ftdm_channel_t *close_chan = ftdmchan; /* close the channel */ + SS7_DEBUG_CHAN(ftdmchan,"FTDM Channel Close %s\n", ""); ftdm_channel_close (&close_chan); } @@ -1205,6 +1220,14 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) /* clear the PAUSE flag */ sngss7_clear_ckt_flag(sngss7_info, FLAG_INFID_PAUSED); + if (sngss7_test_ckt_flag (sngss7_info, FLAG_LOCAL_REL)) { + SS7_DEBUG_CHAN(ftdmchan, "Channel local release on RESUME, restart Reset procedure%s\n", ""); + /* By setting RESET_TX flag the check below sngss7_tx_reset_status_pending() will + be true, and will restart the RESET TX procedure */ + sngss7_set_ckt_flag (sngss7_info, FLAG_REMOTE_REL); + sngss7_set_ckt_flag (sngss7_info, FLAG_RESET_TX); + } + /* We have transmitted Reset/GRS but have not gotten a * Response. In mean time we got a RESUME. We cannot be sure * that our reset has been trasmitted, thus restart reset procedure. */ @@ -1250,7 +1273,6 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) } /* Wait for RESUME */ - /* FIXME: Check if this is a correct action to wait for RESUME */ goto suspend_goto_last; } /* if (sngss7_test_ckt_flag(sngss7_info, FLAG_INFID_PAUSED)) { */ @@ -1269,8 +1291,6 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) /* throw the done flag */ sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX_DN); - /* check the last state and return to it to allow the call to finish */ - goto suspend_goto_last; } if (sngss7_test_ckt_blk_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX)){ @@ -1283,7 +1303,7 @@ 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); - SS7_DEBUG_CHAN(ftdmchan,"Current flags: ckt=0x%X, blk=0x%X\n", + SS7_DEBUG_CHAN(ftdmchan,"Current flags: ckt=0x%X, blk=0x%X\n", sngss7_info->ckt_flags, sngss7_info->blk_flags); /* not bring the cic up if there is a hardware block */ @@ -1295,8 +1315,6 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * 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; } @@ -1316,7 +1334,6 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * 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)) { @@ -1344,7 +1361,6 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) ft_to_sngss7_ubl(ftdmchan); } - goto suspend_goto_last; } /**********************************************************************/ @@ -1398,8 +1414,6 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) /* throw the done flag */ sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX_DN); - /* check the last state and return to it to allow the call to finish */ - goto suspend_goto_last; } if (sngss7_test_ckt_blk_flag (sngss7_info, FLAG_CKT_MN_UNBLK_TX)) { @@ -1423,8 +1437,6 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) ft_to_sngss7_ubl(ftdmchan); } - /* check the last state and return to it to allow the call to finish */ - goto suspend_goto_last; } /**********************************************************************/ @@ -1442,8 +1454,6 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) /* bring the sig status down */ sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN); - /* check the last state and return to it to allow the call to finish */ - goto suspend_goto_last; } if (sngss7_test_ckt_blk_flag (sngss7_info, FLAG_CKT_LC_UNBLK_RX)) { @@ -1465,8 +1475,6 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) } - /* check the last state and return to it to allow the call to finish */ - goto suspend_goto_last; } /**********************************************************************/ if (sngss7_test_ckt_blk_flag (sngss7_info, FLAG_CKT_UCIC_BLOCK) && @@ -1488,8 +1496,6 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) /* throw the done flag */ sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK_DN); - /* bring the channel down */ - goto suspend_goto_last; } if (sngss7_test_ckt_blk_flag (sngss7_info, FLAG_CKT_UCIC_UNBLK)) { @@ -1521,6 +1527,23 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) SS7_DEBUG_CHAN(ftdmchan,"No block flag processed!%s\n", ""); suspend_goto_last: + if (ftdmchan->last_state == FTDM_CHANNEL_STATE_UP) { + /* proceed to UP */ + } else if (!sngss7_channel_status_clear(sngss7_info)) { + SS7_DEBUG_CHAN(ftdmchan,"Channel opted to stay in RESTART due to blocks!%s\n", ""); + SS7_DEBUG_CHAN(ftdmchan,"Current flags: ckt=0x%X, blk=0x%X, circuit->flag=0x%X\n", + sngss7_info->ckt_flags, sngss7_info->blk_flags, + sngss7_info->circuit->flags ); + + goto suspend_goto_restart; + } else { + SS7_DEBUG_CHAN(ftdmchan,"Channel signaling is up proceed to DOWN! [Last State=%i]\n", ftdmchan->last_state); + SS7_DEBUG_CHAN(ftdmchan,"Current flags: ckt=0x%X, blk=0x%X, circuit->flag=0x%X\n", + sngss7_info->ckt_flags, sngss7_info->blk_flags, + sngss7_info->circuit->flags ); + ftdmchan->last_state = FTDM_CHANNEL_STATE_DOWN; + } + state_flag = 0; ftdm_set_state(ftdmchan, ftdmchan->last_state); break; 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 b25b21f0ef..697da825cb 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 @@ -1049,11 +1049,13 @@ if (ftdmchan->state == new_state) { \ #define sngss7_set_options(obj, option) ((obj)->options |= (option)) #define sngss7_tx_block_status_clear(obj) (!sngss7_test_ckt_blk_flag(obj, (FLAG_CKT_MN_BLOCK_TX | \ - FLAG_CKT_MN_BLOCK_TX_DN | \ - FLAG_GRP_MN_BLOCK_TX | \ - FLAG_GRP_MN_BLOCK_TX_DN | \ - FLAG_GRP_HW_BLOCK_TX | \ - FLAG_GRP_HW_BLOCK_TX_DN ))) + FLAG_CKT_MN_BLOCK_TX_DN | \ + FLAG_GRP_MN_BLOCK_TX | \ + FLAG_GRP_MN_BLOCK_TX_DN | \ + FLAG_GRP_HW_BLOCK_TX | \ + FLAG_GRP_HW_BLOCK_TX_DN | \ + FLAG_GRP_HW_UNBLK_TX | \ + FLAG_CKT_MN_UNBLK_TX ))) #define sngss7_block_status_clear(obj) (obj->blk_flags == 0) @@ -1062,10 +1064,12 @@ if (ftdmchan->state == new_state) { \ FLAG_GRP_RESET_TX | \ FLAG_GRP_RESET_RX ))) -#define sngss7_tx_reset_status_pending(obj) ((sngss7_test_ckt_flag(obj, (FLAG_RESET_TX)) && \ +#define sngss7_tx_reset_sent(obj) ((sngss7_test_ckt_flag(obj, (FLAG_RESET_TX)) && \ sngss7_test_ckt_flag(obj, (FLAG_RESET_SENT))) || \ (sngss7_test_ckt_flag(obj, (FLAG_GRP_RESET_TX)) && \ sngss7_test_ckt_flag(obj, (FLAG_GRP_RESET_SENT)))) + +#define sngss7_tx_reset_status_pending(obj) (sngss7_test_ckt_flag(obj, (FLAG_RESET_TX)) || sngss7_test_ckt_flag(obj, (FLAG_GRP_RESET_TX))) #define sngss7_channel_status_clear(obj) ((sngss7_block_status_clear(obj)) && (sngss7_reset_status_clear(obj))) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c index 47fdd47728..7a68fe318f 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c @@ -2232,6 +2232,9 @@ ftdm_status_t check_for_reconfig_flag(ftdm_span_t *ftdmspan) SS7_STATE_CHANGE(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); } + /* Only locally blocked, thus remove a remote block */ + sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); + break; /**************************************************************************/ case (2): From 997c127a9405af27f041c07a87395d10bcef63c4 Mon Sep 17 00:00:00 2001 From: James Zhang Date: Wed, 30 Nov 2011 20:02:25 -0500 Subject: [PATCH 2/3] Fixed following two secnarios From previous commit, failed to clear the done flag _DN which cause SUSPEND to think that there was a block pending, causing state to remain in RESTART S UP -> relay down -> Tx AIS -> relay up -> Tx AIS off -> confirm all back up -> In this condition BLO will not go out due to PAUSE S UP -> Tx AIS -> relay down -> Tx AIS off -> relay up -> confirm all back up -> In this condition UBL will not go out due to PAUSE --- .../src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c | 4 +++- .../ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c | 7 ++++++- 2 files changed, 9 insertions(+), 2 deletions(-) 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 64c4c9252d..e7cc9db573 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 @@ -122,8 +122,11 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ /* as per Q.764, 2.8.2.3 xiv ... remove the block from this channel */ 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); 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_MN_BLOCK_RX); + sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX_DN); /* KONRAD FIX ME : check in case there is a ckt and grp block */ } @@ -1646,7 +1649,6 @@ ftdm_status_t handle_blo_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ /* check if the circuit is already blocked or not */ if (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) { SS7_WARN("Received BLO on circuit that is already blocked!\n"); - sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX_DN); } /* throw the ckt block flag */ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c index 7a68fe318f..eb1eb12961 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c @@ -2234,12 +2234,14 @@ ftdm_status_t check_for_reconfig_flag(ftdm_span_t *ftdmspan) /* Only locally blocked, thus remove a remote block */ 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 (2): /* remotely blocked */ sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); + sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX_DN); /* set the channel to suspended state */ SS7_STATE_CHANGE(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); @@ -2247,8 +2249,11 @@ ftdm_status_t check_for_reconfig_flag(ftdm_span_t *ftdmspan) /**************************************************************************/ case (3): /* both locally and remotely blocked */ - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_UNBLK_TX); + if (!sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) { + sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_UNBLK_TX); + } sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); + sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX_DN); /* set the channel to suspended state */ SS7_STATE_CHANGE(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); From 7b83dd4c968f9769c58b8ef89a83eb55a8218df3 Mon Sep 17 00:00:00 2001 From: James Zhang Date: Thu, 1 Dec 2011 03:16:59 -0500 Subject: [PATCH 3/3] Fixed the exception condition - trigger reset used to clear ckt_flags, this was wrong. if ctk_flags are blindly cleard a PAUSE might be cleared. changed the code to clear only TX RESET and try to reset again. Release Collision If we get out of sync with other side we must reset the circuit. This condition occoured at 1+3 test box Local Management Block Its possible for stack to send us a BLO indicating to us that we are local blocked. This case never worked and we would get stuck there forever. If we never manaully sent a LOCAL block, the BLO from the stack will be acked and then unblocked. This condition occoured at 1+3 test box --- libs/freetdm/src/ftdm_state.c | 1 + .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c | 2 +- .../ftmod_sangoma_ss7_handle.c | 19 +++---- .../ftmod_sangoma_ss7_main.c | 24 ++++++--- .../ftmod_sangoma_ss7_main.h | 11 ++++- .../ftmod_sangoma_ss7_support.c | 49 +++++++++++++++++++ libs/freetdm/src/include/private/ftdm_core.h | 1 + 7 files changed, 89 insertions(+), 18 deletions(-) diff --git a/libs/freetdm/src/ftdm_state.c b/libs/freetdm/src/ftdm_state.c index d3f99f6074..6572ab75a4 100644 --- a/libs/freetdm/src/ftdm_state.c +++ b/libs/freetdm/src/ftdm_state.c @@ -87,6 +87,7 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_complete_state(const char *file, const c ftdm_assert(!fchan->history[hindex].end_time, "End time should be zero!\n"); fchan->history[hindex].end_time = ftdm_current_time_in_ms(); + fchan->last_state_change_time = ftdm_current_time_in_ms(); fchan->state_status = FTDM_STATE_STATUS_COMPLETED; 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 1b24b9f8da..2c8f5172b9 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 @@ -1634,7 +1634,7 @@ static ftdm_status_t handle_tx_rsc(ftdm_stream_handle_t *stream, int span, int c /* throw the reset flag */ sngss7_set_ckt_flag (sngss7_info, FLAG_LOCAL_REL); sngss7_clear_ckt_flag (sngss7_info, FLAG_REMOTE_REL); - sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX); + sngss7_tx_reset_restart(sngss7_info); switch (ftdmchan->state) { /**************************************************************************/ 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 e7cc9db573..295d127064 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 @@ -327,9 +327,8 @@ handle_glare: /* throw the TX reset flag */ if (!sngss7_tx_reset_status_pending(sngss7_info)) { - sngss7_info->ckt_flags=0; + sngss7_tx_reset_restart(sngss7_info); sngss7_set_ckt_flag (sngss7_info, FLAG_REMOTE_REL); - sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX); /* go to RESTART */ ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); @@ -401,9 +400,8 @@ ftdm_status_t handle_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circ /* throw the TX reset flag */ if (!sngss7_tx_reset_status_pending(sngss7_info)) { - sngss7_info->ckt_flags=0; + sngss7_tx_reset_restart(sngss7_info); sngss7_set_ckt_flag (sngss7_info, FLAG_REMOTE_REL); - sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX); /* go to RESTART */ ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); @@ -668,9 +666,8 @@ ftdm_status_t handle_con_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circ /* throw the TX reset flag */ if (!sngss7_tx_reset_status_pending(sngss7_info)) { - sngss7_info->ckt_flags=0; + sngss7_tx_reset_restart(sngss7_info); sngss7_set_ckt_flag (sngss7_info, FLAG_REMOTE_REL); - sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX); /* go to RESTART */ ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); @@ -772,6 +769,10 @@ ftdm_status_t handle_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ /* send out the release complete */ ft_to_sngss7_rlc (ftdmchan); + } else { + SS7_DEBUG_CHAN(ftdmchan, "Collision of REL messages - resetting state.\n", " "); + ft_to_sngss7_rlc (ftdmchan); + goto rel_ind_reset; } break; /**************************************************************************/ @@ -794,11 +795,11 @@ ftdm_status_t handle_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ /**************************************************************************/ default: +rel_ind_reset: /* throw the TX reset flag */ if (!sngss7_tx_reset_status_pending(sngss7_info)) { - sngss7_info->ckt_flags=0; - sngss7_set_ckt_flag (sngss7_info, FLAG_REMOTE_REL); - sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX); + sngss7_set_ckt_flag (sngss7_info, FLAG_REMOTE_REL); + sngss7_tx_reset_restart(sngss7_info); /* go to RESTART */ ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); 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 1b7af43bc8..4c6992e61f 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 @@ -1358,6 +1358,8 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) } if (sngss7_tx_block_status_clear(sngss7_info) && !skip_unblock) { + sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX_DN); + sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX); ft_to_sngss7_ubl(ftdmchan); } @@ -1434,6 +1436,8 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) if (sngss7_tx_block_status_clear(sngss7_info)) { /* send a ubl */ + sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX_DN); + sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX); ft_to_sngss7_ubl(ftdmchan); } @@ -1446,13 +1450,19 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_LC_BLOCK_RX flag %s\n", ""); /* send a BLA */ - /*ft_to_sngss7_bla(ftdmchan);*/ + ft_to_sngss7_bla(ftdmchan); /* throw the done flag */ sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX_DN); - - /* bring the sig status down */ - sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN); + + if (sngss7_tx_block_status_clear(sngss7_info)) { + sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX_DN); + sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX); + ft_to_sngss7_ubl(ftdmchan); + } else { + /* bring the sig status down */ + sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN); + } } @@ -1468,7 +1478,7 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_UNBLK_RX); /* send a uba */ - /*ft_to_sngss7_uba(ftdmchan);*/ + ft_to_sngss7_uba(ftdmchan); if (sngss7_channel_status_clear(sngss7_info)) { sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP); @@ -1530,14 +1540,14 @@ suspend_goto_last: if (ftdmchan->last_state == FTDM_CHANNEL_STATE_UP) { /* proceed to UP */ } else if (!sngss7_channel_status_clear(sngss7_info)) { - SS7_DEBUG_CHAN(ftdmchan,"Channel opted to stay in RESTART due to blocks!%s\n", ""); + SS7_DEBUG_CHAN(ftdmchan,"Channel opted to stay in RESTART due to reset/blocks!%s\n", ""); SS7_DEBUG_CHAN(ftdmchan,"Current flags: ckt=0x%X, blk=0x%X, circuit->flag=0x%X\n", sngss7_info->ckt_flags, sngss7_info->blk_flags, sngss7_info->circuit->flags ); goto suspend_goto_restart; } else { - SS7_DEBUG_CHAN(ftdmchan,"Channel signaling is up proceed to DOWN! [Last State=%i]\n", ftdmchan->last_state); + SS7_DEBUG_CHAN(ftdmchan,"Channel signaling is up proceed to DOWN! [Last State=%s]\n", ftdm_channel_state2str(ftdmchan->last_state)); SS7_DEBUG_CHAN(ftdmchan,"Current flags: ckt=0x%X, blk=0x%X, circuit->flag=0x%X\n", sngss7_info->ckt_flags, sngss7_info->blk_flags, sngss7_info->circuit->flags ); 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 697da825cb..631dadf007 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 @@ -1071,7 +1071,16 @@ if (ftdmchan->state == new_state) { \ #define sngss7_tx_reset_status_pending(obj) (sngss7_test_ckt_flag(obj, (FLAG_RESET_TX)) || sngss7_test_ckt_flag(obj, (FLAG_GRP_RESET_TX))) -#define sngss7_channel_status_clear(obj) ((sngss7_block_status_clear(obj)) && (sngss7_reset_status_clear(obj))) +#define sngss7_channel_status_clear(obj) ((sngss7_block_status_clear(obj)) && \ + (sngss7_reset_status_clear(obj)) && \ + (!sngss7_test_ckt_flag((obj),FLAG_INFID_PAUSED))) + +#define sngss7_tx_reset_restart(obj) do { clear_tx_grs_flags((obj)); \ + clear_tx_grs_data((obj)); \ + clear_tx_rsc_flags((obj)); \ + sngss7_set_ckt_flag((obj), (FLAG_RESET_TX)); \ + } while (0); + #ifdef SMG_RELAY_DBG diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c index eb1eb12961..7696974807 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c @@ -2098,6 +2098,55 @@ void sngss7_set_sig_status(sngss7_chan_data_t *sngss7_info, ftdm_signaling_statu return; } +#if 0 +ftdm_status_t check_for_invalid_states(ftdm_channel_t *ftmchan) +{ + sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; + + if (!sngss7_info) { + SS7_WARN_CHAN(ftdmchan, "Found ftdmchan with no sig module data!%s\n", " "); + return FTDM_FAIL; + } + + if (sngss7_test_flag(sngss7_intf, SNGSS7_PAUSED)) { + return FTDM_SUCCESS; + } + + switch (ftdmchan->state) { + case UP: + case DOWN: + return FTDM_SUCCESS; + + default: + if ((ftdm_current_time_in_ms() - ftdmchan->last_state_change_time) > 30000) { + SS7_WARN_CHAN(ftdmchan, "Circuite in state=%s too long - resetting!%s\n", + ftdm_channel_state2str(ftdmchan->state)); + + ftdm_channel_lock(ftdmchan); + + if (sngss7_channel_status_clear(sngss7_info)) { + sngss7_tx_reset_restart(sngss7_info); + + if (ftdmchan->state == FTDM_CHANNEL_STATE_RESTART) { + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + } else { + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + } + } else { + + } + + + + ftdm_channel_unlock(ftdmchan); + } + } + + return FTDM_SUCCESS; +} +#endif + + /******************************************************************************/ ftdm_status_t check_for_reconfig_flag(ftdm_span_t *ftdmspan) { diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 65ffad677c..f27be789e2 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -469,6 +469,7 @@ struct ftdm_channel { int32_t txdrops; int32_t rxdrops; ftdm_usrmsg_t *usrmsg; + ftdm_time_t last_state_change_time; }; struct ftdm_span {