From 3e2d5f88208baddb1660d2ca0603394102b7d8c0 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 2 May 2024 13:43:01 +0200 Subject: [PATCH] Handle PDU sessions in NG UE context setup request In the case of PDU sessions in the NG UE context setup request, we first have to set up security. Hence, in this commit, implement the "delayed" set up of theses PDU sessions, and acknowledge the setup request after reconfiguration, as requested by O-RAN.WG5.C.1-v11. --- openair2/RRC/NR/nr_rrc_defs.h | 5 +++++ openair2/RRC/NR/nr_rrc_proto.h | 2 ++ openair2/RRC/NR/rrc_gNB.c | 30 ++++++++++++++++++++++++++---- openair2/RRC/NR/rrc_gNB_NGAP.c | 24 ++++++++++-------------- 4 files changed, 43 insertions(+), 18 deletions(-) diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 62402827fc..1c6121db69 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -319,6 +319,11 @@ typedef struct gNB_RRC_UE_s { uint32_t ue_reconfiguration_counter; struct NR_SpCellConfig *spCellConfig; + /* NGUEContextSetup might come with PDU sessions, but setup needs to be + * delayed after security (and capability); PDU sessions are stored here */ + int n_initial_pdu; + pdusession_t *initial_pdus; + /* Nas Pdu */ ngap_pdu_t nas_pdu; diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 0bb66d314e..9ae787bd7e 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -159,6 +159,8 @@ void nr_pdcp_add_drbs(eNB_flag_t enb_flag, uint8_t *const kUPenc, uint8_t *const kUPint); +void trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession_t *sessions, uint64_t ueAggMaxBitRateDownlink); + int rrc_gNB_generate_pcch_msg(sctp_assoc_t assoc_id, const NR_SIB1_t *sib, uint32_t tmsi, uint8_t paging_drx); void nr_rrc_transfer_protected_rrc_message(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue_p, uint8_t srb_id, const uint8_t* buffer, int size); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index cd8c56cfac..0bb2d27e9a 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1321,8 +1321,17 @@ static int handle_ueCapabilityInformation(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_send_NGAP_UE_CAPABILITIES_IND(ctxt_pP, ue_context_p, ue_cap_info); - rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(ctxt_pP, ue_context_p); - rrc_forward_ue_nas_message(RC.nrrrc[ctxt_pP->instance], UE); + if (UE->n_initial_pdu > 0) { + /* there were PDU sessions with the NG UE Context setup, but we had to set + * up security and request capabilities, so trigger PDU sessions now. The + * UE NAS message will be forwarded in the corresponding reconfiguration, + * the Initial context setup response after reconfiguration complete. */ + gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; + trigger_bearer_setup(rrc, UE, UE->n_initial_pdu, UE->initial_pdus, 0); + } else { + rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(ctxt_pP, ue_context_p); + rrc_forward_ue_nas_message(RC.nrrrc[ctxt_pP->instance], UE); + } return 0; } @@ -1415,7 +1424,13 @@ static void handle_rrcReconfigurationComplete(const protocol_ctxt_t *const ctxt_ rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(ctxt_pP, ue_context_p, xid); } break; case RRC_PDUSESSION_ESTABLISH: - if (UE->nb_of_pdusessions > 0) + if (UE->n_initial_pdu > 0) { + /* PDU sessions through initial UE context setup */ + rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(ctxt_pP, ue_context_p); + UE->n_initial_pdu = 0; + free(UE->initial_pdus); + UE->initial_pdus = NULL; + } else if (UE->nb_of_pdusessions > 0) rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(ctxt_pP, ue_context_p, xid); break; case RRC_PDUSESSION_MODIFY: @@ -1548,7 +1563,14 @@ int rrc_gNB_decode_dcch(const protocol_ctxt_t *const ctxt_pP, /* trigger UE capability enquiry if we don't have them yet */ if (ue_context_p->ue_context.ue_cap_buffer.len == 0) { rrc_gNB_generate_UECapabilityEnquiry(ctxt_pP, ue_context_p); - /* else block is executed after receiving UE capability info */ + /* else blocks are executed after receiving UE capability info */ + } else if (ue_context_p->ue_context.n_initial_pdu > 0) { + gNB_RRC_UE_t *UE = &ue_context_p->ue_context; + /* there were PDU sessions with the NG UE Context setup, but we had + * to set up security, so trigger PDU sessions now. The UE NAS + * message will be forwarded in the corresponding reconfiguration, + * the Initial context setup response after reconfiguration complete. */ + trigger_bearer_setup(gnb_rrc_inst, UE, UE->n_initial_pdu, UE->initial_pdus, 0); } else { /* we already have capabilities, and no PDU sessions to setup, ack * this UE */ diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 4e20ab671e..ec6922b598 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -362,7 +362,7 @@ static int decodePDUSessionResourceSetup(pdusession_t *session) return 0; } -static void trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession_t *sessions, uint64_t ueAggMaxBitRateDownlink) +void trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession_t *sessions, uint64_t ueAggMaxBitRateDownlink) { e1ap_bearer_setup_req_t bearer_req = {0}; @@ -493,19 +493,15 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t /* configure only integrity, ciphering comes after receiving SecurityModeComplete */ nr_rrc_pdcp_config_security(&ctxt, ue_context_p, 0); - uint8_t nb_pdusessions_tosetup = req->nb_of_pdusessions; - /* if there are PDU sessions to setup, first send them to the CU-UP. - * Once the E1 bearer are activated, the CUCP will trigger the context - * setup. */ - AssertFatal(nb_pdusessions_tosetup == 0, "no UE context setup request, so can't setup PDU sessions\n"); - if (nb_pdusessions_tosetup > 0) { - trigger_bearer_setup(RC.nrrrc[instance], - UE, - req->nb_of_pdusessions, - req->pdusession_param, - /*req->ueAggMaxBitRateDownlink*/ 0); - } else { - rrc_gNB_generate_SecurityModeCommand(&ctxt, ue_context_p); + rrc_gNB_generate_SecurityModeCommand(&ctxt, ue_context_p); + if (req->nb_of_pdusessions > 0) { + /* if there are PDU sessions to setup, store them to be created once + * security (and UE capabilities) are received */ + 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_param[i]; } return 0;