aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2019-09-02 16:45:27 +0200
committerPau Espin Pedrol <pespin@sysmocom.de>2019-09-03 15:22:12 +0200
commit31c4657c971e40407163034526aafeb9b5a83460 (patch)
tree3f034b28108531fdbc6c1911b12c4572690b96a2
parent2e91fee1ad5c69f9336716b57979eb7557251778 (diff)
Implement GMM State using osmocom FSM
State machine inspired in the one from TS 24.008 4.1.3.3.1. Some state transitions are inroduced in the code but are still commented out since we lack some functionalitites or improvements in the code to handle different scenarios. Most of the logic is still outside of the FSM, but at least now the states are handled in a sane way triggered by events. Change-Id: Idecb43c10d66224d4f9ba9320825040ce6cf9a07
-rw-r--r--include/osmocom/sgsn/Makefile.am1
-rw-r--r--include/osmocom/sgsn/gprs_gmm_fsm.h34
-rw-r--r--include/osmocom/sgsn/gprs_sgsn.h11
-rw-r--r--src/sgsn/Makefile.am1
-rw-r--r--src/sgsn/gprs_gmm.c44
-rw-r--r--src/sgsn/gprs_gmm_fsm.c187
-rw-r--r--src/sgsn/gprs_sgsn.c7
-rw-r--r--src/sgsn/sgsn_libgtp.c9
-rw-r--r--src/sgsn/sgsn_vty.c11
-rw-r--r--tests/sgsn/Makefile.am1
-rw-r--r--tests/sgsn/sgsn_test.c8
11 files changed, 261 insertions, 53 deletions
diff --git a/include/osmocom/sgsn/Makefile.am b/include/osmocom/sgsn/Makefile.am
index 0ab00fe4..9ddc2bc9 100644
--- a/include/osmocom/sgsn/Makefile.am
+++ b/include/osmocom/sgsn/Makefile.am
@@ -6,6 +6,7 @@ noinst_HEADERS = \
gprs_gb.h \
gprs_gb_parse.h \
gprs_gmm.h \
+ gprs_gmm_fsm.h \
gprs_gmm_attach.h \
gprs_mm_state_gb_fsm.h \
gprs_mm_state_iu_fsm.h \
diff --git a/include/osmocom/sgsn/gprs_gmm_fsm.h b/include/osmocom/sgsn/gprs_gmm_fsm.h
new file mode 100644
index 00000000..fd5b4bff
--- /dev/null
+++ b/include/osmocom/sgsn/gprs_gmm_fsm.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <osmocom/core/fsm.h>
+
+/* 3GPP TS 24.008 § 4.1.3.3 GMM mobility management states on the network side */
+enum gmm_fsm_states {
+ ST_GMM_DEREGISTERED, /* 4.1.3.3.1.1 */
+ ST_GMM_COMMON_PROC_INIT, /* 4.1.3.3.1.2 */
+ ST_GMM_REGISTERED_NORMAL, /* 4.1.3.3.2.1 */
+ ST_GMM_REGISTERED_SUSPENDED, /* 4.1.3.3.2.2 */
+ ST_GMM_DEREGISTERED_INIT, /* 4.1.3.3.1.4 */
+};
+
+enum gmm_fsm_events {
+ E_GMM_COMMON_PROC_INIT_REQ,
+ /* E_GMM_COMMON_PROC_FAILED, NOT USED */
+ /* E_GMM_LOWER_LAYER_FAILED, NOT USED */
+ E_GMM_COMMON_PROC_SUCCESS,
+ E_GMM_ATTACH_SUCCESS,
+ /* E_GMM_NET_INIT_DETACH_REQ, NOT USED */
+ /* E_GMM_MS_INIT_DETACH_REQ, NOT USED */
+ /* E_GMM_DETACH_ACCEPTED, */
+ E_GMM_SUSPEND,
+ E_GMM_RESUME,
+ E_GMM_CLEANUP,
+};
+
+static inline bool gmm_fsm_is_registered(struct osmo_fsm_inst *fi)
+{
+ return fi->state == ST_GMM_REGISTERED_NORMAL ||
+ fi->state == ST_GMM_REGISTERED_SUSPENDED;
+}
+
+extern struct osmo_fsm gmm_fsm;
diff --git a/include/osmocom/sgsn/gprs_sgsn.h b/include/osmocom/sgsn/gprs_sgsn.h
index 20e0e06a..0a52a7df 100644
--- a/include/osmocom/sgsn/gprs_sgsn.h
+++ b/include/osmocom/sgsn/gprs_sgsn.h
@@ -23,15 +23,6 @@ struct gprs_subscr;
enum gsm48_gsm_cause;
-/* 3GPP TS 24.008 § 4.1.3.3 GMM mobility management states on the network side */
-enum gprs_gmm_state {
- GMM_DEREGISTERED, /* 4.1.3.3.1.1 */
- GMM_COMMON_PROC_INIT, /* 4.1.3.3.1.2 */
- GMM_REGISTERED_NORMAL, /* 4.1.3.3.2.1 */
- GMM_REGISTERED_SUSPENDED, /* 4.1.3.3.2.2 */
- GMM_DEREGISTERED_INIT, /* 4.1.3.3.1.4 */
-};
-
enum gprs_mm_ctr {
GMM_CTR_PKTS_SIG_IN,
GMM_CTR_PKTS_SIG_OUT,
@@ -128,7 +119,7 @@ struct sgsn_mm_ctx {
enum sgsn_ran_type ran_type;
char imsi[GSM23003_IMSI_MAX_DIGITS+1];
- enum gprs_gmm_state gmm_state;
+ struct osmo_fsm_inst *gmm_fsm;
uint32_t p_tmsi;
uint32_t p_tmsi_old; /* old P-TMSI before new is confirmed */
uint32_t p_tmsi_sig;
diff --git a/src/sgsn/Makefile.am b/src/sgsn/Makefile.am
index a8da9430..4402c9c6 100644
--- a/src/sgsn/Makefile.am
+++ b/src/sgsn/Makefile.am
@@ -43,6 +43,7 @@ osmo_sgsn_SOURCES = \
gprs_gb.c \
gprs_gmm_attach.c \
gprs_gmm.c \
+ gprs_gmm_fsm.c \
gprs_mm_state_gb_fsm.c \
gprs_mm_state_iu_fsm.c \
gprs_ranap.c \
diff --git a/src/sgsn/gprs_gmm.c b/src/sgsn/gprs_gmm.c
index 399f7bf8..3317a092 100644
--- a/src/sgsn/gprs_gmm.c
+++ b/src/sgsn/gprs_gmm.c
@@ -57,6 +57,7 @@
#include <osmocom/sgsn/gprs_gmm_attach.h>
#include <osmocom/sgsn/gprs_mm_state_gb_fsm.h>
#include <osmocom/sgsn/gprs_mm_state_iu_fsm.h>
+#include <osmocom/sgsn/gprs_gmm_fsm.h>
#include <osmocom/sgsn/signal.h>
#include <osmocom/sgsn/gprs_sndcp.h>
#include <osmocom/sgsn/gprs_ranap.h>
@@ -211,7 +212,7 @@ static void mm_ctx_cleanup_free(struct sgsn_mm_ctx *ctx, const char *log_text)
LOGMMCTXP(LOGL_INFO, ctx, "Cleaning MM context due to %s\n", log_text);
/* Mark MM state as deregistered */
- ctx->gmm_state = GMM_DEREGISTERED;
+ osmo_fsm_inst_dispatch(ctx->gmm_fsm, E_GMM_CLEANUP, NULL);
switch(ctx->ran_type) {
case MM_CTX_T_UTRAN_Iu:
@@ -967,7 +968,7 @@ int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx)
memset(&sig_data, 0, sizeof(sig_data));
sig_data.mm = mmctx;
osmo_signal_dispatch(SS_SGSN, S_SGSN_ATTACH, &sig_data);
- ctx->gmm_state = GMM_REGISTERED_NORMAL;
+ osmo_fsm_inst_dispatch(mm->gmm_fsm, E_GMM_ATTACH_SUCCESS, NULL);
#endif
return gsm48_tx_gmm_att_ack(ctx);
@@ -1009,8 +1010,8 @@ void gsm0408_gprs_authenticate(struct sgsn_mm_ctx *ctx)
void gsm0408_gprs_access_granted(struct sgsn_mm_ctx *ctx)
{
- switch (ctx->gmm_state) {
- case GMM_COMMON_PROC_INIT:
+ switch (ctx->gmm_fsm->state) {
+ case ST_GMM_COMMON_PROC_INIT:
LOGMMCTXP(LOGL_NOTICE, ctx,
"Authorized, continuing procedure, IMSI=%s\n",
ctx->imsi);
@@ -1030,8 +1031,8 @@ void gsm0408_gprs_access_denied(struct sgsn_mm_ctx *ctx, int gmm_cause)
if (gmm_cause == SGSN_ERROR_CAUSE_NONE)
gmm_cause = GMM_CAUSE_GPRS_NOTALLOWED;
- switch (ctx->gmm_state) {
- case GMM_COMMON_PROC_INIT:
+ switch (ctx->gmm_fsm->state) {
+ case ST_GMM_COMMON_PROC_INIT:
LOGMMCTXP(LOGL_NOTICE, ctx,
"Not authorized, rejecting ATTACH REQUEST "
"with cause '%s' (%d)\n",
@@ -1040,8 +1041,8 @@ void gsm0408_gprs_access_denied(struct sgsn_mm_ctx *ctx, int gmm_cause)
if (ctx->gmm_att_req.fsm->state != ST_INIT)
osmo_fsm_inst_dispatch(ctx->gmm_att_req.fsm, E_REJECT, (void *) (long) gmm_cause);
break;
- case GMM_REGISTERED_NORMAL:
- case GMM_REGISTERED_SUSPENDED:
+ case ST_GMM_REGISTERED_NORMAL:
+ case ST_GMM_REGISTERED_SUSPENDED:
LOGMMCTXP(LOGL_NOTICE, ctx,
"Authorization lost, detaching "
"with cause '%s' (%d)\n",
@@ -1142,7 +1143,7 @@ static inline void ptmsi_update(struct sgsn_mm_ctx *ctx)
{
uint32_t ptmsi;
/* Don't change the P-TMSI if a P-TMSI re-assignment is under way */
- if (ctx->gmm_state != GMM_COMMON_PROC_INIT) {
+ if (ctx->gmm_fsm->state != ST_GMM_COMMON_PROC_INIT) {
ptmsi = sgsn_alloc_ptmsi();
if (ptmsi != GSM_RESERVED_TMSI) {
ctx->p_tmsi_old = ctx->p_tmsi;
@@ -1150,7 +1151,7 @@ static inline void ptmsi_update(struct sgsn_mm_ctx *ctx)
} else
LOGMMCTXP(LOGL_ERROR, ctx, "P-TMSI allocation failure: using old one.\n");
}
- ctx->gmm_state = GMM_COMMON_PROC_INIT;
+ osmo_fsm_inst_dispatch(ctx->gmm_fsm, E_GMM_COMMON_PROC_INIT_REQ, NULL);
}
/* 3GPP TS 24.008 § 9.4.1 Attach request */
@@ -1360,7 +1361,7 @@ static int gsm48_rx_gmm_att_compl(struct sgsn_mm_ctx *mmctx)
mmctx->t3350_mode = GMM_T3350_MODE_NONE;
mmctx->p_tmsi_old = 0;
mmctx->pending_req = 0;
- mmctx->gmm_state = GMM_REGISTERED_NORMAL;
+ osmo_fsm_inst_dispatch(mmctx->gmm_fsm, E_GMM_ATTACH_SUCCESS, NULL);
switch(mmctx->ran_type) {
case MM_CTX_T_UTRAN_Iu:
osmo_fsm_inst_dispatch(mmctx->iu.mm_state_fsm, E_PMM_PS_ATTACH, NULL);
@@ -1658,11 +1659,10 @@ static int gsm48_rx_gmm_ra_upd_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
mmctx->p_tmsi, mmctx->p_tmsi_old,
mmctx->gb.tlli, mmctx->gb.tlli_new,
osmo_rai_name(&mmctx->ra));
-
- mmctx->gmm_state = GMM_COMMON_PROC_INIT;
+ osmo_fsm_inst_dispatch(mmctx->gmm_fsm, E_GMM_COMMON_PROC_INIT_REQ, NULL);
}
} else if (!gprs_ra_id_equals(&mmctx->ra, &old_ra_id) ||
- mmctx->gmm_state == GMM_DEREGISTERED)
+ mmctx->gmm_fsm->state == ST_GMM_DEREGISTERED)
{
/* We cannot use the mmctx */
LOGMMCTXP(LOGL_INFO, mmctx,
@@ -1715,7 +1715,7 @@ static int gsm48_rx_gmm_ra_upd_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
mmctx_timer_start(mmctx, 3350);
#else
/* Make sure we are NORMAL (i.e. not SUSPENDED anymore) */
- mmctx->gmm_state = GMM_REGISTERED_NORMAL;
+ osmo_fsm_inst_dispatch(mm->gmm_fsm, E_GMM_ATTACH_SUCCESS, NULL);
memset(&sig_data, 0, sizeof(sig_data));
sig_data.mm = mmctx;
@@ -1768,7 +1768,7 @@ static int gsm48_rx_gmm_ra_upd_compl(struct sgsn_mm_ctx *mmctx)
mmctx->t3350_mode = GMM_T3350_MODE_NONE;
mmctx->p_tmsi_old = 0;
mmctx->pending_req = 0;
- mmctx->gmm_state = GMM_REGISTERED_NORMAL;
+ osmo_fsm_inst_dispatch(mmctx->gmm_fsm, E_GMM_COMMON_PROC_SUCCESS, NULL);
switch(mmctx->ran_type) {
case MM_CTX_T_UTRAN_Iu:
osmo_fsm_inst_dispatch(mmctx->iu.mm_state_fsm, E_PMM_RA_UPDATE, NULL);
@@ -1883,7 +1883,7 @@ static int gsm48_rx_gmm_service_req(struct sgsn_mm_ctx *ctx, struct msgb *msg)
goto rejected;
}
- ctx->gmm_state = GMM_COMMON_PROC_INIT;
+ osmo_fsm_inst_dispatch(ctx->gmm_fsm, E_GMM_COMMON_PROC_INIT_REQ, NULL);
ctx->iu.service.type = service_type;
@@ -2832,15 +2832,14 @@ int gprs_gmm_rx_suspend(struct gprs_ra_id *raid, uint32_t tlli)
return -EINVAL;
}
- if (mmctx->gmm_state != GMM_REGISTERED_NORMAL &&
- mmctx->gmm_state != GMM_REGISTERED_SUSPENDED) {
+ if (!gmm_fsm_is_registered(mmctx->gmm_fsm)) {
LOGMMCTXP(LOGL_NOTICE, mmctx, "SUSPEND request while state "
"!= REGISTERED (TLLI=%08x)\n", tlli);
return -EINVAL;
}
/* Transition from REGISTERED_NORMAL to REGISTERED_SUSPENDED */
- mmctx->gmm_state = GMM_REGISTERED_SUSPENDED;
+ osmo_fsm_inst_dispatch(mmctx->gmm_fsm, E_GMM_SUSPEND, NULL);
return 0;
}
@@ -2858,8 +2857,7 @@ int gprs_gmm_rx_resume(struct gprs_ra_id *raid, uint32_t tlli,
return -EINVAL;
}
- if (mmctx->gmm_state != GMM_REGISTERED_NORMAL &&
- mmctx->gmm_state != GMM_REGISTERED_SUSPENDED) {
+ if (!gmm_fsm_is_registered(mmctx->gmm_fsm)) {
LOGMMCTXP(LOGL_NOTICE, mmctx, "RESUME request while state "
"!= SUSPENDED (TLLI=%08x)\n", tlli);
/* FIXME: should we not simply ignore it? */
@@ -2867,6 +2865,6 @@ int gprs_gmm_rx_resume(struct gprs_ra_id *raid, uint32_t tlli,
}
/* Transition from SUSPENDED to NORMAL */
- mmctx->gmm_state = GMM_REGISTERED_NORMAL;
+ osmo_fsm_inst_dispatch(mmctx->gmm_fsm, E_GMM_RESUME, NULL);
return 0;
}
diff --git a/src/sgsn/gprs_gmm_fsm.c b/src/sgsn/gprs_gmm_fsm.c
new file mode 100644
index 00000000..fac06f27
--- /dev/null
+++ b/src/sgsn/gprs_gmm_fsm.c
@@ -0,0 +1,187 @@
+#include <osmocom/core/tdef.h>
+
+#include <osmocom/sgsn/gprs_gmm_fsm.h>
+
+#include <osmocom/sgsn/debug.h>
+#include <osmocom/sgsn/sgsn.h>
+
+#define X(s) (1 << (s))
+
+static const struct osmo_tdef_state_timeout gmm_fsm_timeouts[32] = {
+ [ST_GMM_DEREGISTERED] = { },
+ [ST_GMM_COMMON_PROC_INIT] = { },
+ [ST_GMM_REGISTERED_NORMAL] = { },
+ [ST_GMM_REGISTERED_SUSPENDED] = { },
+ [ST_GMM_DEREGISTERED_INIT] = { },
+};
+
+#define gmm_fsm_state_chg(fi, NEXT_STATE) \
+ osmo_tdef_fsm_inst_state_chg(fi, NEXT_STATE, gmm_fsm_timeouts, sgsn->cfg.T_defs, -1)
+
+static void st_gmm_deregistered(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ switch(event) {
+ case E_GMM_COMMON_PROC_INIT_REQ:
+ gmm_fsm_state_chg(fi, ST_GMM_COMMON_PROC_INIT);
+ break;
+ case E_GMM_ATTACH_SUCCESS:
+ gmm_fsm_state_chg(fi, ST_GMM_REGISTERED_NORMAL);
+ break;
+ }
+}
+
+static void st_gmm_common_proc_init(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ switch(event) {
+ /* TODO: events not used
+ case E_GMM_LOWER_LAYER_FAILED:
+ case E_GMM_COMMON_PROC_FAILED:
+ gmm_fsm_state_chg(fi, ST_GMM_DEREGISTERED);
+ break;
+ */
+ case E_GMM_COMMON_PROC_SUCCESS:
+ case E_GMM_ATTACH_SUCCESS:
+ gmm_fsm_state_chg(fi, ST_GMM_REGISTERED_NORMAL);
+ break;
+ }
+}
+
+static void st_gmm_registered_normal(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ switch(event) {
+ case E_GMM_COMMON_PROC_INIT_REQ:
+ gmm_fsm_state_chg(fi, ST_GMM_COMMON_PROC_INIT);
+ break;
+ /* case E_GMM_NET_INIT_DETACH_REQ:
+ gmm_fsm_state_chg(fi, ST_GMM_DEREGISTERED_INIT);
+ break; */
+ /* case E_GMM_MS_INIT_DETACH_REQ:
+ gmm_fsm_state_chg(fi, ST_GMM_DEREGISTERED);
+ break; */
+ case E_GMM_SUSPEND:
+ gmm_fsm_state_chg(fi, ST_GMM_REGISTERED_SUSPENDED);
+ break;
+ }
+}
+
+static void st_gmm_registered_suspended(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ switch(event) {
+ case E_GMM_RESUME:
+ gmm_fsm_state_chg(fi, ST_GMM_REGISTERED_NORMAL);
+ break;
+ }
+}
+
+static void st_gmm_deregistered_init(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ switch(event) {
+ /* TODO: events not used in osmo-sgsn code
+ case E_GMM_DETACH_ACCEPTED:
+ case E_GMM_LOWER_LAYER_FAILED:
+ gmm_fsm_state_chg(fi, ST_GMM_DEREGISTERED);
+ break;
+ */
+ }
+}
+
+static struct osmo_fsm_state gmm_fsm_states[] = {
+ [ST_GMM_DEREGISTERED] = {
+ .in_event_mask =
+ X(E_GMM_COMMON_PROC_INIT_REQ) |
+ X(E_GMM_ATTACH_SUCCESS),
+ .out_state_mask = X(ST_GMM_COMMON_PROC_INIT),
+ .name = "Deregistered",
+ .action = st_gmm_deregistered,
+ },
+ [ST_GMM_COMMON_PROC_INIT] = {
+ .in_event_mask =
+ /* X(E_GMM_LOWER_LAYER_FAILED) | */
+ /* X(E_GMM_COMMON_PROC_FAILED) | */
+ X(E_GMM_COMMON_PROC_SUCCESS) |
+ X(E_GMM_ATTACH_SUCCESS),
+ .out_state_mask =
+ X(ST_GMM_DEREGISTERED) |
+ X(ST_GMM_REGISTERED_NORMAL),
+ .name = "CommonProcedureInitiated",
+ .action = st_gmm_common_proc_init,
+ },
+ [ST_GMM_REGISTERED_NORMAL] = {
+ .in_event_mask =
+ X(E_GMM_COMMON_PROC_INIT_REQ) |
+ /* X(E_GMM_NET_INIT_DETACH_REQ) | */
+ /* X(E_GMM_MS_INIT_DETACH_REQ) | */
+ X(E_GMM_SUSPEND),
+ .out_state_mask =
+ X(ST_GMM_DEREGISTERED) |
+ X(ST_GMM_COMMON_PROC_INIT) |
+ X(ST_GMM_DEREGISTERED_INIT) |
+ X(ST_GMM_REGISTERED_SUSPENDED),
+ .name = "Registered.NORMAL",
+ .action = st_gmm_registered_normal,
+ },
+ [ST_GMM_REGISTERED_SUSPENDED] = {
+ .in_event_mask = X(E_GMM_RESUME),
+ .out_state_mask =
+ X(ST_GMM_DEREGISTERED) |
+ X(ST_GMM_REGISTERED_NORMAL),
+ .name = "Registered.SUSPENDED",
+ .action = st_gmm_registered_suspended,
+ },
+ [ST_GMM_DEREGISTERED_INIT] = {
+ .in_event_mask = 0
+ /* X(E_GMM_DETACH_ACCEPTED) | */
+ /* X(E_GMM_LOWER_LAYER_FAILED) */,
+ .out_state_mask = X(ST_GMM_DEREGISTERED),
+ .name = "DeregisteredInitiated",
+ .action = st_gmm_deregistered_init,
+ },
+};
+
+const struct value_string gmm_fsm_event_names[] = {
+ OSMO_VALUE_STRING(E_GMM_COMMON_PROC_INIT_REQ),
+ /* OSMO_VALUE_STRING(E_GMM_COMMON_PROC_FAILED), */
+ /* OSMO_VALUE_STRING(E_GMM_LOWER_LAYER_FAILED), */
+ OSMO_VALUE_STRING(E_GMM_COMMON_PROC_SUCCESS),
+ OSMO_VALUE_STRING(E_GMM_ATTACH_SUCCESS),
+ /* OSMO_VALUE_STRING(E_GMM_NET_INIT_DETACH_REQ), */
+ /* OSMO_VALUE_STRING(E_GMM_MS_INIT_DETACH_REQ), */
+ /* OSMO_VALUE_STRING(E_GMM_DETACH_ACCEPTED), */
+ OSMO_VALUE_STRING(E_GMM_SUSPEND),
+ OSMO_VALUE_STRING(E_GMM_CLEANUP),
+ { 0, NULL }
+};
+
+void gmm_fsm_allstate_action(struct osmo_fsm_inst *fi, uint32_t event, void *data) {
+ switch (event) {
+ case E_GMM_CLEANUP:
+ switch (fi->state) {
+ case ST_GMM_DEREGISTERED:
+ break;
+ default:
+ gmm_fsm_state_chg(fi, ST_GMM_DEREGISTERED);
+ break;
+ }
+ }
+}
+
+int gmm_fsm_timer_cb(struct osmo_fsm_inst *fi)
+{
+ return 0;
+}
+
+struct osmo_fsm gmm_fsm = {
+ .name = "GMM",
+ .states = gmm_fsm_states,
+ .num_states = ARRAY_SIZE(gmm_fsm_states),
+ .event_names = gmm_fsm_event_names,
+ .allstate_event_mask = X(E_GMM_CLEANUP),
+ .allstate_action = gmm_fsm_allstate_action,
+ .log_subsys = DMM,
+ .timer_cb = gmm_fsm_timer_cb,
+};
+
+static __attribute__((constructor)) void gmm_fsm_init(void)
+{
+ osmo_fsm_register(&gmm_fsm);
+}
diff --git a/src/sgsn/gprs_sgsn.c b/src/sgsn/gprs_sgsn.c
index 387c0d5a..1c23d06a 100644
--- a/src/sgsn/gprs_sgsn.c
+++ b/src/sgsn/gprs_sgsn.c
@@ -44,6 +44,7 @@
#include <osmocom/sgsn/gprs_gmm_attach.h>
#include <osmocom/sgsn/gprs_mm_state_gb_fsm.h>
#include <osmocom/sgsn/gprs_mm_state_iu_fsm.h>
+#include <osmocom/sgsn/gprs_gmm_fsm.h>
#include <osmocom/sgsn/gprs_llc.h>
#include <pdp.h>
@@ -234,7 +235,6 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_alloc(uint32_t rate_ctr_id)
if (!ctx)
return NULL;
- ctx->gmm_state = GMM_DEREGISTERED;
ctx->auth_triplet.key_seq = GSM_KEY_SEQ_INVAL;
ctx->ctrg = rate_ctr_group_alloc(ctx, &mmctx_ctrg_desc, rate_ctr_id);
if (!ctx->ctrg) {
@@ -242,6 +242,7 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_alloc(uint32_t rate_ctr_id)
talloc_free(ctx);
return NULL;
}
+ ctx->gmm_fsm = osmo_fsm_inst_alloc(&gmm_fsm, ctx, ctx, LOGL_DEBUG, "gmm_fsm");
ctx->gmm_att_req.fsm = osmo_fsm_inst_alloc(&gmm_attach_req_fsm, ctx, ctx, LOGL_DEBUG, "gb_gmm_req");
INIT_LLIST_HEAD(&ctx->pdp_list);
@@ -368,6 +369,8 @@ void sgsn_mm_ctx_cleanup_free(struct sgsn_mm_ctx *mm)
osmo_fsm_inst_free(mm->gb.mm_state_fsm);
if (mm->iu.mm_state_fsm)
osmo_fsm_inst_free(mm->iu.mm_state_fsm);
+ if (mm->gmm_fsm)
+ osmo_fsm_inst_free(mm->gmm_fsm);
sgsn_mm_ctx_free(mm);
mm = NULL;
@@ -736,7 +739,7 @@ void sgsn_ggsn_ctx_drop_pdp(struct sgsn_pdp_ctx *pctx)
{
/* the MM context can be deleted while the GGSN is not reachable or
* if has been crashed. */
- if (pctx->mm && pctx->mm->gmm_state == GMM_REGISTERED_NORMAL) {
+ if (pctx->mm && pctx->mm->gmm_fsm->state == ST_GMM_REGISTERED_NORMAL) {
gsm48_tx_gsm_deact_pdp_req(pctx, GSM_CAUSE_NET_FAIL, true);
sgsn_ggsn_ctx_remove_pdp(pctx->ggsn, pctx);
} else {
diff --git a/src/sgsn/sgsn_libgtp.c b/src/sgsn/sgsn_libgtp.c
index 5e3f48f3..f6d7a690 100644
--- a/src/sgsn/sgsn_libgtp.c
+++ b/src/sgsn/sgsn_libgtp.c
@@ -51,6 +51,7 @@
#include <osmocom/sgsn/gprs_subscriber.h>
#include <osmocom/sgsn/gprs_sndcp.h>
#include <osmocom/sgsn/gprs_ranap.h>
+#include <osmocom/sgsn/gprs_gmm_fsm.h>
#include <gtp.h>
#include <pdp.h>
@@ -655,8 +656,8 @@ static int cb_data_ind(struct pdp_t *lib, void *packet, unsigned int len)
msgb_bvci(msg) = mm->gb.bvci;
msgb_nsei(msg) = mm->gb.nsei;
- switch (mm->gmm_state) {
- case GMM_REGISTERED_SUSPENDED:
+ switch (mm->gmm_fsm->state) {
+ case ST_GMM_REGISTERED_SUSPENDED:
/* initiate PS PAGING procedure */
memset(&pinfo, 0, sizeof(pinfo));
pinfo.mode = BSSGP_PAGING_PS;
@@ -670,11 +671,11 @@ static int cb_data_ind(struct pdp_t *lib, void *packet, unsigned int len)
rate_ctr_inc(&mm->ctrg->ctr[GMM_CTR_PAGING_PS]);
/* FIXME: queue the packet we received from GTP */
break;
- case GMM_REGISTERED_NORMAL:
+ case ST_GMM_REGISTERED_NORMAL:
break;
default:
LOGP(DGPRS, LOGL_ERROR, "GTP DATA IND for TLLI %08X in state "
- "%u\n", mm->gb.tlli, mm->gmm_state);
+ "%s\n", mm->gb.tlli, osmo_fsm_inst_state_name(mm->gmm_fsm));
msgb_free(msg);
return -1;
}
diff --git a/src/sgsn/sgsn_vty.c b/src/sgsn/sgsn_vty.c
index 184ece76..9200822e 100644
--- a/src/sgsn/sgsn_vty.c
+++ b/src/sgsn/sgsn_vty.c
@@ -476,15 +476,6 @@ DEFUN(cfg_apn_imsi_ggsn, cfg_apn_imsi_ggsn_cmd,
return add_apn_ggsn_mapping(vty, argv[0], argv[1], atoi(argv[2]));
}
-const struct value_string gprs_mm_st_strs[] = {
- { GMM_DEREGISTERED, "DEREGISTERED" },
- { GMM_COMMON_PROC_INIT, "COMMON PROCEDURE (INIT)" },
- { GMM_REGISTERED_NORMAL, "REGISTERED (NORMAL)" },
- { GMM_REGISTERED_SUSPENDED, "REGISTERED (SUSPENDED)" },
- { GMM_DEREGISTERED_INIT, "DEREGISTERED (INIT)" },
- { 0, NULL }
-};
-
char *sgsn_gtp_ntoa(struct ul16_t *ul)
{
struct in_addr ia;
@@ -546,7 +537,7 @@ static void vty_dump_mmctx(struct vty *vty, const char *pfx,
vty_out(vty, "%s MSISDN: %s, TLLI: %08x%s HLR: %s",
pfx, mm->msisdn, id, mm->hlr, VTY_NEWLINE);
vty_out(vty, "%s GMM State: %s, Routeing Area: %s, Cell ID: %u%s",
- pfx, get_value_string(gprs_mm_st_strs, mm->gmm_state),
+ pfx, osmo_fsm_inst_state_name(mm->gmm_fsm),
osmo_rai_name(&mm->ra), mm->gb.cell_id, VTY_NEWLINE);
vty_out(vty, "%s MM State: %s, RAN Type: %s%s", pfx, mm_state_name,
get_value_string(sgsn_ran_type_names, mm->ran_type), VTY_NEWLINE);
diff --git a/tests/sgsn/Makefile.am b/tests/sgsn/Makefile.am
index 7ba70eb6..9afe0f70 100644
--- a/tests/sgsn/Makefile.am
+++ b/tests/sgsn/Makefile.am
@@ -48,6 +48,7 @@ sgsn_test_LDADD = \
$(top_builddir)/src/sgsn/gprs_sndcp.o \
$(top_builddir)/src/sgsn/gprs_gmm_attach.o \
$(top_builddir)/src/sgsn/gprs_gmm.o \
+ $(top_builddir)/src/sgsn/gprs_gmm_fsm.o \
$(top_builddir)/src/sgsn/gprs_mm_state_gb_fsm.o \
$(top_builddir)/src/sgsn/gprs_mm_state_iu_fsm.o \
$(top_builddir)/src/sgsn/gprs_sgsn.o \
diff --git a/tests/sgsn/sgsn_test.c b/tests/sgsn/sgsn_test.c
index cc25d47f..7399573f 100644
--- a/tests/sgsn/sgsn_test.c
+++ b/tests/sgsn/sgsn_test.c
@@ -28,6 +28,7 @@
#include <osmocom/gsupclient/gsup_client.h>
#include <osmocom/sgsn/gprs_utils.h>
#include <osmocom/sgsn/gprs_gb_parse.h>
+#include <osmocom/sgsn/gprs_gmm_fsm.h>
#include <osmocom/gprs/gprs_bssgp.h>
@@ -192,7 +193,6 @@ static struct sgsn_mm_ctx *alloc_mm_ctx(uint32_t tlli, struct gprs_ra_id *raid)
lle = gprs_lle_get_or_create(tlli, 3);
ctx = sgsn_mm_ctx_alloc_gb(tlli, raid);
- ctx->gmm_state = GMM_REGISTERED_NORMAL;
ctx->gb.llme = lle->llme;
ictx = sgsn_mm_ctx_by_tlli(tlli, raid);
@@ -1286,7 +1286,7 @@ static void test_gmm_cancel(void)
ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
OSMO_ASSERT(ctx != NULL);
- OSMO_ASSERT(ctx->gmm_state == GMM_COMMON_PROC_INIT);
+ OSMO_ASSERT(ctx->gmm_fsm->state == ST_GMM_COMMON_PROC_INIT);
/* we expect an identity request (IMEI) */
OSMO_ASSERT(sgsn_tx_counter == 1);
@@ -1306,7 +1306,7 @@ static void test_gmm_cancel(void)
* authorization */
OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
- OSMO_ASSERT(ctx->gmm_state == GMM_COMMON_PROC_INIT);
+ OSMO_ASSERT(ctx->gmm_fsm->state == ST_GMM_COMMON_PROC_INIT);
/* we expect an attach accept/reject */
OSMO_ASSERT(sgsn_tx_counter == 1);
@@ -1320,7 +1320,7 @@ static void test_gmm_cancel(void)
send_0408_message(ctx->gb.llme, foreign_tlli, &raid,
attach_compl, ARRAY_SIZE(attach_compl));
- OSMO_ASSERT(ctx->gmm_state == GMM_REGISTERED_NORMAL);
+ OSMO_ASSERT(ctx->gmm_fsm->state == ST_GMM_REGISTERED_NORMAL);
/* we don't expect a response */
OSMO_ASSERT(sgsn_tx_counter == 0);