fix A3 event configuration

While testing the gNB with two hypotetical neighbors, some issues were found
with A3 event configuration.

The configuration of neighbors is:

neighbour_list = (
  {
    nr_cellid = 12345679L;

    neighbour_cell_configuration = (
      {
        gNB_ID              = 0xba0;
        nr_cellid           = 720898;
        physical_cellId     = 1;
        absoluteFrequencySSB= 621312;
        subcarrierSpacing   = 1;
        band                = 78;
        plmn                = { mcc = 505; mnc = 01; mnc_length = 2 };
        tracking_area_code  = 1;
      },
      {
        gNB_ID              = 0xea0;
        nr_cellid           = 1345678L;
        physical_cellId     = 2;
        absoluteFrequencySSB= 640000;
        subcarrierSpacing   = 1;
        band                = 78;
        plmn                = { mcc = 505; mnc = 01; mnc_length = 2 };
        tracking_area_code  = 1;
      }
    );
  }
);

There were two problems.

The first problem is:
- when only default A3 event is configured, it is duplicated in the
  RRC Reconfiguration Report Config To AddMod list with IDs 4 and 5

To test this case, the event configuration is:

nr_measurement_configuration = {
  Periodical = {
    enable                     = 1;
    includeBeamMeasurements    = 1;
    maxNrofRS_IndexesToReport  = 4;
  };

  A2 = {
    enable          = 1;
    threshold       = 60;
    time_to_trigger = 1;
  };

  A3 = (
  {
    physCellId      = -1;
    offset          = 15;
    hysteresis      = 2;
    time_to_trigger = 3
  }
  );
};

The second problem is:
- when configuring an A3 event with an unknown physCellId, the gNB
  does not include any A3 event in the RRC Reconfiguration Report
  Config To AddMod list (which is correct), but configures some
  meas ID with nonexistant Report Config IDs

To test this case, the event configuration is:

nr_measurement_configuration = {
  Periodical = {
    enable                     = 1;
    includeBeamMeasurements    = 1;
    maxNrofRS_IndexesToReport  = 4;
  };

  A2 = {
    enable          = 1;
    threshold       = 60;
    time_to_trigger = 1;
  };

  A3 = (
  {
    physCellId      = 10;
    offset          = 15;
    hysteresis      = 2;
    time_to_trigger = 3
  }
  );
};

Reworking A3 event configuration as done in this commit solves both
issues.
This commit is contained in:
Cedric Roux
2026-01-17 23:00:32 +01:00
parent 102965a669
commit ac535b6338
3 changed files with 40 additions and 14 deletions
+6 -2
View File
@@ -1121,7 +1121,8 @@ NR_MeasConfig_t *get_MeasConfig(const NR_MeasTiming_t *mt,
NR_ReportConfigToAddMod_t *rc_PER,
NR_ReportConfigToAddMod_t *rc_A2,
seq_arr_t *rc_A3_seq,
seq_arr_t *neigh_seq)
seq_arr_t *neigh_seq,
int *neigh_a3_id)
{
DevAssert(mt != NULL && mt->frequencyAndTiming != NULL);
const struct NR_MeasTiming__frequencyAndTiming *ft = mt->frequencyAndTiming;
@@ -1207,7 +1208,10 @@ NR_MeasConfig_t *get_MeasConfig(const NR_MeasTiming_t *mt,
if (neigh_seq) {
int i = 0;
FOR_EACH_SEQ_ARR(nr_neighbour_cell_t *, neigh_cell, neigh_seq) {
NR_ReportConfigId_t reportConfigId = neigh_cell->physicalCellId == -1 ? 3 : i + 4;
NR_ReportConfigId_t reportConfigId = neigh_a3_id[i];
/* check that there is a A3 configured for this neighbour */
if (reportConfigId == -1)
continue;
NR_MeasIdToAddMod_t *measid_A3 = get_MeasId(meas_idx + 1, reportConfigId, i + 2);
meas_idx++;
asn1cSeqAdd(&mc->measIdToAddModList->list, measid_A3);
+2 -1
View File
@@ -164,7 +164,8 @@ NR_MeasConfig_t *get_MeasConfig(const NR_MeasTiming_t *mt,
NR_ReportConfigToAddMod_t *rc_PER,
NR_ReportConfigToAddMod_t *rc_A2,
seq_arr_t *rc_A3_seq,
seq_arr_t *neigh_seq);
seq_arr_t *neigh_seq,
int *neigh_a3_id);
void free_MeasConfig(NR_MeasConfig_t *mc);
int do_NR_Paging(uint8_t Mod_id, uint8_t *buffer, uint32_t tmsi);
+32 -11
View File
@@ -622,9 +622,6 @@ static nr_a3_event_t *get_a3_configuration(gNB_RRC_INST *rrc, int pci)
return a3_event;
}
if (measurementConfiguration->is_default_a3_configuration_exists)
return get_a3_configuration(rrc, -1);
return NULL;
}
@@ -750,6 +747,10 @@ NR_MeasConfig_t *nr_rrc_get_measconfig(const gNB_RRC_INST *rrc, uint64_t nr_cell
if (neighbour_config)
neighbour_cells = neighbour_config->neighbour_cells;
int *neigh_a3_id = NULL;
if (neighbour_cells && neighbour_cells->size)
neigh_a3_id = calloc_or_fail(neighbour_cells->size, sizeof(int));
if (neighbour_cells && rrc->measurementConfiguration.a3_event_list && rrc->measurementConfiguration.a3_event_list->size > 0) {
/* Loop through neighbours and find related A3 configuration
If no related A3 but there is default add the default one.
@@ -759,16 +760,31 @@ NR_MeasConfig_t *nr_rrc_get_measconfig(const gNB_RRC_INST *rrc, uint64_t nr_cell
bool default_a3_added = false; // To ensure that the default configuration is only added once
for (int i = 0; i < neighbour_cells->size; i++) {
nr_neighbour_cell_t *neighbourCell = (nr_neighbour_cell_t *)seq_arr_at(neighbour_cells, i);
if (default_a3_added && neighbourCell->physicalCellId == -1)
continue;
seq_arr_push_back(&neigh_seq, neighbourCell, sizeof(nr_neighbour_cell_t));
const nr_a3_event_t *a3Event = get_a3_configuration((gNB_RRC_INST *)rrc, neighbourCell->physicalCellId);
if (a3Event) {
NR_ReportConfigId_t reportConfigId = neighbourCell->physicalCellId == -1 ? 3 : i + 4;
seq_arr_push_back(&rc_A3_seq, prepare_a3_event_report(a3Event, reportConfigId), sizeof(NR_ReportConfigToAddMod_t));
if (neighbourCell->physicalCellId == -1)
default_a3_added = true;
if (!a3Event) {
/* no A3 event configured for this neighbour, let's try the default one, if it exists */
if (default_a3_added) {
/* default A3 exists and is already added, use it for this neighbour */
neigh_a3_id[i] = 3;
continue;
}
/* try to get the default A3 config */
a3Event = get_a3_configuration((gNB_RRC_INST *)rrc, -1);
if (!a3Event) {
/* no default A3 config found, so no A3 config for this neighbour */
neigh_a3_id[i] = -1;
continue;
}
default_a3_added = true;
/* default A3 report config ID is 3 */
neigh_a3_id[i] = 3;
} else {
/* specific A3 report config ID are 4, 5, ... */
neigh_a3_id[i] = i + 4;
}
NR_ReportConfigId_t reportConfigId = neigh_a3_id[i];
seq_arr_push_back(&rc_A3_seq, prepare_a3_event_report(a3Event, reportConfigId), sizeof(NR_ReportConfigToAddMod_t));
}
}
if (rrc->measurementConfiguration.per_event)
@@ -776,12 +792,14 @@ NR_MeasConfig_t *nr_rrc_get_measconfig(const gNB_RRC_INST *rrc, uint64_t nr_cell
if (rrc->measurementConfiguration.a2_event)
rc_A2 = prepare_a2_event_report(rrc->measurementConfiguration.a2_event);
NR_MeasConfig_t *result = get_MeasConfig(mt, band, scs, cell_info->nr_pci, rc_PER, rc_A2, &rc_A3_seq, &neigh_seq);
NR_MeasConfig_t *result = get_MeasConfig(mt, band, scs, cell_info->nr_pci, rc_PER, rc_A2, &rc_A3_seq, &neigh_seq, neigh_a3_id);
// Clean up sequence arrays
seq_arr_free(&rc_A3_seq, NULL);
seq_arr_free(&neigh_seq, NULL);
free(neigh_a3_id);
return result;
}
return NULL;
@@ -1620,6 +1638,9 @@ static void process_Event_Based_Measurement_Report(gNB_RRC_INST *rrc,
if (!neigh_cell && neighbour) {
// No F1 connection but static neighbour configuration is available
const nr_a3_event_t *a3_event_configuration = get_a3_configuration(rrc, neighbour->physicalCellId);
/* if no A3 event configured for this physical cell ID, try to get the default one */
if (!a3_event_configuration)
a3_event_configuration = get_a3_configuration(rrc, -1);
// Additional check - This part can be modified according to additional cell specific Handover Margin
// a3-Offset: The actual value is field value * 0.5 dB.
if (a3_event_configuration