From 33ff2257396472c9a911052ab4c6a6289ef49262 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 13 Feb 2026 14:13:39 +0100 Subject: [PATCH 01/12] fix (RRC): add SRB2 and DRB validation checks for reestablishment Add validation checks per TS 38.331 5.3.7.1 to ensure SRB2 and at least one DRB are active before processing RRC reestablishment requests. Use more specific NGAP cause code for procedure failures. Reestablishment requests without SRB2 or DRB setup now properly fall back to RRC setup with appropriate NGAP cause indication Major changes: - Add SRB2 active check before processing reestablishment - Add DRB active check (at least one DRB required) Signed-off-by: Guido Casati --- openair2/RRC/NR/rrc_gNB.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index ac173bfcc0..3652ae02ee 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1510,6 +1510,15 @@ static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc, goto fallback_rrc_setup; } + /* TS 38.331 5.3.7.1: requires a retrieved valid UE context. Context without + * SRB2 or any DRB is incomplete for re-establishment (UE initiation needs both, + * treat as not verified). */ + if (!UE->Srb[SRB2].Active || seq_arr_size(&UE->drbs) == 0) { + LOG_E(NR_RRC, "UE context not valid for re-establishment (no SRB2/DRB), fallback to RRC setup\n"); + ngap_cause = NGAP_CAUSE_RADIO_NETWORK_RELEASE_DUE_TO_NGRAN_GENERATED_REASON; + goto fallback_rrc_setup; + } + f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id); nr_ho_source_cu_t *source_ctx = UE->ho_context ? UE->ho_context->source : NULL; From ede596cfc771b492f2fa9a04811dd8468827e00e Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 11 Jun 2026 16:43:26 +0200 Subject: [PATCH 02/12] RRCReestablishmentRequest: note RRCSetup fallback when UE context is missing Signed-off-by: Guido Casati --- openair2/RRC/NR/rrc_gNB.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 3652ae02ee..66307ea8b4 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1488,6 +1488,8 @@ static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc, return; } + /* TS 38.331 §5.3.7.1: retrieve UE context (C-RNTI + physCellId): if it cannot be + * retrieved, respond with RRCSetup (Fig. 5.3.7.1-2). */ ue_context_p = rrc_gNB_get_ue_context_by_rnti(rrc, assoc_id, old_rnti); if (ue_context_p == NULL) { // Fallback 1: Try to find UE by RNTI only (re-establishment on different DU scenario) From 2716a5a3dc4d7da15fce93d5a438b6f42c38d8a3 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 13 Feb 2026 14:34:14 +0100 Subject: [PATCH 03/12] RRCReestablishmentRequest: add PCI range validation Add validation of physCellId against valid range (0-1007) per TS 38.331 specification. Invalid PCI values are now rejected early in the reestablishment procedure. This prevents processing of invalid reestablishment requests with out-of-range PCI values, improving robustness and spec compliance. Major changes: - Add NR_PHYS_CELL_ID_MAX to common/platform_constants.h - Add PCI range check in rrc_handle_RRCReestablishmentRequest() before cell lookup, returning early on invalid values Signed-off-by: Guido Casati --- common/platform_constants.h | 2 ++ openair2/RRC/NR/rrc_gNB.c | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/common/platform_constants.h b/common/platform_constants.h index 636f5d956d..851e850ffb 100644 --- a/common/platform_constants.h +++ b/common/platform_constants.h @@ -55,6 +55,8 @@ /** Maximum number of Paging Occasions per Paging Frame (TS 38.331 PCCH-Config) */ #define NR_PCCH_MAX_PO 4 +#define NR_PHYS_CELL_ID_MAX 1007 /* Maximum Physical Cell ID (0..1007) */ + #define NB_RB_MBMS_MAX (29 * 16) /* 29 = LTE_maxSessionPerPMCH + 16 = LTE_maxServiceCount from LTE_asn_constant.h */ #define NB_RAB_MAX 11 /* from LTE_maxDRB in LTE_asn_constant.h */ diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 66307ea8b4..5492a3b3df 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1451,6 +1451,12 @@ static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc, physCellId, scause); + /* Validate PCI range per TS 38.331: PhysCellId (0..1007) */ + if (physCellId < 0 || physCellId > NR_PHYS_CELL_ID_MAX) { + LOG_E(NR_RRC, "Invalid physCellId %ld (valid range: 0-%d), rejecting reestablishment request\n", physCellId, NR_PHYS_CELL_ID_MAX); + return; + } + const nr_rrc_du_container_t *du = get_du_by_assoc_id(rrc, assoc_id); if (du == NULL) { LOG_E(RRC, "received CCCH message, but no corresponding DU found\n"); From d56892046685abb80a4a2c362fdc284934ae78fe Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 13 Feb 2026 14:36:35 +0100 Subject: [PATCH 04/12] RRCReestablishmentRequest: add input parameters validation Add defensive parameter checks at the start of rrc_handle_RRCReestablishmentRequest to prevent NULL pointer dereferences and invalid assoc_id handling. Signed-off-by: Guido Casati --- openair2/RRC/NR/rrc_gNB.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 5492a3b3df..6f7c4aa2b4 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1437,6 +1437,11 @@ static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc, const NR_RRCReestablishmentRequest_IEs_t *req, const f1ap_initial_ul_rrc_message_t *msg) { + DevAssert(req); + DevAssert(msg); + DevAssert(rrc); + RETURN_IF_INVALID_ASSOC_ID(assoc_id); + uint64_t random_value = 0; const char *scause = get_reestab_cause(req->reestablishmentCause); const long physCellId = req->ue_Identity.physCellId; From cde7d98a616de8d50b8fb87e90674fe29502b25e Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 13 Feb 2026 14:42:17 +0100 Subject: [PATCH 05/12] RRCReestablishmentRequest: add C-RNTI constants and fix spec compliance Replace hardcoded C-RNTI range values (0x1, 0xffef) with named constants NR_C_RNTI_MIN and NR_C_RNTI_MAX. Correct maximum value to 0xfff2 per TS 38.321 Table 7.1-1. Change invalid C-RNTI handling to return early instead of fallback to RRCSetup for spec compliance. Fallback to RRCSetup only occurs when UE context cannot be retrieved, not for validation errors, which for out-of-range values could come from malicious UEs. Major changes: - Add NR_C_RNTI_MIN (0x0001) and NR_C_RNTI_MAX (0xfff2) constants to common/platform_constants.h - Replace magic numbers in C-RNTI validation with named constants - Change error path from fallback_rrc_setup to return for invalid C-RNTI - Early validation before further processing Signed-off-by: Guido Casati --- openair2/RRC/NR/rrc_gNB.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 6f7c4aa2b4..f2377a2466 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -97,6 +97,10 @@ mui_t rrc_gNB_mui = 0; /* Per-transaction max_delays counter to limit retry attempts */ #define MAX_DELAYS 100 +/* C-RNTI range (0001-FFF2) (TS 38.321 Table 7.1-1, Rel-16+) */ +#define NR_C_RNTI_MIN 0x0001 +#define NR_C_RNTI_MAX 0xfff2 + /** @brief clone and re-enqueue an NGAP message after delaying * delays the ongoing transaction (in msg_p) by setting a timer to wait * 10ms; upon expiry, delivers to RRC, which sends the message to itself */ @@ -1462,6 +1466,12 @@ static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc, return; } + /* TS 38.321 Table 7.1-1: out-of-range C-RNTI, ignore request */ + if (old_rnti < NR_C_RNTI_MIN || old_rnti > NR_C_RNTI_MAX) { + LOG_E(NR_RRC, "C-RNTI %04x out of range (%#04x-%#04x): rejecting RRCReestablishmentRequest\n", old_rnti, NR_C_RNTI_MIN, NR_C_RNTI_MAX); + return; + } + const nr_rrc_du_container_t *du = get_du_by_assoc_id(rrc, assoc_id); if (du == NULL) { LOG_E(RRC, "received CCCH message, but no corresponding DU found\n"); @@ -1478,12 +1488,6 @@ static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc, return; } - // Validate C-RNTI range (3GPP TS 38.321 version 15.13.0 Section 7.1 Table 7.1-1) - if (old_rnti < 0x1 || old_rnti > 0xffef) { - LOG_E(NR_RRC, "NR_RRCReestablishmentRequest c_RNTI %04x range error, fallback to RRC setup\n", old_rnti); - goto fallback_rrc_setup; - } - if (current_cell->mtc == NULL) { // some UEs don't send MeasurementTimingConfiguration, so we don't know the // SSB ARFCN and can't do reestablishment. handle it gracefully by doing From f5aaacd9e8740b9f5ea469698fad0566d2b9d10e Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 13 Feb 2026 15:01:59 +0100 Subject: [PATCH 06/12] RRCReestablishmentRequest: replace random value magic number with constant Replace the magic number 0x7fffffffff used for masking 39-bit random values with a named constant NR_RRC_RANDOM_VALUE_39_BIT_MASK defined in nr_rrc_defs.h. Refs: - TS 38.331 5.3.3.3: Random UE identity (39-bit values) Signed-off-by: Guido Casati --- openair2/RRC/NR/rrc_gNB.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index f2377a2466..691cb9b92a 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -101,6 +101,9 @@ mui_t rrc_gNB_mui = 0; #define NR_C_RNTI_MIN 0x0001 #define NR_C_RNTI_MAX 0xfff2 +/* 5.3.3.3 TS 38.331: Random UE identity mask for 39-bit values */ +#define NR_RRC_RANDOM_VALUE_39_BIT_MASK (0x7fffffffffULL) + /** @brief clone and re-enqueue an NGAP message after delaying * delays the ongoing transaction (in msg_p) by setting a timer to wait * 10ms; upon expiry, delivers to RRC, which sends the message to itself */ @@ -1644,7 +1647,7 @@ static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc, fallback_rrc_setup: fill_random(&random_value, sizeof(random_value)); - random_value = random_value & 0x7fffffffff; /* random value is 39 bits */ + random_value = random_value & NR_RRC_RANDOM_VALUE_39_BIT_MASK; ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = ngap_cause}; /* request release of the "old" UE in case it exists */ From f79f5087e50552de70cb72c3cfa328e527fe65b0 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 13 Feb 2026 15:03:37 +0100 Subject: [PATCH 07/12] RRCReestablishmentRequest: add doxygen documentation Signed-off-by: Guido Casati --- openair2/RRC/NR/rrc_gNB.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 691cb9b92a..e649c1fe25 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1439,6 +1439,10 @@ static const nr_rrc_cell_container_t *get_previous_cell_by_pci_in_du(gNB_RRC_INS return rrc_get_cell_by_pci_for_du(&du->cells, pci); } +/** @brief Process RRCReestablishmentRequest on CCCH (TS 38.331 clause 5.3.7.4). + * On valid UE context, update RNTI and PCell and trigger RRCReestablishment, otherwise + * release any old context and send RRCSetup. + * @note Context lookup uses c-RNTI only. Out of range PhysCellId or C-RNTI are ignored. */ static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc, sctp_assoc_t assoc_id, const NR_RRCReestablishmentRequest_IEs_t *req, From cb9dab74e3b4d55983c86c3fb2ef10428b017108 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 11 Jun 2026 17:40:05 +0200 Subject: [PATCH 08/12] fix (gNB RRC): skip CU-UP notify on re-estab without DRBs Avoid E1 bearer modification when the UE has no DRBs left (e.g. after PDU session release). (TS 38.331 clause 5.3.5.6.5 DRB with reestablishPDCP) Changes: - cuup_notify_reestablishment(): return early if drbs is empty Fixes: #148 Signed-off-by: Guido Casati --- openair2/RRC/NR/rrc_gNB.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index e649c1fe25..8b35552dcc 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1092,9 +1092,8 @@ static DRB_nGRAN_to_mod_t get_e1_drb_mod_reestablishment(const drb_t *drb, const return drb_e1; } -/** - * @brief Notify E1 re-establishment to CU-UP - */ +/** @brief Re-establish DRB PDCP on CU-UP (TS 38.331 clause 5.3.5.6.5, TS 38.463 bearer mod). + * Sends pDCP_Reestablishment and updated KUP keys after KgNB derivation. */ static void cuup_notify_reestablishment(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p) { // Quit if no CU-UP is associated @@ -1102,6 +1101,10 @@ static void cuup_notify_reestablishment(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p) return; } + /* TS 38.331 §5.3.5.6.5: no DRB/PDU session (e.g. after release) means nothing to do. */ + if (seq_arr_size(&ue_p->drbs) == 0) + return; + e1ap_bearer_mod_req_t req = { .gNB_cu_cp_ue_id = ue_p->rrc_ue_id, .gNB_cu_up_ue_id = ue_p->rrc_ue_id, From 1a1502ac5afc7f46df542cd1609595693e58bd2d Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 11 Jun 2026 17:53:13 +0200 Subject: [PATCH 09/12] fix (gNB RRC): release RRC connection after last DRB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- openair2/RRC/NR/rrc_gNB_NGAP.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 9811317b75..ffa579ff7c 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -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) From 1c659403b72bee6515d45563cb5f75f82d49d338 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Sun, 21 Jun 2026 16:56:00 +0200 Subject: [PATCH 10/12] fix (RRC): log in nr_rrc_rrcsetup_fallback Signed-off-by: Guido Casati --- openair2/RRC/NR_UE/rrc_UE.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 3861cabd94..eab19775d7 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -2147,7 +2147,7 @@ static void rrc_ue_generate_RRCSetupComplete(NR_UE_RRC_INST_t *rrc, const uint8_ static void nr_rrc_rrcsetup_fallback(NR_UE_RRC_INST_t *rrc) { LOG_W(NR_RRC, - "[UE %ld] Recived RRCSetup in response to %s request\n", + "[UE %ld] Received RRCSetup in response to %s request\n", rrc->ue_id, rrc->ra_trigger == RRC_CONNECTION_REESTABLISHMENT ? "RRCReestablishment" : "RRCResume"); // discard any stored UE Inactive AS context and suspendConfig From e179a6df8ff179fe5c0f7ad2cf6e10a0d115905e Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 23 Jun 2026 16:02:19 +0200 Subject: [PATCH 11/12] fix (UE RRC): queue MAC reset before RLC teardown on RRCSetup fallback When the gNB answers RRCReestablishmentRequest with RRCSetup (TS 38.331 clause 5.3.3.4 fallback), the UE must release all bearers except SRB0 before applying the new masterCellGroup. CONFIG_RESET was queued after RLC release, so the MAC slot thread kept polling LCID 1 from a stale lc_ordered_list while the RLC entity was already NULL. Queue NR_MAC_RRC_CONFIG_RESET (RRC_SETUP_REESTAB_RESUME) first, then release PDCP, RLC, and SDAP. On the MAC thread, clear lc_ordered_list except SRB0 before release_mac_configuration() so the UL scheduler stops looping released logical channels until CONFIG_CG re-adds SRB1. Changes: - rrc_UE.c: move CONFIG_RESET to the start of nr_rrc_rrcsetup_fallback() - config_ue.c: drop non-SRB0 lc_ordered_list entries on RRC_SETUP_REESTAB_RESUME Closes: #128 Signed-off-by: Guido Casati --- openair2/LAYER2/NR_MAC_UE/config_ue.c | 6 ++++++ openair2/RRC/NR_UE/rrc_UE.c | 18 ++++++++---------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index f94df7f560..29a95aff65 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -1901,6 +1901,12 @@ void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t mac->state = UE_BARRED; break; case RRC_SETUP_REESTAB_RESUME: + for (int i = mac->lc_ordered_list.count; i > 0; i--) { + nr_lcordered_info_t *lc = mac->lc_ordered_list.array[i - 1]; + if (lc->rb.type == NR_LCID_SRB && lc->rb.choice.srb_id == 0) + continue; + asn_sequence_del(&mac->lc_ordered_list, i - 1, 1); + } release_mac_configuration(mac, cause); nr_ue_mac_default_configs(mac); break; diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index eab19775d7..ae3443fb41 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -2159,8 +2159,15 @@ static void nr_rrc_rrcsetup_fallback(NR_UE_RRC_INST_t *rrc) memset(rrc->kgnb, 0, sizeof(rrc->kgnb)); rrc->as_security_activated = false; + // release the RRC configuration except for the default L1 parameter values, + // default MAC Cell Group configuration and CCCH configuration + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_CONFIG_RESET; + rrc_msg.payload.config_reset.cause = RRC_SETUP_REESTAB_RESUME; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); + // release radio resources for all established RBs except SRB0, - // including release of the RLC entities, of the associated PDCP entities and of SDAP + // including release of the associated PDCP entities and of SDAP for (int i = 1; i <= MAX_DRBS_PER_UE; i++) { if (get_DRB_status(rrc, i) != RB_NOT_PRESENT) { set_DRB_status(rrc, i, RB_NOT_PRESENT); @@ -2178,15 +2185,6 @@ static void nr_rrc_rrcsetup_fallback(NR_UE_RRC_INST_t *rrc) } nr_sdap_delete_ue_entities(rrc->ue_id); - // release the RRC configuration except for the default L1 parameter values, - // default MAC Cell Group configuration and CCCH configuration - // TODO to be completed - NR_UE_MAC_reset_cause_t cause = RRC_SETUP_REESTAB_RESUME; - nr_mac_rrc_message_t rrc_msg = {0}; - rrc_msg.payload_type = NR_MAC_RRC_CONFIG_RESET; - rrc_msg.payload.config_reset.cause = cause; - nr_rrc_send_msg_to_mac(rrc, &rrc_msg); - // indicate to upper layers fallback of the RRC connection // TODO From 860232782adf92527f2f44b3b338339622ec17a6 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 23 Jun 2026 18:05:59 +0200 Subject: [PATCH 12/12] fix (NGAP/RRC): map spare RRC establishment causes to NGAP notAvailable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A UE RRCSetupRequest with establishmentCause in the spare range (10–15) could abort nr-softmodem: RRC asserted on cause >= NGAP_RRC_CAUSE_LAST, and cause 11 failed NGAP ASN.1 encode when passed through by index. NR RRC (TS 38.331) and NGAP RRCEstablishmentCause (TS 38.413 §9.3.1.111) do not share one integer namespace: spare values must not be sent as NGAP causes. Remove the RRC AssertFatal on causes. When building InitialUEMessage, map RRC indices 0–9 to the matching NGAP cause and map anything else to notAvailable, as specified for unmapped UE causes. Changes: - Drop establishment-cause range AssertFatal in rrc_gNB_send_NGAP_NAS_FIRST_REQ - Add rrc2ngap_establishment_cause() and use it for InitialUEMessage RRCEstablishmentCause - Remove redundant DevCheck on establishment_cause in ngap_gNB_handle_nas_first_req - Adopt mapping logic in rrc_gNB_send_NGAP_NAS_FIRST_REQ Closes: #127 Signed-off-by: Guido Casati --- openair2/RRC/NR/rrc_gNB_NGAP.c | 5 ++--- openair3/NGAP/ngap_gNB_nas_procedures.c | 15 +++++++++++---- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index ffa579ff7c..fe62f58243 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -222,9 +222,8 @@ void rrc_gNB_send_NGAP_NAS_FIRST_REQ(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, NR_RRC req->gNB_ue_ngap_id = UE->rrc_ue_id; // RRC Establishment Cause - /* Assume that cause is coded in the same way in RRC and NGap, just check that the value is in NGap range */ - AssertFatal(UE->establishment_cause < NGAP_RRC_CAUSE_LAST, "Establishment cause invalid (%jd/%d)!", UE->establishment_cause, NGAP_RRC_CAUSE_LAST); - req->establishment_cause = UE->establishment_cause; + req->establishment_cause = + UE->establishment_cause <= NGAP_RRC_CAUSE_MCS_PRIORITY_ACCESS ? UE->establishment_cause : NGAP_RRC_CAUSE_NOTAVAILABLE; // NAS-PDU req->nas_pdu = create_byte_array(rrcSetupComplete->dedicatedNAS_Message.size, rrcSetupComplete->dedicatedNAS_Message.buf); diff --git a/openair3/NGAP/ngap_gNB_nas_procedures.c b/openair3/NGAP/ngap_gNB_nas_procedures.c index 49fd20c91e..48211f532b 100644 --- a/openair3/NGAP/ngap_gNB_nas_procedures.c +++ b/openair3/NGAP/ngap_gNB_nas_procedures.c @@ -126,6 +126,16 @@ static ngap_gNB_amf_data_t *select_amf(ngap_gNB_instance_t *instance_p, const ng return amf; } +/** @brief Map UE EstablishmentCause (TS 38.331) to NGAP RRCEstablishmentCause (clause 9.3.1.111). + * Values 0-9 pass through, otherwise return notAvailable. */ +static NGAP_RRCEstablishmentCause_t rrc2ngap_establishment_cause(ngap_rrc_establishment_cause_t cause) +{ + if (cause <= NGAP_RRC_CAUSE_MCS_PRIORITY_ACCESS) + return cause; + /* clause 9.3.1.111: notAvailable when the UE cause does not map to any other value */ + return NGAP_RRCEstablishmentCause_notAvailable; +} + /** @brief NAS Transport Messages: Initial UE Message * forward the first received (layer 3) uplink NAS message * from the radio interface to the AMF over N2 @@ -201,16 +211,13 @@ int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEf MCC_MNC_TO_PLMNID(plmn->mcc, plmn->mnc, plmn->mnc_digit_length, &userinfo_nr_p->tAI.pLMNIdentity); } - /* Set the establishment cause according to those provided by RRC */ - DevCheck(UEfirstReq->establishment_cause < NGAP_RRC_CAUSE_LAST, UEfirstReq->establishment_cause, NGAP_RRC_CAUSE_LAST, 0); - // RRC Establishment Cause (M) { asn1cSequenceAdd(out->protocolIEs.list, NGAP_InitialUEMessage_IEs_t, ie); ie->id = NGAP_ProtocolIE_ID_id_RRCEstablishmentCause; ie->criticality = NGAP_Criticality_ignore; ie->value.present = NGAP_InitialUEMessage_IEs__value_PR_RRCEstablishmentCause; - ie->value.choice.RRCEstablishmentCause = UEfirstReq->establishment_cause; + ie->value.choice.RRCEstablishmentCause = rrc2ngap_establishment_cause(UEfirstReq->establishment_cause); } // 5G-S-TMSI (O)