RRC multi-cell: extract DU management to cell management library

Move DU tree management from rrc_gNB_du.c into rrc_cell_management so that
DU and cell lookup logic live in one place, improving maintainability and
testability (there is no DU lib).

- rrc_cell_management: add du_compare(), RB_GENERATE(rrc_du_tree),
  get_du_by_assoc_id(), rrc_add_du(), rrc_rm_du(), rrc_cleanup_du(),
  rrc_free_du_container(); declare them in rrc_cell_management.h.
- rrc_gNB_du: move du_compare(), RB_GENERATE, get_du_by_assoc_id()
  to rrc_cell_management
This commit is contained in:
Guido Casati
2026-02-05 11:44:09 +01:00
parent 3dfdc66c41
commit 6d0c7945c2
5 changed files with 94 additions and 19 deletions
+83
View File
@@ -32,6 +32,89 @@
#include "NR_SIB1.h" // for asn_DEF_NR_SIB1
#include "NR_MeasurementTimingConfiguration.h" // for asn_DEF_NR_MeasurementTimingConfiguration
/** @brief Comparison function for DU tree
* @param[in] a Pointer to first DU container
* @param[in] b Pointer to second DU container
* @return Comparison result */
int du_compare(const nr_rrc_du_container_t *a, const nr_rrc_du_container_t *b)
{
if (a->assoc_id > b->assoc_id)
return 1;
if (a->assoc_id == b->assoc_id)
return 0;
return -1; /* a->assoc_id < b->assoc_id */
}
// Generate RB tree functions for DU tree
RB_GENERATE(rrc_du_tree, nr_rrc_du_container_t, entries, du_compare);
/** @brief Find DU by SCTP association ID (uses DU RB-tree lookup)
* @param[in] rrc Pointer to RRC instance
* @param[in] assoc_id SCTP association ID
* @return Pointer to the DU container, or NULL if not found
* @note O(log N_DU) complexity using DU RB-tree lookup */
nr_rrc_du_container_t *get_du_by_assoc_id(gNB_RRC_INST *rrc, const sctp_assoc_t assoc_id)
{
DevAssert(rrc != NULL);
nr_rrc_du_container_t e = {.assoc_id = assoc_id};
return RB_FIND(rrc_du_tree, &rrc->dus, &e);
}
/** @brief Add DU to RRC DU tree and increment rrc->num_dus on success
* @param[in] rrc Pointer to RRC instance
* @param[in] du Pointer to DU container to add
* @return NULL if inserted successfully; pointer to existing DU (collision) if duplicate assoc_id */
nr_rrc_du_container_t *rrc_add_du(gNB_RRC_INST *rrc, nr_rrc_du_container_t *du)
{
DevAssert(rrc != NULL);
DevAssert(du != NULL);
nr_rrc_du_container_t *collision = RB_INSERT(rrc_du_tree, &rrc->dus, du);
if (collision == NULL)
rrc->num_dus++;
return collision;
}
/** @brief Free a DU container and its allocated fields (gNB_DU_name); free the DU itself
* @param[in] du Pointer to DU container to free
* @note Does NOT remove the DU from the tree or free du->cells; caller must do RB_REMOVE and seq_arr_free first */
void rrc_free_du_container(nr_rrc_du_container_t *du)
{
DevAssert(du != NULL);
free(du->gNB_DU_name);
free(du);
}
/** @brief Remove DU from RRC DU tree, decrement rrc->num_dus, and free the DU and its resources
* @param[in] rrc Pointer to RRC instance
* @param[in] du Pointer to DU container to remove (caller must have removed and freed all cells first) */
void rrc_rm_du(gNB_RRC_INST *rrc, nr_rrc_du_container_t *du)
{
DevAssert(rrc != NULL);
DevAssert(du != NULL);
nr_rrc_du_container_t *removed = RB_REMOVE(rrc_du_tree, &rrc->dus, du);
AssertFatal(removed == du, "Failed to remove DU (assoc_id %d) from tree\n", du->assoc_id);
rrc->num_dus--;
seq_arr_free(&du->cells, NULL);
rrc_free_du_container(du);
}
/** @brief Remove all cells from the DU (and from global cell tree), remove the DU from the tree, and free the DU
* @param[in] rrc Pointer to RRC instance
* @param[in] du Pointer to DU container to cleanup (removed from tree and freed) */
void rrc_cleanup_du(gNB_RRC_INST *rrc, nr_rrc_du_container_t *du)
{
DevAssert(rrc != NULL);
DevAssert(du != NULL);
for (size_t i = seq_arr_size(&du->cells); i > 0; i--) {
nr_rrc_cell_container_t **cell_ptr = seq_arr_at(&du->cells, i - 1);
nr_rrc_cell_container_t *cell = *cell_ptr;
LOG_I(NR_RRC, "Removing cell %lu from DU cells array\n", cell->info.cell_id);
seq_arr_erase(&du->cells, cell_ptr);
rrc_rm_cell(rrc, cell);
}
rrc_rm_du(rrc, du);
}
/** @brief Comparison function for cell tree
* @param[in] a Pointer to first cell container
* @param[in] b Pointer to second cell container
+9
View File
@@ -30,6 +30,15 @@
// Generate RB tree functions (prototypes)
int rrc_cell_cmp(const struct nr_rrc_cell_container_t *a, const struct nr_rrc_cell_container_t *b);
RB_PROTOTYPE(rrc_cell_tree, nr_rrc_cell_container_t, entries, rrc_cell_cmp);
int du_compare(const struct nr_rrc_du_container_t *a, const struct nr_rrc_du_container_t *b);
RB_PROTOTYPE(rrc_du_tree, nr_rrc_du_container_t, entries, du_compare);
// DU management (global DU tree)
nr_rrc_du_container_t *rrc_add_du(gNB_RRC_INST *rrc, nr_rrc_du_container_t *du);
void rrc_rm_du(gNB_RRC_INST *rrc, nr_rrc_du_container_t *du);
void rrc_cleanup_du(gNB_RRC_INST *rrc, nr_rrc_du_container_t *du);
void rrc_free_du_container(nr_rrc_du_container_t *du);
nr_rrc_du_container_t *get_du_by_assoc_id(gNB_RRC_INST *rrc, const sctp_assoc_t assoc_id);
// Cell management (global cell tree)
nr_rrc_cell_container_t *get_cell_by_cell_id(struct rrc_cell_tree *cells, const uint64_t cell_id);
+1
View File
@@ -84,6 +84,7 @@
#include "rrc_gNB_du.h"
#include "rrc_gNB_mobility.h"
#include "rrc_gNB_radio_bearers.h"
#include "rrc_cell_management.h"
#include "rrc_messages_types.h"
#include "rrc_gNB_asn1.h"
#include "seq_arr.h"
+1 -18
View File
@@ -20,6 +20,7 @@
*/
#include "rrc_gNB_du.h"
#include "rrc_cell_management.h"
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
@@ -84,18 +85,6 @@ int get_ssb_arfcn(const struct nr_rrc_du_container_t *du)
return ssb_arfcn_mtc(du->mtc);
}
static int du_compare(const nr_rrc_du_container_t *a, const nr_rrc_du_container_t *b)
{
if (a->assoc_id > b->assoc_id)
return 1;
if (a->assoc_id == b->assoc_id)
return 0;
return -1; /* a->assoc_id < b->assoc_id */
}
/* Tree management functions */
RB_GENERATE/*_STATIC*/(rrc_du_tree, nr_rrc_du_container_t, entries, du_compare);
static bool rrc_gNB_plmn_matches(const gNB_RRC_INST *rrc, const f1ap_served_cell_info_t *info)
{
const gNB_RrcConfigurationReq *conf = &rrc->configuration;
@@ -629,12 +618,6 @@ nr_rrc_du_container_t *get_du_for_ue(gNB_RRC_INST *rrc, uint32_t ue_id)
return get_du_by_assoc_id(rrc, ue_data.du_assoc_id);
}
nr_rrc_du_container_t *get_du_by_assoc_id(gNB_RRC_INST *rrc, sctp_assoc_t assoc_id)
{
nr_rrc_du_container_t e = {.assoc_id = assoc_id};
return RB_FIND(rrc_du_tree, &rrc->dus, &e);
}
/* \brief find DU by cell ID. Note: currently the CU is limited to one cell per
* DU, hence here, DU == cell. Modify this to look up a specific cell. */
nr_rrc_du_container_t *get_du_by_cell_id(gNB_RRC_INST *rrc, uint64_t cell_id)
-1
View File
@@ -38,7 +38,6 @@ void rrc_CU_process_f1_lost_connection(struct gNB_RRC_INST_s *rrc, struct f1ap_l
void rrc_gNB_process_f1_du_configuration_update(struct f1ap_gnb_du_configuration_update_s *conf_up, sctp_assoc_t assoc_id);
struct nr_rrc_du_container_t *get_du_for_ue(struct gNB_RRC_INST_s *rrc, uint32_t ue_id);
struct nr_rrc_du_container_t *get_du_by_assoc_id(struct gNB_RRC_INST_s *rrc, sctp_assoc_t assoc_id);
const struct f1ap_served_cell_info_t *get_cell_information_by_phycellId(int phyCellId);
struct nr_rrc_du_container_t *get_du_by_cell_id(struct gNB_RRC_INST_s *rrc, uint64_t cell_id);