Merge remote-tracking branch 'origin/fix-a3-event' into integration_2026_w04 (!3789)

fix A3 event configuration

See commit message for more information.
As a reference, for comparison purpose, PCAPs and TXT files for various tests
done in develop and in this MR are available in the MR description.
This commit is contained in:
Jaroslava Fiedlerova
2026-01-19 13:55:40 +01:00
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