Add NGAP Handover Notify encoder and trigger on the target NG-RAN

This commit introduces the NG Mobility Management Procedure known as
Handover Notification. The outbound message is sent by the target NG-RAN
and is known as Handover Notify. The procedure is used to indicate to
the AMF that the UE has arrived to the target cell and the NG-based
handover has been successfully completed

* after RRCReconfiguration complete, in the N2 callback for HO success
* add NGAP encoder for the message
* RRC callback to trigger Handover Notify message

Co-authored-by: batuhan duyuler <batuhan.duyuler@firecell.io>
This commit is contained in:
Guido Casati
2025-09-18 11:34:30 +02:00
co-authored by batuhan duyuler
parent f66524879d
commit e611d092e9
10 changed files with 159 additions and 1 deletions
+48
View File
@@ -419,6 +419,50 @@ static int ngap_gNB_handover_request_acknowledge(instance_t instance, ngap_hando
return 0;
}
static int ngap_gNB_handover_notify(instance_t instance, const ngap_handover_notify_t *msg)
{
LOG_D(NGAP, "Encode NGAP Handover Notify\n");
ngap_gNB_ue_context_t *ue_context_p = NULL;
byte_array_t ba = { .buf = NULL, .len = 0};
/* Retrieve the NGAP gNB instance associated with Mod_id */
ngap_gNB_instance_t *ngap_gNB_instance_p = ngap_gNB_get_instance(instance);
DevAssert(msg != NULL);
DevAssert(ngap_gNB_instance_p != NULL);
if ((ue_context_p = ngap_get_ue_context(msg->gNB_ue_ngap_id)) == NULL) {
NGAP_ERROR("Failed to encode Handover Notify: no ue context associated with gNB_ue_ngap_id=%d\n", msg->gNB_ue_ngap_id);
return -1;
}
if (ue_context_p->gNB_ue_ngap_id != msg->gNB_ue_ngap_id) {
NGAP_ERROR("Failed to encode Handover Notify: unknown gNB_ue_ngap_id=%d\n", msg->gNB_ue_ngap_id);
return -1;
}
if (ue_context_p->amf_ue_ngap_id != msg->amf_ue_ngap_id) {
NGAP_ERROR("Failed to encode Handover Notify: unknown amf_ue_ngap_id=%ld\n", msg->amf_ue_ngap_id);
return -1;
}
NGAP_NGAP_PDU_t *pdu = encode_ng_handover_notify(msg);
if (ngap_gNB_encode_pdu(pdu, &ba.buf, (uint32_t *)&ba.len) < 0) {
NGAP_ERROR("Failed to encode NG Handover Notify message\n");
ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, pdu);
return -1;
}
/* UE associated signalling -> use the allocated stream */
ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance,
ue_context_p->amf_ref->assoc_id,
ba.buf,
ba.len,
ue_context_p->tx_stream);
return 0;
}
void *ngap_gNB_process_itti_msg(void *notUsed) {
MessageDef *received_msg = NULL;
int result;
@@ -509,6 +553,10 @@ void *ngap_gNB_process_itti_msg(void *notUsed) {
free_ng_handover_req_ack(&NGAP_HANDOVER_REQUEST_ACKNOWLEDGE(received_msg));
break;
case NGAP_HANDOVER_NOTIFY:
ngap_gNB_handover_notify(instance, &NGAP_HANDOVER_NOTIFY(received_msg));
break;
default:
NGAP_ERROR("Received unhandled message: %d:%s\n", ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg));
break;
+2 -1
View File
@@ -53,7 +53,8 @@ static inline int ngap_gNB_encode_initiating(NGAP_NGAP_PDU_t *pdu, uint8_t **buf
NGAP_ProcedureCode_id_UEContextReleaseRequest,
NGAP_ProcedureCode_id_PathSwitchRequest,
NGAP_ProcedureCode_id_PDUSessionResourceModifyIndication,
NGAP_ProcedureCode_id_HandoverPreparation};
NGAP_ProcedureCode_id_HandoverPreparation,
NGAP_ProcedureCode_id_HandoverNotification};
int i;
for (i = 0; i < sizeofArray(tmp); i++)
if (pdu->choice.initiatingMessage->procedureCode == tmp[i])
@@ -560,3 +560,60 @@ void free_ng_handover_command(ngap_handover_command_t *msg)
{
free_byte_array(msg->handoverCommand);
}
NGAP_NGAP_PDU_t *encode_ng_handover_notify(const ngap_handover_notify_t *msg)
{
NGAP_NGAP_PDU_t *pdu = malloc_or_fail(sizeof(*pdu));
// Message Type (M)
pdu->present = NGAP_NGAP_PDU_PR_initiatingMessage;
asn1cCalloc(pdu->choice.initiatingMessage, head);
head->procedureCode = NGAP_ProcedureCode_id_HandoverNotification;
head->criticality = NGAP_Criticality_ignore;
head->value.present = NGAP_InitiatingMessage__value_PR_HandoverNotify;
NGAP_HandoverNotify_t *out = &head->value.choice.HandoverNotify;
// AMF UE NGAP ID (M)
{
asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverNotifyIEs_t, ie);
ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID;
ie->criticality = NGAP_Criticality_reject;
ie->value.present = NGAP_HandoverNotifyIEs__value_PR_AMF_UE_NGAP_ID;
asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, msg->amf_ue_ngap_id);
}
// RAN UE NGAP ID (M)
{
asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverNotifyIEs_t, ie);
ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID;
ie->criticality = NGAP_Criticality_reject;
ie->value.present = NGAP_HandoverNotifyIEs__value_PR_RAN_UE_NGAP_ID;
ie->value.choice.RAN_UE_NGAP_ID = msg->gNB_ue_ngap_id;
}
// User Location Information (M)
{
asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverNotifyIEs_t, ie);
ie->id = NGAP_ProtocolIE_ID_id_UserLocationInformation;
ie->criticality = NGAP_Criticality_ignore;
ie->value.present = NGAP_HandoverNotifyIEs__value_PR_UserLocationInformation;
ie->value.choice.UserLocationInformation.present = NGAP_UserLocationInformation_PR_userLocationInformationNR;
asn1cCalloc(ie->value.choice.UserLocationInformation.choice.userLocationInformationNR, userinfo_nr_p);
// NR User Location Information
const target_ran_node_id_t *target = &msg->user_info.target_ng_ran;
// CGI (M)
MACRO_GNB_ID_TO_CELL_IDENTITY(target->targetgNBId, msg->user_info.nrCellIdentity, &userinfo_nr_p->nR_CGI.nRCellIdentity);
MCC_MNC_TO_TBCD(target->plmn_identity.mcc,
target->plmn_identity.mnc,
target->plmn_identity.mnc_digit_length,
&userinfo_nr_p->nR_CGI.pLMNIdentity);
// TAI (M)
INT24_TO_OCTET_STRING(target->tac, &userinfo_nr_p->tAI.tAC);
MCC_MNC_TO_PLMNID(target->plmn_identity.mcc,
target->plmn_identity.mnc,
target->plmn_identity.mnc_digit_length,
&userinfo_nr_p->tAI.pLMNIdentity);
}
return pdu;
}
@@ -33,5 +33,6 @@ NGAP_NGAP_PDU_t *encode_ng_handover_request_ack(ngap_handover_request_ack_t *msg
void free_ng_handover_req_ack(ngap_handover_request_ack_t *msg);
int decode_ng_handover_command(ngap_handover_command_t *msg, NGAP_NGAP_PDU_t *pdu);
void free_ng_handover_command(ngap_handover_command_t *msg);
NGAP_NGAP_PDU_t *encode_ng_handover_notify(const ngap_handover_notify_t *msg);
#endif /* NGAP_GNB_MOBILITY_MANAGEMENT_H_ */
+1
View File
@@ -101,5 +101,6 @@
#include "NGAP_HandoverRequestAcknowledgeTransfer.h"
#include "NGAP_QosFlowItemWithDataForwarding.h"
#include "NR_HandoverPreparationInformation.h"
#include "NGAP_HandoverNotify.h"
#endif // NGAP_MSG_INCLUDES_H