Paging UE (MAC/PHY): forward PCCH to RRC and gate DLSCH on paging

Deliver MAC paging TB to RRC over ITTI, add a MAC flag
after an accepted P-RNTI DCI so the PHY IF can still invoke the DLSCH
path when ACK and HARQ indications do not line up.

Changes:
- Define NR_RRC_MAC_PCCH_DATA_IND, NRRrcMacPcchDataInd, and
  NR_RRC_MAC_PCCH_DATA_IND() for PCCH SDUs toward RRC.
- Add send_pcch_rrc() (main_ue_nr.c)
- Add pending_pcch_from_prnti to NR_UE_MAC_INST_t: set it in
  nr_ue_process_dci_dl_10() when P-RNTI DCI processing succeeds.
- In handle_dlsch(), call update_harq_status() only if the DL HARQ
  process for harq_pid is active (and not during RAR wait), and call
  nr_ue_send_sdu() when ack_nack is true or pending_pcch_from_prnti
  is set.
- In nr_ue_send_sdu() for FAPI_NR_RX_PDU_TYPE_DLSCH, treat the PDU as
  paging if DL config lists P_RNTI on a DLSCH PDU or the pending flag is
  set. On a valid successful decode, forward the TB with send_pcch_rrc()
  and clear the flag, otherwise keep the flag and skip normal MAC PDU
  parsing on that path.

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
This commit is contained in:
Guido Casati
2026-05-13 14:42:54 +02:00
parent 2b07f362e1
commit 66932ea4bc
7 changed files with 67 additions and 4 deletions

View File

@@ -40,6 +40,7 @@ MESSAGE_DEF(RRC_MAC_DRX_CONFIG_REQ, MESSAGE_PRIORITY_MED, rrc_mac_drx_config_req
MESSAGE_DEF(NR_RRC_MAC_CCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacCcchDataInd, nr_rrc_mac_ccch_data_ind)
MESSAGE_DEF(NR_RRC_MAC_BCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacBcchDataInd, nr_rrc_mac_bcch_data_ind)
MESSAGE_DEF(NR_RRC_MAC_SBCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacSBcchDataInd, nr_rrc_mac_sbcch_data_ind)
MESSAGE_DEF(NR_RRC_MAC_PCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacPcchDataInd, nr_rrc_mac_pcch_data_ind)
// Message to GNB_APP to update SIB19 satellite position information
MESSAGE_DEF(GNB_SAT_POSITION_UPDATE, MESSAGE_PRIORITY_MED, gnb_sat_position_update_t, gnb_sat_position_update)

View File

@@ -37,6 +37,7 @@
#define RRC_MAC_MCCH_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_mcch_data_req
#define RRC_MAC_MCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_mcch_data_ind
#define RRC_MAC_PCCH_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_pcch_data_req
#define NR_RRC_MAC_PCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_mac_pcch_data_ind
#define NR_RRC_MAC_RA_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_mac_ra_ind
#define NR_RRC_MAC_MSG3_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_mac_msg3_ind
@@ -184,6 +185,11 @@ typedef struct NRRrcMacCcchDataInd_s {
uint8_t sdu[CCCH_SDU_SIZE];
} NRRrcMacCcchDataInd;
typedef struct NRRrcMacPcchDataInd_s {
uint32_t sdu_size;
uint8_t sdu[PCCH_SDU_SIZE];
} NRRrcMacPcchDataInd;
typedef struct RrcMacMcchDataReq_s {
uint32_t frame;
uint32_t sdu_size;

View File

@@ -547,6 +547,7 @@ typedef struct NR_UE_MAC_INST_s {
si_schedInfo_t si_SchedInfo;
nr_ue_paging_cfg_t paging_cfg;
bool pending_pcch_from_prnti;
ssb_list_info_t ssb_list;
NR_UE_ServingCell_Info_t sc_info;

View File

@@ -25,6 +25,7 @@ NR_UE_DL_BWP_t *get_dl_bwp_structure(NR_UE_MAC_INST_t *mac, int bwp_id, bool set
NR_UE_UL_BWP_t *get_ul_bwp_structure(NR_UE_MAC_INST_t *mac, int bwp_id, bool setup);
void send_srb0_rrc(int ue_id, const uint8_t *sdu, sdu_size_t sdu_len, void *data);
void send_pcch_rrc(int ue_id, const uint8_t *sdu, sdu_size_t sdu_len, void *data);
void update_mac_ul_timers(NR_UE_MAC_INST_t *mac);
void update_mac_dl_timers(NR_UE_MAC_INST_t *mac);
NR_LC_SCHEDULING_INFO *get_scheduling_info_from_lcid(NR_UE_MAC_INST_t *mac, NR_LogicalChannelIdentity_t lcid);

View File

@@ -23,6 +23,16 @@ void send_srb0_rrc(int ue_id, const uint8_t *sdu, sdu_size_t sdu_len, void *data
itti_send_msg_to_task(TASK_RRC_NRUE, ue_id, message_p);
}
void send_pcch_rrc(int ue_id, const uint8_t *sdu, sdu_size_t sdu_len, void *data)
{
AssertFatal(sdu_len > 0 && sdu_len <= PCCH_SDU_SIZE, "invalid PCCH SDU size %d\n", sdu_len);
MessageDef *message_p = itti_alloc_new_message(TASK_MAC_UE, 0, NR_RRC_MAC_PCCH_DATA_IND);
memset(NR_RRC_MAC_PCCH_DATA_IND(message_p).sdu, 0, sdu_len);
memcpy(NR_RRC_MAC_PCCH_DATA_IND(message_p).sdu, sdu, sdu_len);
NR_RRC_MAC_PCCH_DATA_IND(message_p).sdu_size = sdu_len;
itti_send_msg_to_task(TASK_RRC_NRUE, ue_id, message_p);
}
void nr_ue_init_mac(NR_UE_MAC_INST_t *mac)
{
LOG_I(NR_MAC, "[UE%d] Initializing MAC\n", mac->ue_id);

View File

@@ -1047,6 +1047,7 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
if (rnti_type == TYPE_P_RNTI_) {
const int ret = nr_ue_process_dci_dl_10_p_rnti(mac, frame, slot, dci, dlsch_pdu, current_DL_BWP);
if (ret >= 0) {
mac->pending_pcch_from_prnti = true;
LOG_D(NR_MAC,
"[%04d.%02d][UE %d] P-RNTI DCI accepted: rb=%d+%d sym=%d+%d mcs=%d tbs=%d\n",
frame,
@@ -4388,7 +4389,43 @@ void nr_ue_send_sdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, in
// Processing MAC PDU
// it parses MAC CEs subheaders, MAC CEs, SDU subheaderds and SDUs
switch (dl_info->rx_ind->rx_indication_body[pdu_id].pdu_type) {
case FAPI_NR_RX_PDU_TYPE_DLSCH :
case FAPI_NR_RX_PDU_TYPE_DLSCH: {
fapi_nr_pdsch_pdu_t *pdsch_pdu = &dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu;
const fapi_nr_dl_config_request_t *dl_config = get_dl_config_request(mac, dl_info->slot);
bool is_paging_dlsch = false;
// A paging DLSCH is identified by the matching P-RNTI entry in the DL config.
for (int i = 0; i < dl_config->number_pdus; i++) {
const fapi_nr_dl_config_request_pdu_t *conf = &dl_config->dl_config_list[i];
if (conf->pdu_type == FAPI_NR_DL_CONFIG_TYPE_DLSCH && conf->dlsch_config_pdu.rnti == P_RNTI) {
is_paging_dlsch = true;
break;
}
}
if (is_paging_dlsch || mac->pending_pcch_from_prnti) {
const bool has_pdu = pdsch_pdu->pdu != NULL;
const bool valid_pcch = pdsch_pdu->ack_nack && has_pdu && pdsch_pdu->pdu_length > 0;
if (valid_pcch) {
LOG_D(NR_MAC,
"[%04d.%02d][UE %d] Received PCCH on P-RNTI, forwarding %d bytes to RRC\n",
dl_info->frame,
dl_info->slot,
mac->ue_id,
pdsch_pdu->pdu_length);
mac->pending_pcch_from_prnti = false;
send_pcch_rrc(mac->ue_id, pdsch_pdu->pdu, pdsch_pdu->pdu_length, NULL);
} else {
LOG_W(NR_MAC,
"[%04d.%02d][UE %d] PCCH RX fail: ack=%d len=%d\n",
dl_info->frame,
dl_info->slot,
mac->ue_id,
pdsch_pdu->ack_nack,
pdsch_pdu->pdu_length);
/* Keep pending flag for paging: paging grants may be followed by later
* successful HARQ/LDPC decodes, while this particular reception failed. */
}
break;
}
// start or restart dataInactivityTimer if any MAC entity receives a MAC SDU for DTCH logical channel,
// DCCH logical channel, or CCCH logical channel
if (mac->data_inactivity_timer)
@@ -4400,6 +4437,7 @@ void nr_ue_send_sdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, in
}
nr_ue_process_mac_pdu(mac, dl_info, pdu_id);
break;
}
case FAPI_NR_RX_PDU_TYPE_RAR :
nr_ue_process_rar(mac, dl_info, pdu_id);
break;

View File

@@ -142,12 +142,18 @@ static nr_dci_format_t handle_dci(NR_UE_MAC_INST_t *mac, frame_t frame, int slot
// Note: sdu should always be processed because data and timing advance updates are transmitted by the UE
static int8_t handle_dlsch(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, int pdu_id)
{
if (mac->ra.ra_state != nrRA_WAIT_RAR) // no HARQ for MSG2
const uint8_t harq_pid = dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.harq_pid;
const uint8_t cw_idx = dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.cw_idx;
/* DLSCH path uses DL HARQ status tied to harq_pid: P-RNTI paging does not, so update HARQ status
* only when active. */
if (mac->ra.ra_state != nrRA_WAIT_RAR && mac->dl_harq_info[harq_pid][cw_idx].active)
update_harq_status(mac,
dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.harq_pid,
dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.cw_idx,
cw_idx,
dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack);
if(dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack)
/* The flag is set when MAC accepted a P-RNTI grant: forward PCCH to RRC. */
const bool is_pending_paging = mac->pending_pcch_from_prnti;
if (dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack || is_pending_paging)
nr_ue_send_sdu(mac, dl_info, pdu_id);
return 0;