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
This commit is contained in:
James Zhang 2011-11-30 19:11:33 -05:00
parent 96068d901d
commit fa64d3954d
5 changed files with 67 additions and 33 deletions

View File

@ -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) {

View File

@ -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;
/**********************************************************************/

View File

@ -826,6 +826,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;
/**************************************************************************/
case FTDM_CHANNEL_STATE_HANGUP: /*call is hung up locally */
@ -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 */
@ -902,6 +910,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)) {
/* go to the down state as we have already received RSC-RLC */
@ -925,9 +934,11 @@ 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");
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 */
if (sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_RX)) {
@ -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)){
@ -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;

View File

@ -1053,7 +1053,9 @@ if (ftdmchan->state == new_state) { \
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_BLOCK_TX_DN | \
FLAG_GRP_HW_UNBLK_TX | \
FLAG_CKT_MN_UNBLK_TX )))
#define sngss7_block_status_clear(obj) (obj->blk_flags == 0)
@ -1062,11 +1064,13 @@ 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)))

View File

@ -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):