Forward UE capabilities to DU and use for CellGroupConfig
- Forward UE capabilities in F1 handlers - Store at MAC - Update CellGroupConfig with UE Capabilities of the UE
This commit is contained in:
@@ -1948,6 +1948,7 @@ void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_alloca
|
||||
{
|
||||
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;
|
||||
destroy_nr_list(&sched_ctrl->available_dl_harq);
|
||||
destroy_nr_list(&sched_ctrl->feedback_dl_harq);
|
||||
|
||||
@@ -138,6 +138,42 @@ static int handle_ue_context_drbs_setup(int rnti,
|
||||
return drbs_len;
|
||||
}
|
||||
|
||||
static NR_UE_NR_Capability_t *get_ue_nr_cap(int rnti, uint8_t *buf, uint32_t len)
|
||||
{
|
||||
if (buf == NULL || len == 0)
|
||||
return NULL;
|
||||
|
||||
NR_UE_CapabilityRAT_ContainerList_t *clist = NULL;
|
||||
asn_dec_rval_t dec_rval = uper_decode(NULL, &asn_DEF_NR_UE_CapabilityRAT_ContainerList, (void **)&clist, buf, len, 0, 0);
|
||||
if (dec_rval.code != RC_OK) {
|
||||
LOG_W(NR_MAC, "cannot decode UE capability container list of UE RNTI %04x, ignoring capabilities\n", rnti);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NR_UE_NR_Capability_t *cap = NULL;
|
||||
for (int i = 0; i < clist->list.count; i++) {
|
||||
const NR_UE_CapabilityRAT_Container_t *c = clist->list.array[i];
|
||||
if (cap != NULL || c->rat_Type != NR_RAT_Type_nr) {
|
||||
LOG_W(NR_MAC, "UE RNTI %04x: ignoring capability of type %ld\n", rnti, c->rat_Type);
|
||||
continue;
|
||||
}
|
||||
|
||||
asn_dec_rval_t dec_rval = uper_decode(NULL,
|
||||
&asn_DEF_NR_UE_NR_Capability,
|
||||
(void **)&cap,
|
||||
c->ue_CapabilityRAT_Container.buf,
|
||||
c->ue_CapabilityRAT_Container.size,
|
||||
0,
|
||||
0);
|
||||
if (dec_rval.code != RC_OK) {
|
||||
LOG_W(NR_MAC, "cannot decode NR UE capabilities of UE RNTI %04x, ignoring NR capability\n", rnti);
|
||||
cap = NULL;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return cap;
|
||||
}
|
||||
|
||||
static NR_CellGroupConfig_t *clone_CellGroupConfig(const NR_CellGroupConfig_t *orig)
|
||||
{
|
||||
uint8_t buf[16636];
|
||||
@@ -159,9 +195,12 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
|
||||
.gNB_DU_ue_id = req->gNB_DU_ue_id,
|
||||
};
|
||||
|
||||
NR_UE_NR_Capability_t *ue_cap = NULL;
|
||||
if (req->cu_to_du_rrc_information != NULL) {
|
||||
AssertFatal(req->cu_to_du_rrc_information->cG_ConfigInfo == NULL, "CG-ConfigInfo not handled\n");
|
||||
AssertFatal(req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList == NULL, "UE capabilities not handled yet\n");
|
||||
ue_cap = get_ue_nr_cap(req->gNB_DU_ue_id,
|
||||
req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList,
|
||||
req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length);
|
||||
AssertFatal(req->cu_to_du_rrc_information->measConfig == NULL, "MeasConfig not handled\n");
|
||||
}
|
||||
|
||||
@@ -191,7 +230,16 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
|
||||
if (req->rrc_container != NULL)
|
||||
nr_rlc_srb_recv_sdu(req->gNB_DU_ue_id, DCCH, req->rrc_container, req->rrc_container_length);
|
||||
|
||||
//nr_mac_update_cellgroup()
|
||||
UE->capability = ue_cap;
|
||||
if (ue_cap != NULL) {
|
||||
// store the new UE capabilities, and update the cellGroupConfig
|
||||
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);
|
||||
}
|
||||
|
||||
resp.du_to_cu_rrc_information = calloc(1, sizeof(du_to_cu_rrc_information_t));
|
||||
AssertFatal(resp.du_to_cu_rrc_information != NULL, "out of memory\n");
|
||||
resp.du_to_cu_rrc_information->cellGroupConfig = calloc(1,1024);
|
||||
@@ -228,9 +276,12 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
|
||||
.gNB_DU_ue_id = req->gNB_DU_ue_id,
|
||||
};
|
||||
|
||||
NR_UE_NR_Capability_t *ue_cap = NULL;
|
||||
if (req->cu_to_du_rrc_information != NULL) {
|
||||
AssertFatal(req->cu_to_du_rrc_information->cG_ConfigInfo == NULL, "CG-ConfigInfo not handled\n");
|
||||
AssertFatal(req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList == NULL, "UE capabilities not handled yet\n");
|
||||
ue_cap = get_ue_nr_cap(req->gNB_DU_ue_id,
|
||||
req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList,
|
||||
req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length);
|
||||
AssertFatal(req->cu_to_du_rrc_information->measConfig == NULL, "MeasConfig not handled\n");
|
||||
}
|
||||
|
||||
@@ -263,7 +314,16 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
|
||||
"RRC reconfiguration outcome unsuccessful, but no rollback mechanism implemented to come back to old configuration\n");
|
||||
}
|
||||
|
||||
if (req->srbs_to_be_setup_length > 0 || req->drbs_to_be_setup_length > 0) {
|
||||
if (ue_cap != NULL) {
|
||||
// store the new UE capabilities, and update the cellGroupConfig
|
||||
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);
|
||||
}
|
||||
|
||||
if (req->srbs_to_be_setup_length > 0 || req->drbs_to_be_setup_length > 0 || ue_cap != NULL) {
|
||||
resp.du_to_cu_rrc_information = calloc(1, sizeof(du_to_cu_rrc_information_t));
|
||||
AssertFatal(resp.du_to_cu_rrc_information != NULL, "out of memory\n");
|
||||
resp.du_to_cu_rrc_information->cellGroupConfig = calloc(1, 1024);
|
||||
|
||||
@@ -703,6 +703,7 @@ typedef struct {
|
||||
bool expect_reconfiguration;
|
||||
NR_CellGroupConfig_t *reconfigCellGroup;
|
||||
bool apply_cellgroup;
|
||||
NR_UE_NR_Capability_t *capability;
|
||||
// UE selected beam index
|
||||
uint8_t UE_beam_index;
|
||||
bool Msg4_ACKed;
|
||||
|
||||
@@ -739,19 +739,7 @@ int16_t do_RRCReconfiguration(
|
||||
ie->nonCriticalExtension->dedicatedNAS_MessageList = dedicatedNAS_MessageList;
|
||||
}
|
||||
|
||||
if(cellGroupConfig!=NULL){
|
||||
/* TODO UECAP: update_cellGroupConfig should not even be here, it is
|
||||
* updated by DU */
|
||||
if (scc != NULL) {
|
||||
update_cellGroupConfig(cellGroupConfig,
|
||||
ue_context_pP->ue_context.rrc_ue_id,
|
||||
ue_context_pP ? ue_context_pP->ue_context.UE_Capability_nr : NULL,
|
||||
NULL,
|
||||
scc);
|
||||
} else {
|
||||
LOG_W(RRC, "no scc, cannot update cellGroup\n");
|
||||
}
|
||||
|
||||
if (cellGroupConfig != NULL) {
|
||||
enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig,
|
||||
NULL,
|
||||
(void *)cellGroupConfig,
|
||||
|
||||
@@ -64,7 +64,21 @@ static void ue_context_modification_request_f1ap(const f1ap_ue_context_modif_req
|
||||
MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_REQ);
|
||||
f1ap_ue_context_modif_req_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_REQ(msg);
|
||||
*f1ap_msg = *req;
|
||||
AssertFatal(req->cu_to_du_rrc_information == NULL, "cu_to_du_rrc_information not supported yet\n");
|
||||
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");
|
||||
if (req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList != NULL) {
|
||||
const cu_to_du_rrc_information_t *du2cu_req = req->cu_to_du_rrc_information;
|
||||
cu_to_du_rrc_information_t* du2cu_new = f1ap_msg->cu_to_du_rrc_information;
|
||||
DevAssert(du2cu_req->uE_CapabilityRAT_ContainerList_length > 0);
|
||||
du2cu_new->uE_CapabilityRAT_ContainerList_length = du2cu_req->uE_CapabilityRAT_ContainerList_length;
|
||||
du2cu_new->uE_CapabilityRAT_ContainerList = malloc(du2cu_new->uE_CapabilityRAT_ContainerList_length);
|
||||
AssertFatal(du2cu_new->uE_CapabilityRAT_ContainerList != NULL, "out of memory\n");
|
||||
memcpy(du2cu_new->uE_CapabilityRAT_ContainerList, du2cu_req->uE_CapabilityRAT_ContainerList, du2cu_new->uE_CapabilityRAT_ContainerList_length);
|
||||
}
|
||||
}
|
||||
AssertFatal(req->drbs_to_be_modified_length == 0, "drbs_to_be_modified not supported yet\n");
|
||||
if (req->drbs_to_be_setup_length > 0) {
|
||||
int n = req->drbs_to_be_setup_length;
|
||||
|
||||
@@ -2348,23 +2348,10 @@ void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig,
|
||||
const NR_ServingCellConfigCommon_t *scc)
|
||||
{
|
||||
DevAssert(cellGroupConfig != NULL);
|
||||
/* this is wrong: we should not call this function is spCellConfig is not
|
||||
* allocated */
|
||||
if (cellGroupConfig->spCellConfig == NULL)
|
||||
return;
|
||||
/* same as for spCellConfig */
|
||||
if (configuration == NULL)
|
||||
return;
|
||||
/* if scc is not allocated, there is a serious problem */
|
||||
DevAssert(cellGroupConfig->spCellConfig != NULL);
|
||||
DevAssert(configuration != NULL);
|
||||
DevAssert(scc != NULL);
|
||||
|
||||
/* This is a hack and will be removed once the CellGroupConfig is fully
|
||||
* handled at the DU */
|
||||
if (NODE_IS_CU(RC.nrrrc[0]->node_type)) {
|
||||
LOG_W(RRC, "update of CellGroupConfig not yet supported in F1\n");
|
||||
return;
|
||||
}
|
||||
|
||||
NR_SpCellConfig_t *SpCellConfig = cellGroupConfig->spCellConfig;
|
||||
|
||||
int curr_bwp = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "collection/tree.h"
|
||||
#include "collection/linear_alloc.h"
|
||||
#include "nr_rrc_common.h"
|
||||
#include "ds/byte_array.h"
|
||||
|
||||
#include "common/ngran_types.h"
|
||||
#include "common/platform_constants.h"
|
||||
@@ -243,7 +244,7 @@ typedef struct gNB_RRC_UE_s {
|
||||
NR_HANDOVER_INFO *handover_info;
|
||||
NR_MeasResults_t *measResults;
|
||||
|
||||
|
||||
byte_array_t ue_cap_buffer;
|
||||
NR_UE_NR_Capability_t* UE_Capability_nr;
|
||||
int UE_Capability_size;
|
||||
NR_UE_MRDC_Capability_t* UE_Capability_MRDC;
|
||||
|
||||
+53
-20
@@ -1460,6 +1460,18 @@ static int handle_ueCapabilityInformation(const protocol_ctxt_t *const ctxt_pP,
|
||||
if (ue_cap_info->criticalExtensions.present == NR_UECapabilityInformation__criticalExtensions_PR_ueCapabilityInformation) {
|
||||
const NR_UE_CapabilityRAT_ContainerList_t *ue_CapabilityRAT_ContainerList =
|
||||
ue_cap_info->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList;
|
||||
|
||||
/* Encode UE-CapabilityRAT-ContainerList for sending to the DU */
|
||||
free(UE->ue_cap_buffer.buf);
|
||||
UE->ue_cap_buffer.len = uper_encode_to_new_buffer(&asn_DEF_NR_UE_CapabilityRAT_ContainerList,
|
||||
NULL,
|
||||
ue_CapabilityRAT_ContainerList,
|
||||
(void **)&UE->ue_cap_buffer.buf);
|
||||
if (UE->ue_cap_buffer.len <= 0) {
|
||||
LOG_E(RRC, "could not encode UE-CapabilityRAT-ContainerList, abort handling capabilities\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < ue_CapabilityRAT_ContainerList->list.count; i++) {
|
||||
const NR_UE_CapabilityRAT_Container_t *ue_cap_container = ue_CapabilityRAT_ContainerList->list.array[i];
|
||||
if (ue_cap_container->rat_Type == NR_RAT_Type_nr) {
|
||||
@@ -2370,19 +2382,28 @@ void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_contex
|
||||
srbs[0].lcid = 2;
|
||||
}
|
||||
|
||||
cu_to_du_rrc_information_t cu2du = {0};
|
||||
cu_to_du_rrc_information_t *cu2du_p = NULL;
|
||||
if (UE->ue_cap_buffer.len > 0 && UE->ue_cap_buffer.buf != NULL) {
|
||||
cu2du_p = &cu2du;
|
||||
cu2du.uE_CapabilityRAT_ContainerList = UE->ue_cap_buffer.buf;
|
||||
cu2du.uE_CapabilityRAT_ContainerList_length = UE->ue_cap_buffer.len;
|
||||
}
|
||||
|
||||
f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_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,
|
||||
.plmn.mcc = rrc->configuration.mcc[0],
|
||||
.plmn.mnc = rrc->configuration.mnc[0],
|
||||
.plmn.mnc_digit_length = rrc->configuration.mnc_digit_length[0],
|
||||
.nr_cellid = rrc->nr_cellid,
|
||||
.servCellId = 0, /* TODO: correct value? */
|
||||
.srbs_to_be_setup_length = nb_srb,
|
||||
.srbs_to_be_setup = srbs,
|
||||
.drbs_to_be_setup_length = nb_drb,
|
||||
.drbs_to_be_setup = drbs,
|
||||
.gNB_CU_ue_id = UE->rrc_ue_id,
|
||||
.gNB_DU_ue_id = ue_data.secondary_ue,
|
||||
.plmn.mcc = rrc->configuration.mcc[0],
|
||||
.plmn.mnc = rrc->configuration.mnc[0],
|
||||
.plmn.mnc_digit_length = rrc->configuration.mnc_digit_length[0],
|
||||
.nr_cellid = rrc->nr_cellid,
|
||||
.servCellId = 0, /* TODO: correct value? */
|
||||
.srbs_to_be_setup_length = nb_srb,
|
||||
.srbs_to_be_setup = srbs,
|
||||
.drbs_to_be_setup_length = nb_drb,
|
||||
.drbs_to_be_setup = drbs,
|
||||
.cu_to_du_rrc_information = cu2du_p,
|
||||
};
|
||||
rrc->mac_rrc.ue_context_modification_request(&ue_context_modif_req);
|
||||
}
|
||||
@@ -2727,18 +2748,30 @@ rrc_gNB_generate_SecurityModeCommand(
|
||||
gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id];
|
||||
AssertFatal(!NODE_IS_DU(rrc->node_type), "illegal node type DU!\n");
|
||||
|
||||
cu_to_du_rrc_information_t cu2du = {0};
|
||||
cu_to_du_rrc_information_t *cu2du_p = NULL;
|
||||
if (ue_p->ue_cap_buffer.len > 0 && ue_p->ue_cap_buffer.buf != NULL) {
|
||||
cu2du_p = &cu2du;
|
||||
cu2du.uE_CapabilityRAT_ContainerList = ue_p->ue_cap_buffer.buf;
|
||||
cu2du.uE_CapabilityRAT_ContainerList_length = ue_p->ue_cap_buffer.len;
|
||||
}
|
||||
|
||||
const nr_rrc_du_container_t *du = rrc->du;
|
||||
DevAssert(du != NULL);
|
||||
|
||||
/* the callback will fill the UE context setup request and forward it */
|
||||
f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id);
|
||||
f1ap_ue_context_setup_t ue_context_setup_req = {
|
||||
.gNB_CU_ue_id = ue_p->rrc_ue_id,
|
||||
.gNB_DU_ue_id = ue_data.secondary_ue,
|
||||
.plmn.mcc = rrc->configuration.mcc[0],
|
||||
.plmn.mnc = rrc->configuration.mnc[0],
|
||||
.plmn.mnc_digit_length = rrc->configuration.mnc_digit_length[0],
|
||||
.nr_cellid = rrc->nr_cellid,
|
||||
.servCellId = 0, /* TODO: correct value? */
|
||||
.srbs_to_be_setup = 0, /* no new SRBs */
|
||||
.drbs_to_be_setup = 0, /* no new DRBs */
|
||||
.gNB_CU_ue_id = ue_p->rrc_ue_id,
|
||||
.gNB_DU_ue_id = ue_data.secondary_ue,
|
||||
.plmn.mcc = rrc->configuration.mcc[0],
|
||||
.plmn.mnc = rrc->configuration.mnc[0],
|
||||
.plmn.mnc_digit_length = rrc->configuration.mnc_digit_length[0],
|
||||
.nr_cellid = rrc->nr_cellid,
|
||||
.servCellId = 0, /* TODO: correct value? */
|
||||
.srbs_to_be_setup = 0, /* no new SRBs */
|
||||
.drbs_to_be_setup = 0, /* no new DRBs */
|
||||
.cu_to_du_rrc_information = cu2du_p,
|
||||
};
|
||||
deliver_ue_ctxt_setup_data_t data = {.rrc = rrc, .setup_req = &ue_context_setup_req};
|
||||
nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, rrc_deliver_ue_ctxt_setup_req, &data);
|
||||
|
||||
Reference in New Issue
Block a user