fix (gNB RRC): release RRC connection after last DRB

TS 38.331 §5.3.1.1 forbids RRC_CONNECTED with SRB2 and zero DRBs.
Releasing all DRBs must release the RRC connection.

After PDU session release (3GPP TS 23.502 §4.3.4.2), OAI left
SRB2 up and COTS UEs could re-establish into an invalid configuration.

On NGAP PDU Session Release Response, if no DRBs remain and SRB2 is
active, send NGAP UE Context Release Request. AMF Command drives
RRCRelease on the existing CU-CP path.

Closes: #148

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
This commit is contained in:
Guido Casati
2026-06-11 17:53:13 +02:00
parent cb9dab74e3
commit 1a1502ac5a

View File

@@ -1868,6 +1868,33 @@ void rrc_gNB_send_NGAP_HANDOVER_CANCEL(int module_id, gNB_RRC_UE_t *UE, ngap_cau
itti_send_msg_to_task(TASK_NGAP, module_id, msg_p);
}
/**
* @brief Enforce TS 38.331 §5.3.1.1 after the last DRB of a PDU session release.
* A UE is not allowed to have a configuration with SRB2 but no DRB, and vice versa.
* @note Per TS 23.502 section 4.3.4.2 step 5, NG-RAN releases PDU-session AN resources
* via RRCReconfiguration. If that leaves no DRB with SRB2 still up, request UE context
* release (TS 38.413 section 8.3.2.2). AMF UE Context Release Command triggers RRCRelease
* on the existing CU-CP path. */
static void rrc_gNB_cleanup_srb2_only_connected(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE)
{
DevAssert(seq_arr_size(&UE->drbs) == 0);
DevAssert(UE->Srb[SRB2].Active);
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, UE->rrc_ue_id);
if (!ue_context_p) {
LOG_W(NR_RRC, "UE %u: no RRC context for connection release after last DRB\n", UE->rrc_ue_id);
return;
}
LOG_I(NR_RRC, "UE %u: last DRB released with SRB2 still active: requesting RRC connection release\n", UE->rrc_ue_id);
ngap_cause_t cause = {
.type = NGAP_CAUSE_RADIO_NETWORK,
.value = NGAP_CAUSE_RADIO_NETWORK_RELEASE_DUE_TO_NGRAN_GENERATED_REASON,
};
rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_REQ(rrc->module_id, ue_context_p, cause);
}
void rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, uint8_t xid)
{
MessageDef *msg_p;
@@ -1892,6 +1919,10 @@ void rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(gNB_RRC_INST *rrc, gNB_RRC_UE
LOG_I(NR_RRC, "NGAP PDUSESSION RELEASE RESPONSE: rrc_ue_id %u release_pdu_sessions %d\n", resp->gNB_ue_ngap_id, resp->nb_of_pdusessions_released);
itti_send_msg_to_task (TASK_NGAP, rrc->module_id, msg_p);
/* TS 38.331 §5.3.1.1: cannot keep SRB2 in RRC_CONNECTED after all DRBs are gone. */
if (seq_arr_size(&UE->drbs) == 0 && UE->Srb[SRB2].Active)
rrc_gNB_cleanup_srb2_only_connected(rrc, UE);
}
/** @brief Process NG PDU Session Resource Release command (8.2.2 of 3GPP TS 38.413)