Validate neighbour config when DUs connect
This commit is contained in:
@@ -1697,6 +1697,11 @@ static void fill_measurement_configuration(uint8_t gnb_idx, gNB_RRC_INST *rrc)
|
|||||||
nr_a3_event_t *a3_event = (nr_a3_event_t *)calloc(1, sizeof(nr_a3_event_t));
|
nr_a3_event_t *a3_event = (nr_a3_event_t *)calloc(1, sizeof(nr_a3_event_t));
|
||||||
AssertFatal(a3_event != NULL, "out of memory\n");
|
AssertFatal(a3_event != NULL, "out of memory\n");
|
||||||
a3_event->pci = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_PCI_ID_IDX].i64ptr;
|
a3_event->pci = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_PCI_ID_IDX].i64ptr;
|
||||||
|
AssertFatal(a3_event->pci >= -1 && a3_event->pci < 1024,
|
||||||
|
"entry %s.%s must be -1<=PCI<1024, but is %d\n",
|
||||||
|
measurement_path,
|
||||||
|
MEASUREMENT_EVENTS_PCI_ID,
|
||||||
|
a3_event->pci);
|
||||||
a3_event->timeToTrigger = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_TIMETOTRIGGER_IDX].i64ptr;
|
a3_event->timeToTrigger = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_TIMETOTRIGGER_IDX].i64ptr;
|
||||||
a3_event->a3_offset = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_OFFSET_IDX].i64ptr;
|
a3_event->a3_offset = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_OFFSET_IDX].i64ptr;
|
||||||
a3_event->hysteresis = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_HYSTERESIS_IDX].i64ptr;
|
a3_event->hysteresis = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_HYSTERESIS_IDX].i64ptr;
|
||||||
|
|||||||
@@ -40,12 +40,17 @@ int get_ssb_scs(const struct f1ap_served_cell_info_t *cell_info)
|
|||||||
return cell_info->mode == F1AP_MODE_TDD ? cell_info->tdd.tbw.scs : cell_info->fdd.dl_tbw.scs;
|
return cell_info->mode == F1AP_MODE_TDD ? cell_info->tdd.tbw.scs : cell_info->fdd.dl_tbw.scs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ssb_arfcn_mtc(const NR_MeasurementTimingConfiguration_t *mtc)
|
||||||
|
{
|
||||||
|
/* format has been verified when accepting MeasurementTimingConfiguration */
|
||||||
|
NR_MeasTimingList_t *mtlist = mtc->criticalExtensions.choice.c1->choice.measTimingConf->measTiming;
|
||||||
|
return mtlist->list.array[0]->frequencyAndTiming->carrierFreq;
|
||||||
|
}
|
||||||
|
|
||||||
int get_ssb_arfcn(const struct nr_rrc_du_container_t *du)
|
int get_ssb_arfcn(const struct nr_rrc_du_container_t *du)
|
||||||
{
|
{
|
||||||
DevAssert(du != NULL && du->mtc != NULL);
|
DevAssert(du != NULL && du->mtc != NULL);
|
||||||
/* format has been verified when accepting MeasurementTimingConfiguration */
|
return ssb_arfcn_mtc(du->mtc);
|
||||||
NR_MeasTimingList_t *mtlist = du->mtc->criticalExtensions.choice.c1->choice.measTimingConf->measTiming;
|
|
||||||
return mtlist->list.array[0]->frequencyAndTiming->carrierFreq;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int du_compare(const nr_rrc_du_container_t *a, const nr_rrc_du_container_t *b)
|
static int du_compare(const nr_rrc_du_container_t *a, const nr_rrc_du_container_t *b)
|
||||||
@@ -197,6 +202,58 @@ static void label_intra_frequency_neighbours(gNB_RRC_INST *rrc,
|
|||||||
for_each(cell_neighbour_list, (void *)&ssb_arfcn, is_intra_frequency_neighbour);
|
for_each(cell_neighbour_list, (void *)&ssb_arfcn, is_intra_frequency_neighbour);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool valid_du_in_neighbour_configs(const seq_arr_t *neighbour_cell_configuration, const f1ap_served_cell_info_t *cell, int ssb_arfcn)
|
||||||
|
{
|
||||||
|
for (int c = 0; c < neighbour_cell_configuration->size; c++) {
|
||||||
|
const neighbour_cell_configuration_t *neighbour_config = seq_arr_at(neighbour_cell_configuration, c);
|
||||||
|
for (int ni = 0; ni < neighbour_config->neighbour_cells->size; ni++) {
|
||||||
|
const nr_neighbour_gnb_configuration_t *nc = seq_arr_at(neighbour_config->neighbour_cells, ni);
|
||||||
|
if (nc->nrcell_id != cell->nr_cellid)
|
||||||
|
continue;
|
||||||
|
// current cell is in the nc config, check that config matches
|
||||||
|
if (nc->physicalCellId != cell->nr_pci) {
|
||||||
|
LOG_W(NR_RRC, "Cell %ld in neighbour config: PCI mismatch (%d vs %d)\n", cell->nr_cellid, cell->nr_pci, nc->physicalCellId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (cell->tac && nc->tac != *cell->tac) {
|
||||||
|
LOG_W(NR_RRC, "Cell %ld in neighbour config: TAC mismatch (%d vs %d)\n", cell->nr_cellid, *cell->tac, nc->tac);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (ssb_arfcn != nc->absoluteFrequencySSB) {
|
||||||
|
LOG_W(NR_RRC,
|
||||||
|
"Cell %ld in neighbour config: SSB ARFCN mismatch (%d vs %d)\n",
|
||||||
|
cell->nr_cellid,
|
||||||
|
ssb_arfcn,
|
||||||
|
nc->absoluteFrequencySSB);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (get_ssb_scs(cell) != nc->subcarrierSpacing) {
|
||||||
|
LOG_W(NR_RRC,
|
||||||
|
"Cell %ld in neighbour config: SCS mismatch (%d vs %d)\n",
|
||||||
|
cell->nr_cellid,
|
||||||
|
get_ssb_scs(cell),
|
||||||
|
nc->subcarrierSpacing);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (cell->plmn.mcc != nc->plmn.mcc || cell->plmn.mnc != nc->plmn.mnc
|
||||||
|
|| cell->plmn.mnc_digit_length != nc->plmn.mnc_digit_length) {
|
||||||
|
LOG_W(NR_RRC,
|
||||||
|
"Cell %ld in neighbour config: PLMN mismatch (%03d.%0*d vs %03d.%0*d)\n",
|
||||||
|
cell->nr_cellid,
|
||||||
|
cell->plmn.mcc,
|
||||||
|
cell->plmn.mnc_digit_length,
|
||||||
|
cell->plmn.mnc,
|
||||||
|
nc->plmn.mcc,
|
||||||
|
nc->plmn.mnc_digit_length,
|
||||||
|
nc->plmn.mnc);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LOG_D(NR_RRC, "Cell %ld is neighbor of cell %ld\n", cell->nr_cellid, neighbour_config->nr_cell_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id)
|
void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id)
|
||||||
{
|
{
|
||||||
AssertFatal(assoc_id != 0, "illegal assoc_id == 0: should be -1 (monolithic) or >0 (split)\n");
|
AssertFatal(assoc_id != 0, "illegal assoc_id == 0: should be -1 (monolithic) or >0 (split)\n");
|
||||||
@@ -264,6 +321,15 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id)
|
|||||||
NR_MeasurementTimingConfiguration_t *mtc =
|
NR_MeasurementTimingConfiguration_t *mtc =
|
||||||
extract_mtc(cell_info->measurement_timing_config, cell_info->measurement_timing_config_len);
|
extract_mtc(cell_info->measurement_timing_config, cell_info->measurement_timing_config_len);
|
||||||
|
|
||||||
|
if (rrc->neighbour_cell_configuration
|
||||||
|
&& !valid_du_in_neighbour_configs(rrc->neighbour_cell_configuration, cell_info, ssb_arfcn_mtc(mtc))) {
|
||||||
|
LOG_E(NR_RRC, "problem with DU %ld in neighbor configuration, rejecting DU\n", req->gNB_DU_id);
|
||||||
|
f1ap_setup_failure_t fail = {.cause = F1AP_CauseMisc_unspecified};
|
||||||
|
rrc->mac_rrc.f1_setup_failure(assoc_id, &fail);
|
||||||
|
ASN_STRUCT_FREE(asn_DEF_NR_MeasurementTimingConfiguration, mtc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const f1ap_gnb_du_system_info_t *sys_info = req->cell[0].sys_info;
|
const f1ap_gnb_du_system_info_t *sys_info = req->cell[0].sys_info;
|
||||||
NR_MIB_t *mib = NULL;
|
NR_MIB_t *mib = NULL;
|
||||||
NR_SIB1_t *sib1 = NULL;
|
NR_SIB1_t *sib1 = NULL;
|
||||||
|
|||||||
Reference in New Issue
Block a user