2017-02-13 05:41:20 +00:00
|
|
|
#define TRACE_MODULE _enb_s1_sm
|
2017-03-05 07:49:57 +00:00
|
|
|
|
2017-02-13 05:41:20 +00:00
|
|
|
#include "core_debug.h"
|
|
|
|
|
2017-02-20 10:46:58 +00:00
|
|
|
#include "s1ap_build.h"
|
2017-02-13 05:41:20 +00:00
|
|
|
#include "s1ap_conv.h"
|
|
|
|
#include "s1ap_path.h"
|
|
|
|
|
2017-03-05 07:49:57 +00:00
|
|
|
#include "sm.h"
|
|
|
|
#include "context.h"
|
|
|
|
#include "event.h"
|
|
|
|
|
2017-03-06 08:55:50 +00:00
|
|
|
static void enb_s1ap_handle_s1_setup_request(
|
|
|
|
enb_ctx_t *enb, s1ap_message_t *message);
|
|
|
|
static void enb_s1ap_handle_initial_ue_message(
|
2017-03-06 00:07:59 +00:00
|
|
|
enb_ctx_t *enb, s1ap_message_t *message);
|
2017-02-13 05:41:20 +00:00
|
|
|
|
2017-03-05 04:03:11 +00:00
|
|
|
void enb_s1ap_state_initial(enb_s1ap_sm_t *s, event_t *e)
|
2017-02-13 05:41:20 +00:00
|
|
|
{
|
|
|
|
d_assert(s, return, "Null param");
|
|
|
|
|
|
|
|
sm_trace(1, e);
|
|
|
|
|
2017-03-05 02:30:40 +00:00
|
|
|
FSM_TRAN(s, &enb_s1ap_state_operational);
|
2017-02-13 05:41:20 +00:00
|
|
|
}
|
|
|
|
|
2017-03-05 04:03:11 +00:00
|
|
|
void enb_s1ap_state_final(enb_s1ap_sm_t *s, event_t *e)
|
2017-02-13 05:41:20 +00:00
|
|
|
{
|
|
|
|
d_assert(s, return, "Null param");
|
|
|
|
|
|
|
|
sm_trace(1, e);
|
|
|
|
}
|
|
|
|
|
2017-03-05 04:03:11 +00:00
|
|
|
void enb_s1ap_state_operational(enb_s1ap_sm_t *s, event_t *e)
|
2017-02-13 05:41:20 +00:00
|
|
|
{
|
|
|
|
d_assert(s, return, "Null param");
|
|
|
|
d_assert(e, return, "Null param");
|
|
|
|
|
|
|
|
enb_ctx_t *enb = s->ctx;
|
|
|
|
d_assert(enb, return, "Null param");
|
|
|
|
|
|
|
|
sm_trace(1, e);
|
|
|
|
|
|
|
|
switch (event_get(e))
|
|
|
|
{
|
|
|
|
case FSM_ENTRY_SIG:
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FSM_EXIT_SIG:
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2017-03-05 08:07:43 +00:00
|
|
|
case EVT_MSG_ENB_S1AP:
|
2017-02-13 05:41:20 +00:00
|
|
|
{
|
2017-03-06 00:07:59 +00:00
|
|
|
s1ap_message_t message;
|
2017-02-13 05:41:20 +00:00
|
|
|
status_t rv;
|
2017-03-05 08:05:30 +00:00
|
|
|
pkbuf_t *recvbuf = (pkbuf_t *)event_get_param2(e);
|
2017-03-05 09:09:34 +00:00
|
|
|
d_assert(recvbuf, break, "Null param");
|
2017-02-13 05:41:20 +00:00
|
|
|
|
|
|
|
rv = s1ap_decode_pdu(&message, recvbuf);
|
|
|
|
if (rv != CORE_OK)
|
|
|
|
{
|
2017-03-05 09:09:34 +00:00
|
|
|
d_error("Can't parse S1AP_PDU");
|
2017-02-13 05:41:20 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(message.direction)
|
|
|
|
{
|
|
|
|
case S1AP_PDU_PR_initiatingMessage :
|
|
|
|
{
|
|
|
|
switch(message.procedureCode)
|
|
|
|
{
|
|
|
|
case S1ap_ProcedureCode_id_S1Setup :
|
|
|
|
{
|
2017-03-06 08:55:50 +00:00
|
|
|
enb_s1ap_handle_s1_setup_request(enb, &message);
|
2017-02-13 05:41:20 +00:00
|
|
|
break;
|
|
|
|
}
|
2017-03-05 07:49:57 +00:00
|
|
|
case S1ap_ProcedureCode_id_initialUEMessage :
|
|
|
|
{
|
2017-03-06 08:55:50 +00:00
|
|
|
enb_s1ap_handle_initial_ue_message(enb, &message);
|
2017-03-05 07:49:57 +00:00
|
|
|
break;
|
|
|
|
}
|
2017-02-13 05:41:20 +00:00
|
|
|
default:
|
|
|
|
{
|
|
|
|
d_warn("Not implemented(choice:%d, proc:%d",
|
|
|
|
message.direction, message.procedureCode);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2017-03-05 08:36:16 +00:00
|
|
|
|
2017-02-13 05:41:20 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case S1AP_PDU_PR_successfulOutcome :
|
|
|
|
{
|
|
|
|
switch(message.procedureCode)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
d_warn("Not implemented(choice:%d, proc:%d",
|
|
|
|
message.direction, message.procedureCode);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case S1AP_PDU_PR_unsuccessfulOutcome :
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
d_warn("Not implemented(choice:%d, proc:%d",
|
|
|
|
message.direction, message.procedureCode);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
s1ap_free_pdu(&message);
|
2017-03-05 08:36:16 +00:00
|
|
|
pkbuf_free(recvbuf);
|
2017-02-13 05:41:20 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
d_error("Unknown event %s", event_get_name(e));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-05 04:03:11 +00:00
|
|
|
void enb_s1ap_state_exception(enb_s1ap_sm_t *s, event_t *e)
|
2017-02-13 05:41:20 +00:00
|
|
|
{
|
|
|
|
d_assert(s, return, "Null param");
|
|
|
|
d_assert(e, return, "Null param");
|
|
|
|
|
|
|
|
sm_trace(1, e);
|
|
|
|
|
|
|
|
switch (event_get(e))
|
|
|
|
{
|
|
|
|
case FSM_ENTRY_SIG:
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FSM_EXIT_SIG:
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
d_error("Unknown event %s", event_get_name(e));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-06 08:55:50 +00:00
|
|
|
static void enb_s1ap_handle_s1_setup_request(
|
|
|
|
enb_ctx_t *enb, s1ap_message_t *message)
|
2017-02-13 05:41:20 +00:00
|
|
|
{
|
|
|
|
char buf[INET_ADDRSTRLEN];
|
|
|
|
|
|
|
|
S1ap_S1SetupRequestIEs_t *ies = NULL;
|
|
|
|
pkbuf_t *sendbuf = NULL;
|
2017-02-13 11:10:05 +00:00
|
|
|
c_uint32_t enb_id;
|
2017-02-13 05:41:20 +00:00
|
|
|
|
2017-03-06 08:55:50 +00:00
|
|
|
d_assert(enb, return, "Null param");
|
|
|
|
d_assert(enb->s1ap_sock, return, "Null param");
|
|
|
|
d_assert(message, return, "Null param");
|
2017-02-13 05:41:20 +00:00
|
|
|
|
2017-03-05 02:46:42 +00:00
|
|
|
ies = &message->s1ap_S1SetupRequestIEs;
|
2017-03-06 08:55:50 +00:00
|
|
|
d_assert(ies, return, "Null param");
|
2017-02-13 05:41:20 +00:00
|
|
|
|
2017-03-05 02:29:15 +00:00
|
|
|
s1ap_ENB_ID_to_uint32(&ies->global_ENB_ID.eNB_ID, &enb_id);
|
2017-03-05 02:46:42 +00:00
|
|
|
|
|
|
|
#if 0 /* FIXME : does it needed? */
|
2017-03-05 04:03:11 +00:00
|
|
|
if (mme_ctx_enb_find_by_enb_id(enb_id))
|
2017-02-13 11:10:05 +00:00
|
|
|
{
|
|
|
|
S1ap_Cause_t cause;
|
|
|
|
d_error("eNB-id[0x%x] duplicated from [%s]", enb_id,
|
2017-03-05 04:03:11 +00:00
|
|
|
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf));
|
2017-02-13 11:10:05 +00:00
|
|
|
|
|
|
|
cause.present = S1ap_Cause_PR_protocol;
|
|
|
|
cause.choice.protocol =
|
|
|
|
S1ap_CauseProtocol_message_not_compatible_with_receiver_state;
|
|
|
|
rv = s1ap_build_setup_failure(&sendbuf, cause);
|
|
|
|
}
|
2017-03-05 02:46:42 +00:00
|
|
|
#endif
|
2017-02-13 11:10:05 +00:00
|
|
|
|
2017-03-05 07:49:57 +00:00
|
|
|
d_info("eNB[0x%x] sends S1-Setup-Request from [%s]", enb_id,
|
|
|
|
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf));
|
2017-02-13 05:41:20 +00:00
|
|
|
|
2017-03-05 07:49:57 +00:00
|
|
|
enb->enb_id = enb_id;
|
2017-02-13 05:41:20 +00:00
|
|
|
|
2017-03-05 07:49:57 +00:00
|
|
|
d_assert(s1ap_build_setup_rsp(&sendbuf) == CORE_OK,
|
2017-03-06 08:55:50 +00:00
|
|
|
return, "build error");
|
|
|
|
d_assert(s1ap_send_to_enb(enb, sendbuf) == CORE_OK, , "send error");
|
2017-02-13 05:41:20 +00:00
|
|
|
|
|
|
|
pkbuf_free(sendbuf);
|
2017-03-06 08:55:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void enb_s1ap_handle_initial_ue_message(
|
|
|
|
enb_ctx_t *enb, s1ap_message_t *message)
|
|
|
|
{
|
|
|
|
ue_ctx_t *ue = NULL;
|
|
|
|
S1ap_InitialUEMessage_IEs_t *ies = NULL;
|
|
|
|
S1ap_NAS_PDU_t *nasPdu = NULL;
|
|
|
|
event_t e;
|
|
|
|
pkbuf_t *sendbuf = NULL;
|
|
|
|
|
|
|
|
ies = &message->s1ap_InitialUEMessage_IEs;
|
|
|
|
d_assert(ies, return, "Null param");
|
|
|
|
|
|
|
|
nasPdu = &ies->nas_pdu;
|
|
|
|
d_assert(nasPdu, return, "Null param");
|
|
|
|
|
|
|
|
sendbuf = pkbuf_alloc(0, nasPdu->size);
|
|
|
|
d_assert(sendbuf, return, "Null param");
|
|
|
|
memcpy(sendbuf->payload, nasPdu->buf, nasPdu->size);
|
|
|
|
|
|
|
|
ue = mme_ctx_ue_find_by_enb_ue_s1ap_id(enb, ies->eNB_UE_S1AP_ID);
|
|
|
|
if (!ue)
|
|
|
|
{
|
|
|
|
ue = mme_ctx_ue_add(enb);
|
|
|
|
d_assert(ue, pkbuf_free(sendbuf);return, "Null param");
|
|
|
|
|
|
|
|
ue->enb_ue_s1ap_id = ies->eNB_UE_S1AP_ID;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
d_warn("Duplicated: eNB[0x%x] sends "
|
|
|
|
"Initial-UE Message[eNB-UE-S1AP-ID(%d)]",
|
|
|
|
enb->enb_id, ue->enb_ue_s1ap_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
d_info("eNB[0x%x] sends Initial-UE Message[eNB-UE-S1AP-ID(%d)]",
|
|
|
|
enb->enb_id, ue->enb_ue_s1ap_id);
|
|
|
|
|
|
|
|
fsm_create((fsm_t*)&ue->emm_sm,
|
|
|
|
ue_emm_state_initial, ue_emm_state_final);
|
|
|
|
ue->emm_sm.ctx = ue;
|
|
|
|
|
|
|
|
fsm_init((fsm_t*)&ue->emm_sm, 0);
|
|
|
|
|
|
|
|
event_set(&e, EVT_MSG_UE_EMM);
|
|
|
|
event_set_param1(&e, (c_uintptr_t)ue);
|
|
|
|
event_set_param2(&e, (c_uintptr_t)sendbuf);
|
2017-02-13 05:41:20 +00:00
|
|
|
|
2017-03-06 08:55:50 +00:00
|
|
|
event_send(mme_self()->queue_id, &e);
|
2017-02-13 05:41:20 +00:00
|
|
|
}
|