aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 0ab00fe46..9ddc2bc97 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 000000000..fd5b4bff9
--- /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 20e0e06a6..0a52a7df5 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 a8da94308..4402c9c6c 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 399f7bf89..3317a0929 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 000000000..fac06f27e
--- /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 387c0d5a1..1c23d06a4 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 5e3f48f3f..f6d7a690f 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 184ece761..9200822e3 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 7ba70eb6a..9afe0f704 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 cc25d47ff..7399573fc 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);