Implementation of dedicated RRC Reconfiguration using internal F1 UE context modification
This commit is contained in:
@@ -84,7 +84,7 @@ int nr_rlc_get_available_tx_space(const rnti_t rntiP, const logical_chan_id_t ch
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP, NR_CellGroupConfig_t *cell_groupConfig_from_DU)
|
||||
void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
@@ -33,25 +33,27 @@ static NR_RLC_BearerConfig_t *get_bearerconfig_from_srb(const f1ap_srb_to_be_set
|
||||
return get_SRB_RLC_BearerConfig(srb->srb_id, priority, bucket);
|
||||
}
|
||||
|
||||
static void handle_ue_context_srbs_setup(const f1ap_ue_context_setup_t *req,
|
||||
f1ap_ue_context_setup_t *resp,
|
||||
NR_CellGroupConfig_t *cellGroupConfig)
|
||||
static int handle_ue_context_srbs_setup(int rnti,
|
||||
int srbs_len,
|
||||
const f1ap_srb_to_be_setup_t *req_srbs,
|
||||
f1ap_srb_to_be_setup_t **resp_srbs,
|
||||
NR_CellGroupConfig_t *cellGroupConfig)
|
||||
{
|
||||
DevAssert(req != NULL && resp != NULL && cellGroupConfig != NULL);
|
||||
DevAssert(req_srbs != NULL && resp_srbs != NULL && cellGroupConfig != NULL);
|
||||
|
||||
resp->srbs_to_be_setup_length = req->srbs_to_be_setup_length;
|
||||
resp->srbs_to_be_setup = calloc(req->srbs_to_be_setup_length, sizeof(*resp->srbs_to_be_setup));
|
||||
AssertFatal(resp->srbs_to_be_setup != NULL, "out of memory\n");
|
||||
for (int i = 0; i < req->srbs_to_be_setup_length; i++) {
|
||||
f1ap_srb_to_be_setup_t *srb = &req->srbs_to_be_setup[i];
|
||||
*resp_srbs = calloc(srbs_len, sizeof(**resp_srbs));
|
||||
AssertFatal(*resp_srbs != NULL, "out of memory\n");
|
||||
for (int i = 0; i < srbs_len; i++) {
|
||||
const f1ap_srb_to_be_setup_t *srb = &req_srbs[i];
|
||||
NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_srb(srb);
|
||||
nr_rlc_add_srb(req->rnti, srb->srb_id, rlc_BearerConfig);
|
||||
nr_rlc_add_srb(rnti, srb->srb_id, rlc_BearerConfig);
|
||||
|
||||
resp->srbs_to_be_setup[i] = *srb;
|
||||
(*resp_srbs)[i] = *srb;
|
||||
|
||||
int ret = ASN_SEQUENCE_ADD(&cellGroupConfig->rlc_BearerToAddModList->list, rlc_BearerConfig);
|
||||
DevAssert(ret == 0);
|
||||
}
|
||||
return srbs_len;
|
||||
}
|
||||
|
||||
static NR_RLC_BearerConfig_t *get_bearerconfig_from_drb(const f1ap_drb_to_be_setup_t *drb)
|
||||
@@ -61,27 +63,31 @@ static NR_RLC_BearerConfig_t *get_bearerconfig_from_drb(const f1ap_drb_to_be_set
|
||||
return get_DRB_RLC_BearerConfig(3 + drb->drb_id, drb->drb_id, rlc_conf, priority);
|
||||
}
|
||||
|
||||
static void handle_ue_context_drbs_setup(const f1ap_ue_context_setup_t *req,
|
||||
f1ap_ue_context_setup_t *resp,
|
||||
NR_CellGroupConfig_t *cellGroupConfig)
|
||||
static int handle_ue_context_drbs_setup(int rnti,
|
||||
int drbs_len,
|
||||
const f1ap_drb_to_be_setup_t *req_drbs,
|
||||
f1ap_drb_to_be_setup_t **resp_drbs,
|
||||
NR_CellGroupConfig_t *cellGroupConfig)
|
||||
{
|
||||
DevAssert(req != NULL && resp != NULL && cellGroupConfig != NULL);
|
||||
DevAssert(req_drbs != NULL && resp_drbs != NULL && cellGroupConfig != NULL);
|
||||
|
||||
/* Note: the actual GTP tunnels are created in the F1AP breanch of
|
||||
* ue_context_*_response() */
|
||||
resp->drbs_to_be_setup_length = req->drbs_to_be_setup_length;
|
||||
resp->drbs_to_be_setup = calloc(req->drbs_to_be_setup_length, sizeof(*resp->drbs_to_be_setup));
|
||||
AssertFatal(resp->drbs_to_be_setup != NULL, "out of memory\n");
|
||||
for (int i = 0; i < req->drbs_to_be_setup_length; i++) {
|
||||
f1ap_drb_to_be_setup_t *drb = &req->drbs_to_be_setup[i];
|
||||
*resp_drbs = calloc(drbs_len, sizeof(**resp_drbs));
|
||||
AssertFatal(*resp_drbs != NULL, "out of memory\n");
|
||||
for (int i = 0; i < drbs_len; i++) {
|
||||
const f1ap_drb_to_be_setup_t *drb = &req_drbs[i];
|
||||
NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_drb(drb);
|
||||
nr_rlc_add_drb(req->rnti, drb->drb_id, rlc_BearerConfig);
|
||||
nr_rlc_add_drb(rnti, drb->drb_id, rlc_BearerConfig);
|
||||
|
||||
resp->drbs_to_be_setup[i] = *drb;
|
||||
(*resp_drbs)[i] = *drb;
|
||||
// just put same number of tunnels in DL as in UL
|
||||
(*resp_drbs)[i].up_dl_tnl_length = drb->up_ul_tnl_length;
|
||||
|
||||
int ret = ASN_SEQUENCE_ADD(&cellGroupConfig->rlc_BearerToAddModList->list, rlc_BearerConfig);
|
||||
DevAssert(ret == 0);
|
||||
}
|
||||
return drbs_len;
|
||||
}
|
||||
|
||||
void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
|
||||
@@ -105,11 +111,20 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
|
||||
NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[0]->UE_info, req->rnti);
|
||||
AssertFatal(UE != NULL, "did not find UE with RNTI %04x, but UE Context Setup Failed not implemented\n", req->rnti);
|
||||
|
||||
if (req->srbs_to_be_setup_length > 0)
|
||||
handle_ue_context_srbs_setup(req, &resp, UE->CellGroup);
|
||||
if (req->srbs_to_be_setup_length > 0) {
|
||||
resp.srbs_to_be_setup_length = handle_ue_context_srbs_setup(req->rnti,
|
||||
req->srbs_to_be_setup_length,
|
||||
req->srbs_to_be_setup,
|
||||
&resp.srbs_to_be_setup,
|
||||
UE->CellGroup);
|
||||
}
|
||||
|
||||
if (req->drbs_to_be_setup_length > 0) {
|
||||
handle_ue_context_drbs_setup(req, &resp, NULL);
|
||||
resp.drbs_to_be_setup_length = handle_ue_context_drbs_setup(req->rnti,
|
||||
req->drbs_to_be_setup_length,
|
||||
req->drbs_to_be_setup,
|
||||
&resp.drbs_to_be_setup,
|
||||
UE->CellGroup);
|
||||
}
|
||||
|
||||
if (req->rrc_container != NULL)
|
||||
@@ -149,8 +164,81 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
|
||||
|
||||
void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
|
||||
{
|
||||
(void)req;
|
||||
AssertFatal(false, "not implemented\n");
|
||||
gNB_MAC_INST *mac = RC.nrmac[0];
|
||||
f1ap_ue_context_modif_resp_t resp = {
|
||||
.gNB_CU_ue_id = req->gNB_CU_ue_id,
|
||||
.gNB_DU_ue_id = req->gNB_DU_ue_id,
|
||||
.rnti = req->rnti,
|
||||
};
|
||||
|
||||
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");
|
||||
AssertFatal(req->cu_to_du_rrc_information->measConfig == NULL, "MeasConfig not handled\n");
|
||||
}
|
||||
|
||||
NR_SCHED_LOCK(&mac->sched_lock);
|
||||
NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[0]->UE_info, req->rnti);
|
||||
|
||||
if (req->srbs_to_be_setup_length > 0) {
|
||||
resp.srbs_to_be_setup_length = handle_ue_context_srbs_setup(req->rnti,
|
||||
req->srbs_to_be_setup_length,
|
||||
req->srbs_to_be_setup,
|
||||
&resp.srbs_to_be_setup,
|
||||
UE->CellGroup);
|
||||
}
|
||||
|
||||
if (req->drbs_to_be_setup_length > 0) {
|
||||
resp.drbs_to_be_setup_length = handle_ue_context_drbs_setup(req->rnti,
|
||||
req->drbs_to_be_setup_length,
|
||||
req->drbs_to_be_setup,
|
||||
&resp.drbs_to_be_setup,
|
||||
UE->CellGroup);
|
||||
}
|
||||
|
||||
if (req->rrc_container != NULL)
|
||||
nr_rlc_srb_recv_sdu(req->rnti, DCCH, req->rrc_container, req->rrc_container_length);
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
if (req->srbs_to_be_setup_length > 0 || req->drbs_to_be_setup_length > 0) {
|
||||
/* TODO: if we change e.g. BWP or MCS table, need to automatically call
|
||||
* configure_UE_BWP() (form nr_mac_update_timers()) after some time? */
|
||||
|
||||
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);
|
||||
AssertFatal(resp.du_to_cu_rrc_information->cellGroupConfig != NULL, "out of memory\n");
|
||||
asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig,
|
||||
NULL,
|
||||
UE->CellGroup,
|
||||
resp.du_to_cu_rrc_information->cellGroupConfig,
|
||||
1024);
|
||||
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;
|
||||
|
||||
/* works? */
|
||||
nr_mac_update_cellgroup(RC.nrmac[0], req->rnti, UE->CellGroup);
|
||||
}
|
||||
NR_SCHED_UNLOCK(&mac->sched_lock);
|
||||
|
||||
/* some sanity checks, since we use the same type for request and response */
|
||||
DevAssert(resp.cu_to_du_rrc_information == NULL);
|
||||
// resp.du_to_cu_rrc_information can be either NULL or not
|
||||
DevAssert(resp.rrc_container == NULL && resp.rrc_container_length == 0);
|
||||
|
||||
mac->mac_rrc.ue_context_modification_response(req, &resp);
|
||||
|
||||
/* free the memory we allocated above */
|
||||
free(resp.srbs_to_be_setup);
|
||||
free(resp.drbs_to_be_setup);
|
||||
if (resp.du_to_cu_rrc_information != NULL) {
|
||||
free(resp.du_to_cu_rrc_information->cellGroupConfig);
|
||||
free(resp.du_to_cu_rrc_information);
|
||||
}
|
||||
}
|
||||
|
||||
void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd)
|
||||
|
||||
@@ -59,8 +59,57 @@ static void ue_context_modification_response_direct(const f1ap_ue_context_modif_
|
||||
const f1ap_ue_context_modif_resp_t *resp)
|
||||
{
|
||||
(void)req; /* we don't need the request -- it is to set up GTP in F1 case */
|
||||
(void)resp;
|
||||
AssertFatal(false, "not implemented yet\n");
|
||||
MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_RESP);
|
||||
f1ap_ue_context_modif_resp_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_RESP(msg);
|
||||
|
||||
f1ap_msg->gNB_CU_ue_id = resp->gNB_CU_ue_id;
|
||||
f1ap_msg->gNB_DU_ue_id = resp->gNB_DU_ue_id;
|
||||
f1ap_msg->rnti = resp->rnti;
|
||||
f1ap_msg->mcc = resp->mcc;
|
||||
f1ap_msg->mnc = resp->mnc;
|
||||
f1ap_msg->mnc_digit_length = resp->mnc_digit_length;
|
||||
f1ap_msg->nr_cellid = resp->nr_cellid;
|
||||
f1ap_msg->servCellIndex = resp->servCellIndex;
|
||||
AssertFatal(resp->cellULConfigured == NULL, "not handled\n");
|
||||
f1ap_msg->servCellId = resp->servCellId;
|
||||
|
||||
DevAssert(resp->cu_to_du_rrc_information == NULL && resp->cu_to_du_rrc_information_length == 0);
|
||||
if (resp->du_to_cu_rrc_information) {
|
||||
f1ap_msg->du_to_cu_rrc_information = malloc(sizeof(*resp->du_to_cu_rrc_information));
|
||||
AssertFatal(f1ap_msg->du_to_cu_rrc_information != NULL, "out of memory\n");
|
||||
f1ap_msg->du_to_cu_rrc_information_length = resp->du_to_cu_rrc_information_length;
|
||||
du_to_cu_rrc_information_t *du2cu = f1ap_msg->du_to_cu_rrc_information;
|
||||
du2cu->cellGroupConfig_length = resp->du_to_cu_rrc_information->cellGroupConfig_length;
|
||||
du2cu->cellGroupConfig = calloc(du2cu->cellGroupConfig_length, sizeof(*du2cu->cellGroupConfig));
|
||||
AssertFatal(du2cu->cellGroupConfig != NULL, "out of memory\n");
|
||||
memcpy(du2cu->cellGroupConfig, resp->du_to_cu_rrc_information->cellGroupConfig, du2cu->cellGroupConfig_length);
|
||||
}
|
||||
|
||||
if (resp->drbs_to_be_setup_length > 0) {
|
||||
DevAssert(resp->drbs_to_be_setup != NULL);
|
||||
f1ap_msg->drbs_to_be_setup_length = resp->drbs_to_be_setup_length;
|
||||
f1ap_msg->drbs_to_be_setup = calloc(f1ap_msg->drbs_to_be_setup_length, sizeof(*f1ap_msg->drbs_to_be_setup));
|
||||
for (int i = 0; i < f1ap_msg->drbs_to_be_setup_length; ++i)
|
||||
f1ap_msg->drbs_to_be_setup[i] = resp->drbs_to_be_setup[i];
|
||||
}
|
||||
|
||||
DevAssert(resp->drbs_to_be_modified == NULL && resp->drbs_to_be_modified_length == 0);
|
||||
f1ap_msg->QoS_information_type = resp->QoS_information_type;
|
||||
AssertFatal(resp->drbs_failed_to_be_setup_length == 0 && resp->drbs_failed_to_be_setup == NULL, "not implemented yet\n");
|
||||
|
||||
if (resp->srbs_to_be_setup_length > 0) {
|
||||
DevAssert(resp->srbs_to_be_setup != NULL);
|
||||
f1ap_msg->srbs_to_be_setup_length = resp->srbs_to_be_setup_length;
|
||||
f1ap_msg->srbs_to_be_setup = calloc(f1ap_msg->srbs_to_be_setup_length, sizeof(*f1ap_msg->srbs_to_be_setup));
|
||||
for (int i = 0; i < f1ap_msg->srbs_to_be_setup_length; ++i)
|
||||
f1ap_msg->srbs_to_be_setup[i] = resp->srbs_to_be_setup[i];
|
||||
}
|
||||
|
||||
AssertFatal(resp->srbs_failed_to_be_setup_length == 0 && resp->srbs_failed_to_be_setup == NULL, "not implemented yet\n");
|
||||
|
||||
DevAssert(resp->rrc_container == NULL && resp->rrc_container_length == 0);
|
||||
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, 0, msg);
|
||||
}
|
||||
|
||||
static void ue_context_release_request_direct(const f1ap_ue_context_release_req_t* req)
|
||||
|
||||
@@ -187,6 +187,19 @@ static void cucp_cuup_bearer_context_setup_direct(e1ap_bearer_setup_req_t *const
|
||||
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, UE->rnti, 0, 0, 0);
|
||||
|
||||
fill_DRB_configList(&ctxt, ue_context_p, xid);
|
||||
e1ap_bearer_setup_resp_t resp = {0};
|
||||
resp.numPDUSessions = req->numPDUSessions;
|
||||
for (int i = 0; i < resp.numPDUSessions; ++i) {
|
||||
resp.pduSession[i].numDRBSetup = req->pduSession[i].numDRB2Setup;
|
||||
for (int j = 0; j < req->pduSession[i].numDRB2Setup; j++) {
|
||||
DRB_nGRAN_to_setup_t *req_drb = req->pduSession[i].DRBnGRanList + j;
|
||||
DRB_nGRAN_setup_t *resp_drb = resp.pduSession[i].DRBnGRanList + j;
|
||||
resp_drb->id = req_drb->id;
|
||||
resp_drb->numQosFlowSetup = req_drb->numQosFlow2Setup;
|
||||
for (int k = 0; k < resp_drb->numQosFlowSetup; k++)
|
||||
resp_drb->qosFlows[k].id = req_drb->qosFlows[k].id;
|
||||
}
|
||||
}
|
||||
|
||||
gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id];
|
||||
// Fixme: xid not random, but almost!
|
||||
@@ -195,21 +208,26 @@ static void cucp_cuup_bearer_context_setup_direct(e1ap_bearer_setup_req_t *const
|
||||
int ret = drb_config_gtpu_create(&ctxt, ue_context_p, req, UE->DRB_configList, *SRB_configList2, rrc->e1_inst);
|
||||
if (ret < 0) AssertFatal(false, "Unable to configure DRB or to create GTP Tunnel\n");
|
||||
|
||||
// Used to store teids: if monolithic, will simply be NULL
|
||||
if(!NODE_IS_CU(RC.nrrrc[ctxt.module_id]->node_type)) {
|
||||
rrc_gNB_generate_dedicatedRRCReconfiguration(&ctxt, ue_context_p, NULL);
|
||||
// intentionally empty
|
||||
} else {
|
||||
e1ap_bearer_setup_resp_t resp; // Used to store teids
|
||||
int remote_port = RC.nrrrc[ctxt.module_id]->eth_params_s.remote_portd;
|
||||
in_addr_t my_addr = inet_addr(RC.nrrrc[ctxt.module_id]->eth_params_s.my_addr);
|
||||
instance_t gtpInst = getCxt(CUtype, instance)->gtpInst;
|
||||
// GTP tunnel for DL
|
||||
fill_e1ap_bearer_setup_resp(&resp, req, gtpInst, UE->rnti, remote_port, my_addr);
|
||||
|
||||
prepare_and_send_ue_context_modification_f1(ue_context_p, &resp);
|
||||
}
|
||||
// actually, we should receive the corresponding context setup response
|
||||
// message at the RRC and always react to this one. So in the following, we
|
||||
// just call the corresponding message handler
|
||||
prepare_and_send_ue_context_modification_f1(ue_context_p, &resp);
|
||||
}
|
||||
|
||||
static void cucp_cuup_bearer_context_mod_direct(e1ap_bearer_setup_req_t *const req, instance_t instance, uint8_t xid) {
|
||||
// only update GTP tunnels if it is really a CU
|
||||
if (!NODE_IS_CU(RC.nrrrc[0]->node_type))
|
||||
return;
|
||||
instance_t gtpInst = getCxt(CUtype, instance)->gtpInst;
|
||||
CU_update_UP_DL_tunnel(req, gtpInst, req->rnti);
|
||||
}
|
||||
|
||||
@@ -142,11 +142,7 @@ rrc_gNB_generate_dedicatedRRCReconfiguration_release(
|
||||
uint32_t nas_length,
|
||||
uint8_t *nas_buffer);
|
||||
|
||||
void
|
||||
rrc_gNB_generate_dedicatedRRCReconfiguration(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rrc_gNB_ue_context_t *ue_context_pP,
|
||||
NR_CellGroupConfig_t *cell_groupConfig_from_DU);
|
||||
void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP);
|
||||
|
||||
void bearer_context_setup_direct(e1ap_bearer_setup_req_t *req,
|
||||
instance_t instance);
|
||||
|
||||
+75
-116
@@ -641,17 +641,10 @@ void fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_contex
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rrc_gNB_generate_dedicatedRRCReconfiguration(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rrc_gNB_ue_context_t *ue_context_pP,
|
||||
NR_CellGroupConfig_t *cell_groupConfig_from_DU
|
||||
)
|
||||
void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP)
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id];
|
||||
long drb_priority[NGAP_MAX_DRBS_PER_UE];
|
||||
NR_CellGroupConfig_t *cellGroupConfig = NULL;
|
||||
int xid = -1;
|
||||
|
||||
int drb_id_to_setup_start = 1;
|
||||
@@ -682,7 +675,6 @@ rrc_gNB_generate_dedicatedRRCReconfiguration(
|
||||
}
|
||||
|
||||
xid = ue_p->pduSession[j].xid;
|
||||
drb_priority[DRB_config->drb_Identity - 1] = 13; // For now, we assume only one drb per pdu sessions with a default preiority (will be dynamique in future)
|
||||
}
|
||||
|
||||
/* If list is empty free the list and reset the address */
|
||||
@@ -691,20 +683,7 @@ rrc_gNB_generate_dedicatedRRCReconfiguration(
|
||||
dedicatedNAS_MessageList = NULL;
|
||||
}
|
||||
|
||||
if(cell_groupConfig_from_DU == NULL){
|
||||
cellGroupConfig = calloc(1, sizeof(NR_CellGroupConfig_t));
|
||||
// FIXME: fill_mastercellGroupConfig() won't fill the right priorities
|
||||
fill_mastercellGroupConfig(cellGroupConfig,
|
||||
ue_p->masterCellGroup,
|
||||
rrc->um_on_default_drb,
|
||||
(drb_id_to_setup_start < 2) ? 1 : 0,
|
||||
DRB_configList,
|
||||
drb_priority);
|
||||
}
|
||||
else{
|
||||
LOG_I(NR_RRC, "Master cell group originating from the DU \n");
|
||||
cellGroupConfig = cell_groupConfig_from_DU;
|
||||
}
|
||||
NR_CellGroupConfig_t *cellGroupConfig = ue_p->masterCellGroup;
|
||||
|
||||
AssertFatal(xid > -1, "Invalid xid %d. No PDU sessions setup to configure.\n", xid);
|
||||
NR_SRB_ToAddModList_t *SRB_configList2 = NULL;
|
||||
@@ -2572,69 +2551,46 @@ static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, i
|
||||
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(rrc, resp->rnti);
|
||||
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
|
||||
|
||||
e1ap_bearer_setup_req_t req = {0};
|
||||
req.numPDUSessionsMod = UE->nb_of_pdusessions;
|
||||
req.gNB_cu_cp_ue_id = UE->gNB_ue_ngap_id;
|
||||
req.rnti = UE->rnti;
|
||||
for (int i=0; i < req.numPDUSessionsMod; i++) {
|
||||
req.pduSessionMod[i].numDRB2Modify = resp->drbs_to_be_setup_length;
|
||||
for (int j=0; j < resp->drbs_to_be_setup_length; j++) {
|
||||
f1ap_drb_to_be_setup_t *drb_f1 = resp->drbs_to_be_setup + j;
|
||||
DRB_nGRAN_to_setup_t *drb_e1 = req.pduSessionMod[i].DRBnGRanModList + j;
|
||||
if (resp->drbs_to_be_setup_length > 0) {
|
||||
e1ap_bearer_setup_req_t req = {0};
|
||||
req.numPDUSessionsMod = UE->nb_of_pdusessions;
|
||||
req.gNB_cu_cp_ue_id = UE->gNB_ue_ngap_id;
|
||||
req.rnti = UE->rnti;
|
||||
for (int i = 0; i < req.numPDUSessionsMod; i++) {
|
||||
req.pduSessionMod[i].numDRB2Modify = resp->drbs_to_be_setup_length;
|
||||
for (int j = 0; j < resp->drbs_to_be_setup_length; j++) {
|
||||
f1ap_drb_to_be_setup_t *drb_f1 = resp->drbs_to_be_setup + j;
|
||||
DRB_nGRAN_to_setup_t *drb_e1 = req.pduSessionMod[i].DRBnGRanModList + j;
|
||||
|
||||
drb_e1->id = drb_f1->drb_id;
|
||||
drb_e1->numDlUpParam = drb_f1->up_dl_tnl_length;
|
||||
drb_e1->DlUpParamList[0].tlAddress = drb_f1->up_dl_tnl[0].tl_address;
|
||||
drb_e1->DlUpParamList[0].teId = drb_f1->up_dl_tnl[0].teid;
|
||||
}
|
||||
}
|
||||
|
||||
// send the F1 response message up to update F1-U tunnel info
|
||||
// it seems the rrc transaction id (xid) is not needed here
|
||||
rrc->cucp_cuup.bearer_context_mod(&req, instance, 0);
|
||||
|
||||
NR_CellGroupConfig_t *cellGroupConfig = NULL;
|
||||
|
||||
if(resp->du_to_cu_rrc_information->cellGroupConfig!=NULL){
|
||||
asn_dec_rval_t dec_rval = uper_decode_complete( NULL,
|
||||
&asn_DEF_NR_CellGroupConfig,
|
||||
(void **)&cellGroupConfig,
|
||||
(uint8_t *)resp->du_to_cu_rrc_information->cellGroupConfig,
|
||||
(int) resp->du_to_cu_rrc_information->cellGroupConfig_length);
|
||||
|
||||
if((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
|
||||
AssertFatal(1==0,"Cell group config decode error\n");
|
||||
// free the memory
|
||||
SEQUENCE_free( &asn_DEF_NR_CellGroupConfig, cellGroupConfig, 1 );
|
||||
return;
|
||||
}
|
||||
//xer_fprint(stdout,&asn_DEF_NR_CellGroupConfig, cellGroupConfig);
|
||||
|
||||
if (UE->masterCellGroup == NULL) {
|
||||
UE->masterCellGroup = calloc(1, sizeof(NR_CellGroupConfig_t));
|
||||
}
|
||||
|
||||
if(cellGroupConfig->rlc_BearerToAddModList!=NULL){
|
||||
if (UE->masterCellGroup->rlc_BearerToAddModList != NULL) {
|
||||
int ue_ctxt_rlc_Bearers = UE->masterCellGroup->rlc_BearerToAddModList->list.count;
|
||||
for(int i=ue_ctxt_rlc_Bearers; i<ue_ctxt_rlc_Bearers + cellGroupConfig->rlc_BearerToAddModList->list.count; i++){
|
||||
asn1cSeqAdd(&UE->masterCellGroup->rlc_BearerToAddModList->list, cellGroupConfig->rlc_BearerToAddModList->list.array[i - ue_ctxt_rlc_Bearers]);
|
||||
}
|
||||
} else {
|
||||
LOG_W(NR_RRC, "Empty rlc_BearerToAddModList at ue_context of the CU before filling the updates from UE context setup response \n");
|
||||
UE->masterCellGroup->rlc_BearerToAddModList = calloc(1, sizeof(*cellGroupConfig->rlc_BearerToAddModList));
|
||||
memcpy(UE->masterCellGroup->rlc_BearerToAddModList, cellGroupConfig->rlc_BearerToAddModList, sizeof(*cellGroupConfig->rlc_BearerToAddModList));
|
||||
drb_e1->id = drb_f1->drb_id;
|
||||
drb_e1->numDlUpParam = drb_f1->up_dl_tnl_length;
|
||||
drb_e1->DlUpParamList[0].tlAddress = drb_f1->up_dl_tnl[0].tl_address;
|
||||
drb_e1->DlUpParamList[0].teId = drb_f1->up_dl_tnl[0].teid;
|
||||
}
|
||||
}
|
||||
LOG_I(NR_RRC, "Updated master cell group configuration stored at the UE context of the CU:\n");
|
||||
if (LOG_DEBUGFLAG(DEBUG_ASN1)) {
|
||||
xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, UE->masterCellGroup);
|
||||
|
||||
// send the F1 response message up to update F1-U tunnel info
|
||||
// it seems the rrc transaction id (xid) is not needed here
|
||||
rrc->cucp_cuup.bearer_context_mod(&req, instance, 0);
|
||||
}
|
||||
|
||||
if (resp->du_to_cu_rrc_information != NULL && resp->du_to_cu_rrc_information->cellGroupConfig != NULL) {
|
||||
LOG_W(RRC, "UE context modification response contains new CellGroupConfig for UE %04x, triggering reconfiguration\n", UE->rnti);
|
||||
NR_CellGroupConfig_t *cellGroupConfig = NULL;
|
||||
asn_dec_rval_t dec_rval = uper_decode_complete(NULL,
|
||||
&asn_DEF_NR_CellGroupConfig,
|
||||
(void **)&cellGroupConfig,
|
||||
(uint8_t *)resp->du_to_cu_rrc_information->cellGroupConfig,
|
||||
resp->du_to_cu_rrc_information->cellGroupConfig_length);
|
||||
AssertFatal(dec_rval.code == RC_OK && dec_rval.consumed > 0, "Cell group config decode error\n");
|
||||
|
||||
if (UE->masterCellGroup) {
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->masterCellGroup);
|
||||
LOG_I(RRC, "UE %04x replacing existing CellGroupConfig with new one received from DU\n", UE->rnti);
|
||||
}
|
||||
UE->masterCellGroup = cellGroupConfig;
|
||||
|
||||
rrc_gNB_generate_dedicatedRRCReconfiguration(&ctxt, ue_context_p, cellGroupConfig);
|
||||
|
||||
free(cellGroupConfig->rlc_BearerToAddModList);
|
||||
free(cellGroupConfig);
|
||||
rrc_gNB_generate_dedicatedRRCReconfiguration(&ctxt, ue_context_p);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2817,46 +2773,49 @@ int rrc_gNB_process_e1_setup_req(e1ap_setup_req_t *req, instance_t instance) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_context_p,
|
||||
e1ap_bearer_setup_resp_t *e1ap_resp) {
|
||||
void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_context_p, e1ap_bearer_setup_resp_t *e1ap_resp)
|
||||
{
|
||||
/* Generate a UE context modification request message towards the DU to
|
||||
* instruct the DU for SRB2 and DRB configuration and get the updates on
|
||||
* master cell group config from the DU*/
|
||||
|
||||
/*Generate a UE context modification request message towards the DU to instruct the DU
|
||||
*for SRB2 and DRB configuration and get the updates on master cell group config from the DU*/
|
||||
gNB_RRC_INST *rrc = RC.nrrrc[0];
|
||||
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
|
||||
|
||||
protocol_ctxt_t ctxt = {0};
|
||||
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, UE->rnti, 0, 0, 0);
|
||||
// TODO: So many hard codings
|
||||
MessageDef *message_p;
|
||||
message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_REQ);
|
||||
f1ap_ue_context_modif_req_t *req = &F1AP_UE_CONTEXT_MODIFICATION_REQ(message_p);
|
||||
req->rnti = UE->rnti;
|
||||
req->mcc = RC.nrrrc[ctxt.module_id]->configuration.mcc[0];
|
||||
req->mnc = RC.nrrrc[ctxt.module_id]->configuration.mnc[0];
|
||||
req->mnc_digit_length = RC.nrrrc[ctxt.module_id]->configuration.mnc_digit_length[0];
|
||||
req->nr_cellid = RC.nrrrc[ctxt.module_id]->nr_cellid;
|
||||
|
||||
/*Instruction towards the DU for SRB2 configuration*/
|
||||
req->srbs_to_be_setup = malloc(1*sizeof(f1ap_srb_to_be_setup_t));
|
||||
req->srbs_to_be_setup_length = 1;
|
||||
f1ap_srb_to_be_setup_t *SRBs=req->srbs_to_be_setup;
|
||||
SRBs[0].srb_id = 2;
|
||||
SRBs[0].lcid = 2;
|
||||
|
||||
/*Instruction towards the DU for DRB configuration and tunnel creation*/
|
||||
req->drbs_to_be_setup_length = e1ap_resp->pduSession[0].numDRBSetup;
|
||||
req->drbs_to_be_setup = malloc(1*sizeof(f1ap_drb_to_be_setup_t)*req->drbs_to_be_setup_length);
|
||||
for (int i=0; i < e1ap_resp->pduSession[0].numDRBSetup; i++) {
|
||||
f1ap_drb_to_be_setup_t *DRBs = req->drbs_to_be_setup + i;
|
||||
DRBs[i].drb_id = e1ap_resp->pduSession[0].DRBnGRanList[i].id;
|
||||
DRBs[i].rlc_mode = RLC_MODE_AM;
|
||||
DRBs[i].up_ul_tnl[0].tl_address = e1ap_resp->pduSession[0].DRBnGRanList[i].UpParamList[0].tlAddress;
|
||||
DRBs[i].up_ul_tnl[0].port = RC.nrrrc[ctxt.module_id]->eth_params_s.my_portd;
|
||||
DRBs[i].up_ul_tnl[0].teid = e1ap_resp->pduSession[0].DRBnGRanList[i].UpParamList[0].teId;
|
||||
DRBs[i].up_ul_tnl_length = 1;
|
||||
/* Instruction towards the DU for DRB configuration and tunnel creation */
|
||||
int nb_drb = e1ap_resp->pduSession[0].numDRBSetup;
|
||||
f1ap_drb_to_be_setup_t drbs[nb_drb];
|
||||
for (int i = 0; i < nb_drb; i++) {
|
||||
drbs[i].drb_id = e1ap_resp->pduSession[0].DRBnGRanList[i].id;
|
||||
drbs[i].rlc_mode = rrc->um_on_default_drb ? RLC_MODE_UM : RLC_MODE_AM;
|
||||
drbs[i].up_ul_tnl[0].tl_address = e1ap_resp->pduSession[0].DRBnGRanList[i].UpParamList[0].tlAddress;
|
||||
drbs[i].up_ul_tnl[0].port = rrc->eth_params_s.my_portd;
|
||||
drbs[i].up_ul_tnl[0].teid = e1ap_resp->pduSession[0].DRBnGRanList[i].UpParamList[0].teId;
|
||||
drbs[i].up_ul_tnl_length = 1;
|
||||
}
|
||||
|
||||
itti_send_msg_to_task (TASK_CU_F1, ctxt.module_id, message_p);
|
||||
/* Instruction towards the DU for SRB2 configuration */
|
||||
int nb_srb = 1;
|
||||
f1ap_srb_to_be_setup_t srbs[nb_srb];
|
||||
srbs[0].srb_id = 2;
|
||||
srbs[0].lcid = 2;
|
||||
srbs[0].rlc_mode = RLC_MODE_AM;
|
||||
|
||||
f1ap_ue_context_modif_req_t ue_context_modif_req = {
|
||||
.gNB_CU_ue_id = 0xffffffff, /* filled by F1 for the moment */
|
||||
.gNB_DU_ue_id = 0xffffffff, /* filled by F1 for the moment */
|
||||
.rnti = UE->rnti,
|
||||
.mcc = rrc->configuration.mcc[0],
|
||||
.mnc = rrc->configuration.mnc[0],
|
||||
.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,
|
||||
};
|
||||
rrc->mac_rrc.ue_context_modification_request(&ue_context_modif_req);
|
||||
}
|
||||
|
||||
void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp, instance_t instance) {
|
||||
|
||||
Reference in New Issue
Block a user