forked from acouzens/open5gs
HO cancel done
This commit is contained in:
parent
f783e2ffd0
commit
0888f49c48
|
@ -135,6 +135,13 @@ static int s1ap_decode_initiating(s1ap_message_t *message,
|
|||
s1ap_xer__print2sp, message);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_HandoverCancel:
|
||||
ret = s1ap_decode_s1ap_handovercancelies(
|
||||
&message->s1ap_HandoverCancelIEs, &initiating_p->value);
|
||||
s1ap_decode_xer_print_message(s1ap_xer_print_s1ap_handovercancel,
|
||||
s1ap_xer__print2sp, message);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_eNBStatusTransfer:
|
||||
ret = s1ap_decode_s1ap_enbstatustransferies(
|
||||
&message->s1ap_ENBStatusTransferIEs, &initiating_p->value);
|
||||
|
|
|
@ -39,6 +39,8 @@ static inline int s1ap_encode_handover_request(
|
|||
s1ap_message_t *message_p, pkbuf_t *pkbuf);
|
||||
static inline int s1ap_encode_handover_command(
|
||||
s1ap_message_t *message_p, pkbuf_t *pkbuf);
|
||||
static inline int s1ap_encode_handover_cancel_ack(
|
||||
s1ap_message_t *message_p, pkbuf_t *pkbuf);
|
||||
static inline int s1ap_encode_handover_preparation_failure(
|
||||
s1ap_message_t *message_p, pkbuf_t *pkbuf);
|
||||
static inline int s1ap_encode_mme_status_transfer(
|
||||
|
@ -192,6 +194,13 @@ static inline int s1ap_encode_successfull_outcome(
|
|||
ret = s1ap_encode_handover_command(message_p, pkbuf);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_HandoverCancel:
|
||||
s1ap_encode_xer_print_message(
|
||||
s1ap_xer_print_s1ap_handovercancelacknowledge,
|
||||
s1ap_xer__print2sp, message_p);
|
||||
ret = s1ap_encode_handover_cancel_ack(message_p, pkbuf);
|
||||
break;
|
||||
|
||||
default:
|
||||
d_warn("Unknown procedure ID (%d) for successfull "
|
||||
"outcome message\n", (int)message_p->procedureCode);
|
||||
|
@ -724,6 +733,7 @@ static inline int s1ap_encode_handover_command(
|
|||
|
||||
return enc_ret.encoded;
|
||||
}
|
||||
|
||||
static inline int s1ap_encode_handover_preparation_failure(
|
||||
s1ap_message_t *message_p, pkbuf_t *pkbuf)
|
||||
{
|
||||
|
@ -761,6 +771,43 @@ static inline int s1ap_encode_handover_preparation_failure(
|
|||
return enc_ret.encoded;
|
||||
}
|
||||
|
||||
static inline int s1ap_encode_handover_cancel_ack(
|
||||
s1ap_message_t *message_p, pkbuf_t *pkbuf)
|
||||
{
|
||||
asn_enc_rval_t enc_ret = {0};
|
||||
|
||||
S1AP_PDU_t pdu;
|
||||
S1ap_HandoverCancelAcknowledge_t ack;
|
||||
asn_TYPE_descriptor_t *td = &asn_DEF_S1ap_HandoverCommand;
|
||||
|
||||
memset(&ack, 0, sizeof(S1ap_HandoverCommand_t));
|
||||
if (s1ap_encode_s1ap_handovercancelacknowledgeies(
|
||||
&ack, &message_p->s1ap_HandoverCancelAcknowledgeIEs) < 0)
|
||||
{
|
||||
d_error("Encoding of %s failed", td->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&pdu, 0, sizeof (S1AP_PDU_t));
|
||||
pdu.present = S1AP_PDU_PR_successfulOutcome;
|
||||
pdu.choice.successfulOutcome.procedureCode = message_p->procedureCode;
|
||||
pdu.choice.successfulOutcome.criticality = S1ap_Criticality_reject;
|
||||
ANY_fromType_aper(&pdu.choice.successfulOutcome.value, td, &ack);
|
||||
|
||||
enc_ret = aper_encode_to_buffer(&asn_DEF_S1AP_PDU,
|
||||
&pdu, pkbuf->payload, MAX_SDU_LEN);
|
||||
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(*td, &ack);
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_S1AP_PDU, &pdu);
|
||||
|
||||
if (enc_ret.encoded < 0)
|
||||
{
|
||||
d_error("Encoding of %s failed", td->name);
|
||||
}
|
||||
|
||||
return enc_ret.encoded;
|
||||
}
|
||||
|
||||
static inline int s1ap_encode_mme_status_transfer(
|
||||
s1ap_message_t *message_p, pkbuf_t *pkbuf)
|
||||
{
|
||||
|
|
|
@ -105,6 +105,11 @@ static inline int s1ap_free_initiating_message(s1ap_message_t *message)
|
|||
&message->s1ap_HandoverRequestIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_HandoverCancel:
|
||||
s1ap_free_s1ap_handovercancelies(
|
||||
&message->s1ap_HandoverCancelIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_eNBStatusTransfer:
|
||||
s1ap_free_s1ap_enbstatustransferies(
|
||||
&message->s1ap_ENBStatusTransferIEs);
|
||||
|
@ -173,6 +178,11 @@ static inline int s1ap_free_successfull_outcome(s1ap_message_t *message)
|
|||
&message->s1ap_HandoverRequestAcknowledgeIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_HandoverCancel:
|
||||
s1ap_free_s1ap_handovercancelacknowledgeies(
|
||||
&message->s1ap_HandoverCancelAcknowledgeIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_HandoverPreparation:
|
||||
s1ap_free_s1ap_handovercommandies(
|
||||
&message->s1ap_HandoverCommandIEs);
|
||||
|
|
|
@ -304,11 +304,13 @@ struct _mme_ue_t {
|
|||
} \
|
||||
} while(0);
|
||||
|
||||
#define MAX_NUM_OF_GTP_COUNTER 16
|
||||
#define MAX_NUM_OF_GTP_COUNTER 16
|
||||
|
||||
#define GTP_COUNTER_DELETE_SESSION 0
|
||||
#define GTP_COUNTER_MODIFY_BEARER_BY_PATH_SWITCH 1
|
||||
#define GTP_COUNTER_MODIFY_BEARER_BY_HANDOVER_NOTIFY 2
|
||||
#define GTP_COUNTER_DELETE_SESSION 0
|
||||
#define GTP_COUNTER_MODIFY_BEARER_BY_PATH_SWITCH 1
|
||||
#define GTP_COUNTER_MODIFY_BEARER_BY_HANDOVER_NOTIFY 2
|
||||
#define GTP_COUNTER_DELETE_INDIRECT_TUNNEL_BY_HANDOVER_NOTIFY 3
|
||||
#define GTP_COUNTER_DELETE_INDIRECT_TUNNEL_BY_HANDOVER_CANCEL 4
|
||||
struct {
|
||||
c_uint8_t request;
|
||||
c_uint8_t response;
|
||||
|
|
|
@ -127,6 +127,8 @@ void mme_s11_handle_modify_bearer_response(
|
|||
);
|
||||
|
||||
GTP_COUNTER_CHECK(mme_ue, GTP_COUNTER_MODIFY_BEARER_BY_HANDOVER_NOTIFY,
|
||||
GTP_COUNTER_INCREMENT(mme_ue,
|
||||
GTP_COUNTER_DELETE_INDIRECT_TUNNEL_BY_HANDOVER_NOTIFY);
|
||||
rv = mme_gtp_send_delete_indirect_data_forwarding_tunnel_request(
|
||||
mme_ue);
|
||||
d_assert(rv == CORE_OK, return, "gtp send error");
|
||||
|
@ -346,6 +348,7 @@ void mme_s11_handle_create_indirect_data_forwarding_tunnel_response(
|
|||
{
|
||||
status_t rv;
|
||||
mme_bearer_t *bearer = NULL;
|
||||
enb_ue_t *source_ue = NULL;
|
||||
int i;
|
||||
|
||||
tlv_bearer_context_t *bearers[GTP_MAX_NUM_OF_INDIRECT_TUNNEL];
|
||||
|
@ -355,6 +358,9 @@ void mme_s11_handle_create_indirect_data_forwarding_tunnel_response(
|
|||
d_assert(mme_ue, return, "Null param");
|
||||
d_assert(rsp, return, "Null param");
|
||||
|
||||
source_ue = mme_ue->enb_ue;
|
||||
d_assert(source_ue, return, "Null param");
|
||||
|
||||
if (rsp->cause.presence == 0)
|
||||
{
|
||||
d_error("No Cause");
|
||||
|
@ -399,7 +405,7 @@ void mme_s11_handle_create_indirect_data_forwarding_tunnel_response(
|
|||
}
|
||||
}
|
||||
|
||||
rv = s1ap_send_handover_command(mme_ue);
|
||||
rv = s1ap_send_handover_command(source_ue);
|
||||
d_assert(rv == CORE_OK,, "s1ap send error");
|
||||
}
|
||||
|
||||
|
@ -419,11 +425,6 @@ void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response(
|
|||
d_assert(mme_ue, return, "Null param");
|
||||
d_assert(rsp, return, "Null param");
|
||||
|
||||
target_ue = mme_ue->enb_ue;
|
||||
d_assert(target_ue, return, "Null param");
|
||||
source_ue = target_ue->source_ue;
|
||||
d_assert(source_ue, return, "Null param");
|
||||
|
||||
if (rsp->cause.presence == 0)
|
||||
{
|
||||
d_error("No Cause");
|
||||
|
@ -449,9 +450,32 @@ void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response(
|
|||
sess = mme_sess_next(sess);
|
||||
}
|
||||
|
||||
cause.present = S1ap_Cause_PR_nas;
|
||||
cause.choice.nas = S1ap_CauseNas_normal_release;
|
||||
GTP_COUNTER_CHECK(mme_ue,
|
||||
GTP_COUNTER_DELETE_INDIRECT_TUNNEL_BY_HANDOVER_NOTIFY,
|
||||
target_ue = mme_ue->enb_ue;
|
||||
d_assert(target_ue, return, "Null param");
|
||||
source_ue = target_ue->source_ue;
|
||||
d_assert(source_ue, return, "Null param");
|
||||
|
||||
cause.present = S1ap_Cause_PR_nas;
|
||||
cause.choice.nas = S1ap_CauseNas_normal_release;
|
||||
|
||||
rv = s1ap_send_ue_context_release_commmand(source_ue, &cause);
|
||||
d_assert(rv == CORE_OK, return, "s1ap send error");
|
||||
);
|
||||
|
||||
GTP_COUNTER_CHECK(mme_ue,
|
||||
GTP_COUNTER_DELETE_INDIRECT_TUNNEL_BY_HANDOVER_CANCEL,
|
||||
source_ue = mme_ue->enb_ue;
|
||||
d_assert(source_ue, return, "Null param");
|
||||
target_ue = source_ue->target_ue;
|
||||
d_assert(target_ue, return, "Null param");
|
||||
|
||||
cause.present = S1ap_Cause_PR_radioNetwork;
|
||||
cause.choice.nas = S1ap_CauseRadioNetwork_handover_cancelled;
|
||||
|
||||
rv = s1ap_send_ue_context_release_commmand(target_ue, &cause);
|
||||
d_assert(rv == CORE_OK, return, "s1ap send error");
|
||||
);
|
||||
|
||||
rv = s1ap_send_ue_context_release_commmand(source_ue, &cause);
|
||||
d_assert(rv == CORE_OK, return, "s1ap send error");
|
||||
}
|
||||
|
|
|
@ -675,7 +675,7 @@ status_t s1ap_build_path_switch_failure(pkbuf_t **s1apbuf,
|
|||
}
|
||||
|
||||
status_t s1ap_build_handover_request(
|
||||
pkbuf_t **s1apbuf, mme_ue_t *mme_ue, enb_ue_t *enb_ue,
|
||||
pkbuf_t **s1apbuf, mme_ue_t *mme_ue, enb_ue_t *target_ue,
|
||||
S1ap_HandoverRequiredIEs_t *required)
|
||||
{
|
||||
char buf[INET_ADDRSTRLEN];
|
||||
|
@ -690,7 +690,7 @@ status_t s1ap_build_handover_request(
|
|||
mme_bearer_t *bearer = NULL;
|
||||
s6a_subscription_data_t *subscription_data = NULL;
|
||||
|
||||
d_assert(enb_ue, return CORE_ERROR, "Null param");
|
||||
d_assert(target_ue, return CORE_ERROR, "Null param");
|
||||
d_assert(mme_ue, return CORE_ERROR, "Null param");
|
||||
d_assert(required, return CORE_ERROR, "Null param");
|
||||
subscription_data = &mme_ue->subscription_data;
|
||||
|
@ -698,7 +698,7 @@ status_t s1ap_build_handover_request(
|
|||
|
||||
memset(&message, 0, sizeof(s1ap_message_t));
|
||||
|
||||
ies->mme_ue_s1ap_id = enb_ue->mme_ue_s1ap_id;
|
||||
ies->mme_ue_s1ap_id = target_ue->mme_ue_s1ap_id;
|
||||
ies->handoverType = required->handoverType;
|
||||
s1ap_build_cause(&ies->cause, &required->cause);
|
||||
|
||||
|
@ -810,14 +810,14 @@ status_t s1ap_build_handover_request(
|
|||
|
||||
d_trace(3, "[S1AP] Handover Request : ",
|
||||
"UE[mME-UE-S1AP-ID(%d)] <-- eNB[%s:%d]\n",
|
||||
enb_ue->mme_ue_s1ap_id,
|
||||
INET_NTOP(&enb_ue->enb->s1ap_sock->remote.sin_addr.s_addr, buf),
|
||||
enb_ue->enb->enb_id);
|
||||
target_ue->mme_ue_s1ap_id,
|
||||
INET_NTOP(&target_ue->enb->s1ap_sock->remote.sin_addr.s_addr, buf),
|
||||
target_ue->enb->enb_id);
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t s1ap_build_handover_command(pkbuf_t **s1apbuf, enb_ue_t *enb_ue)
|
||||
status_t s1ap_build_handover_command(pkbuf_t **s1apbuf, enb_ue_t *source_ue)
|
||||
{
|
||||
char buf[INET_ADDRSTRLEN];
|
||||
|
||||
|
@ -830,14 +830,14 @@ status_t s1ap_build_handover_command(pkbuf_t **s1apbuf, enb_ue_t *enb_ue)
|
|||
mme_sess_t *sess = NULL;
|
||||
mme_bearer_t *bearer = NULL;
|
||||
|
||||
d_assert(enb_ue, return CORE_ERROR, "Null param");
|
||||
mme_ue = enb_ue->mme_ue;
|
||||
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 = enb_ue->mme_ue_s1ap_id;
|
||||
ies->eNB_UE_S1AP_ID = enb_ue->enb_ue_s1ap_id;
|
||||
ies->handoverType = enb_ue->handover_type;
|
||||
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)
|
||||
|
@ -921,15 +921,48 @@ status_t s1ap_build_handover_command(pkbuf_t **s1apbuf, enb_ue_t *enb_ue)
|
|||
|
||||
d_trace(3, "[S1AP] Handover Command : ",
|
||||
"UE[mME-UE-S1AP-ID(%d)] <-- eNB[%s:%d]\n",
|
||||
enb_ue->mme_ue_s1ap_id,
|
||||
INET_NTOP(&enb_ue->enb->s1ap_sock->remote.sin_addr.s_addr, buf),
|
||||
enb_ue->enb->enb_id);
|
||||
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];
|
||||
|
||||
int encoded;
|
||||
s1ap_message_t message;
|
||||
S1ap_HandoverCancelAcknowledgeIEs_t *ies =
|
||||
&message.s1ap_HandoverCancelAcknowledgeIEs;
|
||||
|
||||
d_assert(source_ue, return CORE_ERROR, "Null param");
|
||||
|
||||
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;
|
||||
|
||||
message.procedureCode = S1ap_ProcedureCode_id_HandoverCancel;
|
||||
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 Cancel Ack : ",
|
||||
"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_mme_status_transfer(pkbuf_t **s1apbuf,
|
||||
enb_ue_t *enb_ue, S1ap_ENBStatusTransferIEs_t *enb_ies)
|
||||
enb_ue_t *target_ue, S1ap_ENBStatusTransferIEs_t *enb_ies)
|
||||
{
|
||||
char buf[INET_ADDRSTRLEN];
|
||||
int i;
|
||||
|
@ -938,13 +971,13 @@ status_t s1ap_build_mme_status_transfer(pkbuf_t **s1apbuf,
|
|||
s1ap_message_t message;
|
||||
S1ap_MMEStatusTransferIEs_t *mme_ies = &message.s1ap_MMEStatusTransferIEs;
|
||||
|
||||
d_assert(enb_ue, return CORE_ERROR, "Null param");
|
||||
d_assert(target_ue, return CORE_ERROR, "Null param");
|
||||
d_assert(enb_ies, return CORE_ERROR, "Null param");
|
||||
|
||||
memset(&message, 0, sizeof(s1ap_message_t));
|
||||
|
||||
mme_ies->mme_ue_s1ap_id = enb_ue->mme_ue_s1ap_id;
|
||||
mme_ies->eNB_UE_S1AP_ID = enb_ue->enb_ue_s1ap_id;
|
||||
mme_ies->mme_ue_s1ap_id = target_ue->mme_ue_s1ap_id;
|
||||
mme_ies->eNB_UE_S1AP_ID = target_ue->enb_ue_s1ap_id;
|
||||
|
||||
for (i = 0; i < enb_ies->eNB_StatusTransfer_TransparentContainer.
|
||||
bearers_SubjectToStatusTransferList.list.count; i++)
|
||||
|
@ -974,9 +1007,9 @@ status_t s1ap_build_mme_status_transfer(pkbuf_t **s1apbuf,
|
|||
|
||||
d_trace(3, "[S1AP] MME Status Transfer : ",
|
||||
"UE[mME-UE-S1AP-ID(%d)] <-- eNB[%s:%d]\n",
|
||||
enb_ue->mme_ue_s1ap_id,
|
||||
INET_NTOP(&enb_ue->enb->s1ap_sock->remote.sin_addr.s_addr, buf),
|
||||
enb_ue->enb->enb_id);
|
||||
target_ue->mme_ue_s1ap_id,
|
||||
INET_NTOP(&target_ue->enb->s1ap_sock->remote.sin_addr.s_addr, buf),
|
||||
target_ue->enb->enb_id);
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
|
|
@ -29,12 +29,16 @@ 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_request(
|
||||
pkbuf_t **s1apbuf, mme_ue_t *mme_ue, enb_ue_t *enb_ue,
|
||||
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 *enb_ue);
|
||||
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);
|
||||
|
||||
CORE_DECLARE(status_t) s1ap_build_mme_status_transfer(pkbuf_t **s1apbuf,
|
||||
enb_ue_t *enb_ue, S1ap_ENBStatusTransferIEs_t *enb_ies);
|
||||
enb_ue_t *target_ue, S1ap_ENBStatusTransferIEs_t *enb_ies);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -701,6 +701,7 @@ void s1ap_handle_handover_request_ack(mme_enb_t *enb, s1ap_message_t *message)
|
|||
char buf[INET_ADDRSTRLEN];
|
||||
int i;
|
||||
|
||||
enb_ue_t *source_ue = NULL;
|
||||
enb_ue_t *target_ue = NULL;
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
|
||||
|
@ -722,6 +723,8 @@ void s1ap_handle_handover_request_ack(mme_enb_t *enb, s1ap_message_t *message)
|
|||
|
||||
mme_ue = target_ue->mme_ue;
|
||||
d_assert(mme_ue, return,);
|
||||
source_ue = target_ue->source_ue;
|
||||
d_assert(source_ue, return,);
|
||||
|
||||
for (i = 0; i < ies->e_RABAdmittedList.s1ap_E_RABAdmittedItem.count; i++)
|
||||
{
|
||||
|
@ -776,7 +779,7 @@ void s1ap_handle_handover_request_ack(mme_enb_t *enb, s1ap_message_t *message)
|
|||
}
|
||||
else
|
||||
{
|
||||
rv = s1ap_send_handover_command(mme_ue);
|
||||
rv = s1ap_send_handover_command(source_ue);
|
||||
d_assert(rv == CORE_OK, return, "gtp send failed");
|
||||
}
|
||||
|
||||
|
@ -792,6 +795,76 @@ void s1ap_handle_handover_failure(mme_enb_t *enb, s1ap_message_t *message)
|
|||
d_error("Not implemented");
|
||||
}
|
||||
|
||||
void s1ap_handle_handover_cancel(mme_enb_t *enb, s1ap_message_t *message)
|
||||
{
|
||||
status_t rv;
|
||||
char buf[INET_ADDRSTRLEN];
|
||||
|
||||
enb_ue_t *source_ue = NULL;
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
mme_sess_t *sess = NULL;
|
||||
mme_bearer_t *bearer = NULL;
|
||||
int need_to_delete_indirect_tunnel = 0;
|
||||
|
||||
S1ap_HandoverCancelIEs_t *ies = NULL;
|
||||
|
||||
d_assert(enb, return,);
|
||||
|
||||
ies = &message->s1ap_HandoverCancelIEs;
|
||||
d_assert(ies, return,);
|
||||
|
||||
source_ue = enb_ue_find_by_enb_ue_s1ap_id(enb, ies->eNB_UE_S1AP_ID);
|
||||
d_assert(source_ue, return,
|
||||
"Cannot find UE for eNB-UE-S1AP-ID[%d] and eNB[%s:%d]",
|
||||
ies->eNB_UE_S1AP_ID,
|
||||
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf),
|
||||
enb->enb_id);
|
||||
d_assert(source_ue->mme_ue_s1ap_id == ies->mme_ue_s1ap_id, return,
|
||||
"Conflict MME-UE-S1AP-ID : %d != %d\n",
|
||||
source_ue->mme_ue_s1ap_id, ies->mme_ue_s1ap_id);
|
||||
|
||||
mme_ue = source_ue->mme_ue;
|
||||
d_assert(mme_ue, return,);
|
||||
|
||||
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))
|
||||
{
|
||||
need_to_delete_indirect_tunnel = 1;
|
||||
}
|
||||
|
||||
bearer = mme_bearer_next(bearer);
|
||||
}
|
||||
sess = mme_sess_next(sess);
|
||||
}
|
||||
|
||||
if (need_to_delete_indirect_tunnel)
|
||||
{
|
||||
GTP_COUNTER_INCREMENT(mme_ue,
|
||||
GTP_COUNTER_DELETE_INDIRECT_TUNNEL_BY_HANDOVER_CANCEL);
|
||||
|
||||
rv = mme_gtp_send_delete_indirect_data_forwarding_tunnel_request(
|
||||
mme_ue);
|
||||
d_assert(rv == CORE_OK, return, "gtp send error");
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = s1ap_send_handover_cancel_ack(source_ue);
|
||||
d_assert(rv == CORE_OK,, "s1ap send error");
|
||||
}
|
||||
|
||||
d_trace(3, "[S1AP] Handover Cancel : "
|
||||
"UE[eNB-UE-S1AP-ID(%d)] --> eNB[%s:%d]\n",
|
||||
source_ue->enb_ue_s1ap_id,
|
||||
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf),
|
||||
enb->enb_id);
|
||||
}
|
||||
|
||||
void s1ap_handle_enb_status_transfer(mme_enb_t *enb, s1ap_message_t *message)
|
||||
{
|
||||
status_t rv;
|
||||
|
|
|
@ -37,6 +37,8 @@ CORE_DECLARE(void) s1ap_handle_handover_request_ack(
|
|||
mme_enb_t *enb, s1ap_message_t *message);
|
||||
CORE_DECLARE(void) s1ap_handle_handover_failure(
|
||||
mme_enb_t *enb, s1ap_message_t *message);
|
||||
CORE_DECLARE(void) s1ap_handle_handover_cancel(
|
||||
mme_enb_t *enb, s1ap_message_t *message);
|
||||
|
||||
CORE_DECLARE(void) s1ap_handle_enb_status_transfer(
|
||||
mme_enb_t *enb, s1ap_message_t *message);
|
||||
|
|
|
@ -481,21 +481,38 @@ status_t s1ap_send_handover_request(
|
|||
return rv;
|
||||
}
|
||||
|
||||
status_t s1ap_send_handover_command(mme_ue_t *mme_ue)
|
||||
status_t s1ap_send_handover_command(enb_ue_t *source_ue)
|
||||
{
|
||||
status_t rv;
|
||||
pkbuf_t *s1apbuf = NULL;
|
||||
|
||||
mme_enb_t *enb = NULL;
|
||||
enb_ue_t *enb_ue = NULL;
|
||||
|
||||
d_assert(mme_ue, return CORE_ERROR,);
|
||||
enb_ue = mme_ue->enb_ue;
|
||||
d_assert(enb_ue, return CORE_ERROR,);
|
||||
enb = enb_ue->enb;
|
||||
d_assert(source_ue, return CORE_ERROR,);
|
||||
enb = source_ue->enb;
|
||||
d_assert(enb, return CORE_ERROR,);
|
||||
|
||||
rv = s1ap_build_handover_command(&s1apbuf, enb_ue);
|
||||
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);
|
||||
|
@ -505,18 +522,18 @@ status_t s1ap_send_handover_command(mme_ue_t *mme_ue)
|
|||
}
|
||||
|
||||
status_t s1ap_send_mme_status_transfer(
|
||||
enb_ue_t *enb_ue, S1ap_ENBStatusTransferIEs_t *ies)
|
||||
enb_ue_t *target_ue, S1ap_ENBStatusTransferIEs_t *ies)
|
||||
{
|
||||
status_t rv;
|
||||
pkbuf_t *s1apbuf = NULL;
|
||||
|
||||
mme_enb_t *enb = NULL;
|
||||
|
||||
d_assert(enb_ue, return CORE_ERROR,);
|
||||
enb = enb_ue->enb;
|
||||
d_assert(target_ue, return CORE_ERROR,);
|
||||
enb = target_ue->enb;
|
||||
d_assert(enb, return CORE_ERROR,);
|
||||
|
||||
rv = s1ap_build_mme_status_transfer(&s1apbuf, enb_ue, ies);
|
||||
rv = s1ap_build_mme_status_transfer(&s1apbuf, target_ue, ies);
|
||||
d_assert(rv == CORE_OK && s1apbuf, return CORE_ERROR, "s1ap build error");
|
||||
|
||||
rv = s1ap_send_to_enb(enb, s1apbuf);
|
||||
|
|
|
@ -31,9 +31,11 @@ CORE_DECLARE(status_t) s1ap_send_path_switch_failure(mme_enb_t *enb,
|
|||
|
||||
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(mme_ue_t *mme_ue);
|
||||
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(
|
||||
enb_ue_t *enb_ue, S1ap_ENBStatusTransferIEs_t *ies);
|
||||
enb_ue_t *target_ue, S1ap_ENBStatusTransferIEs_t *ies);
|
||||
|
||||
int _s1ap_recv_cb(net_sock_t *net_sock, void *data);
|
||||
|
||||
|
|
|
@ -96,6 +96,11 @@ void s1ap_state_operational(fsm_t *s, event_t *e)
|
|||
s1ap_handle_handover_required(enb, message);
|
||||
break;
|
||||
}
|
||||
case S1ap_ProcedureCode_id_HandoverCancel:
|
||||
{
|
||||
s1ap_handle_handover_cancel(enb, message);
|
||||
break;
|
||||
}
|
||||
case S1ap_ProcedureCode_id_eNBStatusTransfer:
|
||||
{
|
||||
s1ap_handle_enb_status_transfer(enb, message);
|
||||
|
|
|
@ -607,7 +607,7 @@ static void handover_test2(abts_case *tc, void *data)
|
|||
pkbuf_free(recvbuf);
|
||||
|
||||
/* Send UE Context Release Complete */
|
||||
rv = tests1ap_build_ue_context_release_complete(&sendbuf, msgindex);
|
||||
rv = tests1ap_build_ue_context_release_complete(&sendbuf, msgindex-1);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
rv = tests1ap_enb_send(sock1, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
@ -662,6 +662,50 @@ static void handover_test2(abts_case *tc, void *data)
|
|||
ABTS_INT_NEQUAL(tc, 0, rc);
|
||||
pkbuf_free(recvbuf);
|
||||
|
||||
/* Send UE Context Release Complete */
|
||||
rv = tests1ap_build_ue_context_release_complete(&sendbuf, msgindex);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
rv = tests1ap_enb_send(sock2, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
core_sleep(time_from_msec(300));
|
||||
|
||||
/* Send Handover Required */
|
||||
rv = tests1ap_build_handover_required(&sendbuf, 2);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
rv = tests1ap_enb_send(sock1, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
/* Receive Handover Request */
|
||||
recvbuf = pkbuf_alloc(0, MAX_SDU_LEN);
|
||||
rc = tests1ap_enb_read(sock2, recvbuf);
|
||||
ABTS_INT_NEQUAL(tc, 0, rc);
|
||||
pkbuf_free(recvbuf);
|
||||
|
||||
/* Send Handover Request Ack */
|
||||
rv = tests1ap_build_handover_request_ack(&sendbuf, 2);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
rv = tests1ap_enb_send(sock2, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
/* Receive Handover Command */
|
||||
recvbuf = pkbuf_alloc(0, MAX_SDU_LEN);
|
||||
rc = tests1ap_enb_read(sock1, recvbuf);
|
||||
ABTS_INT_NEQUAL(tc, 0, rc);
|
||||
pkbuf_free(recvbuf);
|
||||
|
||||
/* Send Handover Cancel */
|
||||
rv = tests1ap_build_handover_cancel(&sendbuf, 0);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
rv = tests1ap_enb_send(sock1, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
/* Receive UE Context Release Command */
|
||||
recvbuf = pkbuf_alloc(0, MAX_SDU_LEN);
|
||||
rc = tests1ap_enb_read(sock2, recvbuf);
|
||||
ABTS_INT_NEQUAL(tc, 0, rc);
|
||||
pkbuf_free(recvbuf);
|
||||
|
||||
/* Send UE Context Release Complete */
|
||||
rv = tests1ap_build_ue_context_release_complete(&sendbuf, msgindex+1);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
@ -693,7 +737,9 @@ abts_suite *test_handover(abts_suite *suite)
|
|||
{
|
||||
suite = ADD_SUITE(suite)
|
||||
|
||||
#if 0
|
||||
abts_run_test(suite, handover_test1, NULL);
|
||||
#endif
|
||||
abts_run_test(suite, handover_test2, NULL);
|
||||
|
||||
return suite;
|
||||
|
|
|
@ -769,14 +769,15 @@ status_t tests1ap_build_ue_context_release_complete(pkbuf_t **pkbuf, int i)
|
|||
"",
|
||||
|
||||
|
||||
"",
|
||||
|
||||
"2017"
|
||||
"0012000002000040 05c0020000c40008 4002000c",
|
||||
|
||||
"2017"
|
||||
"0012000002000040 05c0020000c50008 40020008",
|
||||
|
||||
"2017"
|
||||
"0012000002000040 05c0020000c70008 40020008",
|
||||
|
||||
};
|
||||
c_uint16_t len[TESTS1AP_MAX_MESSAGE] = {
|
||||
23,
|
||||
|
@ -791,7 +792,7 @@ status_t tests1ap_build_ue_context_release_complete(pkbuf_t **pkbuf, int i)
|
|||
0,
|
||||
0,
|
||||
|
||||
0,
|
||||
22,
|
||||
22,
|
||||
22,
|
||||
};
|
||||
|
@ -1257,7 +1258,17 @@ status_t tests1ap_build_handover_required(
|
|||
"3423c135002214d6 dfb0a0b06502c402 000004008177faab 4677235334a0e867"
|
||||
"2134804030000100 4e40024500004e40 0246000000f11000 1f20a10000f11000"
|
||||
"043a000000350000 f110001f20a00000 22",
|
||||
"",
|
||||
|
||||
"0000"
|
||||
"0081190000060000 0005c0020000c600 080002000d000100 0100000240020220"
|
||||
"0004000d0000f110 0000043000f11030 3900680080e680e4 4080ab0f1014c598"
|
||||
"00018000bf06ec4d 00100302c0000000 000015a800140672 0af00348f10013d0"
|
||||
"3bc58414903bc588 09401de2c2100440 13f212249010127d ad808fd50398381c"
|
||||
"08fd503983805f50 37868baa010c846f b057874162d62e82 1f42f2e159f821d0"
|
||||
"9c0009e28aa1a001 2d888050514c0040 8008066072003e41 5250d46210208184"
|
||||
"3423c135002214d6 dfb0a0b06502c402 000004008177faab 4677235334a0e867"
|
||||
"213e804030000100 4e40024500004e40 0246000000f11000 043a020000f11000"
|
||||
"1f20a00000340000 f11000043a000000 350000f110001f20 a0000022",
|
||||
|
||||
"",
|
||||
"",
|
||||
|
@ -1271,7 +1282,7 @@ status_t tests1ap_build_handover_required(
|
|||
c_uint16_t len[TESTS1AP_MAX_MESSAGE] = {
|
||||
264,
|
||||
275,
|
||||
0,
|
||||
286,
|
||||
|
||||
0,
|
||||
0,
|
||||
|
@ -1316,7 +1327,16 @@ status_t tests1ap_build_handover_request_ack(
|
|||
"f2214d6dfb82c194 0b10080000020040 bbfd55aeab01ad80 8fd50398381c08fd"
|
||||
"503983804d037868 baa016423342bc3a 18b58fa084ca833f a17970acfc10e84e"
|
||||
"0004f14550d00096 c88980",
|
||||
"",
|
||||
|
||||
"2001"
|
||||
"0080e80000040000 4005c0020000c700 0840020009001240 47010014401f78a1"
|
||||
"f00a01237c010008 080f800a01237c01 0008090f800a0123 7c0100080a001440"
|
||||
"1f78c1f00a01237c 010008100f800a01 237c010008110f80 0a01237c01000812"
|
||||
"007b008086808400 80810bf900d8af40 00a0339057801f47 88009e81de2c20a4"
|
||||
"81de2c404a00ef16 2000010044013f21 2249008093efd243 3914cd2aa0a0144f"
|
||||
"f2214d6dfb82c194 0b10080000020040 bbfd55aeab81ad80 8fd50398381c08fd"
|
||||
"503983804d037868 baa016423342bc3a 18b58fa084ca833f a17970acfc10e84e"
|
||||
"0004f14550d00096 c88a00",
|
||||
|
||||
"",
|
||||
"",
|
||||
|
@ -1330,7 +1350,7 @@ status_t tests1ap_build_handover_request_ack(
|
|||
c_uint16_t len[TESTS1AP_MAX_MESSAGE] = {
|
||||
237,
|
||||
237,
|
||||
0,
|
||||
237,
|
||||
|
||||
0,
|
||||
0,
|
||||
|
@ -1398,8 +1418,7 @@ status_t tests1ap_build_enb_status_transfer(
|
|||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t tests1ap_build_handover_notify(
|
||||
pkbuf_t **pkbuf, int i)
|
||||
status_t tests1ap_build_handover_notify(pkbuf_t **pkbuf, int i)
|
||||
{
|
||||
char *payload[TESTS1AP_MAX_MESSAGE] = {
|
||||
"0002"
|
||||
|
@ -1443,3 +1462,45 @@ status_t tests1ap_build_handover_notify(
|
|||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t tests1ap_build_handover_cancel(pkbuf_t **pkbuf, int i)
|
||||
{
|
||||
char *payload[TESTS1AP_MAX_MESSAGE] = {
|
||||
"0004"
|
||||
"0018000003000000 05c0020000c60008 0002000d00024002 0120",
|
||||
"",
|
||||
"",
|
||||
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
|
||||
};
|
||||
c_uint16_t len[TESTS1AP_MAX_MESSAGE] = {
|
||||
28,
|
||||
0,
|
||||
0,
|
||||
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
};
|
||||
char hexbuf[MAX_SDU_LEN];
|
||||
|
||||
*pkbuf = pkbuf_alloc(0, MAX_SDU_LEN);
|
||||
if (!(*pkbuf)) return CORE_ERROR;
|
||||
|
||||
(*pkbuf)->len = len[i];
|
||||
memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf),
|
||||
(*pkbuf)->len);
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ CORE_DECLARE(status_t) tests1ap_build_handover_request_ack(
|
|||
CORE_DECLARE(status_t) tests1ap_build_enb_status_transfer(
|
||||
pkbuf_t **pkbuf, int i);
|
||||
CORE_DECLARE(status_t) tests1ap_build_handover_notify(pkbuf_t **pkbuf, int i);
|
||||
CORE_DECLARE(status_t) tests1ap_build_handover_cancel(pkbuf_t **pkbuf, int i);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue