trigger NR activation based on RRC measurements
An NR-capable UE will transmit some NR measurements. Once received, the whole process on nr-cell addition is started. It will fail quickly. Many things are still missing. What is not handled properly with this commit: - in x2ap_eNB_handle_sgNB_add_req we hardcode the gNB ID - nr triggering is done if we receive a measurement but this measurement is not analyzed at all - no timers (T_dc_overall, T_dc_prep) and as is the code fails and then the next triggering after UE reconnection will not work (x2 ID are not well handled here and there in the code) Note also that the gNB part has not been looked at all for this commit. This is work in progress...
This commit is contained in:
@@ -357,7 +357,7 @@ typedef struct x2ap_ENDC_sgnb_addition_req_ACK_s {
|
||||
|
||||
int SgNB_ue_x2_id;
|
||||
|
||||
/* used for RRC->X2AP in source eNB */
|
||||
/* used for X2AP->RRC in source eNB */
|
||||
int rnti;
|
||||
|
||||
uint8_t nb_e_rabs_admitted_tobeadded;
|
||||
|
||||
@@ -265,7 +265,8 @@ typedef enum UE_STATE_e {
|
||||
RRC_SI_RECEIVED,
|
||||
RRC_CONNECTED,
|
||||
RRC_RECONFIGURED,
|
||||
RRC_HO_EXECUTION
|
||||
RRC_HO_EXECUTION,
|
||||
RRC_NR_NSA,
|
||||
} UE_STATE_t;
|
||||
|
||||
typedef enum HO_STATE_e {
|
||||
|
||||
@@ -4297,6 +4297,10 @@ rrc_eNB_process_MeasurementReport(
|
||||
ctxt_pP->subframe);
|
||||
break;
|
||||
|
||||
case 7:
|
||||
LOG_D(RRC, "NR event frame %d subframe %d\n", ctxt_pP->frame, ctxt_pP->subframe);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_D(RRC,"Other event report frame %d and subframe %d \n", ctxt_pP->frame, ctxt_pP->subframe);
|
||||
break;
|
||||
@@ -4310,6 +4314,22 @@ rrc_eNB_process_MeasurementReport(
|
||||
ue_context_pP->ue_context.measResults->measResultPCell.rsrqResult/2 - 20);
|
||||
}
|
||||
|
||||
/* TODO: improve NR triggering */
|
||||
if (measResults2->measId == 7) {
|
||||
if (ue_context_pP->ue_context.Status != RRC_NR_NSA) {
|
||||
MessageDef *msg;
|
||||
ue_context_pP->ue_context.Status = RRC_NR_NSA;
|
||||
|
||||
msg = itti_alloc_new_message(TASK_RRC_ENB, X2AP_ENDC_SGNB_ADDITION_REQ);
|
||||
X2AP_ENDC_SGNB_ADDITION_REQ(msg).rnti = ctxt_pP->rnti;
|
||||
LOG_I(RRC,
|
||||
"[eNB %d] frame %d subframe %d: UE rnti %x switching to NSA mode\n",
|
||||
ctxt_pP->module_id, ctxt_pP->frame, ctxt_pP->subframe, ctxt_pP->rnti);
|
||||
itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(ctxt_pP->module_id), msg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (measResults2->measResultNeighCells == NULL)
|
||||
return;
|
||||
|
||||
@@ -8399,7 +8419,7 @@ void rrc_eNB_process_AdditionResponseInformation(const module_id_t enb_mod_idP,
|
||||
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt,
|
||||
0,
|
||||
ENB_FLAG_YES,
|
||||
4660,//ue_context->ue_context.rnti,
|
||||
m->rnti,
|
||||
0, 0);
|
||||
|
||||
size = rrc_eNB_generate_RRCConnectionReconfiguration_endc(&ctxt, ue_context, buffer, 8192, scg_CellGroupConfig, nr1_conf);
|
||||
|
||||
@@ -446,6 +446,37 @@ void x2ap_eNB_handle_handover_req_ack(instance_t instance,
|
||||
x2ap_eNB_generate_x2_handover_request_ack(instance_p, target, x2ap_handover_req_ack);
|
||||
}
|
||||
|
||||
static
|
||||
void x2ap_eNB_handle_sgNB_add_req(instance_t instance,
|
||||
x2ap_ENDC_sgnb_addition_req_t *x2ap_ENDC_sgnb_addition_req)
|
||||
{
|
||||
x2ap_id_manager *id_manager;
|
||||
x2ap_eNB_instance_t *instance_p;
|
||||
x2ap_eNB_data_t *x2ap_eNB_data;
|
||||
int ue_id;
|
||||
|
||||
/* TODO: remove hardcoded value */
|
||||
x2ap_eNB_data = x2ap_is_eNB_id_in_list(3584);
|
||||
DevAssert(x2ap_eNB_data != NULL);
|
||||
|
||||
instance_p = x2ap_eNB_get_instance(instance);
|
||||
DevAssert(instance_p != NULL);
|
||||
|
||||
/* allocate x2ap ID */
|
||||
id_manager = &instance_p->id_manager;
|
||||
ue_id = x2ap_allocate_new_id(id_manager);
|
||||
if (ue_id == -1) {
|
||||
X2AP_ERROR("could not allocate a new X2AP UE ID\n");
|
||||
/* TODO: cancel NSA: send (to be defined) message to RRC */
|
||||
exit(1);
|
||||
}
|
||||
/* id_source is ue_id, id_target is unknown yet */
|
||||
x2ap_set_ids(id_manager, ue_id, x2ap_ENDC_sgnb_addition_req->rnti, ue_id, -1);
|
||||
x2ap_id_set_state(id_manager, ue_id, X2ID_STATE_NSA_PREPARE);
|
||||
|
||||
x2ap_eNB_generate_ENDC_x2_SgNB_addition_request(instance_p, x2ap_eNB_data, ue_id);
|
||||
}
|
||||
|
||||
static
|
||||
void x2ap_gNB_trigger_sgNB_add_req_ack(instance_t instance,
|
||||
x2ap_ENDC_sgnb_addition_req_ACK_t *x2ap_ENDC_sgnb_addition_req_ACK)
|
||||
@@ -552,11 +583,15 @@ void *x2ap_task(void *arg) {
|
||||
&X2AP_UE_CONTEXT_RELEASE(received_msg));
|
||||
break;
|
||||
|
||||
case X2AP_ENDC_SGNB_ADDITION_REQ:
|
||||
x2ap_eNB_handle_sgNB_add_req(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||
&X2AP_ENDC_SGNB_ADDITION_REQ(received_msg));
|
||||
break;
|
||||
|
||||
case X2AP_ENDC_SGNB_ADDITION_REQ_ACK:
|
||||
x2ap_gNB_trigger_sgNB_add_req_ack(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||
&X2AP_ENDC_SGNB_ADDITION_REQ_ACK(received_msg));
|
||||
LOG_I(X2AP, "Received elements for X2AP_ENDC_SGNB_ADDITION_REQ_ACK \n");
|
||||
|
||||
break;
|
||||
|
||||
case SCTP_INIT_MSG_MULTI_CNF:
|
||||
|
||||
@@ -1569,7 +1569,7 @@ int x2ap_eNB_generate_ENDC_x2_SgNB_addition_request(
|
||||
ie->id = X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID; //Not sure about that
|
||||
ie->criticality= X2AP_Criticality_reject;
|
||||
ie->value.present = X2AP_SgNBAdditionRequest_IEs__value_PR_UE_X2AP_ID;
|
||||
ie->value.choice.UE_X2AP_ID = ue_id; //x2ap_id_get_id_source(&instance_p->id_manager, ue_id);
|
||||
ie->value.choice.UE_X2AP_ID = x2ap_id_get_id_source(&instance_p->id_manager, ue_id);
|
||||
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||
|
||||
ie = (X2AP_SgNBAdditionRequest_IEs_t *)calloc(1, sizeof(X2AP_SgNBAdditionRequest_IEs_t));
|
||||
|
||||
@@ -1482,9 +1482,7 @@ x2ap_eNB_handle_ENDC_x2_setup_request(instance_t instance,
|
||||
instance_p = x2ap_eNB_get_instance(instance);
|
||||
DevAssert(instance_p != NULL);
|
||||
|
||||
x2ap_eNB_generate_ENDC_x2_setup_response(instance_p, x2ap_eNB_data);
|
||||
return x2ap_eNB_generate_ENDC_x2_SgNB_addition_request(instance_p, x2ap_eNB_data,0); // Not the right place to call the X2 function. Used only initially for testing.
|
||||
|
||||
return x2ap_eNB_generate_ENDC_x2_setup_response(instance_p, x2ap_eNB_data);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -1804,6 +1802,9 @@ int x2ap_eNB_handle_ENDC_sGNB_addition_response (instance_t instance,
|
||||
x2ap_eNB_data_t *x2ap_eNB_data;
|
||||
MessageDef *msg;
|
||||
int ue_id;
|
||||
int id_source;
|
||||
int id_target;
|
||||
int rnti;
|
||||
|
||||
DevAssert (pdu != NULL);
|
||||
x2SgNBAdditionRequest_ack = &pdu->choice.successfulOutcome.value.choice.SgNBAdditionRequestAcknowledge;
|
||||
@@ -1835,6 +1836,8 @@ int x2ap_eNB_handle_ENDC_sGNB_addition_response (instance_t instance,
|
||||
return -1;
|
||||
}
|
||||
|
||||
id_source = ie->value.choice.UE_X2AP_ID;
|
||||
|
||||
X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).MeNB_ue_x2_id = ie->value.choice.UE_X2AP_ID;
|
||||
|
||||
|
||||
@@ -1846,6 +1849,24 @@ int x2ap_eNB_handle_ENDC_sGNB_addition_response (instance_t instance,
|
||||
return -1;
|
||||
}
|
||||
|
||||
id_target = ie->value.choice.SgNB_UE_X2AP_ID;
|
||||
|
||||
ue_id = id_source;
|
||||
|
||||
if (ue_id != x2ap_find_id_from_id_source(&instance_p->id_manager, id_source)) {
|
||||
X2AP_WARN("incorrect/unknown X2AP IDs for UE (old ID %d new ID %d), ignoring sGNB addition response\n",
|
||||
id_source, id_target);
|
||||
itti_free(ITTI_MSG_ORIGIN_ID(msg), msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rnti = x2ap_id_get_rnti(&instance_p->id_manager, ue_id);
|
||||
|
||||
/* id_target is a new information, store it */
|
||||
x2ap_set_ids(&instance_p->id_manager, ue_id, rnti, id_source, id_target);
|
||||
|
||||
X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rnti = rnti;
|
||||
|
||||
X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).SgNB_ue_x2_id = ie->value.choice.SgNB_UE_X2AP_ID;
|
||||
|
||||
/* X2AP_ProtocolIE_ID_id_E_RABs_ToBeAdded_SgNBAddReqList */
|
||||
@@ -1907,10 +1928,7 @@ int x2ap_eNB_handle_ENDC_sGNB_addition_response (instance_t instance,
|
||||
|
||||
itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg);
|
||||
|
||||
x2ap_eNB_generate_ENDC_x2_SgNB_reconfiguration_complete(instance_p, x2ap_eNB_data,0,0); // Not the right place to call the X2 function. Used only initially for testing.
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static
|
||||
|
||||
@@ -37,7 +37,8 @@
|
||||
typedef enum {
|
||||
X2ID_STATE_SOURCE_PREPARE,
|
||||
X2ID_STATE_SOURCE_OVERALL,
|
||||
X2ID_STATE_TARGET
|
||||
X2ID_STATE_TARGET,
|
||||
X2ID_STATE_NSA_PREPARE,
|
||||
} x2id_state_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
Reference in New Issue
Block a user