Merge remote-tracking branch 'origin/nr_ue_multiple_rf' into integration_2026_w05 (!3593)
NR UE: add support for multiple RF frontends
This MR adds basic support for multiple RF-frontends at the UE.
There are multiple reasons why we might want this:
1. There might be different antennas needed for different bands (e.g. NTN or
TN antennas). These antennas might be connected to different RF-frontends.
In case of Handover, the UE needs to dynamically switch between these
RF-frontends.
2. Each rf-simulator connection carries baseband I/Q samples. To be able to
perform a handover between two cells at different frequencies, there must
be two rf-simulator connections, as the baseband channels should not
interfere and thus cannot simply be added.
3. When we want to support multiple UE simulation within one instance of
nr-uesoftmodem, and allow multiple cells and probably even handover between
these cells, we need either:
1. dedicated RF-frontends for each simulated UE, or
2. dedicated RF-frontends for each connected cell and dynamically assign
simulated UEs accordingly.
This MR implements what is needed for 1., 2. and 3.1.
This commit is contained in:
@@ -187,9 +187,9 @@ e2_agent = {
|
||||
```bash
|
||||
cd <path-to>/build
|
||||
# for gNB-mono
|
||||
sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --uicc0.imsi 001010000000001 --rfsimulator.serveraddr 127.0.0.1
|
||||
sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --uicc0.imsi 001010000000001 --rfsimulator.[0].serveraddr 127.0.0.1
|
||||
# for CU/DU and CU-CP/CU-UP/DU split
|
||||
sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3450720000 --rfsim --uicc0.imsi 001010000000001 --rfsimulator.serveraddr 127.0.0.1
|
||||
sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3450720000 --rfsim --uicc0.imsi 001010000000001 --rfsimulator.[0].serveraddr 127.0.0.1
|
||||
```
|
||||
Note: [multi-UE rfsim deployment tutorial](../../doc/NR_SA_Tutorial_OAI_multi_UE.md?ref_type=heads#run-multiple-ues-in-rfsimulator)
|
||||
|
||||
|
||||
@@ -202,7 +202,7 @@ typedef enum {
|
||||
{CONFIG_STRING_RU_END_OF_BURST_DELAY, NULL, 0, .uptr=NULL, .defuintval=400, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_RU_OTA_SYNC_ENABLE, NULL, 0, .strptr=NULL, .defstrval="no", TYPE_STRING, 0}, \
|
||||
{CONFIG_STRING_RU_BF_WEIGHTS_LIST, NULL, 0, .iptr=NULL, .defintarrayval=DEFBFW, TYPE_INTARRAY, 0}, \
|
||||
{CONFIG_STRING_RU_IF_FREQUENCY, NULL, 0, .u64ptr=NULL, .defuintval=0, TYPE_UINT64, 0}, \
|
||||
{CONFIG_STRING_RU_IF_FREQUENCY, NULL, 0, .u64ptr=NULL, .defint64val=0, TYPE_UINT64, 0}, \
|
||||
{CONFIG_STRING_RU_IF_FREQ_OFFSET, NULL, 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \
|
||||
{CONFIG_STRING_RU_DO_PRECODING, NULL, 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \
|
||||
{CONFIG_STRING_RU_SF_AHEAD, HLP_RU_SF_AHEAD, 0, .iptr=NULL, .defintval=4, TYPE_INT, 0}, \
|
||||
|
||||
@@ -137,6 +137,7 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommo
|
||||
AssertFatal(frequencyInfoDL->frequencyBandList.list.array[0]->freqBandIndicatorNR, "Field mandatory present for DL in SIB1\n");
|
||||
mac->nr_band = *frequencyInfoDL->frequencyBandList.list.array[0]->freqBandIndicatorNR;
|
||||
|
||||
AssertFatal(mac->numerology == frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, "DL and SSB subcarrierSpacing must be the same!\n");
|
||||
int bw_index = get_supported_band_index(frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing,
|
||||
mac->frequency_range,
|
||||
frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth);
|
||||
@@ -149,7 +150,7 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommo
|
||||
// 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);
|
||||
cfg->carrier_config.dl_frequency = mac->dl_frequency / 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,
|
||||
@@ -172,25 +173,35 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommo
|
||||
NR_FrequencyInfoUL_SIB_t *frequencyInfoUL = &scc->uplinkConfigCommon->frequencyInfoUL;
|
||||
mac->p_Max = frequencyInfoUL->p_Max ? *frequencyInfoUL->p_Max : INT_MIN;
|
||||
|
||||
AssertFatal(mac->numerology == frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, "UL and SSB subcarrierSpacing must be the same!\n");
|
||||
bw_index = get_supported_band_index(frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing,
|
||||
mac->frequency_range,
|
||||
frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth);
|
||||
cfg->carrier_config.uplink_bandwidth = get_supported_bw_mhz(mac->frequency_range, bw_index);
|
||||
|
||||
/** 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. */
|
||||
* 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)
|
||||
// Initial cell selection: derive from DL frequency or frequencyInfoUL->absoluteFrequencyPointA
|
||||
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);
|
||||
LOG_I(NR_MAC,
|
||||
"Initial cell selection: uplink_frequency=%u kHz (from dl_frequency=%u kHz)\n",
|
||||
cfg->carrier_config.uplink_frequency,
|
||||
cfg->carrier_config.dl_frequency);
|
||||
} else {
|
||||
cfg->carrier_config.uplink_frequency = from_nrarfcn(*frequencyInfoUL->frequencyBandList->list.array[0]->freqBandIndicatorNR,
|
||||
frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing,
|
||||
*frequencyInfoUL->absoluteFrequencyPointA)
|
||||
/ 1000; // freq in kHz
|
||||
LOG_I(NR_MAC,
|
||||
"Initial cell selection: uplink_frequency=%u kHz (from absoluteFrequencyPointA=%ld, band=%ld, scs=%ld)\n",
|
||||
cfg->carrier_config.uplink_frequency,
|
||||
*frequencyInfoUL->absoluteFrequencyPointA,
|
||||
*frequencyInfoUL->frequencyBandList->list.array[0]->freqBandIndicatorNR,
|
||||
frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
@@ -204,7 +215,7 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommo
|
||||
}
|
||||
}
|
||||
|
||||
frame_type_t frame_type = get_frame_type(mac->nr_band, get_softmodem_params()->numerology);
|
||||
frame_type_t frame_type = get_frame_type(mac->nr_band, mac->numerology);
|
||||
// cell config
|
||||
cfg->cell_config.phy_cell_id = mac->physCellId;
|
||||
cfg->cell_config.frame_duplex_type = frame_type;
|
||||
@@ -212,7 +223,7 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommo
|
||||
|
||||
// SSB config
|
||||
cfg->ssb_config.ss_pbch_power = scc->ss_PBCH_BlockPower;
|
||||
cfg->ssb_config.scs_common = get_softmodem_params()->numerology;
|
||||
cfg->ssb_config.scs_common = mac->numerology;
|
||||
|
||||
// SSB Table config
|
||||
cfg->ssb_table.ssb_offset_point_a = frequencyInfoDL->offsetToPointA;
|
||||
@@ -231,7 +242,7 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommo
|
||||
}
|
||||
|
||||
int period_idx = mac->tdd_UL_DL_ConfigurationCommon ? get_tdd_period_idx(mac->tdd_UL_DL_ConfigurationCommon) : 0;
|
||||
config_frame_structure(get_softmodem_params()->numerology,
|
||||
config_frame_structure(mac->numerology,
|
||||
mac->tdd_UL_DL_ConfigurationCommon,
|
||||
period_idx,
|
||||
frame_type,
|
||||
@@ -443,14 +454,16 @@ static void config_common_ue(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommon_t
|
||||
|
||||
// carrier config
|
||||
LOG_D(MAC, "[UE %d] Entering UE Config Common\n", mac->ue_id);
|
||||
mac->numerology = *scc->ssbSubcarrierSpacing;
|
||||
|
||||
AssertFatal(scc->downlinkConfigCommon, "Not expecting downlinkConfigCommon to be NULL here\n");
|
||||
NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL;
|
||||
if (frequencyInfoDL) { // NeedM for inter-freq handover
|
||||
mac->nr_band = *frequencyInfoDL->frequencyBandList.list.array[0];
|
||||
frame_type = get_frame_type(mac->nr_band, get_softmodem_params()->numerology);
|
||||
frame_type = get_frame_type(mac->nr_band, mac->numerology);
|
||||
mac->frequency_range = get_freq_range_from_band(mac->nr_band);
|
||||
|
||||
AssertFatal(mac->numerology == frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, "DL and SSB subcarrierSpacing must be the same!\n");
|
||||
int bw_index = get_supported_band_index(frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing,
|
||||
mac->frequency_range,
|
||||
frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth);
|
||||
@@ -483,6 +496,7 @@ static void config_common_ue(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommon_t
|
||||
NR_FrequencyInfoUL_t *frequencyInfoUL = scc->uplinkConfigCommon->frequencyInfoUL;
|
||||
mac->p_Max = frequencyInfoUL->p_Max ? *frequencyInfoUL->p_Max : INT_MIN;
|
||||
|
||||
AssertFatal(mac->numerology == frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, "UL and SSB subcarrierSpacing must be the same!\n");
|
||||
int bw_index = get_supported_band_index(frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing,
|
||||
mac->frequency_range,
|
||||
frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth);
|
||||
|
||||
@@ -606,6 +606,8 @@ typedef struct NR_UE_MAC_INST_s {
|
||||
uint16_t nr_band;
|
||||
uint8_t ssb_subcarrier_offset;
|
||||
int ssb_start_subcarrier;
|
||||
uint64_t dl_frequency;
|
||||
int numerology;
|
||||
|
||||
NR_SSB_meas_t ssb_measurements[MAX_NB_SSB];
|
||||
NR_CSIRS_meas_t csirs_measurements;
|
||||
|
||||
@@ -106,7 +106,7 @@ typedef struct nr_neighbor_cell_info {
|
||||
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);
|
||||
NR_UE_MAC_INST_t * nr_l2_init_ue(int nb_inst, int numerology);
|
||||
|
||||
/**\brief fetch MAC instance by module_id
|
||||
\param module_id index of MAC instance(s)*/
|
||||
|
||||
@@ -97,7 +97,7 @@ void nr_ue_mac_default_configs(NR_UE_MAC_INST_t *mac)
|
||||
// default values as defined in 38.331 sec 9.2.2
|
||||
|
||||
// sf80 default for retxBSR_Timer sf10 for periodicBSR_Timer
|
||||
int mu = mac->current_UL_BWP ? mac->current_UL_BWP->scs : get_softmodem_params()->numerology;
|
||||
int mu = mac->current_UL_BWP ? mac->current_UL_BWP->scs : mac->numerology;
|
||||
int subframes_per_slot = get_slots_per_frame_from_scs(mu) / 10;
|
||||
nr_timer_setup(&mac->scheduling_info.retxBSR_Timer, 80 * subframes_per_slot, 1); // 1 slot update rate
|
||||
nr_timer_setup(&mac->scheduling_info.periodicBSR_Timer, 10 * subframes_per_slot, 1); // 1 slot update rate
|
||||
@@ -130,7 +130,7 @@ NR_UE_L2_STATE_t nr_ue_get_sync_state(module_id_t mod_id)
|
||||
return mac->state;
|
||||
}
|
||||
|
||||
NR_UE_MAC_INST_t *nr_l2_init_ue(int instance_id)
|
||||
NR_UE_MAC_INST_t *nr_l2_init_ue(int instance_id, int numerology)
|
||||
{
|
||||
AssertFatal(instance_id < MAX_NUM_NR_UE_INST, "instance_id %d is out of range\n", instance_id);
|
||||
AssertFatal(nr_ue_mac_inst[instance_id] == NULL, "MAC instance %d already initialized\n", instance_id);
|
||||
@@ -138,12 +138,13 @@ NR_UE_MAC_INST_t *nr_l2_init_ue(int instance_id)
|
||||
|
||||
NR_UE_MAC_INST_t *mac = nr_ue_mac_inst[instance_id];
|
||||
mac->ue_id = instance_id;
|
||||
mac->numerology = numerology;
|
||||
nr_ue_init_mac(mac);
|
||||
int ret = pthread_mutex_init(&mac->if_mutex, NULL);
|
||||
AssertFatal(ret == 0, "Mutex init failed\n");
|
||||
nr_ue_mac_default_configs(mac);
|
||||
if (IS_SA_MODE(get_softmodem_params()))
|
||||
ue_init_config_request(mac, get_slots_per_frame_from_scs(get_softmodem_params()->numerology));
|
||||
ue_init_config_request(mac, get_slots_per_frame_from_scs(numerology));
|
||||
|
||||
static bool initialized = false;
|
||||
if (!initialized) {
|
||||
|
||||
@@ -427,7 +427,7 @@ void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl
|
||||
const NR_UE_DL_BWP_t *current_DL_BWP = mac->current_DL_BWP;
|
||||
NR_BWP_Id_t dl_bwp_id = current_DL_BWP ? current_DL_BWP->bwp_id : 0;
|
||||
NR_BWP_PDCCH_t *pdcch_config = &mac->config_BWP_PDCCH[dl_bwp_id];
|
||||
int scs = current_DL_BWP ? current_DL_BWP->scs : get_softmodem_params()->numerology;
|
||||
int scs = current_DL_BWP ? current_DL_BWP->scs : mac->numerology;
|
||||
const int slots_per_frame = get_slots_per_frame_from_scs(scs);
|
||||
if (mac->get_sib1) {
|
||||
int ssb_sc_offset_norm;
|
||||
|
||||
Reference in New Issue
Block a user