mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 04:30:28 +00:00
XNAP: add encode/decode and unit test for Xn Handover Success
- Add Handover Success message type definitions
- Implement encoder and decoder for Handover Success
Handover Success (3GPP TS 38.423v16.2.0 §9.1.1.12)
- Source NG-RAN node UE XnAP ID (M)
- Target NG-RAN node UE XnAP ID (M)
- Requested Target Cell Global ID (M)
- Add equality check and memory management helpers
- Extend XNAP library unit tests to cover Handover Success
Reviewed-by: Venkatareddy Akumalla <venkatareddy.akumalla@openairinterface.org>
Signed-off-by: Mohammed Safwan <mohammed.safwan@openairinterface.org>
This commit is contained in:
@@ -390,4 +390,14 @@ typedef struct {
|
||||
xnap_cause_t cause;
|
||||
} xnap_handover_cancel_t;
|
||||
|
||||
/* 3GPP TS 38.423 9.1.1.12 – Handover Success */
|
||||
typedef struct {
|
||||
/* Source NG-RAN node UE XnAP ID (M) */
|
||||
uint32_t s_ng_node_ue_xnap_id;
|
||||
/* Target NG-RAN node UE XnAP ID (M) */
|
||||
uint32_t t_ng_node_ue_xnap_id;
|
||||
/* Requested Target Cell Global ID (M) */
|
||||
xnap_ngran_cgi_t target_cgi;
|
||||
} xnap_handover_success_t;
|
||||
|
||||
#endif /* XNAP_MESSAGES_TYPES_H_ */
|
||||
|
||||
@@ -1381,3 +1381,110 @@ void free_xnap_handover_cancel(xnap_handover_cancel_t *msg)
|
||||
// Nothing to free
|
||||
UNUSED(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief XnAP Handover Success encoding
|
||||
*/
|
||||
XNAP_XnAP_PDU_t *encode_xnap_handover_success(const xnap_handover_success_t *msg)
|
||||
{
|
||||
XNAP_XnAP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu));
|
||||
|
||||
pdu->present = XNAP_XnAP_PDU_PR_initiatingMessage;
|
||||
asn1cCalloc(pdu->choice.initiatingMessage, initMsg);
|
||||
initMsg->procedureCode = XNAP_ProcedureCode_id_handoverSuccess;
|
||||
initMsg->criticality = XNAP_Criticality_ignore;
|
||||
initMsg->value.present = XNAP_InitiatingMessage__value_PR_HandoverSuccess;
|
||||
|
||||
XNAP_HandoverSuccess_t *out = &initMsg->value.choice.HandoverSuccess;
|
||||
|
||||
/* Source NG-RAN node UE XnAP ID (M) */
|
||||
asn1cSequenceAdd(out->protocolIEs.list, XNAP_HandoverSuccess_IEs_t, ie1);
|
||||
ie1->id = XNAP_ProtocolIE_ID_id_sourceNG_RANnodeUEXnAPID;
|
||||
ie1->criticality = XNAP_Criticality_reject;
|
||||
ie1->value.present = XNAP_HandoverSuccess_IEs__value_PR_NG_RANnodeUEXnAPID;
|
||||
ie1->value.choice.NG_RANnodeUEXnAPID = msg->s_ng_node_ue_xnap_id;
|
||||
|
||||
/* Target NG-RAN node UE XnAP ID (M) */
|
||||
asn1cSequenceAdd(out->protocolIEs.list, XNAP_HandoverSuccess_IEs_t, ie2);
|
||||
ie2->id = XNAP_ProtocolIE_ID_id_targetNG_RANnodeUEXnAPID;
|
||||
ie2->criticality = XNAP_Criticality_reject;
|
||||
ie2->value.present = XNAP_HandoverSuccess_IEs__value_PR_NG_RANnodeUEXnAPID_1;
|
||||
ie2->value.choice.NG_RANnodeUEXnAPID_1 = msg->t_ng_node_ue_xnap_id;
|
||||
|
||||
/* Requested Target Cell Global ID (M) */
|
||||
asn1cSequenceAdd(out->protocolIEs.list, XNAP_HandoverSuccess_IEs_t, ie3);
|
||||
ie3->id = XNAP_ProtocolIE_ID_id_requestedTargetCellGlobalID;
|
||||
ie3->criticality = XNAP_Criticality_reject;
|
||||
ie3->value.present = XNAP_HandoverSuccess_IEs__value_PR_Target_CGI;
|
||||
ie3->value.choice.Target_CGI = xnap_encode_target_cgi(&msg->target_cgi);
|
||||
|
||||
return pdu;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief XnAP Handover Success decoding
|
||||
*/
|
||||
bool decode_xnap_handover_success(xnap_handover_success_t *out, const XNAP_XnAP_PDU_t *pdu)
|
||||
{
|
||||
_EQ_CHECK_INT(pdu->present, XNAP_XnAP_PDU_PR_initiatingMessage);
|
||||
AssertError(pdu->choice.initiatingMessage != NULL, return false, "initiatingMessage is NULL");
|
||||
_EQ_CHECK_LONG(pdu->choice.initiatingMessage->procedureCode, XNAP_ProcedureCode_id_handoverSuccess);
|
||||
_EQ_CHECK_INT(pdu->choice.initiatingMessage->value.present, XNAP_InitiatingMessage__value_PR_HandoverSuccess);
|
||||
|
||||
XNAP_HandoverSuccess_t *in = &pdu->choice.initiatingMessage->value.choice.HandoverSuccess;
|
||||
XNAP_HandoverSuccess_IEs_t *ie;
|
||||
|
||||
XNAP_LIB_FIND_IE(XNAP_HandoverSuccess_IEs_t, ie, &in->protocolIEs.list, XNAP_ProtocolIE_ID_id_sourceNG_RANnodeUEXnAPID, true);
|
||||
XNAP_LIB_FIND_IE(XNAP_HandoverSuccess_IEs_t, ie, &in->protocolIEs.list, XNAP_ProtocolIE_ID_id_targetNG_RANnodeUEXnAPID, true);
|
||||
XNAP_LIB_FIND_IE(XNAP_HandoverSuccess_IEs_t, ie, &in->protocolIEs.list, XNAP_ProtocolIE_ID_id_requestedTargetCellGlobalID, true);
|
||||
|
||||
for (int i = 0; i < in->protocolIEs.list.count; i++) {
|
||||
DevAssert(in->protocolIEs.list.array[i]);
|
||||
ie = in->protocolIEs.list.array[i];
|
||||
|
||||
switch (ie->id) {
|
||||
case XNAP_ProtocolIE_ID_id_sourceNG_RANnodeUEXnAPID: {
|
||||
_EQ_CHECK_INT(ie->value.present, XNAP_HandoverSuccess_IEs__value_PR_NG_RANnodeUEXnAPID);
|
||||
out->s_ng_node_ue_xnap_id = ie->value.choice.NG_RANnodeUEXnAPID;
|
||||
} break;
|
||||
|
||||
case XNAP_ProtocolIE_ID_id_targetNG_RANnodeUEXnAPID: {
|
||||
_EQ_CHECK_INT(ie->value.present, XNAP_HandoverSuccess_IEs__value_PR_NG_RANnodeUEXnAPID_1);
|
||||
out->t_ng_node_ue_xnap_id = ie->value.choice.NG_RANnodeUEXnAPID_1;
|
||||
} break;
|
||||
|
||||
case XNAP_ProtocolIE_ID_id_requestedTargetCellGlobalID: {
|
||||
_EQ_CHECK_INT(ie->value.present, XNAP_HandoverSuccess_IEs__value_PR_Target_CGI);
|
||||
if (!xnap_decode_target_cgi(&ie->value.choice.Target_CGI, &out->target_cgi))
|
||||
return false;
|
||||
} break;
|
||||
|
||||
default:
|
||||
PRINT_ERROR("XNAP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief XnAP Handover Success equality function
|
||||
*/
|
||||
bool eq_xnap_handover_success(const xnap_handover_success_t *a, const xnap_handover_success_t *b)
|
||||
{
|
||||
_EQ_CHECK_UINT32(a->s_ng_node_ue_xnap_id, b->s_ng_node_ue_xnap_id);
|
||||
_EQ_CHECK_UINT32(a->t_ng_node_ue_xnap_id, b->t_ng_node_ue_xnap_id);
|
||||
if (!eq_xnap_ngran_cgi(&a->target_cgi, &b->target_cgi))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief XnAP Handover Success memory management
|
||||
*/
|
||||
void free_xnap_handover_success(xnap_handover_success_t *msg)
|
||||
{
|
||||
// Nothing to free
|
||||
UNUSED(msg);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ XNAP_XnAP_PDU_t *encode_xnap_handover_preparation_failure(const xnap_handover_pr
|
||||
XNAP_XnAP_PDU_t *encode_xnap_sn_status_transfer(const xnap_sn_status_transfer_t *sn_status);
|
||||
XNAP_XnAP_PDU_t *encode_xnap_ue_context_release(const xnap_ue_context_release_t *msg);
|
||||
XNAP_XnAP_PDU_t *encode_xnap_handover_cancel(const xnap_handover_cancel_t *msg);
|
||||
XNAP_XnAP_PDU_t *encode_xnap_handover_success(const xnap_handover_success_t *msg);
|
||||
|
||||
bool decode_xnap_handover_request(xnap_handover_req_t *req, const XNAP_XnAP_PDU_t *pdu);
|
||||
bool decode_xnap_handover_request_acknowledge(xnap_handover_req_ack_t *out, const XNAP_XnAP_PDU_t *pdu);
|
||||
@@ -21,6 +22,7 @@ bool decode_xnap_handover_preparation_failure(xnap_handover_preparation_failure_
|
||||
bool decode_xnap_sn_status_transfer(xnap_sn_status_transfer_t *out, const XNAP_XnAP_PDU_t *pdu);
|
||||
bool decode_xnap_ue_context_release(xnap_ue_context_release_t *out, const XNAP_XnAP_PDU_t *pdu);
|
||||
bool decode_xnap_handover_cancel(xnap_handover_cancel_t *out, const XNAP_XnAP_PDU_t *pdu);
|
||||
bool decode_xnap_handover_success(xnap_handover_success_t *out, const XNAP_XnAP_PDU_t *pdu);
|
||||
|
||||
bool eq_xnap_handover_request(const xnap_handover_req_t *a, const xnap_handover_req_t *b);
|
||||
bool eq_xnap_handover_request_acknowledge(const xnap_handover_req_ack_t *a, const xnap_handover_req_ack_t *b);
|
||||
@@ -29,6 +31,7 @@ bool eq_xnap_handover_preparation_failure(const xnap_handover_preparation_failur
|
||||
bool eq_xnap_sn_status_transfer(const xnap_sn_status_transfer_t *a, const xnap_sn_status_transfer_t *b);
|
||||
bool eq_xnap_ue_context_release(const xnap_ue_context_release_t *a, const xnap_ue_context_release_t *b);
|
||||
bool eq_xnap_handover_cancel(const xnap_handover_cancel_t *a, const xnap_handover_cancel_t *b);
|
||||
bool eq_xnap_handover_success(const xnap_handover_success_t *a, const xnap_handover_success_t *b);
|
||||
|
||||
void free_xnap_handover_request(xnap_handover_req_t *msg);
|
||||
void free_xnap_handover_request_acknowledge(xnap_handover_req_ack_t *msg);
|
||||
@@ -36,5 +39,6 @@ void free_xnap_handover_preparation_failure(xnap_handover_preparation_failure_t
|
||||
void free_xnap_sn_status_transfer(xnap_sn_status_transfer_t *msg);
|
||||
void free_xnap_ue_context_release(xnap_ue_context_release_t *msg);
|
||||
void free_xnap_handover_cancel(xnap_handover_cancel_t *msg);
|
||||
void free_xnap_handover_success(xnap_handover_success_t *msg);
|
||||
|
||||
#endif // XNAP_GNB_MOBILITY_MANAGEMENT_H_
|
||||
|
||||
@@ -688,6 +688,44 @@ static void test_xn_handover_cancel(void)
|
||||
printf("%s() successful\n", __func__);
|
||||
}
|
||||
|
||||
/**
|
||||
* 10. XnAP Handover Success Testing
|
||||
*/
|
||||
static void test_xn_handover_success(void)
|
||||
{
|
||||
/* ---------- create message ---------- */
|
||||
plmn_id_t plmn0 = {.mcc = 208, .mnc = 95, .mnc_digit_length = 2};
|
||||
|
||||
xnap_handover_success_t orig = {
|
||||
.s_ng_node_ue_xnap_id = 333333,
|
||||
.t_ng_node_ue_xnap_id = 444444,
|
||||
.target_cgi = {.plmn_id = plmn0, .nrcell_id = 0xABCDEF012ULL},
|
||||
};
|
||||
|
||||
/* ---------- encode ---------- */
|
||||
XNAP_XnAP_PDU_t *xnenc = encode_xnap_handover_success(&orig);
|
||||
AssertFatal(xnenc != NULL, "encode_xnap_handover_success failed");
|
||||
|
||||
XNAP_XnAP_PDU_t *xndec = xnap_encode_decode(xnenc);
|
||||
xnap_msg_free(xnenc);
|
||||
|
||||
/* ---------- decode ---------- */
|
||||
xnap_handover_success_t decoded = {0};
|
||||
bool ret = decode_xnap_handover_success(&decoded, xndec);
|
||||
AssertFatal(ret, "decode_xnap_handover_success failed");
|
||||
xnap_msg_free(xndec);
|
||||
|
||||
/* ---------- equality ---------- */
|
||||
ret = eq_xnap_handover_success(&orig, &decoded);
|
||||
AssertFatal(ret, "XnAP Handover Success mismatch\n");
|
||||
|
||||
/* ---------- cleanup ---------- */
|
||||
free_xnap_handover_success(&decoded);
|
||||
free_xnap_handover_success(&orig);
|
||||
|
||||
printf("%s() successful\n", __func__);
|
||||
}
|
||||
|
||||
int main() {
|
||||
printf("Starting XnAP Library Unit Tests...\n");
|
||||
|
||||
@@ -703,6 +741,7 @@ int main() {
|
||||
test_xn_sn_status_transfer();
|
||||
test_xn_ue_context_release();
|
||||
test_xn_handover_cancel();
|
||||
test_xn_handover_success();
|
||||
|
||||
printf("All XnAP tests passed!\n");
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user