Change in ...osmo-sgsn[master]: Introduce FSM mm_state_gb_fsm

pespin gerrit-no-reply at lists.osmocom.org
Fri Aug 30 16:33:46 UTC 2019


pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-sgsn/+/15353


Change subject: Introduce FSM mm_state_gb_fsm
......................................................................

Introduce FSM mm_state_gb_fsm

Implement TS 23.060 6.1.1 Mobility Management States (A/Gb mode) using
osmocom FSM and drop old implementation.
Most of the logic on each state is still kept in gprs_gmm.c, will be
inserted into the FSM later.

Change-Id: I04004423e993107374d5a3549b8a93ac169251dd
---
M include/osmocom/sgsn/Makefile.am
M include/osmocom/sgsn/gprs_gmm.h
A include/osmocom/sgsn/gprs_mm_state_gb_fsm.h
M include/osmocom/sgsn/gprs_sgsn.h
M src/gprs/Makefile.am
M src/gprs/gprs_gb.c
M src/gprs/gprs_gmm.c
A src/gprs/gprs_mm_state_gb_fsm.c
M src/gprs/gprs_sgsn.c
M tests/sgsn/Makefile.am
10 files changed, 154 insertions(+), 125 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-sgsn refs/changes/53/15353/1

diff --git a/include/osmocom/sgsn/Makefile.am b/include/osmocom/sgsn/Makefile.am
index b91c9f1..d6ee445 100644
--- a/include/osmocom/sgsn/Makefile.am
+++ b/include/osmocom/sgsn/Makefile.am
@@ -7,6 +7,7 @@
 	gprs_gb_parse.h \
 	gprs_gmm.h \
 	gprs_gmm_attach.h \
+	gprs_mm_state_gb_fsm.h \
 	gprs_llc.h \
 	gprs_llc_xid.h \
 	gprs_ranap.h \
diff --git a/include/osmocom/sgsn/gprs_gmm.h b/include/osmocom/sgsn/gprs_gmm.h
index 6c72cda..2fa12e5 100644
--- a/include/osmocom/sgsn/gprs_gmm.h
+++ b/include/osmocom/sgsn/gprs_gmm.h
@@ -50,8 +50,6 @@
 void pdp_ctx_detach_mm_ctx(struct sgsn_pdp_ctx *pdp);
 
 void mmctx_set_pmm_state(struct sgsn_mm_ctx *ctx, enum gprs_mm_state_iu state);
-void mmctx_state_timer_start(struct sgsn_mm_ctx *mm, unsigned int T);
-void mmctx_set_mm_state(struct sgsn_mm_ctx *ctx, enum gprs_mm_state_gb state);
 
 void msgid2mmctx(struct sgsn_mm_ctx *mm, const struct msgb *msg);
 #endif /* _GPRS_GMM_H */
diff --git a/include/osmocom/sgsn/gprs_mm_state_gb_fsm.h b/include/osmocom/sgsn/gprs_mm_state_gb_fsm.h
new file mode 100644
index 0000000..e69e1e1
--- /dev/null
+++ b/include/osmocom/sgsn/gprs_mm_state_gb_fsm.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <osmocom/core/fsm.h>
+
+struct sgsn_mm_ctx;
+
+
+/* TS 23.060 6.1.1 Mobility Management States (A/Gb mode) */
+enum mm_state_gb_fsm_states {
+	ST_MM_IDLE,
+	ST_MM_READY,
+	ST_MM_STANDBY
+};
+
+enum mm_state_gb_fsm_events {
+	E_MM_GPRS_ATTACH,
+	/* E_GPRS_DETACH, TODO: not used */
+	E_MM_PDU_RECEPTION,
+	E_MM_IMPLICIT_DETACH, /* = E_MM_CANCEL_LOCATION */
+	E_MM_READY_TIMER_EXPIRY,
+	/* E_FORCE_TO_STANDBY, TODO: not used */
+	/* E_ABNSORMAL_RLC_CONDITION, TODO: not used */
+	E_MM_RA_UPDATE,
+};
+
+extern struct osmo_fsm mm_state_gb_fsm;
diff --git a/include/osmocom/sgsn/gprs_sgsn.h b/include/osmocom/sgsn/gprs_sgsn.h
index f64e07b..382019c 100644
--- a/include/osmocom/sgsn/gprs_sgsn.h
+++ b/include/osmocom/sgsn/gprs_sgsn.h
@@ -32,12 +32,6 @@
 	GMM_DEREGISTERED_INIT,		/* 4.1.3.3.1.4 */
 };
 
-/* TS 23.060 6.1.1 Mobility Management States (A/Gb mode) */
-enum gprs_mm_state_gb {
-	MM_IDLE,
-	MM_READY,
-	MM_STANDBY
-};
 /* TS 23.060 6.1.2 Mobility Management States (Iu mode) */
 enum gprs_mm_state_iu {
 	PMM_DETACHED,
@@ -161,10 +155,7 @@
 		uint32_t		tlli_new;
 
 		/* TS 23.060 6.1.1 Mobility Management States (A/Gb mode) */
-		enum gprs_mm_state_gb	mm_state;
-		/* timer for mm state. state=READY: T3314 (aka TS 23.060 "READY timer") */
-		struct osmo_timer_list  state_timer;
-		unsigned int		state_T;	/* Txxxx number but only used for mm_state */
+		struct osmo_fsm_inst	*mm_state_fsm;
 	} gb;
 	struct {
 		int			new_key;
diff --git a/src/gprs/Makefile.am b/src/gprs/Makefile.am
index 85ba906..94861e2 100644
--- a/src/gprs/Makefile.am
+++ b/src/gprs/Makefile.am
@@ -63,6 +63,7 @@
 	gprs_gb.c \
 	gprs_gmm_attach.c \
 	gprs_gmm.c \
+	gprs_mm_state_gb_fsm.c \
 	gprs_ranap.c \
 	gprs_sgsn.c \
 	gprs_sndcp.c \
diff --git a/src/gprs/gprs_gb.c b/src/gprs/gprs_gb.c
index 43af434..65342cf 100644
--- a/src/gprs/gprs_gb.c
+++ b/src/gprs/gprs_gb.c
@@ -28,25 +28,11 @@
 
 #include "bscconfig.h"
 
+#include <osmocom/sgsn/gprs_mm_state_gb_fsm.h>
 #include <osmocom/sgsn/gprs_sgsn.h>
 #include <osmocom/sgsn/gprs_gmm.h>
 #include <osmocom/sgsn/debug.h>
 
-/* Update the MM context state */
-static void gsm0408_gprs_notify_pdu_gb(struct sgsn_mm_ctx *mmctx)
-{
-	switch (mmctx->gb.mm_state) {
-	case MM_STANDBY:
-		mmctx_set_mm_state(mmctx, MM_READY);
-		break;
-	case MM_READY: /* RE-arm the timer upon receival of Gb PDUs */
-		mmctx_state_timer_start(mmctx, 3314);
-		break;
-	default:
-		break;
-	}
-}
-
 /* Main entry point for incoming 04.08 GPRS messages from Gb */
 int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme,
 			   bool drop_cipherable)
@@ -63,13 +49,11 @@
 		msgid2mmctx(mmctx, msg);
 		rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_PKTS_SIG_IN]);
 		mmctx->gb.llme = llme;
+		osmo_fsm_inst_dispatch(mmctx->gb.mm_state_fsm, E_MM_PDU_RECEPTION, NULL);
 	}
 
 	/* MMCTX can be NULL */
 
-	if (mmctx)
-		gsm0408_gprs_notify_pdu_gb(mmctx);
-
 	switch (pdisc) {
 	case GSM48_PDISC_MM_GPRS:
 		rc = gsm0408_rcv_gmm(mmctx, msg, llme, drop_cipherable);
diff --git a/src/gprs/gprs_gmm.c b/src/gprs/gprs_gmm.c
index 766d0f4..75d99fb 100644
--- a/src/gprs/gprs_gmm.c
+++ b/src/gprs/gprs_gmm.c
@@ -55,6 +55,7 @@
 #include <osmocom/sgsn/gprs_subscriber.h>
 #include <osmocom/sgsn/sgsn.h>
 #include <osmocom/sgsn/gprs_gmm_attach.h>
+#include <osmocom/sgsn/gprs_mm_state_gb_fsm.h>
 #include <osmocom/sgsn/signal.h>
 #include <osmocom/sgsn/gprs_sndcp.h>
 #include <osmocom/sgsn/gprs_ranap.h>
@@ -102,13 +103,6 @@
 	},
 };
 
-static const struct value_string gprs_mm_state_gb_names[] = {
-	OSMO_VALUE_STRING(MM_IDLE),
-	OSMO_VALUE_STRING(MM_READY),
-	OSMO_VALUE_STRING(MM_STANDBY),
-	{ 0, NULL }
-};
-
 static const struct value_string gprs_mm_state_iu_names[] = {
 	OSMO_VALUE_STRING(PMM_DETACHED),
 	OSMO_VALUE_STRING(PMM_CONNECTED),
@@ -130,56 +124,6 @@
 	}
 }
 
-static void mmctx_state_timer_cb(void *_mm)
-{
-	struct sgsn_mm_ctx *mm = _mm;
-
-	switch (mm->gb.state_T) {
-	case 3314:
-		switch (mm->gb.mm_state) {
-		case MM_READY:
-			LOGMMCTXP(LOGL_INFO, mm, "T3314 expired\n");
-			mmctx_set_mm_state(mm, MM_STANDBY);
-			break;
-		default:
-			LOGMMCTXP(LOGL_ERROR, mm, "T3314 expired in state %s != MM_READY\n",
-				  get_value_string(gprs_mm_state_gb_names, mm->gb.mm_state));
-			break;
-		}
-		break;
-	default:
-		LOGMMCTXP(LOGL_ERROR, mm, "state timer expired in unknown mode %u\n",
-			mm->gb.state_T);
-		break;
-	}
-}
-
-void mmctx_state_timer_start(struct sgsn_mm_ctx *mm, unsigned int T)
-{
-	unsigned long seconds;
-
-	if (mm->gb.state_T && mm->gb.state_T != T)
-		LOGMMCTXP(LOGL_ERROR, mm, "Attempting to start timer %u but %u is active!\n",
-			  T, mm->gb.state_T);
-
-	mm->gb.state_T = T;
-	mm->gb.state_timer.data = mm;
-	mm->gb.state_timer.cb = &mmctx_state_timer_cb;
-
-	seconds = osmo_tdef_get(sgsn->cfg.T_defs, T, OSMO_TDEF_S, -1);
-	osmo_timer_schedule(&mm->gb.state_timer, seconds, 0);
-}
-
-static void mmctx_state_timer_stop(struct sgsn_mm_ctx *mm, unsigned int T)
-{
-	if (mm->gb.state_T == T)
-		osmo_timer_del(&mm->gb.state_timer);
-	else
-		LOGMMCTXP(LOGL_ERROR, mm, "Attempting to stop timer %u but %u is active!\n",
-			  T, mm->gb.state_T);
-	mm->gb.state_T = 0;
-}
-
 void mmctx_set_pmm_state(struct sgsn_mm_ctx *ctx, enum gprs_mm_state_iu state)
 {
 	OSMO_ASSERT(ctx->ran_type == MM_CTX_T_UTRAN_Iu);
@@ -205,35 +149,6 @@
 	ctx->iu.mm_state = state;
 }
 
-void mmctx_set_mm_state(struct sgsn_mm_ctx *ctx, enum gprs_mm_state_gb state)
-{
-	OSMO_ASSERT(ctx->ran_type == MM_CTX_T_GERAN_Gb);
-
-	if (ctx->gb.mm_state == state)
-		return;
-
-	LOGMMCTXP(LOGL_INFO, ctx, "Changing MM state from %s to %s\n",
-		  get_value_string(gprs_mm_state_gb_names, ctx->gb.mm_state),
-		  get_value_string(gprs_mm_state_gb_names, state));
-
-	switch (state) {
-	case MM_READY:
-		/* on expiration, T3314 moves mm state back to MM_STANDBY */
-		mmctx_state_timer_start(ctx, 3314);
-		break;
-	case MM_IDLE:
-		if (ctx->gb.mm_state == MM_READY)
-			mmctx_state_timer_stop(ctx, 3314);
-		break;
-	case MM_STANDBY:
-		if (ctx->gb.mm_state == MM_READY)
-			mmctx_state_timer_stop(ctx, 3314);
-		break;
-	}
-
-	ctx->gb.mm_state = state;
-}
-
 /* Our implementation, should be kept in SGSN */
 
 static void mmctx_timer_cb(void *_mm);
@@ -342,7 +257,7 @@
 		mmctx_set_pmm_state(ctx, PMM_DETACHED);
 		break;
 	case MM_CTX_T_GERAN_Gb:
-		mmctx_set_mm_state(ctx, MM_IDLE);
+		osmo_fsm_inst_dispatch(ctx->gb.mm_state_fsm, E_MM_IMPLICIT_DETACH, NULL);
 		break;
 	}
 
@@ -2097,7 +2012,7 @@
 			gprs_llme_copy_key(mmctx, mmctx->gb.llme);
 			gprs_llgmm_assign(mmctx->gb.llme, TLLI_UNASSIGNED,
 					  mmctx->gb.tlli_new);
-			mmctx_set_mm_state(mmctx, MM_READY);
+			osmo_fsm_inst_dispatch(mmctx->gb.mm_state_fsm, E_MM_GPRS_ATTACH, NULL);
 			break;
 		}
 		rc = 0;
@@ -2126,7 +2041,7 @@
 			mmctx->gb.tlli = mmctx->gb.tlli_new;
 			gprs_llgmm_assign(mmctx->gb.llme, TLLI_UNASSIGNED,
 					  mmctx->gb.tlli_new);
-			mmctx_set_mm_state(mmctx, MM_READY);
+			osmo_fsm_inst_dispatch(mmctx->gb.mm_state_fsm, E_MM_RA_UPDATE, NULL);
 			break;
 		}
 		rc = 0;
diff --git a/src/gprs/gprs_mm_state_gb_fsm.c b/src/gprs/gprs_mm_state_gb_fsm.c
new file mode 100644
index 0000000..2056540
--- /dev/null
+++ b/src/gprs/gprs_mm_state_gb_fsm.c
@@ -0,0 +1,112 @@
+#include <osmocom/core/tdef.h>
+
+#include <osmocom/sgsn/gprs_mm_state_gb_fsm.h>
+
+#include <osmocom/sgsn/debug.h>
+#include <osmocom/sgsn/sgsn.h>
+
+#define X(s) (1 << (s))
+
+static const struct osmo_tdef_state_timeout mm_state_gb_fsm_timeouts[32] = {
+	[ST_MM_IDLE] = { },
+	[ST_MM_READY] = { .T=3314 },
+	[ST_MM_STANDBY] = { },
+};
+
+#define mm_state_gb_fsm_state_chg(fi, NEXT_STATE) \
+	osmo_tdef_fsm_inst_state_chg(fi, NEXT_STATE, mm_state_gb_fsm_timeouts, sgsn->cfg.T_defs, -1)
+
+static void st_mm_idle(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+	switch(event) {
+	case E_MM_GPRS_ATTACH:
+		mm_state_gb_fsm_state_chg(fi, ST_MM_READY);
+		break;
+	case E_MM_PDU_RECEPTION:
+		break;
+	}
+}
+
+static void st_mm_ready(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+	unsigned long t_secs;
+
+	switch(event) {
+	case E_MM_READY_TIMER_EXPIRY:
+	case E_MM_IMPLICIT_DETACH:
+		mm_state_gb_fsm_state_chg(fi, ST_MM_STANDBY);
+		break;
+	case E_MM_PDU_RECEPTION:
+		/* RE-arm the READY timer upon receival of Gb PDUs */
+		t_secs = osmo_tdef_get(sgsn->cfg.T_defs, 3314, OSMO_TDEF_S, -1);
+		osmo_timer_schedule(&fi->timer, t_secs, 0);
+		break;
+	case E_MM_RA_UPDATE:
+		break;
+	}
+}
+
+static void st_mm_standby(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+	switch(event) {
+	case E_MM_PDU_RECEPTION:
+		mm_state_gb_fsm_state_chg(fi, ST_MM_READY);
+		break;
+	}
+}
+
+static struct osmo_fsm_state mm_state_gb_fsm_states[] = {
+	[ST_MM_IDLE] = {
+		.in_event_mask = X(E_MM_GPRS_ATTACH) | X(E_MM_PDU_RECEPTION),
+		.out_state_mask = X(ST_MM_READY),
+		.name = "Idle",
+		.action = st_mm_idle,
+	},
+	[ST_MM_READY] = {
+		.in_event_mask = X(E_MM_READY_TIMER_EXPIRY) | X(E_MM_RA_UPDATE) | X(E_MM_IMPLICIT_DETACH) | X(E_MM_PDU_RECEPTION),
+		.out_state_mask = X(ST_MM_IDLE) | X(ST_MM_STANDBY),
+		.name = "Ready",
+		.action = st_mm_ready,
+	},
+	[ST_MM_STANDBY] = {
+		.in_event_mask = X(E_MM_PDU_RECEPTION),
+		.out_state_mask = X(ST_MM_IDLE) | X(ST_MM_READY),
+		.name = "Standby",
+		.action = st_mm_standby,
+	},
+};
+
+const struct value_string mm_state_gb_fsm_event_names[] = {
+	OSMO_VALUE_STRING(E_MM_GPRS_ATTACH),
+	OSMO_VALUE_STRING(E_MM_PDU_RECEPTION),
+	OSMO_VALUE_STRING(E_MM_IMPLICIT_DETACH),
+	OSMO_VALUE_STRING(E_MM_READY_TIMER_EXPIRY),
+	OSMO_VALUE_STRING(E_MM_RA_UPDATE),
+	{ 0, NULL }
+};
+
+int mm_state_gb_fsm_timer_cb(struct osmo_fsm_inst *fi)
+{
+	switch(fi->state) {
+	case ST_MM_READY:
+		/* timer for mm state. state=READY: T3314 (aka TS 23.060 "READY timer") */
+		osmo_fsm_inst_dispatch(fi, E_MM_READY_TIMER_EXPIRY, NULL);
+		break;
+	}
+
+	return 0;
+}
+
+struct osmo_fsm mm_state_gb_fsm = {
+	.name = "MM_STATE_Gb",
+	.states = mm_state_gb_fsm_states,
+	.num_states = ARRAY_SIZE(mm_state_gb_fsm_states),
+	.event_names = mm_state_gb_fsm_event_names,
+	.log_subsys = DMM,
+	.timer_cb = mm_state_gb_fsm_timer_cb,
+};
+
+static __attribute__((constructor)) void mm_state_gb_fsm_init(void)
+{
+	osmo_fsm_register(&mm_state_gb_fsm);
+}
diff --git a/src/gprs/gprs_sgsn.c b/src/gprs/gprs_sgsn.c
index 6acc66e..82855a6 100644
--- a/src/gprs/gprs_sgsn.c
+++ b/src/gprs/gprs_sgsn.c
@@ -42,6 +42,7 @@
 #include <osmocom/sgsn/gprs_utils.h>
 #include <osmocom/sgsn/signal.h>
 #include <osmocom/sgsn/gprs_gmm_attach.h>
+#include <osmocom/sgsn/gprs_mm_state_gb_fsm.h>
 #include <osmocom/sgsn/gprs_llc.h>
 
 #include <pdp.h>
@@ -243,6 +244,7 @@
 					 const struct gprs_ra_id *raid)
 {
 	struct sgsn_mm_ctx *ctx;
+	char buf[32];
 
 	ctx = sgsn_mm_ctx_alloc(tlli);
 	if (!ctx)
@@ -251,8 +253,9 @@
 	memcpy(&ctx->ra, raid, sizeof(ctx->ra));
 	ctx->ran_type = MM_CTX_T_GERAN_Gb;
 	ctx->gb.tlli = tlli;
-	ctx->gb.mm_state = MM_IDLE;
 	ctx->ciph_algo = sgsn->cfg.cipher;
+	snprintf(buf, sizeof(buf), "%" PRIu32, tlli);
+	ctx->gb.mm_state_fsm = osmo_fsm_inst_alloc(&mm_state_gb_fsm, ctx, ctx, LOGL_DEBUG, buf);
 
 	LOGMMCTXP(LOGL_DEBUG, ctx, "Allocated with %s cipher.\n",
 		  get_value_string(gprs_cipher_names, ctx->ciph_algo));
@@ -334,11 +337,6 @@
 		osmo_timer_del(&mm->timer);
 	}
 
-	if (osmo_timer_pending(&mm->gb.state_timer)) {
-		LOGMMCTXP(LOGL_INFO, mm, "Cancelling MM state timer %u\n", mm->gb.state_T);
-		osmo_timer_del(&mm->gb.state_timer);
-	}
-
 	memset(&sig_data, 0, sizeof(sig_data));
 	sig_data.mm = mm;
 	osmo_signal_dispatch(SS_SGSN, S_SGSN_MM_FREE, &sig_data);
@@ -353,6 +351,8 @@
 
 	if (mm->gmm_att_req.fsm)
 		gmm_att_req_free(mm);
+	if (mm->gb.mm_state_fsm)
+		osmo_fsm_inst_free(mm->gb.mm_state_fsm);
 
 	sgsn_mm_ctx_free(mm);
 	mm = NULL;
diff --git a/tests/sgsn/Makefile.am b/tests/sgsn/Makefile.am
index b035468..8a26d88 100644
--- a/tests/sgsn/Makefile.am
+++ b/tests/sgsn/Makefile.am
@@ -50,6 +50,7 @@
 	$(top_builddir)/src/gprs/gprs_sndcp.o \
 	$(top_builddir)/src/gprs/gprs_gmm_attach.o \
 	$(top_builddir)/src/gprs/gprs_gmm.o \
+	$(top_builddir)/src/gprs/gprs_mm_state_gb_fsm.o \
 	$(top_builddir)/src/gprs/gprs_sgsn.o \
 	$(top_builddir)/src/gprs/sgsn_vty.o \
 	$(top_builddir)/src/gprs/sgsn_libgtp.o \

-- 
To view, visit https://gerrit.osmocom.org/c/osmo-sgsn/+/15353
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-sgsn
Gerrit-Branch: master
Gerrit-Change-Id: I04004423e993107374d5a3549b8a93ac169251dd
Gerrit-Change-Number: 15353
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin at sysmocom.de>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20190830/5348ff0c/attachment-0001.html>


More information about the gerrit-log mailing list