diff options
author | Philipp Maier <pmaier@sysmocom.de> | 2018-10-10 17:00:49 +0200 |
---|---|---|
committer | Philipp Maier <pmaier@sysmocom.de> | 2018-10-24 10:27:39 +0200 |
commit | 9ca7b31cbf78511208c2060b9a8e38ad3a0f4aae (patch) | |
tree | b4c363d2202a5a2f08429d46bdf0b9e15e3976e5 /src | |
parent | f6400737f9f6f7d326030862fd6cbc7cab25b8f0 (diff) |
gsm_04_08_cc: Add global guard timer for MNCC
The external MNCC handler may hang indefinitely in cases where the remote
end of the MNCC ceases to work properly. Add a global guard timer to
make sure the call reaches ACTIVE state.
Change-Id: I7375d1e17cd746aac4eadfe1e587e82cf1630d3d
Related: OS#3599
Diffstat (limited to 'src')
-rw-r--r-- | src/libmsc/gsm_04_08_cc.c | 47 | ||||
-rw-r--r-- | src/libmsc/msc_vty.c | 13 | ||||
-rw-r--r-- | src/libmsc/osmo_msc.c | 2 |
3 files changed, 62 insertions, 0 deletions
diff --git a/src/libmsc/gsm_04_08_cc.c b/src/libmsc/gsm_04_08_cc.c index 19e6cbae8..f9888d77a 100644 --- a/src/libmsc/gsm_04_08_cc.c +++ b/src/libmsc/gsm_04_08_cc.c @@ -73,6 +73,43 @@ static uint32_t new_callref = 0x80000001; +static void gsm48_cc_guard_timeout(void *arg) +{ + struct gsm_trans *trans = arg; + DEBUGP(DCC, "(sub %s) guard timeout expired\n", + vlr_subscr_msisdn_or_name(trans->vsub)); + trans_free(trans); + return; +} + +static void gsm48_stop_guard_timer(struct gsm_trans *trans) +{ + if (osmo_timer_pending(&trans->cc.timer_guard)) { + DEBUGP(DCC, "(sub %s) stopping pending guard timer\n", + vlr_subscr_msisdn_or_name(trans->vsub)); + osmo_timer_del(&trans->cc.timer_guard); + } +} + +static void gsm48_start_guard_timer(struct gsm_trans *trans) +{ + /* NOTE: The purpose of this timer is to prevent the cc state machine + * from hanging in cases where mncc, gsm48 or both become unresponsive + * for some reason. The timer is started initially with the setup from + * the gsm48 side and then re-started with every incoming mncc message. + * Once the mncc state reaches its active state the timer is stopped. + * So if the cc state machine does not show any activity for an + * extended amount of time during call setup or teardown the guard + * timer will time out and hard-clear the connection. */ + if (osmo_timer_pending(&trans->cc.timer_guard)) + gsm48_stop_guard_timer(trans); + DEBUGP(DCC, "(sub %s) starting guard timer with %d seconds\n", + vlr_subscr_msisdn_or_name(trans->vsub), + trans->net->mncc_guard_timeout); + osmo_timer_setup(&trans->cc.timer_guard, gsm48_cc_guard_timeout, trans); + osmo_timer_schedule(&trans->cc.timer_guard, + trans->net->mncc_guard_timeout, 0); +} /* Call Control */ @@ -149,6 +186,10 @@ static void new_cc_state(struct gsm_trans *trans, int state) count_statistics(trans, state); trans->cc.state = state; + + /* Stop the guard timer when a call reaches the active state */ + if (state == GSM_CSTATE_ACTIVE) + gsm48_stop_guard_timer(trans); } static int gsm48_cc_tx_status(struct gsm_trans *trans, void *arg) @@ -259,6 +300,8 @@ void _gsm48_cc_trans_free(struct gsm_trans *trans) } if (trans->cc.state != GSM_CSTATE_NULL) new_cc_state(trans, GSM_CSTATE_NULL); + + gsm48_stop_guard_timer(trans); } static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg); @@ -474,6 +517,8 @@ static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg) struct tlv_parsed tp; struct gsm_mncc setup; + gsm48_start_guard_timer(trans); + memset(&setup, 0, sizeof(struct gsm_mncc)); setup.callref = trans->callref; @@ -1970,6 +2015,8 @@ int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg) log_set_context(LOG_CTX_VLR_SUBSCR, trans->vsub); } + gsm48_start_guard_timer(trans); + if (trans->conn) conn = trans->conn; diff --git a/src/libmsc/msc_vty.c b/src/libmsc/msc_vty.c index fe6ae8883..a16cec894 100644 --- a/src/libmsc/msc_vty.c +++ b/src/libmsc/msc_vty.c @@ -333,6 +333,16 @@ DEFUN(cfg_msc, cfg_msc_cmd, return CMD_SUCCESS; } +DEFUN(cfg_msc_mncc_guard_timeout, + cfg_msc_mncc_guard_timeout_cmd, + "mncc-guard-timeout <0-255>", + "Set global guard timer for mncc interface activity\n" + "guard timer value (sec.)") +{ + gsmnet->mncc_guard_timeout = atoi(argv[0]); + return CMD_SUCCESS; +} + DEFUN(cfg_msc_assign_tmsi, cfg_msc_assign_tmsi_cmd, "assign-tmsi", "Assign TMSI during Location Updating.\n") @@ -421,6 +431,8 @@ DEFUN(cfg_msc_emergency_msisdn, cfg_msc_emergency_msisdn_cmd, static int config_write_msc(struct vty *vty) { vty_out(vty, "msc%s", VTY_NEWLINE); + vty_out(vty, " mncc-guard-timeout %i%s", + gsmnet->mncc_guard_timeout, VTY_NEWLINE); vty_out(vty, " %sassign-tmsi%s", gsmnet->vlr->cfg.assign_tmsi? "" : "no ", VTY_NEWLINE); @@ -1415,6 +1427,7 @@ void msc_vty_init(struct gsm_network *msc_network) install_element(CONFIG_NODE, &cfg_msc_cmd); install_node(&msc_node, config_write_msc); install_element(MSC_NODE, &cfg_msc_assign_tmsi_cmd); + install_element(MSC_NODE, &cfg_msc_mncc_guard_timeout_cmd); install_element(MSC_NODE, &cfg_msc_no_assign_tmsi_cmd); install_element(MSC_NODE, &cfg_msc_auth_tuple_max_reuse_count_cmd); install_element(MSC_NODE, &cfg_msc_auth_tuple_reuse_on_error_cmd); diff --git a/src/libmsc/osmo_msc.c b/src/libmsc/osmo_msc.c index 3965e9b90..c9ecb64ab 100644 --- a/src/libmsc/osmo_msc.c +++ b/src/libmsc/osmo_msc.c @@ -54,6 +54,8 @@ struct gsm_network *gsm_network_init(void *ctx, mncc_recv_cb_t mncc_recv) /* Use 30 min periodic update interval as sane default */ net->t3212 = 5; + net->mncc_guard_timeout = 180; + net->paging_response_timer = MSC_PAGING_RESPONSE_TIMER_DEFAULT; INIT_LLIST_HEAD(&net->trans_list); |