gprs_gmm_fsm.c: Implement RAT change between 2g and 3g
Related: OS#2737 Change-Id: I3fc614da6ba137e871ee0fe86ca22b6a4a354dd2
This commit is contained in:
parent
d999e54aa2
commit
91a8bbd5db
|
@ -1,6 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <osmocom/core/fsm.h>
|
||||
#include <osmocom/sgsn/gprs_sgsn.h>
|
||||
|
||||
|
||||
/* 3GPP TS 24.008 § 4.1.3.3 GMM mobility management states on the network side */
|
||||
enum gmm_fsm_states {
|
||||
|
@ -23,6 +25,12 @@ enum gmm_fsm_events {
|
|||
E_GMM_SUSPEND,
|
||||
E_GMM_RESUME,
|
||||
E_GMM_CLEANUP,
|
||||
E_GMM_RAT_CHANGE,
|
||||
};
|
||||
|
||||
struct gmm_rat_change_data {
|
||||
enum sgsn_ran_type new_ran_type;
|
||||
struct gprs_llc_llme *llme;
|
||||
};
|
||||
|
||||
static inline bool gmm_fsm_is_registered(struct osmo_fsm_inst *fi)
|
||||
|
|
|
@ -1109,6 +1109,23 @@ static bool mmctx_did_rat_change(struct sgsn_mm_ctx *mmctx, struct msgb *msg)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Notify the FSM of a RAT change */
|
||||
static void mmctx_handle_rat_change(struct sgsn_mm_ctx *mmctx, struct msgb *msg, struct gprs_llc_llme *llme)
|
||||
{
|
||||
struct gmm_rat_change_data rat_chg = {
|
||||
.llme = llme
|
||||
};
|
||||
|
||||
rat_chg.new_ran_type = MSG_IU_UE_CTX(msg) ? MM_CTX_T_UTRAN_Iu : MM_CTX_T_GERAN_Gb;
|
||||
|
||||
if (rat_chg.new_ran_type != mmctx->ran_type)
|
||||
osmo_fsm_inst_dispatch(mmctx->gmm_fsm, E_GMM_RAT_CHANGE, (void *) &rat_chg);
|
||||
else
|
||||
LOGMMCTXP(LOGL_ERROR, mmctx, "RAT didn't change or not implemented (ran_type=%u, "
|
||||
"msg_iu_ue_ctx=%p\n", mmctx->ran_type, MSG_IU_UE_CTX(msg));
|
||||
|
||||
}
|
||||
|
||||
/* 3GPP TS 24.008 § 9.4.1 Attach request */
|
||||
static int gsm48_rx_gmm_att_req(struct sgsn_mm_ctx *ctx, struct msgb *msg,
|
||||
struct gprs_llc_llme *llme)
|
||||
|
@ -1234,6 +1251,9 @@ static int gsm48_rx_gmm_att_req(struct sgsn_mm_ctx *ctx, struct msgb *msg,
|
|||
goto rejected;
|
||||
}
|
||||
|
||||
if (mmctx_did_rat_change(ctx, msg))
|
||||
mmctx_handle_rat_change(ctx, msg, llme);
|
||||
|
||||
if (ctx->ran_type == MM_CTX_T_GERAN_Gb) {
|
||||
ctx->gb.tlli = msgb_tlli(msg);
|
||||
ctx->gb.llme = llme;
|
||||
|
@ -1614,7 +1634,12 @@ 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));
|
||||
osmo_fsm_inst_dispatch(mmctx->gmm_fsm, E_GMM_COMMON_PROC_INIT_REQ, NULL);
|
||||
/* A RAT change will trigger the common procedure
|
||||
* below after handling the RAT change. Protect it
|
||||
* here from being called twice */
|
||||
if (!mmctx_did_rat_change(mmctx, msg))
|
||||
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_fsm->state == ST_GMM_DEREGISTERED)
|
||||
|
@ -1646,6 +1671,11 @@ static int gsm48_rx_gmm_ra_upd_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
|
|||
goto rejected;
|
||||
}
|
||||
|
||||
if (mmctx_did_rat_change(mmctx, msg)) {
|
||||
mmctx_handle_rat_change(mmctx, msg, llme);
|
||||
osmo_fsm_inst_dispatch(mmctx->gmm_fsm, E_GMM_COMMON_PROC_INIT_REQ, NULL);
|
||||
}
|
||||
|
||||
/* Store new BVCI/NSEI in MM context (FIXME: delay until we ack?) */
|
||||
msgid2mmctx(mmctx, msg);
|
||||
/* Bump the statistics of received signalling msgs for this MM context */
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include <osmocom/core/tdef.h>
|
||||
|
||||
#include <osmocom/sgsn/gprs_gmm_fsm.h>
|
||||
#include <osmocom/sgsn/gprs_mm_state_gb_fsm.h>
|
||||
#include <osmocom/sgsn/gprs_mm_state_iu_fsm.h>
|
||||
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
#include <osmocom/sgsn/sgsn.h>
|
||||
|
@ -149,11 +151,32 @@ const struct value_string gmm_fsm_event_names[] = {
|
|||
/* OSMO_VALUE_STRING(E_GMM_DETACH_ACCEPTED), */
|
||||
OSMO_VALUE_STRING(E_GMM_SUSPEND),
|
||||
OSMO_VALUE_STRING(E_GMM_CLEANUP),
|
||||
OSMO_VALUE_STRING(E_GMM_RAT_CHANGE),
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
void gmm_fsm_allstate_action(struct osmo_fsm_inst *fi, uint32_t event, void *data) {
|
||||
struct sgsn_mm_ctx *mmctx = fi->priv;
|
||||
struct gmm_rat_change_data *rat_chg = (struct gmm_rat_change_data *)data;
|
||||
|
||||
switch (event) {
|
||||
case E_GMM_RAT_CHANGE:
|
||||
|
||||
switch (fi->state) {
|
||||
case ST_GMM_COMMON_PROC_INIT:
|
||||
gmm_fsm_state_chg(fi, ST_GMM_DEREGISTERED);
|
||||
default:
|
||||
if (mmctx->ran_type == MM_CTX_T_GERAN_Gb)
|
||||
osmo_fsm_inst_dispatch(mmctx->gb.mm_state_fsm, E_MM_IMPLICIT_DETACH, NULL);
|
||||
else if (mmctx->ran_type == MM_CTX_T_UTRAN_Iu) {
|
||||
osmo_fsm_inst_dispatch(mmctx->iu.mm_state_fsm, E_PMM_IMPLICIT_DETACH, NULL);
|
||||
mmctx->gb.llme = rat_chg->llme;
|
||||
}
|
||||
|
||||
mmctx->ran_type = rat_chg->new_ran_type;
|
||||
break;
|
||||
}
|
||||
|
||||
case E_GMM_CLEANUP:
|
||||
switch (fi->state) {
|
||||
case ST_GMM_DEREGISTERED:
|
||||
|
@ -175,7 +198,7 @@ struct osmo_fsm gmm_fsm = {
|
|||
.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_event_mask = X(E_GMM_CLEANUP) | X(E_GMM_RAT_CHANGE),
|
||||
.allstate_action = gmm_fsm_allstate_action,
|
||||
.log_subsys = DMM,
|
||||
.timer_cb = gmm_fsm_timer_cb,
|
||||
|
|
Loading…
Reference in New Issue