Commit 91a08b1b authored by Guido Casati's avatar Guido Casati

Fix MAC frequency overwrite during handover causing integrity check failures

During N2 handover, the UE receives reconfigurationWithSync which correctly
sets the target cell frequency in mac->phy_config.config_req.carrier_config
via config_common_ue() call.

However, when SIB1 is decoded after reconfiguration,
nr_rrc_mac_config_req_sib1() calls config_common_ue_sa() which unconditionally
overwrites the frequency with the command-line parameter (downlink_frequency),
which corresponds to the source cell frequency.

This causes a critical issue during RRC re-establishment:
- The UE uses the wrong frequency (source cell) for key derivation (kgnb*)
- The gNB uses the correct frequency (target cell) for key derivation
- This mismatch results in different kgnb* keys on UE and gNB
- Integrity check fails: "Integrity of RRCReestablishment failed, going to IDLE"

Root cause:
config_common_ue_sa() is used for SIB1 processing (initial cell selection) and
uses ServingCellConfigCommonSIB which doesn't contain absoluteFrequencyPointA.
It must derive frequency from command-line parameters. However, after handover,
the frequency has already been correctly set by config_common_ue() (used for
reconfigurationWithSync) which uses ServingCellConfigCommon with absolute
frequency information.

Solution:
Modify config_common_ue_sa() to preserve the existing frequency if it's already
initialized (non-zero). Only set frequency from command-line parameters during
initial cell selection when dl_frequency is 0. This ensures:
- Initial cell selection: frequency derived from command-line parameter, just once
- After handover: frequency preserved from reconfigurationWithSync
- MAC maintains its own frequency state independently

The fix applies to both DL and UL frequencies to maintain consistency.
There is probably room for more refactoring to the resync flow, since
the functionalities in config_common_ue and config_common_ue_sa are
partially overlapping and upon reconfigurationWithSync some other
configurations might be applied twice.
parent eebf79a0
......@@ -142,9 +142,21 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommo
frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth);
cfg->carrier_config.dl_bandwidth = get_supported_bw_mhz(mac->frequency_range, bw_index);
uint64_t dl_bw_khz = (12 * frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth) *
(15 << frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing);
cfg->carrier_config.dl_frequency = (downlink_frequency[cc_idP][0]/1000) - (dl_bw_khz>>1);
/** Only set frequency if not already initialized (e.g., from handover reconfigurationWithSync)
* MAC maintains its own frequency state, don't overwrite it with command-line parameter which
* is related to the initial cell selection. */
if (cfg->carrier_config.dl_frequency == 0) {
// Initial cell selection: derive from command-line parameter
uint64_t dl_bw_khz = (12 * frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth) *
(15 << frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing);
cfg->carrier_config.dl_frequency = (downlink_frequency[cc_idP][0]/1000) - (dl_bw_khz>>1);
LOG_I(NR_MAC,
"[UE %d] Initial cell selection: dl_frequency=%u kHz (from command-line, band=%d, scs=%ld)\n",
mac->ue_id,
cfg->carrier_config.dl_frequency,
mac->nr_band,
frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing);
}
for (int i = 0; i < 5; i++) {
if (i == frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing) {
......@@ -165,10 +177,21 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommo
frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth);
cfg->carrier_config.uplink_bandwidth = get_supported_bw_mhz(mac->frequency_range, bw_index);
if (frequencyInfoUL->absoluteFrequencyPointA == NULL)
cfg->carrier_config.uplink_frequency = cfg->carrier_config.dl_frequency;
else
cfg->carrier_config.uplink_frequency = cfg->carrier_config.dl_frequency + (uplink_frequency_offset[cc_idP][0] / 1000);
/** Only set UL frequency if not already initialized (e.g., from handover reconfigurationWithSync)
* MAC maintains its own frequency state, don't overwrite it with command-line parameter which
* is related to the initial cell selection. */
if (cfg->carrier_config.uplink_frequency == 0) {
// Initial cell selection: derive from DL frequency
LOG_I(NR_MAC,
"Initial cell selection: uplink_frequency=%u kHz (from dl_frequency=%u kHz, uplink_frequency_offset=%u kHz)\n",
cfg->carrier_config.uplink_frequency,
cfg->carrier_config.dl_frequency,
uplink_frequency_offset[cc_idP][0]);
if (frequencyInfoUL->absoluteFrequencyPointA == NULL)
cfg->carrier_config.uplink_frequency = cfg->carrier_config.dl_frequency;
else
cfg->carrier_config.uplink_frequency = cfg->carrier_config.dl_frequency + (uplink_frequency_offset[cc_idP][0] / 1000);
}
for (int i = 0; i < 5; i++) {
if (i == frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment