nr: improve x2/rrc for ENDC
This commit introduces several enhancements in X2AP and RRC to deal
with ENDC. The main goal is to deal with UE's on/off and with various
errors.
The following work is included:
- DC prep and DC overall X2 timers
- X2 messages for UE release and DC timers' timeout
Open problems:
- what to do when the UE sends an scg Failure? This commit removes
the UE. And this removal may not be correctly done
- UE removal in the gNB's PHY layer (a next commit is coming,
but it is hackish and will need a rework)
This commit is contained in:
@@ -271,7 +271,8 @@ typedef enum UE_STATE_e {
|
||||
RRC_RECONFIGURED,
|
||||
RRC_HO_EXECUTION,
|
||||
RRC_NR_NSA,
|
||||
RRC_NR_NSA_RECONFIGURED
|
||||
RRC_NR_NSA_RECONFIGURED,
|
||||
RRC_NR_NSA_DELETED
|
||||
} UE_STATE_t;
|
||||
|
||||
typedef enum HO_STATE_e {
|
||||
@@ -591,6 +592,8 @@ typedef struct eNB_RRC_UE_s {
|
||||
|
||||
uint8_t Status; // RRC status, type enum UE_STATE_t
|
||||
rnti_t rnti;
|
||||
int gnb_rnti; //RNTI of the UE at the gNB if in ENDC connection
|
||||
int gnb_x2_assoc_id;
|
||||
uint64_t random_ue_identity;
|
||||
|
||||
|
||||
|
||||
@@ -4648,6 +4648,8 @@ rrc_eNB_process_MeasurementReport(
|
||||
if ((ue_context_pP->ue_context.Status != RRC_NR_NSA) && (ue_context_pP->ue_context.Status != RRC_NR_NSA_RECONFIGURED)) {
|
||||
MessageDef *msg;
|
||||
ue_context_pP->ue_context.Status = RRC_NR_NSA;
|
||||
ue_context_pP->ue_context.gnb_rnti = -1; // set when receiving X2AP_ENDC_SGNB_ADDITION_REQ_ACK
|
||||
ue_context_pP->ue_context.gnb_x2_assoc_id = -1; // set when receiving X2AP_ENDC_SGNB_ADDITION_REQ_ACK
|
||||
|
||||
if(is_en_dc_supported(ue_context_pP->ue_context.UE_Capability)) {
|
||||
/** to add gNB as Secondary node CG-ConfigInfo to be added as per 36.423 r15 **/
|
||||
@@ -5006,6 +5008,7 @@ void rrc_eNB_handover_ue_context_release(
|
||||
msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_ENB, GTPV1U_ENB_DELETE_TUNNEL_REQ);
|
||||
memset(>PV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p), 0, sizeof(GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p)));
|
||||
GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).rnti = ue_context_p->ue_context.rnti;
|
||||
GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).from_gnb = 0;
|
||||
|
||||
for (e_rab = 0; e_rab < ue_context_p->ue_context.nb_of_e_rabs; e_rab++) {
|
||||
GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).eps_bearer_id[GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).num_erab++] =
|
||||
@@ -6948,6 +6951,32 @@ rrc_eNB_generate_RRCConnectionSetup(
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void rrc_eNB_process_reconfiguration_complete_endc(const protocol_ctxt_t *const ctxt_pP,
|
||||
rrc_eNB_ue_context_t *const ue_context_p)
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
MessageDef *msg_p;
|
||||
|
||||
msg_p = itti_alloc_new_message (TASK_RRC_ENB, X2AP_ENDC_SGNB_RECONF_COMPLETE);
|
||||
|
||||
/* MeNB_ue_x2_id is unknown, set to 0.
|
||||
* This is not correct but X2 id in the eNB is only 12 bits,
|
||||
* so unfortunately we can't use rnti.
|
||||
* To be corrected if needed.
|
||||
* As of today, when stopping t_dc_prep we remove the UE
|
||||
* from X2. To keep the id until the 'reconfiguration complete' message is received
|
||||
* needs a rethink/rewrite of this logic. For simplicity, let's
|
||||
* keep it as is. The only problem we can get is if/when we
|
||||
* interoperate with a non-OAI gNB. The OAI gNB does not
|
||||
* care about MeNB_ue_x2_id.
|
||||
*/
|
||||
X2AP_ENDC_SGNB_RECONF_COMPLETE(msg_p).MeNB_ue_x2_id = 0;
|
||||
X2AP_ENDC_SGNB_RECONF_COMPLETE(msg_p).SgNB_ue_x2_id = ue_context_p->ue_context.gnb_rnti;
|
||||
X2AP_ENDC_SGNB_RECONF_COMPLETE(msg_p).gnb_x2_assoc_id = ue_context_p->ue_context.gnb_x2_assoc_id;
|
||||
itti_send_msg_to_task (TASK_X2AP, ctxt_pP->instance, msg_p);
|
||||
}
|
||||
|
||||
void setup_ngran_CU(eNB_RRC_INST *rrc) {
|
||||
}
|
||||
|
||||
@@ -7849,6 +7878,8 @@ rrc_eNB_decode_dcch(
|
||||
ue_context_p->ue_context.Status = RRC_NR_NSA_RECONFIGURED;
|
||||
/*Trigger E-RAB Modification Indication */
|
||||
rrc_eNB_send_E_RAB_Modification_Indication(ctxt_pP, ue_context_p);
|
||||
/* send reconfiguration complete to gNB */
|
||||
rrc_eNB_process_reconfiguration_complete_endc(ctxt_pP, ue_context_p);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7909,6 +7940,7 @@ rrc_eNB_decode_dcch(
|
||||
msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_ENB, GTPV1U_ENB_DELETE_TUNNEL_REQ);
|
||||
memset(>PV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p), 0, sizeof(GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p)));
|
||||
GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).rnti = ue_context_p->ue_context.rnti;
|
||||
GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).from_gnb = 0;
|
||||
|
||||
for(i = 0; i < NB_RB_MAX; i++) {
|
||||
if(xid == ue_context_p->ue_context.e_rab[i].xid) {
|
||||
@@ -8439,6 +8471,17 @@ rrc_eNB_decode_dcch(
|
||||
ul_dcch_msg->message.choice.messageClassExtension.choice.c2.choice.scgFailureInformationNR_r15.criticalExtensions.
|
||||
choice.c1.choice.scgFailureInformationNR_r15.failureReportSCG_NR_r15->failureType_r15);
|
||||
xer_fprint(stdout, &asn_DEF_LTE_UL_DCCH_Message, (void *)ul_dcch_msg);
|
||||
|
||||
/* TODO: scg failure indication, what to do? Let's remove the UE for now.
|
||||
* We could re-establish DRB?
|
||||
* Also, the way to remove is to start ue_release_timer_rrc and
|
||||
* send RRCConnectionRelease to the UE, maybe it's not good/correct.
|
||||
*/
|
||||
if (ue_context_p != NULL) {
|
||||
ue_context_p->ue_context.ue_release_timer_thres_rrc = 100;
|
||||
ue_context_p->ue_context.ue_release_timer_rrc = 1;
|
||||
rrc_eNB_generate_RRCConnectionRelease(ctxt_pP, ue_context_p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8989,6 +9032,19 @@ void rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) {
|
||||
ue_to_be_removed[cur_ue]->ue_context.ue_reestablishment_timer = 0;
|
||||
}
|
||||
|
||||
/* remove UE from gNB if UE is in NSA mode */
|
||||
if (ue_to_be_removed[cur_ue]->ue_context.Status == RRC_NR_NSA ||
|
||||
ue_to_be_removed[cur_ue]->ue_context.Status == RRC_NR_NSA_RECONFIGURED) {
|
||||
MessageDef *message_p;
|
||||
message_p = itti_alloc_new_message(TASK_RRC_ENB, X2AP_ENDC_SGNB_RELEASE_REQUEST);
|
||||
X2AP_ENDC_SGNB_RELEASE_REQUEST(message_p).rnti = ue_to_be_removed[cur_ue]->ue_context.gnb_rnti;
|
||||
X2AP_ENDC_SGNB_RELEASE_REQUEST(message_p).assoc_id = ue_to_be_removed[cur_ue]->ue_context.gnb_x2_assoc_id;
|
||||
X2AP_ENDC_SGNB_RELEASE_REQUEST(message_p).cause = X2AP_CAUSE_RADIO_CONNECTION_WITH_UE_LOST;
|
||||
itti_send_msg_to_task(TASK_X2AP, ctxt_pP->module_id, message_p);
|
||||
/* set state to RRC_NR_NSA_DELETED to avoid sending X2AP_ENDC_SGNB_RELEASE_REQUEST again later */
|
||||
ue_to_be_removed[cur_ue]->ue_context.Status = RRC_NR_NSA_DELETED;
|
||||
}
|
||||
|
||||
rrc_eNB_free_UE(ctxt_pP->module_id, ue_to_be_removed[cur_ue]);
|
||||
|
||||
if (ue_to_be_removed[cur_ue]->ue_context.ul_failure_timer >= 20000) {
|
||||
@@ -9106,6 +9162,10 @@ void rrc_eNB_process_AdditionResponseInformation(const module_id_t enb_mod_idP,
|
||||
|
||||
if (ue_context) {
|
||||
ue_context->ue_context.nb_of_modify_endc_e_rabs = m->nb_e_rabs_admitted_tobeadded;
|
||||
|
||||
ue_context->ue_context.gnb_rnti = m->SgNB_ue_x2_id;
|
||||
ue_context->ue_context.gnb_x2_assoc_id = m->gnb_x2_assoc_id;
|
||||
|
||||
int j=0;
|
||||
|
||||
while(j < m->nb_e_rabs_admitted_tobeadded) {
|
||||
@@ -9143,6 +9203,54 @@ void rrc_eNB_process_AdditionResponseInformation(const module_id_t enb_mod_idP,
|
||||
}
|
||||
}
|
||||
|
||||
void rrc_eNB_process_ENDC_DC_prep_timeout(module_id_t module_id, x2ap_ENDC_dc_prep_timeout_t *m)
|
||||
{
|
||||
rrc_eNB_ue_context_t *ue_context;
|
||||
|
||||
ue_context = rrc_eNB_get_ue_context(RC.rrc[module_id], m->rnti);
|
||||
if (ue_context == NULL) {
|
||||
LOG_E(RRC, "receiving DC prep timeout for unknown UE rnti %d\n", m->rnti);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ue_context->ue_context.Status != RRC_NR_NSA) {
|
||||
LOG_E(RRC, "receiving DC prep timeout for UE rnti %d not in state RRC_NR_NSA\n", m->rnti);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_I(RRC, "DC prep timeout for UE rnti %d, put back to RRC_RECONFIGURED mode\n", m->rnti);
|
||||
ue_context->ue_context.Status = RRC_RECONFIGURED;
|
||||
}
|
||||
|
||||
void rrc_eNB_process_ENDC_sgNB_release_required(module_id_t module_id, x2ap_ENDC_sgnb_release_required_t *m)
|
||||
{
|
||||
rrc_eNB_ue_context_t *ue_context;
|
||||
protocol_ctxt_t ctxt;
|
||||
|
||||
ue_context = rrc_eNB_find_ue_context_from_gnb_rnti(RC.rrc[module_id], m->gnb_rnti);
|
||||
if (ue_context == NULL) {
|
||||
LOG_E(RRC, "receiving ENDC SgNB Release Required for unknown UE (with gNB's rnti %d)\n", m->gnb_rnti);
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO: what to do? release the UE? if yes, how? Or re-establish bearers in LTE?
|
||||
* Or something else?
|
||||
* The following removes the UE, maybe it's not correct at all.
|
||||
*/
|
||||
ue_context->ue_context.ue_release_timer_thres_rrc = 100;
|
||||
ue_context->ue_context.ue_release_timer_rrc = 1;
|
||||
|
||||
ue_context->ue_context.Status = RRC_NR_NSA_DELETED;
|
||||
|
||||
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt,
|
||||
module_id, /* TODO: should be 'instance' */
|
||||
ENB_FLAG_YES,
|
||||
ue_context->ue_context.rnti,
|
||||
0, 0);
|
||||
|
||||
rrc_eNB_generate_RRCConnectionRelease(&ctxt, ue_context);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void *rrc_enb_process_itti_msg(void *notUsed) {
|
||||
MessageDef *msg_p;
|
||||
@@ -9426,6 +9534,16 @@ void *rrc_enb_process_itti_msg(void *notUsed) {
|
||||
break;
|
||||
}
|
||||
|
||||
case X2AP_ENDC_DC_PREP_TIMEOUT: {
|
||||
rrc_eNB_process_ENDC_DC_prep_timeout(ENB_INSTANCE_TO_MODULE_ID(instance), &X2AP_ENDC_DC_PREP_TIMEOUT(msg_p));
|
||||
break;
|
||||
}
|
||||
|
||||
case X2AP_ENDC_SGNB_RELEASE_REQUIRED: {
|
||||
rrc_eNB_process_ENDC_sgNB_release_required(ENB_INSTANCE_TO_MODULE_ID(instance), &X2AP_ENDC_SGNB_RELEASE_REQUIRED(msg_p));
|
||||
break;
|
||||
}
|
||||
|
||||
/* Messages from eNB app */
|
||||
case RRC_CONFIGURATION_REQ:
|
||||
LOG_I(RRC, "[eNB %d] Received %s : %p\n", instance, msg_name_p, &RRC_CONFIGURATION_REQ(msg_p));
|
||||
|
||||
@@ -189,6 +189,7 @@ void rrc_eNB_send_GTPV1U_ENB_DELETE_TUNNEL_REQ(
|
||||
MessageDef *msg = itti_alloc_new_message(TASK_RRC_ENB, GTPV1U_ENB_DELETE_TUNNEL_REQ);
|
||||
memset(>PV1U_ENB_DELETE_TUNNEL_REQ(msg), 0, sizeof(GTPV1U_ENB_DELETE_TUNNEL_REQ(msg)));
|
||||
GTPV1U_ENB_DELETE_TUNNEL_REQ(msg).rnti = ue_context_pP->ue_context.rnti;
|
||||
GTPV1U_ENB_DELETE_TUNNEL_REQ(msg).from_gnb = 0;
|
||||
GTPV1U_ENB_DELETE_TUNNEL_REQ(msg).num_erab = ue_context_pP->ue_context.nb_of_e_rabs;
|
||||
for (int e_rab = 0; e_rab < ue_context_pP->ue_context.nb_of_e_rabs; e_rab++) {
|
||||
const rb_id_t gtp_ebi = ue_context_pP->ue_context.enb_gtp_ebi[e_rab];
|
||||
|
||||
@@ -1751,6 +1751,7 @@ int rrc_eNB_process_S1AP_E_RAB_RELEASE_COMMAND(MessageDef *msg_p, const char *ms
|
||||
msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_ENB, GTPV1U_ENB_DELETE_TUNNEL_REQ);
|
||||
memset(>PV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p), 0, sizeof(GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p)));
|
||||
GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).rnti = ue_context_p->ue_context.rnti;
|
||||
GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).from_gnb = 0;
|
||||
|
||||
for(i = 0; i < NB_RB_MAX; i++) {
|
||||
if(xid == ue_context_p->ue_context.e_rab[i].xid) {
|
||||
|
||||
@@ -173,6 +173,23 @@ rrc_eNB_get_ue_context(
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
struct rrc_eNB_ue_context_s *
|
||||
rrc_eNB_find_ue_context_from_gnb_rnti(
|
||||
eNB_RRC_INST *rrc_instance_pP,
|
||||
int gnb_rnti)
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
struct rrc_eNB_ue_context_s *ue_context_p = NULL;
|
||||
RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(rrc_instance_pP->rrc_ue_head)) {
|
||||
if (ue_context_p->ue_context.gnb_rnti == gnb_rnti) {
|
||||
return ue_context_p;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void rrc_eNB_remove_ue_context(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
|
||||
@@ -73,6 +73,11 @@ rrc_eNB_get_ue_context(
|
||||
rnti_t rntiP
|
||||
);
|
||||
|
||||
struct rrc_eNB_ue_context_s *
|
||||
rrc_eNB_find_ue_context_from_gnb_rnti(
|
||||
eNB_RRC_INST *rrc_instance_pP,
|
||||
int gnb_rnti);
|
||||
|
||||
void rrc_eNB_remove_ue_context(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
eNB_RRC_INST* rrc_instance_pP,
|
||||
|
||||
@@ -69,6 +69,8 @@ void rrc_parse_ue_capabilities(gNB_RRC_INST *rrc,LTE_UE_CapabilityRAT_ContainerL
|
||||
|
||||
void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_p, x2ap_ENDC_sgnb_addition_req_t *m);
|
||||
|
||||
void rrc_remove_nsa_user(gNB_RRC_INST *rrc, int rnti);
|
||||
|
||||
void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellconfigcommon,
|
||||
NR_CellGroupConfig_t *secondaryCellGroup,
|
||||
int scg_id,
|
||||
@@ -97,3 +99,5 @@ int parse_CG_ConfigInfo(gNB_RRC_INST *rrc, NR_CG_ConfigInfo_t *CG_ConfigInfo, x2
|
||||
\param void *args_p Pointer on arguments to start the task. */
|
||||
void *rrc_gnb_task(void *args_p);
|
||||
|
||||
/* Trigger RRC periodic processing. To be called once per ms. */
|
||||
void nr_rrc_trigger(protocol_ctxt_t *ctxt, int CC_id, int frame, int subframe);
|
||||
|
||||
@@ -301,6 +301,26 @@ void rrc_gNB_process_AdditionRequestInformation(const module_id_t gnb_mod_idP, x
|
||||
parse_CG_ConfigInfo(rrc,cg_configinfo,m);
|
||||
}
|
||||
|
||||
void rrc_gNB_process_release_request(const module_id_t gnb_mod_idP, x2ap_ENDC_sgnb_release_request_t *m)
|
||||
{
|
||||
gNB_RRC_INST *rrc = RC.nrrrc[gnb_mod_idP];
|
||||
rrc_remove_nsa_user(rrc, m->rnti);
|
||||
}
|
||||
|
||||
void rrc_gNB_process_dc_overall_timeout(const module_id_t gnb_mod_idP, x2ap_ENDC_dc_overall_timeout_t *m)
|
||||
{
|
||||
gNB_RRC_INST *rrc = RC.nrrrc[gnb_mod_idP];
|
||||
rrc_remove_nsa_user(rrc, m->rnti);
|
||||
}
|
||||
|
||||
void nr_rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) {
|
||||
MessageDef *msg;
|
||||
|
||||
/* send a tick to x2ap */
|
||||
msg = itti_alloc_new_message(TASK_RRC_ENB, X2AP_SUBFRAME_PROCESS);
|
||||
itti_send_msg_to_task(TASK_X2AP, ctxt_pP->module_id, msg);
|
||||
}
|
||||
|
||||
///---------------------------------------------------------------------------------------------------------------///
|
||||
///---------------------------------------------------------------------------------------------------------------///
|
||||
void *rrc_gnb_task(void *args_p) {
|
||||
@@ -319,7 +339,10 @@ void *rrc_gnb_task(void *args_p) {
|
||||
itti_receive_msg(TASK_RRC_GNB, &msg_p);
|
||||
msg_name_p = ITTI_MSG_NAME(msg_p);
|
||||
instance = ITTI_MSG_INSTANCE(msg_p);
|
||||
LOG_I(NR_RRC,"Received message %s\n",msg_name_p);
|
||||
|
||||
/* RRC_SUBFRAME_PROCESS is sent every subframe, do not log it */
|
||||
if (ITTI_MSG_ID(msg_p) != RRC_SUBFRAME_PROCESS)
|
||||
LOG_I(NR_RRC,"Received message %s\n",msg_name_p);
|
||||
|
||||
switch (ITTI_MSG_ID(msg_p)) {
|
||||
case TERMINATE_MESSAGE:
|
||||
@@ -333,6 +356,10 @@ void *rrc_gnb_task(void *args_p) {
|
||||
|
||||
/* Messages from MAC */
|
||||
|
||||
case RRC_SUBFRAME_PROCESS:
|
||||
nr_rrc_subframe_process(&RRC_SUBFRAME_PROCESS(msg_p).ctxt, RRC_SUBFRAME_PROCESS(msg_p).CC_id);
|
||||
break;
|
||||
|
||||
/* Messages from PDCP */
|
||||
|
||||
/*
|
||||
@@ -406,6 +433,20 @@ void *rrc_gnb_task(void *args_p) {
|
||||
LOG_I(NR_RRC, "Handling of reconfiguration complete message at RRC gNB is pending \n");
|
||||
break;
|
||||
|
||||
case X2AP_ENDC_SGNB_RELEASE_REQUEST:
|
||||
LOG_I(NR_RRC, "Received ENDC sgNB release request from X2AP \n");
|
||||
rrc_gNB_process_release_request(GNB_INSTANCE_TO_MODULE_ID(instance), &X2AP_ENDC_SGNB_RELEASE_REQUEST(msg_p));
|
||||
break;
|
||||
|
||||
case X2AP_ENDC_DC_OVERALL_TIMEOUT:
|
||||
rrc_gNB_process_dc_overall_timeout(GNB_INSTANCE_TO_MODULE_ID(instance), &X2AP_ENDC_DC_OVERALL_TIMEOUT(msg_p));
|
||||
break;
|
||||
|
||||
/* Messages from GTP */
|
||||
case GTPV1U_ENB_DELETE_TUNNEL_RESP:
|
||||
/* nothing to do? */
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_E(NR_RRC, "[gNB %d] Received unexpected message %s\n", instance, msg_name_p);
|
||||
break;
|
||||
@@ -417,3 +458,11 @@ void *rrc_gnb_task(void *args_p) {
|
||||
}
|
||||
}
|
||||
|
||||
void nr_rrc_trigger(protocol_ctxt_t *ctxt, int CC_id, int frame, int subframe)
|
||||
{
|
||||
MessageDef *message_p;
|
||||
message_p = itti_alloc_new_message(TASK_RRC_GNB, RRC_SUBFRAME_PROCESS);
|
||||
RRC_SUBFRAME_PROCESS(message_p).ctxt = *ctxt;
|
||||
RRC_SUBFRAME_PROCESS(message_p).CC_id = CC_id;
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, ctxt->module_id, message_p);
|
||||
}
|
||||
|
||||
@@ -27,8 +27,6 @@
|
||||
* \company Eurecom
|
||||
* \email: raymond.knopp@eurecom.fr
|
||||
*/
|
||||
#ifndef RRC_GNB_NSA_C
|
||||
#define RRC_GNB_NSA_C
|
||||
|
||||
#include "nr_rrc_defs.h"
|
||||
#include "NR_RRCReconfiguration.h"
|
||||
@@ -247,15 +245,21 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_
|
||||
LOG_W(RRC, "No E-RAB to be added received from SgNB Addition Request message \n");
|
||||
}
|
||||
|
||||
//X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer_size = CG_Config_size; //Need to verify correct value for the buffer_size
|
||||
// Send to X2 entity to transport to MeNB
|
||||
asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CG_Config,
|
||||
NULL,
|
||||
(void *)CG_Config,
|
||||
X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer,
|
||||
1024);
|
||||
X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer_size = (enc_rval.encoded+7)>>3;
|
||||
itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(0), msg); //Check right id instead of hardcoding
|
||||
if (m != NULL) {
|
||||
X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).MeNB_ue_x2_id = m->ue_x2_id;
|
||||
X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).SgNB_ue_x2_id = ue_context_p->ue_context.secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity;
|
||||
|
||||
//X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer_size = CG_Config_size; //Need to verify correct value for the buffer_size
|
||||
// Send to X2 entity to transport to MeNB
|
||||
asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CG_Config,
|
||||
NULL,
|
||||
(void *)CG_Config,
|
||||
X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer,
|
||||
1024);
|
||||
X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer_size = (enc_rval.encoded+7)>>3;
|
||||
itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(0), msg); //Check right id instead of hardcoding
|
||||
}
|
||||
|
||||
rrc->Nb_ue++;
|
||||
// configure MAC and RLC
|
||||
rrc_mac_config_req_gNB(rrc->module_id,
|
||||
@@ -290,5 +294,45 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_
|
||||
|
||||
}
|
||||
|
||||
void rrc_remove_nsa_user(gNB_RRC_INST *rrc, int rnti) {
|
||||
protocol_ctxt_t ctxt;
|
||||
rrc_gNB_ue_context_t *ue_context;
|
||||
MessageDef *msg_delete_tunnels_p;
|
||||
int e_rab;
|
||||
|
||||
#endif
|
||||
LOG_D(RRC, "calling rrc_remove_nsa_user rnti %d\n", rnti);
|
||||
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, rrc->module_id, GNB_FLAG_YES, rnti, 0, 0, rrc->module_id);
|
||||
|
||||
ue_context = rrc_gNB_get_ue_context(rrc, rnti);
|
||||
if (ue_context == NULL) {
|
||||
LOG_W(RRC, "rrc_remove_nsa_user: rnti %d not found\n", rnti);
|
||||
return;
|
||||
}
|
||||
|
||||
pdcp_remove_UE(&ctxt);
|
||||
|
||||
rrc_rlc_remove_ue(&ctxt);
|
||||
|
||||
mac_remove_nr_ue(rrc->module_id, rnti);
|
||||
|
||||
/* delete gtp tunnel */
|
||||
msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_GNB, GTPV1U_ENB_DELETE_TUNNEL_REQ);
|
||||
memset(>PV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p), 0, sizeof(GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p)));
|
||||
GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).rnti = rnti;
|
||||
GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).from_gnb = 1;
|
||||
|
||||
LOG_D(RRC, "ue_context->ue_context.nb_of_e_rabs %d\n", ue_context->ue_context.nb_of_e_rabs);
|
||||
for (e_rab = 0; e_rab < ue_context->ue_context.nb_of_e_rabs; e_rab++) {
|
||||
GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).eps_bearer_id[GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).num_erab++] =
|
||||
ue_context->ue_context.gnb_gtp_ebi[e_rab];
|
||||
// erase data
|
||||
ue_context->ue_context.gnb_gtp_teid[e_rab] = 0;
|
||||
memset(&ue_context->ue_context.gnb_gtp_addrs[e_rab], 0, sizeof(ue_context->ue_context.gnb_gtp_addrs[e_rab]));
|
||||
ue_context->ue_context.gnb_gtp_ebi[e_rab] = 0;
|
||||
}
|
||||
|
||||
itti_send_msg_to_task(TASK_GTPV1_U, rrc->module_id, msg_delete_tunnels_p);
|
||||
|
||||
/* remove context */
|
||||
rrc_gNB_remove_ue_context(&ctxt, rrc, ue_context);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user