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
This commit is contained in:
Guido Casati
2026-02-25 09:50:27 +01:00
parent dae251ddcb
commit 3f4b72df67
+32 -8
View File
@@ -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 */