<p>pespin <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/osmo-sgsn/+/12009">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  osmith: Looks good to me, but someone else must approve
  pespin: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">gprs/gprs_gmm: implement T3314. Timeout to reset MM state READY->STANDBY<br><br>When a MS MM state is READY its exact location is known (PCU).<br>On Gb, T3314 (aka TS 23.060 "READY timer") sets the MM state from<br>READY to STANDBY, where only the RA is known.<br><br>Introduce a second set of timer variables, because state timer<br>can run while another packet state timer is timing out.<br><br>Related: OS#1941<br>Change-Id: I4ce23ebe50d141076c20c9c56990b7103cd25e55<br>---<br>M include/osmocom/sgsn/gprs_sgsn.h<br>M src/gprs/gprs_gmm.c<br>M src/gprs/gprs_sgsn.c<br>M src/gprs/sgsn_vty.c<br>M tests/test_nodes.vty<br>5 files changed, 98 insertions(+), 2 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/sgsn/gprs_sgsn.h b/include/osmocom/sgsn/gprs_sgsn.h</span><br><span>index 9753ea2..336155c 100644</span><br><span>--- a/include/osmocom/sgsn/gprs_sgsn.h</span><br><span>+++ b/include/osmocom/sgsn/gprs_sgsn.h</span><br><span>@@ -156,6 +156,10 @@</span><br><span>                struct gprs_llc_llme    *llme;</span><br><span>               uint32_t                tlli;</span><br><span>                uint32_t                tlli_new;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           /* timer for mm state. state=READY: T3314 (aka TS 23.060 "READY timer") */</span><br><span style="color: hsl(120, 100%, 40%);">+          struct osmo_timer_list  state_timer;</span><br><span style="color: hsl(120, 100%, 40%);">+          unsigned int            state_T;        /* Txxxx number but only used for pmm_states */</span><br><span>      } gb;</span><br><span>        struct {</span><br><span>             int                     new_key;</span><br><span>diff --git a/src/gprs/gprs_gmm.c b/src/gprs/gprs_gmm.c</span><br><span>index db8defc..f7aff73 100644</span><br><span>--- a/src/gprs/gprs_gmm.c</span><br><span>+++ b/src/gprs/gprs_gmm.c</span><br><span>@@ -137,6 +137,57 @@</span><br><span>     }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static void mmctx_set_mm_state(struct sgsn_mm_ctx *ctx, enum gprs_pmm_state state);</span><br><span style="color: hsl(120, 100%, 40%);">+static void mmctx_state_timer_cb(void *_mm)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct sgsn_mm_ctx *mm = _mm;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       switch (mm->gb.state_T) {</span><br><span style="color: hsl(120, 100%, 40%);">+  case 3314:</span><br><span style="color: hsl(120, 100%, 40%);">+            switch (mm->pmm_state) {</span><br><span style="color: hsl(120, 100%, 40%);">+           case MM_READY:</span><br><span style="color: hsl(120, 100%, 40%);">+                        LOGMMCTXP(LOGL_INFO, mm, "T3314 expired\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                        mmctx_set_mm_state(mm, MM_STANDBY);</span><br><span style="color: hsl(120, 100%, 40%);">+                   break;</span><br><span style="color: hsl(120, 100%, 40%);">+                default:</span><br><span style="color: hsl(120, 100%, 40%);">+                      LOGMMCTXP(LOGL_ERROR, mm, "T3314 expired in state %s != MM_READY\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                  get_value_string(gprs_pmm_state_names, mm->pmm_state));</span><br><span style="color: hsl(120, 100%, 40%);">+                  break;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              LOGMMCTXP(LOGL_ERROR, mm, "state timer expired in unknown mode %u\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                       mm->gb.state_T);</span><br><span style="color: hsl(120, 100%, 40%);">+           break;</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void mmctx_state_timer_start(struct sgsn_mm_ctx *mm, unsigned int T)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        unsigned long seconds;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (mm->gb.state_T && mm->gb.state_T != T)</span><br><span style="color: hsl(120, 100%, 40%);">+              LOGMMCTXP(LOGL_ERROR, mm, "Attempting to start timer %u but %u is active!\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                         T, mm->gb.state_T);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    mm->gb.state_T = T;</span><br><span style="color: hsl(120, 100%, 40%);">+        mm->gb.state_timer.data = mm;</span><br><span style="color: hsl(120, 100%, 40%);">+      mm->gb.state_timer.cb = &mmctx_state_timer_cb;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       seconds = osmo_tdef_get(sgsn->cfg.T_defs, T, OSMO_TDEF_S, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+     osmo_timer_schedule(&mm->gb.state_timer, seconds, 0);</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%);">+static void mmctx_state_timer_stop(struct sgsn_mm_ctx *mm, unsigned int T)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      if (mm->gb.state_T == T)</span><br><span style="color: hsl(120, 100%, 40%);">+           osmo_timer_del(&mm->gb.state_timer);</span><br><span style="color: hsl(120, 100%, 40%);">+   else</span><br><span style="color: hsl(120, 100%, 40%);">+          LOGMMCTXP(LOGL_ERROR, mm, "Attempting to stop timer %u but %u is active!\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                          T, mm->gb.state_T);</span><br><span style="color: hsl(120, 100%, 40%);">+      mm->gb.state_T = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static void mmctx_set_pmm_state(struct sgsn_mm_ctx *ctx, enum gprs_pmm_state state)</span><br><span> {</span><br><span>      OSMO_ASSERT(ctx->ran_type == MM_CTX_T_UTRAN_Iu);</span><br><span>@@ -173,6 +224,24 @@</span><br><span>             get_value_string(gprs_pmm_state_names, ctx->pmm_state),</span><br><span>                   get_value_string(gprs_pmm_state_names, state));</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ switch (state) {</span><br><span style="color: hsl(120, 100%, 40%);">+      case MM_READY:</span><br><span style="color: hsl(120, 100%, 40%);">+                /* on expiration, T3314 moves mm state back to MM_STANDBY */</span><br><span style="color: hsl(120, 100%, 40%);">+          mmctx_state_timer_start(ctx, 3314);</span><br><span style="color: hsl(120, 100%, 40%);">+           break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case MM_IDLE:</span><br><span style="color: hsl(120, 100%, 40%);">+         if (ctx->pmm_state == MM_READY)</span><br><span style="color: hsl(120, 100%, 40%);">+                    mmctx_state_timer_stop(ctx, 3314);</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case MM_STANDBY:</span><br><span style="color: hsl(120, 100%, 40%);">+              if (ctx->pmm_state == MM_READY)</span><br><span style="color: hsl(120, 100%, 40%);">+                    mmctx_state_timer_stop(ctx, 3314);</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              /* when changing to state != MM_READY */</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  ctx->pmm_state = state;</span><br><span> }</span><br><span> </span><br><span>@@ -2968,6 +3037,21 @@</span><br><span>         return rc;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* Update the MM context state */</span><br><span style="color: hsl(120, 100%, 40%);">+static void gsm0408_gprs_notify_pdu_gb(struct sgsn_mm_ctx *mmctx)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  switch (mmctx->pmm_state) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case MM_STANDBY:</span><br><span style="color: hsl(120, 100%, 40%);">+              mmctx_set_mm_state(mmctx, MM_READY);</span><br><span style="color: hsl(120, 100%, 40%);">+          break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case MM_READY: /* RE-arm the timer upon receival of Gb PDUs */</span><br><span style="color: hsl(120, 100%, 40%);">+                mmctx_state_timer_start(mmctx, 3314);</span><br><span style="color: hsl(120, 100%, 40%);">+         break;</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</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%);">+</span><br><span> /* Main entry point for incoming 04.08 GPRS messages from Gb */</span><br><span> int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme,</span><br><span>                           bool drop_cipherable)</span><br><span>@@ -2988,6 +3072,9 @@</span><br><span> </span><br><span>         /* MMCTX can be NULL */</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+   if (mmctx)</span><br><span style="color: hsl(120, 100%, 40%);">+            gsm0408_gprs_notify_pdu_gb(mmctx);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>         switch (pdisc) {</span><br><span>     case GSM48_PDISC_MM_GPRS:</span><br><span>            rc = gsm0408_rcv_gmm(mmctx, msg, llme, drop_cipherable);</span><br><span>diff --git a/src/gprs/gprs_sgsn.c b/src/gprs/gprs_sgsn.c</span><br><span>index eb04846..9f02d54 100644</span><br><span>--- a/src/gprs/gprs_sgsn.c</span><br><span>+++ b/src/gprs/gprs_sgsn.c</span><br><span>@@ -341,6 +341,11 @@</span><br><span>                 osmo_timer_del(&mm->timer);</span><br><span>   }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ if (osmo_timer_pending(&mm->gb.state_timer)) {</span><br><span style="color: hsl(120, 100%, 40%);">+         LOGMMCTXP(LOGL_INFO, mm, "Cancelling MM state timer %u\n", mm->gb.state_T);</span><br><span style="color: hsl(120, 100%, 40%);">+              osmo_timer_del(&mm->gb.state_timer);</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  memset(&sig_data, 0, sizeof(sig_data));</span><br><span>  sig_data.mm = mm;</span><br><span>    osmo_signal_dispatch(SS_SGSN, S_SGSN_MM_FREE, &sig_data);</span><br><span>diff --git a/src/gprs/sgsn_vty.c b/src/gprs/sgsn_vty.c</span><br><span>index ae26cbe..6698691 100644</span><br><span>--- a/src/gprs/sgsn_vty.c</span><br><span>+++ b/src/gprs/sgsn_vty.c</span><br><span>@@ -94,7 +94,7 @@</span><br><span> static struct osmo_tdef sgsn_T_defs[] = {</span><br><span>      { .T=3312, .default_val=GSM0408_T3312_SECS, .desc="Periodic RA Update timer (s)" },</span><br><span>        { .T=3313, .default_val=GSM0408_T3313_SECS, .desc="Waiting for paging response timer (s)" },</span><br><span style="color: hsl(0, 100%, 40%);">-  { .T=3314, .default_val=GSM0408_T3314_SECS, .desc="Force to STANDBY on expiry timer (s)" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { .T=3314, .default_val=GSM0408_T3314_SECS, .desc="READY timer. Force to STANDBY on expiry timer (s)" },</span><br><span>   { .T=3316, .default_val=GSM0408_T3316_SECS, .desc="AA-Ready timer (s)" },</span><br><span>  { .T=3322, .default_val=GSM0408_T3322_SECS, .desc="Detach request -> accept timer (s)" },</span><br><span>       { .T=3350, .default_val=GSM0408_T3350_SECS, .desc="Waiting for ATT/RAU/TMSI_COMPL timer (s)" },</span><br><span>diff --git a/tests/test_nodes.vty b/tests/test_nodes.vty</span><br><span>index 630094f..2ef926a 100644</span><br><span>--- a/tests/test_nodes.vty</span><br><span>+++ b/tests/test_nodes.vty</span><br><span>@@ -2,7 +2,7 @@</span><br><span> OsmoSGSN# show timer</span><br><span> T3312 = 600 s       Periodic RA Update timer (s) (default: 600 s)</span><br><span> T3313 = 30 s   Waiting for paging response timer (s) (default: 30 s)</span><br><span style="color: hsl(0, 100%, 40%);">-T3314 = 44 s       Force to STANDBY on expiry timer (s) (default: 44 s)</span><br><span style="color: hsl(120, 100%, 40%);">+T3314 = 44 s      READY timer. Force to STANDBY on expiry timer (s) (default: 44 s)</span><br><span> T3316 = 44 s       AA-Ready timer (s) (default: 44 s)</span><br><span> T3322 = 6 s       Detach request -> accept timer (s) (default: 6 s)</span><br><span> T3350 = 6 s     Waiting for ATT/RAU/TMSI_COMPL timer (s) (default: 6 s)</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-sgsn/+/12009">change 12009</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/c/osmo-sgsn/+/12009"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-sgsn </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I4ce23ebe50d141076c20c9c56990b7103cd25e55 </div>
<div style="display:none"> Gerrit-Change-Number: 12009 </div>
<div style="display:none"> Gerrit-PatchSet: 4 </div>
<div style="display:none"> Gerrit-Owner: laforge <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Assignee: lynxis lazus <lynxis@fe80.eu> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: lynxis lazus <lynxis@fe80.eu> </div>
<div style="display:none"> Gerrit-Reviewer: osmith <osmith@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>