Paging UE (RRC/MAC): preserve camped idle context

Keep normal no-redirection RRCRelease on the acquired
camped-cell context while preserving the existing full
GO_TO_IDLE cell-selection path for other idle transitions.

Changes:
- Add UE_IDLE and GO_TO_IDLE_KEEP_CAMPED to represent camped
  idle without starting RA.
- Map no-redirection RRCRelease to GO_TO_IDLE_KEEP_CAMPED and
  keep SIB1 validity for that path.
- Release connected-mode MAC/BWP0 dedicated config while
  preserving common BWP0 and paging PDCCH context.
- Keep the existing full GO_TO_IDLE cleanup for idle transitions
  that must perform cell selection.

Refs:
- TS 38.331 §5.3.11
- TS 38.304 §5.2.5, §5.2.6, §7.1
- TS 38.321 §5.12

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
This commit is contained in:
Guido Casati
2026-05-28 16:13:54 +02:00
parent 57a365778e
commit f1fd36a22e
4 changed files with 71 additions and 4 deletions

View File

@@ -1864,6 +1864,7 @@ void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t
fapi_nr_synch_request_t sync_req = {.target_Nid_cell = -1, .ssb_bw_scan = true};
switch (cause) {
case GO_TO_IDLE:
/* TS 38.331 §5.3.11: enter RRC_IDLE and perform cell selection per TS 38.304. */
reset_ra(mac, true);
nr_ue_init_mac(mac);
release_mac_configuration(mac, cause);
@@ -1871,6 +1872,21 @@ void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t
// new sync but no target cell id -> -1
nr_ue_send_synch_request(mac, module_id, 0, &sync_req);
break;
case GO_TO_IDLE_KEEP_CAMPED:
/* Normal no-redirection RRCRelease: keep the selected camped cell context for TS 38.304 §5.2.5/§7.1
* paging, while releasing connected-mode MAC state. RA stays idle until paging/NAS triggers access. */
// Stop any in-progress RA and discard PRACH resources
reset_ra(mac, true);
// Apply TS 38.321 §5.12 MAC reset (no PHY sync reinit)
reset_mac_inst(mac);
// Release dedicated MAC config (keep SIB1/common BWP0/paging PDCCH for the camped cell)
release_mac_configuration(mac, cause);
// Restore default MAC Cell Group timers/config (after the reset)
nr_ue_mac_default_configs(mac);
mac->ra.ra_state = nrRA_UE_IDLE;
mac->ra.RA_active = false;
mac->state = UE_IDLE;
break;
case DETACH:
LOG_A(NR_MAC, "Received detach indication\n");
reset_ra(mac, true);

View File

@@ -131,6 +131,7 @@
UE_STATE(UE_NOT_SYNC_RECONF) \
UE_STATE(UE_BARRED) \
UE_STATE(UE_RECEIVING_SIB) \
UE_STATE(UE_IDLE) \
UE_STATE(UE_PERFORMING_RA) \
UE_STATE(UE_CONNECTED) \
UE_STATE(UE_DETACHING)
@@ -176,6 +177,7 @@ typedef struct {
typedef enum {
GO_TO_IDLE,
GO_TO_IDLE_KEEP_CAMPED,
DETACH,
RE_ESTABLISHMENT,
RRC_SETUP_REESTAB_RESUME,

View File

@@ -226,11 +226,51 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac)
// TODO beam failure procedure not implemented
}
static void release_dedicated_bwp0_config(NR_UE_MAC_INST_t *mac)
{
if (mac->dl_BWPs.count > 0) {
NR_UE_DL_BWP_t *bwp = mac->dl_BWPs.array[0];
NR_BWP_PDCCH_t *pdcch = &mac->config_BWP_PDCCH[0];
for (int i = pdcch->list_Coreset.count; i > 0; i--)
asn_sequence_del(&pdcch->list_Coreset, i - 1, 1);
for (int i = pdcch->list_SS.count; i > 0; i--)
asn_sequence_del(&pdcch->list_SS, i - 1, 1);
asn1cFreeStruc(asn_DEF_NR_PDSCH_Config, bwp->pdsch_Config);
mac->current_DL_BWP = bwp;
mac->sc_info.initial_dl_BWPSize = bwp->BWPSize;
mac->sc_info.initial_dl_BWPStart = bwp->BWPStart;
}
if (mac->ul_BWPs.count > 0) {
NR_UE_UL_BWP_t *ubwp = mac->ul_BWPs.array[0];
asn1cFreeStruc(asn_DEF_NR_PUCCH_Config, ubwp->pucch_Config);
asn1cFreeStruc(asn_DEF_NR_SRS_Config, ubwp->srs_Config);
asn1cFreeStruc(asn_DEF_NR_PUSCH_Config, ubwp->pusch_Config);
mac->current_UL_BWP = ubwp;
mac->sc_info.initial_ul_BWPSize = ubwp->BWPSize;
mac->sc_info.initial_ul_BWPStart = ubwp->BWPStart;
}
}
void release_mac_configuration(NR_UE_MAC_INST_t *mac, NR_UE_MAC_reset_cause_t cause)
{
NR_UE_ServingCell_Info_t *sc = &mac->sc_info;
// if cause is Re-establishment, release spCellConfig only
/* Partial release for normal no-redirection RRCRelease: RRC keeps the current cell selected for idle camping
* (TS 38.304 §5.2.5), so keep SIB1/common BWP0/paging PDCCH and drop only connected-mode MAC config. */
if (cause == GO_TO_IDLE_KEEP_CAMPED) {
for (int i = mac->lc_ordered_list.count; i > 0; i--)
asn_sequence_del(&mac->lc_ordered_list, i - 1, 1);
for (int i = mac->dl_BWPs.count - 1; i >= 1; i--)
release_dl_BWP(mac, i);
for (int i = mac->ul_BWPs.count - 1; i >= 1; i--)
release_ul_BWP(mac, i);
release_dedicated_bwp0_config(mac);
return;
}
if (cause == GO_TO_IDLE) {
/* Full idle/cell-selection path: release stored common cell context before selecting/syncing again
* (TS 38.331 §5.3.11, TS 38.304 §5.2.6). */
asn1cFreeStruc(asn_DEF_NR_MIB, mac->mib);
asn1cFreeStruc(asn_DEF_NR_SearchSpace, mac->search_space_zero);
asn1cFreeStruc(asn_DEF_NR_ControlResourceSet, mac->coreset0);

View File

@@ -3510,12 +3510,12 @@ void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc,
NR_RRCRelease_t *RRCRelease)
{
NR_UE_Timers_Constants_t *tac = &rrc->timers_and_constants;
struct NR_RRCRelease_IEs *rrcReleaseIEs = RRCRelease ? RRCRelease->criticalExtensions.choice.rrcRelease : NULL;
// if going to RRC_IDLE was triggered by reception
// of the RRCRelease message including a waitTime
NR_RejectWaitTime_t *waitTime = NULL;
if (RRCRelease) {
struct NR_RRCRelease_IEs *rrcReleaseIEs = RRCRelease->criticalExtensions.choice.rrcRelease;
if(rrcReleaseIEs) {
waitTime = rrcReleaseIEs->nonCriticalExtension ?
rrcReleaseIEs->nonCriticalExtension->waitTime : NULL;
@@ -3590,12 +3590,17 @@ void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc,
nr_rrc_release_rlc_entity(rrc, i);
}
/* TS 38.331 §5.3.11 enters RRC_IDLE with cell selection per TS 38.304 §5.2.6.
* With a normal no-redirection RRCRelease, preserve the already-acquired camped-cell context for paging. */
const bool preserve_camped_context = rrc->nrRrcState != RRC_STATE_DETACH_NR && release_cause == OTHER && RRCRelease
&& (!rrcReleaseIEs || !rrcReleaseIEs->redirectedCarrierInfo);
for (int i = 0; i < NB_CNX_UE; i++) {
rrcPerNB_t *nb = &rrc->perNB[i];
NR_UE_RRC_SI_INFO *SI_info = &nb->SInfo;
init_SI_timers(SI_info);
SI_info->sib_pending = false;
SI_info->sib1_validity = false;
if (!preserve_camped_context)
SI_info->sib1_validity = false;
SI_info->sib2_validity = false;
SI_info->sib3_validity = false;
SI_info->sib4_validity = false;
@@ -3631,7 +3636,11 @@ void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc,
}
// reset MAC
NR_UE_MAC_reset_cause_t cause = (rrc->nrRrcState == RRC_STATE_DETACH_NR) ? DETACH : GO_TO_IDLE;
NR_UE_MAC_reset_cause_t cause = GO_TO_IDLE;
if (rrc->nrRrcState == RRC_STATE_DETACH_NR)
cause = DETACH;
else if (preserve_camped_context)
cause = GO_TO_IDLE_KEEP_CAMPED;
nr_mac_rrc_message_t rrc_msg = {0};
rrc_msg.payload_type = NR_MAC_RRC_CONFIG_RESET;
rrc_msg.payload.config_reset.cause = cause;