diff options
Diffstat (limited to 'src/gprs')
-rw-r--r-- | src/gprs/gprs_gmm.c | 87 | ||||
-rw-r--r-- | src/gprs/gprs_sgsn.c | 5 | ||||
-rw-r--r-- | src/gprs/sgsn_vty.c | 2 |
3 files changed, 93 insertions, 1 deletions
diff --git a/src/gprs/gprs_gmm.c b/src/gprs/gprs_gmm.c index db8defcc6..f7aff7311 100644 --- a/src/gprs/gprs_gmm.c +++ b/src/gprs/gprs_gmm.c @@ -137,6 +137,57 @@ static void mmctx_change_gtpu_endpoints_to_sgsn(struct sgsn_mm_ctx *mm_ctx) } } +static void mmctx_set_mm_state(struct sgsn_mm_ctx *ctx, enum gprs_pmm_state state); +static void mmctx_state_timer_cb(void *_mm) +{ + struct sgsn_mm_ctx *mm = _mm; + + switch (mm->gb.state_T) { + case 3314: + switch (mm->pmm_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_pmm_state_names, mm->pmm_state)); + break; + } + break; + default: + LOGMMCTXP(LOGL_ERROR, mm, "state timer expired in unknown mode %u\n", + mm->gb.state_T); + break; + } +} + +static 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; +} + static void mmctx_set_pmm_state(struct sgsn_mm_ctx *ctx, enum gprs_pmm_state state) { OSMO_ASSERT(ctx->ran_type == MM_CTX_T_UTRAN_Iu); @@ -173,6 +224,24 @@ static void mmctx_set_mm_state(struct sgsn_mm_ctx *ctx, enum gprs_pmm_state stat get_value_string(gprs_pmm_state_names, ctx->pmm_state), get_value_string(gprs_pmm_state_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->pmm_state == MM_READY) + mmctx_state_timer_stop(ctx, 3314); + break; + case MM_STANDBY: + if (ctx->pmm_state == MM_READY) + mmctx_state_timer_stop(ctx, 3314); + break; + default: + /* when changing to state != MM_READY */ + break; + } + ctx->pmm_state = state; } @@ -2968,6 +3037,21 @@ int gsm0408_gprs_rcvmsg_iu(struct msgb *msg, struct gprs_ra_id *ra_id, return rc; } +/* Update the MM context state */ +static void gsm0408_gprs_notify_pdu_gb(struct sgsn_mm_ctx *mmctx) +{ + switch (mmctx->pmm_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) @@ -2988,6 +3072,9 @@ int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme, /* 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_sgsn.c b/src/gprs/gprs_sgsn.c index eb04846eb..9f02d5420 100644 --- a/src/gprs/gprs_sgsn.c +++ b/src/gprs/gprs_sgsn.c @@ -341,6 +341,11 @@ void sgsn_mm_ctx_cleanup_free(struct sgsn_mm_ctx *mm) 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); diff --git a/src/gprs/sgsn_vty.c b/src/gprs/sgsn_vty.c index ae26cbeae..66986911c 100644 --- a/src/gprs/sgsn_vty.c +++ b/src/gprs/sgsn_vty.c @@ -94,7 +94,7 @@ const struct value_string sgsn_auth_pol_strs[] = { static struct osmo_tdef sgsn_T_defs[] = { { .T=3312, .default_val=GSM0408_T3312_SECS, .desc="Periodic RA Update timer (s)" }, { .T=3313, .default_val=GSM0408_T3313_SECS, .desc="Waiting for paging response timer (s)" }, - { .T=3314, .default_val=GSM0408_T3314_SECS, .desc="Force to STANDBY on expiry timer (s)" }, + { .T=3314, .default_val=GSM0408_T3314_SECS, .desc="READY timer. Force to STANDBY on expiry timer (s)" }, { .T=3316, .default_val=GSM0408_T3316_SECS, .desc="AA-Ready timer (s)" }, { .T=3322, .default_val=GSM0408_T3322_SECS, .desc="Detach request -> accept timer (s)" }, { .T=3350, .default_val=GSM0408_T3350_SECS, .desc="Waiting for ATT/RAU/TMSI_COMPL timer (s)" }, |