diff options
author | Pau Espin Pedrol <pespin@sysmocom.de> | 2019-08-30 17:06:36 +0200 |
---|---|---|
committer | Pau Espin Pedrol <pespin@sysmocom.de> | 2019-09-02 11:44:58 +0200 |
commit | ccd1252bd76169439cb66f3a50e4575e0f03ec0b (patch) | |
tree | fe1bb807c01383609b0d74ad1ac25759952d8d69 | |
parent | 02514bc592923b9c082942d64fcf06db2e4bfd44 (diff) |
Introduce FSM mm_state_iu_fsm
Implement TS 23.060 6.1.2 Mobility Management States (Iu 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: I4c9cf8c27194817c56e8949af0205e1cc14af317
-rw-r--r-- | include/osmocom/sgsn/Makefile.am | 1 | ||||
-rw-r--r-- | include/osmocom/sgsn/gprs_gmm.h | 2 | ||||
-rw-r--r-- | include/osmocom/sgsn/gprs_mm_state_iu_fsm.h | 24 | ||||
-rw-r--r-- | include/osmocom/sgsn/gprs_sgsn.h | 9 | ||||
-rw-r--r-- | src/gprs/Makefile.am | 1 | ||||
-rw-r--r-- | src/gprs/gprs_gmm.c | 55 | ||||
-rw-r--r-- | src/gprs/gprs_mm_state_iu_fsm.c | 121 | ||||
-rw-r--r-- | src/gprs/gprs_ranap.c | 8 | ||||
-rw-r--r-- | src/gprs/gprs_sgsn.c | 8 | ||||
-rw-r--r-- | tests/sgsn/Makefile.am | 1 |
10 files changed, 165 insertions, 65 deletions
diff --git a/include/osmocom/sgsn/Makefile.am b/include/osmocom/sgsn/Makefile.am index d6ee4451e..0ab00fe46 100644 --- a/include/osmocom/sgsn/Makefile.am +++ b/include/osmocom/sgsn/Makefile.am @@ -8,6 +8,7 @@ noinst_HEADERS = \ gprs_gmm.h \ gprs_gmm_attach.h \ gprs_mm_state_gb_fsm.h \ + gprs_mm_state_iu_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 2fa12e597..982cd93d6 100644 --- a/include/osmocom/sgsn/gprs_gmm.h +++ b/include/osmocom/sgsn/gprs_gmm.h @@ -49,7 +49,5 @@ void extract_subscr_hlr(struct sgsn_mm_ctx *ctx); 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 msgid2mmctx(struct sgsn_mm_ctx *mm, const struct msgb *msg); #endif /* _GPRS_GMM_H */ diff --git a/include/osmocom/sgsn/gprs_mm_state_iu_fsm.h b/include/osmocom/sgsn/gprs_mm_state_iu_fsm.h new file mode 100644 index 000000000..7f02bcc45 --- /dev/null +++ b/include/osmocom/sgsn/gprs_mm_state_iu_fsm.h @@ -0,0 +1,24 @@ +#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_iu_fsm_states { + ST_PMM_DETACHED, + ST_PMM_CONNECTED, + ST_PMM_IDLE +}; + +enum mm_state_iu_fsm_events { + E_PMM_PS_ATTACH, + /* E_PS_DETACH, TODO: not used */ + E_PMM_PS_CONN_RELEASE, + E_PMM_PS_CONN_ESTABLISH, + E_PMM_IMPLICIT_DETACH, /* = E_PS_ATTACH_REJECT, E_RAU_REJECT */ + E_PMM_RA_UPDATE, /* = Serving RNC relocation */ +}; + +extern struct osmo_fsm mm_state_iu_fsm; diff --git a/include/osmocom/sgsn/gprs_sgsn.h b/include/osmocom/sgsn/gprs_sgsn.h index 382019c2d..8f16c5b30 100644 --- a/include/osmocom/sgsn/gprs_sgsn.h +++ b/include/osmocom/sgsn/gprs_sgsn.h @@ -32,13 +32,6 @@ enum gprs_gmm_state { GMM_DEREGISTERED_INIT, /* 4.1.3.3.1.4 */ }; -/* TS 23.060 6.1.2 Mobility Management States (Iu mode) */ -enum gprs_mm_state_iu { - PMM_DETACHED, - PMM_CONNECTED, - PMM_IDLE -}; - enum gprs_mm_ctr { GMM_CTR_PKTS_SIG_IN, GMM_CTR_PKTS_SIG_OUT, @@ -171,7 +164,7 @@ struct sgsn_mm_ctx { struct ranap_ue_conn_ctx *ue_ctx; struct service_info service; /* TS 23.060 6.1.2 Mobility Management States (Iu mode) */ - enum gprs_mm_state_iu mm_state; + struct osmo_fsm_inst *mm_state_fsm; } iu; struct { struct osmo_fsm_inst *fsm; diff --git a/src/gprs/Makefile.am b/src/gprs/Makefile.am index 94861e297..05d5b4c3c 100644 --- a/src/gprs/Makefile.am +++ b/src/gprs/Makefile.am @@ -64,6 +64,7 @@ osmo_sgsn_SOURCES = \ gprs_gmm_attach.c \ gprs_gmm.c \ gprs_mm_state_gb_fsm.c \ + gprs_mm_state_iu_fsm.c \ gprs_ranap.c \ gprs_sgsn.c \ gprs_sndcp.c \ diff --git a/src/gprs/gprs_gmm.c b/src/gprs/gprs_gmm.c index 81f42737e..edb7eea1e 100644 --- a/src/gprs/gprs_gmm.c +++ b/src/gprs/gprs_gmm.c @@ -56,6 +56,7 @@ #include <osmocom/sgsn/sgsn.h> #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/signal.h> #include <osmocom/sgsn/gprs_sndcp.h> #include <osmocom/sgsn/gprs_ranap.h> @@ -103,52 +104,6 @@ static const struct tlv_definition gsm48_sm_att_tlvdef = { }, }; -static const struct value_string gprs_mm_state_iu_names[] = { - OSMO_VALUE_STRING(PMM_DETACHED), - OSMO_VALUE_STRING(PMM_CONNECTED), - OSMO_VALUE_STRING(PMM_IDLE), - { 0, NULL } -}; - -static void mmctx_change_gtpu_endpoints_to_sgsn(struct sgsn_mm_ctx *mm_ctx) -{ - char buf[INET_ADDRSTRLEN]; - struct sgsn_pdp_ctx *pdp; - llist_for_each_entry(pdp, &mm_ctx->pdp_list, list) { - LOGMMCTXP(LOGL_INFO, mm_ctx, "Changing GTP-U endpoints %s -> %s\n", - sgsn_gtp_ntoa(&pdp->lib->gsnlu), - inet_ntop(AF_INET, &sgsn->cfg.gtp_listenaddr.sin_addr, buf, sizeof(buf))); - sgsn_pdp_upd_gtp_u(pdp, - &sgsn->cfg.gtp_listenaddr.sin_addr, - sizeof(sgsn->cfg.gtp_listenaddr.sin_addr)); - } -} - -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); - - if (ctx->iu.mm_state == state) - return; - - LOGMMCTXP(LOGL_INFO, ctx, "Changing PMM state from %s to %s\n", - get_value_string(gprs_mm_state_iu_names, ctx->iu.mm_state), - get_value_string(gprs_mm_state_iu_names, state)); - - switch (state) { - case PMM_IDLE: - /* TODO: start RA Upd timer */ - mmctx_change_gtpu_endpoints_to_sgsn(ctx); - break; - case PMM_CONNECTED: - break; - case PMM_DETACHED: - break; - } - - ctx->iu.mm_state = state; -} - /* Our implementation, should be kept in SGSN */ static void mmctx_timer_cb(void *_mm); @@ -260,7 +215,7 @@ static void mm_ctx_cleanup_free(struct sgsn_mm_ctx *ctx, const char *log_text) switch(ctx->ran_type) { case MM_CTX_T_UTRAN_Iu: - mmctx_set_pmm_state(ctx, PMM_DETACHED); + osmo_fsm_inst_dispatch(ctx->iu.mm_state_fsm, E_PMM_IMPLICIT_DETACH, NULL); break; case MM_CTX_T_GERAN_Gb: osmo_fsm_inst_dispatch(ctx->gb.mm_state_fsm, E_MM_IMPLICIT_DETACH, NULL); @@ -1019,7 +974,7 @@ int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx) #ifdef BUILD_IU case GSM48_MT_GMM_SERVICE_REQ: ctx->pending_req = 0; - mmctx_set_pmm_state(ctx, PMM_CONNECTED); + osmo_fsm_inst_dispatch(ctx->iu.mm_state_fsm, E_PMM_PS_ATTACH, NULL); rc = gsm48_tx_gmm_service_ack(ctx); if (ctx->iu.service.type != GPRS_SERVICE_T_SIGNALLING) @@ -2014,7 +1969,7 @@ int gsm0408_rcv_gmm(struct sgsn_mm_ctx *mmctx, struct msgb *msg, mmctx->gmm_state = GMM_REGISTERED_NORMAL; switch(mmctx->ran_type) { case MM_CTX_T_UTRAN_Iu: - mmctx_set_pmm_state(mmctx, PMM_CONNECTED); + osmo_fsm_inst_dispatch(mmctx->iu.mm_state_fsm, E_PMM_PS_ATTACH, NULL); break; case MM_CTX_T_GERAN_Gb: /* Unassign the old TLLI */ @@ -2044,7 +1999,7 @@ int gsm0408_rcv_gmm(struct sgsn_mm_ctx *mmctx, struct msgb *msg, mmctx->gmm_state = GMM_REGISTERED_NORMAL; switch(mmctx->ran_type) { case MM_CTX_T_UTRAN_Iu: - mmctx_set_pmm_state(mmctx, PMM_CONNECTED); + osmo_fsm_inst_dispatch(mmctx->iu.mm_state_fsm, E_PMM_RA_UPDATE, NULL); break; case MM_CTX_T_GERAN_Gb: /* Unassign the old TLLI */ diff --git a/src/gprs/gprs_mm_state_iu_fsm.c b/src/gprs/gprs_mm_state_iu_fsm.c new file mode 100644 index 000000000..1ed5f56f1 --- /dev/null +++ b/src/gprs/gprs_mm_state_iu_fsm.c @@ -0,0 +1,121 @@ +#include <arpa/inet.h> + +#include <osmocom/core/tdef.h> + +#include <osmocom/sgsn/gprs_mm_state_iu_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_iu_fsm_timeouts[32] = { + [ST_PMM_DETACHED] = { }, + [ST_PMM_CONNECTED] = { }, + [ST_PMM_IDLE] = { }, +}; + +#define mm_state_iu_fsm_state_chg(fi, NEXT_STATE) \ + osmo_tdef_fsm_inst_state_chg(fi, NEXT_STATE, mm_state_iu_fsm_timeouts, sgsn->cfg.T_defs, -1) + +static void mmctx_change_gtpu_endpoints_to_sgsn(struct sgsn_mm_ctx *mm_ctx) +{ + char buf[INET_ADDRSTRLEN]; + struct sgsn_pdp_ctx *pdp; + llist_for_each_entry(pdp, &mm_ctx->pdp_list, list) { + LOGMMCTXP(LOGL_INFO, mm_ctx, "Changing GTP-U endpoints %s -> %s\n", + sgsn_gtp_ntoa(&pdp->lib->gsnlu), + inet_ntop(AF_INET, &sgsn->cfg.gtp_listenaddr.sin_addr, buf, sizeof(buf))); + sgsn_pdp_upd_gtp_u(pdp, + &sgsn->cfg.gtp_listenaddr.sin_addr, + sizeof(sgsn->cfg.gtp_listenaddr.sin_addr)); + } +} + +static void st_pmm_detached(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + switch(event) { + case E_PMM_PS_ATTACH: + mm_state_iu_fsm_state_chg(fi, ST_PMM_CONNECTED); + break; + case E_PMM_IMPLICIT_DETACH: + break; + } +} + +static void st_pmm_connected(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + switch(event) { + case E_PMM_PS_CONN_RELEASE: + mm_state_iu_fsm_state_chg(fi, ST_PMM_IDLE); + break; + case E_PMM_IMPLICIT_DETACH: + mm_state_iu_fsm_state_chg(fi, ST_PMM_DETACHED); + break; + case E_PMM_RA_UPDATE: + break; + } +} + +static void st_pmm_idle_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state) +{ + struct sgsn_mm_ctx *ctx = fi->priv; + + mmctx_change_gtpu_endpoints_to_sgsn(ctx); +} + +static void st_pmm_idle(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + switch(event) { + case E_PMM_PS_CONN_ESTABLISH: + mm_state_iu_fsm_state_chg(fi, ST_PMM_CONNECTED); + break; + case E_PMM_IMPLICIT_DETACH: + mm_state_iu_fsm_state_chg(fi, ST_PMM_DETACHED); + break; + } +} + +static struct osmo_fsm_state mm_state_iu_fsm_states[] = { + [ST_PMM_DETACHED] = { + .in_event_mask = X(E_PMM_PS_ATTACH) | X(E_PMM_IMPLICIT_DETACH), + .out_state_mask = X(ST_PMM_CONNECTED), + .name = "Detached", + .action = st_pmm_detached, + }, + [ST_PMM_CONNECTED] = { + .in_event_mask = X(E_PMM_PS_CONN_RELEASE) | X(E_PMM_RA_UPDATE) | X(E_PMM_IMPLICIT_DETACH), + .out_state_mask = X(ST_PMM_DETACHED) | X(ST_PMM_IDLE), + .name = "Connected", + .action = st_pmm_connected, + }, + [ST_PMM_IDLE] = { + .in_event_mask = X(E_PMM_IMPLICIT_DETACH) | X(E_PMM_PS_CONN_ESTABLISH), + .out_state_mask = X(ST_PMM_DETACHED) | X(ST_PMM_CONNECTED), + .name = "Idle", + .onenter = st_pmm_idle_on_enter, + .action = st_pmm_idle, + }, +}; + +const struct value_string mm_state_iu_fsm_event_names[] = { + OSMO_VALUE_STRING(E_PMM_PS_ATTACH), + OSMO_VALUE_STRING(E_PMM_PS_CONN_RELEASE), + OSMO_VALUE_STRING(E_PMM_PS_CONN_ESTABLISH), + OSMO_VALUE_STRING(E_PMM_IMPLICIT_DETACH), + OSMO_VALUE_STRING(E_PMM_RA_UPDATE), + { 0, NULL } +}; + +struct osmo_fsm mm_state_iu_fsm = { + .name = "MM_STATE_Iu", + .states = mm_state_iu_fsm_states, + .num_states = ARRAY_SIZE(mm_state_iu_fsm_states), + .event_names = mm_state_iu_fsm_event_names, + .log_subsys = DMM, +}; + +static __attribute__((constructor)) void mm_state_iu_fsm_init(void) +{ + osmo_fsm_register(&mm_state_iu_fsm); +} diff --git a/src/gprs/gprs_ranap.c b/src/gprs/gprs_ranap.c index 836937b6e..027b6665a 100644 --- a/src/gprs/gprs_ranap.c +++ b/src/gprs/gprs_ranap.c @@ -36,6 +36,7 @@ #include <osmocom/sgsn/sgsn.h> #include <osmocom/sgsn/gprs_ranap.h> #include <osmocom/sgsn/gprs_gmm_attach.h> +#include <osmocom/sgsn/gprs_mm_state_iu_fsm.h> /* Send RAB activation requests for all PDP contexts */ void activate_pdp_rabs(struct sgsn_mm_ctx *ctx) @@ -134,12 +135,11 @@ int sgsn_ranap_iu_event(struct ranap_ue_conn_ctx *ctx, enum ranap_iu_event_type /* fall thru */ case RANAP_IU_EVENT_LINK_INVALIDATED: /* Clean up ranap_ue_conn_ctx here */ - if (mm) + if (mm) { LOGMMCTXP(LOGL_INFO, mm, "IU release for imsi %s\n", mm->imsi); - else + osmo_fsm_inst_dispatch(mm->iu.mm_state_fsm, E_PMM_PS_CONN_RELEASE, NULL); + } else LOGIUP(ctx, LOGL_INFO, "IU release\n"); - if (mm && mm->iu.mm_state == PMM_CONNECTED) - mmctx_set_pmm_state(mm, PMM_IDLE); rc = 0; break; case RANAP_IU_EVENT_SECURITY_MODE_COMPLETE: diff --git a/src/gprs/gprs_sgsn.c b/src/gprs/gprs_sgsn.c index 82855a6eb..23347073b 100644 --- a/src/gprs/gprs_sgsn.c +++ b/src/gprs/gprs_sgsn.c @@ -43,6 +43,7 @@ #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_mm_state_iu_fsm.h> #include <osmocom/sgsn/gprs_llc.h> #include <pdp.h> @@ -266,6 +267,7 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_alloc_gb(uint32_t tlli, struct sgsn_mm_ctx *sgsn_mm_ctx_alloc_iu(void *uectx) { #if BUILD_IU + char buf[32]; struct sgsn_mm_ctx *ctx; struct ranap_ue_conn_ctx *ue_ctx = uectx; @@ -279,7 +281,9 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_alloc_iu(void *uectx) ctx->iu.ue_ctx = ue_ctx; ctx->iu.ue_ctx->rab_assign_addr_enc = sgsn->cfg.iu.rab_assign_addr_enc; ctx->iu.new_key = 1; - ctx->iu.mm_state = PMM_DETACHED; + snprintf(buf, sizeof(buf), "%" PRIu32, ue_ctx->conn_id); + ctx->iu.mm_state_fsm = osmo_fsm_inst_alloc(&mm_state_iu_fsm, ctx, ctx, LOGL_DEBUG, buf); + return ctx; #else @@ -353,6 +357,8 @@ void sgsn_mm_ctx_cleanup_free(struct sgsn_mm_ctx *mm) gmm_att_req_free(mm); if (mm->gb.mm_state_fsm) osmo_fsm_inst_free(mm->gb.mm_state_fsm); + if (mm->iu.mm_state_fsm) + osmo_fsm_inst_free(mm->iu.mm_state_fsm); sgsn_mm_ctx_free(mm); mm = NULL; diff --git a/tests/sgsn/Makefile.am b/tests/sgsn/Makefile.am index 8a26d8840..47189e55c 100644 --- a/tests/sgsn/Makefile.am +++ b/tests/sgsn/Makefile.am @@ -51,6 +51,7 @@ sgsn_test_LDADD = \ $(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_mm_state_iu_fsm.o \ $(top_builddir)/src/gprs/gprs_sgsn.o \ $(top_builddir)/src/gprs/sgsn_vty.o \ $(top_builddir)/src/gprs/sgsn_libgtp.o \ |