From 5ce04bcc6f3017f293dabb83f0cd03a92cc70570 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Sat, 20 Jul 2019 23:06:54 +0900 Subject: [PATCH] [#220] T3489 done --- src/mme/emm-sm.c | 2 ++ src/mme/esm-handler.c | 4 ++-- src/mme/esm-sm.c | 32 ++++++++++++++++++++++++++++++ src/mme/mme-context.c | 5 +++++ src/mme/mme-context.h | 20 +++++++++++++++++++ src/mme/mme-sm.c | 17 +++++++++------- src/mme/mme-timer.c | 46 ++++++++++++++++++++++++++++++++++++------- src/mme/mme-timer.h | 27 ++++++++++++++----------- src/mme/nas-path.c | 12 +++++++++-- 9 files changed, 136 insertions(+), 29 deletions(-) diff --git a/src/mme/emm-sm.c b/src/mme/emm-sm.c index c3a1a5d5c..f66ed1812 100644 --- a/src/mme/emm-sm.c +++ b/src/mme/emm-sm.c @@ -71,6 +71,7 @@ void emm_state_de_registered(ogs_fsm_t *s, mme_event_t *e) switch (e->id) { case OGS_FSM_ENTRY_SIG: + CLEAR_SERVICE_INDICATOR(mme_ue); CLEAR_MME_UE_ALL_TIMERS(mme_ue); break; case OGS_FSM_EXIT_SIG: @@ -921,6 +922,7 @@ void emm_state_exception(ogs_fsm_t *s, mme_event_t *e) switch (e->id) { case OGS_FSM_ENTRY_SIG: + CLEAR_SERVICE_INDICATOR(mme_ue); CLEAR_MME_UE_ALL_TIMERS(mme_ue); break; case OGS_FSM_EXIT_SIG: diff --git a/src/mme/esm-handler.c b/src/mme/esm-handler.c index 542f9e805..a71b07610 100644 --- a/src/mme/esm-handler.c +++ b/src/mme/esm-handler.c @@ -85,8 +85,8 @@ int esm_handle_pdn_connectivity_request(mme_bearer_t *bearer, } if (security_protected_required) { - rv = nas_send_esm_information_request(bearer); - ogs_assert(rv == OGS_OK); + CLEAR_BEARER_TIMER(bearer->t3489); + nas_send_esm_information_request(bearer); return OGS_OK; } diff --git a/src/mme/esm-sm.c b/src/mme/esm-sm.c index fff7acb34..2c85e3d30 100644 --- a/src/mme/esm-sm.c +++ b/src/mme/esm-sm.c @@ -19,6 +19,7 @@ #include "nas/nas-message.h" #include "mme-event.h" +#include "mme-timer.h" #include "mme-sm.h" #include "mme-fd-path.h" #include "emm-handler.h" @@ -69,6 +70,7 @@ void esm_state_inactive(ogs_fsm_t *s, mme_event_t *e) switch (e->id) { case OGS_FSM_ENTRY_SIG: + CLEAR_BEARER_ALL_TIMERS(bearer); break; case OGS_FSM_EXIT_SIG: break; @@ -92,6 +94,8 @@ void esm_state_inactive(ogs_fsm_t *s, mme_event_t *e) ogs_debug("[ESM] ESM information response"); ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]", mme_ue->imsi_bcd, sess->pti, bearer->ebi); + + CLEAR_BEARER_TIMER(bearer->t3489); rv = esm_handle_information_response( sess, &message->esm.esm_information_response); if (rv != OGS_OK) { @@ -136,6 +140,30 @@ void esm_state_inactive(ogs_fsm_t *s, mme_event_t *e) break; } break; + case MME_EVT_ESM_TIMER: + switch (e->timer_id) { + case MME_TIMER_T3489: + if (bearer->t3489.retry_count >= + mme_timer_cfg(MME_TIMER_T3489)->max_count) { + ogs_warn("[EMM] Retransmission of IMSI[%s] failed. " + "Stop retransmission", + mme_ue->imsi_bcd); + CLEAR_BEARER_TIMER(bearer->t3489); + OGS_FSM_TRAN(&bearer->sm, &esm_state_exception); + + nas_send_pdn_connectivity_reject(sess, + ESM_CAUSE_ESM_INFORMATION_NOT_RECEIVED); + } else { + bearer->t3489.retry_count++; + nas_send_esm_information_request(bearer); + } + break; + default: + ogs_error("Unknown timer[%s:%d]", + mme_timer_get_name(e->timer_id), e->timer_id); + break; + } + break; default: ogs_error("Unknown event %s", mme_event_get_name(e)); break; @@ -310,11 +338,15 @@ void esm_state_bearer_deactivated(ogs_fsm_t *s, mme_event_t *e) void esm_state_exception(ogs_fsm_t *s, mme_event_t *e) { + mme_bearer_t *bearer = NULL; ogs_assert(e); mme_sm_debug(e); + bearer = e->bearer; + switch (e->id) { case OGS_FSM_ENTRY_SIG: + CLEAR_BEARER_ALL_TIMERS(bearer); break; case OGS_FSM_EXIT_SIG: break; diff --git a/src/mme/mme-context.c b/src/mme/mme-context.c index be8fe200f..c5b67a0aa 100644 --- a/src/mme/mme-context.c +++ b/src/mme/mme-context.c @@ -2525,6 +2525,9 @@ mme_bearer_t *mme_bearer_add(mme_sess_t *sess) bearer->sess = sess; ogs_list_add(&sess->bearer_list, bearer); + + bearer->t3489.timer = ogs_timer_add( + self.timer_mgr, mme_timer_t3489_expire, bearer); e.bearer = bearer; ogs_fsm_create(&bearer->sm, esm_state_initial, esm_state_final); @@ -2544,6 +2547,8 @@ void mme_bearer_remove(mme_bearer_t *bearer) ogs_fsm_fini(&bearer->sm, &e); ogs_fsm_delete(&bearer->sm); + ogs_timer_delete(bearer->t3489.timer); + ogs_list_remove(&bearer->sess->bearer_list, bearer); TLV_CLEAR_DATA(&bearer->tft); diff --git a/src/mme/mme-context.h b/src/mme/mme-context.h index c42004b67..4e1edd05a 100644 --- a/src/mme/mme-context.h +++ b/src/mme/mme-context.h @@ -589,6 +589,26 @@ typedef struct mme_bearer_s { qos_t qos; tlv_octet_t tft; /* Saved TFT */ +#define CLEAR_BEARER_ALL_TIMERS(__bEARER) \ + do { \ + CLEAR_BEARER_TIMER((__bEARER)->t3489); \ + } while(0); +#define CLEAR_BEARER_TIMER(__bEARER_TIMER) \ + do { \ + ogs_timer_stop((__bEARER_TIMER).timer); \ + if ((__bEARER_TIMER).pkbuf) \ + { \ + ogs_pkbuf_free((__bEARER_TIMER).pkbuf); \ + (__bEARER_TIMER).pkbuf = NULL; \ + } \ + (__bEARER_TIMER).retry_count = 0; \ + } while(0); + struct { + ogs_pkbuf_t *pkbuf; + ogs_timer_t *timer; + uint32_t retry_count;; + } t3489; + /* Related Context */ mme_ue_t *mme_ue; mme_sess_t *sess; diff --git a/src/mme/mme-sm.c b/src/mme/mme-sm.c index 54b0fa127..8563afa85 100644 --- a/src/mme/mme-sm.c +++ b/src/mme/mme-sm.c @@ -276,11 +276,7 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e) ogs_fsm_dispatch(&mme_ue->sm, e); if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_exception)) { - CLEAR_SERVICE_INDICATOR(mme_ue); - - rv = mme_send_delete_session_or_ue_context_release( - mme_ue, enb_ue); - ogs_assert(rv == OGS_OK); + mme_send_delete_session_or_ue_context_release(mme_ue, enb_ue); } ogs_pkbuf_free(pkbuf); @@ -332,14 +328,21 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e) * [Enhancement] - Probably Invalid APN * At this point, we'll forcely release UE context */ - rv = mme_send_delete_session_or_ue_context_release( + mme_send_delete_session_or_ue_context_release( mme_ue, mme_ue->enb_ue); - ogs_assert(rv == OGS_OK); } ogs_pkbuf_free(pkbuf); break; + case MME_EVT_ESM_TIMER: + bearer = e->bearer; + ogs_assert(bearer); + ogs_assert(OGS_FSM_STATE(&bearer->sm)); + + ogs_fsm_dispatch(&bearer->sm, e); + break; + case MME_EVT_S6A_MESSAGE: mme_ue = e->mme_ue; ogs_assert(mme_ue); diff --git a/src/mme/mme-timer.c b/src/mme/mme-timer.c index 1687bfa64..02444883e 100644 --- a/src/mme/mme-timer.c +++ b/src/mme/mme-timer.c @@ -32,12 +32,16 @@ static mme_timer_cfg_t g_mme_timer_cfg[MAX_NUM_OF_MME_TIMER] = { { .max_count = 4, .duration = ogs_time_from_sec(3) }, [MME_TIMER_T3470] = { .max_count = 4, .duration = ogs_time_from_sec(3) }, + [MME_TIMER_T3489] = + { .max_count = 2, .duration = ogs_time_from_sec(4) }, [MME_TIMER_SGS_CLI_CONN_TO_SRV] = { .duration = ogs_time_from_sec(3) }, }; -static void mme_ue_timer_event( +static void emm_timer_event_send( mme_timer_e timer_id, mme_ue_t *mme_ue); +static void esm_timer_event_send( + mme_timer_e timer_id, mme_bearer_t *bearer); mme_timer_cfg_t *mme_timer_cfg(mme_timer_e id) { @@ -60,6 +64,8 @@ const char *mme_timer_get_name(mme_timer_e id) return "MME_TIMER_T3460"; case MME_TIMER_T3470: return "MME_TIMER_T3470"; + case MME_TIMER_T3489: + return "MME_TIMER_T3489"; case MME_TIMER_SGS_CLI_CONN_TO_SRV: return "MME_TIMER_SGS_CLI_CONN_TO_SRV"; default: @@ -87,26 +93,30 @@ void mme_timer_s1_delayed_send(void *data) void mme_timer_t3413_expire(void *data) { - mme_ue_timer_event(MME_TIMER_T3413, data); + emm_timer_event_send(MME_TIMER_T3413, data); } void mme_timer_t3422_expire(void *data) { - mme_ue_timer_event(MME_TIMER_T3422, data); + emm_timer_event_send(MME_TIMER_T3422, data); } void mme_timer_t3450_expire(void *data) { - mme_ue_timer_event(MME_TIMER_T3450, data); + emm_timer_event_send(MME_TIMER_T3450, data); } void mme_timer_t3460_expire(void *data) { - mme_ue_timer_event(MME_TIMER_T3460, data); + emm_timer_event_send(MME_TIMER_T3460, data); } void mme_timer_t3470_expire(void *data) { - mme_ue_timer_event(MME_TIMER_T3470, data); + emm_timer_event_send(MME_TIMER_T3470, data); +} +void mme_timer_t3489_expire(void *data) +{ + esm_timer_event_send(MME_TIMER_T3489, data); } -static void mme_ue_timer_event( +static void emm_timer_event_send( mme_timer_e timer_id, mme_ue_t *mme_ue) { int rv; @@ -124,6 +134,28 @@ static void mme_ue_timer_event( } } +static void esm_timer_event_send( + mme_timer_e timer_id, mme_bearer_t *bearer) +{ + int rv; + mme_event_t *e = NULL; + mme_ue_t *mme_ue = NULL; + ogs_assert(bearer); + mme_ue = bearer->mme_ue; + ogs_assert(bearer); + + e = mme_event_new(MME_EVT_ESM_TIMER); + e->timer_id = timer_id; + e->mme_ue = mme_ue; + e->bearer = bearer; + + rv = ogs_queue_push(mme_self()->queue, e); + if (rv != OGS_OK) { + ogs_warn("ogs_queue_push() failed:%d", (int)rv); + mme_event_free(e); + } +} + void mme_timer_sgs_cli_conn_to_srv(void *data) { int rv; diff --git a/src/mme/mme-timer.h b/src/mme/mme-timer.h index 8b7ac4d7d..3ac2e9617 100644 --- a/src/mme/mme-timer.h +++ b/src/mme/mme-timer.h @@ -32,23 +32,27 @@ typedef enum { MME_TIMER_S1_DELAYED_SEND, - MME_TIMER_T3413, /* Paging procedure for EPS services initiated */ - MME_TIMER_T3422, /* DETACH REQUEST sent */ + /* Paging procedure for EPS services initiated */ + MME_TIMER_T3413, - /* - * ATTACH ACCEPT sent + /* DETACH REQUEST sent */ + MME_TIMER_T3422, + + /* ATTACH ACCEPT sent * TRACKING AREA UPDATE ACCEPT sent with GUTI * TRACKING AREA UPDATE ACCEPT sent with TMSI - * GUTI REALLOCATION COMMAND sent - */ + * GUTI REALLOCATION COMMAND sent */ MME_TIMER_T3450, - /* - * AUTHENTICATION REQUEST sent - * SECURITY MODE COMMAND sent - */ + + /* AUTHENTICATION REQUEST sent + * SECURITY MODE COMMAND sent */ MME_TIMER_T3460, - MME_TIMER_T3470, /* IDENTITY REQUEST sent */ + /* IDENTITY REQUEST sent */ + MME_TIMER_T3470, + + /* ESM INFORMATION REQUEST sent */ + MME_TIMER_T3489, MME_TIMER_SGS_CLI_CONN_TO_SRV, @@ -72,6 +76,7 @@ void mme_timer_t3422_expire(void *data); void mme_timer_t3450_expire(void *data); void mme_timer_t3460_expire(void *data); void mme_timer_t3470_expire(void *data); +void mme_timer_t3489_expire(void *data); void mme_timer_sgs_cli_conn_to_srv(void *data); diff --git a/src/mme/nas-path.c b/src/mme/nas-path.c index cf0b37b63..dfeff6a5f 100644 --- a/src/mme/nas-path.c +++ b/src/mme/nas-path.c @@ -318,8 +318,16 @@ int nas_send_esm_information_request(mme_bearer_t *bearer) mme_ue = bearer->mme_ue; ogs_assert(mme_ue); - rv = esm_build_information_request(&esmbuf, bearer); - ogs_assert(rv == OGS_OK && esmbuf); + if (bearer->t3489.pkbuf) { + esmbuf = bearer->t3489.pkbuf; + } else { + rv = esm_build_information_request(&esmbuf, bearer); + ogs_assert(rv == OGS_OK && esmbuf); + } + + bearer->t3489.pkbuf = ogs_pkbuf_copy(esmbuf); + ogs_timer_start(bearer->t3489.timer, + mme_timer_cfg(MME_TIMER_T3489)->duration); rv = nas_send_to_downlink_nas_transport(mme_ue, esmbuf); ogs_assert(rv == OGS_OK);