From dae251ddcb15c02c5d5dfb029a89e721082c78c5 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 24 Feb 2026 12:55:24 +0100 Subject: [PATCH 1/2] Fix DRB array offset when aggregating E1 DRBs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ensure DRBs from multiple PDU sessions are appended into the F1 DRB array without overwriting previously filled entries. Update fill_drb_to_be_setup_from_e1_resp to call fill_f1_drbs_from_e1 with &drbs[nb_drb] so each PDU session’s DRBs are written after the current count --- openair2/RRC/NR/rrc_gNB.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 0d5653bb1e..936f333124 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -3050,7 +3050,7 @@ static int fill_drb_to_be_setup_from_e1_resp(const gNB_RRC_INST *rrc, const pdu_session_setup_t *session = &pduSession[p]; rrc_pdu_session_param_t *pdu = find_pduSession(&UE->pduSessions, session->id); DevAssert(pdu); - nb_drb += fill_f1_drbs_from_e1(rrc, UE, pdu, session->DRBnGRanList, session->numDRBSetup, drbs); + nb_drb += fill_f1_drbs_from_e1(rrc, UE, pdu, session->DRBnGRanList, session->numDRBSetup, &drbs[nb_drb]); } DevAssert(nb_drb < MAX_DRBS_PER_UE); return nb_drb; From 3f4b72df67724a85bfc577f161585df4b9a9194e Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 24 Feb 2026 12:57:20 +0100 Subject: [PATCH 2/2] Handle duplicate PDU sessions in NGAP InitialContextSetup Ensure the CU-CP only sets up PDU sessions that are not already established for the UE, skipping duplicates while keeping the NG UE context valid. This aligns with 3GPP TS 38.413 PDU Session setup semantics for duplicate session IDs Changes: - Change rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ to scan requested PDU sessions and detect IDs that already exist in UE->pduSessions with PDU_SESSION_STATUS_ESTABLISHED - Log a warning and skip already established PDU session IDs so they are not added to UE->initial_pdus - Collect only non-established PDU sessions into a temporary stack array, allocate UE->initial_pdus with the exact count, copy them in, update UE->n_initial_pdu, and only refresh UE AMBR when there is at least one session to set up --- openair2/RRC/NR/rrc_gNB_NGAP.c | 40 +++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index dc9ec9c19a..76a96aa689 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -506,14 +506,38 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t if (req->nb_of_pdusessions > 0) { AssertFatal(req->has_ue_ambr, "UE aggregate maximum bitrate is required when there are PDU sessions to setup"); - /* 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_or_fail(UE->n_initial_pdu, sizeof(*UE->initial_pdus)); - for (int i = 0; i < UE->n_initial_pdu; ++i) - cp_pdusession_resource_item_to_pdusession(&UE->initial_pdus[i], &req->pdusession[i]); - UE->ambr.dl_br = req->ue_ambr.br_dl; - UE->ambr.ul_br = req->ue_ambr.br_ul; + + /* Build the list of PDU sessions to actually set up, filtering out those + * whose PDU Session ID already identifies an active PDU session for this UE. + * According to TS 38.413, establishment of such a PDU session shall be + * reported as failed in the response. */ + int ps_count = 0; + pdusession_t psessions[NGAP_MAX_PDU_SESSION] = {0}; + + for (int i = 0; i < req->nb_of_pdusessions; ++i) { + const pdusession_resource_item_t *src = &req->pdusession[i]; + + rrc_pdu_session_param_t *existing = find_pduSession(&UE->pduSessions, src->pdusession_id); + if (existing != NULL && existing->status == PDU_SESSION_STATUS_ESTABLISHED) { + LOG_W(NR_RRC, "UE %d: InitialContextSetup contains already active PDU session ID %d\n", UE->rrc_ue_id, src->pdusession_id); + continue; + } + + /* This is a PDU session that is not yet active for this UE: add it to the list */ + DevAssert(ps_count < req->nb_of_pdusessions); + cp_pdusession_resource_item_to_pdusession(&psessions[ps_count++], src); + } + + UE->n_initial_pdu = 0; + if (ps_count > 0) { + UE->initial_pdus = calloc_or_fail(ps_count, sizeof(*UE->initial_pdus)); + memcpy(UE->initial_pdus, psessions, ps_count * sizeof(*UE->initial_pdus)); + UE->n_initial_pdu = ps_count; + + /* If we have at least one session to set up, store AMBR */ + UE->ambr.dl_br = req->ue_ambr.br_dl; + UE->ambr.ul_br = req->ue_ambr.br_ul; + } } /* security */