[#220] fix RACE-CONDITION for MESSAGE and TIMER

This commit is contained in:
Sukchan Lee 2019-07-21 07:01:45 +09:00
parent 649b6ec5e9
commit d9238e3036
7 changed files with 84 additions and 36 deletions

View File

@ -93,8 +93,30 @@ static void mme_main(void *data)
ogs_pollset_poll(mme_self()->pollset,
ogs_timer_mgr_next(mme_self()->timer_mgr));
/* Process the MESSAGE FIRST.
*
* For example, if UE Context Release Complete is received,
* the MME_TIMER_UE_CONTEXT_RELEASE is first stopped */
for ( ;; ) {
mme_event_t *e = NULL;
rv = ogs_queue_trypop(mme_self()->queue, (void**)&e);
ogs_assert(rv != OGS_ERROR);
if (rv == OGS_DONE)
goto done;
if (rv == OGS_RETRY)
break;
ogs_assert(e);
ogs_fsm_dispatch(&mme_sm, e);
mme_event_free(e);
}
ogs_timer_mgr_expire(mme_self()->timer_mgr);
/* AND THEN, process the TIMER. */
for ( ;; ) {
mme_event_t *e = NULL;

View File

@ -219,24 +219,7 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
ogs_assert(enb);
ogs_assert(OGS_FSM_STATE(&enb->sm));
/*
* MME main loop is as below,
* 1. Wait Poll. If S1AP message is received, Awake Poll
* 2. Check Timer Expiration. If Timer is expired, push Queue
* 3. In this situation,
* 3-1. S1AP message is processed
* 3-1. And then, Timer handler is processed.
*
* If UE Context Release Complete is received,
* 1. enb_ue context is removed.
* 2. And then, timer handler retransmits UE context release command.
*
* The race-condition is raised,
* So, we should check whether the enb_ue context is removed or not.
*/
if (enb_ue_find_by_mme_ue_s1ap_id(enb_ue->mme_ue_s1ap_id)) {
ogs_fsm_dispatch(&enb->sm, e);
}
ogs_fsm_dispatch(&enb->sm, e);
break;
case MME_EVT_EMM_MESSAGE:

View File

@ -24,18 +24,35 @@
static mme_timer_cfg_t g_mme_timer_cfg[MAX_NUM_OF_MME_TIMER] = {
[MME_TIMER_UE_CONTEXT_RELEASE] =
{ .max_count = 2, .duration = ogs_time_from_sec(1) },
/* Paging procedure for EPS services initiated */
[MME_TIMER_T3413] =
{ .max_count = 2, .duration = ogs_time_from_sec(2) },
/* DETACH REQUEST sent */
[MME_TIMER_T3422] =
{ .max_count = 4, .duration = ogs_time_from_sec(3) },
/* ATTACH ACCEPT sent
* TRACKING AREA UPDATE ACCEPT sent with GUTI
* TRACKING AREA UPDATE ACCEPT sent with TMSI
* GUTI REALLOCATION COMMAND sent */
[MME_TIMER_T3450] =
{ .max_count = 4, .duration = ogs_time_from_sec(3) },
/* AUTHENTICATION REQUEST sent
* SECURITY MODE COMMAND sent */
[MME_TIMER_T3460] =
{ .max_count = 4, .duration = ogs_time_from_sec(3) },
/* IDENTITY REQUEST sent */
[MME_TIMER_T3470] =
{ .max_count = 4, .duration = ogs_time_from_sec(3) },
/* ESM INFORMATION REQUEST sent */
[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) },
};

View File

@ -34,26 +34,11 @@ typedef enum {
MME_TIMER_UE_CONTEXT_RELEASE,
/* Paging procedure for EPS services initiated */
MME_TIMER_T3413,
/* 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 */
MME_TIMER_T3450,
/* AUTHENTICATION REQUEST sent
* SECURITY MODE COMMAND sent */
MME_TIMER_T3460,
/* IDENTITY REQUEST sent */
MME_TIMER_T3470,
/* ESM INFORMATION REQUEST sent */
MME_TIMER_T3489,
MME_TIMER_SGS_CLI_CONN_TO_SRV,

View File

@ -96,13 +96,10 @@ int s1ap_send_to_enb(mme_enb_t *enb, ogs_pkbuf_t *pkbuf, uint16_t stream_no)
int s1ap_send_to_enb_ue(enb_ue_t *enb_ue, ogs_pkbuf_t *pkbuf)
{
mme_enb_t *enb = NULL;
mme_ue_t *mme_ue = NULL;
ogs_assert(enb_ue);
enb = enb_ue->enb;
ogs_assert(enb);
mme_ue = enb_ue->mme_ue;
ogs_assert(mme_ue);
return s1ap_send_to_enb(enb, pkbuf, enb_ue->enb_ostream_id);
}

View File

@ -90,8 +90,30 @@ static void pgw_main(void *data)
ogs_pollset_poll(pgw_self()->pollset,
ogs_timer_mgr_next(pgw_self()->timer_mgr));
/* Process the MESSAGE FIRST.
*
* For example, if UE Context Release Complete is received,
* the MME_TIMER_UE_CONTEXT_RELEASE is first stopped */
for ( ;; ) {
pgw_event_t *e = NULL;
rv = ogs_queue_trypop(pgw_self()->queue, (void**)&e);
ogs_assert(rv != OGS_ERROR);
if (rv == OGS_DONE)
goto done;
if (rv == OGS_RETRY)
break;
ogs_assert(e);
ogs_fsm_dispatch(&pgw_sm, e);
pgw_event_free(e);
}
ogs_timer_mgr_expire(pgw_self()->timer_mgr);
/* AND THEN, process the TIMER. */
for ( ;; ) {
pgw_event_t *e = NULL;

View File

@ -80,8 +80,30 @@ static void sgw_main(void *data)
ogs_pollset_poll(sgw_self()->pollset,
ogs_timer_mgr_next(sgw_self()->timer_mgr));
/* Process the MESSAGE FIRST.
*
* For example, if UE Context Release Complete is received,
* the MME_TIMER_UE_CONTEXT_RELEASE is first stopped */
for ( ;; ) {
sgw_event_t *e = NULL;
rv = ogs_queue_trypop(sgw_self()->queue, (void**)&e);
ogs_assert(rv != OGS_ERROR);
if (rv == OGS_DONE)
goto done;
if (rv == OGS_RETRY)
break;
ogs_assert(e);
ogs_fsm_dispatch(&sgw_sm, e);
sgw_event_free(e);
}
ogs_timer_mgr_expire(sgw_self()->timer_mgr);
/* AND THEN, process the TIMER. */
for ( ;; ) {
sgw_event_t *e = NULL;