DU-level changes to handle F1 UE Context Setup in NSA/phy-test/do-ra
Co-authored-by: Francesco Mani <email@francescomani.it>
This commit is contained in:
committed by
francescomani
co-authored by
Francesco Mani
parent
6c5514d5c9
commit
7b9442f58d
@@ -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"
|
||||
@@ -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,45 +522,75 @@ 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;
|
||||
rnti_t rnti;
|
||||
bool found = nr_mac_get_new_rnti(&mac->UE_info, &rnti);
|
||||
if (!found)
|
||||
return NULL;
|
||||
|
||||
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");
|
||||
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;
|
||||
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);
|
||||
// TODO: fixme: gives a new random RNTI
|
||||
UE->rnti = cellGroupConfig->spCellConfig->reconfigurationWithSync->newUE_Identity;
|
||||
// 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
|
||||
AssertFatal(cellGroupConfig != NULL, "out of memory\n");
|
||||
UE->CellGroup = cellGroupConfig;
|
||||
|
||||
nr_rlc_activate_srb0(UE->rnti, UE, NULL);
|
||||
nr_mac_prepare_ra_ue(mac, UE);
|
||||
/* 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 = {
|
||||
@@ -525,9 +604,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) {
|
||||
@@ -535,15 +616,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");
|
||||
@@ -573,12 +660,13 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
|
||||
|
||||
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
|
||||
// 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) {
|
||||
@@ -601,7 +689,8 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
|
||||
@@ -329,7 +329,6 @@ void mac_top_init_gNB(ngran_node_t node_type,
|
||||
// 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);
|
||||
|
||||
@@ -3559,12 +3559,8 @@ 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();
|
||||
|
||||
Reference in New Issue
Block a user