From 3982cc2e2393446f654b8ece9dc9fceeb2b8ba1d Mon Sep 17 00:00:00 2001 From: Robert Schmidt <robert.schmidt@openairinterface.org> Date: Fri, 18 Aug 2023 09:33:05 +0200 Subject: [PATCH] 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 --- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 1 + .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 68 ++++++++++++++++- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 1 + openair2/RRC/NR/MESSAGES/asn1_msg.c | 14 +--- openair2/RRC/NR/mac_rrc_dl_f1ap.c | 16 +++- openair2/RRC/NR/nr_rrc_config.c | 17 +---- openair2/RRC/NR/nr_rrc_defs.h | 3 +- openair2/RRC/NR/rrc_gNB.c | 73 ++++++++++++++----- 8 files changed, 139 insertions(+), 54 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 07c8da30928..ec6d24a0bd3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -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); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 71d2ecc36ab..0e383e4eaf6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -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); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index d7c38f31792..eacb8c84dd7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -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; diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index ee3ddd08eea..6cd4fc3500c 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -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, diff --git a/openair2/RRC/NR/mac_rrc_dl_f1ap.c b/openair2/RRC/NR/mac_rrc_dl_f1ap.c index 270541a4b9c..88c5ad125e1 100644 --- a/openair2/RRC/NR/mac_rrc_dl_f1ap.c +++ b/openair2/RRC/NR/mac_rrc_dl_f1ap.c @@ -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; diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index d1c55d17cfb..5eaaf7eeac8 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -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); diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 29ad2ccd356..465f968a4d1 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -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; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 1b00e380a28..86d50a4bb02 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -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); -- GitLab