Paging (RRC/ASN): refactor do_NR_Paging and extend UE identity support

Replace the old buffer-based do_NR_Paging API with a params struct and
byte_array_t return; add support for fullI-RNTI and optional accessType/
pagingCause. Encoding uses uper_encode_to_new_buffer, callers own and
free the returned buffer.

Changes:
- asn1_msg.h:
  - Add nr_paging_params_t (ue_identity_type, union ue_identity union
    { m_tmsi or full_i_rnti }, access_type, paging_cause),
  - Add NR_PAGING_FULL_I_RNTI_SIZE define.
- asn1_msg.c:
  - Implement do_NR_Paging with nr_paging_params_t.
  - Support ng-5G-S-TMSI (48-bit, M-TMSI in bytes 2–5)
    and fullI-RNTI (40-bit, 5 bytes).
  - Set optional accessType (non3GPP) and optional nonCriticalExtension
    (pagingRecordList-v1700 with pagingCause-r17).
  - Use asn1cCalloc for ASN.1 allocations and encode via
    uper_encode_to_new_buffer. On failure free buffer and return empty
    byte_array_t.
- rrc_gNB.c: disable do_NR_Paging call in rrc_gNB_generate_pcch_msg
  with #if 0 (will be removed in a descendant commit, no need to update
  call site yet).
- test_asn1_msg.cpp: update caller in asn1 tests (minimal change, test
  will be updated in a later commit)
- common/platform_constants.h: add NR_PCCH_MAX_PAGING_RECORDS

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
This commit is contained in:
Guido Casati
2026-01-21 12:46:27 +01:00
parent 854090632f
commit dfb0c61c62
5 changed files with 111 additions and 30 deletions

View File

@@ -71,6 +71,9 @@
// SDAP
#define MAX_QOS_FLOWS 64
/** Maximum number of PagingRecords in one PCCH Paging message (TS 38.331) */
#define NR_PCCH_MAX_PAGING_RECORDS 32
// SDAP/5G NAS NOS1
#define DEFAULT_NOS1_PDU_ID 10

View File

@@ -61,6 +61,7 @@
#include "NR_RRCReestablishmentRequest.h"
#include "NR_PCCH-Message.h"
#include "NR_PagingRecord.h"
#include "NR_Paging-v1700-IEs.h"
#include "NR_UE-CapabilityRequestFilterNR.h"
#include "NR_HandoverPreparationInformation.h"
#include "NR_HandoverPreparationInformation-IEs.h"
@@ -1517,44 +1518,90 @@ void free_MeasConfig(NR_MeasConfig_t *mc)
ASN_STRUCT_FREE(asn_DEF_NR_MeasConfig, mc);
}
int do_NR_Paging(uint8_t Mod_id, uint8_t *buffer, uint32_t tmsi)
/** @brief Generate NR RRC Paging message (TS 38.331 §5.3.2)
* Creates a PCCH message with a single PagingRecord containing ng-5G-S-TMSI
* for CN-initiated paging of RRC_IDLE UEs. */
byte_array_t do_NR_Paging(int count, const nr_paging_params_t *params)
{
LOG_D(NR_RRC, "[gNB %d] do_NR_Paging start\n", Mod_id);
DevAssert(count > 0 && params != NULL);
DevAssert(count <= NR_PCCH_MAX_PAGING_RECORDS);
LOG_D(NR_RRC, "Generate NR RRC Paging message (count=%d, ue_identity_type=%d)\n", count, params->ue_identity_type);
byte_array_t msg = {.buf = NULL, .len = 0};
NR_PCCH_Message_t pcch_msg = {0};
pcch_msg.message.present = NR_PCCH_MessageType_PR_c1;
pcch_msg.message.present = NR_PCCH_MessageType_PR_c1;
asn1cCalloc(pcch_msg.message.choice.c1, c1);
c1->present = NR_PCCH_MessageType__c1_PR_paging;
c1->choice.paging = CALLOC(1, sizeof(NR_Paging_t));
c1->choice.paging->pagingRecordList = CALLOC(
1, sizeof(*pcch_msg.message.choice.c1->choice.paging->pagingRecordList));
c1->choice.paging->nonCriticalExtension = NULL;
asn_set_empty(&c1->choice.paging->pagingRecordList->list);
c1->choice.paging->pagingRecordList->list.count = 0;
asn1cCalloc(c1->choice.paging, paging);
asn1cSequenceAdd(c1->choice.paging->pagingRecordList->list, NR_PagingRecord_t,
paging_record_p);
/* convert ue_paging_identity_t to PagingUE_Identity_t */
paging_record_p->ue_Identity.present = NR_PagingUE_Identity_PR_ng_5G_S_TMSI;
// set ng_5G_S_TMSI
INT32_TO_BIT_STRING(tmsi, &paging_record_p->ue_Identity.choice.ng_5G_S_TMSI);
/* pagingRecordList (Optional)
* Network may address multiple UEs by including one PagingRecord per UE.
* If pagingRecordList-v1700 is included, it has same entries in same order. */
asn1cCalloc(paging->pagingRecordList, pagingRecordList);
for (int i = 0; i < count; i++) {
asn1cSequenceAdd(pagingRecordList->list, NR_PagingRecord_t, paging_record_p);
const nr_paging_params_t *p = &params[i];
/* add to list */
LOG_D(NR_RRC, "[gNB %d] do_Paging paging_record: PagingRecordList.count %d\n",
Mod_id, c1->choice.paging->pagingRecordList->list.count);
asn_enc_rval_t enc_rval = uper_encode_to_buffer(
&asn_DEF_NR_PCCH_Message, NULL, (void *)&pcch_msg, buffer, NR_RRC_BUF_SIZE);
/* PagingUE-Identity (choice) { ng-5G-S-TMSI | fullI-RNTI } */
paging_record_p->ue_Identity.present = p->ue_identity_type;
if (p->ue_identity_type == NR_PagingUE_Identity_PR_ng_5G_S_TMSI) {
/* ng-5G-S-TMSI: BIT STRING (SIZE(48)) - AMF Set ID, AMF Pointer, 5G-TMSI (TS 38.331 / 23.003) */
BIT_STRING_t *tmsi_bs = &paging_record_p->ue_Identity.choice.ng_5G_S_TMSI;
FIVEG_S_TMSI_TO_BIT_STRING(p->ue_identity.fiveg_s_tmsi, tmsi_bs);
} else {
/* fullI-RNTI: I-RNTI-Value BIT STRING (SIZE(40)) for RAN-initiated paging (RRC_INACTIVE). */
BIT_STRING_t *i_rnti_bs = &paging_record_p->ue_Identity.choice.fullI_RNTI;
i_rnti_bs->size = NR_PAGING_FULL_I_RNTI_SIZE;
i_rnti_bs->buf = calloc_or_fail(NR_PAGING_FULL_I_RNTI_SIZE, sizeof(uint8_t));
i_rnti_bs->bits_unused = 0;
memcpy(i_rnti_bs->buf, p->ue_identity.full_i_rnti, NR_PAGING_FULL_I_RNTI_SIZE);
}
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
/* accessType (optional): indicates whether paging is due to PDU sessions from non-3GPP access */
if (p->access_type) {
paging_record_p->accessType = calloc_or_fail(1, sizeof(long));
*paging_record_p->accessType = NR_PagingRecord__accessType_non3GPP;
}
}
/** If pagingRecordList-v1700 is included: same count/order as pagingRecordList (38.331).
* pagingCause-r17 present means IMS voice, absent in v1700 entry means non-voice (UE-dependent). */
int i = 0;
while (i < count && params[i].paging_cause == NULL)
i++;
if (i < count) {
asn1cCalloc(paging->nonCriticalExtension, ext_v1700);
ext_v1700->pagingGroupList_r17 = NULL;
ext_v1700->nonCriticalExtension = NULL;
asn1cCalloc(ext_v1700->pagingRecordList_v1700, list_v1700);
for (i = 0; i < count; i++) {
asn1cSequenceAdd(list_v1700->list, NR_PagingRecord_v1700_t, rec_v1700);
if (params[i].paging_cause != NULL) {
rec_v1700->pagingCause_r17 = calloc_or_fail(1, sizeof(long));
*rec_v1700->pagingCause_r17 = NR_PagingRecord_v1700__pagingCause_r17_voice;
}
}
}
LOG_D(NR_RRC, "Paging: PagingRecordList.count=%d\n", pagingRecordList->list.count);
if (LOG_DEBUGFLAG(DEBUG_ASN1)) {
xer_fprint(stdout, &asn_DEF_NR_PCCH_Message, (void *)&pcch_msg);
}
int val = uper_encode_to_new_buffer(&asn_DEF_NR_PCCH_Message, NULL, &pcch_msg, (void **)&msg.buf);
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NR_PCCH_Message, &pcch_msg);
if(enc_rval.encoded == -1) {
LOG_I(NR_RRC, "[gNB AssertFatal]ASN1 message encoding failed (%s, %lu)!\n",
enc_rval.failed_type->name, enc_rval.encoded);
return -1;
if (val <= 0) {
LOG_E(NR_RRC, "Failed to encode NR RRC Paging message\n");
free_byte_array(msg);
return msg;
}
return((enc_rval.encoded+7)/8);
msg.len = val;
LOG_I(NR_RRC, "Encoded NR RRC Paging message (%zu bytes)\n", msg.len);
return msg;
}
/* \brief generate HandoverPreparationInformation to be sent to the DU for

View File

@@ -11,6 +11,7 @@
#include <common/utils/assertions.h>
#include "common/platform_constants.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "NR_ARFCN-ValueNR.h"
@@ -36,6 +37,7 @@
#include "NR_SIB2.h"
#include "NR_SIB3.h"
#include "NR_SIB4.h"
#include "NR_PagingUE-Identity.h"
#include "ds/seq_arr.h"
#include "ds/byte_array.h"
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_configuration.h"
@@ -152,7 +154,25 @@ NR_MeasConfig_t *get_MeasConfig(const NR_MeasTiming_t *mt,
seq_arr_t *neigh_seq,
int *neigh_a3_id);
void free_MeasConfig(NR_MeasConfig_t *mc);
int do_NR_Paging(uint8_t Mod_id, uint8_t *buffer, uint32_t tmsi);
#define NR_PAGING_FULL_I_RNTI_SIZE 5 // 40 bits
/** Paging parameters for do_NR_Paging */
typedef struct {
/// UE Identity type (ng-5G-S-TMSI or fullI-RNTI)
NR_PagingUE_Identity_PR ue_identity_type;
union {
/// Full 48-bit 5G-S-TMSI (TS 23.003): AMF Set ID + AMF Pointer + 5G-TMSI
uint64_t fiveg_s_tmsi;
uint8_t full_i_rnti[NR_PAGING_FULL_I_RNTI_SIZE];
} ue_identity;
/// true = accessType non3GPP
bool access_type;
/// pagingCause voice
int *paging_cause;
} nr_paging_params_t;
byte_array_t do_NR_Paging(int count, const nr_paging_params_t *params);
byte_array_t get_HandoverPreparationInformation(nr_rrc_reconfig_param_t *params);
byte_array_t get_HandoverCommandMessage(nr_rrc_reconfig_param_t *params);

View File

@@ -113,8 +113,18 @@ TEST(nr_asn1, rrc_reestablishment)
TEST(nr_asn1, paging)
{
unsigned char buf[1000];
EXPECT_GT(do_NR_Paging(0, buf, 0), 0);
nr_paging_params_t params = {};
params.ue_identity_type = NR_PagingUE_Identity_PR_ng_5G_S_TMSI;
params.ue_identity.m_tmsi = 0;
params.access_type = false;
params.paging_cause = NULL;
byte_array_t msg = do_NR_Paging(&params);
EXPECT_GT(msg.len, 0);
EXPECT_NE(msg.buf, nullptr);
free_byte_array(msg);
}
void free_RRCReconfiguration_params(nr_rrc_reconfig_param_t params)

View File

@@ -3831,15 +3831,16 @@ int rrc_gNB_generate_pcch_msg(sctp_assoc_t assoc_id, const NR_SIB1_t *sib1, uint
(void) Ns; /* not used, suppress warning */
(void) pfoffset; /* not used, suppress warning */
#if 0
/* Create message for PDCP (DLInformationTransfer_t) */
int length = do_NR_Paging(instance, buffer, tmsi);
if (length == -1) {
LOG_I(NR_RRC, "do_Paging error\n");
return -1;
}
// TODO, send message to pdcp
(void) assoc_id;
#endif
return 0;
}