From d4c0431cc7e020ed06383451181d39288692a480 Mon Sep 17 00:00:00 2001 From: Rakesh Mundlamuri Date: Mon, 29 Dec 2025 18:22:46 +0530 Subject: [PATCH] Add NGAP DOWNLINK UE ASSOCIATED NRPPA TRANSPORT message decoding Reference: 3GPP 38.413 v16.0.0 Mandatory fields: AMF UE NGAP ID (supported) RAN UE NGAP ID (supported) Routing ID (supported) NRPPa-PDU (supported) --- common/utils/ocp_itti/intertask_interface.h | 1 + openair2/COMMON/ngap_messages_def.h | 6 ++ openair2/COMMON/ngap_messages_types.h | 13 +++ .../ngap_gNB_NRPPa_transport_procedures.c | 81 +++++++++++++++++++ .../ngap_gNB_NRPPa_transport_procedures.h | 3 + 5 files changed, 104 insertions(+) diff --git a/common/utils/ocp_itti/intertask_interface.h b/common/utils/ocp_itti/intertask_interface.h index d23e62365d..7580698dcf 100644 --- a/common/utils/ocp_itti/intertask_interface.h +++ b/common/utils/ocp_itti/intertask_interface.h @@ -294,6 +294,7 @@ typedef struct { TASK_DEF(TASK_RAL_ENB, 200) \ TASK_DEF(TASK_S1AP, 200) \ TASK_DEF(TASK_NGAP, 200) \ + TASK_DEF(TASK_NRPPA, 200) \ TASK_DEF(TASK_X2AP, 200) \ TASK_DEF(TASK_M2AP_ENB, 200) \ TASK_DEF(TASK_M2AP_MCE, 200) \ diff --git a/openair2/COMMON/ngap_messages_def.h b/openair2/COMMON/ngap_messages_def.h index 09e893f874..95d29baab2 100644 --- a/openair2/COMMON/ngap_messages_def.h +++ b/openair2/COMMON/ngap_messages_def.h @@ -88,3 +88,9 @@ MESSAGE_DEF(NGAP_HANDOVER_CANCEL_ACK, MESSAGE_PRIORITY_MED, ngap_handover_cancel /* NGAP <-> RRC messages (can be initiated either by MME or gNB) */ MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_REQ , MESSAGE_PRIORITY_MED, ngap_ue_release_req_t , ngap_ue_release_req) + +/* NGAP -> NRPPA messages*/ +MESSAGE_DEF(NGAP_DOWNLINKUEASSOCIATEDNRPPA, + MESSAGE_PRIORITY_MED, + ngap_downlink_ue_associated_nrppa_t, + ngap_downlink_ue_associated_nrppa) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index c47a564acb..b33cb34b09 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -79,6 +79,7 @@ #define NGAP_UL_RAN_STATUS_TRANSFER(mSGpTR) (mSGpTR)->ittiMsg.ngap_ul_ran_status_transfer #define NGAP_DL_RAN_STATUS_TRANSFER(mSGpTR) (mSGpTR)->ittiMsg.ngap_dl_ran_status_transfer +#define NGAP_DOWNLINKUEASSOCIATEDNRPPA(mSGpTR) (mSGpTR)->ittiMsg.ngap_downlink_ue_associated_nrppa //-------------------------------------------------------------------------------------------// /* Length of the transport layer address string @@ -1027,4 +1028,16 @@ typedef struct { byte_array_t nrppa_pdu; } ngap_uplink_non_ue_associated_nrppa_t; +// Downlink UE Associated NRPPA Transport message (9.2.9.1 3GPP 38.413 v16.0.0) +typedef struct { + // AMF UE NGAP ID (Mandatory) + uint64_t amf_ue_ngap_id; + // RAN UE NGAP ID (Mandatory) + uint32_t gNB_ue_ngap_id; + // Routing ID (Mandatory) + byte_array_t routing_id; + // NRPPa pdu (Mandatory) + byte_array_t nrppa_pdu; +} ngap_downlink_ue_associated_nrppa_t; + #endif /* NGAP_MESSAGES_TYPES_H_ */ diff --git a/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.c b/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.c index 56a85be44c..67b1db1578 100644 --- a/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.c +++ b/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.c @@ -194,3 +194,84 @@ int ngap_gNB_uplink_non_ue_associated_nrppa_transport(instance_t instance, const ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); return 0; } + +// handle DOWNLINK UE ASSOCIATED NRPPA TRANSPORT (9.2.9.1 of TS 38.413 Version 16.0.0) +int ngap_gNB_handle_downlink_ue_associated_nrppa_transport(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu) +{ + DevAssert(pdu != NULL); + ngap_gNB_amf_data_t *amf_desc_p = NULL; + + if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) { + NGAP_ERROR("[SCTP %d] Received NRPPa downlink message for non existing AMF context\n", assoc_id); + return -1; + } + + ngap_gNB_instance_t *ngap_gNB_instance = NULL; + ngap_gNB_instance = amf_desc_p->ngap_gNB_instance; + + // Prepare the NGAP message for NRPPA + NGAP_DownlinkUEAssociatedNRPPaTransport_t *container = NULL; + NGAP_DownlinkUEAssociatedNRPPaTransportIEs_t *ie = NULL; + + // IE: 9.3.1.1 Message Type + container = &pdu->choice.initiatingMessage->value.choice.DownlinkUEAssociatedNRPPaTransport; + + // IE: 9.3.3.1 AMF UE NGAP ID + uint64_t amf_ue_ngap_id; + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_DownlinkUEAssociatedNRPPaTransportIEs_t, + ie, + container, + NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID, + true); + asn_INTEGER2ulong(&(ie->value.choice.AMF_UE_NGAP_ID), &amf_ue_ngap_id); + + // IE: 9.3.3.2 RAN UE NGAP ID + NGAP_RAN_UE_NGAP_ID_t gnb_ue_ngap_id; + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_DownlinkUEAssociatedNRPPaTransportIEs_t, + ie, + container, + NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID, + true); + gnb_ue_ngap_id = ie->value.choice.RAN_UE_NGAP_ID; + + ngap_gNB_ue_context_t *ue_desc_p = NULL; + if ((ue_desc_p = ngap_get_ue_context(gnb_ue_ngap_id)) == NULL) { + NGAP_ERROR("[SCTP %d] Received NRPPa downlink message for non existing UE context gNB_UE_NGAP_ID: 0x%lx\n", + assoc_id, + gnb_ue_ngap_id); + return -1; + } + + // Is it the first outcome of the AMF for this UE ? If so store the amf UE ngap id + if (ue_desc_p->amf_ue_ngap_id == 0) { + ue_desc_p->amf_ue_ngap_id = amf_ue_ngap_id; + } else { + // We already have a amf ue ngap id check the received is the same + if (ue_desc_p->amf_ue_ngap_id != amf_ue_ngap_id) { + NGAP_ERROR("[SCTP %d] Mismatch in AMF UE NGAP ID (0x%lx != 0x%" PRIx64 "\n", + assoc_id, + amf_ue_ngap_id, + (uint64_t)ue_desc_p->amf_ue_ngap_id); + return -1; + } + } + + MessageDef *msg = itti_alloc_new_message(TASK_NGAP, 0, NGAP_DOWNLINKUEASSOCIATEDNRPPA); + ngap_downlink_ue_associated_nrppa_t *dl_ue_assoc_nrppa = &NGAP_DOWNLINKUEASSOCIATEDNRPPA(msg); + + dl_ue_assoc_nrppa->amf_ue_ngap_id = amf_ue_ngap_id; + dl_ue_assoc_nrppa->gNB_ue_ngap_id = gnb_ue_ngap_id; + + // IE: 9.3.3.13 Routing ID + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_DownlinkUEAssociatedNRPPaTransportIEs_t, ie, container, NGAP_ProtocolIE_ID_id_RoutingID, true); + dl_ue_assoc_nrppa->routing_id = create_byte_array(ie->value.choice.RoutingID.size, ie->value.choice.RoutingID.buf); + + // IE: 9.3.3.14 NRPPa-PDU + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_DownlinkUEAssociatedNRPPaTransportIEs_t, ie, container, NGAP_ProtocolIE_ID_id_NRPPa_PDU, true); + dl_ue_assoc_nrppa->nrppa_pdu = create_byte_array(ie->value.choice.NRPPa_PDU.size, ie->value.choice.NRPPa_PDU.buf); + + // Forward the NRPPA PDU to NRPPA + itti_send_msg_to_task(TASK_NRPPA, ngap_gNB_instance->instance, msg); + + return 0; +} diff --git a/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.h b/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.h index 2624bee0a4..c045ce31aa 100644 --- a/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.h +++ b/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.h @@ -28,4 +28,7 @@ int ngap_gNB_uplink_ue_associated_nrppa_transport(instance_t instance, const nga // UPLINK NON UE ASSOCIATED NRPPA TRANSPORT (9.2.9.4 of TS 38.413 Version 16.0.0) int ngap_gNB_uplink_non_ue_associated_nrppa_transport(instance_t instance, const ngap_uplink_non_ue_associated_nrppa_t *msg); +// DOWNLINK UE ASSOCIATED NRPPA TRANSPORT (9.2.9.1 of TS 38.413 Version 16.0.0) +int ngap_gNB_handle_downlink_ue_associated_nrppa_transport(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu); + #endif /* NGAP_GNB_NRPPA_PROCEDURES_H_ */