forked from acouzens/open5gs
design EMM state machine initially.
This commit is contained in:
parent
93ebb9cd43
commit
87b0897602
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include "core_msgq.h"
|
||||
#include "core_timer.h"
|
||||
#include "core_fsm.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -50,7 +49,7 @@ extern "C" {
|
|||
(__duration), (__ptr_e), (__param))
|
||||
|
||||
typedef struct {
|
||||
fsm_event_t event;
|
||||
c_uintptr_t event;
|
||||
c_uintptr_t param1;
|
||||
c_uintptr_t param2;
|
||||
c_uintptr_t param3;
|
||||
|
@ -61,10 +60,6 @@ typedef struct {
|
|||
c_uintptr_t param8;
|
||||
} event_t;
|
||||
|
||||
extern char *FSM_NAME_INIT_SIG;
|
||||
extern char *FSM_NAME_ENTRY_SIG;
|
||||
extern char *FSM_NAME_EXIT_SIG;
|
||||
|
||||
extern char *EVT_NAME_UNKNOWN;
|
||||
|
||||
/**
|
||||
|
|
|
@ -7,14 +7,21 @@
|
|||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
extern char *FSM_NAME_INIT_SIG;
|
||||
extern char *FSM_NAME_ENTRY_SIG;
|
||||
extern char *FSM_NAME_EXIT_SIG;
|
||||
|
||||
typedef enum _fsm_signal_t {
|
||||
FSM_ENTRY_SIG,
|
||||
FSM_EXIT_SIG,
|
||||
FSM_USER_SIG
|
||||
} fsm_signal_t;
|
||||
|
||||
typedef c_uint32_t fsm_event_t;
|
||||
typedef c_uint32_t fsm_state_t;
|
||||
typedef struct {
|
||||
c_uintptr_t event;
|
||||
} fsm_event_t;
|
||||
typedef c_uintptr_t fsm_state_t;
|
||||
|
||||
typedef void (*fsm_handler_t)(void *s, void *e);
|
||||
|
||||
typedef struct _fsm_t {
|
||||
|
@ -41,6 +48,9 @@ CORE_DECLARE(void) fsm_final(fsm_t *s, fsm_event_t *e);
|
|||
#define FSM_STATE(__s) \
|
||||
(((fsm_t *)__s)->state)
|
||||
|
||||
#define FSM_CHECK(__s, __f) \
|
||||
(FSM_STATE(__s) == (fsm_handler_t)__f)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -10,10 +10,6 @@
|
|||
|
||||
#define EVT_Q_DEPTH 16
|
||||
|
||||
char *FSM_NAME_INIT_SIG = "INIT";
|
||||
char *FSM_NAME_ENTRY_SIG = "ENTRY";
|
||||
char *FSM_NAME_EXIT_SIG = "EXIT";
|
||||
|
||||
char *EVT_NAME_UNKNOWN = "UNKNOWN";
|
||||
|
||||
msgq_id event_create(void)
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
#include "core_fsm.h"
|
||||
|
||||
static fsm_event_t fsm_event[] = {
|
||||
static fsm_event_t entry_event = {
|
||||
FSM_ENTRY_SIG,
|
||||
FSM_EXIT_SIG
|
||||
};
|
||||
static fsm_event_t exit_event = {
|
||||
FSM_EXIT_SIG,
|
||||
};
|
||||
|
||||
char *FSM_NAME_INIT_SIG = "INIT";
|
||||
char *FSM_NAME_ENTRY_SIG = "ENTRY";
|
||||
char *FSM_NAME_EXIT_SIG = "EXIT";
|
||||
|
||||
void fsm_init(fsm_t *s, fsm_event_t *e)
|
||||
{
|
||||
|
@ -12,7 +18,15 @@ void fsm_init(fsm_t *s, fsm_event_t *e)
|
|||
(*s->initial)(s, e);
|
||||
if (s->initial != s->state)
|
||||
{
|
||||
(*s->state)(s, &fsm_event[FSM_ENTRY_SIG]);
|
||||
if (e)
|
||||
{
|
||||
e->event = FSM_ENTRY_SIG;
|
||||
(*s->state)(s, e);
|
||||
}
|
||||
else
|
||||
{
|
||||
(*s->state)(s, &entry_event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,8 +39,24 @@ void fsm_dispatch(fsm_t *s, fsm_event_t *e)
|
|||
(*tmp)(s, e);
|
||||
if (s->state != (fsm_state_t)0)
|
||||
{
|
||||
(*tmp)(s, &fsm_event[FSM_EXIT_SIG]);
|
||||
(*s->state)(s, &fsm_event[FSM_ENTRY_SIG]);
|
||||
if (e)
|
||||
{
|
||||
e->event = FSM_EXIT_SIG;
|
||||
(*tmp)(s, e);
|
||||
}
|
||||
else
|
||||
{
|
||||
(*tmp)(s, &exit_event);
|
||||
}
|
||||
if (e)
|
||||
{
|
||||
e->event = FSM_ENTRY_SIG;
|
||||
(*s->state)(s, e);
|
||||
}
|
||||
else
|
||||
{
|
||||
(*tmp)(s, &entry_event);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -38,12 +68,20 @@ void fsm_final(fsm_t *s, fsm_event_t *e)
|
|||
{
|
||||
if (s->final != s->state)
|
||||
{
|
||||
(*s->state)(s, &fsm_event[FSM_EXIT_SIG]);
|
||||
if (e)
|
||||
{
|
||||
e->event = FSM_EXIT_SIG;
|
||||
(*s->state)(s, e);
|
||||
}
|
||||
else
|
||||
{
|
||||
(*s->state)(s, &exit_event);
|
||||
}
|
||||
}
|
||||
|
||||
if (s->final != (fsm_state_t)0)
|
||||
{
|
||||
(*s->final)(s, 0);
|
||||
(*s->final)(s, e);
|
||||
}
|
||||
|
||||
s->state = s->initial;
|
||||
|
|
|
@ -18,7 +18,7 @@ AM_CPPFLAGS = \
|
|||
|
||||
AM_CFLAGS = \
|
||||
-Wall -Werror @OSCPPFLAGS@ \
|
||||
-Wno-unused-function
|
||||
-Wno-unused-function -Wno-unused-variable
|
||||
|
||||
TESTS = testcore
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ enum bomb_signal_t {
|
|||
};
|
||||
|
||||
typedef struct _tick_event_t {
|
||||
fsm_event_t event;
|
||||
c_uintptr_t event;
|
||||
} tick_event_t;
|
||||
|
||||
typedef struct _bomb_t {
|
||||
|
@ -176,17 +176,17 @@ enum alarm_signal_t {
|
|||
};
|
||||
|
||||
typedef struct _alarm_t {
|
||||
fsm_t fsm;
|
||||
fsm_t fsm;
|
||||
c_uint32_t time;
|
||||
} alarm_t;
|
||||
|
||||
typedef struct _set_event_t {
|
||||
fsm_event_t event;
|
||||
c_uintptr_t event;
|
||||
c_uint8_t digit;
|
||||
} set_event_t;
|
||||
|
||||
typedef struct _time_event_t {
|
||||
fsm_event_t event;
|
||||
c_uintptr_t event;
|
||||
c_uint8_t current_time;
|
||||
} time_event_t;
|
||||
|
||||
|
|
|
@ -152,7 +152,7 @@ void emm_handle_attach_request(
|
|||
d_warn("Not implemented(type:%d)",
|
||||
eps_mobile_identity->imsi.type);
|
||||
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -472,7 +472,8 @@ void emm_handle_detach_request(
|
|||
break;
|
||||
}
|
||||
|
||||
SET_DETACH_TYPE(mme_ue, detach_request->detach_type);
|
||||
/* Save detach type */
|
||||
mme_ue->detach_type = detach_request->detach_type;
|
||||
}
|
||||
|
||||
void emm_handle_detach_accept(mme_ue_t *mme_ue)
|
||||
|
@ -509,8 +510,6 @@ void emm_handle_detach_accept(mme_ue_t *mme_ue)
|
|||
d_assert(nas_send_to_downlink_nas_transport(mme_ue, emmbuf) == CORE_OK,,);
|
||||
}
|
||||
|
||||
CLEAR_DETACH_TYPE(mme_ue);
|
||||
|
||||
cause.present = S1ap_Cause_PR_nas;
|
||||
cause.choice.nas = S1ap_CauseNas_detach;
|
||||
|
||||
|
|
415
src/mme/emm_sm.c
415
src/mme/emm_sm.c
|
@ -21,7 +21,7 @@ void emm_state_initial(fsm_t *s, event_t *e)
|
|||
|
||||
mme_sm_trace(3, e);
|
||||
|
||||
FSM_TRAN(s, &emm_state_operational);
|
||||
FSM_TRAN(s, &emm_state_detached);
|
||||
}
|
||||
|
||||
void emm_state_final(fsm_t *s, event_t *e)
|
||||
|
@ -31,13 +31,18 @@ void emm_state_final(fsm_t *s, event_t *e)
|
|||
mme_sm_trace(3, e);
|
||||
}
|
||||
|
||||
void emm_state_operational(fsm_t *s, event_t *e)
|
||||
void emm_state_detached(fsm_t *s, event_t *e)
|
||||
{
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
|
||||
d_assert(s, return, "Null param");
|
||||
d_assert(e, return, "Null param");
|
||||
|
||||
mme_sm_trace(3, e);
|
||||
|
||||
mme_ue = mme_ue_find(event_get_param1(e));
|
||||
d_assert(mme_ue, return, "Null param");
|
||||
|
||||
switch (event_get(e))
|
||||
{
|
||||
case FSM_ENTRY_SIG:
|
||||
|
@ -50,15 +55,305 @@ void emm_state_operational(fsm_t *s, event_t *e)
|
|||
}
|
||||
case MME_EVT_EMM_MESSAGE:
|
||||
{
|
||||
index_t index = event_get_param1(e);
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
nas_message_t *message = NULL;
|
||||
nas_message_t *message = (nas_message_t *)event_get_param4(e);
|
||||
d_assert(message, break, "Null param");
|
||||
|
||||
d_assert(index, return, "Null param");
|
||||
mme_ue = mme_ue_find(index);
|
||||
switch(message->emm.h.message_type)
|
||||
{
|
||||
case NAS_ATTACH_REQUEST:
|
||||
{
|
||||
/* Update Kenb */
|
||||
if (SECURITY_CONTEXT_IS_VALID(mme_ue))
|
||||
mme_kdf_enb(mme_ue->kasme, mme_ue->ul_count.i32,
|
||||
mme_ue->kenb);
|
||||
|
||||
CLEAR_EPS_BEARER_ID(mme_ue);
|
||||
mme_ue_paged(mme_ue);
|
||||
|
||||
emm_handle_attach_request(
|
||||
mme_ue, &message->emm.attach_request);
|
||||
|
||||
if (!MME_UE_HAVE_IMSI(mme_ue))
|
||||
{
|
||||
/* Unknown GUTI */
|
||||
FSM_TRAN(s, &emm_state_identity);
|
||||
break;
|
||||
}
|
||||
|
||||
if (SECURITY_CONTEXT_IS_VALID(mme_ue))
|
||||
{
|
||||
event_emm_to_esm(
|
||||
mme_ue, &mme_ue->last_pdn_connectivity_request);
|
||||
FSM_TRAN(s, &emm_state_default_esm);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MME_UE_HAVE_SESSION(mme_ue))
|
||||
{
|
||||
mme_s11_handle_delete_all_sessions_in_ue(mme_ue);
|
||||
}
|
||||
else
|
||||
{
|
||||
mme_s6a_send_air(mme_ue);
|
||||
}
|
||||
FSM_TRAN(s, &emm_state_auth);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
d_error("Unknown event %s", mme_event_get_name(e));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void emm_state_identity(fsm_t *s, event_t *e)
|
||||
{
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
|
||||
d_assert(s, return, "Null param");
|
||||
d_assert(e, return, "Null param");
|
||||
|
||||
mme_sm_trace(3, e);
|
||||
|
||||
mme_ue = mme_ue_find(event_get_param1(e));
|
||||
d_assert(mme_ue, return, "Null param");
|
||||
|
||||
switch (event_get(e))
|
||||
{
|
||||
case FSM_ENTRY_SIG:
|
||||
{
|
||||
mme_ue_t *mme_ue = mme_ue_find(event_get_param1(e));
|
||||
d_assert(mme_ue, return, "Null param");
|
||||
|
||||
message = (nas_message_t *)event_get_param4(e);
|
||||
emm_handle_identity_request(mme_ue);
|
||||
break;
|
||||
}
|
||||
case FSM_EXIT_SIG:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case MME_EVT_EMM_MESSAGE:
|
||||
{
|
||||
nas_message_t *message = (nas_message_t *)event_get_param4(e);
|
||||
d_assert(message, break, "Null param");
|
||||
|
||||
switch(message->emm.h.message_type)
|
||||
{
|
||||
case NAS_IDENTITY_RESPONSE:
|
||||
{
|
||||
emm_handle_identity_response(mme_ue,
|
||||
&message->emm.identity_response);
|
||||
|
||||
d_assert(MME_UE_HAVE_IMSI(mme_ue), break,
|
||||
"No IMSI in IDENTITY_RESPONSE");
|
||||
|
||||
if (SECURITY_CONTEXT_IS_VALID(mme_ue))
|
||||
{
|
||||
event_emm_to_esm(mme_ue,
|
||||
&mme_ue->last_pdn_connectivity_request);
|
||||
FSM_TRAN(s, &emm_state_default_esm);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MME_UE_HAVE_SESSION(mme_ue))
|
||||
{
|
||||
mme_s11_handle_delete_all_sessions_in_ue(mme_ue);
|
||||
}
|
||||
else
|
||||
{
|
||||
mme_s6a_send_air(mme_ue);
|
||||
}
|
||||
FSM_TRAN(s, &emm_state_auth);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NAS_EMM_STATUS:
|
||||
{
|
||||
emm_handle_emm_status(mme_ue, &message->emm.emm_status);
|
||||
FSM_TRAN(s, &emm_state_detached);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
d_warn("Unknown message(type:%d)",
|
||||
message->emm.h.message_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
d_error("Unknown event %s", mme_event_get_name(e));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void emm_state_auth(fsm_t *s, event_t *e)
|
||||
{
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
|
||||
d_assert(s, return, "Null param");
|
||||
d_assert(e, return, "Null param");
|
||||
|
||||
mme_sm_trace(3, e);
|
||||
|
||||
mme_ue = mme_ue_find(event_get_param1(e));
|
||||
d_assert(mme_ue, return, "Null param");
|
||||
|
||||
switch (event_get(e))
|
||||
{
|
||||
case FSM_ENTRY_SIG:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case FSM_EXIT_SIG:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case MME_EVT_EMM_MESSAGE:
|
||||
{
|
||||
nas_message_t *message = (nas_message_t *)event_get_param4(e);
|
||||
d_assert(message, break, "Null param");
|
||||
|
||||
switch(message->emm.h.message_type)
|
||||
{
|
||||
case NAS_AUTHENTICATION_RESPONSE:
|
||||
{
|
||||
emm_handle_authentication_response(
|
||||
mme_ue, &message->emm.authentication_response);
|
||||
break;
|
||||
}
|
||||
case NAS_SECURITY_MODE_COMPLETE:
|
||||
{
|
||||
d_trace(3, "[NAS] Security mode complete : "
|
||||
"UE[%s] --> EMM\n", mme_ue->imsi_bcd);
|
||||
|
||||
/* Update Kenb */
|
||||
if (SECURITY_CONTEXT_IS_VALID(mme_ue))
|
||||
mme_kdf_enb(mme_ue->kasme, mme_ue->ul_count.i32,
|
||||
mme_ue->kenb);
|
||||
|
||||
mme_s6a_send_ulr(mme_ue);
|
||||
FSM_TRAN(s, &emm_state_default_esm);
|
||||
break;
|
||||
}
|
||||
case NAS_EMM_STATUS:
|
||||
{
|
||||
emm_handle_emm_status(mme_ue, &message->emm.emm_status);
|
||||
FSM_TRAN(s, &emm_state_detached);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
d_warn("Unknown message(type:%d)",
|
||||
message->emm.h.message_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
d_error("Unknown event %s", mme_event_get_name(e));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void emm_state_default_esm(fsm_t *s, event_t *e)
|
||||
{
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
|
||||
d_assert(s, return, "Null param");
|
||||
d_assert(e, return, "Null param");
|
||||
|
||||
mme_sm_trace(3, e);
|
||||
|
||||
mme_ue = mme_ue_find(event_get_param1(e));
|
||||
d_assert(mme_ue, return, "Null param");
|
||||
|
||||
switch (event_get(e))
|
||||
{
|
||||
case FSM_ENTRY_SIG:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case FSM_EXIT_SIG:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case MME_EVT_EMM_MESSAGE:
|
||||
{
|
||||
nas_message_t *message = (nas_message_t *)event_get_param4(e);
|
||||
d_assert(message, break, "Null param");
|
||||
|
||||
switch(message->emm.h.message_type)
|
||||
{
|
||||
case NAS_ATTACH_COMPLETE:
|
||||
{
|
||||
d_trace(3, "[NAS] Attach complete : UE[%s] --> EMM\n",
|
||||
mme_ue->imsi_bcd);
|
||||
emm_handle_attach_complete(
|
||||
mme_ue, &message->emm.attach_complete);
|
||||
FSM_TRAN(s, &emm_state_attached);
|
||||
break;
|
||||
}
|
||||
case NAS_EMM_STATUS:
|
||||
{
|
||||
emm_handle_emm_status(mme_ue, &message->emm.emm_status);
|
||||
FSM_TRAN(s, &emm_state_detached);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
d_warn("Unknown message(type:%d)",
|
||||
message->emm.h.message_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
d_error("Unknown event %s", mme_event_get_name(e));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void emm_state_attached(fsm_t *s, event_t *e)
|
||||
{
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
|
||||
d_assert(s, return, "Null param");
|
||||
d_assert(e, return, "Null param");
|
||||
|
||||
mme_sm_trace(3, e);
|
||||
|
||||
mme_ue = mme_ue_find(event_get_param1(e));
|
||||
d_assert(mme_ue, return, "Null param");
|
||||
|
||||
switch (event_get(e))
|
||||
{
|
||||
case FSM_ENTRY_SIG:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case FSM_EXIT_SIG:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case MME_EVT_EMM_MESSAGE:
|
||||
{
|
||||
nas_message_t *message = (nas_message_t *)event_get_param4(e);
|
||||
d_assert(message, break, "Null param");
|
||||
|
||||
if (message->emm.h.security_header_type
|
||||
|
@ -86,15 +381,15 @@ void emm_state_operational(fsm_t *s, event_t *e)
|
|||
mme_ue->kenb);
|
||||
|
||||
CLEAR_EPS_BEARER_ID(mme_ue);
|
||||
|
||||
mme_ue_paged(mme_ue);
|
||||
|
||||
emm_handle_attach_request(
|
||||
mme_ue, &message->emm.attach_request);
|
||||
|
||||
if (!MME_UE_HAVE_IMSI(mme_ue))
|
||||
{
|
||||
/* Unknown GUTI */
|
||||
emm_handle_identity_request(mme_ue);
|
||||
FSM_TRAN(s, &emm_state_identity);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -102,80 +397,27 @@ void emm_state_operational(fsm_t *s, event_t *e)
|
|||
{
|
||||
event_emm_to_esm(
|
||||
mme_ue, &mme_ue->last_pdn_connectivity_request);
|
||||
FSM_TRAN(s, &emm_state_default_esm);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MME_UE_HAVE_SESSION(mme_ue))
|
||||
{
|
||||
mme_s11_handle_delete_all_sessions_request_in_ue(
|
||||
mme_ue);
|
||||
mme_s11_handle_delete_all_sessions_in_ue(mme_ue);
|
||||
}
|
||||
else
|
||||
{
|
||||
mme_s6a_send_air(mme_ue);
|
||||
}
|
||||
FSM_TRAN(s, &emm_state_auth);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case NAS_IDENTITY_RESPONSE:
|
||||
{
|
||||
emm_handle_identity_response(mme_ue,
|
||||
&message->emm.identity_response);
|
||||
|
||||
d_assert(MME_UE_HAVE_IMSI(mme_ue), break,
|
||||
"No IMSI in IDENTITY_RESPONSE");
|
||||
|
||||
if (SECURITY_CONTEXT_IS_VALID(mme_ue))
|
||||
{
|
||||
event_emm_to_esm(mme_ue,
|
||||
&mme_ue->last_pdn_connectivity_request);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MME_UE_HAVE_SESSION(mme_ue))
|
||||
{
|
||||
mme_s11_handle_delete_all_sessions_request_in_ue(
|
||||
mme_ue);
|
||||
}
|
||||
else
|
||||
{
|
||||
mme_s6a_send_air(mme_ue);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case NAS_AUTHENTICATION_RESPONSE:
|
||||
{
|
||||
emm_handle_authentication_response(
|
||||
mme_ue, &message->emm.authentication_response);
|
||||
break;
|
||||
}
|
||||
case NAS_SECURITY_MODE_COMPLETE:
|
||||
{
|
||||
d_trace(3, "[NAS] Security mode complete : "
|
||||
"UE[%s] --> EMM\n", mme_ue->imsi_bcd);
|
||||
|
||||
/* Update Kenb */
|
||||
if (SECURITY_CONTEXT_IS_VALID(mme_ue))
|
||||
mme_kdf_enb(mme_ue->kasme, mme_ue->ul_count.i32,
|
||||
mme_ue->kenb);
|
||||
|
||||
mme_s6a_send_ulr(mme_ue);
|
||||
break;
|
||||
}
|
||||
case NAS_ATTACH_COMPLETE:
|
||||
{
|
||||
d_trace(3, "[NAS] Attach complete : UE[%s] --> EMM\n",
|
||||
mme_ue->imsi_bcd);
|
||||
emm_handle_attach_complete(
|
||||
mme_ue, &message->emm.attach_complete);
|
||||
break;
|
||||
}
|
||||
case NAS_EMM_STATUS:
|
||||
{
|
||||
emm_handle_emm_status(mme_ue, &message->emm.emm_status);
|
||||
FSM_TRAN(s, &emm_state_detached);
|
||||
break;
|
||||
}
|
||||
case NAS_DETACH_REQUEST:
|
||||
|
@ -185,13 +427,14 @@ void emm_state_operational(fsm_t *s, event_t *e)
|
|||
|
||||
if (MME_UE_HAVE_SESSION(mme_ue))
|
||||
{
|
||||
mme_s11_handle_delete_all_sessions_request_in_ue(
|
||||
mme_ue);
|
||||
mme_s11_handle_delete_all_sessions_in_ue(mme_ue);
|
||||
}
|
||||
else
|
||||
{
|
||||
emm_handle_detach_accept(mme_ue);
|
||||
}
|
||||
|
||||
FSM_TRAN(s, &emm_state_detached);
|
||||
break;
|
||||
}
|
||||
case NAS_TRACKING_AREA_UPDATE_REQUEST:
|
||||
|
@ -203,7 +446,7 @@ void emm_state_operational(fsm_t *s, event_t *e)
|
|||
}
|
||||
default:
|
||||
{
|
||||
d_warn("Not implemented(type:%d)",
|
||||
d_warn("Unknown message(type:%d)",
|
||||
message->emm.h.message_type);
|
||||
break;
|
||||
}
|
||||
|
@ -212,13 +455,6 @@ void emm_state_operational(fsm_t *s, event_t *e)
|
|||
}
|
||||
case MME_EVT_EMM_T3413:
|
||||
{
|
||||
index_t index = event_get_param1(e);
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
|
||||
d_assert(index, return, "Null param");
|
||||
mme_ue = mme_ue_find(index);
|
||||
d_assert(mme_ue, return, "Null param");
|
||||
|
||||
if (mme_ue->max_paging_retry >= MAX_NUM_OF_PAGING)
|
||||
{
|
||||
/* Paging failed */
|
||||
|
@ -246,28 +482,3 @@ void emm_state_operational(fsm_t *s, event_t *e)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void emm_state_exception(fsm_t *s, event_t *e)
|
||||
{
|
||||
d_assert(s, return, "Null param");
|
||||
d_assert(e, return, "Null param");
|
||||
|
||||
mme_sm_trace(3, e);
|
||||
|
||||
switch (event_get(e))
|
||||
{
|
||||
case FSM_ENTRY_SIG:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case FSM_EXIT_SIG:
|
||||
{
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
d_error("Unknown event %s", mme_event_get_name(e));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,11 +29,19 @@ void esm_state_final(fsm_t *s, event_t *e)
|
|||
|
||||
void esm_state_operational(fsm_t *s, event_t *e)
|
||||
{
|
||||
mme_sess_t *sess = NULL;
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
|
||||
d_assert(s, return, "Null param");
|
||||
d_assert(e, return, "Null param");
|
||||
|
||||
mme_sm_trace(3, e);
|
||||
|
||||
sess = mme_sess_find(event_get_param1(e));
|
||||
d_assert(sess, return, "Null param");
|
||||
mme_ue = sess->mme_ue;
|
||||
d_assert(mme_ue, return, "Null param");
|
||||
|
||||
switch (event_get(e))
|
||||
{
|
||||
case FSM_ENTRY_SIG:
|
||||
|
@ -46,17 +54,7 @@ void esm_state_operational(fsm_t *s, event_t *e)
|
|||
}
|
||||
case MME_EVT_ESM_MESSAGE:
|
||||
{
|
||||
index_t index = event_get_param1(e);
|
||||
mme_sess_t *sess = NULL;
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
nas_message_t *message = NULL;
|
||||
|
||||
d_assert(index, return, "Null param");
|
||||
sess = mme_sess_find(index);
|
||||
d_assert(sess, return, "Null param");
|
||||
mme_ue = sess->mme_ue;
|
||||
d_assert(mme_ue, return, "Null param");
|
||||
message = (nas_message_t *)event_get_param3(e);
|
||||
nas_message_t *message = (nas_message_t *)event_get_param3(e);
|
||||
d_assert(message, break, "Null param");
|
||||
|
||||
switch(message->esm.h.message_type)
|
||||
|
|
|
@ -910,6 +910,7 @@ mme_sgw_t* mme_sgw_next(mme_sgw_t *sgw)
|
|||
mme_enb_t* mme_enb_add(net_sock_t *s1ap_sock)
|
||||
{
|
||||
mme_enb_t *enb = NULL;
|
||||
event_t e;
|
||||
|
||||
index_alloc(&mme_enb_pool, &enb);
|
||||
d_assert(enb, return NULL, "Null param");
|
||||
|
@ -922,17 +923,21 @@ mme_enb_t* mme_enb_add(net_sock_t *s1ap_sock)
|
|||
list_init(&enb->enb_ue_list);
|
||||
list_append(&self.enb_list, enb);
|
||||
|
||||
event_set_param1(&e, (c_uintptr_t)enb->index);
|
||||
fsm_create(&enb->sm, s1ap_state_initial, s1ap_state_final);
|
||||
fsm_init(&enb->sm, 0);
|
||||
fsm_init(&enb->sm, (fsm_event_t *)&e);
|
||||
|
||||
return enb;
|
||||
}
|
||||
|
||||
status_t mme_enb_remove(mme_enb_t *enb)
|
||||
{
|
||||
event_t e;
|
||||
|
||||
d_assert(enb, return CORE_ERROR, "Null param");
|
||||
|
||||
fsm_final(&enb->sm, 0);
|
||||
event_set_param1(&e, (c_uintptr_t)enb->index);
|
||||
fsm_final(&enb->sm, (fsm_event_t *)&e);
|
||||
fsm_clear(&enb->sm);
|
||||
|
||||
enb_ue_remove_in_enb(enb);
|
||||
|
@ -1117,6 +1122,7 @@ enb_ue_t* enb_ue_next_in_enb(enb_ue_t *enb_ue)
|
|||
mme_ue_t* mme_ue_add(enb_ue_t *enb_ue)
|
||||
{
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
event_t e;
|
||||
|
||||
d_assert(enb_ue, return NULL, "Null param");
|
||||
|
||||
|
@ -1135,17 +1141,21 @@ mme_ue_t* mme_ue_add(enb_ue_t *enb_ue)
|
|||
mme_ue->enb_ue = enb_ue;
|
||||
enb_ue->mme_ue = mme_ue;
|
||||
|
||||
event_set_param1(&e, (c_uintptr_t)mme_ue->index);
|
||||
fsm_create(&mme_ue->sm, emm_state_initial, emm_state_final);
|
||||
fsm_init(&mme_ue->sm, 0);
|
||||
fsm_init(&mme_ue->sm, (fsm_event_t *)&e);
|
||||
|
||||
return mme_ue;
|
||||
}
|
||||
|
||||
status_t mme_ue_remove(mme_ue_t *mme_ue)
|
||||
{
|
||||
event_t e;
|
||||
|
||||
d_assert(mme_ue, return CORE_ERROR, "Null param");
|
||||
|
||||
fsm_final(&mme_ue->sm, 0);
|
||||
event_set_param1(&e, (c_uintptr_t)mme_ue->index);
|
||||
fsm_final(&mme_ue->sm, (fsm_event_t *)&e);
|
||||
fsm_clear(&mme_ue->sm);
|
||||
|
||||
/* Clear hash table */
|
||||
|
@ -1462,6 +1472,7 @@ mme_sess_t *mme_sess_add(mme_ue_t *mme_ue, c_uint8_t pti)
|
|||
{
|
||||
mme_sess_t *sess = NULL;
|
||||
mme_bearer_t *bearer = NULL;
|
||||
event_t e;
|
||||
|
||||
d_assert(mme_ue, return NULL, "Null param");
|
||||
d_assert(pti != NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
|
||||
|
@ -1483,18 +1494,22 @@ mme_sess_t *mme_sess_add(mme_ue_t *mme_ue, c_uint8_t pti)
|
|||
d_assert(bearer, mme_sess_remove(sess); return NULL,
|
||||
"Can't add default bearer context");
|
||||
|
||||
event_set_param1(&e, (c_uintptr_t)sess->index);
|
||||
fsm_create(&sess->sm, esm_state_initial, esm_state_final);
|
||||
fsm_init(&sess->sm, 0);
|
||||
fsm_init(&sess->sm, (fsm_event_t *)&e);
|
||||
|
||||
return sess;
|
||||
}
|
||||
|
||||
status_t mme_sess_remove(mme_sess_t *sess)
|
||||
{
|
||||
event_t e;
|
||||
|
||||
d_assert(sess, return CORE_ERROR, "Null param");
|
||||
d_assert(sess->mme_ue, return CORE_ERROR, "Null param");
|
||||
|
||||
fsm_final(&sess->sm, 0);
|
||||
event_set_param1(&e, (c_uintptr_t)sess->index);
|
||||
fsm_final(&sess->sm, (fsm_event_t *)&e);
|
||||
fsm_clear(&sess->sm);
|
||||
|
||||
mme_bearer_remove_all(sess);
|
||||
|
|
|
@ -144,8 +144,8 @@ struct _mme_ue_t {
|
|||
fsm_t sm; /* A state machine */
|
||||
|
||||
/* UE identity */
|
||||
#define MME_UE_HAVE_IMSI(mme) \
|
||||
((mme) && ((mme)->imsi_len))
|
||||
#define MME_UE_HAVE_IMSI(__mME) \
|
||||
((__mME) && ((__mME)->imsi_len))
|
||||
c_uint8_t imsi[MAX_IMSI_LEN];
|
||||
int imsi_len;
|
||||
c_int8_t imsi_bcd[MAX_IMSI_BCD_LEN+1];
|
||||
|
@ -164,14 +164,14 @@ struct _mme_ue_t {
|
|||
e_cgi_t e_cgi;
|
||||
plmn_id_t visited_plmn_id;
|
||||
|
||||
#define SECURITY_CONTEXT_IS_VALID(mme) \
|
||||
((mme) && \
|
||||
((mme)->security_context_available == 1) && ((mme)->mac_failed == 0))
|
||||
#define CLEAR_SECURITY_CONTEXT(mme) \
|
||||
#define SECURITY_CONTEXT_IS_VALID(__mME) \
|
||||
((__mME) && \
|
||||
((__mME)->security_context_available == 1) && ((__mME)->mac_failed == 0))
|
||||
#define CLEAR_SECURITY_CONTEXT(__mME) \
|
||||
do { \
|
||||
d_assert((mme), break, "Null param"); \
|
||||
(mme)->security_context_available = 0; \
|
||||
(mme)->mac_failed = 0; \
|
||||
d_assert((__mME), break, "Null param"); \
|
||||
(__mME)->security_context_available = 0; \
|
||||
(__mME)->mac_failed = 0; \
|
||||
} while(0)
|
||||
int security_context_available;
|
||||
int mac_failed;
|
||||
|
@ -215,10 +215,10 @@ struct _mme_ue_t {
|
|||
#define MIN_EPS_BEARER_ID 5
|
||||
#define MAX_EPS_BEARER_ID 15
|
||||
|
||||
#define CLEAR_EPS_BEARER_ID(mme) \
|
||||
#define CLEAR_EPS_BEARER_ID(__mME) \
|
||||
do { \
|
||||
d_assert((mme), break, "Null param"); \
|
||||
(mme)->ebi = MIN_EPS_BEARER_ID - 1; \
|
||||
d_assert((__mME), break, "Null param"); \
|
||||
(__mME)->ebi = MIN_EPS_BEARER_ID - 1; \
|
||||
} while(0)
|
||||
c_uint8_t ebi; /* EPS Bearer ID generator */
|
||||
list_t sess_list;
|
||||
|
@ -238,24 +238,10 @@ struct _mme_ue_t {
|
|||
/* UE Radio Capability */
|
||||
void *radio_capa;
|
||||
|
||||
#define MME_UE_DETACH_INITIATED(mme) \
|
||||
((mme_ue) && (mme_ue)->detach_type.detach_type)
|
||||
#define SET_DETACH_TYPE(mme, type) \
|
||||
do { \
|
||||
d_assert((mme), break, "Null param"); \
|
||||
(mme)->detach_type = (type); \
|
||||
} while(0)
|
||||
#define CLEAR_DETACH_TYPE(mme) \
|
||||
do { \
|
||||
d_assert((mme), break, "Null param"); \
|
||||
memset(&((mme)->detach_type), 0, sizeof(nas_detach_type_t)); \
|
||||
} while(0)
|
||||
/* Detach Request */
|
||||
nas_detach_type_t detach_type;
|
||||
};
|
||||
|
||||
#define MME_UE_IN_ATTACH_STATE(mme) \
|
||||
((mme) && mme_sess_first(mme) && \
|
||||
(mme_sess_next(mme_sess_first(mme)) == NULL))
|
||||
typedef struct _mme_sess_t {
|
||||
lnode_t node; /* A node of list_t */
|
||||
index_t index; /* An index of this node */
|
||||
|
@ -267,22 +253,22 @@ typedef struct _mme_sess_t {
|
|||
list_t bearer_list;
|
||||
|
||||
/* Related Context */
|
||||
#define MME_S11_PATH_IN_SESSION(session) \
|
||||
#define MME_S11_PATH_IN_SESSION(__sESS) \
|
||||
do { \
|
||||
d_assert((session), return, "Null param"); \
|
||||
(session)->sgw = mme_sgw_next((session)->sgw); \
|
||||
if (!(session)->sgw) (session)->sgw = mme_sgw_first(); \
|
||||
d_assert((session)->sgw, return, "Null param"); \
|
||||
d_assert((__sESS), return, "Null param"); \
|
||||
(__sESS)->sgw = mme_sgw_next((__sESS)->sgw); \
|
||||
if (!(__sESS)->sgw) (__sESS)->sgw = mme_sgw_first(); \
|
||||
d_assert((__sESS)->sgw, return, "Null param"); \
|
||||
} while(0)
|
||||
mme_sgw_t *sgw;
|
||||
mme_ue_t *mme_ue;
|
||||
|
||||
#define MME_UE_HAVE_APN(mme) \
|
||||
((mme) && (mme_sess_first(mme)) && \
|
||||
((mme_sess_first(mme))->pdn))
|
||||
#define MME_SESSION_GET_PGW_IPV4_ADDR(sess) \
|
||||
(((sess) && ((sess)->pdn) && (((sess)->pdn)->pgw.ipv4_addr)) ? \
|
||||
(((sess)->pdn)->pgw.ipv4_addr) : (mme_self()->s5c_addr))
|
||||
#define MME_UE_HAVE_APN(__mME) \
|
||||
((__mME) && (mme_sess_first(__mME)) && \
|
||||
((mme_sess_first(__mME))->pdn))
|
||||
#define MME_SESSION_GET_PGW_IPV4_ADDR(__sESS) \
|
||||
(((__sESS) && ((__sESS)->pdn) && (((__sESS)->pdn)->pgw.ipv4_addr)) ? \
|
||||
(((__sESS)->pdn)->pgw.ipv4_addr) : (mme_self()->s5c_addr))
|
||||
pdn_t *pdn;
|
||||
|
||||
/* Protocol Configuration Options */
|
||||
|
@ -298,19 +284,14 @@ typedef struct _mme_bearer_t {
|
|||
|
||||
c_uint8_t ebi; /* EPS Bearer ID */
|
||||
|
||||
#define MME_UE_HAVE_SESSION(mme) \
|
||||
((mme) && (mme_sess_first(mme)) && \
|
||||
(mme_default_bearer_in_sess(mme_sess_first(mme))) && \
|
||||
((mme_default_bearer_in_sess(mme_sess_first(mme)))->sgw_s1u_teid) && \
|
||||
((mme_default_bearer_in_sess(mme_sess_first(mme)))->sgw_s1u_addr))
|
||||
#define MME_SESSION_IS_VALID(__sESS) \
|
||||
((__sESS) && (mme_bearer_first(__sESS)) && \
|
||||
((mme_default_bearer_in_sess(__sESS)->sgw_s1u_teid) && \
|
||||
(mme_default_bearer_in_sess(__sESS)->sgw_s1u_addr)))
|
||||
|
||||
#define MME_UE_HAVE_DEFAULT_BEARER(mme) \
|
||||
((mme) && (mme_sess_first(mme)) && \
|
||||
(mme_default_bearer_in_sess(mme_sess_first(mme))) && \
|
||||
((mme_default_bearer_in_sess(mme_sess_first(mme)))->enb_s1u_teid) && \
|
||||
((mme_default_bearer_in_sess(mme_sess_first(mme)))->enb_s1u_addr) && \
|
||||
((mme_default_bearer_in_sess(mme_sess_first(mme)))->sgw_s1u_teid) && \
|
||||
((mme_default_bearer_in_sess(mme_sess_first(mme)))->sgw_s1u_addr))
|
||||
#define MME_UE_HAVE_SESSION(__mME) \
|
||||
((__mME) && (mme_sess_first(__mME)) && \
|
||||
MME_SESSION_IS_VALID(mme_sess_first(__mME)))
|
||||
c_uint32_t enb_s1u_teid;
|
||||
c_uint32_t enb_s1u_addr;
|
||||
c_uint32_t sgw_s1u_teid;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define __MME_EVENT_H__
|
||||
|
||||
#include "core_event.h"
|
||||
#include "core_fsm.h"
|
||||
#include "core_pkbuf.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -118,35 +118,44 @@ void mme_s11_handle_create_session_response(
|
|||
d_assert(rv == CORE_OK, return, "xact_commit error");
|
||||
}
|
||||
|
||||
void mme_s11_handle_delete_all_sessions_request_in_ue(mme_ue_t *mme_ue)
|
||||
void mme_s11_handle_delete_all_sessions_in_ue(mme_ue_t *mme_ue)
|
||||
{
|
||||
status_t rv;
|
||||
pkbuf_t *s11buf = NULL;
|
||||
mme_sess_t *sess = NULL;
|
||||
mme_sess_t *sess = NULL, *next_sess = NULL;
|
||||
|
||||
d_assert(mme_ue, return, "Null param");
|
||||
sess = mme_sess_first(mme_ue);
|
||||
while (sess != NULL)
|
||||
{
|
||||
gtp_header_t h;
|
||||
gtp_xact_t *xact = NULL;
|
||||
next_sess = mme_sess_next(sess);
|
||||
|
||||
memset(&h, 0, sizeof(gtp_header_t));
|
||||
h.type = GTP_DELETE_SESSION_REQUEST_TYPE;
|
||||
h.teid = mme_ue->sgw_s11_teid;
|
||||
if (MME_SESSION_IS_VALID(sess))
|
||||
{
|
||||
gtp_header_t h;
|
||||
gtp_xact_t *xact = NULL;
|
||||
|
||||
rv = mme_s11_build_delete_session_request(&s11buf, h.type, sess);
|
||||
d_assert(rv == CORE_OK, return, "S11 build error");
|
||||
memset(&h, 0, sizeof(gtp_header_t));
|
||||
h.type = GTP_DELETE_SESSION_REQUEST_TYPE;
|
||||
h.teid = mme_ue->sgw_s11_teid;
|
||||
|
||||
xact = gtp_xact_local_create(sess->sgw, &h, s11buf);
|
||||
d_assert(xact, return, "Null param");
|
||||
rv = mme_s11_build_delete_session_request(&s11buf, h.type, sess);
|
||||
d_assert(rv == CORE_OK, return, "S11 build error");
|
||||
|
||||
GTP_XACT_STORE_SESSION(xact, sess);
|
||||
xact = gtp_xact_local_create(sess->sgw, &h, s11buf);
|
||||
d_assert(xact, return, "Null param");
|
||||
|
||||
rv = gtp_xact_commit(xact);
|
||||
d_assert(rv == CORE_OK, return, "xact_commit error");
|
||||
GTP_XACT_STORE_SESSION(xact, sess);
|
||||
|
||||
sess = mme_sess_next(sess);
|
||||
rv = gtp_xact_commit(xact);
|
||||
d_assert(rv == CORE_OK, return, "xact_commit error");
|
||||
}
|
||||
else
|
||||
{
|
||||
mme_sess_remove(sess);
|
||||
}
|
||||
|
||||
sess = next_sess;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,8 +12,7 @@ extern "C" {
|
|||
CORE_DECLARE(void) mme_s11_handle_create_session_request(mme_sess_t *sess);
|
||||
CORE_DECLARE(void) mme_s11_handle_create_session_response(
|
||||
gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_create_session_response_t *rsp);
|
||||
CORE_DECLARE(void) mme_s11_handle_delete_all_sessions_request_in_ue(
|
||||
mme_ue_t *mme_ue);
|
||||
CORE_DECLARE(void) mme_s11_handle_delete_all_sessions_in_ue(mme_ue_t *mme_ue);
|
||||
CORE_DECLARE(void) mme_s11_handle_delete_session_response(
|
||||
gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_delete_session_response_t *rsp);
|
||||
|
||||
|
|
213
src/mme/mme_sm.c
213
src/mme/mme_sm.c
|
@ -34,8 +34,6 @@ void mme_state_final(fsm_t *s, event_t *e)
|
|||
d_assert(s, return, "Null param");
|
||||
}
|
||||
|
||||
int test = 0;
|
||||
|
||||
void mme_state_operational(fsm_t *s, event_t *e)
|
||||
{
|
||||
status_t rv;
|
||||
|
@ -113,11 +111,7 @@ void mme_state_operational(fsm_t *s, event_t *e)
|
|||
}
|
||||
case MME_EVT_S1AP_LO_CONNREFUSED:
|
||||
{
|
||||
index_t index = event_get_param1(e);
|
||||
mme_enb_t *enb = NULL;
|
||||
|
||||
d_assert(index, break, "Null param");
|
||||
enb = mme_enb_find(index);
|
||||
mme_enb_t *enb = mme_enb_find(event_get_param1(e));
|
||||
if (enb)
|
||||
{
|
||||
d_trace(1, "eNB-S1[%x] connection refused!!!\n",
|
||||
|
@ -134,12 +128,11 @@ void mme_state_operational(fsm_t *s, event_t *e)
|
|||
case MME_EVT_S1AP_MESSAGE:
|
||||
{
|
||||
s1ap_message_t message;
|
||||
index_t index = event_get_param1(e);
|
||||
mme_enb_t *enb = NULL;
|
||||
pkbuf_t *pkbuf = NULL;
|
||||
|
||||
d_assert(index, break, "Null param");
|
||||
d_assert(enb = mme_enb_find(index), break, "No eNB context");
|
||||
enb = mme_enb_find(event_get_param1(e));
|
||||
d_assert(enb, break, "No eNB context");
|
||||
d_assert(FSM_STATE(&enb->sm), break, "No S1AP State Machine");
|
||||
|
||||
pkbuf = (pkbuf_t *)event_get_param2(e);
|
||||
|
@ -157,14 +150,13 @@ void mme_state_operational(fsm_t *s, event_t *e)
|
|||
case MME_EVT_EMM_MESSAGE:
|
||||
{
|
||||
nas_message_t message;
|
||||
index_t index = event_get_param1(e);
|
||||
pkbuf_t *pkbuf = (pkbuf_t *)event_get_param3(e);
|
||||
pkbuf_t *pkbuf = NULL;
|
||||
enb_ue_t *enb_ue = NULL;
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
|
||||
enb_ue = enb_ue_find(index);
|
||||
enb_ue = enb_ue_find(event_get_param1(e));
|
||||
d_assert(enb_ue, break, "No ENB UE context");
|
||||
|
||||
pkbuf = (pkbuf_t *)event_get_param3(e);
|
||||
d_assert(pkbuf, break, "Null param");
|
||||
d_assert(nas_emm_decode(&message, pkbuf) == CORE_OK,
|
||||
pkbuf_free(pkbuf); break, "Can't decode NAS_EMM");
|
||||
|
@ -220,11 +212,7 @@ void mme_state_operational(fsm_t *s, event_t *e)
|
|||
}
|
||||
case MME_EVT_EMM_T3413:
|
||||
{
|
||||
index_t index = event_get_param1(e);
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
|
||||
d_assert(index, break, "Null param");
|
||||
mme_ue = mme_ue_find(index);
|
||||
mme_ue_t *mme_ue = mme_ue_find(event_get_param1(e));
|
||||
d_assert(mme_ue, break, "No UE context");
|
||||
d_assert(FSM_STATE(&mme_ue->sm), break, "No EMM State Machine");
|
||||
|
||||
|
@ -235,13 +223,11 @@ void mme_state_operational(fsm_t *s, event_t *e)
|
|||
case MME_EVT_ESM_MESSAGE:
|
||||
{
|
||||
nas_message_t message;
|
||||
index_t index = event_get_param1(e);
|
||||
mme_sess_t *sess = NULL;
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
pkbuf_t *pkbuf = NULL;
|
||||
|
||||
d_assert(index, break, "Null param");
|
||||
sess = mme_sess_find(index);
|
||||
sess = mme_sess_find(event_get_param1(e));
|
||||
d_assert(sess, break, "No Session context");
|
||||
d_assert(mme_ue = sess->mme_ue, break, "No UE context");
|
||||
d_assert(FSM_STATE(&sess->sm), break, "No ESM State Machine");
|
||||
|
@ -259,6 +245,72 @@ void mme_state_operational(fsm_t *s, event_t *e)
|
|||
|
||||
break;
|
||||
}
|
||||
case MME_EVT_S6A_MESSAGE:
|
||||
{
|
||||
mme_ue_t *mme_ue = mme_ue_find(event_get_param1(e));
|
||||
pkbuf_t *s6abuf = (pkbuf_t *)event_get_param2(e);
|
||||
s6a_message_t *s6a_message = NULL;
|
||||
|
||||
d_assert(mme_ue, return, "Null param");
|
||||
d_assert(s6abuf, return, "Null param");
|
||||
s6a_message = s6abuf->payload;
|
||||
d_assert(s6a_message, return, "Null param");
|
||||
|
||||
switch(s6a_message->cmd_code)
|
||||
{
|
||||
case S6A_CMD_CODE_AUTHENTICATION_INFORMATION:
|
||||
{
|
||||
if (s6a_message->result_code != ER_DIAMETER_SUCCESS)
|
||||
{
|
||||
emm_handle_attach_reject(mme_ue,
|
||||
S1ap_CauseNas_authentication_failure,
|
||||
EMM_CAUSE_EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED,
|
||||
ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED);
|
||||
|
||||
FSM_TRAN(&mme_ue->sm, emm_state_detached);
|
||||
break;
|
||||
}
|
||||
|
||||
mme_s6a_handle_aia(mme_ue, &s6a_message->aia_message);
|
||||
break;
|
||||
}
|
||||
case S6A_CMD_CODE_UPDATE_LOCATION:
|
||||
{
|
||||
if (s6a_message->result_code != ER_DIAMETER_SUCCESS)
|
||||
{
|
||||
emm_handle_attach_reject(mme_ue,
|
||||
S1ap_CauseNas_unspecified,
|
||||
EMM_CAUSE_EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED,
|
||||
ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED);
|
||||
|
||||
FSM_TRAN(&mme_ue->sm, emm_state_detached);
|
||||
break;
|
||||
}
|
||||
|
||||
mme_s6a_handle_ula(mme_ue, &s6a_message->ula_message);
|
||||
|
||||
if (FSM_CHECK(&mme_ue->sm, emm_state_default_esm))
|
||||
{
|
||||
event_emm_to_esm(mme_ue,
|
||||
&mme_ue->last_pdn_connectivity_request);
|
||||
}
|
||||
else if (FSM_CHECK(&mme_ue->sm, emm_state_attached))
|
||||
{
|
||||
d_error("Not implemented for Tracking Area Update");
|
||||
}
|
||||
else
|
||||
d_assert(0,, "Invaild EMM state");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
d_error("Invalid type(%d)", event_get_param2(e));
|
||||
break;
|
||||
}
|
||||
}
|
||||
pkbuf_free(s6abuf);
|
||||
break;
|
||||
}
|
||||
case MME_EVT_S11_MESSAGE:
|
||||
{
|
||||
status_t rv;
|
||||
|
@ -288,14 +340,18 @@ void mme_state_operational(fsm_t *s, event_t *e)
|
|||
{
|
||||
mme_s11_handle_create_session_response(
|
||||
xact, mme_ue, &message.create_session_response);
|
||||
if (MME_UE_IN_ATTACH_STATE(mme_ue))
|
||||
|
||||
if (FSM_CHECK(&mme_ue->sm, emm_state_default_esm))
|
||||
{
|
||||
emm_handle_attach_accept(mme_ue);
|
||||
}
|
||||
else
|
||||
else if (FSM_CHECK(&mme_ue->sm, emm_state_attached))
|
||||
{
|
||||
d_error("Not implemented of multiple PDN");
|
||||
d_assert(0, , "Coming Soon!");
|
||||
}
|
||||
else
|
||||
d_assert(0, break, "Invalid EMM state");
|
||||
|
||||
break;
|
||||
}
|
||||
case GTP_MODIFY_BEARER_RESPONSE_TYPE:
|
||||
|
@ -307,41 +363,26 @@ void mme_state_operational(fsm_t *s, event_t *e)
|
|||
mme_s11_handle_delete_session_response(
|
||||
xact, mme_ue, &message.delete_session_response);
|
||||
|
||||
if (MME_UE_DETACH_INITIATED(mme_ue))
|
||||
{
|
||||
/* Detach Request is Initiated */
|
||||
if (mme_sess_first(mme_ue) == NULL)
|
||||
{
|
||||
/* All session is deleted */
|
||||
emm_handle_detach_accept(mme_ue);
|
||||
}
|
||||
else
|
||||
{
|
||||
d_trace(3, "wait to delete all sessions"
|
||||
"in detach state\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
if (FSM_CHECK(&mme_ue->sm, emm_state_auth))
|
||||
{
|
||||
if (mme_sess_first(mme_ue) == NULL)
|
||||
{
|
||||
/* If no session, it menas UE try to attach */
|
||||
mme_s6a_send_air(mme_ue);
|
||||
}
|
||||
else
|
||||
}
|
||||
else if (FSM_CHECK(&mme_ue->sm, emm_state_detached))
|
||||
{
|
||||
if (mme_sess_first(mme_ue) == NULL)
|
||||
{
|
||||
if (SECURITY_CONTEXT_IS_VALID(mme_ue))
|
||||
{
|
||||
/* PDN Disconnect Request */
|
||||
d_error("Not implemented of multiple PDN");
|
||||
}
|
||||
else
|
||||
{
|
||||
d_trace(3, "wait to delete all sessions"
|
||||
"in no security context\n");
|
||||
}
|
||||
emm_handle_detach_accept(mme_ue);
|
||||
}
|
||||
}
|
||||
else if (FSM_CHECK(&mme_ue->sm, emm_state_attached))
|
||||
{
|
||||
d_assert(0, , "Coming Soon!");
|
||||
}
|
||||
else
|
||||
d_assert(0, break, "Invalid EMM state");
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -377,74 +418,6 @@ void mme_state_operational(fsm_t *s, event_t *e)
|
|||
gtp_xact_timeout(event_get_param1(e), event_get(e));
|
||||
break;
|
||||
}
|
||||
case MME_EVT_S6A_MESSAGE:
|
||||
{
|
||||
index_t index = event_get_param1(e);
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
pkbuf_t *s6abuf = (pkbuf_t *)event_get_param2(e);
|
||||
s6a_message_t *s6a_message = NULL;
|
||||
|
||||
d_assert(index, return, "Null param");
|
||||
mme_ue = mme_ue_find(index);
|
||||
d_assert(mme_ue, return, "Null param");
|
||||
|
||||
d_assert(s6abuf, return, "Null param");
|
||||
s6a_message = s6abuf->payload;
|
||||
d_assert(s6a_message, return, "Null param");
|
||||
|
||||
switch(s6a_message->cmd_code)
|
||||
{
|
||||
case S6A_CMD_CODE_AUTHENTICATION_INFORMATION:
|
||||
{
|
||||
if (s6a_message->result_code != ER_DIAMETER_SUCCESS)
|
||||
{
|
||||
emm_handle_attach_reject(mme_ue,
|
||||
S1ap_CauseNas_authentication_failure,
|
||||
EMM_CAUSE_EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED,
|
||||
ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
mme_s6a_handle_aia(mme_ue, &s6a_message->aia_message);
|
||||
break;
|
||||
}
|
||||
case S6A_CMD_CODE_UPDATE_LOCATION:
|
||||
{
|
||||
if (s6a_message->result_code != ER_DIAMETER_SUCCESS)
|
||||
{
|
||||
emm_handle_attach_reject(mme_ue,
|
||||
S1ap_CauseNas_unspecified,
|
||||
EMM_CAUSE_EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED,
|
||||
ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
mme_s6a_handle_ula(mme_ue, &s6a_message->ula_message);
|
||||
|
||||
if (MME_UE_HAVE_DEFAULT_BEARER(mme_ue))
|
||||
{
|
||||
/* if there is default bearer, UE attached completely */
|
||||
d_error("Not implemented for Tracking Area Update");
|
||||
}
|
||||
else
|
||||
{
|
||||
event_emm_to_esm(mme_ue,
|
||||
&mme_ue->last_pdn_connectivity_request);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
d_error("Invalid type(%d)", event_get_param2(e));
|
||||
break;
|
||||
}
|
||||
}
|
||||
pkbuf_free(s6abuf);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
d_error("No handler for event %s", mme_event_get_name(e));
|
||||
|
|
|
@ -21,7 +21,11 @@ void s1ap_state_exception(fsm_t *s, event_t *e);
|
|||
|
||||
void emm_state_initial(fsm_t *s, event_t *e);
|
||||
void emm_state_final(fsm_t *s, event_t *e);
|
||||
void emm_state_operational(fsm_t *s, event_t *e);
|
||||
void emm_state_detached(fsm_t *s, event_t *e);
|
||||
void emm_state_identity(fsm_t *s, event_t *e);
|
||||
void emm_state_auth(fsm_t *s, event_t *e);
|
||||
void emm_state_default_esm(fsm_t *s, event_t *e);
|
||||
void emm_state_attached(fsm_t *s, event_t *e);
|
||||
void emm_state_exception(fsm_t *s, event_t *e);
|
||||
|
||||
void esm_state_initial(fsm_t *s, event_t *e);
|
||||
|
|
|
@ -28,11 +28,16 @@ void s1ap_state_final(fsm_t *s, event_t *e)
|
|||
|
||||
void s1ap_state_operational(fsm_t *s, event_t *e)
|
||||
{
|
||||
mme_enb_t *enb = NULL;
|
||||
|
||||
d_assert(s, return, "Null param");
|
||||
d_assert(e, return, "Null param");
|
||||
|
||||
mme_sm_trace(3, e);
|
||||
|
||||
enb = mme_enb_find(event_get_param1(e));
|
||||
d_assert(enb, return, "Null param");
|
||||
|
||||
switch (event_get(e))
|
||||
{
|
||||
case FSM_ENTRY_SIG:
|
||||
|
@ -45,15 +50,7 @@ void s1ap_state_operational(fsm_t *s, event_t *e)
|
|||
}
|
||||
case MME_EVT_S1AP_MESSAGE:
|
||||
{
|
||||
index_t index = event_get_param1(e);
|
||||
mme_enb_t *enb = NULL;
|
||||
s1ap_message_t *message = NULL;
|
||||
|
||||
d_assert(index, return, "Null param");
|
||||
enb = mme_enb_find(index);
|
||||
d_assert(enb, return, "Null param");
|
||||
|
||||
message = (s1ap_message_t *)event_get_param3(e);
|
||||
s1ap_message_t *message = (s1ap_message_t *)event_get_param3(e);
|
||||
d_assert(message, break, "Null param");
|
||||
|
||||
switch(message->direction)
|
||||
|
|
|
@ -91,11 +91,11 @@ typedef struct _pgw_sess_t {
|
|||
list_t bearer_list;
|
||||
|
||||
/* Related Context */
|
||||
#define PGW_S5C_PATH_IN_SESSION(session, xaction) \
|
||||
#define PGW_S5C_PATH_IN_SESSION(__sESS, __xACT) \
|
||||
do { \
|
||||
d_assert((session), return, "Null param"); \
|
||||
d_assert((xaction), return, "Null param"); \
|
||||
(session)->sgw = (xaction)->gnode; \
|
||||
d_assert((__sESS), return, "Null param"); \
|
||||
d_assert((__xACT), return, "Null param"); \
|
||||
(__sESS)->sgw = (__xACT)->gnode; \
|
||||
} while(0)
|
||||
pgw_sgw_t *sgw;
|
||||
} pgw_sess_t;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define __PGW_EVENT_H__
|
||||
|
||||
#include "core_event.h"
|
||||
#include "core_fsm.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
|
@ -83,18 +83,18 @@ typedef struct _sgw_sess_t {
|
|||
list_t bearer_list;
|
||||
|
||||
/* Related Context */
|
||||
#define SGW_S11_PATH_IN_SESSION(session, xaction) \
|
||||
#define SGW_S11_PATH_IN_SESSION(__sESS, __xACT) \
|
||||
do { \
|
||||
d_assert((session), return, "Null param"); \
|
||||
d_assert((xaction), return, "Null param"); \
|
||||
(session)->mme = (xaction)->gnode; \
|
||||
d_assert((__sESS), return, "Null param"); \
|
||||
d_assert((__xACT), return, "Null param"); \
|
||||
(__sESS)->mme = (__xACT)->gnode; \
|
||||
} while(0)
|
||||
sgw_mme_t *mme;
|
||||
#define SGW_S5C_PATH_IN_SESSION(session, gnode) \
|
||||
#define SGW_S5C_PATH_IN_SESSION(__sESS, __gNODE) \
|
||||
do { \
|
||||
d_assert((session), return, "Null param"); \
|
||||
d_assert((gnode), return, "Null param"); \
|
||||
(session)->pgw = gnode; \
|
||||
d_assert((__sESS), return, "Null param"); \
|
||||
d_assert((__gNODE), return, "Null param"); \
|
||||
(__sESS)->pgw = __gNODE; \
|
||||
} while(0)
|
||||
sgw_mme_t *pgw;
|
||||
sgw_ue_t *sgw_ue;
|
||||
|
@ -132,14 +132,14 @@ typedef struct _sgw_bearer_t {
|
|||
|
||||
#define SGW_DL_NOTI_SENT 0x0001
|
||||
|
||||
#define CHECK_DL_NOTI_SENT(bearer) ((bearer)->state & SGW_DL_NOTI_SENT)
|
||||
#define SET_DL_NOTI_SENT(bearer) \
|
||||
#define CHECK_DL_NOTI_SENT(__bEARER) ((__bEARER)->state & SGW_DL_NOTI_SENT)
|
||||
#define SET_DL_NOTI_SENT(__bEARER) \
|
||||
do { \
|
||||
(bearer)->state |= SGW_DL_NOTI_SENT;\
|
||||
(__bEARER)->state |= SGW_DL_NOTI_SENT;\
|
||||
} while (0)
|
||||
#define RESET_DL_NOTI_SENT(bearer) \
|
||||
#define RESET_DL_NOTI_SENT(__bEARER) \
|
||||
do { \
|
||||
(bearer)->state &= ~SGW_DL_NOTI_SENT;\
|
||||
(__bEARER)->state &= ~SGW_DL_NOTI_SENT;\
|
||||
} while (0)
|
||||
|
||||
CORE_DECLARE(status_t) sgw_context_init(void);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define __SGW_EVENT_H__
|
||||
|
||||
#include "core_event.h"
|
||||
#include "core_fsm.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
|
@ -301,6 +301,18 @@ static void attach_test1(abts_case *tc, void *data)
|
|||
rc = tests1ap_enb_read(sock, recvbuf);
|
||||
pkbuf_free(recvbuf);
|
||||
|
||||
/* Send Attach Complete +
|
||||
* Activate Default EPS Bearer Context Accept */
|
||||
rv = tests1ap_build_attach_complete(&sendbuf, msgindex+1);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
rv = tests1ap_enb_send(sock, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
/* Receive EMM information */
|
||||
recvbuf = pkbuf_alloc(0, MAX_SDU_LEN);
|
||||
rc = tests1ap_enb_read(sock, recvbuf);
|
||||
pkbuf_free(recvbuf);
|
||||
|
||||
/* Send Detach Request */
|
||||
rv = tests1ap_build_detach_request(&sendbuf, msgindex);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
@ -570,6 +582,18 @@ static void attach_test2(abts_case *tc, void *data)
|
|||
rc = tests1ap_enb_read(sock, recvbuf);
|
||||
pkbuf_free(recvbuf);
|
||||
|
||||
/* Send Attach Complete +
|
||||
* Activate Default EPS Bearer Context Accept */
|
||||
rv = tests1ap_build_attach_complete(&sendbuf, msgindex+1);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
rv = tests1ap_enb_send(sock, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
/* Receive EMM information */
|
||||
recvbuf = pkbuf_alloc(0, MAX_SDU_LEN);
|
||||
rc = tests1ap_enb_read(sock, recvbuf);
|
||||
pkbuf_free(recvbuf);
|
||||
|
||||
/*****************************************************************
|
||||
* Attach Request : IMSI, Integrity Protected, MAC Failed
|
||||
* Send Initial-UE Message + Attach Request + PDN Connectivity */
|
||||
|
|
|
@ -490,11 +490,16 @@ status_t tests1ap_build_attach_complete(pkbuf_t **pkbuf, int i)
|
|||
"403a000005000000 05c00100009d0008 00020001001a000e 0d27c183eb950207"
|
||||
"4300035200c20064 40080000f1101079 baf0004340060000 f1105ba0",
|
||||
|
||||
"",
|
||||
"000d"
|
||||
"403a000005000000 05c00100009e0008 00020002001a000e 0d27e8a2a3f10207"
|
||||
"4300035200c20064 40080000f1101079 baf0004340060000 f1105ba0",
|
||||
|
||||
"",
|
||||
|
||||
"",
|
||||
"",
|
||||
"000d"
|
||||
"403a000005000000 05c0010000020008 00020011001a000e 0d27225d92bb0207"
|
||||
"4300035200c20064 40080000f1101079 baf0004340060000 f1105ba0",
|
||||
"",
|
||||
|
||||
"000d"
|
||||
|
@ -506,11 +511,11 @@ status_t tests1ap_build_attach_complete(pkbuf_t **pkbuf, int i)
|
|||
};
|
||||
c_uint16_t len[TESTS1AP_MAX_MESSAGE] = {
|
||||
62,
|
||||
0,
|
||||
62,
|
||||
0,
|
||||
|
||||
0,
|
||||
0,
|
||||
62,
|
||||
0,
|
||||
|
||||
62,
|
||||
|
|
Loading…
Reference in New Issue