add ho failure and ho prep failure... All done

This commit is contained in:
Sukchan Lee 2017-09-15 13:28:07 +09:00
parent a02cca7e54
commit d0fd6c4a73
9 changed files with 298 additions and 164 deletions

View File

@ -216,16 +216,16 @@ static inline int s1ap_free_unsuccessfull_outcome(s1ap_message_t *message)
&message->s1ap_PathSwitchRequestFailureIEs);
break;
case S1ap_ProcedureCode_id_HandoverResourceAllocation:
s1ap_free_s1ap_handoverfailureies(
&message->s1ap_HandoverFailureIEs);
break;
case S1ap_ProcedureCode_id_HandoverPreparation:
s1ap_free_s1ap_handoverpreparationfailureies(
&message->s1ap_HandoverPreparationFailureIEs);
break;
case S1ap_ProcedureCode_id_HandoverResourceAllocation:
s1ap_free_s1ap_handoverfailureies(
&message->s1ap_HandoverFailureIEs);
break;
default:
d_warn("Unknown procedure ID (%d) for unsuccessfull "
"outcome message\n", (int)message->procedureCode);

View File

@ -1498,14 +1498,40 @@ status_t mme_ue_associate_target_ue(mme_ue_t *mme_ue, enb_ue_t *target_ue)
}
/*
* mme_ue is deassociated with source like the following conditions
* mme_ue is deassociated with target_ue like the following conditions
*
* UE Context Release Complete : enb_ue_remove()
* Handover Cancel -> Delete Indirect Tunnel -> Deassociate -> UL Relase
* Handover Cancel -> Deassociate -> UL Relase
* S1AP Handover Failure
*/
status_t mme_ue_deassociate_target_ue(enb_ue_t *target_ue)
{
enb_ue_t *source_ue = NULL;
d_assert(target_ue, return CORE_ERROR,);
target_ue->mme_ue = NULL;
target_ue->source_ue = NULL;
source_ue = target_ue->source_ue;
if (source_ue)
source_ue->target_ue = NULL;
return CORE_OK;
}
/*
* mme_ue is deassociated with source_ue like the following conditions
*
* S1AP UE Context Release Complete : enb_ue_remove()
*/
status_t mme_ue_deassociate_source_ue(enb_ue_t *source_ue)
{
enb_ue_t *target_ue = source_ue->target_ue;
enb_ue_t *target_ue = NULL;
d_assert(source_ue, return CORE_ERROR,);
target_ue = source_ue->target_ue;
if (target_ue)
target_ue->source_ue = NULL;
else if (source_ue->mme_ue)

View File

@ -469,6 +469,7 @@ CORE_DECLARE(status_t) mme_ue_associate_enb_ue(
mme_ue_t *mme_ue, enb_ue_t *enb_ue);
CORE_DECLARE(status_t) mme_ue_associate_target_ue(
mme_ue_t *mme_ue, enb_ue_t *target_ue);
CORE_DECLARE(status_t) mme_ue_deassociate_target_ue(enb_ue_t *target_ue);
CORE_DECLARE(status_t) mme_ue_deassociate_source_ue(enb_ue_t *source_ue);
CORE_DECLARE(hash_index_t *) mme_ue_first();

View File

@ -471,6 +471,8 @@ void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response(
target_ue = source_ue->target_ue;
d_assert(target_ue, return, "Null param");
mme_ue_deassociate_target_ue(target_ue);
cause.present = S1ap_Cause_PR_radioNetwork;
cause.choice.nas = S1ap_CauseRadioNetwork_handover_cancelled;

View File

@ -674,6 +674,150 @@ status_t s1ap_build_path_switch_failure(pkbuf_t **s1apbuf,
return CORE_OK;
}
status_t s1ap_build_handover_command(pkbuf_t **s1apbuf, enb_ue_t *source_ue)
{
char buf[INET_ADDRSTRLEN];
int encoded;
s1ap_message_t message;
S1ap_HandoverCommandIEs_t *ies = &message.s1ap_HandoverCommandIEs;
S1ap_E_RABDataForwardingItem_t *e_rab = NULL;
mme_ue_t *mme_ue = NULL;
mme_sess_t *sess = NULL;
mme_bearer_t *bearer = NULL;
d_assert(source_ue, return CORE_ERROR, "Null param");
mme_ue = source_ue->mme_ue;
memset(&message, 0, sizeof(s1ap_message_t));
ies->mme_ue_s1ap_id = source_ue->mme_ue_s1ap_id;
ies->eNB_UE_S1AP_ID = source_ue->enb_ue_s1ap_id;
ies->handoverType = source_ue->handover_type;
sess = mme_sess_first(mme_ue);
while(sess)
{
bearer = mme_bearer_first(sess);
while(bearer)
{
if (MME_HAVE_SGW_DL_INDIRECT_TUNNEL(bearer) ||
MME_HAVE_SGW_UL_INDIRECT_TUNNEL(bearer))
{
e_rab = (S1ap_E_RABDataForwardingItem_t *)
core_calloc(1, sizeof(S1ap_E_RABDataForwardingItem_t));
e_rab->e_RAB_ID = bearer->ebi;
}
if (MME_HAVE_SGW_DL_INDIRECT_TUNNEL(bearer))
{
e_rab->dL_transportLayerAddress =
(S1ap_TransportLayerAddress_t *)
core_calloc(1, sizeof(S1ap_TransportLayerAddress_t));
e_rab->dL_transportLayerAddress->size = 4;
e_rab->dL_transportLayerAddress->buf = core_calloc(
e_rab->dL_transportLayerAddress->size, sizeof(c_uint8_t));
memcpy(e_rab->dL_transportLayerAddress->buf,
&bearer->sgw_dl_addr,
e_rab->dL_transportLayerAddress->size);
e_rab->dL_gTP_TEID = (S1ap_GTP_TEID_t *)
core_calloc(1, sizeof(S1ap_GTP_TEID_t));
s1ap_uint32_to_OCTET_STRING(
bearer->sgw_dl_teid, e_rab->dL_gTP_TEID);
}
if (MME_HAVE_SGW_UL_INDIRECT_TUNNEL(bearer))
{
e_rab->uL_S1ap_TransportLayerAddress =
(S1ap_TransportLayerAddress_t *)
core_calloc(1, sizeof(S1ap_TransportLayerAddress_t));
e_rab->uL_S1ap_TransportLayerAddress->size = 4;
e_rab->uL_S1ap_TransportLayerAddress->buf = core_calloc(
e_rab->uL_S1ap_TransportLayerAddress->size,
sizeof(c_uint8_t));
memcpy(e_rab->uL_S1ap_TransportLayerAddress->buf,
&bearer->sgw_ul_addr,
e_rab->uL_S1ap_TransportLayerAddress->size);
e_rab->uL_S1ap_GTP_TEID = (S1ap_GTP_TEID_t *)
core_calloc(1, sizeof(S1ap_GTP_TEID_t));
s1ap_uint32_to_OCTET_STRING(
bearer->sgw_ul_teid, e_rab->uL_S1ap_GTP_TEID);
}
if (MME_HAVE_SGW_DL_INDIRECT_TUNNEL(bearer) ||
MME_HAVE_SGW_UL_INDIRECT_TUNNEL(bearer))
{
ASN_SEQUENCE_ADD(&ies->e_RABDataForwardingList, e_rab);
}
bearer = mme_bearer_next(bearer);
}
sess = mme_sess_next(sess);
}
if (ies->e_RABDataForwardingList.s1ap_E_RABDataForwardingItem.count)
{
ies->presenceMask |=
S1AP_HANDOVERCOMMANDIES_E_RABDATAFORWARDINGLIST_PRESENT;
}
s1ap_buffer_to_OCTET_STRING(mme_ue->container.buf, mme_ue->container.size,
&ies->target_ToSource_TransparentContainer);
S1AP_CLEAR_DATA(&mme_ue->container);
message.procedureCode = S1ap_ProcedureCode_id_HandoverPreparation;
message.direction = S1AP_PDU_PR_successfulOutcome;
encoded = s1ap_encode_pdu(s1apbuf, &message);
s1ap_free_pdu(&message);
d_assert(s1apbuf && encoded >= 0,return CORE_ERROR,);
d_trace(3, "[S1AP] Handover Command : ",
"UE[mME-UE-S1AP-ID(%d)] <-- eNB[%s:%d]\n",
source_ue->mme_ue_s1ap_id,
INET_NTOP(&source_ue->enb->s1ap_sock->remote.sin_addr.s_addr, buf),
source_ue->enb->enb_id);
return CORE_OK;
}
status_t s1ap_build_handover_preparation_failure(
pkbuf_t **s1apbuf, enb_ue_t *source_ue, S1ap_Cause_t *cause)
{
char buf[INET_ADDRSTRLEN];
int encoded;
s1ap_message_t message;
S1ap_HandoverPreparationFailureIEs_t *ies =
&message.s1ap_HandoverPreparationFailureIEs;
memset(&message, 0, sizeof(s1ap_message_t));
ies->mme_ue_s1ap_id = source_ue->mme_ue_s1ap_id;
ies->eNB_UE_S1AP_ID = source_ue->enb_ue_s1ap_id;
s1ap_build_cause(&ies->cause, cause);
message.procedureCode = S1ap_ProcedureCode_id_HandoverPreparation;
message.direction = S1AP_PDU_PR_unsuccessfulOutcome;
encoded = s1ap_encode_pdu(s1apbuf, &message);
s1ap_free_pdu(&message);
d_assert(s1apbuf && encoded >= 0,return CORE_ERROR,);
d_trace(3, "[S1AP] Handover Preparation Failure : ",
"UE[mME-UE-S1AP-ID(%d)] <-- eNB[%s:%d]\n",
source_ue->mme_ue_s1ap_id,
INET_NTOP(&source_ue->enb->s1ap_sock->remote.sin_addr.s_addr, buf),
source_ue->enb->enb_id);
return CORE_OK;
}
status_t s1ap_build_handover_request(
pkbuf_t **s1apbuf, mme_ue_t *mme_ue, enb_ue_t *target_ue,
S1ap_HandoverRequiredIEs_t *required)
@ -817,117 +961,6 @@ status_t s1ap_build_handover_request(
return CORE_OK;
}
status_t s1ap_build_handover_command(pkbuf_t **s1apbuf, enb_ue_t *source_ue)
{
char buf[INET_ADDRSTRLEN];
int encoded;
s1ap_message_t message;
S1ap_HandoverCommandIEs_t *ies = &message.s1ap_HandoverCommandIEs;
S1ap_E_RABDataForwardingItem_t *e_rab = NULL;
mme_ue_t *mme_ue = NULL;
mme_sess_t *sess = NULL;
mme_bearer_t *bearer = NULL;
d_assert(source_ue, return CORE_ERROR, "Null param");
mme_ue = source_ue->mme_ue;
memset(&message, 0, sizeof(s1ap_message_t));
ies->mme_ue_s1ap_id = source_ue->mme_ue_s1ap_id;
ies->eNB_UE_S1AP_ID = source_ue->enb_ue_s1ap_id;
ies->handoverType = source_ue->handover_type;
sess = mme_sess_first(mme_ue);
while(sess)
{
bearer = mme_bearer_first(sess);
while(bearer)
{
if (MME_HAVE_SGW_DL_INDIRECT_TUNNEL(bearer) ||
MME_HAVE_SGW_UL_INDIRECT_TUNNEL(bearer))
{
e_rab = (S1ap_E_RABDataForwardingItem_t *)
core_calloc(1, sizeof(S1ap_E_RABDataForwardingItem_t));
e_rab->e_RAB_ID = bearer->ebi;
}
if (MME_HAVE_SGW_DL_INDIRECT_TUNNEL(bearer))
{
e_rab->dL_transportLayerAddress =
(S1ap_TransportLayerAddress_t *)
core_calloc(1, sizeof(S1ap_TransportLayerAddress_t));
e_rab->dL_transportLayerAddress->size = 4;
e_rab->dL_transportLayerAddress->buf = core_calloc(
e_rab->dL_transportLayerAddress->size, sizeof(c_uint8_t));
memcpy(e_rab->dL_transportLayerAddress->buf,
&bearer->sgw_dl_addr,
e_rab->dL_transportLayerAddress->size);
e_rab->dL_gTP_TEID = (S1ap_GTP_TEID_t *)
core_calloc(1, sizeof(S1ap_GTP_TEID_t));
s1ap_uint32_to_OCTET_STRING(
bearer->sgw_dl_teid, e_rab->dL_gTP_TEID);
}
if (MME_HAVE_SGW_UL_INDIRECT_TUNNEL(bearer))
{
e_rab->uL_S1ap_TransportLayerAddress =
(S1ap_TransportLayerAddress_t *)
core_calloc(1, sizeof(S1ap_TransportLayerAddress_t));
e_rab->uL_S1ap_TransportLayerAddress->size = 4;
e_rab->uL_S1ap_TransportLayerAddress->buf = core_calloc(
e_rab->uL_S1ap_TransportLayerAddress->size,
sizeof(c_uint8_t));
memcpy(e_rab->uL_S1ap_TransportLayerAddress->buf,
&bearer->sgw_ul_addr,
e_rab->uL_S1ap_TransportLayerAddress->size);
e_rab->uL_S1ap_GTP_TEID = (S1ap_GTP_TEID_t *)
core_calloc(1, sizeof(S1ap_GTP_TEID_t));
s1ap_uint32_to_OCTET_STRING(
bearer->sgw_ul_teid, e_rab->uL_S1ap_GTP_TEID);
}
if (MME_HAVE_SGW_DL_INDIRECT_TUNNEL(bearer) ||
MME_HAVE_SGW_UL_INDIRECT_TUNNEL(bearer))
{
ASN_SEQUENCE_ADD(&ies->e_RABDataForwardingList, e_rab);
}
bearer = mme_bearer_next(bearer);
}
sess = mme_sess_next(sess);
}
if (ies->e_RABDataForwardingList.s1ap_E_RABDataForwardingItem.count)
{
ies->presenceMask |=
S1AP_HANDOVERCOMMANDIES_E_RABDATAFORWARDINGLIST_PRESENT;
}
s1ap_buffer_to_OCTET_STRING(mme_ue->container.buf, mme_ue->container.size,
&ies->target_ToSource_TransparentContainer);
S1AP_CLEAR_DATA(&mme_ue->container);
message.procedureCode = S1ap_ProcedureCode_id_HandoverPreparation;
message.direction = S1AP_PDU_PR_successfulOutcome;
encoded = s1ap_encode_pdu(s1apbuf, &message);
s1ap_free_pdu(&message);
d_assert(s1apbuf && encoded >= 0,return CORE_ERROR,);
d_trace(3, "[S1AP] Handover Command : ",
"UE[mME-UE-S1AP-ID(%d)] <-- eNB[%s:%d]\n",
source_ue->mme_ue_s1ap_id,
INET_NTOP(&source_ue->enb->s1ap_sock->remote.sin_addr.s_addr, buf),
source_ue->enb->enb_id);
return CORE_OK;
}
status_t s1ap_build_handover_cancel_ack(pkbuf_t **s1apbuf, enb_ue_t *source_ue)
{
char buf[INET_ADDRSTRLEN];

View File

@ -28,12 +28,15 @@ CORE_DECLARE(status_t) s1ap_build_path_switch_ack(
CORE_DECLARE(status_t) s1ap_build_path_switch_failure(pkbuf_t **s1apbuf,
c_uint32_t enb_ue_s1ap_id, c_uint32_t mme_ue_s1ap_id, S1ap_Cause_t *cause);
CORE_DECLARE(status_t) s1ap_build_handover_command(
pkbuf_t **s1apbuf, enb_ue_t *source_ue);
CORE_DECLARE(status_t) s1ap_build_handover_preparation_failure(
pkbuf_t **s1apbuf, enb_ue_t *source_ue, S1ap_Cause_t *cause);
CORE_DECLARE(status_t) s1ap_build_handover_request(
pkbuf_t **s1apbuf, mme_ue_t *mme_ue, enb_ue_t *target_ue,
S1ap_HandoverRequiredIEs_t *required);
CORE_DECLARE(status_t) s1ap_build_handover_command(
pkbuf_t **s1apbuf, enb_ue_t *source_ue);
CORE_DECLARE(status_t) s1ap_build_handover_cancel_ack(
pkbuf_t **s1apbuf, enb_ue_t *source_ue);

View File

@ -680,7 +680,10 @@ void s1ap_handle_handover_required(mme_enb_t *enb, s1ap_message_t *message)
}
else
{
d_assert(0, return,);
rv = s1ap_send_handover_preparation_failure(source_ue, &ies->cause);
d_assert(rv == CORE_OK, return, "s1ap send error");
return;
}
source_ue->handover_type = ies->handoverType;
@ -792,7 +795,44 @@ void s1ap_handle_handover_request_ack(mme_enb_t *enb, s1ap_message_t *message)
void s1ap_handle_handover_failure(mme_enb_t *enb, s1ap_message_t *message)
{
d_error("Not implemented");
status_t rv;
char buf[INET_ADDRSTRLEN];
S1ap_HandoverFailureIEs_t *ies = NULL;
S1ap_Cause_t cause;
enb_ue_t *target_ue = NULL;
enb_ue_t *source_ue = NULL;
d_assert(enb, return,);
ies = &message->s1ap_HandoverFailureIEs;
d_assert(ies, return,);
target_ue = enb_ue_find_by_mme_ue_s1ap_id(ies->mme_ue_s1ap_id);
d_assert(target_ue, return,
"Cannot find UE for MME-UE-S1AP-ID[%d] and eNB[%s:%d]",
ies->mme_ue_s1ap_id,
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb->enb_id);
source_ue = target_ue->source_ue;
d_assert(source_ue, return,);
rv = s1ap_send_handover_preparation_failure(source_ue, &ies->cause);
d_assert(rv == CORE_OK, return, "s1ap send error");
mme_ue_deassociate_target_ue(target_ue);
cause.present = S1ap_Cause_PR_radioNetwork;
cause.choice.nas = S1ap_CauseRadioNetwork_ho_failure_in_target_EPC_eNB_or_target_system;
rv = s1ap_send_ue_context_release_commmand(target_ue, &cause);
d_assert(rv == CORE_OK, return, "s1ap send error");
d_trace(3, "[S1AP] Handover Failure : "
"UE[eNB-UE-S1AP-ID(%d)] --> eNB[%s:%d]\n",
target_ue->enb_ue_s1ap_id,
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb->enb_id);
}
void s1ap_handle_handover_cancel(mme_enb_t *enb, s1ap_message_t *message)
@ -862,6 +902,8 @@ void s1ap_handle_handover_cancel(mme_enb_t *enb, s1ap_message_t *message)
target_ue = source_ue->target_ue;
d_assert(target_ue, return,);
mme_ue_deassociate_target_ue(target_ue);
cause.present = S1ap_Cause_PR_radioNetwork;
cause.choice.nas = S1ap_CauseRadioNetwork_handover_cancelled;

View File

@ -424,6 +424,69 @@ status_t s1ap_send_path_switch_failure(mme_enb_t *enb,
return rv;
}
status_t s1ap_send_handover_command(enb_ue_t *source_ue)
{
status_t rv;
pkbuf_t *s1apbuf = NULL;
mme_enb_t *enb = NULL;
d_assert(source_ue, return CORE_ERROR,);
enb = source_ue->enb;
d_assert(enb, return CORE_ERROR,);
rv = s1ap_build_handover_command(&s1apbuf, source_ue);
d_assert(rv == CORE_OK && s1apbuf, return CORE_ERROR, "s1ap build error");
rv = s1ap_send_to_enb(enb, s1apbuf);
d_assert(rv == CORE_OK,, "s1ap send error");
return rv;
}
status_t s1ap_send_handover_preparation_failure(
enb_ue_t *source_ue, S1ap_Cause_t *cause)
{
status_t rv;
pkbuf_t *s1apbuf = NULL;
mme_enb_t *enb = NULL;
d_assert(source_ue, return CORE_ERROR,);
enb = source_ue->enb;
d_assert(enb, return CORE_ERROR,);
rv = s1ap_build_handover_preparation_failure(&s1apbuf, source_ue, cause);
d_assert(rv == CORE_OK && s1apbuf, return CORE_ERROR, "s1ap build error");
rv = s1ap_send_to_enb(enb, s1apbuf);
d_assert(rv == CORE_OK,, "s1ap send error");
return rv;
}
status_t s1ap_send_handover_cancel_ack(enb_ue_t *source_ue)
{
status_t rv;
pkbuf_t *s1apbuf = NULL;
mme_enb_t *enb = NULL;
d_assert(source_ue, return CORE_ERROR,);
enb = source_ue->enb;
d_assert(enb, return CORE_ERROR,);
rv = s1ap_build_handover_cancel_ack(&s1apbuf, source_ue);
d_assert(rv == CORE_OK && s1apbuf, return CORE_ERROR, "s1ap build error");
rv = s1ap_send_to_enb(enb, s1apbuf);
d_assert(rv == CORE_OK,, "s1ap send error");
return rv;
}
status_t s1ap_send_handover_request(
mme_ue_t *mme_ue, S1ap_HandoverRequiredIEs_t *ies)
{
@ -481,46 +544,6 @@ status_t s1ap_send_handover_request(
return rv;
}
status_t s1ap_send_handover_command(enb_ue_t *source_ue)
{
status_t rv;
pkbuf_t *s1apbuf = NULL;
mme_enb_t *enb = NULL;
d_assert(source_ue, return CORE_ERROR,);
enb = source_ue->enb;
d_assert(enb, return CORE_ERROR,);
rv = s1ap_build_handover_command(&s1apbuf, source_ue);
d_assert(rv == CORE_OK && s1apbuf, return CORE_ERROR, "s1ap build error");
rv = s1ap_send_to_enb(enb, s1apbuf);
d_assert(rv == CORE_OK,, "s1ap send error");
return rv;
}
status_t s1ap_send_handover_cancel_ack(enb_ue_t *source_ue)
{
status_t rv;
pkbuf_t *s1apbuf = NULL;
mme_enb_t *enb = NULL;
d_assert(source_ue, return CORE_ERROR,);
enb = source_ue->enb;
d_assert(enb, return CORE_ERROR,);
rv = s1ap_build_handover_cancel_ack(&s1apbuf, source_ue);
d_assert(rv == CORE_OK && s1apbuf, return CORE_ERROR, "s1ap build error");
rv = s1ap_send_to_enb(enb, s1apbuf);
d_assert(rv == CORE_OK,, "s1ap send error");
return rv;
}
status_t s1ap_send_mme_status_transfer(
enb_ue_t *target_ue, S1ap_ENBStatusTransferIEs_t *ies)
{

View File

@ -29,9 +29,13 @@ CORE_DECLARE(status_t) s1ap_send_path_switch_ack(mme_ue_t *mme_ue);
CORE_DECLARE(status_t) s1ap_send_path_switch_failure(mme_enb_t *enb,
c_uint32_t enb_ue_s1ap_id, c_uint32_t mme_ue_s1ap_id, S1ap_Cause_t *cause);
CORE_DECLARE(status_t) s1ap_send_handover_command(enb_ue_t *source_ue);
CORE_DECLARE(status_t) s1ap_send_handover_preparation_failure(
enb_ue_t *source_ue, S1ap_Cause_t *cause);
CORE_DECLARE(status_t) s1ap_send_handover_request(
mme_ue_t *mme_ue, S1ap_HandoverRequiredIEs_t *required);
CORE_DECLARE(status_t) s1ap_send_handover_command(enb_ue_t *source_ue);
CORE_DECLARE(status_t) s1ap_send_handover_cancel_ack(enb_ue_t *source_ue);
CORE_DECLARE(status_t) s1ap_send_mme_status_transfer(