Merge remote-tracking branch 'origin/bwp_switch_fix' into integration_2025_w49 (!3660)

Fixes for BWP switching

This MR fixes some issues when performing BWP switching via
reconfiguration. It also adds a CI test for BWP switching.  # Please
enter a commit message to explain why this merge is necessary,
This commit is contained in:
Robert Schmidt
2025-12-03 17:31:22 +01:00
23 changed files with 399 additions and 370 deletions
@@ -146,7 +146,11 @@ gNBs =
);
first_active_bwp = 1;
bwp_list = ({ scs = 1; bwpStart = 0; bwpSize = 106;});
bwp_list = (
{ scs = 1; bwpStart = 0; bwpSize = 106;},
{ scs = 1; bwpStart = 0; bwpSize = 36;},
{ scs = 1; bwpStart = 36; bwpSize = 70;}
);
# ------- SCTP definitions
SCTP :
@@ -30,20 +30,28 @@
310000
800813
330101
330102
330103
310001
400001
350000
370001
370000
370002
370003
370004
370002
360001
100002
360002
350000
410002
370012
400002
410003
370013
400003
410000
350000
400000
410001
350000
400001
310011
310002
330201
@@ -88,24 +96,10 @@
</testCase>
<testCase id="330101">
<class>Deploy_Object</class>
<desc>Deploy gNB-CU-CP in a container</desc>
<desc>Deploy gNB-CU-CP/gNB-CU-UP/gNB-DU (TDD/n76/40MHz/B200)</desc>
<node>ofqot</node>
<yaml_path>ci-scripts/yaml_files/sa_e1_b200_gnb</yaml_path>
<services>gnb_cucp</services>
</testCase>
<testCase id="330102">
<class>Deploy_Object</class>
<desc>Deploy gNB-CU-UP in a container</desc>
<node>ofqot</node>
<yaml_path>ci-scripts/yaml_files/sa_e1_b200_gnb</yaml_path>
<services>gnb_cuup</services>
</testCase>
<testCase id="330103">
<class>Deploy_Object</class>
<desc>Deploy gNB-DU (TDD/Band78/40MHz/B200) in a container</desc>
<node>ofqot</node>
<yaml_path>ci-scripts/yaml_files/sa_e1_b200_gnb</yaml_path>
<services>gnb_du_tdd</services>
<services>gnb_cucp gnb_cuup gnb_du_tdd</services>
</testCase>
<testCase id="300000">
@@ -132,16 +126,6 @@
<ping_rttavg_threshold>25</ping_rttavg_threshold>
</testCase>
<testCase id="370000">
<class>Iperf</class>
<desc>iperf (DL/80Mbps/UDP)(30 sec)</desc>
<iperf_args>-u -b 80M -t 30 -R</iperf_args>
<id>idefix</id>
<svr_id>sabox-nepes</svr_id>
<iperf_packetloss_threshold>10</iperf_packetloss_threshold>
<iperf_bitrate_threshold>95</iperf_bitrate_threshold>
</testCase>
<testCase id="400001">
<class>Custom_Command</class>
<desc>Check UE is on dedicated BWP ID 1</desc>
@@ -149,19 +133,76 @@
<command>echo ci get_current_bwp | nc -N 127.0.0.1 9091 | grep 'DL BWP ID 1 (dedicated) UL BWP ID 1 (dedicated)'</command>
</testCase>
<testCase id="370001">
<testCase id="410001">
<class>Custom_Command</class>
<desc>Switch to dedicated BWP ID 1</desc>
<node>ofqot</node>
<command>echo ci trigger_bwp_switch 1 | nc -N 127.0.0.1 9091 | grep 'triggered BWP switch to BWP ID 1 for UE'</command>
</testCase>
<testCase id="400000">
<class>Custom_Command</class>
<desc>Check UE is on initial BWP ID 0</desc>
<node>ofqot</node>
<command>echo ci get_current_bwp | nc -N 127.0.0.1 9091 | grep 'DL BWP ID 0 (initial) UL BWP ID 0 (initial)'</command>
</testCase>
<testCase id="410002">
<class>Custom_Command</class>
<desc>Switch to dedicated BWP ID 2</desc>
<node>ofqot</node>
<command>echo ci trigger_bwp_switch 2 | nc -N 127.0.0.1 9091 | grep 'triggered BWP switch to BWP ID 2 for UE'</command>
</testCase>
<testCase id="370012">
<class>Iperf</class>
<desc>iperf (UL/8Mbps/UDP)(30 sec)</desc>
<iperf_args>-u -b 8M -t 30</iperf_args>
<desc>iperf (DL/TCP)(10 sec)(single-ue profile)</desc>
<iperf_args>-t 10 -R</iperf_args>
<id>idefix</id>
<svr_id>sabox-nepes</svr_id>
<iperf_packetloss_threshold>1</iperf_packetloss_threshold>
<iperf_bitrate_threshold>95</iperf_bitrate_threshold>
<iperf_tcp_rate_target>35</iperf_tcp_rate_target>
</testCase>
<testCase id="400002">
<class>Custom_Command</class>
<desc>Check UE is on dedicated BWP ID 2</desc>
<node>ofqot</node>
<command>echo ci get_current_bwp | nc -N 127.0.0.1 9091 | grep 'DL BWP ID 2 (dedicated) UL BWP ID 2 (dedicated)'</command>
</testCase>
<testCase id="410003">
<class>Custom_Command</class>
<desc>Switch to dedicated BWP ID 3</desc>
<node>ofqot</node>
<command>echo ci trigger_bwp_switch 3 | nc -N 127.0.0.1 9091 | grep 'triggered BWP switch to BWP ID 3 for UE'</command>
</testCase>
<testCase id="370013">
<class>Iperf</class>
<desc>iperf (DL/TCP)(10 sec)(single-ue profile)</desc>
<iperf_args>-t 10 -R</iperf_args>
<id>idefix</id>
<svr_id>sabox-nepes</svr_id>
<iperf_tcp_rate_target>85</iperf_tcp_rate_target>
</testCase>
<testCase id="400003">
<class>Custom_Command</class>
<desc>Check UE is on dedicated BWP ID 3</desc>
<node>ofqot</node>
<command>echo ci get_current_bwp | nc -N 127.0.0.1 9091 | grep 'DL BWP ID 3 (dedicated) UL BWP ID 3 (dedicated)'</command>
</testCase>
<testCase id="410000">
<class>Custom_Command</class>
<desc>Switch to initial BWP ID 0</desc>
<node>ofqot</node>
<command>echo ci trigger_bwp_switch 0 | nc -N 127.0.0.1 9091 | grep 'triggered BWP switch to BWP ID 0 for UE'</command>
</testCase>
<testCase id="370002">
<class>Iperf</class>
<desc>iperf (BIDIR TCP)(10 sec)(single-ue profile)</desc>
<desc>iperf (BIDIR TCP)(20 sec)(single-ue profile)</desc>
<iperf_args>-t 20 --bidir</iperf_args>
<id>idefix</id>
<svr_id>sabox-nepes</svr_id>
@@ -169,17 +210,17 @@
<testCase id="370003">
<class>Iperf</class>
<desc>iperf (DL/TCP)(30 sec)(single-ue profile)</desc>
<iperf_args>-t 30 -R</iperf_args>
<desc>iperf (DL/TCP)(20 sec)(single-ue profile)</desc>
<iperf_args>-t 20 -R</iperf_args>
<id>idefix</id>
<svr_id>sabox-nepes</svr_id>
<iperf_tcp_rate_target>30</iperf_tcp_rate_target>
<iperf_tcp_rate_target>140</iperf_tcp_rate_target>
</testCase>
<testCase id="370004">
<class>Iperf</class>
<desc>iperf (UL/TCP)(30 sec)(single-ue profile)</desc>
<iperf_args>-t 30</iperf_args>
<desc>iperf (UL/TCP)(20 sec)(single-ue profile)</desc>
<iperf_args>-t 20</iperf_args>
<id>idefix</id>
<svr_id>sabox-nepes</svr_id>
<iperf_tcp_rate_target>15</iperf_tcp_rate_target>
+22
View File
@@ -38,6 +38,7 @@
#include "openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h"
#include "openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h"
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
#include "openair2/LAYER2/NR_MAC_gNB/mac_config.h"
#include "openair2/RRC/NR/rrc_gNB_mobility.h"
#include "openair3/NGAP/ngap_gNB_ue_context.h"
@@ -276,6 +277,8 @@ static int get_current_bwp(char *buf, int debug, telnet_printfunc_t prnt)
if (rnti < 0)
ERROR_MSG_RET("could not identify UE (no UE, no such RNTI, or multiple UEs)\n");
NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[0]->UE_info, rnti);
if (!UE)
ERROR_MSG_RET("could not find UE with RNTI %04x\n", rnti);
int dl_bwp = UE->current_DL_BWP.bwp_id;
const char *dl_bwp_text = dl_bwp > 0 ? "dedicated" : "initial";
int ul_bwp = UE->current_UL_BWP.bwp_id;
@@ -365,6 +368,24 @@ static int trigger_ngap_pdu_session_release(char *buf, int debug, telnet_printfu
return 0;
}
static int trigger_bwp_switch(char *buf, int debug, telnet_printfunc_t prnt)
{
char *sbwpId = strtok(buf, " ");
int bwpId = atoi(sbwpId);
char *srnti = strtok(NULL, " ");
prnt("bwpId %d rnti %s\n", bwpId, srnti);
int rnti = fetch_rnti(srnti, prnt);
if (rnti < 0)
ERROR_MSG_RET("could not identify UE (no UE, no such RNTI, or multiple UEs)\n");
if (!nr_trigger_bwp_switch(rnti, bwpId)) {
prnt("failed trigger BWP switch for UE %04x BWP ID %d\n", rnti, bwpId);
return -1;
} else {
prnt("triggered BWP switch to BWP ID %d for UE %04x\n", bwpId, rnti);
return 0;
}
}
static telnetshell_cmddef_t cicmds[] = {
{"get_single_rnti", "", get_single_rnti},
{"force_reestab", "[rnti(hex,opt)]", trigger_reestab},
@@ -374,6 +395,7 @@ static telnetshell_cmddef_t cicmds[] = {
{"trigger_f1_ho", "[rrc_ue_id(int,opt)]", rrc_gNB_trigger_f1_ho},
{"fetch_du_by_ue_id", "[rrc_ue_id(int,opt)]", fetch_du_by_ue_id},
{"get_current_bwp", "[rnti(hex,opt)]", get_current_bwp},
{"trigger_bwp_switch", "newBWPId [rnti(hex,opt)]", trigger_bwp_switch},
{"trigger_n2_ho", "[neighbour_pci(uint32_t),ueId(uint32_t)]", rrc_gNB_trigger_n2_ho},
{"pdu_session_release", "[gNB_ue_ngap_id(int,opt)]", trigger_ngap_pdu_session_release},
{"", "", NULL},
+26
View File
@@ -420,3 +420,29 @@ Note that you should increase the aggregation level candidates as described in
[the corresponding section above](#pdcch-aggregation-level). This is because the
scheduler has to schedule multiple DCIs in a single DL slots for multiple UL
slots. As a suggestion, you could try `uess_agg_levels = [4, 2, 2, 0, 0]`.
## Multiple Dedicated BWPs
A maximum of 4 dedicated BWPs can be configured for a UE per standard, but only
1 BWP can be active in UL and DL direction at a given time. In the code we
only configure a single BWP for the UE at a given time and we would switch by
reconfiguring this BWP. All this procedure is transparent for users and LOGs
mark BWP switching according to the configuration file enumeration. It is
possible to configure multiple dedicated BWPs and 1st active BWP via
configuration file.
### Setup of the Configuration files ##
In the configuration file you have the option to select the 1st active BWP, the
BWP location and SCS of each BWP in the following way (example with 2
additional BWPs):
```
first_active_bwp = 1;
bwp_list = ({ scs = 1; bwpStart = 0; bwpSize = 106;},
{ scs = 1; bwpStart = 0; bwpSize = 24;});
```
This example configures 3 additional BWPs, with IDs from 1 to 3. A similar
example can be found in configuration file
`ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf` tested in CI.
-44
View File
@@ -1,44 +0,0 @@
# Procedure to add dedicated Bandwidth part (BWP)
## Contributed by 5G Testbed IISc
### Developers: Abhijith A, Shruthi S
# Terminology #
## Bandwidth part (BWP) ##
Bandwidth Part (BWP) is a set of contiguous Resource Blocks in the resource grid.
Parameters of a BWP are communicated to UE using RRC parameters: BWP-Downlink and BWP-Uplink.
A UE can be configured with a set of 4 BWPs in uplink (UL) and downlink (DL) direction (3GPP TS 38.331 Annex B.2 Description of BWP configuration options). But only 1 BWP can be active in UL and DL direction at a given time.
# Procedure to run multiple dedicated BWPs #
A maximum of 4 dedicated BWPs can be configured for a UE.
To configure multiple BWPs, add the following parameters in the physical parameters section:
## Setup of the Configuration files ##
In the configuration file you have the option to select the 1st active BWP, the RIV and SCS of each BWP in the following way (example with 3 additional BWPs):
```
first_active_bwp = 1;
bwp_list = ({ scs = 1; bwpStart = 0; bwpSize = 106;},
{ scs = 1; bwpStart = 0; bwpSize = 51;},
{ scs = 1; bwpStart = 0; bwpSize = 24;});
```
This example configures 3 additional BWPs, with IDs from 1 to 3. Find these parameters in this configuration file: "ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf"
# Testing gNB and UE in RF simulator
## gNB command:
```
sudo ./nr-softmodem -O ../../../ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf --rfsim --rfsimulator.serveraddr server
```
## UE command:
```
sudo ./nr-uesoftmodem -C 3319680000 -r 106 --numerology 1 --ssb 516 --band 78 --rfsim --rfsimulator.serveraddr 127.0.0.1
```
+9 -8
View File
@@ -1368,7 +1368,7 @@ void nfapi_stop_l1()
}
}
static void get_bwp_config(nr_mac_config_t *configuration)
static void get_bwp_config(nr_mac_config_t *configuration, const NR_ServingCellConfigCommon_t *scc)
{
char path[MAX_OPTNAME_SIZE * 2 + 8];
snprintf(path, sizeof(path), "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0);
@@ -1377,10 +1377,13 @@ static void get_bwp_config(nr_mac_config_t *configuration)
AssertFatal(configuration->num_additional_bwps >= 0 && configuration->num_additional_bwps <= 4,
"Invalid number of additional BWPs %d\n",
configuration->num_additional_bwps);
int bw = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth;
for (int i = 0; i < configuration->num_additional_bwps; i++) {
configuration->bwp_config[i].id = i + 1;
int bwp_start = *BWPParamList.paramarray[i][GNB_BWP_START_IDX].iptr;
AssertFatal(bwp_start >= 0 && bwp_start < bw, "Invalid BWP start value %d\n", bwp_start);
int bwp_size = *BWPParamList.paramarray[i][GNB_BWP_SIZE_IDX].iptr;
AssertFatal(bwp_start + bwp_size <= bw, "BWP start %d and BWP size %d exceeds full BW %d\n", bwp_start, bwp_size, bw);
configuration->bwp_config[i].location_and_bw = PRBalloc_to_locationandbandwidth(bwp_size, bwp_start);
configuration->bwp_config[i].scs = *BWPParamList.paramarray[i][GNB_BWP_SCS_IDX].iptr;
LOG_I(GNB_APP,
@@ -1418,12 +1421,6 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
config.pdsch_AntennaPorts.XP,
config.pusch_AntennaPorts);
// BWP
get_bwp_config(&config);
AssertFatal(config.num_additional_bwps <= 4, "Impossible to configure more than 4 additional BWPs\n");
config.first_active_bwp = *GNBParamList.paramarray[0][GNB_1ST_ACTIVE_BWP_IDX].iptr;
AssertFatal(config.first_active_bwp <= config.num_additional_bwps, "1st active BWP does not belog to the configured BWPs\n");
// RU
GET_PARAMS_LIST(RUParamList, RUParams, RUPARAMS_DESC, CONFIG_STRING_RU_LIST, NULL);
int num_tx = 0;
@@ -1524,7 +1521,11 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
config.num_agg_level_candidates[PDCCH_AGG_LEVEL16]);
NR_ServingCellConfigCommon_t *scc = get_scc_config(cfg, config.minRXTXTIME, config.do_SRS);
//xer_fprint(stdout, &asn_DEF_NR_ServingCellConfigCommon, scc);
// BWP
get_bwp_config(&config, scc);
AssertFatal(config.num_additional_bwps <= 4, "Impossible to configure more than 4 additional BWPs\n");
config.first_active_bwp = *GNBParamList.paramarray[0][GNB_1ST_ACTIVE_BWP_IDX].iptr;
AssertFatal(config.first_active_bwp <= config.num_additional_bwps, "1st active BWP does not belog to the configured BWPs\n");
if (MacRLC_ParamList.numelt > 0) {
/* NR RLC config is needed by mac_top_init_gNB() */
@@ -2781,7 +2781,6 @@ uint16_t nr_dci_size(const NR_UE_DL_BWP_t *DL_BWP,
nr_dci_format_t format,
nr_rnti_type_t rnti_type,
NR_ControlResourceSet_t *coreset,
int bwp_id,
int ss_type,
uint16_t cset0_bwp_size,
uint16_t alt_size)
@@ -159,7 +159,6 @@ uint16_t nr_dci_size(const NR_UE_DL_BWP_t *DL_BWP,
nr_dci_format_t format,
nr_rnti_type_t rnti_type,
NR_ControlResourceSet_t *coreset,
int bwp_id,
int ss_type,
uint16_t cset0_bwp_size,
uint16_t alt_size);
@@ -198,7 +198,6 @@ static void config_dci_pdu(NR_UE_MAC_INST_t *mac,
NR_UL_DCI_FORMAT_0_0,
rnti_type,
coreset,
dl_bwp_id,
ss->searchSpaceType->present,
mac->type0_PDCCH_CSS_config.num_rbs,
0);
@@ -211,7 +210,6 @@ static void config_dci_pdu(NR_UE_MAC_INST_t *mac,
NR_DL_DCI_FORMAT_1_0,
rnti_type,
coreset,
dl_bwp_id,
ss->searchSpaceType->present,
mac->type0_PDCCH_CSS_config.num_rbs,
0);
@@ -225,7 +223,6 @@ static void config_dci_pdu(NR_UE_MAC_INST_t *mac,
dci_format[i],
rnti_type,
coreset,
dl_bwp_id,
ss->searchSpaceType->present,
mac->type0_PDCCH_CSS_config.num_rbs,
alt_size);
+1 -2
View File
@@ -586,11 +586,10 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
pusch_config_pdu->pusch_uci.harq_ack_bit_length = 0;
pusch_config_pdu->bwp_start = current_UL_BWP->BWPStart;
if (dci_format == NR_UL_DCI_FORMAT_0_0 && ss_type == NR_SearchSpace__searchSpaceType_PR_common) {
pusch_config_pdu->bwp_start = sc_info->initial_ul_BWPStart;
pusch_config_pdu->bwp_size = sc_info->initial_ul_BWPSize;
} else {
pusch_config_pdu->bwp_start = current_UL_BWP->BWPStart;
pusch_config_pdu->bwp_size = current_UL_BWP->BWPSize;
}
+21 -2
View File
@@ -1065,6 +1065,24 @@ bool nr_update_sib19(const gnb_sat_position_update_t *sat_position)
return true;
}
bool nr_trigger_bwp_switch(uint16_t rnti, int bwp_id)
{
gNB_MAC_INST *nrmac = RC.nrmac[0];
NR_SCHED_LOCK(&nrmac->sched_lock);
NR_UE_info_t *UE = find_nr_UE(&nrmac->UE_info, rnti);
bool success = false;
if (!UE) {
LOG_W(NR_MAC, "could not find UE for RNTI %04x\n", rnti);
} else if (UE->current_DL_BWP.bwp_id == bwp_id) {
LOG_W(NR_MAC, "UE %04x is already on BWP ID %d, not triggering reconfiguration\n", rnti, bwp_id);
} else { // UE != NULL && current_DL_BWP.bwp_id != bwp_id
nr_mac_trigger_reconfiguration(nrmac, UE, bwp_id);
success = true;
}
NR_SCHED_UNLOCK(&nrmac->sched_lock);
return success;
}
void prepare_du_configuration_update(gNB_MAC_INST *mac,
f1ap_served_cell_info_t *info,
NR_BCCH_BCH_Message_t *mib,
@@ -1116,8 +1134,9 @@ bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t
NR_SCHED_LOCK(&nrmac->sched_lock);
NR_UE_info_t *UE = get_new_nr_ue_inst(&nrmac->UE_info.uid_allocator, rnti, CellGroup);
DevAssert(UE->uid < MAX_MOBILES_PER_GNB); // test-mode: we assume we can always create a UE
free_and_zero(UE->ra); // test-mode (sims, phy-test): UE will not do RA
DevAssert(UE->uid < MAX_MOBILES_PER_GNB); // physical simulators: we assume we can always create a UE
free_and_zero(UE->ra); // physical simulators: UE will not do RA
UE->local_bwp_id = 1; // for physical simulators
bool res = add_connected_nr_ue(nrmac, UE);
if (!res) {
LOG_E(NR_MAC, "Error adding UE %04x\n", rnti);
@@ -958,7 +958,6 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP,
&uldci_payload,
NR_UL_DCI_FORMAT_0_0,
TYPE_TC_RNTI_,
ul_bwp->bwp_id,
ss,
coreset,
0, // parameter not needed for DCI 0_0
@@ -1385,7 +1384,6 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac,
&dci_payload,
NR_DL_DCI_FORMAT_1_0,
rnti_type,
dl_bwp->bwp_id,
sched_ctrl->search_space,
coreset,
0, // parameter not needed for DCI 1_0
@@ -473,7 +473,6 @@ static void nr_fill_nfapi_dl_SIB_pdu(gNB_MAC_INST *gNB_mac,
&dci_payload,
dci_format,
rnti_type,
0,
search_space,
coreset,
0,
@@ -398,7 +398,8 @@ bwp_info_t get_pdsch_bwp_start_size(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE)
// except for the case when DCI format 1_0 is decoded in any common search space in which case the size of CORESET 0 shall be
// used if CORESET 0 is configured for the cell and the size of initial DL bandwidth part shall be used if CORESET 0 is not
// configured for the cell.
if (dl_bwp->dci_format == NR_DL_DCI_FORMAT_1_0 && sched_ctrl->search_space->searchSpaceType
if (dl_bwp->dci_format == NR_DL_DCI_FORMAT_1_0
&& sched_ctrl->search_space->searchSpaceType
&& sched_ctrl->search_space->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_common) {
if (sched_ctrl->coreset->controlResourceSetId == 0) {
bwp_info.bwpStart = nr_mac->cset0_bwp_start;
@@ -406,9 +407,9 @@ bwp_info_t get_pdsch_bwp_start_size(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE)
bwp_info.bwpStart = dl_bwp->BWPStart + sched_ctrl->sched_pdcch.rb_start;
}
if (nr_mac->cset0_bwp_size > 0) {
bwp_info.bwpSize = min(dl_bwp->BWPSize - bwp_info.bwpStart, nr_mac->cset0_bwp_size);
bwp_info.bwpSize = min(dl_bwp->BWPSize, nr_mac->cset0_bwp_size);
} else {
bwp_info.bwpSize = min(dl_bwp->BWPSize - bwp_info.bwpStart, UE->sc_info.initial_dl_BWPSize);
bwp_info.bwpSize = min(dl_bwp->BWPSize, UE->sc_info.initial_dl_BWPSize);
}
} else {
bwp_info.bwpSize = dl_bwp->BWPSize;
@@ -592,6 +593,21 @@ static bool allocate_dl_retransmission(gNB_MAC_INST *nr_mac,
return true;
}
static void ack_reconfig(gNB_MAC_INST *mac, NR_UE_info_t *UE)
{
if (UE->reconfigSpCellConfig) {
// in case of reestablishment, the spCellConfig had to be released
// temporarily. Reapply now before doing the reconfiguration.
UE->CellGroup->spCellConfig = UE->reconfigSpCellConfig;
// UE->reconfigSpCellConfig to be NULLed after receiving reconfiguration complete
}
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
/* clean BWP structures */
clean_bwp_structures(UE->CellGroup->spCellConfig);
configure_UE_BWP(mac, scc, UE, false, NR_SearchSpace__searchSpaceType_PR_common, -1, -1);
UE->await_reconfig = false;
}
typedef struct UEsched_s {
float coef;
NR_UE_info_t * UE;
@@ -866,6 +882,12 @@ static void pf_dl(gNB_MAC_INST *mac,
.tda_info = tda_info,
};
sched_pdsch.action = NULL;
int srb1 = 1;
/* everything that's only 3 bytes is an ack. To be safe, use a bit more. */
if (iterator->UE->await_reconfig && sched_ctrl->rlc_status[srb1].bytes_in_buffer > 10)
sched_pdsch.action = ack_reconfig;
// Fix me: currently, the RLC does not give us the total number of PDUs
// awaiting. Therefore, for the time being, we put a fixed overhead of 12
// (for 4 PDUs) and optionally + 2 for TA. Once RLC gives the number of
@@ -1191,7 +1213,6 @@ void post_process_dlsch(gNB_MAC_INST *nr_mac, post_process_pdsch_t *pdsch, NR_UE
&dci_payload,
current_BWP->dci_format,
rnti_type,
bwp_id,
sched_ctrl->search_space,
sched_ctrl->coreset,
UE->pdsch_HARQ_ACK_Codebook,
@@ -907,8 +907,10 @@ dci_pdu_rel15_t prepare_dci_dl_payload(const gNB_MAC_INST *gNB_mac,
dci_payload.dai[0].val = pucch ? (pucch->dai_c - 1) & 3 : 0;
// bwp indicator
// as per table 7.3.1.1.2-1 in 38.212
if (dl_BWP)
dci_payload.bwp_indicator.val = UE->sc_info.n_dl_bwp < 4 ? dl_BWP->bwp_id : dl_BWP->bwp_id - 1;
if (dl_BWP) {
int ext_bwp_id = dl_BWP->bwp_id ? 1 : 0; // BWP-ID sent to the UE is always 1 except for BWP 0
dci_payload.bwp_indicator.val = UE->sc_info.n_dl_bwp < 4 ? ext_bwp_id : ext_bwp_id - 1;
}
return dci_payload;
}
@@ -1182,7 +1184,6 @@ void config_uldci(const NR_UE_ServingCell_Info_t *sc_info,
NR_UE_UL_BWP_t *ul_bwp,
NR_SearchSpace__searchSpaceType_PR ss_type)
{
int bwp_id = ul_bwp->bwp_id;
nr_dci_format_t dci_format = ul_bwp->dci_format;
// 3GPP TS 38.214 Section 6.1.2.2.2 Uplink resource allocation type 1
@@ -1214,7 +1215,8 @@ void config_uldci(const NR_UE_ServingCell_Info_t *sc_info,
LOG_D(NR_MAC,"Configuring DCI Format 0_1\n");
dci_pdu_rel15->dai[0].val = 0; //TODO
// bwp indicator as per table 7.3.1.1.2-1 in 38.212
dci_pdu_rel15->bwp_indicator.val = sc_info->n_ul_bwp < 4 ? bwp_id : bwp_id - 1;
int ext_bwp_id = ul_bwp->bwp_id ? 1 : 0; // BWP-ID sent to the UE is always 1 except for BWP 0
dci_pdu_rel15->bwp_indicator.val = sc_info->n_ul_bwp < 4 ? ext_bwp_id : ext_bwp_id - 1;
// SRS resource indicator
if (pusch_Config && pusch_Config->txConfig != NULL) {
AssertFatal(*pusch_Config->txConfig == NR_PUSCH_Config__txConfig_codebook,
@@ -1640,7 +1642,6 @@ void fill_dci_pdu_rel15(const NR_UE_ServingCell_Info_t *servingCellInfo,
dci_pdu_rel15_t *dci_pdu_rel15,
int dci_format,
int rnti_type,
int bwp_id,
NR_SearchSpace_t *ss,
NR_ControlResourceSet_t *coreset,
long pdsch_HARQ_ACK_Codebook,
@@ -1671,7 +1672,6 @@ void fill_dci_pdu_rel15(const NR_UE_ServingCell_Info_t *servingCellInfo,
NR_UL_DCI_FORMAT_0_0,
rnti_type,
coreset,
bwp_id,
ss->searchSpaceType->present,
cset0_bwp_size,
0);
@@ -1685,7 +1685,6 @@ void fill_dci_pdu_rel15(const NR_UE_ServingCell_Info_t *servingCellInfo,
NR_DL_DCI_FORMAT_1_0,
rnti_type,
coreset,
bwp_id,
ss->searchSpaceType->present,
cset0_bwp_size,
0);
@@ -1702,10 +1701,10 @@ void fill_dci_pdu_rel15(const NR_UE_ServingCell_Info_t *servingCellInfo,
dci_format,
rnti_type,
coreset,
bwp_id,
ss->searchSpaceType->present,
cset0_bwp_size,
alt_size);
if (dci_size == 0)
return;
pdcch_dci_pdu->PayloadSizeBits = dci_size;
@@ -2703,38 +2702,26 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
AssertFatal(dl_bwp_switch == ul_bwp_switch, "Different UL and DL BWP not supported\n");
DL_BWP->bwp_id = dl_bwp_switch;
UL_BWP->bwp_id = ul_bwp_switch;
UE->local_bwp_id = dl_bwp_switch; // assuming they are the same
} else {
// (re)configuring BWP
// TODO BWP switching not via RRC reconfiguration
// via RRC if firstActiveXlinkBWP_Id is NULL, MAC stays on the same BWP as before
if (servingCellConfig->firstActiveDownlinkBWP_Id)
DL_BWP->bwp_id = *servingCellConfig->firstActiveDownlinkBWP_Id;
if (servingCellConfig->uplinkConfig->firstActiveUplinkBWP_Id)
UL_BWP->bwp_id = *servingCellConfig->uplinkConfig->firstActiveUplinkBWP_Id;
DL_BWP->bwp_id = UE->local_bwp_id;
UL_BWP->bwp_id = UE->local_bwp_id;
}
const struct NR_ServingCellConfig__downlinkBWP_ToAddModList *bwpList = servingCellConfig->downlinkBWP_ToAddModList;
if(bwpList)
sc_info->n_dl_bwp = bwpList->list.count;
if (DL_BWP->bwp_id>0) {
for (int i=0; i<bwpList->list.count; i++) {
dl_bwp = bwpList->list.array[i];
if(dl_bwp->bwp_Id == DL_BWP->bwp_id)
break;
}
AssertFatal(dl_bwp!=NULL,"Couldn't find DLBWP corresponding to BWP ID %ld\n",DL_BWP->bwp_id);
sc_info->n_dl_bwp = 1;
if (DL_BWP->bwp_id > 0) {
dl_bwp = bwpList->list.array[0];
AssertFatal(dl_bwp, "Couldn't find DLBWP corresponding to BWP ID %ld\n", DL_BWP->bwp_id);
}
const struct NR_UplinkConfig__uplinkBWP_ToAddModList *ubwpList = servingCellConfig->uplinkConfig->uplinkBWP_ToAddModList;
if(ubwpList)
sc_info->n_ul_bwp = ubwpList->list.count;
if (UL_BWP->bwp_id>0) {
for (int i=0; i<ubwpList->list.count; i++) {
ul_bwp = ubwpList->list.array[i];
if(ul_bwp->bwp_Id == UL_BWP->bwp_id)
break;
}
AssertFatal(ul_bwp!=NULL,"Couldn't find ULBWP corresponding to BWP ID %ld\n",UL_BWP->bwp_id);
sc_info->n_ul_bwp = 1;
if (UL_BWP->bwp_id > 0) {
ul_bwp = ubwpList->list.array[0];
AssertFatal(ul_bwp, "Couldn't find ULBWP corresponding to BWP ID %ld\n", UL_BWP->bwp_id);
}
// selection of dedicated BWPs
@@ -2762,12 +2749,12 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
}
// TDA lists
if (DL_BWP->bwp_id>0)
if (DL_BWP->bwp_id > 0)
DL_BWP->tdaList_Common = dl_bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList;
else
DL_BWP->tdaList_Common = scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList;
if(UL_BWP->bwp_id>0)
if(UL_BWP->bwp_id > 0)
UL_BWP->tdaList_Common = ul_bwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList;
else
UL_BWP->tdaList_Common = scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList;
@@ -3217,9 +3204,10 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, slot_t slot, nfapi_nr_dl_tt
NR_NZP_CSI_RS_ResourceSetId_t *nzp = NULL;
for (int csi_list=0; csi_list<csi_measconfig->csi_ResourceConfigToAddModList->list.count; csi_list++) {
NR_CSI_ResourceConfig_t *csires = csi_measconfig->csi_ResourceConfigToAddModList->list.array[csi_list];
if(csires->bwp_Id == dl_bwp->bwp_id &&
csires->csi_RS_ResourceSetList.present == NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB &&
csires->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList) {
if (csires->bwp_Id > 1)
LOG_E(NR_MAC, "Invalid CSI resource BWP ID %ld, we only configure BWP up to 1\n", csires->bwp_Id);
else if (csires->csi_RS_ResourceSetList.present == NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB &&
csires->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList) {
nzp = csires->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.array[0];
}
}
@@ -3456,46 +3444,11 @@ void nr_measgap_scheduling(gNB_MAC_INST *nr_mac, frame_t frame, sub_frame_t slot
void clean_bwp_structures(NR_SpCellConfig_t *spCellConfig)
{
NR_ServingCellConfig_t *spCellConfigDedicated = spCellConfig->spCellConfigDedicated;
if (spCellConfigDedicated->downlinkBWP_ToReleaseList) {
struct NR_ServingCellConfig__downlinkBWP_ToReleaseList *rel_dl = spCellConfigDedicated->downlinkBWP_ToReleaseList;
struct NR_ServingCellConfig__downlinkBWP_ToAddModList *add_dl = spCellConfigDedicated->downlinkBWP_ToAddModList;
int num_rel = rel_dl->list.count;
int num_add = add_dl->list.count;
for (int i = 0; i < num_rel; i++) {
NR_BWP_Id_t *rel_id = rel_dl->list.array[i];
for (int j = 0; j < num_add; j++) {
NR_BWP_Downlink_t *dl_bwp = add_dl->list.array[j];
if (*rel_id == dl_bwp->bwp_Id) {
asn_sequence_del(&add_dl->list, j, 1);
}
}
asn_sequence_del(&rel_dl->list, i, 1);
}
if (rel_dl->list.count == 0)
free_and_zero(rel_dl);
if (add_dl->list.count == 0)
free_and_zero(add_dl);
}
if (spCellConfigDedicated->uplinkConfig->uplinkBWP_ToReleaseList) {
struct NR_UplinkConfig__uplinkBWP_ToReleaseList *rel_ul = spCellConfigDedicated->uplinkConfig->uplinkBWP_ToReleaseList;
struct NR_UplinkConfig__uplinkBWP_ToAddModList *add_ul = spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList;
int num_rel = rel_ul->list.count;
int num_add = add_ul->list.count;
for (int i = 0; i < num_rel; i++) {
NR_BWP_Id_t *rel_id = rel_ul->list.array[i];
for (int j = 0; j < num_add; j++) {
NR_BWP_Uplink_t *ul_bwp = add_ul->list.array[j];
if (*rel_id == ul_bwp->bwp_Id) {
asn_sequence_del(&add_ul->list, j, 1);
}
}
asn_sequence_del(&rel_ul->list, i, 1);
}
if (rel_ul->list.count == 0)
free_and_zero(rel_ul);
if (add_ul->list.count == 0)
free_and_zero(add_ul);
}
if (spCellConfigDedicated->downlinkBWP_ToAddModList && spCellConfigDedicated->downlinkBWP_ToAddModList->list.count > 1)
asn_sequence_del(&spCellConfigDedicated->downlinkBWP_ToAddModList->list, 0, 1);
if (spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList
&& spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count > 1)
asn_sequence_del(&spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list, 0, 1);
}
void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group)
@@ -3517,8 +3470,6 @@ void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group)
/* remove reestablishRLC, we don't need it anymore */
for (int i = 0; i < cell_group->rlc_BearerToAddModList->list.count; ++i)
free_and_zero(cell_group->rlc_BearerToAddModList->list.array[i]->reestablishRLC);
/* clean BWP structures */
clean_bwp_structures(spCellConfig);
}
int nr_mac_get_reconfig_delay_slots(NR_SubcarrierSpacing_t scs)
@@ -3818,6 +3769,7 @@ bool prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE)
NR_CellGroupConfig_t *cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, &mac->radio_config, &mac->rlc_config);
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
UE->CellGroup = cellGroupConfig;
UE->local_bwp_id = mac->radio_config.first_active_bwp;
if (!cellGroupConfig)
return true;
@@ -3922,15 +3874,35 @@ bool nr_mac_check_ul_failure(gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ctrl_t *
return false;
}
void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, const NR_UE_info_t *UE, int new_bwp_id)
static bool verify_bwp_switch(const NR_UE_info_t *UE, const nr_mac_config_t *configuration, int new_bwp_id)
{
if (new_bwp_id == UE->current_DL_BWP.bwp_id) {
LOG_E(NR_MAC, "Source BWP ID and target BWP ID are the same, can't perform switch\n");
return false;
}
if (new_bwp_id == 0)
return true;
for (int i = 0; i < configuration->num_additional_bwps; i++) {
const nr_bwp_config_t *bwp_config = &configuration->bwp_config[i];
if (bwp_config->id == new_bwp_id)
return true;
}
LOG_E(NR_MAC, "New BWP %d does not belong to the list of configured BWPs, can't perform switch\n", new_bwp_id);
return false;
}
void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, NR_UE_info_t *UE, int new_bwp_id)
{
DevAssert(UE->CellGroup != NULL);
NR_CellGroupConfig_t *cellGroup_for_UE = NULL;
if (new_bwp_id >= 0) {
AssertFatal(UE->current_DL_BWP.bwp_id == UE->current_UL_BWP.bwp_id, "We only support same BWP for UL and DL\n");
if (new_bwp_id == UE->current_DL_BWP.bwp_id)
LOG_E(NR_MAC, "Source BWP ID and target BWP ID are the same, can't perform switch\n");
else
if (!verify_bwp_switch(UE, &nrmac->radio_config, new_bwp_id))
return;
else {
UE->sc_info.csi_MeasConfig = NULL; // to avoid segfault when freeing csi_MeasConfig in configDedicated
UE->local_bwp_id = new_bwp_id;
cellGroup_for_UE = update_cellGroupConfig_for_BWP_switch(UE->CellGroup,
&nrmac->radio_config,
UE->capability,
@@ -3938,6 +3910,7 @@ void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, const NR_UE_info_
UE->uid,
UE->current_DL_BWP.bwp_id,
new_bwp_id);
}
}
uint8_t buf[2048];
asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig,
@@ -3946,6 +3919,7 @@ void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, const NR_UE_info_
buf,
sizeof(buf));
AssertFatal(enc_rval.encoded > 0, "ASN1 encoding of CellGroupConfig failed, failed type %s\n", enc_rval.failed_type->name);
UE->await_reconfig = true;
du_to_cu_rrc_information_t du2cu = {
.cellGroupConfig = buf,
.cellGroupConfig_length = (enc_rval.encoded + 7) >> 3,
+12 -11
View File
@@ -253,9 +253,10 @@ void nr_csi_meas_reporting(int Mod_idP,frame_t frame, slot_t slot)
"Only periodic CSI reporting is implemented currently\n");
const NR_PUCCH_CSI_Resource_t *pucchcsires = csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.array[0];
if(pucchcsires->uplinkBandwidthPartId != ul_bwp->bwp_id)
if(pucchcsires->uplinkBandwidthPartId > 1) {
LOG_E(NR_MAC, "Invalid PUCCH BWP ID %ld, we only configure BWP up to 1\n", pucchcsires->uplinkBandwidthPartId);
continue;
}
// we schedule CSI reporting max_fb_time slots in advance
int period, offset;
csi_period_offset(csirep, NULL, &period, &offset);
@@ -393,16 +394,15 @@ int get_pucch_resourceid(NR_PUCCH_Config_t *pucch_Config, int O_uci, int pucch_r
return *resource_id;
}
static void handle_dl_harq(NR_UE_info_t * UE,
int8_t harq_pid,
bool success,
int harq_round_max)
static void handle_dl_harq(gNB_MAC_INST *mac, NR_UE_info_t * UE, int8_t harq_pid, bool success, int harq_round_max)
{
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
NR_UE_harq_t *harq = &sched_ctrl->harq_processes[harq_pid];
harq->feedback_slot = -1;
harq->is_waiting = false;
if (success) {
if (harq->sched_pdsch.action)
harq->sched_pdsch.action(mac, UE);
finish_nr_dl_harq(sched_ctrl, harq_pid);
} else if (harq->round >= harq_round_max - 1) {
abort_nr_dl_harq(UE, harq_pid);
@@ -749,7 +749,6 @@ static void extract_pucch_csi_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR reportQuantity_type_r16 =
NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR_NOTHING;
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP;
NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP;
const int n_slots_frame = nrmac->frame_structure.numb_slots_frame;
int cumul_bits = 0;
@@ -764,8 +763,10 @@ static void extract_pucch_csi_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
NR_CSI_ReportConfig_t *csirep = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id];
uint8_t cqi_table = (dl_bwp->dci_format == NR_DL_DCI_FORMAT_1_1 && csirep->cqi_Table) ? *csirep->cqi_Table : NR_CSI_ReportConfig__cqi_Table_table1;
const NR_PUCCH_CSI_Resource_t *pucchcsires = csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.array[0];
if(pucchcsires->uplinkBandwidthPartId != ul_bwp->bwp_id)
if(pucchcsires->uplinkBandwidthPartId > 1) {
LOG_E(NR_MAC, "Invalid PUCCH BWP ID %ld, we only configure BWP up to 1\n", pucchcsires->uplinkBandwidthPartId);
continue;
}
int period, offset;
csi_period_offset(csirep, NULL, &period, &offset);
// verify if report with current id has been scheduled for this frame and slot
@@ -873,7 +874,7 @@ static NR_UE_harq_t *find_harq(frame_t frame, slot_t slot, NR_UE_info_t * UE, in
frame,
slot);
remove_front_nr_list(&sched_ctrl->feedback_dl_harq);
handle_dl_harq(UE, pid, 0, harq_round_max);
handle_dl_harq(NULL, UE, pid, false, harq_round_max);
pid = sched_ctrl->feedback_dl_harq.head;
if (pid < 0)
return NULL;
@@ -930,7 +931,7 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, frame_t frame, slot_t slot, con
LOG_D(NR_MAC,"%4d.%2d bit %d pid %d ack/nack %d\n",frame, slot, harq_bit,pid,harq_value);
nr_mac_update_pdcch_closed_loop_adjust(sched_ctrl, harq_confidence != 0);
bool success = harq_value == 0 && harq_confidence == 0;
handle_dl_harq(UE, pid, success, nrmac->dl_bler.harq_round_max);
handle_dl_harq(nrmac, UE, pid, success, nrmac->dl_bler.harq_round_max);
if (is_ra) {
bool ue_rejected = nr_check_Msg4_MsgB_Ack(mod_id, frame, slot, UE, success);
if (ue_rejected) {
@@ -1009,7 +1010,7 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, frame_t frame, slot_t slot, c
const int8_t pid = sched_ctrl->feedback_dl_harq.head;
remove_front_nr_list(&sched_ctrl->feedback_dl_harq);
LOG_D(NR_MAC,"%4d.%2d bit %d pid %d ack/nack %d\n",frame, slot, harq_bit, pid, acknack);
handle_dl_harq(UE, pid, uci_234->harq.harq_crc != 1 && acknack, nrmac->dl_bler.harq_round_max);
handle_dl_harq(nrmac, UE, pid, uci_234->harq.harq_crc != 1 && acknack, nrmac->dl_bler.harq_round_max);
}
free(uci_234->harq.harq_payload);
}
@@ -163,7 +163,8 @@ bwp_info_t get_pusch_bwp_start_size(NR_UE_info_t *UE)
// contiguously allocated non-interleaved virtual resource blocks within the active bandwidth part of size PRBs except for the
// case when DCI format 0_0 is decoded in any common search space in which case the size of the initial UL bandwidth part shall
// be used.
if (ul_bwp->dci_format == NR_UL_DCI_FORMAT_0_0 && sched_ctrl->search_space->searchSpaceType
if (ul_bwp->dci_format == NR_UL_DCI_FORMAT_0_0
&& sched_ctrl->search_space->searchSpaceType
&& sched_ctrl->search_space->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_common) {
bwp_info.bwpSize = min(ul_bwp->BWPSize, UE->sc_info.initial_ul_BWPSize);
} else {
@@ -772,10 +773,9 @@ static void nr_rx_ra_sdu(const module_id_t mod_id,
nr_mac_reset_ul_failure(sched_ctrl);
reset_dl_harq_list(sched_ctrl);
reset_ul_harq_list(sched_ctrl);
// we configure the UE using common search space with DCIX0 while waiting for a reconfiguration in SA
// in NSA (or do-ra) there is no reconfiguration in NR
int ss_type = IS_SA_MODE(get_softmodem_params()) ? NR_SearchSpace__searchSpaceType_PR_common
: NR_SearchSpace__searchSpaceType_PR_ue_Specific;
// we configure the UE using dedicated search space: In SA (CFRA used for
// handover) and NSA (or do-ra), the UE has the full config already.
int ss_type = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
configure_UE_BWP(mac, scc, UE, false, ss_type, -1, -1);
// initialize ta_frame in case there is no Msg3 received
UE->UE_sched_ctrl.ta_frame = (frame + 100) % MAX_FRAME_NUMBER;
@@ -2606,7 +2606,6 @@ void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE
&uldci_payload,
current_BWP->dci_format,
TYPE_C_RNTI_,
current_BWP->bwp_id,
ss,
coreset,
UE->pdsch_HARQ_ACK_Codebook,
+2
View File
@@ -43,4 +43,6 @@ typedef struct gnb_sat_position_update_s {
bool nr_update_sib19(const gnb_sat_position_update_t *sat_position);
bool nr_trigger_bwp_switch(uint16_t rnti, int bwp_id);
#endif /*__LAYER2_NR_MAC_CONFIG_H__*/
+1 -2
View File
@@ -258,7 +258,6 @@ void fill_dci_pdu_rel15(const NR_UE_ServingCell_Info_t *servingCellInfo,
dci_pdu_rel15_t *dci_pdu_rel15,
int dci_format,
int rnti_type,
int bwp_id,
NR_SearchSpace_t *ss,
NR_ControlResourceSet_t *coreset,
long pdsch_HARQ_ACK_Codebook,
@@ -478,7 +477,7 @@ void nr_mac_trigger_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpac
void nr_mac_reset_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl);
bool nr_mac_check_ul_failure(gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ctrl_t *sched_ctrl);
void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, const NR_UE_info_t *UE, int new_bwp_id);
void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, NR_UE_info_t *UE, int new_bwp_id);
bool nr_mac_add_lcid(NR_UE_sched_ctrl_t *sched_ctrl, const nr_lc_config_t *c);
nr_lc_config_t *nr_mac_get_lc_config(NR_UE_sched_ctrl_t* sched_ctrl, int lcid);
@@ -576,6 +576,7 @@ static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id, const NR_C
cellGroupConfig->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(UE->rnti, UE->uid, scc, mac->frame);
// TODO: in NSA we assign capabilities here, otherwise outside => not logic
UE->capability = cap;
UE->local_bwp_id = 1; // get_default_secondaryCellGroup sets 1st active BWP as 1
}
// note: we don't pass the cellGroupConfig to add_new_nr_ue() because we need
// the uid to create the CellGroupConfig (which is in the UE context created
@@ -770,9 +771,12 @@ void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req)
} else if (req->reconfig_compl) {
LOG_I(NR_MAC, "DU received confirmation of successful RRC Reconfiguration\n");
if (UE->reconfigSpCellConfig) {
// in case of reestablishment, the spCellConfig had to be released
// temporarily. Reapply now before doing the reconfiguration.
UE->CellGroup->spCellConfig = UE->reconfigSpCellConfig;
if (UE->await_reconfig) {
// in case of reestablishment, the spCellConfig had to be released
// temporarily. Reapply now before doing the reconfiguration.
UE->CellGroup->spCellConfig = UE->reconfigSpCellConfig;
UE->await_reconfig = false;
}
UE->reconfigSpCellConfig = NULL;
for (int i = 1; i < seq_arr_size(&UE->UE_sched_ctrl.lc_config); ++i) {
nr_lc_config_t *c = seq_arr_at(&UE->UE_sched_ctrl.lc_config, i);
@@ -971,6 +975,7 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc)
* reconfiguration has succeeded (indicated by the CU) */
UE->reconfigSpCellConfig = UE->CellGroup->spCellConfig;
UE->CellGroup->spCellConfig = NULL;
UE->await_reconfig = true;
mac_remove_nr_ue(mac, *dl_rrc->old_gNB_DU_ue_id);
pthread_mutex_unlock(&mac->sched_lock);
nr_rlc_remove_ue(dl_rrc->gNB_DU_ue_id);
+11 -1
View File
@@ -475,6 +475,9 @@ typedef struct NR_pdsch_dmrs {
NR_PTRS_DownlinkConfig_t *phaseTrackingRS;
} NR_pdsch_dmrs_t;
struct NR_UE_info;
struct gNB_MAC_INST_s;
typedef void (*feedback_action_t)(struct gNB_MAC_INST_s *mac, struct NR_UE_info *ue);
typedef struct NR_sched_pdsch {
/// RB allocation within active BWP
uint16_t rbSize;
@@ -501,6 +504,7 @@ typedef struct NR_sched_pdsch {
// time_domain_allocation is the index of a list of tda
int time_domain_allocation;
NR_tda_info_t tda_info;
feedback_action_t action;
} NR_sched_pdsch_t;
typedef struct NR_UE_harq {
@@ -772,7 +776,7 @@ typedef struct measgap_config {
} measgap_config_t;
/*! \brief UE list used by gNB to order UEs/CC for scheduling*/
typedef struct {
typedef struct NR_UE_info {
rnti_t rnti;
uid_t uid; // unique ID of this UE
/// scheduling control info
@@ -795,7 +799,13 @@ typedef struct {
float dl_thr_ue;
long pdsch_HARQ_ACK_Codebook;
bool is_redcap;
bool await_reconfig;
NR_RA_t *ra;
// 3GPP mandates that BWPs are enumerated consecutively, but we only send one (dedicated)
// BWP to the UE (and modify that BWP on reconfiguration); consequently, the BWP ID for a
// dedicated BWP is always 1 from the UE's point of view, even if the gNB has multiple BWPs.
// The below ID is the "true" (non-consecutive) BWP ID from the gNB's point of view
NR_BWP_Id_t local_bwp_id;
} NR_UE_info_t;
typedef struct {
+105 -147
View File
@@ -1505,10 +1505,38 @@ static NR_PTRS_UplinkConfig_t *config_ulptrs(const nr_ptrs_config_t *ptrs)
return ulptrs;
}
static NR_SetupRelease_PUSCH_Config_t *config_pusch(const bool use_deltaMCS,
long ue_supported_ul_layers(const NR_UE_NR_Capability_t *uecap)
{
long ul_max_layers = 1;
if (uecap
&& uecap->featureSets
&& uecap->featureSets->featureSetsUplinkPerCC
&& uecap->featureSets->featureSetsUplinkPerCC->list.count > 0) {
NR_FeatureSetUplinkPerCC_t *ul_feature_setup_per_cc = uecap->featureSets->featureSetsUplinkPerCC->list.array[0];
if (ul_feature_setup_per_cc->mimo_CB_PUSCH->maxNumberMIMO_LayersCB_PUSCH) {
switch (*ul_feature_setup_per_cc->mimo_CB_PUSCH->maxNumberMIMO_LayersCB_PUSCH) {
case NR_MIMO_LayersUL_twoLayers:
ul_max_layers = 2;
break;
case NR_MIMO_LayersUL_fourLayers:
ul_max_layers = 4;
break;
default:
ul_max_layers = 1;
}
}
}
return ul_max_layers;
}
static long set_ul_max_layers(const nr_mac_config_t *configuration, const NR_UE_NR_Capability_t *uecap)
{
return min(ue_supported_ul_layers(uecap), configuration->pusch_AntennaPorts);
}
static NR_SetupRelease_PUSCH_Config_t *config_pusch(const nr_mac_config_t *configuration,
const NR_ServingCellConfigCommon_t *scc,
const NR_UE_NR_Capability_t *uecap,
const nr_ptrs_config_t *ptrs)
const NR_UE_NR_Capability_t *uecap)
{
NR_SetupRelease_PUSCH_Config_t *setup_puschconfig = calloc(1, sizeof(*setup_puschconfig));
setup_puschconfig->present = NR_SetupRelease_PUSCH_Config_PR_setup;
@@ -1526,8 +1554,8 @@ static NR_SetupRelease_PUSCH_Config_t *config_pusch(const bool use_deltaMCS,
if (!pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup)
pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup = calloc(1, sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup));
NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup;
if (ptrs) {
NR_PTRS_UplinkConfig_t *ptrs_config = config_ulptrs(ptrs);
if (configuration->ptrs) {
NR_PTRS_UplinkConfig_t *ptrs_config = config_ulptrs(configuration->ptrs);
NR_SetupRelease_PTRS_UplinkConfig_t *phaseTrackingRS = calloc(1, sizeof(*phaseTrackingRS));
phaseTrackingRS->present = NR_SetupRelease_PTRS_UplinkConfig_PR_setup;
phaseTrackingRS->choice.setup = ptrs_config;
@@ -1569,7 +1597,7 @@ static NR_SetupRelease_PUSCH_Config_t *config_pusch(const bool use_deltaMCS,
asn1cSeqAdd(&pusch_Config->pusch_PowerControl->pathlossReferenceRSToAddModList->list, plrefRS);
pusch_Config->pusch_PowerControl->pathlossReferenceRSToReleaseList = NULL;
pusch_Config->pusch_PowerControl->twoPUSCH_PC_AdjustmentStates = NULL;
if (use_deltaMCS) {
if (configuration->use_deltaMCS) {
if (!pusch_Config->pusch_PowerControl->deltaMCS)
pusch_Config->pusch_PowerControl->deltaMCS = calloc(1, sizeof(*pusch_Config->pusch_PowerControl->deltaMCS));
*pusch_Config->pusch_PowerControl->deltaMCS = NR_PUSCH_PowerControl__deltaMCS_enabled;
@@ -1582,14 +1610,14 @@ static NR_SetupRelease_PUSCH_Config_t *config_pusch(const bool use_deltaMCS,
pusch_Config->resourceAllocation = NR_PUSCH_Config__resourceAllocation_resourceAllocationType1;
pusch_Config->pusch_TimeDomainAllocationList = NULL;
pusch_Config->pusch_AggregationFactor = NULL;
set_ul_mcs_table(uecap, scc, pusch_Config);
set_ul_mcs_table(configuration->force_UL256qam_off ? NULL : uecap, scc, pusch_Config);
pusch_Config->transformPrecoder = NULL;
if (!pusch_Config->codebookSubset)
pusch_Config->codebookSubset = calloc(1, sizeof(*pusch_Config->codebookSubset));
*pusch_Config->codebookSubset = NR_PUSCH_Config__codebookSubset_nonCoherent;
if (!pusch_Config->maxRank)
pusch_Config->maxRank = calloc(1, sizeof(*pusch_Config->maxRank));
*pusch_Config->maxRank = 1;
*pusch_Config->maxRank = set_ul_max_layers(configuration, uecap);
pusch_Config->rbg_Size = NULL;
pusch_Config->uci_OnPUSCH = NULL;
pusch_Config->tp_pi2BPSK = NULL;
@@ -1696,20 +1724,18 @@ static NR_BWP_Downlink_t *config_downlinkBWP(const NR_ServingCellConfigCommon_t
const NR_UE_NR_Capability_t *uecap,
int dl_antenna_ports,
bool force_256qam_off,
int bwp_loop,
bool is_SA,
const nr_mac_config_t *configuration)
{
NR_BWP_Downlink_t *bwp = calloc_or_fail(1, sizeof(*bwp));
bwp->bwp_Id = 1;
bwp->bwp_Common = calloc(1,sizeof(*bwp->bwp_Common));
if(configuration->num_additional_bwps > 0) {
const nr_bwp_config_t *bwp_config = &configuration->bwp_config[bwp_loop];
bwp->bwp_Id = bwp_config->id;
if(configuration->num_additional_bwps > 0 && configuration->first_active_bwp > 0) {
const nr_bwp_config_t *bwp_config = &configuration->bwp_config[configuration->first_active_bwp - 1];
bwp->bwp_Common->genericParameters.locationAndBandwidth = bwp_config->location_and_bw;
bwp->bwp_Common->genericParameters.subcarrierSpacing = bwp_config->scs;
bwp->bwp_Common->genericParameters.cyclicPrefix = NULL;
} else {
bwp->bwp_Id=bwp_loop+1;
bwp->bwp_Common->genericParameters.locationAndBandwidth = PRBalloc_to_locationandbandwidth(scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth,0);
bwp->bwp_Common->genericParameters.subcarrierSpacing = scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.subcarrierSpacing;
bwp->bwp_Common->genericParameters.cyclicPrefix = scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.cyclicPrefix;
@@ -1743,7 +1769,7 @@ static NR_BWP_Downlink_t *config_downlinkBWP(const NR_ServingCellConfigCommon_t
agg_level_candidates[PDCCH_AGG_LEVEL4] = NR_SearchSpace__nrofCandidates__aggregationLevel4_n1;
agg_level_candidates[PDCCH_AGG_LEVEL8] = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0;
agg_level_candidates[PDCCH_AGG_LEVEL16] = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0;
ss = rrc_searchspace_config(true, searchspaceid, 0, agg_level_candidates);
ss = rrc_searchspace_config(true, searchspaceid, coreset->controlResourceSetId, agg_level_candidates);
}
asn1cSeqAdd(&bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list, ss);
@@ -1784,7 +1810,7 @@ static NR_BWP_Downlink_t *config_downlinkBWP(const NR_ServingCellConfigCommon_t
verify_agg_levels(num_cces, configuration->num_agg_level_candidates, coreset2->controlResourceSetId, rrc_num_agg_level_candidates);
searchspaceid = 10 + bwp->bwp_Id;
NR_SearchSpace_t *ss2 = rrc_searchspace_config(true, searchspaceid, is_SA ? 0 : coreset2->controlResourceSetId, agg_level_candidates);
NR_SearchSpace_t *ss2 = rrc_searchspace_config(true, searchspaceid, coreset2->controlResourceSetId, agg_level_candidates);
asn1cSeqAdd(&bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list, ss2);
searchspaceid = 20 + bwp->bwp_Id;
@@ -1802,8 +1828,7 @@ static NR_BWP_Downlink_t *config_downlinkBWP(const NR_ServingCellConfigCommon_t
return bwp;
}
static NR_BWP_Uplink_t *config_uplinkBWP(long bwp_loop,
bool is_SA,
static NR_BWP_Uplink_t *config_uplinkBWP(bool is_SA,
int uid,
int maxMIMO_Layers,
const nr_mac_config_t *configuration,
@@ -1811,14 +1836,14 @@ static NR_BWP_Uplink_t *config_uplinkBWP(long bwp_loop,
const NR_UE_NR_Capability_t *uecap)
{
NR_BWP_Uplink_t *ubwp = calloc_or_fail(1, sizeof(*ubwp));
ubwp->bwp_Id = 1;
ubwp->bwp_Common = calloc(1, sizeof(*ubwp->bwp_Common));
if(configuration->num_additional_bwps > 0) {
ubwp->bwp_Id = configuration->bwp_config[bwp_loop].id;
ubwp->bwp_Common->genericParameters.locationAndBandwidth = configuration->bwp_config[bwp_loop].location_and_bw;
ubwp->bwp_Common->genericParameters.subcarrierSpacing = configuration->bwp_config[bwp_loop].scs;
if(configuration->num_additional_bwps > 0 && configuration->first_active_bwp > 0) {
int bwp_idx = configuration->first_active_bwp - 1;
ubwp->bwp_Common->genericParameters.locationAndBandwidth = configuration->bwp_config[bwp_idx].location_and_bw;
ubwp->bwp_Common->genericParameters.subcarrierSpacing = configuration->bwp_config[bwp_idx].scs;
ubwp->bwp_Common->genericParameters.cyclicPrefix = NULL;
} else {
ubwp->bwp_Id=bwp_loop+1;
ubwp->bwp_Common->genericParameters.locationAndBandwidth = PRBalloc_to_locationandbandwidth(scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth,0);
ubwp->bwp_Common->genericParameters.subcarrierSpacing = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing;
ubwp->bwp_Common->genericParameters.cyclicPrefix = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.cyclicPrefix;
@@ -1855,16 +1880,13 @@ static NR_BWP_Uplink_t *config_uplinkBWP(long bwp_loop,
scheduling_request_config(scc, pucch_Config, ubwp->bwp_Common->genericParameters.subcarrierSpacing);
set_dl_DataToUL_ACK(pucch_Config, configuration->minRXTXTIME, ubwp->bwp_Common->genericParameters.subcarrierSpacing);
ubwp->bwp_Dedicated->pusch_Config = config_pusch(configuration->use_deltaMCS,
scc,
configuration->force_UL256qam_off ? NULL : uecap,
configuration->ptrs);
ubwp->bwp_Dedicated->pusch_Config = config_pusch(configuration, scc, uecap);
ubwp->bwp_Dedicated->srs_Config = get_config_srs(scc,
NULL,
curr_bwp,
uid,
bwp_loop + 1,
ubwp->bwp_Id,
maxMIMO_Layers,
configuration->minRXTXTIME,
configuration->do_SRS);
@@ -3268,6 +3290,7 @@ static void fill_harq_IEs(NR_ServingCellConfig_t *scc, int num_dlharq, int num_u
static NR_BWP_UplinkDedicated_t *configure_initial_ul_bwp(const NR_ServingCellConfigCommon_t *scc,
const nr_mac_config_t *configuration,
int maxMIMO_Layers,
const NR_UE_NR_Capability_t *uecap,
int id)
{
NR_BWP_UplinkDedicated_t *initialUplinkBWP = calloc(1, sizeof(*initialUplinkBWP));
@@ -3282,14 +3305,14 @@ static NR_BWP_UplinkDedicated_t *configure_initial_ul_bwp(const NR_ServingCellCo
pucch_Config->resourceToAddModList = calloc(1, sizeof(*pucch_Config->resourceToAddModList));
pucch_Config->resourceToReleaseList = NULL;
int num_pucch2 = get_nb_pucch2_per_slot(scc, curr_bwp);
config_pucch_resset0(pucch_Config, id, curr_bwp, num_pucch2, NULL);
config_pucch_resset1(pucch_Config, id, num_pucch2, NULL);
config_pucch_resset0(pucch_Config, id, curr_bwp, num_pucch2, uecap);
config_pucch_resset1(pucch_Config, id, num_pucch2, uecap);
set_pucch_power_config(pucch_Config, configuration->do_CSIRS);
initialUplinkBWP->pusch_Config = config_pusch(configuration->use_deltaMCS, scc, NULL, configuration->ptrs);
initialUplinkBWP->pusch_Config = config_pusch(configuration, scc, uecap);
// We are using do_srs = 0 here because the periodic SRS will only be enabled in update_cellGroupConfig() if do_srs == 1
initialUplinkBWP->srs_Config = get_config_srs(scc, NULL, curr_bwp, id, 0, maxMIMO_Layers, configuration->minRXTXTIME, 0);
initialUplinkBWP->srs_Config = get_config_srs(scc, uecap, curr_bwp, id, 0, maxMIMO_Layers, configuration->minRXTXTIME, 0);
scheduling_request_config(scc, pucch_Config, scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing);
set_dl_DataToUL_ACK(pucch_Config, configuration->minRXTXTIME, genericParameters->subcarrierSpacing);
@@ -3299,6 +3322,7 @@ static NR_BWP_UplinkDedicated_t *configure_initial_ul_bwp(const NR_ServingCellCo
static NR_BWP_DownlinkDedicated_t *configure_initial_dl_bwp(const NR_ServingCellConfigCommon_t *scc,
const int pdsch_AntennaPorts,
uint64_t bitmap,
const NR_UE_NR_Capability_t *uecap,
const nr_mac_config_t *configuration)
{
NR_BWP_DownlinkDedicated_t *bwp_Dedicated = calloc(1, sizeof(*bwp_Dedicated));
@@ -3330,6 +3354,11 @@ static NR_BWP_DownlinkDedicated_t *configure_initial_dl_bwp(const NR_ServingCell
bwp_Dedicated->pdcch_Config->choice.setup = pdcch_Config;
bwp_Dedicated->pdsch_Config = config_pdsch(bitmap, 0, pdsch_AntennaPorts, configuration->ptrs);
// we might call configuration of initial BWP for BWP switch when we already have UE capabilities
set_dl_mcs_table(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing,
configuration->force_256qam_off ? NULL : uecap,
bwp_Dedicated,
scc);
return bwp_Dedicated;
}
@@ -3367,10 +3396,14 @@ static NR_CSI_MeasConfig_t *get_csiMeasConfig(const NR_ServingCellConfig_t *conf
pdsch_Config = configDedicated->initialDownlinkBWP->pdsch_Config;
curr_bwp = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
} else {
NR_BWP_Downlink_t *bwp = configDedicated->downlinkBWP_ToAddModList->list.array[0];
NR_BWP_Downlink_t *bwp = NULL;
for (int i = 0; i < configDedicated->downlinkBWP_ToAddModList->list.count; i++) {
if (bwp_id == configDedicated->downlinkBWP_ToAddModList->list.array[i]->bwp_Id)
bwp = configDedicated->downlinkBWP_ToAddModList->list.array[i];
}
AssertFatal(bwp, "BWP ID doesn't match\n");
pdsch_Config = bwp->bwp_Dedicated->pdsch_Config;
curr_bwp = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
AssertFatal(bwp_id == bwp->bwp_Id, "BWP ID doesn't match\n");
}
const int pdsch_AntennaPorts =
@@ -3501,25 +3534,24 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid,
uint64_t bitmap = get_ssb_bitmap(scc);
int first_active_bwp = 0;
if (configuration->num_additional_bwps > 0)
first_active_bwp = configuration->first_active_bwp;
first_active_bwp = configuration->first_active_bwp > 0 ? 1 : 0;
asn1cCallocOne(configDedicated->firstActiveDownlinkBWP_Id, first_active_bwp);
asn1cCallocOne(uplinkConfig->firstActiveUplinkBWP_Id, first_active_bwp);
if (first_active_bwp == 0) {
uplinkConfig->initialUplinkBWP = configure_initial_ul_bwp(scc, configuration, maxMIMO_Layers, uid);
configDedicated->initialDownlinkBWP = configure_initial_dl_bwp(scc, pdsch_AntennaPorts, bitmap, configuration);
uplinkConfig->initialUplinkBWP = configure_initial_ul_bwp(scc, configuration, maxMIMO_Layers, NULL, uid);
configDedicated->initialDownlinkBWP = configure_initial_dl_bwp(scc, pdsch_AntennaPorts, bitmap, NULL, configuration);
} else {
configDedicated->downlinkBWP_ToAddModList = calloc(1, sizeof(*configDedicated->downlinkBWP_ToAddModList));
NR_BWP_Downlink_t *bwp = config_downlinkBWP(scc,
NULL,
0,
false,
first_active_bwp - 1,
true,
configuration);
asn1cSeqAdd(&configDedicated->downlinkBWP_ToAddModList->list, bwp);
uplinkConfig->uplinkBWP_ToAddModList = calloc(1, sizeof(*uplinkConfig->uplinkBWP_ToAddModList));
NR_BWP_Uplink_t *ubwp = config_uplinkBWP(first_active_bwp - 1, true, uid, maxMIMO_Layers, configuration, scc, NULL);
NR_BWP_Uplink_t *ubwp = config_uplinkBWP(true, uid, maxMIMO_Layers, configuration, scc, NULL);
asn1cSeqAdd(&uplinkConfig->uplinkBWP_ToAddModList->list, ubwp);
}
@@ -3739,75 +3771,22 @@ NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid,
return cellGroupConfig;
}
long ue_supported_ul_layers(const NR_UE_NR_Capability_t *uecap)
{
long ul_max_layers = 1;
if (uecap
&& uecap->featureSets
&& uecap->featureSets->featureSetsUplinkPerCC
&& uecap->featureSets->featureSetsUplinkPerCC->list.count > 0) {
NR_FeatureSetUplinkPerCC_t *ul_feature_setup_per_cc = uecap->featureSets->featureSetsUplinkPerCC->list.array[0];
if (ul_feature_setup_per_cc->mimo_CB_PUSCH->maxNumberMIMO_LayersCB_PUSCH) {
switch (*ul_feature_setup_per_cc->mimo_CB_PUSCH->maxNumberMIMO_LayersCB_PUSCH) {
case NR_MIMO_LayersUL_twoLayers:
ul_max_layers = 2;
break;
case NR_MIMO_LayersUL_fourLayers:
ul_max_layers = 4;
break;
default:
ul_max_layers = 1;
}
}
}
return ul_max_layers;
}
static long set_ul_max_layers(const nr_mac_config_t *configuration, const NR_UE_NR_Capability_t *uecap)
{
return min(ue_supported_ul_layers(uecap), configuration->pusch_AntennaPorts);
}
NR_CellGroupConfig_t * update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t *cellGroupConfig,
const nr_mac_config_t *configuration,
const NR_UE_NR_Capability_t *uecap,
const NR_ServingCellConfigCommon_t *scc,
int uid,
int old_bwp,
int new_bwp)
NR_CellGroupConfig_t *update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t *cellGroupConfig,
const nr_mac_config_t *configuration,
const NR_UE_NR_Capability_t *uecap,
const NR_ServingCellConfigCommon_t *scc,
int uid,
int old_bwp,
int new_bwp)
{
NR_SpCellConfig_t *spCellConfig = cellGroupConfig->spCellConfig;
NR_ServingCellConfig_t *configDedicated = spCellConfig->spCellConfigDedicated;
*configDedicated->firstActiveDownlinkBWP_Id = new_bwp;
*configDedicated->firstActiveDownlinkBWP_Id = new_bwp != 0; // 1 for any BWP != 0
NR_UplinkConfig_t *uplinkConfig = configDedicated->uplinkConfig;
*uplinkConfig->firstActiveUplinkBWP_Id = new_bwp;
*uplinkConfig->firstActiveUplinkBWP_Id = new_bwp != 0; // 1 for any BWP != 0
nr_mac_config_t local_config = *configuration;
long ul_maxMIMO_Layers = set_ul_max_layers(configuration, uecap);
// release old BWP
struct NR_ServingCellConfig__downlinkBWP_ToAddModList *dl_BWP_list = configDedicated->downlinkBWP_ToAddModList;
struct NR_UplinkConfig__uplinkBWP_ToAddModList *ul_BWP_list = uplinkConfig->uplinkBWP_ToAddModList;
if (old_bwp > 0) { // we need to remove old BWP only if it is not the initial
AssertFatal(dl_BWP_list, "Source BWP %d should be present in the list\n", old_bwp);
AssertFatal(ul_BWP_list, "Source BWP %d should be present in the list\n", old_bwp);
NR_BWP_Id_t id = dl_BWP_list->list.array[0]->bwp_Id;
if (!configDedicated->downlinkBWP_ToReleaseList)
configDedicated->downlinkBWP_ToReleaseList = calloc_or_fail(1, sizeof(*configDedicated->downlinkBWP_ToReleaseList));
asn1cSequenceAdd(configDedicated->downlinkBWP_ToReleaseList->list, NR_BWP_Id_t, rel_id);
*rel_id = id;
AssertFatal(configDedicated->downlinkBWP_ToReleaseList->list.count == 1,
"logic error: there shouldn't be more than 1 BWP to release, but downlinkBWP_ToReleaseList has %d\n",
configDedicated->downlinkBWP_ToReleaseList->list.count);
id = ul_BWP_list->list.array[0]->bwp_Id;
if (!uplinkConfig->uplinkBWP_ToReleaseList)
uplinkConfig->uplinkBWP_ToReleaseList = calloc_or_fail(1, sizeof(*uplinkConfig->uplinkBWP_ToReleaseList));
asn1cSequenceAdd(uplinkConfig->uplinkBWP_ToReleaseList->list, NR_BWP_Id_t, ul_rel_id);
*ul_rel_id = id;
AssertFatal(uplinkConfig->uplinkBWP_ToReleaseList->list.count == 1,
"logic error: there shouldn't be more than 1 BWP to release, but uplinkBWP_ToReleaseList has %d\n",
uplinkConfig->uplinkBWP_ToReleaseList->list.count);
}
local_config.first_active_bwp = new_bwp;
uint64_t bitmap = get_ssb_bitmap(scc);
const int pdsch_AntennaPorts =
configuration->pdsch_AntennaPorts.N1 * configuration->pdsch_AntennaPorts.N2 * configuration->pdsch_AntennaPorts.XP;
@@ -3817,23 +3796,22 @@ NR_CellGroupConfig_t * update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_
configDedicated->initialDownlinkBWP = calloc_or_fail(1, sizeof(*configDedicated->initialDownlinkBWP));
if (!uplinkConfig->initialUplinkBWP)
uplinkConfig->initialUplinkBWP = calloc_or_fail(1, sizeof(*uplinkConfig->initialUplinkBWP));
uplinkConfig->initialUplinkBWP = configure_initial_ul_bwp(scc, configuration, ul_maxMIMO_Layers, uid);
configDedicated->initialDownlinkBWP = configure_initial_dl_bwp(scc, pdsch_AntennaPorts, bitmap, configuration);
uplinkConfig->initialUplinkBWP = configure_initial_ul_bwp(scc, &local_config, ul_maxMIMO_Layers, uecap, uid);
configDedicated->initialDownlinkBWP = configure_initial_dl_bwp(scc, pdsch_AntennaPorts, bitmap, uecap, &local_config);
} else {
if (!configDedicated->downlinkBWP_ToAddModList)
configDedicated->downlinkBWP_ToAddModList = calloc_or_fail(1, sizeof(*configDedicated->downlinkBWP_ToAddModList));
NR_BWP_Downlink_t *dl_bwp = config_downlinkBWP(scc,
uecap,
pdsch_AntennaPorts,
configuration->force_256qam_off,
new_bwp - 1,
local_config.force_256qam_off,
true,
configuration);
&local_config);
asn1cSeqAdd(&configDedicated->downlinkBWP_ToAddModList->list, dl_bwp);
if (!uplinkConfig->uplinkBWP_ToAddModList)
uplinkConfig->uplinkBWP_ToAddModList = calloc_or_fail(1, sizeof(*uplinkConfig->uplinkBWP_ToAddModList));
NR_BWP_Uplink_t *ul_bwp = config_uplinkBWP(new_bwp - 1, true, uid, ul_maxMIMO_Layers, configuration, scc, uecap);
NR_BWP_Uplink_t *ul_bwp = config_uplinkBWP(true, uid, ul_maxMIMO_Layers, &local_config, scc, uecap);
asn1cSeqAdd(&uplinkConfig->uplinkBWP_ToAddModList->list, ul_bwp);
}
@@ -3841,9 +3819,9 @@ NR_CellGroupConfig_t * update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_
configDedicated->csi_MeasConfig->choice.setup = get_csiMeasConfig(configDedicated,
uecap,
scc,
configuration,
&local_config,
uid,
new_bwp,
*uplinkConfig->firstActiveUplinkBWP_Id,
bitmap);
// we temporarily need to keep both the old and the new BWP in the CG used by the gNB
@@ -4055,10 +4033,7 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC
ulConfig->initialUplinkBWP = initialUplinkBWP;
initialUplinkBWP->pucch_Config = NULL;
initialUplinkBWP->pusch_Config = config_pusch(configuration->use_deltaMCS,
servingcellconfigcommon,
uecap,
configuration->ptrs);
initialUplinkBWP->pusch_Config = config_pusch(configuration, servingcellconfigcommon, uecap);
long maxMIMO_Layers = set_ul_max_layers(configuration, uecap);
int curr_bwp = NRRIV2BW(servingcellconfigcommon->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth,
@@ -4073,44 +4048,27 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC
configuration->do_SRS);
// Downlink BWPs
int n_dl_bwp = 1;
int firstActiveDownlinkBWP_Id = 1;
if (configuration->num_additional_bwps > 0) {
n_dl_bwp = configuration->num_additional_bwps;
firstActiveDownlinkBWP_Id = configuration->first_active_bwp;
}
configDedicated->downlinkBWP_ToAddModList = calloc(1, sizeof(*configDedicated->downlinkBWP_ToAddModList));
for (int bwp_loop = 0; bwp_loop < n_dl_bwp; bwp_loop++) {
NR_BWP_Downlink_t *bwp = config_downlinkBWP(servingcellconfigcommon,
uecap,
dl_antenna_ports,
configuration->force_256qam_off,
bwp_loop,
false,
configuration);
asn1cSeqAdd(&configDedicated->downlinkBWP_ToAddModList->list, bwp);
configDedicated->firstActiveDownlinkBWP_Id = calloc(1, sizeof(*configDedicated->firstActiveDownlinkBWP_Id));
*configDedicated->firstActiveDownlinkBWP_Id = firstActiveDownlinkBWP_Id;
configDedicated->defaultDownlinkBWP_Id = calloc(1, sizeof(*configDedicated->defaultDownlinkBWP_Id));
*configDedicated->defaultDownlinkBWP_Id = 1;
}
NR_BWP_Downlink_t *bwp = config_downlinkBWP(servingcellconfigcommon,
uecap,
dl_antenna_ports,
configuration->force_256qam_off,
false,
configuration);
asn1cSeqAdd(&configDedicated->downlinkBWP_ToAddModList->list, bwp);
configDedicated->firstActiveDownlinkBWP_Id = calloc(1, sizeof(*configDedicated->firstActiveDownlinkBWP_Id));
*configDedicated->firstActiveDownlinkBWP_Id = firstActiveDownlinkBWP_Id;
configDedicated->defaultDownlinkBWP_Id = calloc(1, sizeof(*configDedicated->defaultDownlinkBWP_Id));
*configDedicated->defaultDownlinkBWP_Id = 1;
// Uplink BWPs
int n_ul_bwp = 1;
int firstActiveUplinkBWP_Id = 1;
if (configuration->num_additional_bwps > 0) {
n_ul_bwp = configuration->num_additional_bwps;
firstActiveUplinkBWP_Id = configuration->first_active_bwp;
}
if (n_ul_bwp > 0) {
ulConfig->uplinkBWP_ToAddModList = calloc(1, sizeof(*ulConfig->uplinkBWP_ToAddModList));
for (int bwp_loop = 0; bwp_loop < n_ul_bwp; bwp_loop++) {
NR_BWP_Uplink_t *ubwp = config_uplinkBWP(bwp_loop, false, uid, maxMIMO_Layers, configuration, servingcellconfigcommon, uecap);
asn1cSeqAdd(&ulConfig->uplinkBWP_ToAddModList->list, ubwp);
}
ulConfig->firstActiveUplinkBWP_Id = calloc(1, sizeof(*ulConfig->firstActiveUplinkBWP_Id));
*ulConfig->firstActiveUplinkBWP_Id = firstActiveUplinkBWP_Id;
}
ulConfig->uplinkBWP_ToAddModList = calloc(1, sizeof(*ulConfig->uplinkBWP_ToAddModList));
NR_BWP_Uplink_t *ubwp = config_uplinkBWP(false, uid, maxMIMO_Layers, configuration, servingcellconfigcommon, uecap);
asn1cSeqAdd(&ulConfig->uplinkBWP_ToAddModList->list, ubwp);
ulConfig->firstActiveUplinkBWP_Id = calloc(1, sizeof(*ulConfig->firstActiveUplinkBWP_Id));
*ulConfig->firstActiveUplinkBWP_Id = firstActiveUplinkBWP_Id;
configDedicated->bwp_InactivityTimer = NULL;
configDedicated->downlinkBWP_ToReleaseList = NULL;
+7 -7
View File
@@ -124,13 +124,13 @@ NR_RLC_BearerConfig_t *get_DRB_RLC_BearerConfig(long lcChannelId,
NR_RLC_Config_PR rlc_conf,
long priority,
const nr_rlc_configuration_t *default_rlc_config);
NR_CellGroupConfig_t * update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t *cellGroupConfig,
const nr_mac_config_t *configuration,
const NR_UE_NR_Capability_t *uecap,
const NR_ServingCellConfigCommon_t *scc,
int uid,
int old_bwp,
int new_bwp);
NR_CellGroupConfig_t *update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t *cellGroupConfig,
const nr_mac_config_t *configuration,
const NR_UE_NR_Capability_t *uecap,
const NR_ServingCellConfigCommon_t *scc,
int uid,
int old_bwp,
int new_bwp);
NR_MeasurementTimingConfiguration_t *get_nr_mtc(uint8_t *buf, uint32_t len);
measgap_config_t create_measgap_config(const NR_MeasurementTimingConfiguration_t *mtc, int scs, int min_rxtxtime);
int encode_measgap_config(const measgap_config_t *c, uint8_t *buf);