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

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Implement GMM State using osmocom FSM<br><br>State machine inspired in the one from TS 24.008 4.1.3.3.1. Some state<br>transitions are inroduced in the code but are still commented out since<br>we lack some functionalitites or improvements in the code to handle<br>different scenarios.<br><br>Most of the logic is still outside of the FSM, but at least now the<br>states are handled in a sane way triggered by events.<br><br>Change-Id: Idecb43c10d66224d4f9ba9320825040ce6cf9a07<br>---<br>M include/osmocom/sgsn/Makefile.am<br>A include/osmocom/sgsn/gprs_gmm_fsm.h<br>M include/osmocom/sgsn/gprs_sgsn.h<br>M src/sgsn/Makefile.am<br>M src/sgsn/gprs_gmm.c<br>A src/sgsn/gprs_gmm_fsm.c<br>M src/sgsn/gprs_sgsn.c<br>M src/sgsn/sgsn_libgtp.c<br>M src/sgsn/sgsn_vty.c<br>M tests/sgsn/Makefile.am<br>M tests/sgsn/sgsn_test.c<br>11 files changed, 261 insertions(+), 53 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/sgsn/Makefile.am b/include/osmocom/sgsn/Makefile.am</span><br><span>index 0ab00fe..9ddc2bc 100644</span><br><span>--- a/include/osmocom/sgsn/Makefile.am</span><br><span>+++ b/include/osmocom/sgsn/Makefile.am</span><br><span>@@ -6,6 +6,7 @@</span><br><span>   gprs_gb.h \</span><br><span>  gprs_gb_parse.h \</span><br><span>    gprs_gmm.h \</span><br><span style="color: hsl(120, 100%, 40%);">+  gprs_gmm_fsm.h \</span><br><span>     gprs_gmm_attach.h \</span><br><span>  gprs_mm_state_gb_fsm.h \</span><br><span>     gprs_mm_state_iu_fsm.h \</span><br><span>diff --git a/include/osmocom/sgsn/gprs_gmm_fsm.h b/include/osmocom/sgsn/gprs_gmm_fsm.h</span><br><span>new file mode 100644</span><br><span>index 0000000..fd5b4bf</span><br><span>--- /dev/null</span><br><span>+++ b/include/osmocom/sgsn/gprs_gmm_fsm.h</span><br><span>@@ -0,0 +1,34 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/fsm.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* 3GPP TS 24.008 § 4.1.3.3 GMM mobility management states on the network side */</span><br><span style="color: hsl(120, 100%, 40%);">+enum gmm_fsm_states {</span><br><span style="color: hsl(120, 100%, 40%);">+    ST_GMM_DEREGISTERED,            /* 4.1.3.3.1.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+     ST_GMM_COMMON_PROC_INIT,        /* 4.1.3.3.1.2 */</span><br><span style="color: hsl(120, 100%, 40%);">+     ST_GMM_REGISTERED_NORMAL,       /* 4.1.3.3.2.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+     ST_GMM_REGISTERED_SUSPENDED,    /* 4.1.3.3.2.2 */</span><br><span style="color: hsl(120, 100%, 40%);">+     ST_GMM_DEREGISTERED_INIT,       /* 4.1.3.3.1.4 */</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%);">+enum gmm_fsm_events {</span><br><span style="color: hsl(120, 100%, 40%);">+        E_GMM_COMMON_PROC_INIT_REQ,</span><br><span style="color: hsl(120, 100%, 40%);">+   /* E_GMM_COMMON_PROC_FAILED, NOT USED */</span><br><span style="color: hsl(120, 100%, 40%);">+      /* E_GMM_LOWER_LAYER_FAILED, NOT USED */</span><br><span style="color: hsl(120, 100%, 40%);">+      E_GMM_COMMON_PROC_SUCCESS,</span><br><span style="color: hsl(120, 100%, 40%);">+    E_GMM_ATTACH_SUCCESS,</span><br><span style="color: hsl(120, 100%, 40%);">+ /* E_GMM_NET_INIT_DETACH_REQ, NOT USED */</span><br><span style="color: hsl(120, 100%, 40%);">+     /* E_GMM_MS_INIT_DETACH_REQ, NOT USED */</span><br><span style="color: hsl(120, 100%, 40%);">+      /* E_GMM_DETACH_ACCEPTED, */</span><br><span style="color: hsl(120, 100%, 40%);">+  E_GMM_SUSPEND,</span><br><span style="color: hsl(120, 100%, 40%);">+        E_GMM_RESUME,</span><br><span style="color: hsl(120, 100%, 40%);">+ E_GMM_CLEANUP,</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 inline bool gmm_fsm_is_registered(struct osmo_fsm_inst *fi)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   return fi->state == ST_GMM_REGISTERED_NORMAL ||</span><br><span style="color: hsl(120, 100%, 40%);">+           fi->state == ST_GMM_REGISTERED_SUSPENDED;</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%);">+extern struct osmo_fsm gmm_fsm;</span><br><span>diff --git a/include/osmocom/sgsn/gprs_sgsn.h b/include/osmocom/sgsn/gprs_sgsn.h</span><br><span>index 20e0e06..0a52a7d 100644</span><br><span>--- a/include/osmocom/sgsn/gprs_sgsn.h</span><br><span>+++ b/include/osmocom/sgsn/gprs_sgsn.h</span><br><span>@@ -23,15 +23,6 @@</span><br><span> </span><br><span> enum gsm48_gsm_cause;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/* 3GPP TS 24.008 § 4.1.3.3 GMM mobility management states on the network side */</span><br><span style="color: hsl(0, 100%, 40%);">-enum gprs_gmm_state {</span><br><span style="color: hsl(0, 100%, 40%);">-     GMM_DEREGISTERED,               /* 4.1.3.3.1.1 */</span><br><span style="color: hsl(0, 100%, 40%);">-       GMM_COMMON_PROC_INIT,           /* 4.1.3.3.1.2 */</span><br><span style="color: hsl(0, 100%, 40%);">-       GMM_REGISTERED_NORMAL,          /* 4.1.3.3.2.1 */</span><br><span style="color: hsl(0, 100%, 40%);">-       GMM_REGISTERED_SUSPENDED,       /* 4.1.3.3.2.2 */</span><br><span style="color: hsl(0, 100%, 40%);">-       GMM_DEREGISTERED_INIT,          /* 4.1.3.3.1.4 */</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> enum gprs_mm_ctr {</span><br><span>    GMM_CTR_PKTS_SIG_IN,</span><br><span>         GMM_CTR_PKTS_SIG_OUT,</span><br><span>@@ -128,7 +119,7 @@</span><br><span>  enum sgsn_ran_type      ran_type;</span><br><span> </span><br><span>        char                    imsi[GSM23003_IMSI_MAX_DIGITS+1];</span><br><span style="color: hsl(0, 100%, 40%);">-       enum gprs_gmm_state     gmm_state;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct osmo_fsm_inst    *gmm_fsm;</span><br><span>    uint32_t                p_tmsi;</span><br><span>      uint32_t                p_tmsi_old;     /* old P-TMSI before new is confirmed */</span><br><span>     uint32_t                p_tmsi_sig;</span><br><span>diff --git a/src/sgsn/Makefile.am b/src/sgsn/Makefile.am</span><br><span>index a8da943..4402c9c 100644</span><br><span>--- a/src/sgsn/Makefile.am</span><br><span>+++ b/src/sgsn/Makefile.am</span><br><span>@@ -43,6 +43,7 @@</span><br><span>         gprs_gb.c \</span><br><span>  gprs_gmm_attach.c \</span><br><span>  gprs_gmm.c \</span><br><span style="color: hsl(120, 100%, 40%);">+  gprs_gmm_fsm.c \</span><br><span>     gprs_mm_state_gb_fsm.c \</span><br><span>     gprs_mm_state_iu_fsm.c \</span><br><span>     gprs_ranap.c \</span><br><span>diff --git a/src/sgsn/gprs_gmm.c b/src/sgsn/gprs_gmm.c</span><br><span>index 399f7bf..3317a09 100644</span><br><span>--- a/src/sgsn/gprs_gmm.c</span><br><span>+++ b/src/sgsn/gprs_gmm.c</span><br><span>@@ -57,6 +57,7 @@</span><br><span> #include <osmocom/sgsn/gprs_gmm_attach.h></span><br><span> #include <osmocom/sgsn/gprs_mm_state_gb_fsm.h></span><br><span> #include <osmocom/sgsn/gprs_mm_state_iu_fsm.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/sgsn/gprs_gmm_fsm.h></span><br><span> #include <osmocom/sgsn/signal.h></span><br><span> #include <osmocom/sgsn/gprs_sndcp.h></span><br><span> #include <osmocom/sgsn/gprs_ranap.h></span><br><span>@@ -211,7 +212,7 @@</span><br><span>     LOGMMCTXP(LOGL_INFO, ctx, "Cleaning MM context due to %s\n", log_text);</span><br><span> </span><br><span>        /* Mark MM state as deregistered */</span><br><span style="color: hsl(0, 100%, 40%);">-     ctx->gmm_state = GMM_DEREGISTERED;</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fsm_inst_dispatch(ctx->gmm_fsm, E_GMM_CLEANUP, NULL);</span><br><span> </span><br><span>    switch(ctx->ran_type) {</span><br><span>   case MM_CTX_T_UTRAN_Iu:</span><br><span>@@ -967,7 +968,7 @@</span><br><span>                memset(&sig_data, 0, sizeof(sig_data));</span><br><span>          sig_data.mm = mmctx;</span><br><span>                 osmo_signal_dispatch(SS_SGSN, S_SGSN_ATTACH, &sig_data);</span><br><span style="color: hsl(0, 100%, 40%);">-            ctx->gmm_state = GMM_REGISTERED_NORMAL;</span><br><span style="color: hsl(120, 100%, 40%);">+            osmo_fsm_inst_dispatch(mm->gmm_fsm, E_GMM_ATTACH_SUCCESS, NULL);</span><br><span> #endif</span><br><span> </span><br><span>            return gsm48_tx_gmm_att_ack(ctx);</span><br><span>@@ -1009,8 +1010,8 @@</span><br><span> </span><br><span> void gsm0408_gprs_access_granted(struct sgsn_mm_ctx *ctx)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- switch (ctx->gmm_state) {</span><br><span style="color: hsl(0, 100%, 40%);">-    case GMM_COMMON_PROC_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+    switch (ctx->gmm_fsm->state) {</span><br><span style="color: hsl(120, 100%, 40%);">+  case ST_GMM_COMMON_PROC_INIT:</span><br><span>                LOGMMCTXP(LOGL_NOTICE, ctx,</span><br><span>               "Authorized, continuing procedure, IMSI=%s\n",</span><br><span>                     ctx->imsi);</span><br><span>@@ -1030,8 +1031,8 @@</span><br><span>  if (gmm_cause == SGSN_ERROR_CAUSE_NONE)</span><br><span>              gmm_cause = GMM_CAUSE_GPRS_NOTALLOWED;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      switch (ctx->gmm_state) {</span><br><span style="color: hsl(0, 100%, 40%);">-    case GMM_COMMON_PROC_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+    switch (ctx->gmm_fsm->state) {</span><br><span style="color: hsl(120, 100%, 40%);">+  case ST_GMM_COMMON_PROC_INIT:</span><br><span>                LOGMMCTXP(LOGL_NOTICE, ctx,</span><br><span>                    "Not authorized, rejecting ATTACH REQUEST "</span><br><span>                        "with cause '%s' (%d)\n",</span><br><span>@@ -1040,8 +1041,8 @@</span><br><span>                if (ctx->gmm_att_req.fsm->state != ST_INIT)</span><br><span>                    osmo_fsm_inst_dispatch(ctx->gmm_att_req.fsm, E_REJECT, (void *) (long) gmm_cause);</span><br><span>                break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case GMM_REGISTERED_NORMAL:</span><br><span style="color: hsl(0, 100%, 40%);">-     case GMM_REGISTERED_SUSPENDED:</span><br><span style="color: hsl(120, 100%, 40%);">+        case ST_GMM_REGISTERED_NORMAL:</span><br><span style="color: hsl(120, 100%, 40%);">+        case ST_GMM_REGISTERED_SUSPENDED:</span><br><span>            LOGMMCTXP(LOGL_NOTICE, ctx,</span><br><span>                    "Authorization lost, detaching "</span><br><span>                           "with cause '%s' (%d)\n",</span><br><span>@@ -1142,7 +1143,7 @@</span><br><span> {</span><br><span>   uint32_t ptmsi;</span><br><span>      /* Don't change the P-TMSI if a P-TMSI re-assignment is under way */</span><br><span style="color: hsl(0, 100%, 40%);">-        if (ctx->gmm_state != GMM_COMMON_PROC_INIT) {</span><br><span style="color: hsl(120, 100%, 40%);">+      if (ctx->gmm_fsm->state != ST_GMM_COMMON_PROC_INIT) {</span><br><span>          ptmsi = sgsn_alloc_ptmsi();</span><br><span>          if (ptmsi != GSM_RESERVED_TMSI) {</span><br><span>                    ctx->p_tmsi_old = ctx->p_tmsi;</span><br><span>@@ -1150,7 +1151,7 @@</span><br><span>                 } else</span><br><span>                       LOGMMCTXP(LOGL_ERROR, ctx, "P-TMSI allocation failure: using old one.\n");</span><br><span>         }</span><br><span style="color: hsl(0, 100%, 40%);">-       ctx->gmm_state = GMM_COMMON_PROC_INIT;</span><br><span style="color: hsl(120, 100%, 40%);">+     osmo_fsm_inst_dispatch(ctx->gmm_fsm, E_GMM_COMMON_PROC_INIT_REQ, NULL);</span><br><span> }</span><br><span> </span><br><span> /* 3GPP TS 24.008 § 9.4.1 Attach request */</span><br><span>@@ -1360,7 +1361,7 @@</span><br><span>  mmctx->t3350_mode = GMM_T3350_MODE_NONE;</span><br><span>  mmctx->p_tmsi_old = 0;</span><br><span>    mmctx->pending_req = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-      mmctx->gmm_state = GMM_REGISTERED_NORMAL;</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_fsm_inst_dispatch(mmctx->gmm_fsm, E_GMM_ATTACH_SUCCESS, NULL);</span><br><span>       switch(mmctx->ran_type) {</span><br><span>         case MM_CTX_T_UTRAN_Iu:</span><br><span>              osmo_fsm_inst_dispatch(mmctx->iu.mm_state_fsm, E_PMM_PS_ATTACH, NULL);</span><br><span>@@ -1658,11 +1659,10 @@</span><br><span>                          mmctx->p_tmsi, mmctx->p_tmsi_old,</span><br><span>                              mmctx->gb.tlli, mmctx->gb.tlli_new,</span><br><span>                            osmo_rai_name(&mmctx->ra));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                      mmctx->gmm_state = GMM_COMMON_PROC_INIT;</span><br><span style="color: hsl(120, 100%, 40%);">+                   osmo_fsm_inst_dispatch(mmctx->gmm_fsm, E_GMM_COMMON_PROC_INIT_REQ, NULL);</span><br><span>                 }</span><br><span>    } else if (!gprs_ra_id_equals(&mmctx->ra, &old_ra_id) ||</span><br><span style="color: hsl(0, 100%, 40%);">-             mmctx->gmm_state == GMM_DEREGISTERED)</span><br><span style="color: hsl(120, 100%, 40%);">+              mmctx->gmm_fsm->state == ST_GMM_DEREGISTERED)</span><br><span>  {</span><br><span>            /* We cannot use the mmctx */</span><br><span>                LOGMMCTXP(LOGL_INFO, mmctx,</span><br><span>@@ -1715,7 +1715,7 @@</span><br><span>  mmctx_timer_start(mmctx, 3350);</span><br><span> #else</span><br><span>     /* Make sure we are NORMAL (i.e. not SUSPENDED anymore) */</span><br><span style="color: hsl(0, 100%, 40%);">-      mmctx->gmm_state = GMM_REGISTERED_NORMAL;</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_fsm_inst_dispatch(mm->gmm_fsm, E_GMM_ATTACH_SUCCESS, NULL);</span><br><span> </span><br><span>      memset(&sig_data, 0, sizeof(sig_data));</span><br><span>  sig_data.mm = mmctx;</span><br><span>@@ -1768,7 +1768,7 @@</span><br><span>         mmctx->t3350_mode = GMM_T3350_MODE_NONE;</span><br><span>  mmctx->p_tmsi_old = 0;</span><br><span>    mmctx->pending_req = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-      mmctx->gmm_state = GMM_REGISTERED_NORMAL;</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_fsm_inst_dispatch(mmctx->gmm_fsm, E_GMM_COMMON_PROC_SUCCESS, NULL);</span><br><span>  switch(mmctx->ran_type) {</span><br><span>         case MM_CTX_T_UTRAN_Iu:</span><br><span>              osmo_fsm_inst_dispatch(mmctx->iu.mm_state_fsm, E_PMM_RA_UPDATE, NULL);</span><br><span>@@ -1883,7 +1883,7 @@</span><br><span>            goto rejected;</span><br><span>       }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   ctx->gmm_state = GMM_COMMON_PROC_INIT;</span><br><span style="color: hsl(120, 100%, 40%);">+     osmo_fsm_inst_dispatch(ctx->gmm_fsm, E_GMM_COMMON_PROC_INIT_REQ, NULL);</span><br><span> </span><br><span>       ctx->iu.service.type = service_type;</span><br><span> </span><br><span>@@ -2832,15 +2832,14 @@</span><br><span>                return -EINVAL;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (mmctx->gmm_state != GMM_REGISTERED_NORMAL &&</span><br><span style="color: hsl(0, 100%, 40%);">-         mmctx->gmm_state != GMM_REGISTERED_SUSPENDED) {</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!gmm_fsm_is_registered(mmctx->gmm_fsm)) {</span><br><span>             LOGMMCTXP(LOGL_NOTICE, mmctx, "SUSPEND request while state "</span><br><span>                       "!= REGISTERED (TLLI=%08x)\n", tlli);</span><br><span>              return -EINVAL;</span><br><span>      }</span><br><span> </span><br><span>        /* Transition from REGISTERED_NORMAL to REGISTERED_SUSPENDED */</span><br><span style="color: hsl(0, 100%, 40%);">- mmctx->gmm_state = GMM_REGISTERED_SUSPENDED;</span><br><span style="color: hsl(120, 100%, 40%);">+       osmo_fsm_inst_dispatch(mmctx->gmm_fsm, E_GMM_SUSPEND, NULL);</span><br><span>      return 0;</span><br><span> }</span><br><span> </span><br><span>@@ -2858,8 +2857,7 @@</span><br><span>           return -EINVAL;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (mmctx->gmm_state != GMM_REGISTERED_NORMAL &&</span><br><span style="color: hsl(0, 100%, 40%);">-         mmctx->gmm_state != GMM_REGISTERED_SUSPENDED) {</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!gmm_fsm_is_registered(mmctx->gmm_fsm)) {</span><br><span>             LOGMMCTXP(LOGL_NOTICE, mmctx, "RESUME request while state "</span><br><span>                        "!= SUSPENDED (TLLI=%08x)\n", tlli);</span><br><span>               /* FIXME: should we not simply ignore it? */</span><br><span>@@ -2867,6 +2865,6 @@</span><br><span>         }</span><br><span> </span><br><span>        /* Transition from SUSPENDED to NORMAL */</span><br><span style="color: hsl(0, 100%, 40%);">-       mmctx->gmm_state = GMM_REGISTERED_NORMAL;</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_fsm_inst_dispatch(mmctx->gmm_fsm, E_GMM_RESUME, NULL);</span><br><span>       return 0;</span><br><span> }</span><br><span>diff --git a/src/sgsn/gprs_gmm_fsm.c b/src/sgsn/gprs_gmm_fsm.c</span><br><span>new file mode 100644</span><br><span>index 0000000..fac06f2</span><br><span>--- /dev/null</span><br><span>+++ b/src/sgsn/gprs_gmm_fsm.c</span><br><span>@@ -0,0 +1,187 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/tdef.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/sgsn/gprs_gmm_fsm.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/sgsn/debug.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/sgsn/sgsn.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define X(s) (1 << (s))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const struct osmo_tdef_state_timeout gmm_fsm_timeouts[32] = {</span><br><span style="color: hsl(120, 100%, 40%);">+     [ST_GMM_DEREGISTERED] = { },</span><br><span style="color: hsl(120, 100%, 40%);">+  [ST_GMM_COMMON_PROC_INIT] = { },</span><br><span style="color: hsl(120, 100%, 40%);">+      [ST_GMM_REGISTERED_NORMAL] = { },</span><br><span style="color: hsl(120, 100%, 40%);">+     [ST_GMM_REGISTERED_SUSPENDED] = { },</span><br><span style="color: hsl(120, 100%, 40%);">+  [ST_GMM_DEREGISTERED_INIT] = { },</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%);">+#define gmm_fsm_state_chg(fi, NEXT_STATE) \</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_tdef_fsm_inst_state_chg(fi, NEXT_STATE, gmm_fsm_timeouts, sgsn->cfg.T_defs, -1)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void st_gmm_deregistered(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   switch(event) {</span><br><span style="color: hsl(120, 100%, 40%);">+       case E_GMM_COMMON_PROC_INIT_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+              gmm_fsm_state_chg(fi, ST_GMM_COMMON_PROC_INIT);</span><br><span style="color: hsl(120, 100%, 40%);">+               break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case E_GMM_ATTACH_SUCCESS:</span><br><span style="color: hsl(120, 100%, 40%);">+            gmm_fsm_state_chg(fi, ST_GMM_REGISTERED_NORMAL);</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 st_gmm_common_proc_init(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  switch(event) {</span><br><span style="color: hsl(120, 100%, 40%);">+       /* TODO: events not used</span><br><span style="color: hsl(120, 100%, 40%);">+      case E_GMM_LOWER_LAYER_FAILED:</span><br><span style="color: hsl(120, 100%, 40%);">+        case E_GMM_COMMON_PROC_FAILED:</span><br><span style="color: hsl(120, 100%, 40%);">+                gmm_fsm_state_chg(fi, ST_GMM_DEREGISTERED);</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%);">+    case E_GMM_COMMON_PROC_SUCCESS:</span><br><span style="color: hsl(120, 100%, 40%);">+       case E_GMM_ATTACH_SUCCESS:</span><br><span style="color: hsl(120, 100%, 40%);">+            gmm_fsm_state_chg(fi, ST_GMM_REGISTERED_NORMAL);</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 st_gmm_registered_normal(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ switch(event) {</span><br><span style="color: hsl(120, 100%, 40%);">+       case E_GMM_COMMON_PROC_INIT_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+              gmm_fsm_state_chg(fi, ST_GMM_COMMON_PROC_INIT);</span><br><span style="color: hsl(120, 100%, 40%);">+               break;</span><br><span style="color: hsl(120, 100%, 40%);">+        /* case E_GMM_NET_INIT_DETACH_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+            gmm_fsm_state_chg(fi, ST_GMM_DEREGISTERED_INIT);</span><br><span style="color: hsl(120, 100%, 40%);">+              break; */</span><br><span style="color: hsl(120, 100%, 40%);">+     /* case E_GMM_MS_INIT_DETACH_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+             gmm_fsm_state_chg(fi, ST_GMM_DEREGISTERED);</span><br><span style="color: hsl(120, 100%, 40%);">+           break; */</span><br><span style="color: hsl(120, 100%, 40%);">+     case E_GMM_SUSPEND:</span><br><span style="color: hsl(120, 100%, 40%);">+           gmm_fsm_state_chg(fi, ST_GMM_REGISTERED_SUSPENDED);</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 st_gmm_registered_suspended(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      switch(event) {</span><br><span style="color: hsl(120, 100%, 40%);">+       case E_GMM_RESUME:</span><br><span style="color: hsl(120, 100%, 40%);">+            gmm_fsm_state_chg(fi, ST_GMM_REGISTERED_NORMAL);</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 st_gmm_deregistered_init(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ switch(event) {</span><br><span style="color: hsl(120, 100%, 40%);">+       /* TODO: events not used in osmo-sgsn code</span><br><span style="color: hsl(120, 100%, 40%);">+    case E_GMM_DETACH_ACCEPTED:</span><br><span style="color: hsl(120, 100%, 40%);">+   case E_GMM_LOWER_LAYER_FAILED:</span><br><span style="color: hsl(120, 100%, 40%);">+                gmm_fsm_state_chg(fi, ST_GMM_DEREGISTERED);</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct osmo_fsm_state gmm_fsm_states[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+     [ST_GMM_DEREGISTERED] = {</span><br><span style="color: hsl(120, 100%, 40%);">+             .in_event_mask =</span><br><span style="color: hsl(120, 100%, 40%);">+                      X(E_GMM_COMMON_PROC_INIT_REQ) |</span><br><span style="color: hsl(120, 100%, 40%);">+                       X(E_GMM_ATTACH_SUCCESS),</span><br><span style="color: hsl(120, 100%, 40%);">+              .out_state_mask = X(ST_GMM_COMMON_PROC_INIT),</span><br><span style="color: hsl(120, 100%, 40%);">+         .name = "Deregistered",</span><br><span style="color: hsl(120, 100%, 40%);">+             .action = st_gmm_deregistered,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+    [ST_GMM_COMMON_PROC_INIT] = {</span><br><span style="color: hsl(120, 100%, 40%);">+         .in_event_mask =</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* X(E_GMM_LOWER_LAYER_FAILED) | */</span><br><span style="color: hsl(120, 100%, 40%);">+                   /* X(E_GMM_COMMON_PROC_FAILED) | */</span><br><span style="color: hsl(120, 100%, 40%);">+                   X(E_GMM_COMMON_PROC_SUCCESS) |</span><br><span style="color: hsl(120, 100%, 40%);">+                        X(E_GMM_ATTACH_SUCCESS),</span><br><span style="color: hsl(120, 100%, 40%);">+              .out_state_mask =</span><br><span style="color: hsl(120, 100%, 40%);">+                     X(ST_GMM_DEREGISTERED) |</span><br><span style="color: hsl(120, 100%, 40%);">+                      X(ST_GMM_REGISTERED_NORMAL),</span><br><span style="color: hsl(120, 100%, 40%);">+          .name = "CommonProcedureInitiated",</span><br><span style="color: hsl(120, 100%, 40%);">+         .action = st_gmm_common_proc_init,</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+    [ST_GMM_REGISTERED_NORMAL] = {</span><br><span style="color: hsl(120, 100%, 40%);">+                .in_event_mask =</span><br><span style="color: hsl(120, 100%, 40%);">+                      X(E_GMM_COMMON_PROC_INIT_REQ) |</span><br><span style="color: hsl(120, 100%, 40%);">+                       /* X(E_GMM_NET_INIT_DETACH_REQ) | */</span><br><span style="color: hsl(120, 100%, 40%);">+                  /* X(E_GMM_MS_INIT_DETACH_REQ) | */</span><br><span style="color: hsl(120, 100%, 40%);">+                   X(E_GMM_SUSPEND),</span><br><span style="color: hsl(120, 100%, 40%);">+             .out_state_mask =</span><br><span style="color: hsl(120, 100%, 40%);">+                     X(ST_GMM_DEREGISTERED) |</span><br><span style="color: hsl(120, 100%, 40%);">+                      X(ST_GMM_COMMON_PROC_INIT) |</span><br><span style="color: hsl(120, 100%, 40%);">+                  X(ST_GMM_DEREGISTERED_INIT) |</span><br><span style="color: hsl(120, 100%, 40%);">+                 X(ST_GMM_REGISTERED_SUSPENDED),</span><br><span style="color: hsl(120, 100%, 40%);">+               .name = "Registered.NORMAL",</span><br><span style="color: hsl(120, 100%, 40%);">+                .action = st_gmm_registered_normal,</span><br><span style="color: hsl(120, 100%, 40%);">+   },</span><br><span style="color: hsl(120, 100%, 40%);">+    [ST_GMM_REGISTERED_SUSPENDED] = {</span><br><span style="color: hsl(120, 100%, 40%);">+             .in_event_mask = X(E_GMM_RESUME),</span><br><span style="color: hsl(120, 100%, 40%);">+             .out_state_mask =</span><br><span style="color: hsl(120, 100%, 40%);">+                     X(ST_GMM_DEREGISTERED) |</span><br><span style="color: hsl(120, 100%, 40%);">+                      X(ST_GMM_REGISTERED_NORMAL),</span><br><span style="color: hsl(120, 100%, 40%);">+          .name = "Registered.SUSPENDED",</span><br><span style="color: hsl(120, 100%, 40%);">+             .action = st_gmm_registered_suspended,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+    [ST_GMM_DEREGISTERED_INIT] = {</span><br><span style="color: hsl(120, 100%, 40%);">+                .in_event_mask = 0</span><br><span style="color: hsl(120, 100%, 40%);">+                    /* X(E_GMM_DETACH_ACCEPTED) | */</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* X(E_GMM_LOWER_LAYER_FAILED) */,</span><br><span style="color: hsl(120, 100%, 40%);">+            .out_state_mask = X(ST_GMM_DEREGISTERED),</span><br><span style="color: hsl(120, 100%, 40%);">+             .name = "DeregisteredInitiated",</span><br><span style="color: hsl(120, 100%, 40%);">+            .action = st_gmm_deregistered_init,</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%);">+const struct value_string gmm_fsm_event_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_VALUE_STRING(E_GMM_COMMON_PROC_INIT_REQ),</span><br><span style="color: hsl(120, 100%, 40%);">+        /* OSMO_VALUE_STRING(E_GMM_COMMON_PROC_FAILED), */</span><br><span style="color: hsl(120, 100%, 40%);">+    /*  OSMO_VALUE_STRING(E_GMM_LOWER_LAYER_FAILED),  */</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_VALUE_STRING(E_GMM_COMMON_PROC_SUCCESS),</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_VALUE_STRING(E_GMM_ATTACH_SUCCESS),</span><br><span style="color: hsl(120, 100%, 40%);">+      /*  OSMO_VALUE_STRING(E_GMM_NET_INIT_DETACH_REQ), */</span><br><span style="color: hsl(120, 100%, 40%);">+  /*  OSMO_VALUE_STRING(E_GMM_MS_INIT_DETACH_REQ), */</span><br><span style="color: hsl(120, 100%, 40%);">+   /* OSMO_VALUE_STRING(E_GMM_DETACH_ACCEPTED), */</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_VALUE_STRING(E_GMM_SUSPEND),</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_VALUE_STRING(E_GMM_CLEANUP),</span><br><span style="color: hsl(120, 100%, 40%);">+     { 0, NULL }</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%);">+void gmm_fsm_allstate_action(struct osmo_fsm_inst *fi, uint32_t event, void *data) {</span><br><span style="color: hsl(120, 100%, 40%);">+       switch (event) {</span><br><span style="color: hsl(120, 100%, 40%);">+      case E_GMM_CLEANUP:</span><br><span style="color: hsl(120, 100%, 40%);">+           switch (fi->state) {</span><br><span style="color: hsl(120, 100%, 40%);">+               case ST_GMM_DEREGISTERED:</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%);">+                      gmm_fsm_state_chg(fi, ST_GMM_DEREGISTERED);</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int gmm_fsm_timer_cb(struct osmo_fsm_inst *fi)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     return 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%);">+struct osmo_fsm gmm_fsm = {</span><br><span style="color: hsl(120, 100%, 40%);">+   .name = "GMM",</span><br><span style="color: hsl(120, 100%, 40%);">+      .states = gmm_fsm_states,</span><br><span style="color: hsl(120, 100%, 40%);">+     .num_states = ARRAY_SIZE(gmm_fsm_states),</span><br><span style="color: hsl(120, 100%, 40%);">+     .event_names = gmm_fsm_event_names,</span><br><span style="color: hsl(120, 100%, 40%);">+   .allstate_event_mask = X(E_GMM_CLEANUP),</span><br><span style="color: hsl(120, 100%, 40%);">+      .allstate_action = gmm_fsm_allstate_action,</span><br><span style="color: hsl(120, 100%, 40%);">+   .log_subsys = DMM,</span><br><span style="color: hsl(120, 100%, 40%);">+    .timer_cb = gmm_fsm_timer_cb,</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 __attribute__((constructor)) void gmm_fsm_init(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   osmo_fsm_register(&gmm_fsm);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/sgsn/gprs_sgsn.c b/src/sgsn/gprs_sgsn.c</span><br><span>index 387c0d5..1c23d06 100644</span><br><span>--- a/src/sgsn/gprs_sgsn.c</span><br><span>+++ b/src/sgsn/gprs_sgsn.c</span><br><span>@@ -44,6 +44,7 @@</span><br><span> #include <osmocom/sgsn/gprs_gmm_attach.h></span><br><span> #include <osmocom/sgsn/gprs_mm_state_gb_fsm.h></span><br><span> #include <osmocom/sgsn/gprs_mm_state_iu_fsm.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/sgsn/gprs_gmm_fsm.h></span><br><span> #include <osmocom/sgsn/gprs_llc.h></span><br><span> </span><br><span> #include <pdp.h></span><br><span>@@ -234,7 +235,6 @@</span><br><span>        if (!ctx)</span><br><span>            return NULL;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        ctx->gmm_state = GMM_DEREGISTERED;</span><br><span>        ctx->auth_triplet.key_seq = GSM_KEY_SEQ_INVAL;</span><br><span>    ctx->ctrg = rate_ctr_group_alloc(ctx, &mmctx_ctrg_desc, rate_ctr_id);</span><br><span>         if (!ctx->ctrg) {</span><br><span>@@ -242,6 +242,7 @@</span><br><span>           talloc_free(ctx);</span><br><span>            return NULL;</span><br><span>         }</span><br><span style="color: hsl(120, 100%, 40%);">+     ctx->gmm_fsm = osmo_fsm_inst_alloc(&gmm_fsm, ctx, ctx, LOGL_DEBUG, "gmm_fsm");</span><br><span>      ctx->gmm_att_req.fsm = osmo_fsm_inst_alloc(&gmm_attach_req_fsm, ctx, ctx, LOGL_DEBUG, "gb_gmm_req");</span><br><span>        INIT_LLIST_HEAD(&ctx->pdp_list);</span><br><span> </span><br><span>@@ -368,6 +369,8 @@</span><br><span>            osmo_fsm_inst_free(mm->gb.mm_state_fsm);</span><br><span>  if (mm->iu.mm_state_fsm)</span><br><span>          osmo_fsm_inst_free(mm->iu.mm_state_fsm);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (mm->gmm_fsm)</span><br><span style="color: hsl(120, 100%, 40%);">+           osmo_fsm_inst_free(mm->gmm_fsm);</span><br><span> </span><br><span>      sgsn_mm_ctx_free(mm);</span><br><span>        mm = NULL;</span><br><span>@@ -736,7 +739,7 @@</span><br><span> {</span><br><span>        /* the MM context can be deleted while the GGSN is not reachable or</span><br><span>   * if has been crashed. */</span><br><span style="color: hsl(0, 100%, 40%);">-      if (pctx->mm && pctx->mm->gmm_state == GMM_REGISTERED_NORMAL) {</span><br><span style="color: hsl(120, 100%, 40%);">+      if (pctx->mm && pctx->mm->gmm_fsm->state == ST_GMM_REGISTERED_NORMAL) {</span><br><span>          gsm48_tx_gsm_deact_pdp_req(pctx, GSM_CAUSE_NET_FAIL, true);</span><br><span>          sgsn_ggsn_ctx_remove_pdp(pctx->ggsn, pctx);</span><br><span>       } else  {</span><br><span>diff --git a/src/sgsn/sgsn_libgtp.c b/src/sgsn/sgsn_libgtp.c</span><br><span>index 5e3f48f..f6d7a69 100644</span><br><span>--- a/src/sgsn/sgsn_libgtp.c</span><br><span>+++ b/src/sgsn/sgsn_libgtp.c</span><br><span>@@ -51,6 +51,7 @@</span><br><span> #include <osmocom/sgsn/gprs_subscriber.h></span><br><span> #include <osmocom/sgsn/gprs_sndcp.h></span><br><span> #include <osmocom/sgsn/gprs_ranap.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/sgsn/gprs_gmm_fsm.h></span><br><span> </span><br><span> #include <gtp.h></span><br><span> #include <pdp.h></span><br><span>@@ -655,8 +656,8 @@</span><br><span>        msgb_bvci(msg) = mm->gb.bvci;</span><br><span>     msgb_nsei(msg) = mm->gb.nsei;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    switch (mm->gmm_state) {</span><br><span style="color: hsl(0, 100%, 40%);">-     case GMM_REGISTERED_SUSPENDED:</span><br><span style="color: hsl(120, 100%, 40%);">+        switch (mm->gmm_fsm->state) {</span><br><span style="color: hsl(120, 100%, 40%);">+   case ST_GMM_REGISTERED_SUSPENDED:</span><br><span>            /* initiate PS PAGING procedure */</span><br><span>           memset(&pinfo, 0, sizeof(pinfo));</span><br><span>                pinfo.mode = BSSGP_PAGING_PS;</span><br><span>@@ -670,11 +671,11 @@</span><br><span>                rate_ctr_inc(&mm->ctrg->ctr[GMM_CTR_PAGING_PS]);</span><br><span>           /* FIXME: queue the packet we received from GTP */</span><br><span>           break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case GMM_REGISTERED_NORMAL:</span><br><span style="color: hsl(120, 100%, 40%);">+   case ST_GMM_REGISTERED_NORMAL:</span><br><span>               break;</span><br><span>       default:</span><br><span>             LOGP(DGPRS, LOGL_ERROR, "GTP DATA IND for TLLI %08X in state "</span><br><span style="color: hsl(0, 100%, 40%);">-                        "%u\n", mm->gb.tlli, mm->gmm_state);</span><br><span style="color: hsl(120, 100%, 40%);">+                  "%s\n", mm->gb.tlli, osmo_fsm_inst_state_name(mm->gmm_fsm));</span><br><span>                 msgb_free(msg);</span><br><span>              return -1;</span><br><span>   }</span><br><span>diff --git a/src/sgsn/sgsn_vty.c b/src/sgsn/sgsn_vty.c</span><br><span>index 184ece7..9200822 100644</span><br><span>--- a/src/sgsn/sgsn_vty.c</span><br><span>+++ b/src/sgsn/sgsn_vty.c</span><br><span>@@ -476,15 +476,6 @@</span><br><span>    return add_apn_ggsn_mapping(vty, argv[0], argv[1], atoi(argv[2]));</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-const struct value_string gprs_mm_st_strs[] = {</span><br><span style="color: hsl(0, 100%, 40%);">-      { GMM_DEREGISTERED, "DEREGISTERED" },</span><br><span style="color: hsl(0, 100%, 40%);">- { GMM_COMMON_PROC_INIT, "COMMON PROCEDURE (INIT)" },</span><br><span style="color: hsl(0, 100%, 40%);">-  { GMM_REGISTERED_NORMAL, "REGISTERED (NORMAL)" },</span><br><span style="color: hsl(0, 100%, 40%);">-     { GMM_REGISTERED_SUSPENDED, "REGISTERED (SUSPENDED)" },</span><br><span style="color: hsl(0, 100%, 40%);">-       { GMM_DEREGISTERED_INIT, "DEREGISTERED (INIT)" },</span><br><span style="color: hsl(0, 100%, 40%);">-     { 0, NULL }</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> char *sgsn_gtp_ntoa(struct ul16_t *ul)</span><br><span> {</span><br><span>         struct in_addr ia;</span><br><span>@@ -546,7 +537,7 @@</span><br><span>     vty_out(vty, "%s  MSISDN: %s, TLLI: %08x%s HLR: %s",</span><br><span>               pfx, mm->msisdn, id, mm->hlr, VTY_NEWLINE);</span><br><span>    vty_out(vty, "%s  GMM State: %s, Routeing Area: %s, Cell ID: %u%s",</span><br><span style="color: hsl(0, 100%, 40%);">-           pfx, get_value_string(gprs_mm_st_strs, mm->gmm_state),</span><br><span style="color: hsl(120, 100%, 40%);">+             pfx, osmo_fsm_inst_state_name(mm->gmm_fsm),</span><br><span>               osmo_rai_name(&mm->ra), mm->gb.cell_id, VTY_NEWLINE);</span><br><span>      vty_out(vty, "%s  MM State: %s, RAN Type: %s%s", pfx, mm_state_name,</span><br><span>               get_value_string(sgsn_ran_type_names, mm->ran_type), VTY_NEWLINE);</span><br><span>diff --git a/tests/sgsn/Makefile.am b/tests/sgsn/Makefile.am</span><br><span>index 7ba70eb..9afe0f7 100644</span><br><span>--- a/tests/sgsn/Makefile.am</span><br><span>+++ b/tests/sgsn/Makefile.am</span><br><span>@@ -48,6 +48,7 @@</span><br><span>       $(top_builddir)/src/sgsn/gprs_sndcp.o \</span><br><span>      $(top_builddir)/src/sgsn/gprs_gmm_attach.o \</span><br><span>         $(top_builddir)/src/sgsn/gprs_gmm.o \</span><br><span style="color: hsl(120, 100%, 40%);">+ $(top_builddir)/src/sgsn/gprs_gmm_fsm.o \</span><br><span>    $(top_builddir)/src/sgsn/gprs_mm_state_gb_fsm.o \</span><br><span>    $(top_builddir)/src/sgsn/gprs_mm_state_iu_fsm.o \</span><br><span>    $(top_builddir)/src/sgsn/gprs_sgsn.o \</span><br><span>diff --git a/tests/sgsn/sgsn_test.c b/tests/sgsn/sgsn_test.c</span><br><span>index cc25d47..7399573 100644</span><br><span>--- a/tests/sgsn/sgsn_test.c</span><br><span>+++ b/tests/sgsn/sgsn_test.c</span><br><span>@@ -28,6 +28,7 @@</span><br><span> #include <osmocom/gsupclient/gsup_client.h></span><br><span> #include <osmocom/sgsn/gprs_utils.h></span><br><span> #include <osmocom/sgsn/gprs_gb_parse.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/sgsn/gprs_gmm_fsm.h></span><br><span> </span><br><span> #include <osmocom/gprs/gprs_bssgp.h></span><br><span> </span><br><span>@@ -192,7 +193,6 @@</span><br><span> </span><br><span>    lle = gprs_lle_get_or_create(tlli, 3);</span><br><span>       ctx = sgsn_mm_ctx_alloc_gb(tlli, raid);</span><br><span style="color: hsl(0, 100%, 40%);">- ctx->gmm_state = GMM_REGISTERED_NORMAL;</span><br><span>   ctx->gb.llme = lle->llme;</span><br><span> </span><br><span>  ictx = sgsn_mm_ctx_by_tlli(tlli, raid);</span><br><span>@@ -1286,7 +1286,7 @@</span><br><span> </span><br><span>  ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);</span><br><span>  OSMO_ASSERT(ctx != NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-       OSMO_ASSERT(ctx->gmm_state == GMM_COMMON_PROC_INIT);</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_ASSERT(ctx->gmm_fsm->state == ST_GMM_COMMON_PROC_INIT);</span><br><span> </span><br><span>       /* we expect an identity request (IMEI) */</span><br><span>   OSMO_ASSERT(sgsn_tx_counter == 1);</span><br><span>@@ -1306,7 +1306,7 @@</span><br><span>    * authorization */</span><br><span>  OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   OSMO_ASSERT(ctx->gmm_state == GMM_COMMON_PROC_INIT);</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_ASSERT(ctx->gmm_fsm->state == ST_GMM_COMMON_PROC_INIT);</span><br><span> </span><br><span>       /* we expect an attach accept/reject */</span><br><span>      OSMO_ASSERT(sgsn_tx_counter == 1);</span><br><span>@@ -1320,7 +1320,7 @@</span><br><span>   send_0408_message(ctx->gb.llme, foreign_tlli, &raid,</span><br><span>                    attach_compl, ARRAY_SIZE(attach_compl));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  OSMO_ASSERT(ctx->gmm_state == GMM_REGISTERED_NORMAL);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(ctx->gmm_fsm->state == ST_GMM_REGISTERED_NORMAL);</span><br><span> </span><br><span>      /* we don't expect a response */</span><br><span>         OSMO_ASSERT(sgsn_tx_counter == 0);</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-sgsn/+/15385">change 15385</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/+/15385"/><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: Idecb43c10d66224d4f9ba9320825040ce6cf9a07 </div>
<div style="display:none"> Gerrit-Change-Number: 15385 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: pespin <pespin@sysmocom.de> </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: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-CC: fixeria <axilirator@gmail.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>