HO cancel done

This commit is contained in:
Sukchan Lee 2017-09-15 12:06:26 +09:00
parent f783e2ffd0
commit 0888f49c48
15 changed files with 397 additions and 63 deletions

View File

@ -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);

View File

@ -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)
{

View File

@ -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);

View File

@ -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;

View File

@ -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");
}

View File

@ -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;
}

View File

@ -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
}

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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
}