Merge remote-tracking branch 'origin/new_UE_context_improvements' into integration_2025_w18 (!3291)

Improvements in handling UE context in gNB DU

The goal of this MR is to improve the handling of UE context in gNB DU.
To achieve this goal, the UE structure is created as soon as the gNB
receive a PRACH indication. At that stage the UE is placed in a new
structure containing UEs performing RA, untill RA is complete where it
is moved to the list of connected UEs. To simplify the code and to
improve the handling of initial procedures (see #751), DCI 10 and DCI 00
is used at every stage until the DU receives from CU the indication of
UE RRC reconfiguration being completed.
This commit is contained in:
Robert Schmidt
2025-05-05 09:10:36 +02:00
49 changed files with 1301 additions and 1724 deletions
-3
View File
@@ -1138,8 +1138,6 @@ set(L2_NR_SRC
${NR_RRC_DIR}/mac_rrc_dl_f1ap.c
${NR_RRC_DIR}/nr_rrc_config.c
${NR_RRC_DIR}/rrc_gNB_nsa.c
${NR_RRC_DIR}/rrc_gNB_internode.c
${NR_RRC_DIR}/rrc_gNB_reconfig.c
${NR_RRC_DIR}/rrc_gNB_UE_context.c
${NR_RRC_DIR}/rrc_gNB_NGAP.c
${NR_RRC_DIR}/rrc_gNB_radio_bearers.c
@@ -1366,7 +1364,6 @@ include_directories("${OPENAIR1_DIR}/SCHED_NR_UE")
##########################
add_library (GTPV1U
${NR_RRC_DIR}/rrc_gNB_GTPV1U.c
${RRC_DIR}/rrc_eNB_GTPV1U.c
${OPENAIR3_DIR}/ocp-gtpu/gtp_itf.cpp
)
+4 -4
View File
@@ -15,10 +15,10 @@ Ref :
DLSCH encoding : 220.0
L1 Rx processing : 530.0
PUSCH inner-receiver : 360.0
Schedule Response : 3.0
DL & UL scheduling timing : 17.0
UL Indication : 3.0
Slot Indication : 17.0
Schedule Response : 1.0
DL & UL scheduling timing : 12.0
UL Indication : 1.0
Slot Indication : 13.0
DeviationThreshold :
feprx : 0.25
feptx_prec : 0.25
+4 -4
View File
@@ -15,10 +15,10 @@ Ref :
DLSCH encoding : 140.0
L1 Rx processing : 345.0
PUSCH inner-receiver : 150.0
Schedule Response : 3.0
DL & UL scheduling timing : 7.0
UL Indication : 3.0
Slot Indication : 8.0
Schedule Response : 1.0
DL & UL scheduling timing : 5.0
UL Indication : 1.0
Slot Indication : 6.0
DeviationThreshold :
feprx : 0.25
feptx_prec : 0.25
+3 -3
View File
@@ -15,10 +15,10 @@ Ref :
DLSCH encoding : 155.0
L1 Rx processing : 345.0
PUSCH inner-receiver : 155.0
Schedule Response : 3.0
DL & UL scheduling timing : 13.0
Schedule Response : 1.0
DL & UL scheduling timing : 8.0
UL Indication : 3.0
Slot Indication : 12.0
Slot Indication : 9.0
DeviationThreshold :
feprx : 0.25
feptx_prec : 0.25
+3 -3
View File
@@ -15,10 +15,10 @@ Ref :
DLSCH encoding : 100.0
L1 Rx processing : 290.0
PUSCH inner-receiver : 115.0
Schedule Response : 3.0
DL & UL scheduling timing : 6.0
Schedule Response : 1.0
DL & UL scheduling timing : 4.0
UL Indication : 2.0
Slot Indication : 7.0
Slot Indication : 5.0
DeviationThreshold :
feprx : 0.25
feptx_prec : 0.25
+1 -1
View File
@@ -47,7 +47,7 @@
static int get_single_ue_rnti_mac(void)
{
NR_UE_info_t *ue = NULL;
UE_iterator(RC.nrmac[0]->UE_info.list, it) {
UE_iterator(RC.nrmac[0]->UE_info.connected_ue_list, it) {
if (it && ue)
return -1;
if (it)
+2 -2
View File
@@ -123,7 +123,7 @@ static int get_stats(char *buf, int debug, telnet_printfunc_t prnt)
static b_t last_total[MAX_MOBILES_PER_GNB] = {0}; // TODO: hash table?
ue_stat_t ue_stat[MAX_MOBILES_PER_GNB] = {0};
int num_ues = 0;
UE_iterator((NR_UE_info_t **)mac->UE_info.list, it) {
UE_iterator((NR_UE_info_t **)mac->UE_info.connected_ue_list, it) {
nr_rlc_statistics_t rlc = {0};
nr_rlc_get_statistics(it->rnti, srb_flag, rb_id, &rlc);
b_t *lt = &last_total[num_ues];
@@ -369,7 +369,7 @@ static int stop_modem(char *buf, int debug, telnet_printfunc_t prnt)
* scheduler, which has many PUCCH structures filled with expected frame/slot
* combinations that won't happen. */
const gNB_MAC_INST *mac = RC.nrmac[0];
UE_iterator((NR_UE_info_t **)mac->UE_info.list, it) {
UE_iterator((NR_UE_info_t **)mac->UE_info.connected_ue_list, it) {
nr_mac_trigger_ul_failure(&it->UE_sched_ctrl, 1);
}
usleep(50000);
-4
View File
@@ -1844,12 +1844,10 @@ INPUT = \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR_UE/rrc_defs.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR_UE/L2_interface_ue.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/L2_INTERFACE/openair_rrc_L2_interface.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/rrc_gNB_internode.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/nr_rrc_defs.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/cucp_cuup_if.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/cucp_cuup_direct.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/nr_rrc_config.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/rrc_gNB_GTPV1U.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/mac_rrc_dl_direct.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/rrc_gNB_radio_bearers.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/rrc_gNB_NGAP.h \
@@ -1862,10 +1860,8 @@ INPUT = \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/rrc_gNB.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/nr_rrc_config.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/rrc_gNB_radio_bearers.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/rrc_gNB_reconfig.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/rrc_gNB_NGAP.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/mac_rrc_dl_f1ap.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/rrc_gNB_GTPV1U.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/mac_rrc_dl.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/rrc_gNB_nsa.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/LTE/rrc_eNB_GTPV1U.c \
+5 -5
View File
@@ -305,11 +305,6 @@ static int create_gNB_tasks(ngran_node_t node_type, configmodule_interface_t *cf
}
if (gnb_nb > 0) {
if (itti_create_task (TASK_GNB_APP, gNB_app_task, NULL) < 0) {
LOG_E(GNB_APP, "Create task for gNB APP failed\n");
return -1;
}
if (!NODE_IS_DU(node_type)) {
if (itti_create_task (TASK_RRC_GNB, rrc_gnb_task, NULL) < 0) {
LOG_E(NR_RRC, "Create task for NR RRC gNB failed\n");
@@ -333,6 +328,11 @@ static int create_gNB_tasks(ngran_node_t node_type, configmodule_interface_t *cf
itti_free(TASK_UNKNOWN, msg);
}
if (itti_create_task (TASK_GNB_APP, gNB_app_task, NULL) < 0) {
LOG_E(GNB_APP, "Create task for gNB APP failed\n");
return -1;
}
//Use check on x2ap to consider the NSA scenario
if((is_x2ap_enabled() || IS_SA_MODE(get_softmodem_params())) && (node_type != ngran_gNB_CUCP)) {
if (itti_create_task (TASK_GTPV1_U, &gtpv1uTask, NULL) < 0) {
+9 -7
View File
@@ -184,8 +184,8 @@ int g_mcsIndex = -1, g_mcsTableIdx = 0, g_rbStart = -1, g_rbSize = -1, g_nrOfLay
void nr_dlsim_preprocessor(module_id_t module_id, frame_t frame, slot_t slot)
{
NR_UE_info_t *UE_info = RC.nrmac[module_id]->UE_info.list[0];
AssertFatal(RC.nrmac[module_id]->UE_info.list[1]==NULL, "can have only a single UE\n");
NR_UE_info_t *UE_info = RC.nrmac[module_id]->UE_info.connected_ue_list[0];
AssertFatal(RC.nrmac[module_id]->UE_info.connected_ue_list[1] == NULL, "Only single UE allowed in dlsim\n");
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl;
NR_UE_DL_BWP_t *current_BWP = &UE_info->current_DL_BWP;
NR_ServingCellConfigCommon_t *scc = RC.nrmac[0]->common_channels[0].ServingCellConfigCommon;
@@ -780,8 +780,10 @@ printf("%d\n", slot);
NR_UE_NR_Capability_t *UE_Capability_nr = CALLOC(1,sizeof(NR_UE_NR_Capability_t));
prepare_sim_uecap(UE_Capability_nr, scc, mu, N_RB_DL, g_mcsTableIdx, 0);
NR_CellGroupConfig_t *secondaryCellGroup = get_default_secondaryCellGroup(scc, scd, UE_Capability_nr, 0, 1, &conf, 0);
rnti_t rnti = 0x1234;
int uid = 0;
NR_CellGroupConfig_t *secondaryCellGroup = get_default_secondaryCellGroup(scc, scd, UE_Capability_nr, 0, 1, &conf, uid);
secondaryCellGroup->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(rnti, uid, scc);
/* -U option modify DMRS */
if(modify_dmrs) {
@@ -796,15 +798,15 @@ printf("%d\n", slot);
//xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup);
// UE dedicated configuration
nr_mac_add_test_ue(RC.nrmac[0], secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity, secondaryCellGroup);
nr_mac_add_test_ue(RC.nrmac[0], rnti, secondaryCellGroup);
// reset preprocessor to the one of DLSIM after it has been set during
// nr_mac_config_scc()
gNB_mac->pre_processor_dl = nr_dlsim_preprocessor;
phy_init_nr_gNB(gNB);
N_RB_DL = gNB->frame_parms.N_RB_DL;
NR_UE_info_t *UE_info = RC.nrmac[0]->UE_info.list[0];
NR_UE_info_t *UE_info = RC.nrmac[0]->UE_info.connected_ue_list[0];
configure_UE_BWP(RC.nrmac[0], scc, &UE_info->UE_sched_ctrl, NULL, UE_info, -1, -1);
configure_UE_BWP(RC.nrmac[0], scc, UE_info, false, NR_SearchSpace__searchSpaceType_PR_ue_Specific, -1, -1);
// stub to configure frame_parms
// nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions);
+6 -5
View File
@@ -672,15 +672,16 @@ int main(int argc, char *argv[])
fix_scd(scd);
NR_UE_NR_Capability_t* UE_Capability_nr = CALLOC(1,sizeof(NR_UE_NR_Capability_t));
prepare_sim_uecap(UE_Capability_nr,scc,mu,
N_RB_UL,0,mcs_table);
NR_CellGroupConfig_t *secondaryCellGroup = get_default_secondaryCellGroup(scc, scd, UE_Capability_nr, 0, 1, &conf, 0);
prepare_sim_uecap(UE_Capability_nr, scc, mu, N_RB_UL, 0, mcs_table);
rnti_t rnti = 0x1234;
int uid = 0;
NR_CellGroupConfig_t *secondaryCellGroup = get_default_secondaryCellGroup(scc, scd, UE_Capability_nr, 0, 1, &conf, uid);
secondaryCellGroup->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(rnti, uid, scc);
NR_BCCH_BCH_Message_t *mib = get_new_MIB_NR(scc);
// UE dedicated configuration
nr_mac_add_test_ue(RC.nrmac[0], secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity, secondaryCellGroup);
nr_mac_add_test_ue(RC.nrmac[0], rnti, secondaryCellGroup);
frame_parms->nb_antennas_tx = 1;
frame_parms->nb_antennas_rx = n_rx;
nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
@@ -37,7 +37,7 @@ bool read_mac_sm(void* data)
NR_UEs_t *UE_info = &RC.nrmac[mod_id]->UE_info;
size_t num_ues = 0;
UE_iterator(UE_info->list, ue) {
UE_iterator(UE_info->connected_ue_list, ue) {
if (ue)
num_ues += 1;
}
@@ -49,7 +49,7 @@ bool read_mac_sm(void* data)
}
size_t i = 0; //TODO
UE_iterator(UE_info->list, UE) {
UE_iterator(UE_info->connected_ue_list, UE) {
const NR_UE_sched_ctrl_t* sched_ctrl = &UE->UE_sched_ctrl;
mac_ue_stats_impl_t* rd = &mac->msg.ue_stats[i];
@@ -38,7 +38,7 @@ uint32_t num_act_rb(NR_UEs_t* const UE_info)
assert(UE_info!= NULL);
uint32_t act_rb = 0;
UE_iterator(UE_info->list, UE) {
UE_iterator(UE_info->connected_ue_list, UE) {
uint16_t const rnti = UE->rnti;
for(int rb_id = 1; rb_id < 6; ++rb_id ){
nr_rlc_statistics_t rlc = {0};
@@ -55,7 +55,7 @@ void active_avg_to_tx(NR_UEs_t* const UE_info)
{
assert(UE_info!= NULL);
UE_iterator(UE_info->list, UE) {
UE_iterator(UE_info->connected_ue_list, UE) {
uint16_t const rnti = UE->rnti;
for(int rb_id = 1; rb_id < 6; ++rb_id ){
nr_rlc_statistics_t rlc = {0};
@@ -91,7 +91,7 @@ bool read_rlc_sm(void* data)
rlc->msg.tstamp = time_now_us();
uint32_t i = 0;
UE_iterator(UE_info->list, UE) {
UE_iterator(UE_info->connected_ue_list, UE) {
uint16_t const rnti = UE->rnti;
//for every LC ID
for(int rb_id = 1; rb_id < 6; ++rb_id ){
@@ -282,7 +282,7 @@ static arr_ue_id_t filter_ues_by_s_nssai_in_du_or_monolithic(const test_info_lst
const ngran_node_t node_type = get_e2_node_type();
// Take MAC info
UE_iterator (RC.nrmac[0]->UE_info.list, ue) {
UE_iterator(RC.nrmac[0]->UE_info.connected_ue_list, ue) {
NR_UE_sched_ctrl_t *sched_ctrl = &ue->UE_sched_ctrl;
// UE matches if any of its DRBs matches
for (size_t l = 0; l < seq_arr_size(&sched_ctrl->lc_config); ++l) {
@@ -262,11 +262,13 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu
if (f1ap_ue_context_setup_req->cu_to_du_rrc_information!=NULL) {
/* optional */
/* 6.1 cG_ConfigInfo */
if(f1ap_ue_context_setup_req->cu_to_du_rrc_information->cG_ConfigInfo!=NULL){
if(f1ap_ue_context_setup_req->cu_to_du_rrc_information->cG_ConfigInfo_length > 0) {
DevAssert(f1ap_ue_context_setup_req->cu_to_du_rrc_information->cG_ConfigInfo != NULL);
asn1cCalloc(ie6->value.choice.CUtoDURRCInformation.cG_ConfigInfo, cG_ConfigInfo);
OCTET_STRING_fromBuf(cG_ConfigInfo, (const char *)f1ap_ue_context_setup_req->cu_to_du_rrc_information->cG_ConfigInfo,
f1ap_ue_context_setup_req->cu_to_du_rrc_information->cG_ConfigInfo_length);
}
/* optional */
/* 6.2 uE_CapabilityRAT_ContainerList */
if(f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList!=NULL){
@@ -178,6 +178,11 @@ int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_i
f1ap_ue_context_setup_req->cu_to_du_rrc_information = (cu_to_du_rrc_information_t *)calloc(1,sizeof(cu_to_du_rrc_information_t));
cu_to_du_rrc_information_t *cu2du = f1ap_ue_context_setup_req->cu_to_du_rrc_information;
const F1AP_CUtoDURRCInformation_t *cu2duie = &ieCuRrcInfo->value.choice.CUtoDURRCInformation;
if (cu2duie->cG_ConfigInfo != NULL) {
cu2du->cG_ConfigInfo = malloc_or_fail(cu2duie->cG_ConfigInfo->size);
cu2du->cG_ConfigInfo_length = cu2duie->cG_ConfigInfo->size;
memcpy(cu2du->cG_ConfigInfo, cu2duie->cG_ConfigInfo->buf, cu2du->cG_ConfigInfo_length);
}
if(cu2duie->uE_CapabilityRAT_ContainerList!=NULL){
cu2du->uE_CapabilityRAT_ContainerList = calloc(1, cu2duie->uE_CapabilityRAT_ContainerList->size);
memcpy(cu2du->uE_CapabilityRAT_ContainerList,
+2 -1
View File
@@ -2136,7 +2136,8 @@ gNB_RRC_INST *RCconfig_NRRRC()
openair_rrc_gNB_configuration(rrc, &nrrrc_config);
}//End if (num_gnbs>0)
config_security(rrc);
if (!NODE_IS_DU(rrc->node_type))
config_security(rrc);
return rrc;
}
+14 -58
View File
@@ -858,14 +858,6 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c
find_SSB_and_RO_available(nrmac);
NR_COMMON_channels_t *cc = &nrmac->common_channels[0];
NR_SCHED_LOCK(&nrmac->sched_lock);
for (int n = 0; n < NR_NB_RA_PROC_MAX; n++) {
NR_RA_t *ra = &cc->ra[n];
nr_clear_ra_proc(ra);
}
NR_SCHED_UNLOCK(&nrmac->sched_lock);
if (IS_SA_MODE(get_softmodem_params()))
config_sched_ctrlCommon(nrmac);
}
@@ -979,18 +971,18 @@ bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t
DevAssert(get_softmodem_params()->phy_test);
NR_SCHED_LOCK(&nrmac->sched_lock);
NR_UE_info_t *UE = add_new_nr_ue(nrmac, rnti, CellGroup);
if (!UE) {
NR_UE_info_t *UE = get_new_nr_ue_inst(&nrmac->UE_info.uid_allocator, rnti, CellGroup);
DevAssert(UE != NULL); // 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
bool res = add_connected_nr_ue(nrmac, UE);
if (!res) {
LOG_E(NR_MAC, "Error adding UE %04x\n", rnti);
delete_nr_ue_data(UE, NULL, &nrmac->UE_info.uid_allocator);
NR_SCHED_UNLOCK(&nrmac->sched_lock);
return false;
}
if (CellGroup->spCellConfig && CellGroup->spCellConfig->reconfigurationWithSync
&& CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated
&& CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra) {
nr_mac_prepare_ra_ue(RC.nrmac[0], UE->rnti, CellGroup);
}
int ss_type = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
configure_UE_BWP(nrmac, nrmac->common_channels[0].ServingCellConfigCommon, UE, false, ss_type, -1, -1);
process_addmod_bearers_cellGroupConfig(&UE->UE_sched_ctrl, CellGroup->rlc_BearerToAddModList);
AssertFatal(CellGroup->rlc_BearerToReleaseList == NULL, "cannot release bearers while adding new UEs\n");
NR_SCHED_UNLOCK(&nrmac->sched_lock);
@@ -998,32 +990,18 @@ bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t
return true;
}
bool nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup)
void nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, NR_UE_info_t *UE)
{
DevAssert(nrmac != NULL);
DevAssert(CellGroup != NULL);
NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock);
// NSA case: need to pre-configure CFRA
const int CC_id = 0;
NR_COMMON_channels_t *cc = &nrmac->common_channels[CC_id];
uint8_t ra_index = 0;
/* checking for free RA process */
for(; ra_index < NR_NB_RA_PROC_MAX; ra_index++) {
if ((cc->ra[ra_index].ra_state == nrRA_gNB_IDLE) && (!cc->ra[ra_index].cfra))
break;
}
if (ra_index == NR_NB_RA_PROC_MAX) {
LOG_E(NR_MAC, "RA processes are not available for CFRA RNTI %04x\n", rnti);
return false;
}
NR_RA_t *ra = &cc->ra[ra_index];
NR_RA_t *ra = UE->ra;
ra->cfra = true;
ra->rnti = rnti;
ra->CellGroup = CellGroup;
NR_CellGroupConfig_t *CellGroup = UE->CellGroup;
DevAssert(CellGroup != NULL);
struct NR_CFRA *cfra = CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra;
uint8_t num_preamble = cfra->resources.choice.ssb->ssb_ResourceList.list.count;
ra->preambles.num_preambles = num_preamble;
NR_COMMON_channels_t *cc = &nrmac->common_channels[0];
for (int i = 0; i < cc->num_active_ssb; i++) {
for (int j = 0; j < num_preamble; j++) {
if (cc->ssb_index[i] == cfra->resources.choice.ssb->ssb_ResourceList.list.array[j]->ssb) {
@@ -1033,27 +1011,5 @@ bool nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig
}
}
}
LOG_I(NR_MAC, "Added new %s process for UE RNTI %04x with initial CellGroup\n", ra->cfra ? "CFRA" : "CBRA", rnti);
return true;
}
/* Prepare a new CellGroupConfig to be applied for this UE. We cannot
* immediatly apply it, as we have to wait for the reconfiguration through RRC.
* This function sets up everything to apply the reconfiguration. Later, we
* will trigger the UE inactivity with nr_mac_interrupt_ue_transmission(); upon
* expiry, nr_mac_apply_cellgroup() will apply the CellGroupConfig (radio
* config etc). */
bool nr_mac_prepare_cellgroup_update(gNB_MAC_INST *nrmac, NR_UE_info_t *UE, NR_CellGroupConfig_t *CellGroup)
{
DevAssert(nrmac != NULL);
DevAssert(UE != NULL);
DevAssert(CellGroup != NULL);
/* we assume that this function is mutex-protected from outside */
NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock);
UE->reconfigCellGroup = CellGroup;
UE->expect_reconfiguration = true;
return true;
LOG_I(NR_MAC, "Added new %s process for UE RNTI %04x with initial CellGroup\n", ra->cfra ? "CFRA" : "CBRA", UE->rnti);
}
File diff suppressed because it is too large Load Diff
@@ -323,7 +323,7 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP,
static void nr_store_dlsch_buffer(module_id_t module_id, frame_t frame, slot_t slot)
{
UE_iterator(RC.nrmac[module_id]->UE_info.list, UE) {
UE_iterator(RC.nrmac[module_id]->UE_info.connected_ue_list, UE) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
sched_ctrl->num_total_bytes = 0;
sched_ctrl->dl_pdus_total = 0;
@@ -609,9 +609,6 @@ static void pf_dl(module_id_t module_id,
/* Loop UE_info->list to check retransmission */
UE_iterator(UE_list, UE) {
if (!UE->Msg4_MsgB_ACKed)
continue;
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
NR_UE_DL_BWP_t *current_BWP = &UE->current_DL_BWP;
@@ -865,7 +862,7 @@ static void nr_dlsch_preprocessor(module_id_t module_id, frame_t frame, slot_t s
gNB_MAC_INST *mac = RC.nrmac[module_id];
NR_UEs_t *UE_info = &mac->UE_info;
if (UE_info->list[0] == NULL)
if (UE_info->connected_ue_list[0] == NULL)
return;
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
@@ -885,7 +882,7 @@ static void nr_dlsch_preprocessor(module_id_t module_id, frame_t frame, slot_t s
max_sched_ues = min(max_sched_ues, MAX_DCI_CORESET);
/* proportional fair scheduling algorithm */
pf_dl(module_id, frame, slot, UE_info->list, max_sched_ues, num_beams, n_rb_sched);
pf_dl(module_id, frame, slot, UE_info->connected_ue_list, max_sched_ues, num_beams, n_rb_sched);
}
nr_pp_impl_dl nr_init_dlsch_preprocessor(int CC_id) {
@@ -940,7 +937,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
const NR_BWP_t *initialDL = &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters;
gNB_mac->mac_stats.total_prb_aggregate += NRRIV2BW(initialDL->locationAndBandwidth, MAX_BWP_SIZE);
UE_iterator(UE_info->list, UE) {
UE_iterator(UE_info->connected_ue_list, UE) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
NR_UE_DL_BWP_t *current_BWP = &UE->current_DL_BWP;
@@ -62,7 +62,7 @@ void nr_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slot)
int slot_period = slot % mac->frame_structure.numb_slots_period;
if (!is_xlsch_in_slot(dlsch_slot_bitmap, slot_period))
return;
NR_UE_info_t *UE = mac->UE_info.list[0];
NR_UE_info_t *UE = mac->UE_info.connected_ue_list[0];
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP;
@@ -214,9 +214,9 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slo
/* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */
NR_COMMON_channels_t *cc = nr_mac->common_channels;
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
NR_UE_info_t *UE = nr_mac->UE_info.list[0];
NR_UE_info_t *UE = nr_mac->UE_info.connected_ue_list[0];
AssertFatal(nr_mac->UE_info.list[1] == NULL,
AssertFatal(nr_mac->UE_info.connected_ue_list[1] == NULL,
"cannot handle more than one UE\n");
if (UE == NULL)
return false;
@@ -125,16 +125,22 @@ static const uint16_t cqi_table3[16][2] = {{0, 0},
static void determine_aggregation_level_search_order(int agg_level_search_order[NUM_PDCCH_AGG_LEVELS],
float pdcch_cl_adjust);
uint8_t get_dl_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl,
const nr_dci_format_t dci_format) {
uint8_t get_dl_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl, const nr_dci_format_t dci_format)
{
// TODO check this but it should be enough for now
// if there is not csi report activated RI is 0 from initialization
if(dci_format == NR_DL_DCI_FORMAT_1_0)
return 1;
else
return (sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.ri + 1);
return sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.ri + 1;
}
int get_ul_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl, const nr_dci_format_t dci_format)
{
if(dci_format == NR_UL_DCI_FORMAT_0_0)
return 1;
else
return sched_ctrl->srs_feedback.ul_ri + 1;
}
// Table 5.2.2.2.1-3 and Table 5.2.2.2.1-4 in 38.214
@@ -292,7 +298,7 @@ NR_pdsch_dmrs_t get_dl_dmrs_params(const NR_ServingCellConfigCommon_t *scc,
int frontloaded_symb = 1; // default value
nr_dci_format_t dci_format = dl_bwp ? dl_bwp->dci_format : NR_DL_DCI_FORMAT_1_0;
if (dci_format == NR_DL_DCI_FORMAT_1_0) {
dmrs.numDmrsCdmGrpsNoData = tda_info->nrOfSymbols == 2 ? 1 : 2;
dmrs.numDmrsCdmGrpsNoData = tda_info->nrOfSymbols <= 2 ? 1 : 2;
dmrs.dmrs_ports_id = 0;
}
else {
@@ -394,10 +400,10 @@ NR_ControlResourceSet_t *get_coreset(gNB_MAC_INST *nrmac,
}
}
NR_SearchSpace_t *get_searchspace(NR_ServingCellConfigCommon_t *scc,
NR_BWP_DownlinkDedicated_t *bwp_Dedicated,
NR_SearchSpace__searchSpaceType_PR target_ss) {
static NR_SearchSpace_t *get_searchspace(NR_ServingCellConfigCommon_t *scc,
NR_BWP_DownlinkDedicated_t *bwp_Dedicated,
NR_SearchSpace__searchSpaceType_PR target_ss)
{
int n = 0;
if(bwp_Dedicated)
n = bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count;
@@ -696,7 +702,7 @@ NR_pusch_dmrs_t get_ul_dmrs_params(const NR_ServingCellConfigCommon_t *scc,
dmrs.num_dmrs_cdm_grps_no_data = 2;
} else {
if (ul_bwp->transform_precoding && Layers < 3)
dmrs.num_dmrs_cdm_grps_no_data = ul_bwp->dci_format == NR_UL_DCI_FORMAT_0_1 || tda_info->nrOfSymbols == 2 ? 1 : 2;
dmrs.num_dmrs_cdm_grps_no_data = ul_bwp->dci_format == NR_UL_DCI_FORMAT_0_1 || tda_info->nrOfSymbols <= 2 ? 1 : 2;
else
dmrs.num_dmrs_cdm_grps_no_data = 2;
}
@@ -2060,8 +2066,18 @@ void remove_front_nr_list(NR_list_t *listP)
NR_UE_info_t *find_nr_UE(NR_UEs_t *UEs, rnti_t rntiP)
{
UE_iterator(UEs->connected_ue_list, UE) {
if (UE->rnti == rntiP) {
LOG_D(NR_MAC,"Search and found rnti: %04x\n", rntiP);
return UE;
}
}
return NULL;
}
UE_iterator(UEs->list, UE) {
NR_UE_info_t *find_ra_UE(NR_UEs_t *UEs, rnti_t rntiP)
{
UE_iterator(UEs->access_ue_list, UE) {
if (UE->rnti == rntiP) {
LOG_D(NR_MAC,"Search and found rnti: %04x\n", rntiP);
return UE;
@@ -2073,7 +2089,6 @@ NR_UE_info_t *find_nr_UE(NR_UEs_t *UEs, rnti_t rntiP)
void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_allocator_t *uia)
{
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->reconfigCellGroup);
ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->capability);
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
seq_arr_free(&sched_ctrl->lc_config, NULL);
@@ -2088,6 +2103,7 @@ void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_alloca
free_sched_pucch_list(sched_ctrl);
uid_linear_allocator_free(uia, UE->uid);
LOG_I(NR_MAC, "Remove NR rnti 0x%04x\n", UE->rnti);
free_and_zero(UE->ra);
free(UE);
}
@@ -2195,31 +2211,17 @@ static void set_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl,
// main function to configure parameters of current BWP
void configure_UE_BWP(gNB_MAC_INST *nr_mac,
NR_ServingCellConfigCommon_t *scc,
NR_UE_sched_ctrl_t *sched_ctrl,
NR_RA_t *ra,
NR_UE_info_t *UE,
bool is_RA,
int target_ss,
int dl_bwp_switch,
int ul_bwp_switch)
{
AssertFatal((ra != NULL && UE == NULL) || (ra == NULL && UE != NULL), "RA and UE structures are mutually exlusive in BWP configuration\n");
NR_CellGroupConfig_t *CellGroup = UE->CellGroup;
NR_UE_ServingCell_Info_t *sc_info = &UE->sc_info;
NR_UE_DL_BWP_t *DL_BWP = &UE->current_DL_BWP;
NR_UE_UL_BWP_t *UL_BWP = &UE->current_UL_BWP;
NR_CellGroupConfig_t *CellGroup;
NR_UE_ServingCell_Info_t *sc_info;
NR_UE_DL_BWP_t *DL_BWP;
NR_UE_UL_BWP_t *UL_BWP;
if (ra) {
DL_BWP = &ra->DL_BWP;
UL_BWP = &ra->UL_BWP;
CellGroup = ra->CellGroup;
sc_info = &ra->sc_info;
}
else {
DL_BWP = &UE->current_DL_BWP;
UL_BWP = &UE->current_UL_BWP;
CellGroup = UE->CellGroup;
sc_info = &UE->sc_info;
}
NR_BWP_Downlink_t *dl_bwp = NULL;
NR_BWP_Uplink_t *ul_bwp = NULL;
NR_BWP_DownlinkDedicated_t *bwpd = NULL;
@@ -2230,15 +2232,10 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
int old_dl_bwp_id = DL_BWP->bwp_id;
int old_ul_bwp_id = UL_BWP->bwp_id;
int target_ss;
NR_ServingCellConfig_t *servingCellConfig = NULL;
if (CellGroup &&
CellGroup->spCellConfig &&
CellGroup->spCellConfig->spCellConfigDedicated) {
if (CellGroup && CellGroup->spCellConfig && CellGroup->spCellConfig->spCellConfigDedicated) {
servingCellConfig = CellGroup->spCellConfig->spCellConfigDedicated;
target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
if(dl_bwp_switch >= 0 && ul_bwp_switch >= 0) {
AssertFatal(dl_bwp_switch == ul_bwp_switch, "Different UL and DL BWP not supported\n");
@@ -2298,7 +2295,6 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
else {
DL_BWP->bwp_id = 0;
UL_BWP->bwp_id = 0;
target_ss = NR_SearchSpace__searchSpaceType_PR_common;
DL_BWP->pdsch_Config = NULL;
UL_BWP->pusch_Config = NULL;
UL_BWP->pucch_Config = NULL;
@@ -2359,7 +2355,10 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
UL_BWP->rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup;
}
if(UE) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
// Reset required fields in sched_ctrl (e.g. ul_ri and tpmi)
reset_sched_ctrl(sched_ctrl);
if(!is_RA) {
if (servingCellConfig) {
if (servingCellConfig->csi_MeasConfig) {
sc_info->csi_MeasConfig = servingCellConfig->csi_MeasConfig->choice.setup;
@@ -2398,23 +2397,16 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
sc_info->nrofHARQ_ProcessesForPUSCH_r17 = pusch_servingcellconfig->ext3->nrofHARQ_ProcessesForPUSCH_r17;
}
}
create_dl_harq_list(sched_ctrl, sc_info);
create_ul_harq_list(sched_ctrl, sc_info);
}
if (CellGroup && CellGroup->physicalCellGroupConfig)
UE->pdsch_HARQ_ACK_Codebook = CellGroup->physicalCellGroupConfig->pdsch_HARQ_ACK_Codebook;
// Reset required fields in sched_ctrl (e.g. ul_ri and tpmi)
reset_sched_ctrl(sched_ctrl);
// setting PDCCH related structures for sched_ctrl
sched_ctrl->search_space = get_searchspace(scc,
bwpd,
target_ss);
sched_ctrl->coreset = get_coreset(nr_mac,
scc,
bwpd,
sched_ctrl->search_space,
target_ss);
sched_ctrl->search_space = get_searchspace(scc, bwpd, target_ss);
sched_ctrl->coreset = get_coreset(nr_mac, scc, bwpd, sched_ctrl->search_space, target_ss);
sched_ctrl->sched_pdcch = set_pdcch_structure(nr_mac,
sched_ctrl->search_space,
@@ -2436,11 +2428,7 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
NR_UL_DCI_FORMAT_0_1 : NR_UL_DCI_FORMAT_0_0) :
NR_UL_DCI_FORMAT_0_0;
set_max_fb_time(UL_BWP, DL_BWP);
set_sched_pucch_list(sched_ctrl, UL_BWP, scc, &nr_mac->frame_structure);
}
if(ra) {
} else {
// setting PDCCH related structures for RA
struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList = NULL;
NR_SearchSpaceId_t ra_SearchSpace = 0;
@@ -2453,26 +2441,29 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
}
AssertFatal(commonSearchSpaceList->list.count > 0, "common SearchSpace list has 0 elements\n");
for (int i = 0; i < commonSearchSpaceList->list.count; i++) {
NR_SearchSpace_t * ss = commonSearchSpaceList->list.array[i];
NR_SearchSpace_t *ss = commonSearchSpaceList->list.array[i];
if (ss->searchSpaceId == ra_SearchSpace)
ra->ra_ss = ss;
sched_ctrl->search_space = ss;
}
AssertFatal(ra->ra_ss!=NULL,"SearchSpace cannot be null for RA\n");
AssertFatal(sched_ctrl->search_space != NULL, "SearchSpace cannot be null for RA\n");
ra->coreset = get_coreset(nr_mac, scc, dl_bwp, ra->ra_ss, NR_SearchSpace__searchSpaceType_PR_common);
sched_ctrl->coreset = get_coreset(nr_mac, scc, dl_bwp, sched_ctrl->search_space, NR_SearchSpace__searchSpaceType_PR_common);
NR_COMMON_channels_t *cc = &nr_mac->common_channels[0];
int ssb_index = cc->ssb_index[ra->beam_id];
ra->sched_pdcch = set_pdcch_structure(nr_mac,
ra->ra_ss,
ra->coreset,
scc,
&dl_genericParameters,
&nr_mac->type0_PDCCH_CSS_config[ssb_index]);
int ssb_index = cc->ssb_index[UE->UE_beam_index];
sched_ctrl->sched_pdcch = set_pdcch_structure(nr_mac,
sched_ctrl->search_space,
sched_ctrl->coreset,
scc,
&dl_genericParameters,
&nr_mac->type0_PDCCH_CSS_config[ssb_index]);
UL_BWP->dci_format = NR_UL_DCI_FORMAT_0_0;
DL_BWP->dci_format = NR_DL_DCI_FORMAT_1_0;
}
set_max_fb_time(UL_BWP, DL_BWP);
set_sched_pucch_list(sched_ctrl, UL_BWP, scc, &nr_mac->frame_structure);
// Set MCS tables
long *dl_mcs_Table = DL_BWP->pdsch_Config ? DL_BWP->pdsch_Config->mcs_Table : NULL;
DL_BWP->mcsTableIdx = get_pdsch_mcs_table(dl_mcs_Table, DL_BWP->dci_format, TYPE_C_RNTI_, target_ss);
@@ -2482,9 +2473,7 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
// Set uplink MCS table
long *mcs_Table = NULL;
if (UL_BWP->pusch_Config)
mcs_Table = UL_BWP->transform_precoding ?
UL_BWP->pusch_Config->mcs_Table :
UL_BWP->pusch_Config->mcs_TableTransformPrecoder;
mcs_Table = UL_BWP->transform_precoding ? UL_BWP->pusch_Config->mcs_Table : UL_BWP->pusch_Config->mcs_TableTransformPrecoder;
UL_BWP->mcs_table = get_pusch_mcs_table(mcs_Table, !UL_BWP->transform_precoding, UL_BWP->dci_format, TYPE_C_RNTI_, target_ss, false);
}
@@ -2502,49 +2491,29 @@ static void init_bler_stats(const NR_bler_options_t *bler_options, NR_bler_stats
bler_stats->bler = (float)(bler_options->lower + bler_options->upper) / 2.0f;
}
//------------------------------------------------------------------------------
NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConfig_t *CellGroup)
/* @brief returns a new UE allocated instance.
*
* It will be typically added to the access_ue_list, but not always (e.g.,
* phytest mode), so this is not done in this function (and also, to allow
* error handling). Remove with delete_nr_ue_data(). */
NR_UE_info_t *get_new_nr_ue_inst(uid_allocator_t *uia, rnti_t rnti, NR_CellGroupConfig_t *CellGroup)
{
NR_ServingCellConfigCommon_t *scc = nr_mac->common_channels[0].ServingCellConfigCommon;
NR_UEs_t *UE_info = &nr_mac->UE_info;
LOG_I(NR_MAC, "Adding new UE context with RNTI 0x%04x\n", rntiP);
dump_nr_list(UE_info->list);
// We will attach at the end, to mitigate race conditions
// This is not good, but we will fix it progressively
NR_UE_info_t *UE = calloc(1, sizeof(NR_UE_info_t));
if(!UE) {
LOG_E(NR_MAC,"want to add UE %04x but the fixed allocated size is full\n",rntiP);
uid_t uid = uid_linear_allocator_new(uia);
/* if the UE list is full, we should reject the UE with an RRC reject
* message, but we do not have this functionality. To keep it simple, do not
* create a UE context here, so we can print an error message. */
if (uid >= MAX_MOBILES_PER_GNB) {
uid_linear_allocator_free(uia, uid);
return NULL;
}
UE->rnti = rntiP;
UE->uid = uid_linear_allocator_new(&UE_info->uid_allocator);
NR_UE_info_t *UE = calloc_or_fail(1, sizeof(NR_UE_info_t));
UE->rnti = rnti;
UE->CellGroup = CellGroup;
UE->Msg4_MsgB_ACKed = CellGroup != NULL;
UE->uid = uid;
UE->ra = calloc(1, sizeof(*UE->ra));
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
memset(sched_ctrl, 0, sizeof(*sched_ctrl));
sched_ctrl->dl_max_mcs = 28; /* do not limit MCS for individual UEs */
sched_ctrl->ta_update = 31;
sched_ctrl->sched_srs.frame = -1;
sched_ctrl->sched_srs.slot = -1;
sched_ctrl->pdcch_cl_adjust = 0;
// Initialize bler_stats
init_bler_stats(&nr_mac->dl_bler, &sched_ctrl->dl_bler_stats, nr_mac->frame);
init_bler_stats(&nr_mac->ul_bler, &sched_ctrl->ul_bler_stats, nr_mac->frame);
// initialize LCID structure
seq_arr_init(&sched_ctrl->lc_config, sizeof(nr_lc_config_t));
// initialize UE BWP information
NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP;
memset(dl_bwp, 0, sizeof(*dl_bwp));
NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP;
memset(ul_bwp, 0, sizeof(*ul_bwp));
configure_UE_BWP(nr_mac, scc, sched_ctrl, NULL, UE, -1, -1);
/* set illegal time domain allocation to force recomputation of all fields */
sched_ctrl->sched_pdsch.time_domain_allocation = -1;
@@ -2558,27 +2527,87 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf
create_dl_harq_list(sched_ctrl, &UE->sc_info);
create_ul_harq_list(sched_ctrl, &UE->sc_info);
reset_srs_stats(UE);
// initialize LCID structure
seq_arr_init(&sched_ctrl->lc_config, sizeof(nr_lc_config_t));
return UE;
}
NR_SCHED_LOCK(&UE_info->mutex);
int i;
for(i=0; i<MAX_MOBILES_PER_GNB; i++) {
if (UE_info->list[i] == NULL) {
UE_info->list[i] = UE;
break;
bool add_UE_to_list(int list_size, NR_UE_info_t *list[list_size], NR_UE_info_t *UE)
{
for (int i = 0; i < list_size; i++) {
if (!list[i]) {
list[i] = UE;
return true;
}
}
if (i == MAX_MOBILES_PER_GNB) {
LOG_E(NR_MAC,"Try to add UE %04x but the list is full\n", rntiP);
delete_nr_ue_data(UE, nr_mac->common_channels, &UE_info->uid_allocator);
NR_SCHED_UNLOCK(&UE_info->mutex);
return NULL;
}
NR_SCHED_UNLOCK(&UE_info->mutex);
return false;
}
LOG_D(NR_MAC, "Add NR rnti %x\n", rntiP);
dump_nr_list(UE_info->list);
return (UE);
NR_UE_info_t *remove_UE_from_list(int list_size, NR_UE_info_t *list[list_size], rnti_t rnti)
{
for (int i = 0; i < list_size; i++) {
NR_UE_info_t *curr_UE = list[i];
if (curr_UE->rnti != rnti)
continue;
/* remove this UE from the list, return the pointer */
memmove(&list[i], &list[i+1], sizeof(list[0]) * (list_size - i - 1));
list[list_size - 1] = NULL;
return curr_UE;
}
LOG_E(NR_MAC, "UE %04x to be removed not found in list\n", rnti);
return NULL;
}
/** @brief Transitions a UE from access list to connected list (i.e., the RA
* list to the "normal" UE context list. */
bool transition_ra_connected_nr_ue(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE)
{
NR_UEs_t *UE_info = &nr_mac->UE_info;
// remove UE from initial access list (moved to connected mode)
NR_UE_info_t *r = remove_UE_from_list(NR_NB_RA_PROC_MAX, UE_info->access_ue_list, UE->rnti);
DevAssert(r == UE); /* sanity check: we should have removed the current UE ptr from list */
free_and_zero(UE->ra);
return add_connected_nr_ue(nr_mac, UE);
}
/** @brief Add a UE to the list of UEs in * connected mode.
*
* To remove the UE, use mac_remove_nr_ue(). */
bool add_connected_nr_ue(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE)
{
LOG_I(NR_MAC, "Adding new UE context with RNTI 0x%04x\n", UE->rnti);
NR_UEs_t *UE_info = &nr_mac->UE_info;
dump_nr_list(UE_info->connected_ue_list);
AssertFatal(!UE->ra, "UE in connected cannot have RA process\n");
NR_SCHED_LOCK(&UE_info->mutex);
bool success = add_UE_to_list(MAX_MOBILES_PER_GNB, UE_info->connected_ue_list, UE);
if (!success) {
LOG_E(NR_MAC,"Try to add UE %04x but the list is full\n", UE->rnti);
delete_nr_ue_data(UE, NULL, &UE_info->uid_allocator);
NR_SCHED_UNLOCK(&UE_info->mutex);
return false;
}
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
sched_ctrl->dl_max_mcs = 28; /* do not limit MCS for individual UEs */
sched_ctrl->sched_srs.frame = -1;
sched_ctrl->sched_srs.slot = -1;
sched_ctrl->pdcch_cl_adjust = 0;
reset_srs_stats(UE);
// Initialize bler_stats
init_bler_stats(&nr_mac->dl_bler, &sched_ctrl->dl_bler_stats, nr_mac->frame);
init_bler_stats(&nr_mac->ul_bler, &sched_ctrl->ul_bler_stats, nr_mac->frame);
NR_SCHED_UNLOCK(&UE_info->mutex);
dump_nr_list(UE_info->connected_ue_list);
return true;
}
void free_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl)
@@ -2683,38 +2712,11 @@ void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti)
{
/* already mutex protected */
NR_SCHED_ENSURE_LOCKED(&nr_mac->sched_lock);
NR_UEs_t *UE_info = &nr_mac->UE_info;
NR_SCHED_LOCK(&UE_info->mutex);
UE_iterator(UE_info->list, UE) {
if (UE->rnti==rnti)
break;
}
if (!UE) {
LOG_W(NR_MAC,"Call to del rnti %04x, but not existing\n", rnti);
NR_SCHED_UNLOCK(&UE_info->mutex);
return;
}
NR_UE_info_t * newUEs[MAX_MOBILES_PER_GNB+1]={0};
int newListIdx=0;
for (int i=0; i<MAX_MOBILES_PER_GNB; i++)
if(UE_info->list[i] && UE_info->list[i]->rnti != rnti)
newUEs[newListIdx++]=UE_info->list[i];
memcpy(UE_info->list, newUEs, sizeof(UE_info->list));
NR_UE_info_t *UE = remove_UE_from_list(MAX_MOBILES_PER_GNB + 1, UE_info->connected_ue_list, rnti);
NR_SCHED_UNLOCK(&UE_info->mutex);
const int CC_id = 0;
NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id];
for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
NR_RA_t *ra = &cc->ra[i];
if (ra->rnti == UE->rnti) {
nr_clear_ra_proc(ra);
ra->cfra = 0;
}
}
delete_nr_ue_data(UE, nr_mac->common_channels, &UE_info->uid_allocator);
}
@@ -2799,7 +2801,7 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, slot_t slot, nfapi_nr_dl_tt
UE_info->sched_csirs = 0;
UE_iterator(UE_info->list, UE) {
UE_iterator(UE_info->connected_ue_list, UE) {
NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP;
// CSI-RS is common to all UEs in a given BWP
@@ -3030,7 +3032,7 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, slot_t slot, nfapi_nr_dl_tt
}
}
static void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group)
void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group)
{
DevAssert(cell_group != NULL);
/* remove a reconfigurationWithSync, we don't need it anymore */
@@ -3050,38 +3052,6 @@ static void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group)
free_and_zero(cell_group->rlc_BearerToAddModList->list.array[i]->reestablishRLC);
}
static void nr_mac_apply_cellgroup(gNB_MAC_INST *mac, NR_UE_info_t *UE, frame_t frame, slot_t slot)
{
LOG_D(NR_MAC, "%4d.%2d RNTI %04x: UE inactivity timer expired\n", frame, slot, UE->rnti);
/* check if there is a new CellGroupConfig to be applied */
if (UE->interrupt_action == FOLLOW_INSYNC_RECONFIG && UE->reconfigCellGroup != NULL) {
LOG_D(NR_MAC, "%4d.%2d RNTI %04x: Apply CellGroupConfig after UE inactivity\n", frame, slot, UE->rnti);
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
UE->CellGroup = UE->reconfigCellGroup;
UE->reconfigCellGroup = NULL;
UE->interrupt_action = FOLLOW_INSYNC;
if (LOG_DEBUGFLAG(DEBUG_ASN1))
xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *)UE->CellGroup);
nr_mac_clean_cellgroup(UE->CellGroup);
}
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
configure_UE_BWP(mac, scc, sched_ctrl, NULL, UE, -1, -1);
reset_srs_stats(UE);
if (IS_SA_MODE(get_softmodem_params())) {
// add all available DL,UL HARQ processes for this UE in SA
create_dl_harq_list(sched_ctrl, &UE->sc_info);
create_ul_harq_list(sched_ctrl, &UE->sc_info);
}
}
int nr_mac_get_reconfig_delay_slots(NR_SubcarrierSpacing_t scs)
{
/* we previously assumed a specific "slot ahead" value for the PHY processing
@@ -3109,7 +3079,7 @@ int nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, interr
// frames, after the inactivity of the UE.
UE->UE_sched_ctrl.ta_frame = (mac->frame - 1 + 1024) % 1024;
LOG_D(NR_MAC, "UE %04x: Interrupt UE transmission (%d slots) action %d reconfigCellGroup %p\n", UE->rnti, slots, UE->interrupt_action, UE->reconfigCellGroup);
LOG_D(NR_MAC, "UE %04x: Interrupt UE transmission (%d slots) action %d\n", UE->rnti, slots, UE->interrupt_action);
return 0;
}
@@ -3161,7 +3131,7 @@ void nr_mac_update_timers(module_id_t module_id, frame_t frame, slot_t slot)
NR_SCHED_ENSURE_LOCKED(&mac->sched_lock);
NR_UEs_t *UE_info = &mac->UE_info;
UE_iterator(UE_info->list, UE) {
UE_iterator(UE_info->connected_ue_list, UE) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
if (nr_mac_check_release(sched_ctrl, UE->rnti)) {
@@ -3182,8 +3152,6 @@ void nr_mac_update_timers(module_id_t module_id, frame_t frame, slot_t slot)
nr_timer_stop(&sched_ctrl->transm_interrupt);
if (UE->interrupt_action == FOLLOW_OUTOFSYNC)
nr_mac_trigger_ul_failure(sched_ctrl, UE->current_DL_BWP.scs);
else
nr_mac_apply_cellgroup(mac, UE, frame, slot);
}
}
}
@@ -3519,24 +3487,14 @@ bool nr_mac_remove_lcid(NR_UE_sched_ctrl_t *sched_ctrl, long lcid)
return true;
}
static const NR_RA_t *find_nr_RA_rnti(const NR_RA_t *ra_base, int ra_count, rnti_t rnti)
{
for (int i = 0; i < ra_count; ++i) {
const NR_RA_t *ra = &ra_base[i];
if (ra->ra_state != nrRA_gNB_IDLE && ra->rnti == rnti)
return ra;
}
return NULL;
}
bool nr_mac_get_new_rnti(NR_UEs_t *UEs, const NR_RA_t *ra_base, int ra_count, rnti_t *rnti)
bool nr_mac_get_new_rnti(NR_UEs_t *UEs, rnti_t *rnti)
{
int loop = 0;
bool exist_connected_ue, exist_in_pending_ra_ue;
do {
*rnti = (taus() % 0xffef) + 1;
exist_connected_ue = find_nr_UE(UEs, *rnti) != NULL;
exist_in_pending_ra_ue = find_nr_RA_rnti(ra_base, ra_count, *rnti) != NULL;
exist_in_pending_ra_ue = find_ra_UE(UEs, *rnti) != NULL;
loop++;
} while (loop < 100 && (exist_connected_ue || exist_in_pending_ra_ue));
return loop < 100; // nothing found: loop count 100
@@ -521,7 +521,7 @@ void nr_schedule_srs(int module_id, frame_t frame, int slot)
NR_UEs_t *UE_info = &nrmac->UE_info;
UE_iterator(UE_info->list, UE) {
UE_iterator(UE_info->connected_ue_list, UE) {
const int CC_id = 0;
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
NR_UE_UL_BWP_t *current_BWP = &UE->current_UL_BWP;
+59 -37
View File
@@ -171,39 +171,54 @@ static int get_pucch_index(int frame, int slot, const frame_structure_t *fs, int
return (frame_start + ul_period_start + ul_period_slot) % sched_pucch_size;
}
void nr_schedule_pucch(gNB_MAC_INST *nrmac, frame_t frameP, slot_t slotP)
static void schedule_pucch_core(gNB_MAC_INST *nrmac, NR_UE_info_t *UE, frame_t frame, slot_t slot)
{
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
const int pucch_index = get_pucch_index(frame, slot, &nrmac->frame_structure, sched_ctrl->sched_pucch_size);
NR_sched_pucch_t *curr_pucch = &UE->UE_sched_ctrl.sched_pucch[pucch_index];
if (!curr_pucch->active)
return;
if (frame != curr_pucch->frame || slot != curr_pucch->ul_slot) {
LOG_E(NR_MAC,
"PUCCH frame/slot mismatch: current %4d.%2d vs. request %4d.%2d: not scheduling PUCCH\n",
curr_pucch->frame,
curr_pucch->ul_slot,
frame,
slot);
memset(curr_pucch, 0, sizeof(*curr_pucch));;
return;
}
const uint16_t O_ack = curr_pucch->dai_c;
const uint16_t O_csi = curr_pucch->csi_bits;
const uint8_t O_sr = curr_pucch->sr_flag;
LOG_D(NR_MAC,
"Scheduling PUCCH[%d] RX for UE %04x in %4d.%2d O_ack %d, O_sr %d, O_csi %d\n",
pucch_index,
UE->rnti,
curr_pucch->frame,
curr_pucch->ul_slot,
O_ack,O_sr,
O_csi);
nr_fill_nfapi_pucch(nrmac, frame, slot, curr_pucch, UE);
memset(curr_pucch, 0, sizeof(*curr_pucch));
}
void nr_schedule_pucch(gNB_MAC_INST *nrmac, frame_t frame, slot_t slot)
{
/* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */
NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock);
if (!is_ul_slot(slotP, &nrmac->frame_structure))
if (!is_ul_slot(slot, &nrmac->frame_structure))
return;
UE_iterator(nrmac->UE_info.list, UE) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
const int pucch_index = get_pucch_index(frameP, slotP, &nrmac->frame_structure, sched_ctrl->sched_pucch_size);
NR_sched_pucch_t *curr_pucch = &UE->UE_sched_ctrl.sched_pucch[pucch_index];
if (!curr_pucch->active)
continue;
if (frameP != curr_pucch->frame || slotP != curr_pucch->ul_slot) {
LOG_E(NR_MAC,
"PUCCH frame/slot mismatch: current %4d.%2d vs. request %4d.%2d: not scheduling PUCCH\n",
curr_pucch->frame,
curr_pucch->ul_slot,
frameP,
slotP);
memset(curr_pucch, 0, sizeof(*curr_pucch));;
continue;
}
const uint16_t O_ack = curr_pucch->dai_c;
const uint16_t O_csi = curr_pucch->csi_bits;
const uint8_t O_sr = curr_pucch->sr_flag;
LOG_D(NR_MAC,"Scheduling PUCCH[%d] RX for UE %04x in %4d.%2d O_ack %d, O_sr %d, O_csi %d\n",
pucch_index,UE->rnti,curr_pucch->frame,curr_pucch->ul_slot,O_ack,O_sr,O_csi);
nr_fill_nfapi_pucch(nrmac, frameP, slotP, curr_pucch, UE);
memset(curr_pucch, 0, sizeof(*curr_pucch));
UE_iterator(nrmac->UE_info.access_ue_list, init_UE) {
if (init_UE->ra->ra_state == nrRA_WAIT_Msg4_MsgB_ACK)
schedule_pucch_core(nrmac, init_UE, frame, slot);
}
UE_iterator(nrmac->UE_info.connected_ue_list, UE) {
schedule_pucch_core(nrmac, UE, frame, slot);
}
}
@@ -217,7 +232,7 @@ void nr_csi_meas_reporting(int Mod_idP,frame_t frame, slot_t slot)
/* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */
NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock);
UE_iterator(nrmac->UE_info.list, UE ) {
UE_iterator(nrmac->UE_info.connected_ue_list, UE) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP;
const int n_slots_frame = nrmac->frame_structure.numb_slots_frame;
@@ -854,14 +869,19 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, frame_t frame, slot_t slot, con
gNB_MAC_INST *nrmac = RC.nrmac[mod_id];
int rssi_threshold = nrmac->pucch_rssi_threshold;
NR_SCHED_LOCK(&nrmac->sched_lock);
NR_UE_info_t * UE = find_nr_UE(&nrmac->UE_info, uci_01->rnti);
NR_UE_info_t *UE = find_nr_UE(&nrmac->UE_info, uci_01->rnti);
bool is_ra = false;
if (!UE) {
LOG_E(NR_MAC, "%s(): unknown RNTI %04x in PUCCH UCI\n", __func__, uci_01->rnti);
NR_SCHED_UNLOCK(&nrmac->sched_lock);
return;
UE = find_ra_UE(&nrmac->UE_info, uci_01->rnti);
if (UE)
is_ra = true;
else {
LOG_E(NR_MAC, "Unknown RNTI %04x in PUCCH UCI\n", uci_01->rnti);
NR_SCHED_UNLOCK(&nrmac->sched_lock);
return;
}
}
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
if (((uci_01->pduBitmap >> 1) & 0x01)) {
// iterate over received harq bits
for (int harq_bit = 0; harq_bit < uci_01->harq.num_harq; harq_bit++) {
@@ -877,10 +897,12 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, frame_t frame, slot_t slot, con
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,harq_value);
nr_mac_update_pdcch_closed_loop_adjust(sched_ctrl, harq_confidence != 0);
handle_dl_harq(UE, pid, harq_value == 0 && harq_confidence == 0, nrmac->dl_bler.harq_round_max);
if (!UE->Msg4_MsgB_ACKed && harq_value == 0 && harq_confidence == 0)
UE->Msg4_MsgB_ACKed = true;
if (harq_confidence == 1) UE->mac_stats.pucch0_DTX++;
bool success = harq_value == 0 && harq_confidence == 0;
handle_dl_harq(UE, pid, success, nrmac->dl_bler.harq_round_max);
if (is_ra)
nr_check_Msg4_MsgB_Ack(mod_id, frame, slot, UE, success);
if (harq_confidence == 1)
UE->mac_stats.pucch0_DTX++;
}
// tpc (power control) only if we received AckNack
@@ -1219,7 +1241,7 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, slot_t slot)
if (!is_ul_slot(slot, &nrmac->frame_structure))
return;
const int CC_id = 0;
UE_iterator(nrmac->UE_info.list, UE) {
UE_iterator(nrmac->UE_info.connected_ue_list, UE) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP;
const int n_slots_frame = nrmac->frame_structure.numb_slots_frame;
+206 -271
View File
@@ -56,7 +56,7 @@ int get_ul_tda(gNB_MAC_INST *nrmac, int frame, int slot)
}
// Avoid slots with the SRS
UE_iterator(nrmac->UE_info.list, UE) {
UE_iterator(nrmac->UE_info.connected_ue_list, UE) {
NR_sched_srs_t sched_srs = UE->UE_sched_ctrl.sched_srs;
if(sched_srs.srs_scheduled && sched_srs.frame == frame && sched_srs.slot == slot)
return 1;
@@ -461,17 +461,13 @@ static int nr_process_mac_pdu(instance_t module_idP,
break;
case UL_SCH_LCID_C_RNTI:
for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
NR_RA_t *ra = &RC.nrmac[module_idP]->common_channels[CC_id].ra[i];
if (ra->ra_state == nrRA_gNB_IDLE && ra->rnti == UE->rnti) {
// Extract C-RNTI value
rnti_t crnti = ((pduP[1] & 0xFF) << 8) | (pduP[2] & 0xFF);
AssertFatal(false,
"Received MAC CE for C-RNTI %04x without RA running, procedure exists? Or is it a bug while decoding the "
"MAC PDU?\n",
crnti);
break;
}
if (UE->ra && UE->ra->ra_state == nrRA_gNB_IDLE) {
// Extract C-RNTI value
rnti_t crnti = ((pduP[1] & 0xFF) << 8) | (pduP[2] & 0xFF);
AssertFatal(false,
"Received MAC CE for C-RNTI %04x without RA running, procedure exists? Or is it a bug while decoding the "
"MAC PDU?\n",
crnti);
}
break;
@@ -547,65 +543,31 @@ static void abort_nr_ul_harq(NR_UE_info_t *UE, int8_t harq_pid)
sched_ctrl->sched_ul_bytes = 0;
}
static bool get_UE_waiting_CFRA_msg3(const gNB_MAC_INST *gNB_mac,
const int CC_id,
const frame_t frame,
const slot_t slot,
rnti_t rnti)
static void handle_nr_ul_harq(gNB_MAC_INST *nrmac,
NR_UE_info_t *UE,
frame_t frame,
slot_t slot,
rnti_t rnti,
int crc_harq_id,
bool crc_status)
{
bool UE_waiting_CFRA_msg3 = false;
for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
const NR_RA_t *ra = &gNB_mac->common_channels[CC_id].ra[i];
if (ra->cfra && ra->ra_state == nrRA_WAIT_Msg3 && frame == ra->Msg3_frame && slot == ra->Msg3_slot && rnti == ra->rnti) {
UE_waiting_CFRA_msg3 = true;
break;
}
}
return UE_waiting_CFRA_msg3;
}
void handle_nr_ul_harq(const int CC_idP, module_id_t mod_id, frame_t frame, slot_t slot, const nfapi_nr_crc_t *crc_pdu)
{
gNB_MAC_INST *nrmac = RC.nrmac[mod_id];
if (nrmac->radio_config.disable_harq) {
LOG_D(NR_MAC, "skipping UL feedback handling as HARQ is disabled\n");
return;
}
NR_SCHED_LOCK(&nrmac->sched_lock);
for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) {
NR_RA_t *ra = &nrmac->common_channels[CC_idP].ra[i];
// if we find any ongoing RA that has already scheduled MSG3
// and it is expecting its reception in current frame and slot with matching RNTI
// we can exit the function (no HARQ involved)
if (ra->ra_state >= nrRA_WAIT_Msg3 && ra->rnti == crc_pdu->rnti && frame == ra->Msg3_frame && slot == ra->Msg3_slot) {
LOG_D(NR_MAC, "UL for rnti %04x in RA (MSG3), no need to process HARQ\n", crc_pdu->rnti);
NR_SCHED_UNLOCK(&nrmac->sched_lock);
return;
}
}
NR_UE_info_t *UE = find_nr_UE(&nrmac->UE_info, crc_pdu->rnti);
if (!UE) {
NR_SCHED_UNLOCK(&nrmac->sched_lock);
LOG_E(NR_MAC, "Couldn't identify UE connected with current UL HARQ process\n");
return;
}
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
int8_t harq_pid = sched_ctrl->feedback_ul_harq.head;
LOG_D(NR_MAC, "Comparing crc_pdu->harq_id vs feedback harq_pid = %d %d\n",crc_pdu->harq_id, harq_pid);
while (crc_pdu->harq_id != harq_pid || harq_pid < 0) {
LOG_W(NR_MAC, "Unexpected ULSCH HARQ PID %d (have %d) for RNTI 0x%04x\n", crc_pdu->harq_id, harq_pid, crc_pdu->rnti);
if (harq_pid < 0) {
NR_SCHED_UNLOCK(&nrmac->sched_lock);
LOG_D(NR_MAC, "Comparing crc harq_id vs feedback harq_pid = %d %d\n", crc_harq_id, harq_pid);
while (crc_harq_id != harq_pid || harq_pid < 0) {
LOG_W(NR_MAC, "Unexpected ULSCH HARQ PID %d (have %d) for RNTI 0x%04x\n", crc_harq_id, harq_pid, rnti);
if (harq_pid < 0)
return;
}
remove_front_nr_list(&sched_ctrl->feedback_ul_harq);
sched_ctrl->ul_harq_processes[harq_pid].is_waiting = false;
if(sched_ctrl->ul_harq_processes[harq_pid].round >= RC.nrmac[mod_id]->ul_bler.harq_round_max - 1) {
if(sched_ctrl->ul_harq_processes[harq_pid].round >= nrmac->ul_bler.harq_round_max - 1) {
abort_nr_ul_harq(UE, harq_pid);
} else {
sched_ctrl->ul_harq_processes[harq_pid].round++;
@@ -618,52 +580,211 @@ void handle_nr_ul_harq(const int CC_idP, module_id_t mod_id, frame_t frame, slot
DevAssert(harq->is_waiting);
harq->feedback_slot = -1;
harq->is_waiting = false;
if (!crc_pdu->tb_crc_status) {
if (!crc_status) {
finish_nr_ul_harq(sched_ctrl, harq_pid);
LOG_D(NR_MAC,
"Ulharq id %d crc passed for RNTI %04x\n",
harq_pid,
crc_pdu->rnti);
} else if (harq->round >= RC.nrmac[mod_id]->ul_bler.harq_round_max - 1) {
rnti);
} else if (harq->round >= nrmac->ul_bler.harq_round_max - 1) {
abort_nr_ul_harq(UE, harq_pid);
LOG_D(NR_MAC,
"RNTI %04x: Ulharq id %d crc failed in all rounds\n",
crc_pdu->rnti,
rnti,
harq_pid);
} else {
harq->round++;
LOG_D(NR_MAC,
"Ulharq id %d crc failed for RNTI %04x\n",
harq_pid,
crc_pdu->rnti);
rnti);
add_tail_nr_list(&sched_ctrl->retrans_ul_harq, harq_pid);
}
NR_SCHED_UNLOCK(&nrmac->sched_lock);
}
static void handle_msg3_failed_rx(NR_RA_t *ra, int i, int harq_round_max)
static void handle_msg3_failed_rx(gNB_MAC_INST *mac, NR_RA_t *ra, rnti_t rnti, int harq_round_max)
{
// for CFRA (NSA) do not schedule retransmission of msg3
if (ra->cfra) {
LOG_D(NR_MAC, "Random Access %i failed at state %s (NSA msg3 reception failed)\n", i, nrra_text[ra->ra_state]);
nr_clear_ra_proc(ra);
LOG_W(NR_MAC, "UE %04x RA failed at state %s (NSA msg3 reception failed)\n", rnti, nrra_text[ra->ra_state]);
nr_release_ra_UE(mac, rnti);
return;
}
if (ra->msg3_round >= harq_round_max - 1) {
LOG_W(NR_MAC, "Random Access %i failed at state %s (Reached msg3 max harq rounds)\n", i, nrra_text[ra->ra_state]);
nr_clear_ra_proc(ra);
LOG_W(NR_MAC, "UE %04x RA failed at state %s (Reached msg3 max harq rounds)\n", rnti, nrra_text[ra->ra_state]);
nr_release_ra_UE(mac, rnti);
return;
}
LOG_D(NR_MAC, "Random Access %i Msg3 CRC did not pass\n", i);
LOG_D(NR_MAC, "UE %04x Msg3 CRC did not pass\n", rnti);
ra->msg3_round++;
ra->ra_state = nrRA_Msg3_retransmission;
}
/*
* When data are received on PHY and transmitted to MAC
*/
static void nr_rx_ra_sdu(const module_id_t mod_id,
const int CC_id,
const frame_t frame,
const sub_frame_t slot,
rnti_t rnti,
uint8_t *sdu,
const uint32_t sdu_len,
const uint16_t timing_advance,
const uint8_t ul_cqi,
const uint16_t rssi)
{
gNB_MAC_INST *mac = RC.nrmac[mod_id];
NR_UE_info_t *UE = find_ra_UE(&mac->UE_info, rnti);
if (!UE) {
LOG_E(NR_MAC, "UL SDU discarded. Couldn't finde UE with RNTI %04x \n", rnti);
return;
}
NR_RA_t *ra = UE->ra;
if (ra->ra_type == RA_4_STEP && ra->ra_state != nrRA_WAIT_Msg3) {
LOG_W(NR_MAC, "UL SDU discarded for RNTI %04x RA state not waiting for PUSCH\n", UE->rnti);
return;
}
const int target_snrx10 = mac->pusch_target_snrx10;
if (!sdu) { // NACK
if (ra->ra_state != nrRA_WAIT_Msg3)
return;
if((frame!=ra->Msg3_frame) || (slot!=ra->Msg3_slot))
return;
if (ul_cqi != 0xff)
ra->msg3_TPC = nr_get_tpc(target_snrx10, ul_cqi, 30, 0);
handle_msg3_failed_rx(mac, ra, rnti, mac->ul_bler.harq_round_max);
return;
}
bool no_sig = true;
for (uint32_t k = 0; k < sdu_len; k++) {
if (sdu[k] != 0) {
no_sig = false;
break;
}
}
T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(mod_id), T_INT(CC_id),
T_INT(rnti), T_INT(frame), T_INT(slot), T_INT(-1) /* harq_pid */,
T_BUFFER(sdu, sdu_len));
if (no_sig) {
LOG_W(NR_MAC, "MSG3 ULSCH with no signal\n");
handle_msg3_failed_rx(mac, ra, rnti, mac->ul_bler.harq_round_max);
return;
}
if (ra->ra_type == RA_2_STEP) {
// random access pusch with RA-RNTI
if (ra->RA_rnti != rnti) {
LOG_E(NR_MAC, "expected TC_RNTI %04x to match current RNTI %04x\n", ra->RA_rnti, rnti);
return;
}
}
// re-initialize ta update variables after RA procedure completion
UE->UE_sched_ctrl.ta_frame = frame;
LOG_A(NR_MAC, "%4d.%2d PUSCH with TC_RNTI 0x%04x received correctly\n", frame, slot, rnti);
NR_UE_sched_ctrl_t *UE_scheduling_control = &UE->UE_sched_ctrl;
if (ul_cqi != 0xff) {
UE_scheduling_control->tpc0 = nr_get_tpc(target_snrx10, ul_cqi, 30, UE_scheduling_control->sched_pusch.phr_txpower_calc);
UE_scheduling_control->pusch_snrx10 = ul_cqi * 5 - 640 - UE_scheduling_control->sched_pusch.phr_txpower_calc * 10;
}
if (timing_advance != 0xffff)
UE_scheduling_control->ta_update = timing_advance;
UE_scheduling_control->raw_rssi = rssi;
LOG_D(NR_MAC, "[UE %04x] PUSCH TPC %d and TA %d\n", UE->rnti, UE_scheduling_control->tpc0, UE_scheduling_control->ta_update);
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
if (ra->cfra) {
LOG_A(NR_MAC, "(rnti 0x%04x) CFRA procedure succeeded!\n", UE->rnti);
nr_mac_reset_ul_failure(UE_scheduling_control);
reset_dl_harq_list(UE_scheduling_control);
reset_ul_harq_list(UE_scheduling_control);
process_addmod_bearers_cellGroupConfig(&UE->UE_sched_ctrl, UE->CellGroup->rlc_BearerToAddModList);
int ss_type;
// 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
if (IS_SA_MODE(get_softmodem_params()))
ss_type = NR_SearchSpace__searchSpaceType_PR_common;
else
ss_type = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
configure_UE_BWP(mac, scc, UE, false, ss_type, -1, -1);
if (!transition_ra_connected_nr_ue(mac, UE)) {
LOG_E(NR_MAC, "cannot add UE %04x: list is full\n", UE->rnti);
delete_nr_ue_data(UE, NULL, &mac->UE_info.uid_allocator);
return;
}
} else {
LOG_D(NR_MAC, "[RAPROC] Received %s:\n", ra->ra_type == RA_2_STEP ? "MsgA-PUSCH" : "Msg3");
for (uint32_t k = 0; k < sdu_len; k++) {
LOG_D(NR_MAC, "(%i): 0x%x\n", k, sdu[k]);
}
// 3GPP TS 38.321 Section 5.4.3 Multiplexing and assembly
// Logical channels shall be prioritised in accordance with the following order (highest priority listed first):
// - MAC CE for C-RNTI, or data from UL-CCCH;
// This way, we need to process MAC CE for C-RNTI if RA is active and it is present in the MAC PDU
// Search for MAC CE for C-RNTI
rnti_t crnti = lcid_crnti_lookahead(sdu, sdu_len);
if (crnti != 0) { // 3GPP TS 38.321 Table 7.1-1: RNTI values, RNTI 0x0000: N/A
// Replace the current UE by the UE identified by C-RNTI
NR_UE_info_t *old_UE = find_nr_UE(&mac->UE_info, crnti);
if (!old_UE) {
// The UE identified by C-RNTI no longer exists at the gNB
// Let's abort the current RA, so the UE will trigger a new RA later but using RRCSetupRequest instead. A better
// solution may be implemented
LOG_W(NR_MAC, "No UE found with C-RNTI %04x, ignoring Msg3 to have UE come back with new RA attempt\n", UE->rnti);
nr_release_ra_UE(mac, rnti);
return;
}
// in case UE beam has changed
old_UE->UE_beam_index = UE->UE_beam_index;
// Reset UL failure for old UE
nr_mac_reset_ul_failure(&old_UE->UE_sched_ctrl);
// Reset HARQ processes
reset_dl_harq_list(&old_UE->UE_sched_ctrl);
reset_ul_harq_list(&old_UE->UE_sched_ctrl);
// Trigger RRC Reconfiguration
LOG_I(NR_MAC, "Received UL_SCH_LCID_C_RNTI with C-RNTI 0x%04x, triggering RRC Reconfiguration\n", crnti);
nr_mac_trigger_reconfiguration(mac, old_UE);
nr_release_ra_UE(mac, rnti);
LOG_A(NR_MAC, "%4d.%2d UE %04x: RA with C-RNTI complete\n", frame, slot, crnti);
// we configure the UE using common search space with DCIX0 while waiting for a reconfiguration
configure_UE_BWP(mac, scc, old_UE, false, NR_SearchSpace__searchSpaceType_PR_common, -1, -1);
// TODO do we actually need to still process the PDU?
nr_process_mac_pdu(mod_id, old_UE, CC_id, frame, slot, sdu, sdu_len, -1);
return;
} else {
// UE Contention Resolution Identity
// Store the first 48 bits belonging to the uplink CCCH SDU within Msg3 to fill in Msg4
// First byte corresponds to R/LCID MAC sub-header
memcpy(ra->cont_res_id, &sdu[1], sizeof(uint8_t) * 6);
}
// Decode MAC PDU for the correct UE, after checking for MAC CE for C-RNTI
// harq_pid set a non valid value because it is not used in this call
// the function is only called to decode the contention resolution sub-header
nr_process_mac_pdu(mod_id, UE, CC_id, frame, slot, sdu, sdu_len, -1);
LOG_I(NR_MAC,
"Activating scheduling %s for TC_RNTI 0x%04x (state %s)\n",
ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4",
UE->rnti,
nrra_text[ra->ra_state]);
ra->ra_state = ra->ra_type == RA_2_STEP ? nrRA_MsgB : nrRA_Msg4;
LOG_D(NR_MAC, "TC_RNTI 0x%04x next RA state %s\n", UE->rnti, nrra_text[ra->ra_state]);
return;
}
}
static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
const int CC_idP,
const frame_t frameP,
@@ -677,20 +798,14 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
const uint16_t rssi)
{
gNB_MAC_INST *gNB_mac = RC.nrmac[gnb_mod_idP];
const int current_rnti = rntiP;
LOG_D(NR_MAC, "rx_sdu for rnti %04x\n", current_rnti);
const int target_snrx10 = gNB_mac->pusch_target_snrx10;
const int rssi_threshold = gNB_mac->pusch_rssi_threshold;
const int pusch_failure_thres = gNB_mac->pusch_failure_thres;
NR_UE_info_t *UE = find_nr_UE(&gNB_mac->UE_info, current_rnti);
bool UE_waiting_CFRA_msg3 = get_UE_waiting_CFRA_msg3(gNB_mac, CC_idP, frameP, slotP, current_rnti);
if (UE && UE_waiting_CFRA_msg3 == false) {
if (UE) {
NR_UE_sched_ctrl_t *UE_scheduling_control = &UE->UE_sched_ctrl;
if (sduP)
T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(gnb_mod_idP), T_INT(CC_idP),
T_INT(rntiP), T_INT(frameP), T_INT(slotP), T_INT(harq_pid),
@@ -729,7 +844,6 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
UE_scheduling_control->ta_update = timing_advance;
UE_scheduling_control->raw_rssi = rssi;
UE_scheduling_control->pusch_snrx10 = ul_cqi * 5 - 640 - (txpower_calc * 10);
if (UE_scheduling_control->tpc0 > 1)
LOG_D(NR_MAC,
"[UE %04x] %d.%d. PUSCH TPC %d and TA %d pusch_snrx10 %d rssi %d phrx_tx_power %d PHR (1PRB) %d mcs %d, nb_rb %d\n",
@@ -747,7 +861,7 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
NR_UE_ul_harq_t *cur_harq = &UE_scheduling_control->ul_harq_processes[harq_pid];
if (cur_harq->round == 0)
UE->mac_stats.pusch_snrx10 = UE_scheduling_control->pusch_snrx10;
UE->mac_stats.pusch_snrx10 = UE_scheduling_control->pusch_snrx10;
LOG_D(NR_MAC, "[UE %04x] PUSCH TPC %d and TA %d\n",UE->rnti,UE_scheduling_control->tpc0,UE_scheduling_control->ta_update);
}
else{
@@ -769,15 +883,13 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
if (sduP != NULL) {
LOG_D(NR_MAC, "Received PDU at MAC gNB \n");
UE->UE_sched_ctrl.pusch_consecutive_dtx_cnt = 0;
UE_scheduling_control->sched_ul_bytes -= sdu_lenP;
if (UE_scheduling_control->sched_ul_bytes < 0)
UE_scheduling_control->sched_ul_bytes = 0;
nr_process_mac_pdu(gnb_mod_idP, UE, CC_idP, frameP, slotP, sduP, sdu_lenP, harq_pid);
}
else {
} else {
if (ul_cqi == 0xff || ul_cqi <= 128) {
UE->UE_sched_ctrl.pusch_consecutive_dtx_cnt++;
UE->mac_stats.ulsch_DTX++;
@@ -791,186 +903,9 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
nr_mac_trigger_ul_failure(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs);
}
}
} else if (sduP) {
bool no_sig = true;
for (uint32_t k = 0; k < sdu_lenP; k++) {
if (sduP[k] != 0) {
no_sig = false;
break;
}
}
T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(gnb_mod_idP), T_INT(CC_idP),
T_INT(rntiP), T_INT(frameP), T_INT(slotP), T_INT(-1) /* harq_pid */,
T_BUFFER(sduP, sdu_lenP));
/* we don't know this UE (yet). Check whether there is a ongoing RA (Msg 3)
* and check the corresponding UE's RNTI match, in which case we activate
* it. */
for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) {
NR_RA_t *ra = &gNB_mac->common_channels[CC_idP].ra[i];
if (ra->ra_type == RA_4_STEP && ra->ra_state != nrRA_WAIT_Msg3)
continue;
if (no_sig) {
LOG_W(NR_MAC, "Random Access %i ULSCH with no signal\n", i);
handle_msg3_failed_rx(ra, i, gNB_mac->ul_bler.harq_round_max);
continue;
}
if (ra->ra_type == RA_2_STEP) {
// random access pusch with RA-RNTI
if (ra->RA_rnti != current_rnti) {
LOG_E(NR_MAC, "expected TC_RNTI %04x to match current RNTI %04x\n", ra->RA_rnti, current_rnti);
continue;
}
} else {
// random access pusch with TC-RNTI
if (ra->rnti != current_rnti) {
LOG_E(NR_MAC, "expected TC_RNTI %04x to match current RNTI %04x\n", ra->rnti, current_rnti);
if ((frameP == ra->Msg3_frame) && (slotP == ra->Msg3_slot)) {
LOG_W(NR_MAC,
"Random Access %i failed at state %s (TC_RNTI %04x RNTI %04x)\n",
i,
nrra_text[ra->ra_state],
ra->rnti,
current_rnti);
nr_clear_ra_proc(ra);
}
continue;
}
}
UE = UE ? UE : add_new_nr_ue(gNB_mac, ra->rnti, ra->CellGroup);
if (!UE) {
LOG_W(NR_MAC,
"Random Access %i discarded at state %s (TC_RNTI %04x RNTI %04x): max number of users achieved!\n",
i,
nrra_text[ra->ra_state],
ra->rnti,
current_rnti);
nr_clear_ra_proc(ra);
return;
}
UE->UE_beam_index = ra->beam_id;
// re-initialize ta update variables after RA procedure completion
UE->UE_sched_ctrl.ta_frame = frameP;
LOG_A(NR_MAC, "%4d.%2d PUSCH with TC_RNTI 0x%04x received correctly\n", frameP, slotP, current_rnti);
NR_UE_sched_ctrl_t *UE_scheduling_control = &UE->UE_sched_ctrl;
if (ul_cqi != 0xff) {
UE_scheduling_control->tpc0 = nr_get_tpc(target_snrx10, ul_cqi, 30, UE_scheduling_control->sched_pusch.phr_txpower_calc);
UE_scheduling_control->pusch_snrx10 = ul_cqi * 5 - 640 - UE_scheduling_control->sched_pusch.phr_txpower_calc * 10;
}
if (timing_advance != 0xffff)
UE_scheduling_control->ta_update = timing_advance;
UE_scheduling_control->raw_rssi = rssi;
LOG_D(NR_MAC, "[UE %04x] PUSCH TPC %d and TA %d\n", UE->rnti, UE_scheduling_control->tpc0, UE_scheduling_control->ta_update);
if (ra->cfra) {
LOG_A(NR_MAC, "(rnti 0x%04x) CFRA procedure succeeded!\n", ra->rnti);
nr_mac_reset_ul_failure(UE_scheduling_control);
reset_dl_harq_list(UE_scheduling_control);
reset_ul_harq_list(UE_scheduling_control);
process_addmod_bearers_cellGroupConfig(&UE->UE_sched_ctrl, ra->CellGroup->rlc_BearerToAddModList);
nr_clear_ra_proc(ra);
} else {
LOG_D(NR_MAC, "[RAPROC] Received %s:\n", ra->ra_type == RA_2_STEP ? "MsgA-PUSCH" : "Msg3");
for (uint32_t k = 0; k < sdu_lenP; k++) {
LOG_D(NR_MAC, "(%i): 0x%x\n", k, sduP[k]);
}
// 3GPP TS 38.321 Section 5.4.3 Multiplexing and assembly
// Logical channels shall be prioritised in accordance with the following order (highest priority listed first):
// - MAC CE for C-RNTI, or data from UL-CCCH;
// This way, we need to process MAC CE for C-RNTI if RA is active and it is present in the MAC PDU
// Search for MAC CE for C-RNTI
rnti_t crnti = lcid_crnti_lookahead(sduP, sdu_lenP);
if (crnti != 0) { // 3GPP TS 38.321 Table 7.1-1: RNTI values, RNTI 0x0000: N/A
// this UE is the one identified by the RNTI in sduP
ra->rnti = crnti;
// Remove UE context just created after Msg.3 in some milliseconds as the UE is one already known (not now, as the UE
// context is still needed for the moment)
nr_mac_trigger_release_timer(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs);
// Replace the current UE by the UE identified by C-RNTI
UE = find_nr_UE(&gNB_mac->UE_info, crnti);
if (!UE) {
// The UE identified by C-RNTI no longer exists at the gNB
// Let's abort the current RA, so the UE will trigger a new RA later but using RRCSetupRequest instead. A better
// solution may be implemented
LOG_W(NR_MAC, "No UE found with C-RNTI %04x, ignoring Msg3 to have UE come back with new RA attempt\n", ra->rnti);
mac_remove_nr_ue(gNB_mac, ra->rnti);
nr_clear_ra_proc(ra);
return;
}
// The UE identified by C-RNTI still exists at the gNB
// Reset Msg4_ACKed to not schedule ULSCH and DLSCH before RRC Reconfiguration
UE->Msg4_MsgB_ACKed = false;
nr_mac_reset_ul_failure(&UE->UE_sched_ctrl);
// Reset HARQ processes
reset_dl_harq_list(&UE->UE_sched_ctrl);
reset_ul_harq_list(&UE->UE_sched_ctrl);
// Switch to BWP where RA is configured, typically in the InitialBWP
// At this point, UE already switched and triggered RA in that BWP, need to do BWP switching also at gNB for C-RNTI
if (ra->DL_BWP.bwp_id != UE->current_DL_BWP.bwp_id || ra->UL_BWP.bwp_id != UE->current_UL_BWP.bwp_id) {
LOG_D(NR_MAC, "UE %04x Switch BWP from %ld to BWP id %ld\n", UE->rnti, UE->current_DL_BWP.bwp_id, ra->DL_BWP.bwp_id);
NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[CC_idP].ServingCellConfigCommon;
configure_UE_BWP(gNB_mac, scc, &UE->UE_sched_ctrl, NULL, UE, ra->DL_BWP.bwp_id, ra->UL_BWP.bwp_id);
}
if (UE->reconfigCellGroup) {
// Nothing to do
// A RRCReconfiguration message should be already pending (for example, an ongoing RRCReestablishment), and it will be
// transmitted in Msg4
} else {
// Trigger RRC Reconfiguration
LOG_I(NR_MAC, "Received UL_SCH_LCID_C_RNTI with C-RNTI 0x%04x, triggering RRC Reconfiguration\n", UE->rnti);
nr_mac_trigger_reconfiguration(gNB_mac, UE);
}
} else {
// UE Contention Resolution Identity
// Store the first 48 bits belonging to the uplink CCCH SDU within Msg3 to fill in Msg4
// First byte corresponds to R/LCID MAC sub-header
memcpy(ra->cont_res_id, &sduP[1], sizeof(uint8_t) * 6);
}
// Decode MAC PDU for the correct UE, after checking for MAC CE for C-RNTI
// harq_pid set a non valid value because it is not used in this call
// the function is only called to decode the contention resolution sub-header
nr_process_mac_pdu(gnb_mod_idP, UE, CC_idP, frameP, slotP, sduP, sdu_lenP, -1);
LOG_I(NR_MAC,
"Activating scheduling %s for TC_RNTI 0x%04x (state %s)\n",
ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4",
ra->rnti,
nrra_text[ra->ra_state]);
ra->ra_state = ra->ra_type == RA_2_STEP ? nrRA_MsgB : nrRA_Msg4;
LOG_D(NR_MAC, "TC_RNTI 0x%04x next RA state %s\n", ra->rnti, nrra_text[ra->ra_state]);
return;
}
}
} else {
for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) {
NR_RA_t *ra = &gNB_mac->common_channels[CC_idP].ra[i];
if (ra->ra_state != nrRA_WAIT_Msg3)
continue;
if((frameP!=ra->Msg3_frame) || (slotP!=ra->Msg3_slot))
continue;
if (ul_cqi != 0xff)
ra->msg3_TPC = nr_get_tpc(target_snrx10, ul_cqi, 30, 0);
handle_msg3_failed_rx(ra, i, gNB_mac->ul_bler.harq_round_max);
}
handle_nr_ul_harq(gNB_mac, UE, frameP, slotP, current_rnti, harq_pid, sduP == NULL);
} else {
nr_rx_ra_sdu(gnb_mod_idP, CC_idP, frameP, slotP, current_rnti, sduP, sdu_lenP, timing_advance, ul_cqi, rssi);
}
}
@@ -1891,7 +1826,7 @@ static void pf_ul(module_id_t module_id,
UE_iterator(UE_list, UE) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
if (!UE->Msg4_MsgB_ACKed || sched_ctrl->ul_failure)
if (sched_ctrl->ul_failure)
continue;
LOG_D(NR_MAC,"pf_ul: preparing UL scheduling for UE %04x\n",UE->rnti);
@@ -2012,7 +1947,7 @@ static void pf_ul(module_id_t module_id,
continue;
}
sched_pusch->nrOfLayers = sched_ctrl->srs_feedback.ul_ri + 1;
sched_pusch->nrOfLayers = get_ul_nrOfLayers(sched_ctrl, current_BWP->dci_format);
sched_pusch->time_domain_allocation = get_ul_tda(nrmac, sched_frame, sched_slot);
sched_pusch->tda_info = get_ul_tda_info(current_BWP,
sched_ctrl->coreset->controlResourceSetId,
@@ -2162,7 +2097,7 @@ static void pf_ul(module_id_t module_id,
sched_pusch->nrOfLayers = sched_ctrl->srs_feedback.ul_ri + 1;
sched_pusch->nrOfLayers = get_ul_nrOfLayers(sched_ctrl, current_BWP->dci_format);
sched_pusch->time_domain_allocation = get_ul_tda(nrmac, sched_frame, sched_slot);
sched_pusch->tda_info = get_ul_tda_info(current_BWP,
sched_ctrl->coreset->controlResourceSetId,
@@ -2279,7 +2214,7 @@ static bool nr_ulsch_preprocessor(module_id_t module_id, frame_t frame, slot_t s
{
gNB_MAC_INST *nr_mac = RC.nrmac[module_id];
// no UEs
if (nr_mac->UE_info.list[0] == NULL)
if (nr_mac->UE_info.connected_ue_list[0] == NULL)
return false;
NR_COMMON_channels_t *cc = nr_mac->common_channels;
@@ -2308,7 +2243,7 @@ static bool nr_ulsch_preprocessor(module_id_t module_id, frame_t frame, slot_t s
max_sched_ues = min(max_sched_ues, MAX_DCI_CORESET);
/* proportional fair scheduling algorithm */
pf_ul(module_id, frame, slot, sched_frame, sched_slot, nr_mac->UE_info.list, max_sched_ues, num_beams, len);
pf_ul(module_id, frame, slot, sched_frame, sched_slot, nr_mac->UE_info.connected_ue_list, max_sched_ues, num_beams, len);
return true;
}
@@ -2369,7 +2304,7 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, slot_t slot, nfapi_
NR_ServingCellConfigCommon_t *scc = nr_mac->common_channels[0].ServingCellConfigCommon;
NR_UEs_t *UE_info = &nr_mac->UE_info;
UE_iterator( UE_info->list, UE) {
UE_iterator(UE_info->connected_ue_list, UE) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
if (sched_ctrl->ul_failure && !get_softmodem_params()->phy_test)
continue;
+17 -26
View File
@@ -60,11 +60,10 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c
void nr_mac_configure_sib1(gNB_MAC_INST *nrmac, const plmn_id_t *plmn, uint64_t cellID, int tac);
bool nr_mac_configure_other_sib(gNB_MAC_INST *nrmac, int num_cu_sib, const f1ap_sib_msg_t cu_sib[num_cu_sib]);
bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup);
bool nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup);
void nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, NR_UE_info_t *UE);
bool add_new_UE_RA(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE);
int nr_mac_get_reconfig_delay_slots(NR_SubcarrierSpacing_t scs);
bool nr_mac_prepare_cellgroup_update(gNB_MAC_INST *nrmac, NR_UE_info_t *UE, NR_CellGroupConfig_t *CellGroup);
int nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, interrupt_followup_action_t action, int slots);
int nr_transmission_action_indicator_stop(gNB_MAC_INST *mac, NR_UE_info_t *UE_info);
@@ -135,8 +134,6 @@ void nr_initiate_ra_proc(module_id_t module_idP,
int16_t timing_offset,
uint32_t preamble_power);
void nr_clear_ra_proc(NR_RA_t *ra);
int nr_allocate_CCEs(int module_idP, int CC_idP, frame_t frameP, slot_t slotP, int test_only);
void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP);
@@ -273,11 +270,6 @@ NR_ControlResourceSet_t *get_coreset(gNB_MAC_INST *nrmac,
NR_SearchSpace_t *ss,
NR_SearchSpace__searchSpaceType_PR ss_type);
/* find a search space within a BWP */
NR_SearchSpace_t *get_searchspace(NR_ServingCellConfigCommon_t *scc,
NR_BWP_DownlinkDedicated_t *bwp_Dedicated,
NR_SearchSpace__searchSpaceType_PR target_ss);
long get_K2(NR_PUSCH_TimeDomainResourceAllocationList_t *tdaList,
int time_domain_assignment,
int mu,
@@ -310,21 +302,23 @@ void remove_nr_list(NR_list_t *listP, int id);
void add_tail_nr_list(NR_list_t *listP, int id);
void add_front_nr_list(NR_list_t *listP, int id);
void remove_front_nr_list(NR_list_t *listP);
void nr_release_ra_UE(gNB_MAC_INST *mac, rnti_t rnti);
NR_UE_info_t * find_nr_UE(NR_UEs_t* UEs, rnti_t rntiP);
NR_UE_info_t *find_ra_UE(NR_UEs_t *UEs, rnti_t rntiP);
void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_allocator_t *uia);
void configure_UE_BWP(gNB_MAC_INST *nr_mac,
NR_ServingCellConfigCommon_t *scc,
NR_UE_sched_ctrl_t *sched_ctrl,
NR_RA_t *ra,
NR_UE_info_t *UE,
bool is_RA,
int target_ss,
int dl_bwp_switch,
int ul_bwp_switch);
NR_UE_info_t* add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConfig_t *CellGroup);
bool transition_ra_connected_nr_ue(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE);
bool add_connected_nr_ue(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE);
void nr_check_Msg4_MsgB_Ack(module_id_t module_id, frame_t frame, slot_t slot, NR_UE_info_t *UE, bool success);
void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti);
NR_UE_info_t *get_new_nr_ue_inst(uid_allocator_t *uia, rnti_t rnti, NR_CellGroupConfig_t *CellGroup);
int nr_get_default_pucch_res(int pucch_ResourceCommon);
int nr_write_ce_dlsch_pdu(module_id_t module_idP,
@@ -362,12 +356,6 @@ void reset_dl_harq_list(NR_UE_sched_ctrl_t *sched_ctrl);
void reset_ul_harq_list(NR_UE_sched_ctrl_t *sched_ctrl);
void handle_nr_ul_harq(const int CC_idP,
module_id_t mod_id,
frame_t frame,
slot_t slot,
const nfapi_nr_crc_t *crc_pdu);
uint8_t *allocate_transportBlock_buffer(byte_array_t *tb, uint32_t needed);
void free_transportBlock_buffer(byte_array_t *tb);
@@ -392,9 +380,11 @@ uint16_t get_pm_index(const gNB_MAC_INST *nrmac,
uint8_t get_mcs_from_cqi(int mcs_table, int cqi_table, int cqi_idx);
uint8_t get_dl_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl, const nr_dci_format_t dci_format);
int get_ul_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl, const nr_dci_format_t dci_format);
void free_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl);
bool add_UE_to_list(int list_size, NR_UE_info_t *list[list_size], NR_UE_info_t *UE);
NR_UE_info_t *remove_UE_from_list(int list_size, NR_UE_info_t *list[list_size], rnti_t rnti);
int get_dl_tda(const gNB_MAC_INST *nrmac, int slot);
int get_ul_tda(gNB_MAC_INST *nrmac, int frame, int slot);
@@ -430,7 +420,6 @@ int get_mcs_from_bler(const NR_bler_options_t *bler_options,
int ul_buffer_index(int frame, int slot, int slots_per_frame, int size);
void UL_tti_req_ahead_initialization(gNB_MAC_INST *gNB, int n, int CCid, frame_t frameP, int slotP);
void fapi_beam_index_allocation(NR_ServingCellConfigCommon_t *scc, gNB_MAC_INST *mac);
int get_fapi_beamforming_index(gNB_MAC_INST *mac, int ssb_idx);
NR_beam_alloc_t beam_allocation_procedure(NR_beam_info_t *beam_info, int frame, int slot, int beam_index, int slots_per_frame);
@@ -467,11 +456,13 @@ void process_addmod_bearers_cellGroupConfig(NR_UE_sched_ctrl_t *sched_ctrl,
bool nr_mac_add_lcid(NR_UE_sched_ctrl_t *sched_ctrl, const nr_lc_config_t *c);
bool nr_mac_remove_lcid(NR_UE_sched_ctrl_t *sched_ctrl, long lcid);
bool nr_mac_get_new_rnti(NR_UEs_t *UEs, const NR_RA_t *ra_base, int ra_count, rnti_t *rnti);
bool nr_mac_get_new_rnti(NR_UEs_t *UEs, rnti_t *rnti);
void nr_mac_update_pdcch_closed_loop_adjust(NR_UE_sched_ctrl_t *sched_ctrl, bool feedback_not_detected);
void prepare_du_configuration_update(gNB_MAC_INST *mac,
f1ap_served_cell_info_t *info,
NR_BCCH_BCH_Message_t *mib,
const NR_BCCH_DL_SCH_Message_t *sib1);
void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group);
#endif /*__LAYER2_NR_MAC_PROTO_H__*/
+141 -58
View File
@@ -27,6 +27,7 @@
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h"
#include "F1AP_CauseRadioNetwork.h"
#include "NR_HandoverPreparationInformation.h"
#include "NR_CG-ConfigInfo.h"
#include "openair3/ocp-gtpu/gtp_itf.h"
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h"
#include "lib/f1ap_interface_management.h"
@@ -105,7 +106,7 @@ void du_clear_all_ue_states()
gNB_MAC_INST *mac = RC.nrmac[0];
NR_SCHED_LOCK(&mac->sched_lock);
NR_UE_info_t *UE = *mac->UE_info.list;
NR_UE_info_t *UE = *mac->UE_info.connected_ue_list;
instance_t f1inst = get_f1_gtp_instance();
@@ -116,7 +117,7 @@ void du_clear_all_ue_states()
if (du_exists_f1_ue_data(rnti))
du_remove_f1_ue_data(rnti);
newGtpuDeleteAllTunnels(f1inst, rnti);
UE = *mac->UE_info.list;
UE = *mac->UE_info.connected_ue_list;
}
NR_SCHED_UNLOCK(&mac->sched_lock);
}
@@ -342,6 +343,8 @@ static int handle_ue_context_drbs_setup(NR_UE_info_t *UE,
resp_drb->up_dl_tnl[0].teid = resp_f1.gnb_NGu_teid[0];
}
if (!cellGroupConfig->rlc_BearerToAddModList)
cellGroupConfig->rlc_BearerToAddModList = calloc_or_fail(1, sizeof(*cellGroupConfig->rlc_BearerToAddModList));
int ret = ASN_SEQUENCE_ADD(&cellGroupConfig->rlc_BearerToAddModList->list, rlc_BearerConfig);
DevAssert(ret == 0);
}
@@ -461,6 +464,52 @@ static NR_UE_NR_Capability_t *get_ue_nr_cap_from_ho_prep_info(uint8_t *buf, uint
return cap;
}
static NR_CG_ConfigInfo_t *get_cg_config_info(uint8_t *buf, uint32_t len)
{
struct NR_CG_ConfigInfo *cg_configinfo = NULL;
asn_dec_rval_t dec_rval = uper_decode_complete(NULL, &asn_DEF_NR_CG_ConfigInfo, (void **)&cg_configinfo, buf, len);
if (dec_rval.code != RC_OK) {
LOG_W(NR_MAC, "cannot decode CG-ConfigInfo, ignoring it\n");
return NULL;
}
//xer_fprint(stdout, &asn_DEF_NR_CG_ConfigInfo, cg_configinfo);
return cg_configinfo;
}
static NR_UE_NR_Capability_t *get_ue_nr_cap_from_cg_config_info(const NR_CG_ConfigInfo_t *cgci)
{
/* INTO DU handler */
if (cgci->criticalExtensions.present != NR_CG_ConfigInfo__criticalExtensions_PR_c1)
return NULL;
if (!cgci->criticalExtensions.choice.c1
|| cgci->criticalExtensions.choice.c1->present != NR_CG_ConfigInfo__criticalExtensions__c1_PR_cg_ConfigInfo)
return NULL;
const NR_CG_ConfigInfo_IEs_t *cgci_ie = cgci->criticalExtensions.choice.c1->choice.cg_ConfigInfo;
if (!cgci_ie->ue_CapabilityInfo)
return NULL;
// Decode UE-CapabilityRAT-ContainerList
const OCTET_STRING_t *cap_buf = cgci_ie->ue_CapabilityInfo;
NR_UE_CapabilityRAT_ContainerList_t *clist = NULL;
asn_dec_rval_t dec_rval = uper_decode_complete(NULL,
&asn_DEF_NR_UE_CapabilityRAT_ContainerList,
(void **)&clist,
cap_buf->buf,
cap_buf->size);
if (dec_rval.code != RC_OK) {
LOG_W(NR_MAC,
"Failed to decode NR_UE_CapabilityRAT_ContainerList (%zu bits), size of OCTET_STRING %lu\n",
dec_rval.consumed,
cap_buf->size);
return NULL;
}
NR_UE_NR_Capability_t *cap = get_nr_cap(clist);
ASN_STRUCT_FREE(asn_DEF_NR_UE_CapabilityRAT_ContainerList, clist);
return cap;
}
NR_CellGroupConfig_t *clone_CellGroupConfig(const NR_CellGroupConfig_t *orig)
{
uint8_t buf[16636];
@@ -473,43 +522,74 @@ NR_CellGroupConfig_t *clone_CellGroupConfig(const NR_CellGroupConfig_t *orig)
return cloned;
}
static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id)
static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id, const NR_CG_ConfigInfo_t *cgci)
{
const bool is_SA = IS_SA_MODE(get_softmodem_params());
int CC_id = 0;
const NR_COMMON_channels_t *cc = &mac->common_channels[CC_id];
rnti_t rnti;
bool found = nr_mac_get_new_rnti(&mac->UE_info, cc->ra, sizeofArray(cc->ra), &rnti);
if (!found)
return NULL;
NR_UE_info_t* UE = add_new_nr_ue(mac, rnti, NULL);
if (!UE)
return NULL;
if (get_softmodem_params()->phy_test) {
AssertFatal(mac->UE_info.connected_ue_list[0] == NULL, "phytest: UE already present\n");
rnti = 0x1234;
} else {
bool found = nr_mac_get_new_rnti(&mac->UE_info, &rnti);
if (!found)
return NULL;
}
f1_ue_data_t new_ue_data = {.secondary_ue = cu_id};
bool success = du_add_f1_ue_data(rnti, &new_ue_data);
DevAssert(success);
const NR_ServingCellConfigCommon_t *scc = mac->common_channels[CC_id].ServingCellConfigCommon;
const NR_ServingCellConfig_t *sccd = mac->common_channels[CC_id].pre_ServingCellConfig;
NR_CellGroupConfig_t *cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, sccd, &mac->radio_config);
cellGroupConfig->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(UE->rnti, UE->uid, scc);
NR_UE_info_t *UE = get_new_nr_ue_inst(&mac->UE_info.uid_allocator, rnti, NULL);
AssertFatal(UE != NULL, "cannot create UE context, UE context setup failure not implemented\n");
NR_CellGroupConfig_t *cellGroupConfig = NULL;
NR_COMMON_channels_t *cc = &mac->common_channels[CC_id];
const NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
const NR_ServingCellConfig_t *sccd = cc->pre_ServingCellConfig;
const nr_mac_config_t *configuration = &mac->radio_config;
if (is_SA) {
cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, sccd, &mac->radio_config);
cellGroupConfig->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(UE->rnti, UE->uid, scc);
} else {
NR_UE_NR_Capability_t *cap = get_ue_nr_cap_from_cg_config_info(cgci);
cellGroupConfig = get_default_secondaryCellGroup(scc, sccd, cap, 1, 1, configuration, UE->uid);
cellGroupConfig->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(UE->rnti, UE->uid, scc);
// TODO: in NSA we assign capabilities here, otherwise outside => not logic
UE->capability = cap;
}
// 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
// by add_new_nr_ue(); it's a kind of chicken-and-egg problem), so below we
// complete the UE context with the information that add_new_nr_ue() would
// have added
UE->Msg4_MsgB_ACKed = true;
AssertFatal(cellGroupConfig != NULL, "out of memory\n");
UE->CellGroup = cellGroupConfig;
nr_rlc_activate_srb0(UE->rnti, UE, NULL);
nr_mac_prepare_ra_ue(mac, rnti, UE->CellGroup);
/* SRB1 is added to RLC and MAC in the handler later */
if (get_softmodem_params()->phy_test) {
// phytest mode: we don't set up RA, etc
free_and_zero(UE->ra); // test-mode: UE will not do RA
bool res = add_connected_nr_ue(mac, UE);
DevAssert(res);
} else {
if (!add_new_UE_RA(mac, UE)) {
delete_nr_ue_data(UE, /*not used*/ NULL, &mac->UE_info.uid_allocator);
LOG_E(NR_MAC, "UE list full while creating new UE\n");
return NULL;
}
nr_mac_prepare_ra_ue(mac, UE);
if (is_SA) {
/* SRB1 is added to RLC and MAC in the handler later */
nr_rlc_activate_srb0(UE->rnti, UE, NULL);
}
}
return UE;
}
void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
{
const bool is_SA = IS_SA_MODE(get_softmodem_params());
gNB_MAC_INST *mac = RC.nrmac[0];
/* response has same type as request... */
f1ap_ue_context_setup_t resp = {
@@ -523,9 +603,11 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
bool ue_id_provided = resp.gNB_DU_ue_id > 0 && resp.gNB_DU_ue_id < 0xffff;
NR_UE_NR_Capability_t *ue_cap = NULL;
NR_CG_ConfigInfo_t *cg_configinfo = NULL;
if (req->cu_to_du_rrc_information != NULL) {
const cu_to_du_rrc_information_t *cu2du = req->cu_to_du_rrc_information;
AssertFatal(cu2du->cG_ConfigInfo == NULL, "CG-ConfigInfo not handled\n");
if (cu2du->cG_ConfigInfo != NULL)
cg_configinfo = get_cg_config_info(cu2du->cG_ConfigInfo, cu2du->cG_ConfigInfo_length);
if (cu2du->handoverPreparationInfo != NULL) {
ue_cap = get_ue_nr_cap_from_ho_prep_info(cu2du->handoverPreparationInfo, cu2du->handoverPreparationInfo_length);
} else if (cu2du->uE_CapabilityRAT_ContainerList != NULL) {
@@ -533,15 +615,21 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
}
AssertFatal(cu2du->measConfig == NULL, "MeasConfig not handled\n");
}
/* 38.473: "For DC operation, the CG-ConfigInfo IE shall be included in the CU
* to DU RRC Information IE at the gNB acting as secondary node" As of now,
* we only handle NSA => we check we have CG-ConfigInfo if not SA or have SA
* and no CG-ConfigInfo */
AssertFatal(is_SA ^ (cg_configinfo != NULL), "cannot have SA and CG-ConfigInfo: NR-DC not supported xor need CG-ConfigInfo for NSA/phy-test/do-ra\n");
NR_SCHED_LOCK(&mac->sched_lock);
NR_UE_info_t *UE = NULL;
if (!ue_id_provided) {
UE = create_new_UE(mac, req->gNB_CU_ue_id);
UE = create_new_UE(mac, req->gNB_CU_ue_id, cg_configinfo);
resp.gNB_DU_ue_id = UE->rnti;
resp.crnti = &UE->rnti;
} else {
DevAssert(is_SA);
UE = find_nr_UE(&mac->UE_info, req->gNB_DU_ue_id);
}
AssertFatal(UE, "no UE found or could not be created, but UE Context Setup Failed not implemented\n");
@@ -569,18 +657,23 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
nr_rlc_srb_recv_sdu(req->gNB_DU_ue_id, id, req->rrc_container, req->rrc_container_length);
}
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
UE->capability = ue_cap;
if (ue_cap != NULL) {
if (ue_cap != NULL && cg_configinfo == NULL) {
// store the new UE capabilities, and update the cellGroupConfig
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
// only to be done if we did not already update through the cg_configinfo
update_cellGroupConfig(new_CellGroup, UE->uid, UE->capability, &mac->radio_config, scc);
}
if (!ue_id_provided) {
if (!ue_id_provided && cg_configinfo == NULL) {
/* new UE: tell the UE to reestablish RLC */
struct NR_CellGroupConfig__rlc_BearerToAddModList *addmod = new_CellGroup->rlc_BearerToAddModList;
for (int i = 0; i < addmod->list.count; ++i) {
asn1cCallocOne(addmod->list.array[i]->reestablishRLC, NR_RLC_BearerConfig__reestablishRLC_true);
for (int i = 1; i < seq_arr_size(&UE->UE_sched_ctrl.lc_config); ++i) {
nr_lc_config_t *lc_config = seq_arr_at(&UE->UE_sched_ctrl.lc_config, i);
nr_rlc_reestablish_entity(UE->rnti, lc_config->lcid);
}
}
}
@@ -593,7 +686,10 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
AssertFatal(enc_rval.encoded > 0, "Could not encode CellGroup, failed element %s\n", enc_rval.failed_type->name);
resp.du_to_cu_rrc_information->cellGroupConfig_length = (enc_rval.encoded + 7) >> 3;
nr_mac_prepare_cellgroup_update(mac, UE, new_CellGroup);
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
UE->CellGroup = new_CellGroup;
int ss_type = cg_configinfo ? NR_SearchSpace__searchSpaceType_PR_ue_Specific: NR_SearchSpace__searchSpaceType_PR_common;
configure_UE_BWP(mac, scc, UE, false, ss_type, -1, -1);
NR_SCHED_UNLOCK(&mac->sched_lock);
@@ -664,9 +760,15 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
nr_rlc_srb_recv_sdu(req->gNB_DU_ue_id, id, req->rrc_container, req->rrc_container_length);
}
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
if (req->ReconfigComplOutcome != RRCreconf_info_not_present && req->ReconfigComplOutcome != RRCreconf_success) {
LOG_E(NR_MAC,
"RRC reconfiguration outcome unsuccessful, but no rollback mechanism implemented to come back to old configuration\n");
} else if (req->ReconfigComplOutcome == RRCreconf_success) {
LOG_I(NR_MAC, "DU received confirmation of successful RRC Reconfiguration\n");
// we re-configure the BWP to apply the CellGroup and to use UE specific Search Space with DCIX1
nr_mac_clean_cellgroup(UE->CellGroup);
configure_UE_BWP(mac, scc, UE, false, NR_SearchSpace__searchSpaceType_PR_ue_Specific, -1, -1);
}
if (ue_cap != NULL) {
@@ -674,7 +776,6 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->capability);
UE->capability = ue_cap;
LOG_I(NR_MAC, "UE %04x: received capabilities, updating CellGroupConfig\n", UE->rnti);
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
update_cellGroupConfig(new_CellGroup, UE->uid, UE->capability, &mac->radio_config, scc);
}
@@ -692,7 +793,9 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
AssertFatal(enc_rval.encoded > 0, "Could not encode CellGroup, failed element %s\n", enc_rval.failed_type->name);
resp.du_to_cu_rrc_information->cellGroupConfig_length = (enc_rval.encoded + 7) >> 3;
nr_mac_prepare_cellgroup_update(mac, UE, new_CellGroup);
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
UE->CellGroup = new_CellGroup;
configure_UE_BWP(mac, scc, UE, false, NR_SearchSpace__searchSpaceType_PR_common, -1, -1);
} else {
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, new_CellGroup); // we actually don't need it
}
@@ -759,13 +862,6 @@ void ue_context_modification_refuse(const f1ap_ue_context_modif_refuse_t *refuse
return;
}
const int CC_id = 0;
NR_COMMON_channels_t *cc = &mac->common_channels[CC_id];
for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
NR_RA_t *ra = &cc->ra[i];
if (ra->rnti == UE->rnti)
nr_clear_ra_proc(ra);
}
NR_SCHED_UNLOCK(&mac->sched_lock);
f1ap_ue_context_release_req_t request = {
@@ -822,6 +918,7 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc)
pthread_mutex_lock(&mac->sched_lock);
/* check first that the scheduler knows such UE */
NR_UE_info_t *UE = find_nr_UE(&mac->UE_info, dl_rrc->gNB_DU_ue_id);
UE = UE ? UE : find_ra_UE(&mac->UE_info, dl_rrc->gNB_DU_ue_id);
if (UE == NULL) {
LOG_E(MAC, "ERROR: unknown UE with RNTI %04x, ignoring DL RRC Message Transfer\n", dl_rrc->gNB_DU_ue_id);
pthread_mutex_unlock(&mac->sched_lock);
@@ -836,24 +933,13 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc)
DevAssert(success);
}
if (UE->expect_reconfiguration && dl_rrc->srb_id == 1) {
/* we expected a reconfiguration, and this is on DCCH. We assume this is
* the reconfiguration: nr_mac_prepare_cellgroup_update() already stored
* the CellGroupConfig. Below, we trigger a timer, and the CellGroupConfig
* will be applied after its expiry in nr_mac_apply_cellgroup().*/
NR_SCHED_LOCK(&mac->sched_lock);
int delay = nr_mac_get_reconfig_delay_slots(UE->current_UL_BWP.scs);
nr_mac_interrupt_ue_transmission(mac, UE, FOLLOW_INSYNC_RECONFIG, delay);
NR_SCHED_UNLOCK(&mac->sched_lock);
UE->expect_reconfiguration = false;
/* Re-establish RLC for all remaining bearers */
if (UE->reestablish_rlc) {
for (int i = 1; i < seq_arr_size(&UE->UE_sched_ctrl.lc_config); ++i) {
nr_lc_config_t *lc_config = seq_arr_at(&UE->UE_sched_ctrl.lc_config, i);
nr_rlc_reestablish_entity(dl_rrc->gNB_DU_ue_id, lc_config->lcid);
}
UE->reestablish_rlc = false;
if (UE->reestablish_rlc && dl_rrc->srb_id == 1) {
// we expected a reconfiguration to re-establish RLC, and this is on DCCH. We assume this is the reconfiguration.
for (int i = 1; i < seq_arr_size(&UE->UE_sched_ctrl.lc_config); ++i) {
nr_lc_config_t *lc_config = seq_arr_at(&UE->UE_sched_ctrl.lc_config, i);
nr_rlc_reestablish_entity(dl_rrc->gNB_DU_ue_id, lc_config->lcid);
}
UE->reestablish_rlc = false;
}
if (dl_rrc->old_gNB_DU_ue_id != NULL) {
@@ -870,28 +956,25 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc)
* from the current configuration. Also, expect the reconfiguration from
* the CU, so save the old UE's CellGroup for the new UE */
UE->CellGroup->spCellConfig = NULL;
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
uid_t temp_uid = UE->uid;
UE->uid = oldUE->uid;
oldUE->uid = temp_uid;
configure_UE_BWP(mac, scc, sched_ctrl, NULL, UE, -1, -1);
for (int i = 1; i < seq_arr_size(&oldUE->UE_sched_ctrl.lc_config); ++i) {
const nr_lc_config_t *c = seq_arr_at(&oldUE->UE_sched_ctrl.lc_config, i);
nr_mac_add_lcid(&UE->UE_sched_ctrl, c);
}
nr_mac_prepare_cellgroup_update(mac, UE, oldUE->CellGroup);
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
UE->CellGroup = oldUE->CellGroup;
oldUE->CellGroup = NULL;
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);
nr_rlc_update_id(*dl_rrc->old_gNB_DU_ue_id, dl_rrc->gNB_DU_ue_id);
/* 38.331 clause 5.3.7.4: apply the specified configuration defined in 9.2.1 for SRB1 */
nr_rlc_reconfigure_entity(dl_rrc->gNB_DU_ue_id, 1, NULL);
/* Set flag to trigger RLC re-establishment
* for remaining RBs in next RRCReconfiguration */
UE->reestablish_rlc = true;
/* 38.331 clause 5.3.7.4: apply the specified configuration defined in 9.2.1 for SRB1 */
nr_rlc_reconfigure_entity(dl_rrc->gNB_DU_ue_id, 1, NULL);
instance_t f1inst = get_f1_gtp_instance();
if (f1inst >= 0) // we actually use F1-U
gtpv1u_update_ue_id(f1inst, *dl_rrc->old_gNB_DU_ue_id, dl_rrc->gNB_DU_ue_id);
+8 -28
View File
@@ -106,7 +106,7 @@ void *nrmac_stats_thread(void *arg) {
}
void clear_mac_stats(gNB_MAC_INST *gNB) {
UE_iterator(gNB->UE_info.list, UE) {
UE_iterator(gNB->UE_info.connected_ue_list, UE) {
memset(&UE->mac_stats,0,sizeof(UE->mac_stats));
}
}
@@ -121,7 +121,7 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset
NR_SCHED_ENSURE_LOCKED(&gNB->sched_lock);
NR_SCHED_LOCK(&gNB->UE_info.mutex);
UE_iterator(gNB->UE_info.list, UE) {
UE_iterator(gNB->UE_info.connected_ue_list, UE) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
NR_mac_stats_t *stats = &UE->mac_stats;
const int avg_rsrp = stats->num_rsrp_meas > 0 ? stats->cumul_rsrp / stats->num_rsrp_meas : 0;
@@ -312,29 +312,6 @@ void mac_top_init_gNB(ngran_node_t node_type,
// These should be out of here later
if (get_softmodem_params()->usim_test == 0 ) nr_pdcp_layer_init();
if(IS_SOFTMODEM_NOS1 && get_softmodem_params()->phy_test) {
// get default noS1 configuration
NR_RadioBearerConfig_t *rbconfig = NULL;
NR_RLC_BearerConfig_t *rlc_rbconfig = NULL;
fill_nr_noS1_bearer_config(&rbconfig, &rlc_rbconfig);
/* Note! previously, in nr_DRB_preconfiguration(), we passed ENB_FLAG_NO
* if ENB_NAS_USE_TUN was *not* set. It seems to me that we could not set
* this flag anywhere in the code, hence we would always configure PDCP
* with ENB_FLAG_NO in nr_DRB_preconfiguration(). This makes sense for
* noS1, because the result of passing ENB_FLAG_NO to PDCP is that PDCP
* will output the packets at a local interface, which is in line with
* the noS1 mode. Hence, below, we simply hardcode ENB_FLAG_NO */
// setup PDCP, RLC
nr_pdcp_entity_security_keys_and_algos_t null_security_parameters = {0};
nr_pdcp_add_drbs(ENB_FLAG_NO, 0x1234, rbconfig->drb_ToAddModList, &null_security_parameters);
nr_rlc_add_drb(0x1234, rbconfig->drb_ToAddModList->list.array[0]->drb_Identity, rlc_rbconfig);
// free memory
free_nr_noS1_bearer_config(&rbconfig, &rlc_rbconfig);
}
} else {
RC.nrmac = NULL;
}
@@ -359,9 +336,12 @@ void mac_top_destroy_gNB(gNB_MAC_INST *mac)
ASN_STRUCT_FREE(asn_DEF_NR_ServingCellConfig, cc->pre_ServingCellConfig);
ASN_STRUCT_FREE(asn_DEF_NR_ServingCellConfigCommon, cc->ServingCellConfigCommon);
NR_UEs_t *UE_info = &mac->UE_info;
for (int i = 0; i < sizeofArray(UE_info->list); ++i)
if (UE_info->list[i])
delete_nr_ue_data(UE_info->list[i], cc, &UE_info->uid_allocator);
for (int i = 0; i < sizeofArray(UE_info->connected_ue_list); ++i)
if (UE_info->connected_ue_list[i])
delete_nr_ue_data(UE_info->connected_ue_list[i], cc, &UE_info->uid_allocator);
for (int i = 0; i < sizeofArray(UE_info->access_ue_list); ++i)
if (UE_info->access_ue_list[i])
delete_nr_ue_data(UE_info->access_ue_list[i], cc, &UE_info->uid_allocator);
}
void nr_mac_send_f1_setup_req(void)
+3 -23
View File
@@ -229,8 +229,6 @@ typedef struct {
NR_beam_alloc_t Msg3_beam;
/// harq_pid used for Msg4 transmission
uint8_t harq_pid;
/// UE RNTI allocated during RAR
rnti_t rnti;
/// RA RNTI allocated from received PRACH
uint16_t RA_rnti;
/// MsgB RNTI allocated from received MsgA
@@ -251,25 +249,12 @@ typedef struct {
int msg3_nbSymb;
/// MAC PDU length for Msg4
int mac_pdu_length;
/// RA search space
NR_SearchSpace_t *ra_ss;
/// RA Coreset
NR_ControlResourceSet_t *coreset;
NR_sched_pdcch_t sched_pdcch;
// Beam index
uint8_t beam_id;
/// CellGroup for UE that is to come (NSA is non-null, null for SA)
NR_CellGroupConfig_t *CellGroup;
/// Preambles for contention-free access
NR_preamble_ue_t preambles;
int contention_resolution_timer;
nr_ra_type_t ra_type;
/// CFRA flag
bool cfra;
// BWP for RA
NR_UE_DL_BWP_t DL_BWP;
NR_UE_UL_BWP_t UL_BWP;
NR_UE_ServingCell_Info_t sc_info;
} NR_RA_t;
/*! \brief gNB common channels */
@@ -289,8 +274,6 @@ typedef struct {
/// used for otherSIB data
uint8_t other_sib_bcch_pdu[2][NR_MAX_SIB_LENGTH / 8];
int other_sib_bcch_length[2];
/// Template for RA computations
NR_RA_t ra[NR_NB_RA_PROC_MAX];
/// VRB map for common channels
uint16_t vrb_map[MAX_NUM_BEAM_PERIODS][275];
/// VRB map for common channels and PUSCH, dynamically allocated because
@@ -654,7 +637,6 @@ typedef struct {
int pusch_snrx10;
int pucch_snrx10;
uint16_t ul_rssi;
uint8_t current_harq_pid;
int pusch_consecutive_dtx_cnt;
int pucch_consecutive_dtx_cnt;
bool ul_failure;
@@ -761,27 +743,25 @@ typedef struct {
NR_mac_stats_t mac_stats;
/// currently active CellGroupConfig
NR_CellGroupConfig_t *CellGroup;
/// CellGroupConfig that is to be activated after the next reconfiguration
bool expect_reconfiguration;
/// reestablishRLC has to be signaled in RRCreconfiguration
bool reestablish_rlc;
NR_CellGroupConfig_t *reconfigCellGroup;
interrupt_followup_action_t interrupt_action;
NR_UE_NR_Capability_t *capability;
// UE selected beam index
uint8_t UE_beam_index;
bool Msg4_MsgB_ACKed;
float ul_thr_ue;
float dl_thr_ue;
long pdsch_HARQ_ACK_Codebook;
bool is_redcap;
NR_RA_t *ra;
} NR_UE_info_t;
typedef struct {
/// scheduling control info
// last element always NULL
pthread_mutex_t mutex;
NR_UE_info_t *list[MAX_MOBILES_PER_GNB+1];
NR_UE_info_t *connected_ue_list[MAX_MOBILES_PER_GNB + 1];
NR_UE_info_t *access_ue_list[NR_NB_RA_PROC_MAX];
// bitmap of CSI-RS already scheduled in current slot
int sched_csirs;
uid_allocator_t uid_allocator;
-6
View File
@@ -899,12 +899,6 @@ void nr_rlc_remove_ue(int ue_id)
nr_rlc_manager_unlock(nr_rlc_ue_manager);
}
rlc_op_status_t rrc_rlc_remove_ue (const protocol_ctxt_t* const x)
{
nr_rlc_remove_ue(x->rntiMaybeUEid);
return RLC_OP_STATUS_OK;
}
bool nr_rlc_update_id(int from_id, int to_id)
{
nr_rlc_manager_lock(nr_rlc_ue_manager);
-1
View File
@@ -203,7 +203,6 @@ static void handle_nr_ulsch(NR_UL_IND_t *UL_info)
crc->timing_advance,
crc->ul_cqi,
crc->rssi);
handle_nr_ul_harq(UL_info->CC_id, UL_info->module_id, UL_info->frame, UL_info->slot, crc);
}
UL_info->rx_ind.number_of_pdus = 0;
UL_info->crc_ind.number_crcs = 0;
-26
View File
@@ -425,32 +425,6 @@ NR_RadioBearerConfig_t *get_default_rbconfig(int eps_bearer_id,
return rbconfig;
}
void fill_nr_noS1_bearer_config(NR_RadioBearerConfig_t **rbconfig,
NR_RLC_BearerConfig_t **rlc_rbconfig)
{
/* the EPS bearer ID is arbitrary; the rb_id is 1/the first DRB, it needs to
* match the one in get_DRB_RLC_BearerConfig(). No ciphering is to be
* configured */
*rbconfig = get_default_rbconfig(10, 1, NR_CipheringAlgorithm_nea0, NR_SecurityConfig__keyToUse_master);
AssertFatal(*rbconfig != NULL, "get_default_rbconfig() failed\n");
/* LCID is 4 because the RLC layer requires it to be 3+rb_id; the rb_id 1 is
* common with get_default_rbconfig() (first RB). We pre-configure RLC UM
* Bi-directional, priority is 1 */
*rlc_rbconfig = get_DRB_RLC_BearerConfig(4, 1, NR_RLC_Config_PR_um_Bi_Directional, 1);
AssertFatal(*rlc_rbconfig != NULL, "get_DRB_RLC_BearerConfig() failed\n");
}
void free_nr_noS1_bearer_config(NR_RadioBearerConfig_t **rbconfig,
NR_RLC_BearerConfig_t **rlc_rbconfig)
{
ASN_STRUCT_FREE(asn_DEF_NR_RadioBearerConfig, *rbconfig);
*rbconfig = NULL;
if (rlc_rbconfig != NULL) {
ASN_STRUCT_FREE(asn_DEF_NR_RLC_BearerConfig, *rlc_rbconfig);
*rlc_rbconfig = NULL;
}
}
//------------------------------------------------------------------------------
int do_RRCSetup(uint8_t *const buffer,
size_t buffer_size,
-5
View File
@@ -80,11 +80,6 @@ NR_RadioBearerConfig_t *get_default_rbconfig(int eps_bearer_id,
e_NR_CipheringAlgorithm ciphering_algorithm,
e_NR_SecurityConfig__keyToUse key_to_use);
void fill_nr_noS1_bearer_config(NR_RadioBearerConfig_t **rbconfig,
NR_RLC_BearerConfig_t **rlc_rbconfig);
void free_nr_noS1_bearer_config(NR_RadioBearerConfig_t **rbconfig,
NR_RLC_BearerConfig_t **rlc_rbconfig);
int do_RRCSetup(uint8_t *const buffer,
size_t buffer_size,
const uint8_t transaction_id,
+7 -2
View File
@@ -84,9 +84,14 @@ static void ue_context_setup_request_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_c
if (req->cu_to_du_rrc_information != NULL) {
f1ap_msg->cu_to_du_rrc_information = calloc(1, sizeof(*f1ap_msg->cu_to_du_rrc_information));
AssertFatal(f1ap_msg->cu_to_du_rrc_information != NULL, "out of memory\n");
AssertFatal(req->cu_to_du_rrc_information->cG_ConfigInfo == NULL && req->cu_to_du_rrc_information->cG_ConfigInfo_length == 0, "cg_ConfigInfo not implemented\n");
AssertFatal(req->cu_to_du_rrc_information->measConfig == NULL && req->cu_to_du_rrc_information->measConfig_length == 0, "cg_ConfigInfo not implemented\n");
const cu_to_du_rrc_information_t *du2cu_req = req->cu_to_du_rrc_information;
if (req->cu_to_du_rrc_information->cG_ConfigInfo != NULL) {
cu_to_du_rrc_information_t* du2cu_new = f1ap_msg->cu_to_du_rrc_information;
du2cu_new->cG_ConfigInfo_length = du2cu_req->cG_ConfigInfo_length;
du2cu_new->cG_ConfigInfo = malloc_or_fail(du2cu_new->cG_ConfigInfo_length);
memcpy(du2cu_new->cG_ConfigInfo, du2cu_req->cG_ConfigInfo, du2cu_new->cG_ConfigInfo_length);
}
AssertFatal(req->cu_to_du_rrc_information->measConfig == NULL && req->cu_to_du_rrc_information->measConfig_length == 0, "cg_ConfigInfo not implemented\n");
if (req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList != NULL) {
cu_to_du_rrc_information_t* du2cu_new = f1ap_msg->cu_to_du_rrc_information;
DevAssert(du2cu_req->uE_CapabilityRAT_ContainerList_length > 0);
+11 -11
View File
@@ -3128,7 +3128,15 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid,
asn1cSeqAdd(&bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList->list, coreset);
int searchspaceid = 5;
int css_num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS];
css_num_agg_level_candidates[PDCCH_AGG_LEVEL1] = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0;
css_num_agg_level_candidates[PDCCH_AGG_LEVEL2] = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0;
css_num_agg_level_candidates[PDCCH_AGG_LEVEL4] = NR_SearchSpace__nrofCandidates__aggregationLevel4_n1;
css_num_agg_level_candidates[PDCCH_AGG_LEVEL8] = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0;
css_num_agg_level_candidates[PDCCH_AGG_LEVEL16] = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0;
int searchspaceid = 4;
NR_SearchSpace_t *ss = rrc_searchspace_config(true, searchspaceid, 0, css_num_agg_level_candidates);
searchspaceid = 5;
int rrc_num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS];
int num_cces = get_coreset_num_cces(coreset->frequencyDomainResources.buf, coreset->duration);
verify_agg_levels(num_cces,
@@ -3137,6 +3145,7 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid,
searchspaceid,
rrc_num_agg_level_candidates);
NR_SearchSpace_t *ss2 = rrc_searchspace_config(false, searchspaceid, coreset->controlResourceSetId, rrc_num_agg_level_candidates);
asn1cSeqAdd(&bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list, ss);
asn1cSeqAdd(&bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list, ss2);
bwp_Dedicated->pdsch_Config = config_pdsch(bitmap, 0, pdsch_AntennaPorts);
@@ -3550,23 +3559,14 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC
NR_CellGroupConfig_t *secondaryCellGroup = calloc(1, sizeof(*secondaryCellGroup));
secondaryCellGroup->cellGroupId = scg_id;
/* LCID is 4 because the RLC layer requires it to be 3+rb_id; the rb_id is 1
* for first RB. We pre-configure RLC UM Bi-directional, priority is 1 */
NR_RLC_BearerConfig_t *RLC_BearerConfig = get_DRB_RLC_BearerConfig(4, 1, NR_RLC_Config_PR_um_Bi_Directional, 1);
secondaryCellGroup->rlc_BearerToAddModList = calloc(1, sizeof(*secondaryCellGroup->rlc_BearerToAddModList));
asn1cSeqAdd(&secondaryCellGroup->rlc_BearerToAddModList->list, RLC_BearerConfig);
/* rlc_BearerToAddModList is handled outside */
secondaryCellGroup->mac_CellGroupConfig = configure_mac_cellgroup(&configuration->timer_config);
secondaryCellGroup->physicalCellGroupConfig = configure_phy_cellgroup();
secondaryCellGroup->spCellConfig = calloc(1, sizeof(*secondaryCellGroup->spCellConfig));
secondaryCellGroup->spCellConfig->servCellIndex = calloc(1, sizeof(*secondaryCellGroup->spCellConfig->servCellIndex));
*secondaryCellGroup->spCellConfig->servCellIndex = servCellIndex;
secondaryCellGroup->spCellConfig->reconfigurationWithSync =
calloc(1, sizeof(*secondaryCellGroup->spCellConfig->reconfigurationWithSync));
rnti_t rnti = get_softmodem_params()->phy_test == 1 ? 0x1234 : (taus() & 0xffff);
secondaryCellGroup->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(rnti, uid, servingcellconfigcommon);
secondaryCellGroup->spCellConfig->rlf_TimersAndConstants =
calloc(1, sizeof(*secondaryCellGroup->spCellConfig->rlf_TimersAndConstants));
+3 -3
View File
@@ -221,9 +221,9 @@ typedef struct gNB_RRC_UE_s {
ngap_security_capabilities_t security_capabilities;
//NSA block
/* Number of NSA e_rab */
sctp_assoc_t x2_target_assoc;
int MeNB_ue_x2_id;
int nb_of_e_rabs;
/* list of pdu session to be setup by RRC layers */
nr_e_rab_param_t e_rab[NB_RB_MAX];//[S1AP_MAX_E_RAB];
uint32_t nsa_gtp_teid[S1AP_MAX_E_RAB];
transport_layer_addr_t nsa_gtp_addrs[S1AP_MAX_E_RAB];
@@ -238,7 +238,7 @@ typedef struct gNB_RRC_UE_s {
uint32_t ue_rrc_inactivity_timer;
uint32_t ue_reestablishment_counter;
uint32_t ue_reconfiguration_counter;
bool ongoing_reconfiguration;
bool an_release; // flag if core requested UE release
/* NGUEContextSetup might come with PDU sessions, but setup needs to be
+4 -8
View File
@@ -41,17 +41,13 @@
#define NR_MAX_SUPPORTED_DL_LAYERS 4
void rrc_parse_ue_capabilities(gNB_RRC_INST *rrc,NR_UE_CapabilityRAT_ContainerList_t *UE_CapabilityRAT_ContainerList, x2ap_ENDC_sgnb_addition_req_t *m, NR_CG_ConfigInfo_IEs_t * cg_config_info);
void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m, sctp_assoc_t assoc_id);
void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_context_setup_t *resp);
void rrc_release_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context);
void rrc_remove_nsa_user_context(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context);
void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2ap_ENDC_sgnb_addition_req_t *m);
void rrc_remove_nsa_user(gNB_RRC_INST *rrc, int rnti);
void rrc_remove_ue(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p);
NR_RRCReconfiguration_IEs_t *get_default_reconfig(const NR_CellGroupConfig_t *secondaryCellGroup);
NR_CG_Config_t *generate_CG_Config(const NR_RRCReconfiguration_t *reconfig, const NR_RadioBearerConfig_t *rbconfig);
int parse_CG_ConfigInfo(gNB_RRC_INST *rrc, NR_CG_ConfigInfo_t *CG_ConfigInfo, x2ap_ENDC_sgnb_addition_req_t *m);
void rrc_gNB_generate_SecurityModeCommand(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p);
+38 -36
View File
@@ -255,41 +255,14 @@ void openair_rrc_gNB_configuration(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *c
RB_INIT(&rrc->cuups);
RB_INIT(&rrc->dus);
rrc->configuration = *configuration;
if (get_softmodem_params()->phy_test > 0 || get_softmodem_params()->do_ra > 0) {
AssertFatal(NODE_IS_MONOLITHIC(rrc->node_type), "phy_test and do_ra only work in monolithic\n");
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_allocate_new_ue_context(rrc);
LOG_I(NR_RRC,"Adding new user (%p)\n",ue_context_p);
if (!NODE_IS_CU(rrc->node_type)) {
rrc_add_nsa_user(rrc,ue_context_p,NULL);
}
}
}
static void rrc_gNB_process_AdditionRequestInformation(const module_id_t gnb_mod_idP, x2ap_ENDC_sgnb_addition_req_t *m)
{
struct NR_CG_ConfigInfo *cg_configinfo = NULL;
asn_dec_rval_t dec_rval = uper_decode_complete(NULL,
&asn_DEF_NR_CG_ConfigInfo,
(void **)&cg_configinfo,
(uint8_t *)m->rrc_buffer,
(int) m->rrc_buffer_size);//m->rrc_buffer_size);
gNB_RRC_INST *rrc=RC.nrrrc[gnb_mod_idP];
if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
AssertFatal(1==0,"NR_UL_DCCH_MESSAGE decode error\n");
// free the memory
SEQUENCE_free(&asn_DEF_NR_CG_ConfigInfo, cg_configinfo, 1);
return;
}
xer_fprint(stdout,&asn_DEF_NR_CG_ConfigInfo, cg_configinfo);
// recreate enough of X2 EN-DC Container
AssertFatal(cg_configinfo->criticalExtensions.choice.c1->present == NR_CG_ConfigInfo__criticalExtensions__c1_PR_cg_ConfigInfo,
"ueCapabilityInformation not present\n");
parse_CG_ConfigInfo(rrc,cg_configinfo,m);
LOG_I(NR_RRC, "Successfully parsed CG_ConfigInfo of size %zu bits. (%zu bytes)\n",
dec_rval.consumed, (dec_rval.consumed +7/8));
gNB_RRC_INST *rrc = RC.nrrrc[gnb_mod_idP];
AssertFatal(NODE_IS_MONOLITHIC(rrc->node_type), "NSA, phy_test, and do_ra only work in monolithic\n");
sctp_assoc_t assoc_id = -1; // monolithic gNB
rrc_add_nsa_user(rrc, m, assoc_id);
}
//-----------------------------------------------------------------------------
@@ -1145,6 +1118,7 @@ int nr_rrc_reconfiguration_req(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p, const int
{
uint8_t xid = rrc_gNB_get_next_transaction_identifier(rrc->module_id);
ue_p->xids[xid] = RRC_DEDICATED_RECONF;
ue_p->ongoing_reconfiguration = true;
NR_CellGroupConfig_t *masterCellGroup = ue_p->masterCellGroup;
if (dl_bwp_id > 0) {
@@ -1237,6 +1211,7 @@ static void rrc_handle_RRCSetupRequest(gNB_RRC_INST *rrc,
UE->establishment_cause = rrcSetupRequest->establishmentCause;
UE->nr_cellid = msg->nr_cellid;
UE->masterCellGroup = cellGroupConfig;
UE->ongoing_reconfiguration = false;
activate_srb(UE, 1);
rrc_gNB_generate_RRCSetup(0, msg->crnti, ue_context_p, msg->du2cu_rrc_container, msg->du2cu_rrc_container_length);
}
@@ -1804,6 +1779,7 @@ static void handle_rrcReconfigurationComplete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *U
{
uint8_t xid = reconfig_complete->rrc_TransactionIdentifier;
UE->ue_reconfiguration_counter++;
UE->ongoing_reconfiguration = false;
switch (UE->xids[xid]) {
case RRC_PDUSESSION_RELEASE: {
@@ -1854,6 +1830,15 @@ static void handle_rrcReconfigurationComplete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *U
UE->ho_context->target->ho_success(rrc, UE);
nr_rrc_finalize_ho(UE);
}
f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id);
RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id);
f1ap_ue_context_modif_req_t ue_context_modif_req = {
.gNB_CU_ue_id = UE->rrc_ue_id,
.gNB_DU_ue_id = ue_data.secondary_ue,
.ReconfigComplOutcome = RRCreconf_success,
};
rrc->mac_rrc.ue_context_modification_request(ue_data.du_assoc_id, &ue_context_modif_req);
}
static void rrc_gNB_generate_UECapabilityEnquiry(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue)
@@ -2044,16 +2029,27 @@ void rrc_gNB_process_initial_ul_rrc_message(sctp_assoc_t assoc_id, const f1ap_in
ASN_STRUCT_FREE(asn_DEF_NR_UL_CCCH_Message, ul_ccch_msg);
}
static void rrc_gNB_trigger_nsa_release(module_id_t mod_id, int ue_id)
{
gNB_RRC_INST *rrc = RC.nrrrc[mod_id];
rrc_gNB_ue_context_t *ue_context = rrc_gNB_get_ue_context(rrc, ue_id);
if (!ue_context) {
LOG_E(NR_RRC, "could not find UE for ID %d\n", ue_id);
return;
}
rrc_release_nsa_user(rrc, ue_context);
}
void rrc_gNB_process_release_request(const module_id_t gnb_mod_idP, x2ap_ENDC_sgnb_release_request_t *m)
{
gNB_RRC_INST *rrc = RC.nrrrc[gnb_mod_idP];
rrc_remove_nsa_user(rrc, m->rnti);
/* it's not the RNTI, it's the UE ID ... */
rrc_gNB_trigger_nsa_release(gnb_mod_idP, m->rnti);
}
void rrc_gNB_process_dc_overall_timeout(const module_id_t gnb_mod_idP, x2ap_ENDC_dc_overall_timeout_t *m)
{
gNB_RRC_INST *rrc = RC.nrrrc[gnb_mod_idP];
rrc_remove_nsa_user(rrc, m->rnti);
/* it's not the RNTI, it's the UE ID ... */
rrc_gNB_trigger_nsa_release(gnb_mod_idP, m->rnti);
}
/* \brief fill E1 bearer modification's DRB from F1 DRB
@@ -2171,6 +2167,11 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance
if (LOG_DEBUGFLAG(DEBUG_ASN1))
xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, UE->masterCellGroup);
if (!IS_SA_MODE(get_softmodem_params())) {
rrc_add_nsa_user_resp(rrc, UE, resp);
return;
}
if (resp->drbs_to_be_setup_length > 0) {
int num_drb = get_number_active_drbs(UE);
DevAssert(num_drb == 0 || num_drb == resp->drbs_to_be_setup_length);
@@ -2417,7 +2418,8 @@ static void rrc_CU_process_ue_modification_required(MessageDef *msg_p, instance_
xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, UE->masterCellGroup);
/* trigger reconfiguration */
nr_rrc_reconfiguration_req(rrc, UE, 0, 0);
if (!UE->ongoing_reconfiguration)
nr_rrc_reconfiguration_req(rrc, UE, 0, 0);
return;
}
LOG_W(RRC,
-65
View File
@@ -1,65 +0,0 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file rrc_gNB_GTPV1U.c
* \brief rrc GTPV1U procedures for gNB
* \author Lionel GAUTHIER, Panos MATZAKOS
* \version 1.0
* \company Eurecom
* \email: lionel.gauthier@eurecom.fr, panagiotis.matzakos@eurecom.fr
*/
#include "openair2/RRC/NR/rrc_gNB_GTPV1U.h"
#include "LOG/log.h"
#include "RRC/NR/nr_rrc_defs.h"
#include "common/ran_context.h"
#include "openair2/RRC/NR/rrc_gNB_UE_context.h"
#include "rrc_defs.h"
#include "rrc_eNB_GTPV1U.h"
#include "s1ap_messages_types.h"
int rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(gNB_RRC_UE_t *ue,
const gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP,
uint8_t *inde_list)
{
if (!create_tunnel_resp_pP) {
LOG_E(NR_RRC, "create_tunnel_resp_pP error\n");
return -1;
}
for (int i = 0; i < create_tunnel_resp_pP->num_tunnels; i++) {
ue->nsa_gtp_teid[inde_list[i]] = create_tunnel_resp_pP->enb_S1u_teid[i];
ue->nsa_gtp_addrs[inde_list[i]] = create_tunnel_resp_pP->enb_addr;
ue->nsa_gtp_ebi[inde_list[i]] = create_tunnel_resp_pP->eps_bearer_id[i];
LOG_I(RRC,
"UE %d: rrc_eNB_process_GTPV1U_CREATE_TUNNEL_RESP tunnel (%u, %u) bearer UE context index %u, msg index %u, id %u, gtp "
"addr len %d \n",
ue->rrc_ue_id,
create_tunnel_resp_pP->enb_S1u_teid[i],
ue->nsa_gtp_teid[inde_list[i]],
inde_list[i],
i,
create_tunnel_resp_pP->eps_bearer_id[i],
create_tunnel_resp_pP->enb_addr.length);
}
return 0;
}
-41
View File
@@ -1,41 +0,0 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file rrc_gNB_GTPV1U.h
* \brief rrc GTPV1U procedures for gNB
* \author Lionel GAUTHIER, Panos MATZAKOS
* \version 1.0
* \company Eurecom
* \email: lionel.gauthier@eurecom.fr, panagiotis.matzakos@eurecom.fr
*/
#ifndef RRC_GNB_GTPV1U_H_
#define RRC_GNB_GTPV1U_H_
#include <stdint.h>
#include "openair2/RRC/NR/nr_rrc_defs.h"
#include "gtpv1_u_messages_types.h"
int rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(gNB_RRC_UE_t *ue,
const gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP,
uint8_t *inde_list);
#endif
+16 -1
View File
@@ -437,11 +437,17 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id)
if (rrc->node_name != NULL)
resp.gNB_CU_name = strdup(rrc->node_name);
rrc->mac_rrc.f1_setup_response(assoc_id, &resp);
/* we need to setup one default UE for phy-test and do-ra modes in the MAC */
if (get_softmodem_params()->phy_test > 0 || get_softmodem_params()->do_ra > 0)
rrc_add_nsa_user(rrc, NULL, assoc_id);
}
static int invalidate_du_connections(gNB_RRC_INST *rrc, sctp_assoc_t assoc_id)
{
int count = 0;
seq_arr_t ue_context_to_remove;
seq_arr_init(&ue_context_to_remove, sizeof(rrc_gNB_ue_context_t *));
rrc_gNB_ue_context_t *ue_context_p = NULL;
RB_FOREACH(ue_context_p, rrc_nr_ue_tree_s, &rrc->rrc_ue_head) {
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
@@ -451,7 +457,7 @@ static int invalidate_du_connections(gNB_RRC_INST *rrc, sctp_assoc_t assoc_id)
nr_rrc_finalize_ho(UE);
}
f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_id);
if (ue_data.du_assoc_id == assoc_id) {
if (ue_data.du_assoc_id == assoc_id && IS_SA_MODE(get_softmodem_params())) {
/* this UE belongs to the DU that disconnected, set du_assoc_id to 0,
* meaning DU is offline, then trigger release request */
ue_data.du_assoc_id = 0;
@@ -460,8 +466,17 @@ static int invalidate_du_connections(gNB_RRC_INST *rrc, sctp_assoc_t assoc_id)
ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CAUSE_RADIO_NETWORK_RADIO_CONNECTION_WITH_UE_LOST};
rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_REQ(0, ue_context_p, cause);
count++;
} else {
seq_arr_push_back(&ue_context_to_remove, &ue_context_p, sizeof(ue_context_p));
}
}
for (int i = 0; i < seq_arr_size(&ue_context_to_remove); ++i) {
/* we retrieve a pointer (=iterator) to the UE context pointer
* (ue_context_p), so dereference once */
rrc_gNB_ue_context_t *p = *(rrc_gNB_ue_context_t **)seq_arr_at(&ue_context_to_remove, i);
rrc_remove_nsa_user_context(rrc, p);
}
seq_arr_free(&ue_context_to_remove, NULL);
return count;
}
-147
View File
@@ -1,147 +0,0 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file rrc_gNB_internode.c
* \brief rrc internode procedures for gNB
* \author Raymond Knopp
* \date 2019
* \version 1.0
* \company Eurecom
* \email: raymond.knopp@eurecom.fr
*/
#ifndef RRC_GNB_INTERNODE_C
#define RRC_GNB_INTERNODE_C
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "OCTET_STRING.h"
#include "RRC/NR/nr_rrc_proto.h"
#include "T.h"
#include "asn_codecs.h"
#include "assertions.h"
#include "common/utils/T/T.h"
#include "constr_TYPE.h"
#include "executables/softmodem-common.h"
#include "nr_rrc_defs.h"
#include "uper_decoder.h"
#include "uper_encoder.h"
#include "x2ap_messages_types.h"
int parse_CG_ConfigInfo(gNB_RRC_INST *rrc, NR_CG_ConfigInfo_t *CG_ConfigInfo, x2ap_ENDC_sgnb_addition_req_t *m) {
if (CG_ConfigInfo->criticalExtensions.present == NR_CG_ConfigInfo__criticalExtensions_PR_c1) {
if (CG_ConfigInfo->criticalExtensions.choice.c1) {
if (CG_ConfigInfo->criticalExtensions.choice.c1->present == NR_CG_ConfigInfo__criticalExtensions__c1_PR_cg_ConfigInfo) {
NR_CG_ConfigInfo_IEs_t *cg_ConfigInfo = CG_ConfigInfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo;
if (cg_ConfigInfo->ue_CapabilityInfo) {
// Decode UE-CapabilityRAT-ContainerList
NR_UE_CapabilityRAT_ContainerList_t *UE_CapabilityRAT_ContainerList=NULL;
UE_CapabilityRAT_ContainerList = calloc(1,sizeof(NR_UE_CapabilityRAT_ContainerList_t));
asn_dec_rval_t dec_rval = uper_decode(NULL,
&asn_DEF_NR_UE_CapabilityRAT_ContainerList,
(void **)&UE_CapabilityRAT_ContainerList,
cg_ConfigInfo->ue_CapabilityInfo->buf,
cg_ConfigInfo->ue_CapabilityInfo->size, 0, 0);
if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
AssertFatal(1==0,"[InterNode] Failed to decode NR_UE_CapabilityRAT_ContainerList (%zu bits), size of OCTET_STRING %lu\n",
dec_rval.consumed, cg_ConfigInfo->ue_CapabilityInfo->size);
}
rrc_parse_ue_capabilities(rrc,UE_CapabilityRAT_ContainerList, m,cg_ConfigInfo);
}
if (cg_ConfigInfo->candidateCellInfoListMN) AssertFatal(1==0,"Can't handle candidateCellInfoListMN yet\n");
} else AssertFatal(1==0,"c1 extension is not cg_ConfigInfo, returning\n");
} else {
LOG_E(RRC,"c1 extension not found, returning\n");
return(-1);
}
} else {
LOG_E(RRC,"Ignoring unknown CG_ConfigInfo extensions\n");
return(-1);
}
return(0);
}
NR_CG_Config_t *generate_CG_Config(const NR_RRCReconfiguration_t *reconfig, const NR_RadioBearerConfig_t *rbconfig)
{
NR_CG_Config_t *cg_Config = calloc(1, sizeof(*cg_Config));
cg_Config->criticalExtensions.present = NR_CG_Config__criticalExtensions_PR_c1;
cg_Config->criticalExtensions.choice.c1 = calloc(1,sizeof(*cg_Config->criticalExtensions.choice.c1));
cg_Config->criticalExtensions.choice.c1->present = NR_CG_Config__criticalExtensions__c1_PR_cg_Config;
cg_Config->criticalExtensions.choice.c1->choice.cg_Config = calloc(1,sizeof(NR_CG_Config_IEs_t));
char buffer[1024];
asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_RRCReconfiguration, NULL, (void *)reconfig, buffer, 1024);
AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n",
enc_rval.failed_type->name, enc_rval.encoded);
cg_Config->criticalExtensions.choice.c1->choice.cg_Config->scg_CellGroupConfig = calloc(1,sizeof(OCTET_STRING_t));
OCTET_STRING_fromBuf(cg_Config->criticalExtensions.choice.c1->choice.cg_Config->scg_CellGroupConfig,
(const char *)buffer,
(enc_rval.encoded+7)>>3);
FILE *fd; // file to be generated for nr-ue
if (get_softmodem_params()->phy_test==1 || get_softmodem_params()->do_ra > 0) {
// This is for phytest only, emulate first X2 message if uecap.raw file is present
LOG_I(RRC,"Dumping NR_RRCReconfiguration message (%jd bytes)\n",(enc_rval.encoded+7)>>3);
for (int i=0; i<(enc_rval.encoded+7)>>3; i++) {
printf("%02x",((uint8_t *)buffer)[i]);
}
printf("\n");
fd = fopen("reconfig.raw","w");
if (fd != NULL) {
fwrite((void *)buffer,1,(size_t)((enc_rval.encoded+7)>>3),fd);
fclose(fd);
}
}
enc_rval = uper_encode_to_buffer(&asn_DEF_NR_RadioBearerConfig, NULL, (void *)rbconfig, buffer, 1024);
AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n",
enc_rval.failed_type->name, enc_rval.encoded);
cg_Config->criticalExtensions.choice.c1->choice.cg_Config->scg_RB_Config = calloc(1,sizeof(OCTET_STRING_t));
OCTET_STRING_fromBuf(cg_Config->criticalExtensions.choice.c1->choice.cg_Config->scg_RB_Config,
(const char *)buffer,
(enc_rval.encoded+7)>>3);
if (get_softmodem_params()->phy_test==1 || get_softmodem_params()->do_ra > 0) {
LOG_I(RRC,"Dumping scg_RB_Config message (%jd bytes)\n",(enc_rval.encoded+7)>>3);
for (int i=0; i<(enc_rval.encoded+7)>>3; i++) {
printf("%02x",((uint8_t *)buffer)[i]);
}
printf("\n");
fd = fopen("rbconfig.raw","w");
if (fd != NULL) {
fwrite((void *)buffer,1,(size_t)((enc_rval.encoded+7)>>3),fd);
fclose(fd);
}
}
return cg_Config;
}
#endif
-1
View File
@@ -231,7 +231,6 @@ static void rrc_gNB_trigger_reconfiguration_for_handover(gNB_RRC_INST *rrc, gNB_
.plmn = rrc->configuration.plmn[0],
.nr_cellid = rrc->nr_cellid, // TODO target cell ID
.servCellId = 0, // TODO: correct value?
.ReconfigComplOutcome = RRCreconf_success,
.transm_action_ind = &transmission_action_indicator,
};
deliver_ue_ctxt_modification_data_t data = {.rrc = rrc,
+261 -233
View File
@@ -60,8 +60,9 @@
#include "openair2/F1AP/f1ap_ids.h"
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h"
#include "openair2/RRC/NR/rrc_gNB_GTPV1U.h"
#include "openair3/SECU/key_nas_deriver.h"
#include "openair2/SDAP/nr_sdap/nr_sdap_entity.h"
#include "rrc_gNB_du.h"
#include "rlc.h"
#include "s1ap_messages_types.h"
#include "tree.h"
@@ -70,115 +71,87 @@
#include "x2ap_messages_types.h"
#include "xer_decoder.h"
#include "xer_encoder.h"
#include "f1ap_common.h"
void rrc_parse_ue_capabilities(gNB_RRC_INST *rrc, NR_UE_CapabilityRAT_ContainerList_t *UE_CapabilityRAT_ContainerList, x2ap_ENDC_sgnb_addition_req_t *m, NR_CG_ConfigInfo_IEs_t *cg_config_info)
// In case of phy-test and do-ra mode, read UE capabilities directly from file
// and put it into a CG-ConfigInfo field
static int cg_config_info_from_ue_cap_file(uint32_t maxlen, uint8_t buf[maxlen])
{
OCTET_STRING_t *ueCapabilityRAT_Container_nr=NULL;
OCTET_STRING_t *ueCapabilityRAT_Container_MRDC=NULL;
asn_dec_rval_t dec_rval;
int list_size=0;
NR_CG_ConfigInfo_t *cgci = calloc_or_fail(1, sizeof(*cgci));
cgci->criticalExtensions.present = NR_CG_ConfigInfo__criticalExtensions_PR_c1;
cgci->criticalExtensions.choice.c1 = calloc_or_fail(1, sizeof(*cgci->criticalExtensions.choice.c1));
cgci->criticalExtensions.choice.c1->present = NR_CG_ConfigInfo__criticalExtensions__c1_PR_cg_ConfigInfo;
NR_CG_ConfigInfo_IEs_t *cgci_ies = calloc_or_fail(1, sizeof(*cgci_ies));
cgci->criticalExtensions.choice.c1->choice.cg_ConfigInfo = cgci_ies;
AssertFatal(UE_CapabilityRAT_ContainerList!=NULL,"UE_CapabilityRAT_ContainerList is null\n");
AssertFatal((list_size=UE_CapabilityRAT_ContainerList->list.count) >= 2, "UE_CapabilityRAT_ContainerList->list.size %d < 2\n",UE_CapabilityRAT_ContainerList->list.count);
if (uecap_file != NULL) {
LOG_I(NR_RRC, "creating CG-ConfigInfo from UE capability file %s\n", uecap_file);
for (int i=0; i<list_size; i++) {
if (UE_CapabilityRAT_ContainerList->list.array[i]->rat_Type == NR_RAT_Type_nr) ueCapabilityRAT_Container_nr = &UE_CapabilityRAT_ContainerList->list.array[i]->ue_CapabilityRAT_Container;
else if (UE_CapabilityRAT_ContainerList->list.array[i]->rat_Type == NR_RAT_Type_eutra_nr) ueCapabilityRAT_Container_MRDC = &UE_CapabilityRAT_ContainerList->list.array[i]->ue_CapabilityRAT_Container;
}
// decode and store capabilities
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_allocate_new_ue_context(rrc);
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
if (ueCapabilityRAT_Container_nr != NULL) {
dec_rval = uper_decode(NULL, &asn_DEF_NR_UE_NR_Capability, (void **)&UE->UE_Capability_nr, ueCapabilityRAT_Container_nr->buf, ueCapabilityRAT_Container_nr->size, 0, 0);
if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
LOG_E(RRC, "Failed to decode UE NR capabilities (%zu bytes) container size %lu\n", dec_rval.consumed,ueCapabilityRAT_Container_nr->size);
ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->UE_Capability_nr);
UE->UE_Capability_nr = 0;
AssertFatal(1==0,"exiting\n");
FILE *f = fopen(uecap_file, "r");
if (!f) {
LOG_E(NR_RRC, "cannot open file %s, cannot read UE capabilities\n", uecap_file);
return 0;
}
}
if (ueCapabilityRAT_Container_MRDC != NULL) {
dec_rval = uper_decode(NULL, &asn_DEF_NR_UE_MRDC_Capability, (void **)&UE->UE_Capability_MRDC, ueCapabilityRAT_Container_MRDC->buf, ueCapabilityRAT_Container_MRDC->size, 0, 0);
if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
LOG_E(RRC, "Failed to decode UE MRDC capabilities (%zu bytes)\n", dec_rval.consumed);
ASN_STRUCT_FREE(asn_DEF_NR_UE_MRDC_Capability, UE->UE_Capability_MRDC);
UE->UE_Capability_MRDC = 0;
AssertFatal(1==0,"exiting\n");
char UE_NR_Capability_xer[65536];
size_t size = fread(UE_NR_Capability_xer, 1, sizeof UE_NR_Capability_xer, f);
fclose(f);
if (size == 0 || size == sizeof UE_NR_Capability_xer) {
LOG_E(NR_RRC, "UE Capabilities XER file %s could not be read (read %ld bytes)\n", uecap_file, size);
return 0;
}
NR_UE_NR_Capability_t *cap = calloc_or_fail(1, sizeof(*cap));
asn_dec_rval_t dec_rval = xer_decode(0, &asn_DEF_NR_UE_NR_Capability, (void *)&cap, UE_NR_Capability_xer, size);
DevAssert(dec_rval.code == RC_OK);
//xer_fprint(stdout, &asn_DEF_NR_UE_NR_Capability, cap);
OCTET_STRING_t *os_cap = calloc_or_fail(1, sizeof(*os_cap));
os_cap->size = uper_encode_to_new_buffer(&asn_DEF_NR_UE_NR_Capability, NULL, cap, (void **)&os_cap->buf);
cgci_ies->ue_CapabilityInfo = os_cap;
}
// dump ue_capabilities
//xer_fprint(stdout, &asn_DEF_NR_CG_ConfigInfo, cgci);
asn_enc_rval_t rval = uper_encode_to_buffer(&asn_DEF_NR_CG_ConfigInfo, NULL, cgci, buf, maxlen);
DevAssert(rval.encoded > 0);
return (rval.encoded + 7) >> 3;
}
if ( LOG_DEBUGFLAG(DEBUG_ASN1) && ueCapabilityRAT_Container_nr != NULL ) {
xer_fprint(stdout, &asn_DEF_NR_UE_NR_Capability, UE->UE_Capability_nr);
}
if ( LOG_DEBUGFLAG(DEBUG_ASN1) && ueCapabilityRAT_Container_MRDC != NULL ) {
xer_fprint(stdout, &asn_DEF_NR_UE_MRDC_Capability, UE->UE_Capability_MRDC);
}
LOG_A(NR_RRC, "Successfully decoded UE NR capabilities (NR and MRDC)\n");
AssertFatal(NODE_IS_MONOLITHIC(rrc->node_type), "phy_test and do_ra only work in monolithic\n");
LOG_I(NR_RRC,"Adding new NSA user (%p)\n",ue_context_p);
rrc_add_nsa_user(rrc,ue_context_p, m);
static instance_t get_f1_gtp_instance(void)
{
const f1ap_cudu_inst_t *inst = getCxt(0);
if (!inst)
return -1; // means no F1
return inst->gtpInst;
}
/* generate prototypes for the tree management functions (RB_INSERT used in rrc_add_nsa_user) */
RB_PROTOTYPE(rrc_nr_ue_tree_s, rrc_gNB_ue_context_s, entries,
rrc_gNB_compare_ue_rnti_id);
void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2ap_ENDC_sgnb_addition_req_t *m)
void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m, sctp_assoc_t assoc_id)
{
AssertFatal(!IS_SA_MODE(get_softmodem_params()), "%s() cannot be called in SA mode, it is intrinsically for NSA\n", __func__);
// generate nr-Config-r15 containers for LTE RRC : inside message for X2 EN-DC (CG-Config Message from 38.331)
const nr_mac_config_t *configuration = &RC.nrmac[0]->radio_config;
MessageDef *msg;
msg = itti_alloc_new_message(TASK_RRC_ENB, 0, X2AP_ENDC_SGNB_ADDITION_REQ_ACK);
gtpv1u_enb_create_tunnel_req_t create_tunnel_req;
gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp;
protocol_ctxt_t ctxt={0};
nr_pdcp_entity_security_keys_and_algos_t security_parameters = {0};
int i;
/* all the 0 are DU-related info that we will fill later, see rrc_add_nsa_user_resp() below */
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_create_ue_context(assoc_id, 0, rrc, 0, 0);
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
// In case of phy-test and do-ra mode, read UE capabilities directly from file
if (get_softmodem_params()->phy_test == 1 || get_softmodem_params()->do_ra == 1) {
NR_UE_NR_Capability_t* UE_Capability_nr = NULL;
char UE_NR_Capability_xer[65536];
FILE *f = NULL;
if (uecap_file)
f = fopen(uecap_file, "r");
if (f) {
size_t size = fread(UE_NR_Capability_xer, 1, sizeof UE_NR_Capability_xer, f);
if (size == 0 || size == sizeof UE_NR_Capability_xer)
LOG_E(NR_RRC,"UE Capabilities XER file %s is too large (%ld)\n", uecap_file, size);
else {
UE_Capability_nr = CALLOC(1,sizeof(NR_UE_NR_Capability_t));
asn_dec_rval_t dec_rval = xer_decode(0, &asn_DEF_NR_UE_NR_Capability, (void *)&UE_Capability_nr, UE_NR_Capability_xer, size);
assert(dec_rval.code == RC_OK);
xer_fprint(stdout,&asn_DEF_NR_UE_NR_Capability,(void *)UE_Capability_nr);
}
fclose(f);
}
else
LOG_E(NR_RRC,"Could not open UE Capabilities input file. Not handling OAI UE Capabilities.\n");
UE->UE_Capability_nr = UE_Capability_nr;
}
nr_pdcp_entity_security_keys_and_algos_t security_parameters = {0};
// NR RRCReconfiguration
uint8_t tmp[1024];
uint8_t *cgci_buf = NULL;
uint32_t cgci_len = 0;
if (get_softmodem_params()->phy_test == 1 || get_softmodem_params()->do_ra == 1) {
DevAssert(m == NULL);
UE->rb_config = get_default_rbconfig(10 /* EPS bearer ID */, 1 /* drb ID */, NR_CipheringAlgorithm_nea0, NR_SecurityConfig__keyToUse_master);
cgci_len = cg_config_info_from_ue_cap_file(sizeof tmp, tmp);
DevAssert(cgci_len > 0);
cgci_buf = tmp;
} else {
DevAssert(m != NULL);
cgci_buf = m->rrc_buffer;
cgci_len = m->rrc_buffer_size;
/* TODO: handle more than one bearer */
if (m == NULL) {
LOG_E(RRC, "fatal: m==NULL\n");
exit(1);
}
if (m->nb_e_rabs_tobeadded != 1) {
LOG_E(RRC, "fatal: m->nb_e_rabs_tobeadded = %d, should be 1\n", m->nb_e_rabs_tobeadded);
exit(1);
@@ -196,7 +169,7 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a
*/
/* preset nea0 as fallback */
UE->ciphering_algorithm = 0;
for (i = 0; i < rrc->security.ciphering_algorithms_count; i++) {
for (int i = 0; i < rrc->security.ciphering_algorithms_count; i++) {
int nea_mask[4] = {
0,
0x8000, /* nea1 */
@@ -254,27 +227,12 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a
UE->rb_config = get_default_rbconfig(m->e_rabs_tobeadded[0].e_rab_id, m->e_rabs_tobeadded[0].drb_ID, cipher_algo, NR_SecurityConfig__keyToUse_secondary);
}
NR_ServingCellConfig_t *scc = RC.nrmac[0]->common_channels[0].pre_ServingCellConfig;
// The MAC has the ServingCellConfigCommon; the below code is incorrect: the
// CU should send a UE Context Setup Request to request the creating of the
// MAC Context
NR_ServingCellConfigCommon_t *sccc = RC.nrmac[0]->common_channels[0].ServingCellConfigCommon;
NR_CellGroupConfig_t *secondaryCellGroup =
get_default_secondaryCellGroup(sccc, scc, UE->UE_Capability_nr, 1, 1, configuration, ue_context_p->ue_context.rrc_ue_id);
AssertFatal(secondaryCellGroup != NULL, "out of memory\n");
NR_RRCReconfiguration_t *reconfig = calloc(1, sizeof(NR_RRCReconfiguration_t));
reconfig->rrc_TransactionIdentifier = 0;
reconfig->criticalExtensions.present = NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration;
reconfig->criticalExtensions.choice.rrcReconfiguration = get_default_reconfig(secondaryCellGroup);
UE->rnti = secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity;
NR_CG_Config_t *CG_Config = generate_CG_Config(reconfig, UE->rb_config);
if(m!=NULL) {
uint8_t inde_list[m->nb_e_rabs_tobeadded];
memset(inde_list, 0, m->nb_e_rabs_tobeadded*sizeof(uint8_t));
UE->x2_target_assoc = m->target_assoc_id;
UE->MeNB_ue_x2_id = m->ue_x2_id;
gtpv1u_enb_create_tunnel_req_t create_tunnel_req = {0};
gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp = {0};
if (m->nb_e_rabs_tobeadded>0) {
for (int i=0; i<m->nb_e_rabs_tobeadded; i++) {
// Add the new E-RABs at the corresponding rrc ue context of the gNB
@@ -286,7 +244,6 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a
create_tunnel_req.eps_bearer_id[i] = UE->e_rab[i].param.e_rab_id;
create_tunnel_req.sgw_S1u_teid[i] = UE->e_rab[i].param.gtp_teid;
memcpy(&create_tunnel_req.sgw_addr[i], &UE->e_rab[i].param.sgw_addr, sizeof(transport_layer_addr_t));
inde_list[i] = i;
LOG_I(RRC,"S1-U tunnel: index %d target sgw ip %d.%d.%d.%d length %d gtp teid %u\n",
i,
create_tunnel_req.sgw_addr[i].buffer[0],
@@ -300,146 +257,217 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a
create_tunnel_req.rnti = ue_context_p->ue_context.rrc_ue_id;
create_tunnel_req.num_tunnels = m->nb_e_rabs_tobeadded;
RB_INSERT(rrc_nr_ue_tree_s, &RC.nrrrc[rrc->module_id]->rrc_ue_head, ue_context_p);
memset(&create_tunnel_resp, 0, sizeof(create_tunnel_resp));
if (!IS_SOFTMODEM_NOS1) {
LOG_D(RRC, "Calling gtpv1u_create_s1u_tunnel()\n");
gtpv1u_create_s1u_tunnel(rrc->module_id, &create_tunnel_req, &create_tunnel_resp, nr_pdcp_data_req_drb);
rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(&ue_context_p->ue_context, &create_tunnel_resp, &inde_list[0]);
DevAssert(create_tunnel_resp.num_tunnels == 1);
UE->nsa_gtp_teid[0] = create_tunnel_resp.enb_S1u_teid[0];
UE->nsa_gtp_addrs[0] = create_tunnel_resp.enb_addr;
UE->nsa_gtp_ebi[0] = create_tunnel_resp.eps_bearer_id[0];
}
X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).nb_e_rabs_admitted_tobeadded = m->nb_e_rabs_tobeadded;
X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).target_assoc_id = m->target_assoc_id;
for (int i = 0; i < UE->nb_of_e_rabs; i++) {
X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).e_rabs_admitted_tobeadded[i].e_rab_id = UE->e_rab[i].param.e_rab_id;
X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).e_rabs_admitted_tobeadded[i].gtp_teid = create_tunnel_resp.enb_S1u_teid[i];
memcpy(&X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).e_rabs_admitted_tobeadded[i].gnb_addr, &create_tunnel_resp.enb_addr, sizeof(transport_layer_addr_t));
//The length field in the X2AP targetting structure is expected in bits but the create_tunnel_resp returns the address length in bytes
X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).e_rabs_admitted_tobeadded[i].gnb_addr.length = create_tunnel_resp.enb_addr.length*8;
LOG_I(RRC,"S1-U create_tunnel_resp tunnel: index %d target gNB ip %d.%d.%d.%d length %d gtp teid %u\n",
i,
create_tunnel_resp.enb_addr.buffer[0],
create_tunnel_resp.enb_addr.buffer[1],
create_tunnel_resp.enb_addr.buffer[2],
create_tunnel_resp.enb_addr.buffer[3],
create_tunnel_resp.enb_addr.length,
create_tunnel_resp.enb_S1u_teid[i]);
LOG_I(RRC,"X2AP sGNB Addition Request: index %d target gNB ip %d.%d.%d.%d length %d gtp teid %u\n",
i,
X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).e_rabs_admitted_tobeadded[i].gnb_addr.buffer[0],
X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).e_rabs_admitted_tobeadded[i].gnb_addr.buffer[1],
X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).e_rabs_admitted_tobeadded[i].gnb_addr.buffer[2],
X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).e_rabs_admitted_tobeadded[i].gnb_addr.buffer[3],
X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).e_rabs_admitted_tobeadded[i].gnb_addr.length,
X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).e_rabs_admitted_tobeadded[i].gtp_teid);
}
} else
LOG_W(RRC, "No E-RAB to be added received from SgNB Addition Request message \n");
X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).MeNB_ue_x2_id = m->ue_x2_id;
X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).SgNB_ue_x2_id = secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity;
//X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer_size = CG_Config_size; //Need to verify correct value for the buffer_size
// Send to X2 entity to transport to MeNB
asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CG_Config,
NULL,
(void *)CG_Config,
X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer,
sizeof(X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer));
X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer_size = (enc_rval.encoded+7)>>3;
itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(0), msg); //Check right id instead of hardcoding
}
}
// below we configure the stack. In SA, we fully adopted F1, meaning that
// layers use different IDs (MAC/RLC use RNTI as DU UE ID, above use NGAP ID
// as CU UE ID.
uint32_t du_ue_id = ue_context_p->ue_context.rnti;
uint32_t rrc_ue_id = ue_context_p->ue_context.rrc_ue_id;
f1_ue_data_t du_ue_data = {.secondary_ue = rrc_ue_id};
bool success = du_add_f1_ue_data(du_ue_id, &du_ue_data);
DevAssert(success);
f1_ue_data_t cu_ue_data = {.secondary_ue = du_ue_id};
success = cu_add_f1_ue_data(rrc_ue_id, &cu_ue_data);
DevAssert(success);
LOG_I(RRC, "Assign CU UE ID %d and DU UE ID %d to UE RNTI %04x\n", rrc_ue_id, du_ue_id, ue_context_p->ue_context.rnti);
// configure MAC and RLC
bool ret = false;
if (get_softmodem_params()->phy_test) {
// phytest mode: we don't set up RA, etc
ret = nr_mac_add_test_ue(RC.nrmac[rrc->module_id], du_ue_id, secondaryCellGroup);
} else {
DevAssert(secondaryCellGroup->spCellConfig
&& secondaryCellGroup->spCellConfig->reconfigurationWithSync
&& secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated
&& secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra);
NR_SCHED_LOCK(&RC.nrmac[rrc->module_id]->sched_lock);
ret = nr_mac_prepare_ra_ue(RC.nrmac[rrc->module_id], du_ue_id, secondaryCellGroup);
NR_SCHED_UNLOCK(&RC.nrmac[rrc->module_id]->sched_lock);
}
AssertFatal(ret, "cannot add NSA UE in MAC, aborting\n");
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, rrc->module_id, GNB_FLAG_YES, rrc_ue_id, 0, 0, rrc->module_id);
LOG_W(RRC,
"Calling RRC PDCP/RLC ASN1 request functions for protocol context %p with module_id %d, rnti %lx, frame %d, subframe %d eNB_index %d \n",
&ctxt,
ctxt.module_id,
ctxt.rntiMaybeUEid,
ctxt.frame,
ctxt.subframe,
ctxt.eNB_index);
nr_pdcp_add_drbs(ctxt.enb_flag,
rrc_ue_id,
ue_context_p->ue_context.rb_config->drb_ToAddModList,
DevAssert(UE->rb_config != NULL);
nr_pdcp_add_drbs(GNB_FLAG_YES,
UE->rrc_ue_id,
UE->rb_config->drb_ToAddModList,
&security_parameters);
ctxt.rntiMaybeUEid = du_ue_id;
// assume only a single bearer
const NR_DRB_ToAddModList_t *drb_list = ue_context_p->ue_context.rb_config->drb_ToAddModList;
DevAssert(drb_list->list.count == 1);
const NR_DRB_ToAddMod_t *drb = drb_list->list.array[0];
const struct NR_CellGroupConfig__rlc_BearerToAddModList *bearer_list = secondaryCellGroup->rlc_BearerToAddModList;
const NR_RLC_BearerConfig_t *bearer = bearer_list->list.array[0];
DevAssert(bearer_list->list.count == 1);
DevAssert(drb->drb_Identity == bearer->servedRadioBearer->choice.drb_Identity);
nr_rlc_add_drb(ctxt.rntiMaybeUEid, drb->drb_Identity, bearer);
LOG_D(RRC, "%s:%d: done RRC PDCP/RLC ASN1 request for UE rnti %lx\n", __FUNCTION__, __LINE__, ctxt.rntiMaybeUEid);
cu_to_du_rrc_information_t cu2du = {
.cG_ConfigInfo = cgci_buf,
.cG_ConfigInfo_length = cgci_len,
};
/* assumption: only a single bearer, see above */
NR_DRB_ToAddModList_t *rb_list = UE->rb_config->drb_ToAddModList;
AssertFatal(rb_list->list.count == 1, "can only handle one bearer for NSA/phy-test/do-ra, but has %d\n", rb_list->list.count);
int drb_id = rb_list->list.array[0]->drb_Identity;
f1ap_flows_mapped_to_drb_t *flow = calloc(1, sizeof(f1ap_flows_mapped_to_drb_t));
flow->qos_params.qos_characteristics.qos_type = NON_DYNAMIC;
flow->qfi = flow->qos_params.qos_characteristics.non_dynamic.fiveqi = 9;
f1ap_drb_to_be_setup_t drbs = {
.drb_id = drb_id,
.rlc_mode = F1AP_RLC_MODE_UM_BIDIR, // hardcoded keep it backwards compatible for now
// rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM,
.up_ul_tnl_length = 1,
.drb_info.flows_to_be_setup_length = 1,
.drb_info.flows_mapped_to_drb = flow,
};
// Note: E1 support for NSA/phy-test/do-ra not implemented yet
instance_t f1inst = get_f1_gtp_instance();
if (f1inst >= 0) {
gtpv1u_gnb_create_tunnel_req_t req = {
.ue_id = UE->rrc_ue_id,
.incoming_rb_id[0] = drb_id,
.pdusession_id[0] = drb_id,
.outgoing_teid[0] = 0xffff, // will be updated later
.dst_addr[0].length = 32,
.num_tunnels = 1,
};
gtpv1u_gnb_create_tunnel_resp_t resp = {0};
int ret = gtpv1u_create_ngu_tunnel(f1inst, &req, &resp, NULL, NULL);
AssertFatal(ret == 0, "gtpv1u_create_ngu_tunnel failed: ret %d\n", ret);
drbs.up_ul_tnl[0].port = rrc->eth_params_s.my_portd;
memcpy(&drbs.up_ul_tnl[0].tl_address, &resp.gnb_addr.buffer, 4);
drbs.up_ul_tnl[0].teid = resp.gnb_NGu_teid[0];
}
f1ap_ue_context_setup_t req = {
.gNB_CU_ue_id = UE->rrc_ue_id,
.gNB_DU_ue_id = 0xffffffff, /* not known yet */
.plmn.mcc = rrc->configuration.plmn[0].mcc,
.plmn.mnc = rrc->configuration.plmn[0].mnc,
.plmn.mnc_digit_length = rrc->configuration.plmn[0].mnc_digit_length,
.nr_cellid = rrc->nr_cellid,
.servCellId = 0,
.drbs_to_be_setup_length = 1,
.drbs_to_be_setup = &drbs,
.cu_to_du_rrc_information = &cu2du,
};
f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id);
RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id);
rrc->mac_rrc.ue_context_setup_request(ue_data.du_assoc_id, &req);
}
void rrc_remove_nsa_user(gNB_RRC_INST *rrc, int rnti) {
protocol_ctxt_t ctxt;
rrc_gNB_ue_context_t *ue_context;
int e_rab;
static NR_RRCReconfiguration_IEs_t *get_default_reconfig(const NR_CellGroupConfig_t *secondaryCellGroup)
{
NR_RRCReconfiguration_IEs_t *reconfig = calloc(1, sizeof(NR_RRCReconfiguration_IEs_t));
AssertFatal(reconfig != NULL, "out of memory\n");
AssertFatal(secondaryCellGroup != NULL, "secondaryCellGroup is null\n");
reconfig->radioBearerConfig = NULL;
LOG_D(RRC, "calling rrc_remove_nsa_user rnti %x\n", rnti);
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, rrc->module_id, GNB_FLAG_YES, rnti, 0, 0, rrc->module_id);
char scg_buffer[1024];
asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, NULL, (void *)secondaryCellGroup, scg_buffer, 1024);
AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", enc_rval.failed_type->name, enc_rval.encoded);
reconfig->secondaryCellGroup = calloc(1, sizeof(*reconfig->secondaryCellGroup));
OCTET_STRING_fromBuf(reconfig->secondaryCellGroup, (const char *)scg_buffer, (enc_rval.encoded + 7) >> 3);
reconfig->measConfig = NULL;
reconfig->lateNonCriticalExtension = NULL;
reconfig->nonCriticalExtension = NULL;
return reconfig;
}
ue_context = rrc_gNB_get_ue_context_by_rnti_any_du(rrc, rnti);
if (ue_context == NULL) {
LOG_W(RRC, "rrc_remove_nsa_user: rnti %x not found\n", rnti);
static NR_CG_Config_t *generate_CG_Config(const NR_RRCReconfiguration_t *reconfig, const NR_RadioBearerConfig_t *rbconfig)
{
NR_CG_Config_t *cg_Config = calloc_or_fail(1, sizeof(*cg_Config));
cg_Config->criticalExtensions.present = NR_CG_Config__criticalExtensions_PR_c1;
cg_Config->criticalExtensions.choice.c1 = calloc_or_fail(1, sizeof(*cg_Config->criticalExtensions.choice.c1));
cg_Config->criticalExtensions.choice.c1->present = NR_CG_Config__criticalExtensions__c1_PR_cg_Config;
NR_CG_Config_IEs_t *cgc_ie = calloc_or_fail(1, sizeof(*cgc_ie));
cg_Config->criticalExtensions.choice.c1->choice.cg_Config = cgc_ie;
cgc_ie->scg_CellGroupConfig = calloc_or_fail(1, sizeof(*cgc_ie->scg_CellGroupConfig));
cgc_ie->scg_CellGroupConfig->size =
uper_encode_to_new_buffer(&asn_DEF_NR_RRCReconfiguration, NULL, reconfig, (void **)&cgc_ie->scg_CellGroupConfig->buf);
AssertFatal(cgc_ie->scg_CellGroupConfig->size > 0,
"ASN1 message encoding of RRCReconfiguration failed (%ld)!\n",
cgc_ie->scg_CellGroupConfig->size);
cgc_ie->scg_RB_Config = calloc_or_fail(1, sizeof(*cgc_ie->scg_RB_Config));
cgc_ie->scg_RB_Config->size =
uper_encode_to_new_buffer(&asn_DEF_NR_RadioBearerConfig, NULL, rbconfig, (void **)&cgc_ie->scg_RB_Config->buf);
AssertFatal(cgc_ie->scg_RB_Config->size > 0, "ASN1 message encoding failed (%ld)!\n", cgc_ie->scg_RB_Config->size);
if (get_softmodem_params()->phy_test == 1 || get_softmodem_params()->do_ra > 0) {
// This is for phytest only, emulate first X2 message if uecap.raw file is present
LOG_I(RRC, "Dumping NR_RRCReconfiguration message (%jd bytes) to reconfig.raw\n", cgc_ie->scg_CellGroupConfig->size);
FILE *fd = fopen("reconfig.raw", "w");
AssertFatal(fd != NULL, "could not open reconig.raw for writing: %d, %s\n", errno, strerror(errno));
fwrite(cgc_ie->scg_CellGroupConfig->buf, cgc_ie->scg_CellGroupConfig->size, 1, fd);
fclose(fd);
LOG_I(RRC, "Dumping scg_RB_Config message (%jd bytes) to reconfig.raw\n", cgc_ie->scg_RB_Config->size);
fd = fopen("rbconfig.raw", "w");
AssertFatal(fd != NULL, "could not open rbconig.raw for writing: %d, %s\n", errno, strerror(errno));
fwrite(cgc_ie->scg_RB_Config->buf, cgc_ie->scg_RB_Config->size, 1, fd);
fclose(fd);
}
return cg_Config;
}
void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_context_setup_t *resp)
{
DevAssert(resp->crnti != NULL);
/* we did not fill any DU-related ID info in rrc_add_nsa_user() */
UE->rnti = *resp->crnti;
DevAssert(cu_exists_f1_ue_data(UE->rrc_ue_id));
f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id);
ue_data.secondary_ue = resp->gNB_DU_ue_id;
bool success = cu_update_f1_ue_data(UE->rrc_ue_id, &ue_data);
DevAssert(success);
instance_t f1inst = get_f1_gtp_instance();
if (f1inst >= 0) {
// Note: E1 support for NSA/phy-test/do-ra not implemented yet
// so set up GTP from here
for (int i = 0; i < resp->drbs_to_be_setup_length; ++i) {
f1ap_drb_to_be_setup_t *drb = &resp->drbs_to_be_setup[i];
DevAssert(drb->up_dl_tnl_length == 1);
in_addr_t addr = drb->up_dl_tnl[0].tl_address;
uint32_t teid = drb->up_dl_tnl[0].teid;
GtpuUpdateTunnelOutgoingAddressAndTeid(f1inst, UE->rrc_ue_id, drb->drb_id, addr, teid);
}
}
NR_RRCReconfiguration_t *reconfig = calloc(1, sizeof(NR_RRCReconfiguration_t));
reconfig->rrc_TransactionIdentifier = 0;
reconfig->criticalExtensions.present = NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration;
reconfig->criticalExtensions.choice.rrcReconfiguration = get_default_reconfig(UE->masterCellGroup);
NR_CG_Config_t *CG_Config = generate_CG_Config(reconfig, UE->rb_config);
if (get_softmodem_params()->phy_test > 0 || get_softmodem_params()->do_ra > 0) {
/* we are done, no X2 answer necessary */
ASN_STRUCT_FREE(asn_DEF_NR_CG_Config, CG_Config);
return;
}
nr_pdcp_remove_UE(ue_context->ue_context.rrc_ue_id);
rrc_rlc_remove_ue(&ctxt);
MessageDef *msg = itti_alloc_new_message(TASK_RRC_ENB, 0, X2AP_ENDC_SGNB_ADDITION_REQ_ACK);
x2ap_ENDC_sgnb_addition_req_ACK_t *ack = &X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg);
// lock the scheduler before removing the UE. Note: mac_remove_nr_ue() checks
// that the scheduler is actually locked!
NR_SCHED_LOCK(&RC.nrmac[rrc->module_id]->sched_lock);
mac_remove_nr_ue(RC.nrmac[rrc->module_id], rnti);
NR_SCHED_UNLOCK(&RC.nrmac[rrc->module_id]->sched_lock);
gtpv1u_enb_delete_tunnel_req_t tmp={0};
tmp.rnti=rnti;
tmp.from_gnb=1;
LOG_D(RRC, "ue_context->ue_context.nb_of_e_rabs %d will be deleted for rnti %x\n", ue_context->ue_context.nb_of_e_rabs, rnti);
for (e_rab = 0; e_rab < ue_context->ue_context.nb_of_e_rabs; e_rab++) {
tmp.eps_bearer_id[tmp.num_erab++]= ue_context->ue_context.nsa_gtp_ebi[e_rab];
// erase data
ue_context->ue_context.nsa_gtp_teid[e_rab] = 0;
memset(&ue_context->ue_context.nsa_gtp_addrs[e_rab], 0, sizeof(ue_context->ue_context.nsa_gtp_addrs[e_rab]));
ue_context->ue_context.nsa_gtp_ebi[e_rab] = 0;
ack->nb_e_rabs_admitted_tobeadded = UE->nb_of_e_rabs;
DevAssert(UE->x2_target_assoc > 0);
ack->target_assoc_id = UE->x2_target_assoc;
for (int i = 0; i < UE->nb_of_e_rabs; i++) {
ack->e_rabs_admitted_tobeadded[i].e_rab_id = UE->e_rab[i].param.e_rab_id;
ack->e_rabs_admitted_tobeadded[i].gtp_teid = UE->nsa_gtp_teid[0];
memcpy(&ack->e_rabs_admitted_tobeadded[i].gnb_addr, &UE->nsa_gtp_addrs[0], sizeof(transport_layer_addr_t));
ack->e_rabs_admitted_tobeadded[i].gnb_addr.length = 32; // bits, IPv4 only
}
gtpv1u_delete_all_s1u_tunnel(rrc->module_id, rnti);
/* remove context */
rrc_gNB_remove_ue_context(rrc, ue_context);
ack->MeNB_ue_x2_id = UE->MeNB_ue_x2_id;
ack->SgNB_ue_x2_id = UE->rrc_ue_id;
// Send to X2 entity to transport to MeNB
asn_enc_rval_t enc_rval =
uper_encode_to_buffer(&asn_DEF_NR_CG_Config, NULL, (void *)CG_Config, ack->rrc_buffer, sizeof(ack->rrc_buffer));
ack->rrc_buffer_size = (enc_rval.encoded + 7) >> 3;
itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(0), msg);
ASN_STRUCT_FREE(asn_DEF_NR_CG_Config, CG_Config);
}
void rrc_remove_nsa_user_context(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context)
{
if (!IS_SOFTMODEM_NOS1)
gtpv1u_delete_all_s1u_tunnel(rrc->module_id, ue_context->ue_context.rrc_ue_id);
instance_t f1inst = get_f1_gtp_instance();
if (f1inst >= 0)
gtpv1u_delete_all_s1u_tunnel(f1inst, ue_context->ue_context.rrc_ue_id);
// we don't use E1 => we have to free SDAP
nr_sdap_delete_ue_entities(ue_context->ue_context.rrc_ue_id);
rrc_remove_ue(rrc, ue_context);
}
void rrc_release_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context)
{
gNB_RRC_UE_t *UE = &ue_context->ue_context;
f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id);
RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id);
f1ap_ue_context_release_cmd_t cmd = {
.gNB_CU_ue_id = UE->rrc_ue_id,
.gNB_DU_ue_id = ue_data.secondary_ue,
.cause = F1AP_CAUSE_RADIO_NETWORK,
.cause_value = 10, // 10 = F1AP_CauseRadioNetwork_normal_release
};
rrc->mac_rrc.ue_context_release_command(ue_data.du_assoc_id, &cmd);
rrc_remove_nsa_user_context(rrc, ue_context);
}
-66
View File
@@ -1,66 +0,0 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file rrc_gNB_reconfig.c
* \brief rrc gNB RRCreconfiguration support routines
* \author Raymond Knopp
* \date 2019
* \version 1.0
* \company Eurecom
* \email: raymond.knopp@eurecom.fr
*/
#ifndef RRC_GNB_NSA_C
#define RRC_GNB_NSA_C
#include <stdlib.h>
#include "OCTET_STRING.h"
#include "RRC/NR/nr_rrc_proto.h"
#include "asn_codecs.h"
#include "assertions.h"
#include "constr_TYPE.h"
#include "oai_asn1.h"
#include "uper_encoder.h"
NR_RRCReconfiguration_IEs_t *get_default_reconfig(const NR_CellGroupConfig_t *secondaryCellGroup)
{
NR_RRCReconfiguration_IEs_t *reconfig = calloc(1, sizeof(NR_RRCReconfiguration_IEs_t));
AssertFatal(reconfig != NULL, "out of memory\n");
AssertFatal(secondaryCellGroup!=NULL,"secondaryCellGroup is null\n");
// radioBearerConfig
reconfig->radioBearerConfig=NULL;
char scg_buffer[1024];
asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, NULL, (void *)secondaryCellGroup, scg_buffer, 1024);
AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", enc_rval.failed_type->name, enc_rval.encoded);
reconfig->secondaryCellGroup = calloc(1,sizeof(*reconfig->secondaryCellGroup));
OCTET_STRING_fromBuf(reconfig->secondaryCellGroup,
(const char *)scg_buffer,
(enc_rval.encoded+7)>>3);
// measConfig
reconfig->measConfig=NULL;
// lateNonCriticalExtension
reconfig->lateNonCriticalExtension = NULL;
// nonCriticalExtension
reconfig->nonCriticalExtension = NULL;
return reconfig;
}
#endif
+1 -2
View File
@@ -1138,8 +1138,7 @@ static void rrc_ue_generate_RRCSetupComplete(const NR_UE_RRC_INST_t *rrc, const
nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, size, buffer, deliver_pdu_srb_rlc, NULL);
}
static void nr_rrc_process_rrcsetup(NR_UE_RRC_INST_t *rrc,
const NR_RRCSetup_t *rrcSetup)
static void nr_rrc_process_rrcsetup(NR_UE_RRC_INST_t *rrc, const NR_RRCSetup_t *rrcSetup)
{
// if the RRCSetup is received in response to an RRCReestablishmentRequest
// or RRCResumeRequest or RRCResumeRequest1
+14 -21
View File
@@ -107,17 +107,10 @@ void sdap_data_ind(rb_id_t pdcp_entity,
size);
}
struct thread_args {
nr_sdap_entity_t *entity;
bool is_gnb;
};
static void *sdap_tun_read_thread(void *arg)
{
DevAssert(arg != NULL);
struct thread_args *ta = arg;
nr_sdap_entity_t *entity = ta->entity;
bool is_gnb = ta->is_gnb;
free(ta);
nr_sdap_entity_t *entity = arg;
char rx_buf[NL_MAX_PAYLOAD];
int len;
@@ -134,9 +127,9 @@ static void *sdap_tun_read_thread(void *arg)
LOG_D(SDAP, "read data of size %d\n", len);
protocol_ctxt_t ctxt = {.enb_flag = is_gnb, .rntiMaybeUEid = entity->ue_id};
protocol_ctxt_t ctxt = {.enb_flag = entity->is_gnb, .rntiMaybeUEid = entity->ue_id};
bool dc = is_gnb ? false : SDAP_HDR_UL_DATA_PDU;
bool dc = entity->is_gnb ? false : SDAP_HDR_UL_DATA_PDU;
DevAssert(entity != NULL);
entity->tx_entity(entity,
@@ -161,30 +154,25 @@ void start_sdap_tun_gnb_first_ue_default_pdu_session(ue_id_t ue_id)
{
nr_sdap_entity_t *entity = nr_sdap_get_entity(ue_id, get_softmodem_params()->default_pdu_session_id);
DevAssert(entity != NULL);
DevAssert(entity->is_gnb);
char *ifprefix = get_softmodem_params()->nsa ? "oaitun_gnb" : "oaitun_enb";
char ifname[IFNAMSIZ];
tun_generate_ifname(ifname, ifprefix, ue_id - 1);
entity->pdusession_sock = tun_alloc(ifname);
tun_config(ifname, "10.0.1.1", NULL);
struct thread_args *ta = calloc_or_fail(1, sizeof(*ta));
ta->entity = entity;
ta->is_gnb = true;
threadCreate(&entity->pdusession_thread, sdap_tun_read_thread, ta, "gnb_tun_read_thread", -1, OAI_PRIORITY_RT_LOW);
threadCreate(&entity->pdusession_thread, sdap_tun_read_thread, entity, "gnb_tun_read_thread", -1, OAI_PRIORITY_RT_LOW);
}
void start_sdap_tun_ue(ue_id_t ue_id, int pdu_session_id, int sock)
{
nr_sdap_entity_t *entity = nr_sdap_get_entity(ue_id, pdu_session_id);
DevAssert(entity != NULL);
DevAssert(!entity->is_gnb);
entity->pdusession_sock = sock;
entity->stop_thread = false;
char thread_name[64];
snprintf(thread_name, sizeof(thread_name), "ue_tun_read_%ld_p%d", ue_id, pdu_session_id);
struct thread_args *ta = calloc_or_fail(1, sizeof(*ta));
ta->entity = entity;
ta->is_gnb = false;
threadCreate(&entity->pdusession_thread, sdap_tun_read_thread, ta, thread_name, -1, OAI_PRIORITY_RT_LOW);
threadCreate(&entity->pdusession_thread, sdap_tun_read_thread, entity, thread_name, -1, OAI_PRIORITY_RT_LOW);
}
@@ -201,7 +189,7 @@ void create_ue_ip_if(const char *ipv4, const char *ipv6, int ue_id, int pdu_sess
start_sdap_tun_ue(ue_id, pdu_session_id, sock); // interface name suffix is ue_id+1
}
void remove_ue_ip_if(nr_sdap_entity_t *entity)
void remove_ip_if(nr_sdap_entity_t *entity)
{
DevAssert(entity != NULL);
// Stop the read thread
@@ -211,6 +199,11 @@ void remove_ue_ip_if(nr_sdap_entity_t *entity)
// Bring down the IP interface
int default_pdu = get_softmodem_params()->default_pdu_session_id;
char ifname[IFNAMSIZ];
tun_generate_ue_ifname(ifname, entity->ue_id, entity->pdusession_id != default_pdu ? entity->pdusession_id : -1);
if (entity->is_gnb) {
char *ifprefix = get_softmodem_params()->nsa ? "oaitun_gnb" : "oaitun_enb";
tun_generate_ifname(ifname, ifprefix, entity->ue_id - 1);
} else {
tun_generate_ue_ifname(ifname, entity->ue_id, entity->pdusession_id != default_pdu ? entity->pdusession_id : -1);
}
tun_destroy(ifname, entity->pdusession_sock);
}
+9 -2
View File
@@ -502,6 +502,7 @@ nr_sdap_entity_t *new_nr_sdap_entity(int is_gnb,
sdap_entity->ue_id = ue_id;
sdap_entity->pdusession_id = pdusession_id;
sdap_entity->is_gnb = is_gnb;
sdap_entity->tx_entity = nr_sdap_tx_entity;
sdap_entity->rx_entity = nr_sdap_rx_entity;
@@ -587,6 +588,8 @@ bool nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id)
if (entityPtr->ue_id == ue_id && entityPtr->pdusession_id == pdusession_id) {
sdap_info.sdap_entity_llist = sdap_info.sdap_entity_llist->next_entity;
if (entityPtr->pdusession_sock != -1)
remove_ip_if(entityPtr);
free(entityPtr);
LOG_D(SDAP, "Successfully deleted Entity.\n");
ret = true;
@@ -600,8 +603,8 @@ bool nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id)
if (entityPtr->ue_id == ue_id && entityPtr->pdusession_id == pdusession_id) {
entityPrev->next_entity = entityPtr->next_entity;
if (entityPrev->pdusession_sock != -1) {
remove_ue_ip_if(entityPrev);
if (entityPtr->pdusession_sock != -1) {
remove_ip_if(entityPtr);
}
free(entityPtr);
LOG_D(SDAP, "Successfully deleted Entity.\n");
@@ -627,6 +630,8 @@ bool nr_sdap_delete_ue_entities(ue_id_t ue_id)
/* Handle scenario where ue_id matches the head of the list */
while (entityPtr != NULL && entityPtr->ue_id == ue_id && upperBound < MAX_DRBS_PER_UE) {
sdap_info.sdap_entity_llist = entityPtr->next_entity;
if (entityPtr->pdusession_sock != -1)
remove_ip_if(entityPtr);
free(entityPtr);
entityPtr = sdap_info.sdap_entity_llist;
ret = true;
@@ -638,6 +643,8 @@ bool nr_sdap_delete_ue_entities(ue_id_t ue_id)
entityPtr = entityPtr->next_entity;
} else {
entityPrev->next_entity = entityPtr->next_entity;
if (entityPtr->pdusession_sock != -1)
remove_ip_if(entityPtr);
free(entityPtr);
entityPtr = entityPrev->next_entity;
LOG_I(SDAP, "Successfully deleted SDAP entity for UE %ld\n", ue_id);
+4 -1
View File
@@ -80,6 +80,9 @@ void nr_pdcp_submit_sdap_ctrl_pdu(ue_id_t ue_id, rb_id_t sdap_ctrl_pdu_drb, nr_s
typedef struct nr_sdap_entity_s {
ue_id_t ue_id;
rb_id_t default_drb;
/// sdap_tun_read_thread needs to know if we are gNB/UE, so for noS1 mode,
/// store which one we are
bool is_gnb;
int pdusession_id;
int pdusession_sock;
pthread_t pdusession_thread;
@@ -218,5 +221,5 @@ bool is_sdap_tx(bool is_gnb, NR_SDAP_Config_t *sdap_config);
void nr_reconfigure_sdap_entity(NR_SDAP_Config_t *sdap_config, ue_id_t ue_id, int pdusession_id, int drb_id);
void set_qfi(uint8_t qfi, uint8_t pduid, ue_id_t ue_id);
void remove_ue_ip_if(nr_sdap_entity_t *entity);
void remove_ip_if(nr_sdap_entity_t *entity);
#endif