From 5ff24cce71e23ecad2e0799507ce529af2270452 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 4 Jun 2025 16:19:15 +0200 Subject: [PATCH] Refactor pdusession_t Definitions Motivation: The previous code had overlapping and partially inconsiste definitions of `pdusession_t` and related structures across NGAP and RRC. This struct type was used for either the data stored in the UE context and the NGAP message IEs holding the PDU session to setup/modify information. This patch aims to separte the `pdusession_t` in RRC, where it logically belongs, since RRC owns the state of the PDU sessions. NGAP should only deal with protocol messages, i.e. enc/dec and transfer structures to RRC. This clarifies module ownership. This also makes the code easier to maintain. Changes: * Moved `pdusession_t` definition from NGAP (`ngap_messages_types.h`) to RRC (`nr_rrc_defs.h`) * Added a simpler `pdusession_resource_item_t` structure to NGAP for use in protocol messages * Adjusted NGAP structures accordingly (Initial Context Setup, PDU Session Setup Request, and PDU Session Modify Request). * do decodePDUSessionResourceSetup to decode the NGAP IEs holding PDU session information and store what necessary in the UE context PDU Session IE: NOTE this changes were necessary since previously this function was acting on the common NGAP/RRC pdu_session_t struct --- openair2/COMMON/ngap_messages_types.h | 44 ++++++++------------------- openair2/RRC/NR/nr_rrc_defs.h | 25 +++++++++++++++ openair2/RRC/NR/rrc_gNB_NGAP.c | 28 +++++++++-------- 3 files changed, 54 insertions(+), 43 deletions(-) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index 6bd2ed5a5f..db7529b797 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -231,31 +231,6 @@ typedef struct ngap_mobility_restriction_s{ ngap_plmn_identity_t serving_plmn; }ngap_mobility_restriction_t; -typedef enum pdu_session_type_e { - PDUSessionType_ipv4 = 0, - PDUSessionType_ipv6 = 1, - PDUSessionType_ipv4v6 = 2, - PDUSessionType_ethernet = 3, - PDUSessionType_unstructured = 4 -}pdu_session_type_t; - -typedef struct pdusession_s { - /* Unique pdusession_id for the UE. */ - int pdusession_id; - byte_array_t nas_pdu; - byte_array_t pdusessionTransfer; - uint8_t nb_qos; - /* Quality of service for this pdusession */ - pdusession_level_qos_parameter_t qos[QOSFLOW_MAX_VALUE]; - /* The transport layer address for the IP packets */ - pdu_session_type_t pdu_session_type; - // NG-RAN endpoint of the NG-U (N3) transport bearer - gtpu_tunnel_t n3_outgoing; - // UPF endpoint of the NG-U (N3) transport bearer - gtpu_tunnel_t n3_incoming; - nssai_t nssai; -} pdusession_t; - typedef enum pdusession_qosflow_mapping_ind_e{ QOSFLOW_MAPPING_INDICATION_UL = 0, QOSFLOW_MAPPING_INDICATION_DL = 1, @@ -563,6 +538,13 @@ typedef struct ngap_downlink_nas_s { byte_array_t nas_pdu; } ngap_downlink_nas_t; +/* PDU Session Resource Setup/Modify Request Item */ +typedef struct { + int pdusession_id; + byte_array_t nas_pdu; + nssai_t nssai; + byte_array_t pdusessionTransfer; +} pdusession_resource_item_t; typedef struct ngap_initial_context_setup_req_s { /* UE id for initial connection to NGAP */ @@ -588,8 +570,8 @@ typedef struct ngap_initial_context_setup_req_s { /* Number of pdusession to be setup in the list */ uint8_t nb_of_pdusessions; - /* list of pdusession to be setup by RRC layers */ - pdusession_t pdusession[NGAP_MAX_PDU_SESSION]; + // PDU Session Resource Setup Request List + pdusession_resource_item_t pdusession[NGAP_MAX_PDU_SESSION]; /* Mobility Restriction List */ uint8_t mobility_restriction_flag; @@ -637,8 +619,8 @@ typedef struct ngap_pdusession_setup_req_s { /* Number of pdusession to be setup in the list */ uint8_t nb_pdusessions_tosetup; - /* E RAB setup request */ - pdusession_t pdusession[NGAP_MAX_PDU_SESSION]; + // PDU Session Resource Setup Request List + pdusession_resource_item_t pdusession[NGAP_MAX_PDU_SESSION]; /* UE Aggregated Max Bitrates */ ngap_ambr_t ueAggMaxBitRate; @@ -693,8 +675,8 @@ typedef struct ngap_pdusession_modify_req_s { /* Number of pdusession to be modify in the list */ uint8_t nb_pdusessions_tomodify; - /* pdu session modify request */ - pdusession_t pdusession[NGAP_MAX_PDU_SESSION]; + // PDU Session Resource Modify Request List + pdusession_resource_item_t pdusession[NGAP_MAX_PDU_SESSION]; } ngap_pdusession_modify_req_t; typedef struct ngap_pdusession_modify_resp_s { diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 9998562b61..89fcfe7561 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -99,6 +99,31 @@ typedef enum pdu_session_satus_e { PDU_SESSION_STATUS_RELEASED } pdu_session_status_t; +typedef enum pdu_session_type_e { + PDUSessionType_ipv4 = 0, + PDUSessionType_ipv6 = 1, + PDUSessionType_ipv4v6 = 2, + PDUSessionType_ethernet = 3, + PDUSessionType_unstructured = 4 +}pdu_session_type_t; + +typedef struct pdusession_s { + /* Unique pdusession_id for the UE. */ + int pdusession_id; + byte_array_t nas_pdu; + byte_array_t pdusessionTransfer; + uint8_t nb_qos; + /* Quality of service for this pdusession */ + pdusession_level_qos_parameter_t qos[QOSFLOW_MAX_VALUE]; + /* The transport layer address for the IP packets */ + pdu_session_type_t pdu_session_type; + // NG-RAN endpoint of the NG-U (N3) transport bearer + gtpu_tunnel_t n3_outgoing; + // UPF endpoint of the NG-U (N3) transport bearer + gtpu_tunnel_t n3_incoming; + nssai_t nssai; +} pdusession_t; + typedef struct pdu_session_param_s { pdusession_t param; pdu_session_status_t status; diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 42fe17fec9..1bb60df9bc 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -254,7 +254,7 @@ static void fill_qos(NGAP_QosFlowSetupRequestList_t *qos, pdusession_t *session) session->nb_qos = qos->list.count; } -static int decodePDUSessionResourceSetup(pdusession_t *session) +static int decodePDUSessionResourceSetup(pdusession_t *out, const pdusession_resource_item_t *session) { NGAP_PDUSessionResourceSetupRequestTransfer_t *pdusessionTransfer = NULL; asn_codec_ctx_t st = {.max_stack_size = 100 * 1000}; @@ -283,11 +283,11 @@ static int decodePDUSessionResourceSetup(pdusession_t *session) NGAP_GTPTunnel_t *gTPTunnel_p = pdusessionTransfer_ies->value.choice.UPTransportLayerInformation.choice.gTPTunnel; /* Set the transport layer address */ - memcpy(session->n3_incoming.addr.buffer, gTPTunnel_p->transportLayerAddress.buf, gTPTunnel_p->transportLayerAddress.size); - session->n3_incoming.addr.length = gTPTunnel_p->transportLayerAddress.size * 8 - gTPTunnel_p->transportLayerAddress.bits_unused; + memcpy(out->n3_incoming.addr.buffer, gTPTunnel_p->transportLayerAddress.buf, gTPTunnel_p->transportLayerAddress.size); + out->n3_incoming.addr.length = gTPTunnel_p->transportLayerAddress.size * 8 - gTPTunnel_p->transportLayerAddress.bits_unused; /* GTP tunnel endpoint ID */ - OCTET_STRING_TO_INT32(&gTPTunnel_p->gTP_TEID, session->n3_incoming.teid); + OCTET_STRING_TO_INT32(&gTPTunnel_p->gTP_TEID, out->n3_incoming.teid); } break; @@ -302,7 +302,7 @@ static int decodePDUSessionResourceSetup(pdusession_t *session) /* mandatory PDUSessionType */ case NGAP_ProtocolIE_ID_id_PDUSessionType: - session->pdu_session_type = (uint8_t)pdusessionTransfer_ies->value.choice.PDUSessionType; + out->pdu_session_type = (uint8_t)pdusessionTransfer_ies->value.choice.PDUSessionType; break; /* optional SecurityIndication */ @@ -315,7 +315,7 @@ static int decodePDUSessionResourceSetup(pdusession_t *session) /* mandatory QosFlowSetupRequestList */ case NGAP_ProtocolIE_ID_id_QosFlowSetupRequestList: - fill_qos(&pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList, session); + fill_qos(&pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList, out); break; /* optional CommonNetworkInstance */ @@ -365,7 +365,6 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession session->nas_pdu = sessions[i].nas_pdu; session->pdusessionTransfer = sessions[i].pdusessionTransfer; session->nssai = sessions[i].nssai; - decodePDUSessionResourceSetup(session); bearer_req.gNB_cu_cp_ue_id = UE->rrc_ue_id; security_information_t *secInfo = &bearer_req.secInfo; secInfo->cipheringAlgorithm = rrc->security.do_drb_ciphering ? UE->ciphering_algorithm : 0; @@ -520,8 +519,9 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t UE->n_initial_pdu = req->nb_of_pdusessions; UE->initial_pdus = calloc(UE->n_initial_pdu, sizeof(*UE->initial_pdus)); AssertFatal(UE->initial_pdus != NULL, "out of memory\n"); - for (int i = 0; i < UE->n_initial_pdu; ++i) - UE->initial_pdus[i] = req->pdusession[i]; + for (int i = 0; i < UE->n_initial_pdu; ++i) { + decodePDUSessionResourceSetup(&UE->initial_pdus[i], &req->pdusession[i]); + } } /* security */ @@ -901,7 +901,7 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins // At least one because marking one as existing, and setting up another, that // might be more work than is worth it. See 8.2.1.4 in 38.413 for (int i = 0; i < msg->nb_pdusessions_tosetup; ++i) { - const pdusession_t *p = &msg->pdusession[i]; + const pdusession_resource_item_t *p = &msg->pdusession[i]; rrc_pdu_session_param_t *exist = find_pduSession(UE, p->pdusession_id, false /* don't create */); if (exist) { LOG_E(NR_RRC, "UE %d: already has existing PDU session %d rejecting PDU Session Resource Setup Request\n", UE->rrc_ue_id, p->pdusession_id); @@ -934,7 +934,11 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins return; } - if (!trigger_bearer_setup(rrc, UE, msg->nb_pdusessions_tosetup, msg->pdusession, msg->ueAggMaxBitRate.br_dl)) { + pdusession_t to_setup[NGAP_MAX_PDU_SESSION] = {0}; + for (int i = 0; i < msg->nb_pdusessions_tosetup; ++i) { + decodePDUSessionResourceSetup(&to_setup[i], &msg->pdusession[i]); + } + if (!trigger_bearer_setup(rrc, UE, msg->nb_pdusessions_tosetup, to_setup, msg->ueAggMaxBitRate.br_dl)) { // Reject PDU Session Resource setup if there's no CU-UP associated LOG_W(NR_RRC, "UE %d: reject PDU Session Setup in PDU Session Resource Setup Response\n", UE->rrc_ue_id); ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CAUSE_RADIO_NETWORK_RESOURCES_NOT_AVAILABLE_FOR_THE_SLICE}; @@ -1062,7 +1066,7 @@ int rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(MessageDef *msg_p, instance_t ins bool all_failed = true; for (int i = 0; i < req->nb_pdusessions_tomodify; i++) { rrc_pdu_session_param_t *sess; - const pdusession_t *sessMod = req->pdusession + i; + const pdusession_resource_item_t *sessMod = req->pdusession + i; for (sess = UE->pduSession; sess < UE->pduSession + UE->nb_of_pdusessions; sess++) if (sess->param.pdusession_id == sessMod->pdusession_id) break;