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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user