aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPhilipp Maier <pmaier@sysmocom.de>2018-10-10 17:00:49 +0200
committerPhilipp Maier <pmaier@sysmocom.de>2018-10-24 10:27:39 +0200
commit9ca7b31cbf78511208c2060b9a8e38ad3a0f4aae (patch)
treeb4c363d2202a5a2f08429d46bdf0b9e15e3976e5 /src
parentf6400737f9f6f7d326030862fd6cbc7cab25b8f0 (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.c47
-rw-r--r--src/libmsc/msc_vty.c13
-rw-r--r--src/libmsc/osmo_msc.c2
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);