Paging (F1AP/MAC): queue paging records in MAC from F1AP paging

When the core pages an idle UE, the DU queues paging records unti
MAC can send it on PCCH at the right PF/PO. This commit moves that
buffering into gNB MAC and connects the existing F1AP Paging entry points.

The CN UE paging is therefore routed from F1AP inputs into a MAC-managed
PCCH queue. The unused RRC PCCH generator stub is dropped. This makes paging
delivery path explicit in MAC for later PF/PO scheduling.

Changes:
- f1ap_du_paging.c: decode F1AP Paging and call f1_paging()
- mac_rrc_dl_handler.c: add f1_paging()-  CN UE identity only, reject RAN UE,
  call nr_mac_pcch_enqueue
- gNB_scheduler_pcch.c (new): queue init/free/enqueue, store identity only
  (nr_mac_pcch_record_t: ue_id, fiveg_s_tmsi) in spsc_q
- nr_mac_gNB.h: add nr_mac_pcch_record_t and pcch_queue on NR_COMMON_channels_t
- mac_rrc_dl_direct.c: f1_paging_transfer_direct(), call f1_paging()

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
This commit is contained in:
Guido Casati
2026-01-23 11:51:53 +01:00
parent 29d31cde8e
commit 5fae4b3c29
11 changed files with 130 additions and 18 deletions

View File

@@ -1207,6 +1207,7 @@ set (MAC_NR_SRC
${NR_GNB_MAC_DIR}/gNB_scheduler_uci.c
${NR_GNB_MAC_DIR}/gNB_scheduler_srs.c
${NR_GNB_MAC_DIR}/gNB_scheduler_RA.c
${NR_GNB_MAC_DIR}/gNB_scheduler_pcch.c
${NR_GNB_MAC_DIR}/mac_rrc_dl_handler.c
${NR_GNB_MAC_DIR}/mac_rrc_ul_direct.c
${NR_GNB_MAC_DIR}/mac_rrc_ul_f1ap.c

View File

@@ -8,18 +8,30 @@
#include "conversions.h"
#include "oai_asn1.h"
#include "openair2/RRC/LTE/rrc_proto.h"
#include "common/utils/LOG/log.h"
#include "openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h"
#include "F1AP_F1AP-PDU.h"
/* @brief Handle F1AP Paging message at DU */
/** @brief Handle F1AP Paging message at DU.
*
* Decodes the F1AP Paging PDU and, for CN UE identity (5G-S-TMSI), builds the
* NR RRC Paging message (PCCH, TS 38.331 §8.2) and hands it to MAC for queuing,
* together with the UE_ID (ue_identity_index_value mod 1024) for PF/PO (TS 38.304 §7).
* MAC will pull the PDU at paging occasion and schedule it.
* RAN UE paging identity is not supported.
*
* @param instance DU instance (used as module_id for MAC).
* @param assoc_id SCTP association (unused).
* @param stream Stream (unused).
* @param pdu F1AP Paging PDU to decode and process.
* @return 0 on success, -1 on decode failure. */
int DU_handle_Paging(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu)
{
f1ap_paging_t decoded = {0};
DevAssert(pdu);
(void)instance;
(void)assoc_id;
(void)stream;
UNUSED(assoc_id);
UNUSED(stream);
if (LOG_DEBUGFLAG(DEBUG_ASN1)) {
xer_fprint(stdout, &asn_DEF_F1AP_F1AP_PDU, pdu);
@@ -30,10 +42,10 @@ int DU_handle_Paging(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream
return -1;
}
/** @todo Build PCCH-Message (Paging) at DU per TS 38.331 §5.3.2; apply
* RRC padding per §8.5; deliver as RLC SDU per §8.2. For each
* cell in Paging Cell List that belongs to this DU, queue for MAC; MAC schedules
* at PF/PO per TS 38.304 §7. */
LOG_I(F1AP, "[DU %ld] Decoded F1AP Paging: identity_type=%d, n_cells=%u\n", instance, decoded.identity_type, decoded.n_cells);
/* Build PCCH from F1AP Paging and enqueue it in MAC (TS 38.331 §8.2). */
f1_paging(&decoded);
free_f1ap_paging(&decoded);
return 0;

View File

@@ -5,6 +5,10 @@
#ifndef F1AP_DU_PAGING_H_
#define F1AP_DU_PAGING_H_
#include <stdint.h>
#include "f1ap_common.h"
#include "f1ap_messages_types.h"
/* Paging (gNB-CU initiated) */
int DU_handle_Paging(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu);

View File

@@ -0,0 +1,64 @@
/*
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
*/
/*!
* \brief gNB PCCH (paging) scheduling procedures
*/
#include <stdbool.h>
#include <stdint.h>
#include "assertions.h"
#include "NR_MAC_gNB/nr_mac_gNB.h"
#include "NR_MAC_gNB/mac_proto.h"
#include "common/utils/LOG/log.h"
#include "common/utils/ds/byte_array.h"
#include "openair2/RRC/NR/MESSAGES/asn1_msg.h"
void nr_mac_pcch_queue_free(NR_COMMON_channels_t *cc)
{
DevAssert(cc);
spsc_q_free(&cc->pcch_queue);
}
void nr_mac_pcch_queue_init(NR_COMMON_channels_t *cc)
{
DevAssert(cc);
const bool ok = spsc_q_alloc(&cc->pcch_queue, NR_PCCH_MAX_PAGING_RECORDS, sizeof(nr_mac_pcch_record_t));
AssertFatal(ok, "failed to allocate PCCH queue\n");
}
static void nr_mac_pcch_queue_push(spsc_q_t *q, module_id_t module_id, const nr_mac_pcch_record_t *item)
{
DevAssert(q);
DevAssert(item);
if (!spsc_q_put(q, item, sizeof(*item)))
LOG_W(NR_MAC, "[gNB %d] PCCH queue full, dropping paging record\n", module_id);
}
/** @brief Enqueue a pending CN paging record for transmission at the UE's PO.
*
* Stores identity only: PCCH-Message (Paging, TS 38.331 §6.2.2) encoding is deferred
* until the UE's paging occasion (TS 38.304 §7.1).
*
* @param fiveg_s_tmsi ng-5G-S-TMSI from NGAP/F1AP Paging (TS 38.413 / TS 38.473).
* @param ue_id UE identity index value mod 1024 (= UE_ID for PF/PO, TS 38.304 §7.1). */
void nr_mac_pcch_enqueue(module_id_t module_id, uint64_t fiveg_s_tmsi, uint16_t ue_id)
{
gNB_MAC_INST *mac = RC.nrmac[module_id];
DevAssert(mac);
const int CC_id = 0;
NR_COMMON_channels_t *cc = &mac->common_channels[CC_id];
const nr_mac_pcch_record_t item = {
.ue_id = ue_id % 1024,
.fiveg_s_tmsi = fiveg_s_tmsi & ((1ULL << 48) - 1),
};
NR_SCHED_LOCK(&mac->sched_lock);
nr_mac_pcch_queue_push(&cc->pcch_queue, module_id, &item);
NR_SCHED_UNLOCK(&mac->sched_lock);
LOG_I(NR_MAC, "[gNB %d] PCCH record enqueued UE_ID=%u (5G-S-TMSI=0x%012lx)\n", module_id, item.ue_id, fiveg_s_tmsi);
}

View File

@@ -89,7 +89,11 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, slot_t slot, nfapi_
/* \brief default UL preprocessor */
void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_pusch);
/////// Random Access MAC-PHY interface functions and primitives ///////
void nr_mac_pcch_queue_init(NR_COMMON_channels_t *cc);
void nr_mac_pcch_queue_free(NR_COMMON_channels_t *cc);
void nr_mac_pcch_enqueue(module_id_t module_id, uint64_t fiveg_s_tmsi, uint16_t ue_id);
////// Random Access MAC-PHY interface functions and primitives ///////
void nr_schedule_RA(module_id_t module_idP,
frame_t frameP,

View File

@@ -1107,3 +1107,22 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc)
/* the DU ue id is the RNTI */
nr_rlc_srb_recv_sdu(dl_rrc->gNB_DU_ue_id, dl_rrc->srb_id, dl_rrc->rrc_container, dl_rrc->rrc_container_length);
}
/** @brief For CN-initiated Paging, enqueue one MAC record per F1AP/NGAP Paging.
* TS 38.413 §8.5.1.2: each NGAP PAGING shall result in one radio page per cell.
* One received indication is mapped to one DU queue entry. */
void f1_paging(const f1ap_paging_t *paging)
{
DevAssert(paging);
if (paging->identity_type != F1AP_PAGING_IDENTITY_CN_UE) {
LOG_W(MAC, "RAN UE paging identity not supported\n");
return;
}
const module_id_t module_id = 0;
const uint64_t fiveg_s_tmsi = paging->identity.cn_ue_paging_identity;
const uint16_t ue_id = paging->ue_identity_index_value % 1024;
LOG_I(MAC, "Paging transfer: ue_identity_index=%u, 5G-S-TMSI=0x%012lu\n", paging->ue_identity_index_value, fiveg_s_tmsi);
nr_mac_pcch_enqueue(module_id, fiveg_s_tmsi, ue_id);
}

View File

@@ -22,5 +22,6 @@ void ue_context_modification_refuse(const f1ap_ue_context_modif_refuse_t *refuse
void ue_context_release_command(const f1ap_ue_context_rel_cmd_t *cmd);
void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc);
void f1_paging(const f1ap_paging_t *paging);
#endif /* MAC_RRC_DL_HANDLER_H */

View File

@@ -275,7 +275,8 @@ void mac_top_init_gNB(ngran_node_t node_type,
LOG_D(MAC,"[MAIN] ALLOCATE %zu Bytes for %d gNB_MAC_INST @ %p\n",sizeof(gNB_MAC_INST), RC.nb_nr_macrlc_inst, RC.mac);
bzero(RC.nrmac[i], sizeof(gNB_MAC_INST));
nr_mac_pcch_queue_init(&RC.nrmac[i]->common_channels[0]);
RC.nrmac[i]->Mod_id = i;
RC.nrmac[i]->tag = (NR_TAG_t*)malloc(sizeof(NR_TAG_t));
@@ -352,6 +353,7 @@ void mac_top_init_gNB(ngran_node_t node_type,
void mac_top_destroy_gNB(gNB_MAC_INST *mac)
{
NR_COMMON_channels_t *cc = &mac->common_channels[0];
nr_mac_pcch_queue_free(cc);
ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_Message, cc->mib);
ASN_STRUCT_FREE(asn_DEF_NR_BCCH_DL_SCH_Message, cc->sib1);
ASN_STRUCT_FREE(asn_DEF_NR_ServingCellConfigCommon, cc->ServingCellConfigCommon);

View File

@@ -20,6 +20,7 @@
#include "common/utils/ds/seq_arr.h"
#include "common/utils/nr/nr_common.h"
#include "common/utils/ds/byte_array.h"
#include "common/utils/ds/spsc_q.h"
#include "openair2/LAYER2/nr_rlc/nr_rlc_configuration.h"
#define NR_SCHED_LOCK(lock) \
@@ -105,6 +106,14 @@ typedef struct {
bool new_beam;
} NR_beam_alloc_t;
/** Pending CN paging record */
typedef struct {
/// UE_ID for PF/PO computation (TS 38.304 §7.1)
uint16_t ue_id;
/// ng-5G-S-TMSI (48 bits)
uint64_t fiveg_s_tmsi;
} nr_mac_pcch_record_t;
typedef struct nr_pdsch_AntennaPorts_t {
int N1;
int N2;
@@ -329,6 +338,8 @@ typedef struct {
/// Max prach length in slots
int prach_len;
nr_prach_info_t prach_info;
/// PCCH SDU queue (one spsc_q per common-channel context)
spsc_q_t pcch_queue;
} NR_COMMON_channels_t;
// SP ZP CSI-RS Resource Set Activation/Deactivation MAC CE

View File

@@ -81,11 +81,7 @@ static void dl_rrc_message_transfer_direct(sctp_assoc_t assoc_id, const f1ap_dl_
static void f1_paging_transfer_direct(sctp_assoc_t assoc_id, const f1ap_paging_t *paging)
{
AssertFatal(assoc_id == -1, "illegal assoc_id %d\n", assoc_id);
/** @todo Build PCCH-Message (Paging) at DU per TS 38.331 §5.3.2; apply
* RRC padding per §8.5; deliver as RLC SDU per §8.2. For each
* cell in Paging Cell List that belongs to this DU, queue for MAC;
* MAC schedules at PF/PO per TS 38.304 §7. */
(void)paging;
f1_paging(paging);
}
void mac_rrc_dl_direct_init(nr_mac_rrc_dl_if_t *mac_rrc)

View File

@@ -72,8 +72,6 @@ void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_contex
e1ap_bearer_setup_resp_t *e1ap_resp);
void trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, uint64_t ueAggMaxBitRateDownlink);
int rrc_gNB_generate_pcch_msg(sctp_assoc_t assoc_id, const NR_SIB1_t *sib, uint32_t tmsi, uint8_t paging_drx);
/** @}*/
/* UE Management Procedures */