Add PDCP API getter and setter for PDCP count values in PDCP entity

* Introduced nr_pdcp_count_update() to apply COUNT values to the PDCP entity:
  - Computes tx_next, rx_next, and rx_deliv from HFN+SN
  - Handles both 12-bit and 18-bit SN modes with dynamic bitmask
* Introduced nr_pdcp_get_drb_count_values() to extract PDCP COUNT values from entity:
  - Used for building UL RAN Status Transfer on source CU side
This commit is contained in:
Guido Casati
2025-09-18 11:34:31 +02:00
parent e527b99de1
commit e96d7f9576
4 changed files with 168 additions and 1 deletions
+94
View File
@@ -601,6 +601,94 @@ static void nr_pdcp_entity_get_stats(nr_pdcp_entity_t *entity,
*out = entity->stats;
}
/** @note: this function applies to the gNB only */
static nr_pdcp_count_t nr_pdcp_entity_get_count_dl(nr_pdcp_entity_t *entity)
{
nr_pdcp_count_t count = {0};
const int sn_bits = entity->sn_size;
const uint32_t sn_mask = entity->sn_max;
count.hfn = entity->rx_deliv >> sn_bits;
count.sn = entity->rx_deliv & sn_mask;
return count;
}
/** @note: this function applies to the gNB only */
static nr_pdcp_count_t nr_pdcp_entity_get_count_ul(nr_pdcp_entity_t *entity)
{
nr_pdcp_count_t count = {0};
const int sn_bits = entity->sn_size;
const uint32_t sn_mask = entity->sn_max;
count.hfn = entity->tx_next >> sn_bits;
count.sn = entity->tx_next & sn_mask;
return count;
}
/** @note: this function applies to the gNB only */
static void nr_pdcp_entity_set_count_dl(nr_pdcp_entity_t *entity, nr_pdcp_count_t pdcp_count, int sn_size)
{
// SN length in bits
const uint32_t sn_mask = (1 << sn_size) - 1;
// Compose COUNT values for tx_next (DL) and rx_next (UL)
uint32_t count = (pdcp_count.hfn << sn_size) | (pdcp_count.sn & sn_mask);
// Apply the COUNT values
entity->rx_next = count + 1;
entity->rx_deliv = count;
LOG_I(PDCP,
"DRB %d: Applied PDCP Count\n"
" DL COUNT - SN: %d HFN: %d (COUNT=%u)\n"
" SN length: %s\n"
" PDCP entity state after update:\n"
" rx_next = %u\n"
" rx_deliv = %u\n"
" sn_size = %d\n"
" sn_max = %d\n"
" window = %d\n",
entity->rb_id,
pdcp_count.sn,
pdcp_count.hfn,
count,
sn_size == LONG_SN_SIZE ? "18-bit" : "12-bit",
entity->rx_next,
entity->rx_deliv,
entity->sn_size,
entity->sn_max,
entity->window_size);
}
/** @note: this function applies to the gNB only */
static void nr_pdcp_entity_set_count_ul(nr_pdcp_entity_t *entity, nr_pdcp_count_t pdcp_count, int sn_size)
{
// SN length in bits
const uint32_t sn_mask = (1 << sn_size) - 1;
// Compose COUNT values for tx_next (DL) and rx_next (UL)
uint32_t count = (pdcp_count.hfn << sn_size) | (pdcp_count.sn & sn_mask);
// Apply the COUNT values
entity->tx_next = count;
LOG_I(PDCP,
"DRB %d: Applied PDCP Count\n"
" UL COUNT - SN: %d HFN: %d (COUNT=%u)\n"
" SN length: %s\n"
" PDCP entity state after update:\n"
" tx_next = %u\n"
" sn_size = %d\n"
" sn_max = %d\n"
" window = %d\n",
entity->rb_id,
pdcp_count.sn,
pdcp_count.hfn,
count,
sn_size == LONG_SN_SIZE ? "18-bit" : "12-bit",
entity->tx_next,
entity->sn_size,
entity->sn_max,
entity->window_size);
}
nr_pdcp_entity_t *new_nr_pdcp_entity(
nr_pdcp_entity_type_t type,
@@ -675,5 +763,11 @@ nr_pdcp_entity_t *new_nr_pdcp_entity(
nr_pdcp_entity_set_security(ret, security_parameters);
/* PDCP Count API */
ret->get_pdcp_count_dl = nr_pdcp_entity_get_count_dl;
ret->get_pdcp_count_ul = nr_pdcp_entity_get_count_ul;
ret->set_pdcp_count_dl = nr_pdcp_entity_set_count_dl;
ret->set_pdcp_count_ul = nr_pdcp_entity_set_count_ul;
return ret;
}
+12 -1
View File
@@ -55,6 +55,11 @@ typedef struct {
uint8_t ciphering_key[NR_K_KEY_SIZE];
} nr_pdcp_entity_security_keys_and_algos_t;
typedef struct {
uint32_t sn;
uint32_t hfn;
} nr_pdcp_count_t;
typedef struct {
//nr_pdcp_entity_type_t mode;
/* PDU stats */
@@ -87,7 +92,6 @@ typedef struct {
uint8_t mode; /* 0: PDCP AM, 1: PDCP UM, 2: PDCP TM */
} nr_pdcp_statistics_t;
typedef struct nr_pdcp_entity_t {
nr_pdcp_entity_type_t type;
@@ -180,6 +184,13 @@ typedef struct nr_pdcp_entity_t {
/* Keep tracks of whether the PDCP entity was suspended or not */
bool entity_suspended;
/* PDCP Count API */
nr_pdcp_count_t (*get_pdcp_count_dl)(struct nr_pdcp_entity_t *entity);
nr_pdcp_count_t (*get_pdcp_count_ul)(struct nr_pdcp_entity_t *entity);
void (*set_pdcp_count_dl)(struct nr_pdcp_entity_t *entity, nr_pdcp_count_t count, int sn_size);
void (*set_pdcp_count_ul)(struct nr_pdcp_entity_t *entity, nr_pdcp_count_t count, int sn_size);
} nr_pdcp_entity_t;
nr_pdcp_entity_t *new_nr_pdcp_entity(
+54
View File
@@ -1072,3 +1072,57 @@ int nr_pdcp_get_num_ues(ue_id_t *ue_list, int len)
return num_ues;
}
void nr_pdcp_count_update(ue_id_t ue_id,
rb_id_t drb_id,
nr_pdcp_count_t dl_count,
nr_pdcp_count_t ul_count,
int sn_size)
{
nr_pdcp_manager_lock(nr_pdcp_ue_manager);
nr_pdcp_ue_t *ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id);
if (ue == NULL) {
LOG_E(PDCP, "UE %ld not found in PDCP manager\n", ue_id);
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
return;
}
nr_pdcp_entity_t *entity = nr_pdcp_get_rb(ue, drb_id, false);
if (entity == NULL) {
LOG_E(PDCP, "No PDCP entity found for UE %ld DRB %ld\n", ue_id, drb_id);
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
return;
}
entity->set_pdcp_count_dl(entity, dl_count, sn_size);
entity->set_pdcp_count_ul(entity, ul_count, sn_size);
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
}
/** * @brief Get PDCP COUNT values (PDCP-SN and HFN) for UL and DL from the PDCP entity
* @param[in] ue_id Unique UE ID
* @param[in] rb_id Radio Bearer ID
* @param[out] ul_count UL PDCP count (SN, HFN)
* @param[out] dl_count DL PDCP count (SN, HFN)
*/
void nr_pdcp_get_drb_count_values(ue_id_t ue_id, rb_id_t rb_id, nr_pdcp_count_t *ul_count, nr_pdcp_count_t *dl_count)
{
nr_pdcp_manager_lock(nr_pdcp_ue_manager);
nr_pdcp_ue_t *ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id);
nr_pdcp_entity_t *entity = nr_pdcp_get_rb(ue, rb_id, false);
if (!entity) {
LOG_E(PDCP, "No entity found (DRB %ld)\n", rb_id);
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
return;
}
*dl_count = entity->get_pdcp_count_dl(entity);
*ul_count = entity->get_pdcp_count_ul(entity);
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
}
@@ -125,4 +125,12 @@ int nr_pdcp_get_num_ues(ue_id_t *ue_list, int len);
bool nr_pdcp_get_statistics(ue_id_t ue_id, int srb_flag, int rb_id, nr_pdcp_statistics_t *out);
void nr_pdcp_count_update(ue_id_t ue_id,
rb_id_t drb_id,
nr_pdcp_count_t dl_count,
nr_pdcp_count_t ul_count,
int sn_size);
void nr_pdcp_get_drb_count_values(ue_id_t ue_id, rb_id_t rb_id, nr_pdcp_count_t *ul_count, nr_pdcp_count_t *dl_count);
#endif /* NR_PDCP_OAI_API_H */