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;