Add neighboring cell measurements
Implement intra-frequency neighboring cell measurements including: - Measurement configuration structures - Blind search and known PCI validation - RSRP measurements for neighbor cells Co-authored-by: Roberto Louro Magueta <rmagueta@allbesmart.pt>
This commit is contained in:
co-authored by
Roberto Louro Magueta
parent
dfd3ad267e
commit
3fdbe01157
@@ -2858,3 +2858,17 @@ void nr_rrc_mac_config_req_cg(module_id_t module_id,
|
||||
ret = pthread_mutex_unlock(&mac->if_mutex);
|
||||
AssertFatal(!ret, "mutex failed %d\n", ret);
|
||||
}
|
||||
|
||||
void nr_rrc_mac_config_req_meas(module_id_t module_id, const nr_neighbor_cell_info_t *neighbor_cells, int num_neighbors)
|
||||
{
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
|
||||
for (int i = 0; i < num_neighbors && i < NUMBER_OF_NEIGHBORING_CELLS_MAX; i++) {
|
||||
fapi_nr_neighboring_cell_t *phy_cell = &mac->phy_config.config_req.meas_config.nr_neighboring_cell[i];
|
||||
phy_cell->Nid_cell = neighbor_cells[i].Nid_cell;
|
||||
phy_cell->ssb_freq = neighbor_cells[i].ssb_freq;
|
||||
phy_cell->active = neighbor_cells[i].active;
|
||||
}
|
||||
|
||||
mac->if_module->phy_config_request(&mac->phy_config);
|
||||
}
|
||||
|
||||
@@ -97,6 +97,14 @@ void nr_rrc_mac_config_other_sib(module_id_t module_id, NR_SIB19_r17_t *sib19_r1
|
||||
void nr_rrc_mac_resume_rb(module_id_t module_id, bool is_srb, int rb_id);
|
||||
void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t cause);
|
||||
|
||||
typedef struct nr_neighbor_cell_info {
|
||||
int16_t Nid_cell; // Physical Cell ID
|
||||
uint32_t ssb_freq; // SSB frequency (ARFCN)
|
||||
uint8_t active; // 1 = active, 0 = inactive
|
||||
} nr_neighbor_cell_info_t;
|
||||
|
||||
void nr_rrc_mac_config_req_meas(module_id_t module_id, const nr_neighbor_cell_info_t *neighbor_cells, int num_neighbors);
|
||||
|
||||
/**\brief initialization NR UE MAC instance(s)*/
|
||||
NR_UE_MAC_INST_t * nr_l2_init_ue(int nb_inst);
|
||||
|
||||
|
||||
+136
-23
@@ -921,6 +921,14 @@ static void nr_rrc_manage_rlc_bearers(NR_UE_RRC_INST_t *rrc, const NR_CellGroupC
|
||||
}
|
||||
}
|
||||
|
||||
static void nr_ue_meas_reset(meas_t *meas_cell, bool csi_meas)
|
||||
{
|
||||
if (csi_meas)
|
||||
meas_cell->csi_rsrp_dBm.init = false;
|
||||
else
|
||||
meas_cell->ss_rsrp_dBm.init = false;
|
||||
}
|
||||
|
||||
static void nr_rrc_process_reconfigurationWithSync(NR_UE_RRC_INST_t *rrc,
|
||||
NR_ReconfigurationWithSync_t *reconfigurationWithSync,
|
||||
int gNB_index)
|
||||
@@ -934,6 +942,24 @@ static void nr_rrc_process_reconfigurationWithSync(NR_UE_RRC_INST_t *rrc,
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear neighbor cell lists from measurement objects during handover
|
||||
rrcPerNB_t *rrcNB = &rrc->perNB[gNB_index];
|
||||
for (int i = 0; i < MAX_MEAS_OBJ; i++) {
|
||||
if (rrcNB->MeasObj[i] && rrcNB->MeasObj[i]->measObject.present == NR_MeasObjectToAddMod__measObject_PR_measObjectNR) {
|
||||
NR_MeasObjectNR_t *measObjNR = rrcNB->MeasObj[i]->measObject.choice.measObjectNR;
|
||||
if (measObjNR->cellsToAddModList) {
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_CellsToAddModList, measObjNR->cellsToAddModList);
|
||||
measObjNR->cellsToAddModList = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
l3_measurements_t *l3m = &rrcNB->l3_measurements;
|
||||
for (int i = 0; i < NUMBER_OF_NEIGHBORING_CELLS_MAX; i++) {
|
||||
nr_ue_meas_reset(&l3m->neighboring_cell[i], false);
|
||||
nr_ue_meas_reset(&l3m->neighboring_cell[i], true);
|
||||
}
|
||||
|
||||
if (reconfigurationWithSync->spCellConfigCommon) {
|
||||
/* if the frequencyInfoDL is included, consider the target SpCell
|
||||
to be one on the SSB frequency indicated by the frequencyInfoDL */
|
||||
@@ -1353,7 +1379,11 @@ static void handle_measid_remove(rrcPerNB_t *rrc, struct NR_MeasIdToRemoveList *
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_measid_addmod(rrcPerNB_t *rrc, struct NR_MeasIdToAddModList *addmod_list, NR_UE_Timers_Constants_t *timers)
|
||||
static void handle_measid_addmod(rrcPerNB_t *rrc,
|
||||
struct NR_MeasIdToAddModList *addmod_list,
|
||||
NR_UE_Timers_Constants_t *timers,
|
||||
nr_neighbor_cell_info_t *neighbor_cells,
|
||||
int *num_neighbors)
|
||||
{
|
||||
for (int i = 0; i < addmod_list->list.count; i++) {
|
||||
NR_MeasId_t id = addmod_list->list.array[i]->measId;
|
||||
@@ -1387,11 +1417,56 @@ static void handle_measid_addmod(rrcPerNB_t *rrc, struct NR_MeasIdToAddModList *
|
||||
nr_timer_start(&timers->T321);
|
||||
}
|
||||
}
|
||||
// Check for A3 event and extract neighbor cell info for MAC/PHY
|
||||
else if (reportNR->reportType.present == NR_ReportConfigNR__reportType_PR_eventTriggered) {
|
||||
NR_EventTriggerConfig_t *eventTriggerConfig = reportNR->reportType.choice.eventTriggered;
|
||||
if (eventTriggerConfig->eventId.present == NR_EventTriggerConfig__eventId_PR_eventA3) {
|
||||
if (rrc->MeasObj[measObjectId]
|
||||
&& rrc->MeasObj[measObjectId]->measObject.present == NR_MeasObjectToAddMod__measObject_PR_measObjectNR) {
|
||||
NR_MeasObjectNR_t *obj_nr = rrc->MeasObj[measObjectId]->measObject.choice.measObjectNR;
|
||||
|
||||
uint32_t ssb_freq = 0;
|
||||
if (obj_nr->ssbFrequency) {
|
||||
ssb_freq = *obj_nr->ssbFrequency;
|
||||
}
|
||||
|
||||
if (obj_nr->cellsToAddModList) {
|
||||
NR_CellsToAddModList_t *cellsToAddModList = obj_nr->cellsToAddModList;
|
||||
for (int j = 0; j < cellsToAddModList->list.count; j++) {
|
||||
if (*num_neighbors < NUMBER_OF_NEIGHBORING_CELLS_MAX) {
|
||||
NR_CellsToAddMod_t *cell = cellsToAddModList->list.array[j];
|
||||
neighbor_cells[*num_neighbors].Nid_cell = cell->physCellId;
|
||||
neighbor_cells[*num_neighbors].ssb_freq = ssb_freq;
|
||||
neighbor_cells[*num_neighbors].active = 1;
|
||||
(*num_neighbors)++;
|
||||
} else {
|
||||
LOG_W(NR_RRC,
|
||||
"More than %d neighboring cells configured, ignoring excess cells!\n",
|
||||
NUMBER_OF_NEIGHBORING_CELLS_MAX);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// We do not know PCI of neighboring cells, so we do blind search
|
||||
if (*num_neighbors < NUMBER_OF_NEIGHBORING_CELLS_MAX) {
|
||||
neighbor_cells[*num_neighbors].Nid_cell = -1;
|
||||
neighbor_cells[*num_neighbors].ssb_freq = ssb_freq;
|
||||
neighbor_cells[*num_neighbors].active = 1;
|
||||
(*num_neighbors)++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void nr_rrc_ue_process_measConfig(rrcPerNB_t *rrc, NR_MeasConfig_t *const measConfig, NR_UE_Timers_Constants_t *timers)
|
||||
static void nr_rrc_ue_process_measConfig(rrcPerNB_t *rrc,
|
||||
NR_MeasConfig_t *const measConfig,
|
||||
NR_UE_Timers_Constants_t *timers,
|
||||
nr_neighbor_cell_info_t *neighbor_cells,
|
||||
int *num_neighbors)
|
||||
{
|
||||
if (measConfig->measObjectToRemoveList)
|
||||
handle_measobj_remove(rrc, measConfig->measObjectToRemoveList, timers);
|
||||
@@ -1412,7 +1487,7 @@ static void nr_rrc_ue_process_measConfig(rrcPerNB_t *rrc, NR_MeasConfig_t *const
|
||||
handle_measid_remove(rrc, measConfig->measIdToRemoveList, timers);
|
||||
|
||||
if (measConfig->measIdToAddModList)
|
||||
handle_measid_addmod(rrc, measConfig->measIdToAddModList, timers);
|
||||
handle_measid_addmod(rrc, measConfig->measIdToAddModList, timers, neighbor_cells, num_neighbors);
|
||||
|
||||
LOG_W(NR_RRC, "Measurement gaps not yet supported!\n");
|
||||
|
||||
@@ -1485,7 +1560,12 @@ static void nr_rrc_ue_process_rrcReconfiguration(NR_UE_RRC_INST_t *rrc, int gNB_
|
||||
}
|
||||
if (ie->measConfig) {
|
||||
LOG_I(NR_RRC, "RRCReconfiguration includes Measurement Configuration\n");
|
||||
nr_rrc_ue_process_measConfig(rrcNB, ie->measConfig, &rrc->timers_and_constants);
|
||||
nr_neighbor_cell_info_t neighbor_cells[NUMBER_OF_NEIGHBORING_CELLS_MAX];
|
||||
int num_neighbors = 0;
|
||||
nr_rrc_ue_process_measConfig(rrcNB, ie->measConfig, &rrc->timers_and_constants, neighbor_cells, &num_neighbors);
|
||||
if (num_neighbors > 0) {
|
||||
nr_rrc_mac_config_req_meas(rrc->ue_id, neighbor_cells, num_neighbors);
|
||||
}
|
||||
}
|
||||
if (ie->lateNonCriticalExtension) {
|
||||
LOG_E(NR_RRC, "RRCReconfiguration includes lateNonCriticalExtension. Not handled.\n");
|
||||
@@ -2613,13 +2693,10 @@ static void apply_ema(val_init_t *vi_rsrp_dBm, float filter_coeff_rsrp, int rsrp
|
||||
*meas_init = true;
|
||||
}
|
||||
|
||||
void nr_ue_meas_filtering(rrcPerNB_t *rrc, bool is_neighboring_cell, uint16_t Nid_cell, bool csi_meas, int rsrp_dBm)
|
||||
void nr_ue_meas_filtering(rrcPerNB_t *rrc, meas_t *meas_cell, uint16_t Nid_cell, bool csi_meas, int rsrp_dBm)
|
||||
{
|
||||
if (is_neighboring_cell)
|
||||
return;
|
||||
|
||||
l3_measurements_t *l3_measurements = &rrc->l3_measurements;
|
||||
meas_t *meas_cell = &l3_measurements->serving_cell;
|
||||
|
||||
if (meas_cell->Nid_cell != Nid_cell) {
|
||||
meas_cell->ss_rsrp_dBm.init = false;
|
||||
meas_cell->csi_rsrp_dBm.init = false;
|
||||
@@ -2788,6 +2865,54 @@ static void nr_rrc_handle_ra_indication(NR_UE_RRC_INST_t *rrc, bool ra_succeeded
|
||||
}
|
||||
}
|
||||
|
||||
static void nr_rrc_handle_meas_indication(NR_UE_RRC_INST_t *rrc, NRRrcMacMeasDataInd *meas_ind)
|
||||
{
|
||||
rrcPerNB_t *rrcNB = rrc->perNB + meas_ind->gnb_index;
|
||||
l3_measurements_t *l3_measurements = &rrcNB->l3_measurements;
|
||||
meas_t *meas_cell = NULL;
|
||||
|
||||
if (meas_ind->is_neighboring_cell) {
|
||||
uint16_t target_nid_cell = meas_ind->Nid_cell;
|
||||
for (int i = 0; i < NUMBER_OF_NEIGHBORING_CELLS_MAX; i++) {
|
||||
if (l3_measurements->neighboring_cell[i].Nid_cell == target_nid_cell) {
|
||||
meas_cell = &l3_measurements->neighboring_cell[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!meas_cell) {
|
||||
for (int i = 0; i < NUMBER_OF_NEIGHBORING_CELLS_MAX; i++) {
|
||||
if (!l3_measurements->neighboring_cell[i].ss_rsrp_dBm.init && !l3_measurements->neighboring_cell[i].csi_rsrp_dBm.init) {
|
||||
meas_cell = &l3_measurements->neighboring_cell[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
meas_cell = &l3_measurements->serving_cell;
|
||||
}
|
||||
|
||||
if (!meas_cell) {
|
||||
LOG_E(NR_RRC, "meas_cell not found!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (meas_ind->is_neighboring_cell && meas_ind->rsrp_dBm == INT_MAX) {
|
||||
LOG_W(NR_RRC, "[Nid_cell %i] Neighboring cell not detected. L3 measurements will be reset.\n", meas_ind->Nid_cell);
|
||||
meas_cell->Nid_cell = meas_ind->Nid_cell;
|
||||
nr_ue_meas_reset(meas_cell, meas_ind->is_csi_meas);
|
||||
} else {
|
||||
LOG_D(NR_RRC,
|
||||
"[%s][Nid_cell %i] Received %s measurements: RSRP = %i (dBm)\n",
|
||||
meas_ind->is_neighboring_cell ? "Neighboring cell" : "Active cell",
|
||||
meas_ind->Nid_cell,
|
||||
meas_ind->is_csi_meas ? "CSI meas" : "SSB meas",
|
||||
meas_ind->rsrp_dBm);
|
||||
|
||||
nr_ue_meas_filtering(rrcNB, meas_cell, meas_ind->Nid_cell, meas_ind->is_csi_meas, meas_ind->rsrp_dBm);
|
||||
nr_ue_check_meas_report(rrc, meas_ind->gnb_index);
|
||||
}
|
||||
}
|
||||
|
||||
void *rrc_nrue_task(void *args_p)
|
||||
{
|
||||
itti_mark_task_ready(TASK_RRC_NRUE);
|
||||
@@ -2892,21 +3017,9 @@ void *rrc_nrue(void *notUsed)
|
||||
|
||||
nr_rrc_ue_decode_NR_SBCCH_SL_BCH_Message(rrc, sbcch->gnb_index,sbcch->frame, sbcch->slot, sbcch->sdu,
|
||||
sbcch->sdu_size, sbcch->rx_slss_id);
|
||||
break;
|
||||
case NR_RRC_MAC_MEAS_DATA_IND:
|
||||
|
||||
LOG_D(NR_RRC, "[%s][Nid_cell %i] Received %s measurements: RSRP = %i (dBm)\n",
|
||||
NR_RRC_MAC_MEAS_DATA_IND(msg_p).is_neighboring_cell? "Neighboring cell" : "Active cell",
|
||||
NR_RRC_MAC_MEAS_DATA_IND(msg_p).Nid_cell,
|
||||
NR_RRC_MAC_MEAS_DATA_IND(msg_p).is_csi_meas ? "CSI meas" : "SSB meas",
|
||||
NR_RRC_MAC_MEAS_DATA_IND(msg_p).rsrp_dBm);
|
||||
|
||||
rrcPerNB_t *rrcNB = rrc->perNB + NR_RRC_MAC_MEAS_DATA_IND(msg_p).gnb_index;
|
||||
nr_ue_meas_filtering(rrcNB,
|
||||
NR_RRC_MAC_MEAS_DATA_IND(msg_p).is_neighboring_cell,
|
||||
NR_RRC_MAC_MEAS_DATA_IND(msg_p).Nid_cell,
|
||||
NR_RRC_MAC_MEAS_DATA_IND(msg_p).is_csi_meas,
|
||||
NR_RRC_MAC_MEAS_DATA_IND(msg_p).rsrp_dBm);
|
||||
nr_ue_check_meas_report(rrc, NR_RRC_MAC_MEAS_DATA_IND(msg_p).gnb_index);
|
||||
nr_rrc_handle_meas_indication(rrc, &NR_RRC_MAC_MEAS_DATA_IND(msg_p));
|
||||
break;
|
||||
|
||||
case NR_RRC_MAC_CCCH_DATA_IND: {
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
#define MAX_MEAS_CONFIG 64
|
||||
#define MAX_MEAS_ID 64
|
||||
#define MAX_QUANTITY_CONFIG 2
|
||||
#define NUMBER_OF_NEIGHBORING_CELLS_MAX 1
|
||||
|
||||
typedef enum {
|
||||
nr_SecondaryCellGroupConfig_r15=0,
|
||||
@@ -196,6 +197,7 @@ typedef struct l3_measurements_s {
|
||||
float ssb_filter_coeff_rsrp;
|
||||
float csi_RS_filter_coeff_rsrp;
|
||||
meas_t serving_cell;
|
||||
meas_t neighboring_cell[NUMBER_OF_NEIGHBORING_CELLS_MAX];
|
||||
long trigger_to_measid;
|
||||
long trigger_quantity;
|
||||
long rs_type;
|
||||
|
||||
Reference in New Issue
Block a user