<p>Vadim Yanitskiy <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/11992">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  Harald Welte: Looks good to me, approved
  Vadim Yanitskiy: Looks good to me, but someone else must approve

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">libmsc/gsm_09_11.c: implement guard timer for NCSS sessions<br><br>It may happen that either the MS or an EUSE would become<br>unresponsive during a call independent SS session, e.g.<br>due to a bug, or a dropped message. In such cases, the<br>corresponding transaction would remain unfreed forever.<br><br>This change introduces a guard timer, that prevents keeping<br>'stalled' NCSS sessions forever. As soon as it expires, both<br>sides (i.e. MS and EUSE) are getting notified, and the<br>transaction is being released.<br><br>By default, the timer expires after 30 seconds. As soon as<br>either the MS, or an EUSE initiates any activity,<br>the watchdog timer is rescheduled.<br><br>The timeout value can be configured from the VTY:<br><br>  msc<br>   ...<br>   ! Use 0 to disable this timer<br>   ncss guard-timeout 30<br><br>Please note that changing the timeout value at run-time<br>doesn't affect the existing NCSS sessions, excepting the<br>case when the timer is disabled at run-time.<br><br>This change makes TC_lu_and_ss_session_timeout pass.<br><br>Change-Id: Icf4d87c45e90324764073e8230e0fb9cb96dd9cb<br>Related Change-Id: (TTCN) I3e1791773d56617172ae27a46889a1ae4d400e2f<br>Related: OS#3655<br>---<br>M include/osmocom/msc/gsm_data.h<br>M include/osmocom/msc/transaction.h<br>M src/libmsc/gsm_09_11.c<br>M src/libmsc/msc_vty.c<br>M src/libmsc/osmo_msc.c<br>M tests/test_nodes.vty<br>6 files changed, 90 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/msc/gsm_data.h b/include/osmocom/msc/gsm_data.h</span><br><span>index dab082d..7d3a1e7 100644</span><br><span>--- a/include/osmocom/msc/gsm_data.h</span><br><span>+++ b/include/osmocom/msc/gsm_data.h</span><br><span>@@ -192,6 +192,8 @@</span><br><span> </span><br><span>        /* Global MNCC guard timer value */</span><br><span>  int mncc_guard_timeout;</span><br><span style="color: hsl(120, 100%, 40%);">+       /* Global guard timer value for NCSS sessions */</span><br><span style="color: hsl(120, 100%, 40%);">+      int ncss_guard_timeout;</span><br><span> </span><br><span>  struct {</span><br><span>             struct mgcp_client_conf conf;</span><br><span>diff --git a/include/osmocom/msc/transaction.h b/include/osmocom/msc/transaction.h</span><br><span>index 39b09ae..830328b 100644</span><br><span>--- a/include/osmocom/msc/transaction.h</span><br><span>+++ b/include/osmocom/msc/transaction.h</span><br><span>@@ -87,6 +87,8 @@</span><br><span>                    * a subscriber after successful Paging Response</span><br><span>                      */</span><br><span>                  struct msgb *msg;</span><br><span style="color: hsl(120, 100%, 40%);">+                     /* Inactivity timer, triggers transaction release */</span><br><span style="color: hsl(120, 100%, 40%);">+                  struct osmo_timer_list timer_guard;</span><br><span>          } ss;</span><br><span>        };</span><br><span> </span><br><span>diff --git a/src/libmsc/gsm_09_11.c b/src/libmsc/gsm_09_11.c</span><br><span>index d2ad0b7..c133656 100644</span><br><span>--- a/src/libmsc/gsm_09_11.c</span><br><span>+++ b/src/libmsc/gsm_09_11.c</span><br><span>@@ -51,6 +51,39 @@</span><br><span> /* FIXME: choose a proper range */</span><br><span> static uint32_t new_callref = 0x20000001;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static void ncss_session_timeout_handler(void *_trans)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    struct gsm_trans *trans = (struct gsm_trans *) _trans;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct osmo_gsup_message gsup_msg = { 0 };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* The timeout might be disabled from the VTY */</span><br><span style="color: hsl(120, 100%, 40%);">+      if (trans->net->ncss_guard_timeout == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     LOGP(DMM, LOGL_NOTICE, "SS/USSD session timeout, releasing "</span><br><span style="color: hsl(120, 100%, 40%);">+                "transaction (trans=%p, callref=%x)\n", trans, trans->callref);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Indicate connection release to subscriber (if active) */</span><br><span style="color: hsl(120, 100%, 40%);">+   if (trans->conn != NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+         /* This pair of cause location and value is used by commercial networks */</span><br><span style="color: hsl(120, 100%, 40%);">+            msc_send_ussd_release_complete_cause(trans->conn, trans->transaction_id,</span><br><span style="color: hsl(120, 100%, 40%);">+                        GSM48_CAUSE_LOC_PUN_S_LU, GSM48_CC_CAUSE_NORMAL_UNSPEC);</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Terminate GSUP session with EUSE */</span><br><span style="color: hsl(120, 100%, 40%);">+        gsup_msg.message_type = OSMO_GSUP_MSGT_PROC_SS_ERROR;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_STRLCPY_ARRAY(gsup_msg.imsi, trans->vsub->imsi);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ gsup_msg.session_state = OSMO_GSUP_SESSION_STATE_END;</span><br><span style="color: hsl(120, 100%, 40%);">+ gsup_msg.session_id = trans->callref;</span><br><span style="color: hsl(120, 100%, 40%);">+      gsup_msg.cause = GMM_CAUSE_NET_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        osmo_gsup_client_enc_send(trans->net->vlr->gsup_client, &gsup_msg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Finally, release this transaction */</span><br><span style="color: hsl(120, 100%, 40%);">+       trans_free(trans);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* Entry point for call independent MO SS messages */</span><br><span> int gsm0911_rcv_nc_ss(struct ran_conn *conn, struct msgb *msg)</span><br><span> {</span><br><span>@@ -108,6 +141,10 @@</span><br><span>                       return -ENOMEM;</span><br><span>              }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+         /* Init inactivity timer */</span><br><span style="color: hsl(120, 100%, 40%);">+           osmo_timer_setup(&trans->ss.timer_guard,</span><br><span style="color: hsl(120, 100%, 40%);">+                       ncss_session_timeout_handler, trans);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>              /* Count active NC SS/USSD sessions */</span><br><span>               osmo_counter_inc(conn->network->active_nc_ss);</span><br><span> </span><br><span>@@ -116,6 +153,12 @@</span><br><span>              cm_service_request_concludes(conn, msg);</span><br><span>     }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* (Re)schedule the inactivity timer */</span><br><span style="color: hsl(120, 100%, 40%);">+       if (conn->network->ncss_guard_timeout > 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+         osmo_timer_schedule(&trans->ss.timer_guard,</span><br><span style="color: hsl(120, 100%, 40%);">+                    conn->network->ncss_guard_timeout, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  /* Attempt to extract Facility IE */</span><br><span>         rc = gsm0480_extract_ie_by_tag(gh, msgb_l3len(msg),</span><br><span>          &facility_ie, &facility_ie_len, GSM0480_IE_FACILITY);</span><br><span>@@ -233,6 +276,12 @@</span><br><span>                 transt->conn = ran_conn_get(conn, RAN_CONN_USE_TRANS_NC_SS);</span><br><span>              transt->paging_request = NULL;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+         /* (Re)schedule the inactivity timer */</span><br><span style="color: hsl(120, 100%, 40%);">+               if (conn->network->ncss_guard_timeout > 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 osmo_timer_schedule(&transt->ss.timer_guard,</span><br><span style="color: hsl(120, 100%, 40%);">+                           conn->network->ncss_guard_timeout, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+          }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>          /* Send stored message */</span><br><span>            ss_msg = transt->ss.msg;</span><br><span>          gh = (struct gsm48_hdr *) msgb_push(ss_msg, sizeof(*gh));</span><br><span>@@ -317,6 +366,10 @@</span><br><span>     }</span><br><span>    trans->transaction_id = tid;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+   /* Init inactivity timer */</span><br><span style="color: hsl(120, 100%, 40%);">+   osmo_timer_setup(&trans->ss.timer_guard,</span><br><span style="color: hsl(120, 100%, 40%);">+               ncss_session_timeout_handler, trans);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>      /* Attempt to find connection */</span><br><span>     conn = connection_for_subscr(vsub);</span><br><span>  if (conn) {</span><br><span>@@ -371,6 +424,9 @@</span><br><span>    if (trans->ss.msg != NULL)</span><br><span>                msgb_free(trans->ss.msg);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+      /* Stop inactivity timer */</span><br><span style="color: hsl(120, 100%, 40%);">+   osmo_timer_del(&trans->ss.timer_guard);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>     /* One session less */</span><br><span>       osmo_counter_dec(trans->net->active_nc_ss);</span><br><span> }</span><br><span>@@ -420,6 +476,12 @@</span><br><span>                        return 0;</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* (Re)schedule the inactivity timer */</span><br><span style="color: hsl(120, 100%, 40%);">+       if (net->ncss_guard_timeout > 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              osmo_timer_schedule(&trans->ss.timer_guard,</span><br><span style="color: hsl(120, 100%, 40%);">+                    net->ncss_guard_timeout, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  /* Allocate and prepare a new MT message */</span><br><span>  ss_msg = gsm48_msgb_alloc_name("GSM 04.08 SS/USSD");</span><br><span>       gh = (struct gsm48_hdr *) msgb_push(ss_msg, sizeof(*gh));</span><br><span>diff --git a/src/libmsc/msc_vty.c b/src/libmsc/msc_vty.c</span><br><span>index 078b83a..5aa533b 100644</span><br><span>--- a/src/libmsc/msc_vty.c</span><br><span>+++ b/src/libmsc/msc_vty.c</span><br><span>@@ -375,6 +375,18 @@</span><br><span>                 "mncc-guard-timeout <0-255>",</span><br><span>                MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define NCSS_STR "Configure call independent Supplementary Services\n"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+DEFUN(cfg_msc_ncss_guard_timeout,</span><br><span style="color: hsl(120, 100%, 40%);">+      cfg_msc_ncss_guard_timeout_cmd,</span><br><span style="color: hsl(120, 100%, 40%);">+      "ncss guard-timeout <0-255>",</span><br><span style="color: hsl(120, 100%, 40%);">+      NCSS_STR "Set guard timer for session activity\n"</span><br><span style="color: hsl(120, 100%, 40%);">+      "guard timer value (sec.), or 0 to disable\n")</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   gsmnet->ncss_guard_timeout = atoi(argv[0]);</span><br><span style="color: hsl(120, 100%, 40%);">+        return CMD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> DEFUN(cfg_msc_assign_tmsi, cfg_msc_assign_tmsi_cmd,</span><br><span>       "assign-tmsi",</span><br><span>       "Assign TMSI during Location Updating.\n")</span><br><span>@@ -496,6 +508,8 @@</span><br><span>                vty_out(vty, " mncc external %s%s", gsmnet->mncc_sock_path, VTY_NEWLINE);</span><br><span>       vty_out(vty, " mncc guard-timeout %i%s",</span><br><span>           gsmnet->mncc_guard_timeout, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+  vty_out(vty, " ncss guard-timeout %i%s",</span><br><span style="color: hsl(120, 100%, 40%);">+            gsmnet->ncss_guard_timeout, VTY_NEWLINE);</span><br><span>         vty_out(vty, " %sassign-tmsi%s",</span><br><span>           gsmnet->vlr->cfg.assign_tmsi? "" : "no ", VTY_NEWLINE);</span><br><span> </span><br><span>@@ -1588,6 +1602,7 @@</span><br><span>        install_element(MSC_NODE, &cfg_msc_mncc_external_cmd);</span><br><span>   install_element(MSC_NODE, &cfg_msc_mncc_guard_timeout_cmd);</span><br><span>      install_element(MSC_NODE, &cfg_msc_deprecated_mncc_guard_timeout_cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+    install_element(MSC_NODE, &cfg_msc_ncss_guard_timeout_cmd);</span><br><span>      install_element(MSC_NODE, &cfg_msc_no_assign_tmsi_cmd);</span><br><span>  install_element(MSC_NODE, &cfg_msc_auth_tuple_max_reuse_count_cmd);</span><br><span>      install_element(MSC_NODE, &cfg_msc_auth_tuple_reuse_on_error_cmd);</span><br><span>diff --git a/src/libmsc/osmo_msc.c b/src/libmsc/osmo_msc.c</span><br><span>index 9828da1..5c6f0aa 100644</span><br><span>--- a/src/libmsc/osmo_msc.c</span><br><span>+++ b/src/libmsc/osmo_msc.c</span><br><span>@@ -54,6 +54,7 @@</span><br><span>  net->t3212 = 5;</span><br><span> </span><br><span>       net->mncc_guard_timeout = 180;</span><br><span style="color: hsl(120, 100%, 40%);">+     net->ncss_guard_timeout = 30;</span><br><span> </span><br><span>         net->paging_response_timer = MSC_PAGING_RESPONSE_TIMER_DEFAULT;</span><br><span> </span><br><span>diff --git a/tests/test_nodes.vty b/tests/test_nodes.vty</span><br><span>index f2312d1..fb9e5f0 100644</span><br><span>--- a/tests/test_nodes.vty</span><br><span>+++ b/tests/test_nodes.vty</span><br><span>@@ -34,6 +34,7 @@</span><br><span>   mncc internal</span><br><span>   mncc external MNCC_SOCKET_PATH</span><br><span>   mncc guard-timeout <0-255></span><br><span style="color: hsl(120, 100%, 40%);">+  ncss guard-timeout <0-255></span><br><span>   no assign-tmsi</span><br><span>   auth-tuple-max-reuse-count <-1-2147483647></span><br><span>   auth-tuple-reuse-on-error (0|1)</span><br><span>@@ -50,6 +51,12 @@</span><br><span>   mgw remote-port <0-65535></span><br><span> ...</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+OsmoMSC(config-msc)# ncss?</span><br><span style="color: hsl(120, 100%, 40%);">+  ncss  Configure call independent Supplementary Services</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+OsmoMSC(config-msc)# ncss ?</span><br><span style="color: hsl(120, 100%, 40%);">+  guard-timeout  Set guard timer for session activity</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> OsmoMSC(config-msc)# mncc?</span><br><span>   mncc  Configure Mobile Network Call Control</span><br><span> </span><br><span>@@ -123,6 +130,7 @@</span><br><span>  periodic location update 30</span><br><span> msc</span><br><span>  mncc guard-timeout 180</span><br><span style="color: hsl(120, 100%, 40%);">+ ncss guard-timeout 30</span><br><span>  assign-tmsi</span><br><span>  cs7-instance-a 0</span><br><span> ...</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/11992">change 11992</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/11992"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-msc </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: Icf4d87c45e90324764073e8230e0fb9cb96dd9cb </div>
<div style="display:none"> Gerrit-Change-Number: 11992 </div>
<div style="display:none"> Gerrit-PatchSet: 12 </div>
<div style="display:none"> Gerrit-Owner: Vadim Yanitskiy <axilirator@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: Harald Welte <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder (1000002) </div>
<div style="display:none"> Gerrit-Reviewer: Max <msuraev@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Neels Hofmeyr <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Vadim Yanitskiy <axilirator@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: daniel <dwillmann@sysmocom.de> </div>
<div style="display:none"> Gerrit-CC: Stefan Sperling <stsp@stsp.name> </div>