Commit 3982cc2e authored by Robert Schmidt's avatar Robert Schmidt

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
parent 7e2487c2
...@@ -1948,6 +1948,7 @@ void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_alloca ...@@ -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->CellGroup);
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->reconfigCellGroup); 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; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
destroy_nr_list(&sched_ctrl->available_dl_harq); destroy_nr_list(&sched_ctrl->available_dl_harq);
destroy_nr_list(&sched_ctrl->feedback_dl_harq); destroy_nr_list(&sched_ctrl->feedback_dl_harq);
......
...@@ -138,6 +138,42 @@ static int handle_ue_context_drbs_setup(int rnti, ...@@ -138,6 +138,42 @@ static int handle_ue_context_drbs_setup(int rnti,
return drbs_len; 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) static NR_CellGroupConfig_t *clone_CellGroupConfig(const NR_CellGroupConfig_t *orig)
{ {
uint8_t buf[16636]; uint8_t buf[16636];
...@@ -159,9 +195,12 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req) ...@@ -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, .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) { 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->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"); 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) ...@@ -191,7 +230,16 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
if (req->rrc_container != NULL) if (req->rrc_container != NULL)
nr_rlc_srb_recv_sdu(req->gNB_DU_ue_id, DCCH, req->rrc_container, req->rrc_container_length); 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)); 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"); AssertFatal(resp.du_to_cu_rrc_information != NULL, "out of memory\n");
resp.du_to_cu_rrc_information->cellGroupConfig = calloc(1,1024); 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) ...@@ -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, .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) { 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->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"); 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) ...@@ -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"); "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)); 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"); AssertFatal(resp.du_to_cu_rrc_information != NULL, "out of memory\n");
resp.du_to_cu_rrc_information->cellGroupConfig = calloc(1, 1024); resp.du_to_cu_rrc_information->cellGroupConfig = calloc(1, 1024);
......
...@@ -703,6 +703,7 @@ typedef struct { ...@@ -703,6 +703,7 @@ typedef struct {
bool expect_reconfiguration; bool expect_reconfiguration;
NR_CellGroupConfig_t *reconfigCellGroup; NR_CellGroupConfig_t *reconfigCellGroup;
bool apply_cellgroup; bool apply_cellgroup;
NR_UE_NR_Capability_t *capability;
// UE selected beam index // UE selected beam index
uint8_t UE_beam_index; uint8_t UE_beam_index;
bool Msg4_ACKed; bool Msg4_ACKed;
......
...@@ -739,19 +739,7 @@ int16_t do_RRCReconfiguration( ...@@ -739,19 +739,7 @@ int16_t do_RRCReconfiguration(
ie->nonCriticalExtension->dedicatedNAS_MessageList = dedicatedNAS_MessageList; ie->nonCriticalExtension->dedicatedNAS_MessageList = dedicatedNAS_MessageList;
} }
if(cellGroupConfig!=NULL){ 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");
}
enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig,
NULL, NULL,
(void *)cellGroupConfig, (void *)cellGroupConfig,
......
...@@ -64,7 +64,21 @@ static void ue_context_modification_request_f1ap(const f1ap_ue_context_modif_req ...@@ -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); 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_ue_context_modif_req_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_REQ(msg);
*f1ap_msg = *req; *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"); AssertFatal(req->drbs_to_be_modified_length == 0, "drbs_to_be_modified not supported yet\n");
if (req->drbs_to_be_setup_length > 0) { if (req->drbs_to_be_setup_length > 0) {
int n = req->drbs_to_be_setup_length; int n = req->drbs_to_be_setup_length;
......
...@@ -2348,23 +2348,10 @@ void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, ...@@ -2348,23 +2348,10 @@ void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig,
const NR_ServingCellConfigCommon_t *scc) const NR_ServingCellConfigCommon_t *scc)
{ {
DevAssert(cellGroupConfig != NULL); DevAssert(cellGroupConfig != NULL);
/* this is wrong: we should not call this function is spCellConfig is not DevAssert(cellGroupConfig->spCellConfig != NULL);
* allocated */ DevAssert(configuration != NULL);
if (cellGroupConfig->spCellConfig == NULL)
return;
/* same as for spCellConfig */
if (configuration == NULL)
return;
/* if scc is not allocated, there is a serious problem */
DevAssert(scc != 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; NR_SpCellConfig_t *SpCellConfig = cellGroupConfig->spCellConfig;
int curr_bwp = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); int curr_bwp = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "collection/tree.h" #include "collection/tree.h"
#include "collection/linear_alloc.h" #include "collection/linear_alloc.h"
#include "nr_rrc_common.h" #include "nr_rrc_common.h"
#include "ds/byte_array.h"
#include "common/ngran_types.h" #include "common/ngran_types.h"
#include "common/platform_constants.h" #include "common/platform_constants.h"
...@@ -243,7 +244,7 @@ typedef struct gNB_RRC_UE_s { ...@@ -243,7 +244,7 @@ typedef struct gNB_RRC_UE_s {
NR_HANDOVER_INFO *handover_info; NR_HANDOVER_INFO *handover_info;
NR_MeasResults_t *measResults; NR_MeasResults_t *measResults;
byte_array_t ue_cap_buffer;
NR_UE_NR_Capability_t* UE_Capability_nr; NR_UE_NR_Capability_t* UE_Capability_nr;
int UE_Capability_size; int UE_Capability_size;
NR_UE_MRDC_Capability_t* UE_Capability_MRDC; NR_UE_MRDC_Capability_t* UE_Capability_MRDC;
......
...@@ -1460,6 +1460,18 @@ static int handle_ueCapabilityInformation(const protocol_ctxt_t *const ctxt_pP, ...@@ -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) { if (ue_cap_info->criticalExtensions.present == NR_UECapabilityInformation__criticalExtensions_PR_ueCapabilityInformation) {
const NR_UE_CapabilityRAT_ContainerList_t *ue_CapabilityRAT_ContainerList = const NR_UE_CapabilityRAT_ContainerList_t *ue_CapabilityRAT_ContainerList =
ue_cap_info->criticalExtensions.choice.ueCapabilityInformation->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++) { 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]; 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) { if (ue_cap_container->rat_Type == NR_RAT_Type_nr) {
...@@ -2370,6 +2382,14 @@ void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_contex ...@@ -2370,6 +2382,14 @@ void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_contex
srbs[0].lcid = 2; 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); 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 = { f1ap_ue_context_modif_req_t ue_context_modif_req = {
.gNB_CU_ue_id = UE->rrc_ue_id, .gNB_CU_ue_id = UE->rrc_ue_id,
...@@ -2383,6 +2403,7 @@ void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_contex ...@@ -2383,6 +2403,7 @@ void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_contex
.srbs_to_be_setup = srbs, .srbs_to_be_setup = srbs,
.drbs_to_be_setup_length = nb_drb, .drbs_to_be_setup_length = nb_drb,
.drbs_to_be_setup = drbs, .drbs_to_be_setup = drbs,
.cu_to_du_rrc_information = cu2du_p,
}; };
rrc->mac_rrc.ue_context_modification_request(&ue_context_modif_req); rrc->mac_rrc.ue_context_modification_request(&ue_context_modif_req);
} }
...@@ -2727,6 +2748,17 @@ rrc_gNB_generate_SecurityModeCommand( ...@@ -2727,6 +2748,17 @@ rrc_gNB_generate_SecurityModeCommand(
gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id];
AssertFatal(!NODE_IS_DU(rrc->node_type), "illegal node type DU!\n"); 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 */ /* 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); 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 = { f1ap_ue_context_setup_t ue_context_setup_req = {
...@@ -2739,6 +2771,7 @@ rrc_gNB_generate_SecurityModeCommand( ...@@ -2739,6 +2771,7 @@ rrc_gNB_generate_SecurityModeCommand(
.servCellId = 0, /* TODO: correct value? */ .servCellId = 0, /* TODO: correct value? */
.srbs_to_be_setup = 0, /* no new SRBs */ .srbs_to_be_setup = 0, /* no new SRBs */
.drbs_to_be_setup = 0, /* no new DRBs */ .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}; 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); nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, rrc_deliver_ue_ctxt_setup_req, &data);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment