Commit 51ab31a3 authored by Cedric Roux's avatar Cedric Roux

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...
parent ad5706c8
...@@ -357,7 +357,7 @@ typedef struct x2ap_ENDC_sgnb_addition_req_ACK_s { ...@@ -357,7 +357,7 @@ typedef struct x2ap_ENDC_sgnb_addition_req_ACK_s {
int SgNB_ue_x2_id; int SgNB_ue_x2_id;
/* used for RRC->X2AP in source eNB */ /* used for X2AP->RRC in source eNB */
int rnti; int rnti;
uint8_t nb_e_rabs_admitted_tobeadded; uint8_t nb_e_rabs_admitted_tobeadded;
......
...@@ -265,7 +265,8 @@ typedef enum UE_STATE_e { ...@@ -265,7 +265,8 @@ typedef enum UE_STATE_e {
RRC_SI_RECEIVED, RRC_SI_RECEIVED,
RRC_CONNECTED, RRC_CONNECTED,
RRC_RECONFIGURED, RRC_RECONFIGURED,
RRC_HO_EXECUTION RRC_HO_EXECUTION,
RRC_NR_NSA,
} UE_STATE_t; } UE_STATE_t;
typedef enum HO_STATE_e { typedef enum HO_STATE_e {
......
...@@ -4297,6 +4297,10 @@ rrc_eNB_process_MeasurementReport( ...@@ -4297,6 +4297,10 @@ rrc_eNB_process_MeasurementReport(
ctxt_pP->subframe); ctxt_pP->subframe);
break; break;
case 7:
LOG_D(RRC, "NR event frame %d subframe %d\n", ctxt_pP->frame, ctxt_pP->subframe);
break;
default: default:
LOG_D(RRC,"Other event report frame %d and subframe %d \n", ctxt_pP->frame, ctxt_pP->subframe); LOG_D(RRC,"Other event report frame %d and subframe %d \n", ctxt_pP->frame, ctxt_pP->subframe);
break; break;
...@@ -4310,6 +4314,22 @@ rrc_eNB_process_MeasurementReport( ...@@ -4310,6 +4314,22 @@ rrc_eNB_process_MeasurementReport(
ue_context_pP->ue_context.measResults->measResultPCell.rsrqResult/2 - 20); 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) if (measResults2->measResultNeighCells == NULL)
return; return;
...@@ -8399,7 +8419,7 @@ void rrc_eNB_process_AdditionResponseInformation(const module_id_t enb_mod_idP, ...@@ -8399,7 +8419,7 @@ void rrc_eNB_process_AdditionResponseInformation(const module_id_t enb_mod_idP,
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt,
0, 0,
ENB_FLAG_YES, ENB_FLAG_YES,
4660,//ue_context->ue_context.rnti, m->rnti,
0, 0); 0, 0);
size = rrc_eNB_generate_RRCConnectionReconfiguration_endc(&ctxt, ue_context, buffer, 8192, scg_CellGroupConfig, nr1_conf); 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, ...@@ -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); 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 static
void x2ap_gNB_trigger_sgNB_add_req_ack(instance_t instance, void x2ap_gNB_trigger_sgNB_add_req_ack(instance_t instance,
x2ap_ENDC_sgnb_addition_req_ACK_t *x2ap_ENDC_sgnb_addition_req_ACK) x2ap_ENDC_sgnb_addition_req_ACK_t *x2ap_ENDC_sgnb_addition_req_ACK)
...@@ -552,11 +583,15 @@ void *x2ap_task(void *arg) { ...@@ -552,11 +583,15 @@ void *x2ap_task(void *arg) {
&X2AP_UE_CONTEXT_RELEASE(received_msg)); &X2AP_UE_CONTEXT_RELEASE(received_msg));
break; 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: case X2AP_ENDC_SGNB_ADDITION_REQ_ACK:
x2ap_gNB_trigger_sgNB_add_req_ack(ITTI_MESSAGE_GET_INSTANCE(received_msg), x2ap_gNB_trigger_sgNB_add_req_ack(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&X2AP_ENDC_SGNB_ADDITION_REQ_ACK(received_msg)); &X2AP_ENDC_SGNB_ADDITION_REQ_ACK(received_msg));
LOG_I(X2AP, "Received elements for X2AP_ENDC_SGNB_ADDITION_REQ_ACK \n"); LOG_I(X2AP, "Received elements for X2AP_ENDC_SGNB_ADDITION_REQ_ACK \n");
break; break;
case SCTP_INIT_MSG_MULTI_CNF: case SCTP_INIT_MSG_MULTI_CNF:
......
...@@ -1569,7 +1569,7 @@ int x2ap_eNB_generate_ENDC_x2_SgNB_addition_request( ...@@ -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->id = X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID; //Not sure about that
ie->criticality= X2AP_Criticality_reject; ie->criticality= X2AP_Criticality_reject;
ie->value.present = X2AP_SgNBAdditionRequest_IEs__value_PR_UE_X2AP_ID; 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); ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
ie = (X2AP_SgNBAdditionRequest_IEs_t *)calloc(1, sizeof(X2AP_SgNBAdditionRequest_IEs_t)); 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, ...@@ -1482,9 +1482,7 @@ x2ap_eNB_handle_ENDC_x2_setup_request(instance_t instance,
instance_p = x2ap_eNB_get_instance(instance); instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL); DevAssert(instance_p != NULL);
x2ap_eNB_generate_ENDC_x2_setup_response(instance_p, x2ap_eNB_data); return 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.
} }
int int
...@@ -1804,6 +1802,9 @@ int x2ap_eNB_handle_ENDC_sGNB_addition_response (instance_t instance, ...@@ -1804,6 +1802,9 @@ int x2ap_eNB_handle_ENDC_sGNB_addition_response (instance_t instance,
x2ap_eNB_data_t *x2ap_eNB_data; x2ap_eNB_data_t *x2ap_eNB_data;
MessageDef *msg; MessageDef *msg;
int ue_id; int ue_id;
int id_source;
int id_target;
int rnti;
DevAssert (pdu != NULL); DevAssert (pdu != NULL);
x2SgNBAdditionRequest_ack = &pdu->choice.successfulOutcome.value.choice.SgNBAdditionRequestAcknowledge; x2SgNBAdditionRequest_ack = &pdu->choice.successfulOutcome.value.choice.SgNBAdditionRequestAcknowledge;
...@@ -1835,6 +1836,8 @@ int x2ap_eNB_handle_ENDC_sGNB_addition_response (instance_t instance, ...@@ -1835,6 +1836,8 @@ int x2ap_eNB_handle_ENDC_sGNB_addition_response (instance_t instance,
return -1; 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; 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, ...@@ -1846,6 +1849,24 @@ int x2ap_eNB_handle_ENDC_sGNB_addition_response (instance_t instance,
return -1; 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_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 */ /* X2AP_ProtocolIE_ID_id_E_RABs_ToBeAdded_SgNBAddReqList */
...@@ -1907,10 +1928,7 @@ int x2ap_eNB_handle_ENDC_sGNB_addition_response (instance_t instance, ...@@ -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); 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; return 0;
} }
static static
......
...@@ -37,7 +37,8 @@ ...@@ -37,7 +37,8 @@
typedef enum { typedef enum {
X2ID_STATE_SOURCE_PREPARE, X2ID_STATE_SOURCE_PREPARE,
X2ID_STATE_SOURCE_OVERALL, X2ID_STATE_SOURCE_OVERALL,
X2ID_STATE_TARGET X2ID_STATE_TARGET,
X2ID_STATE_NSA_PREPARE,
} x2id_state_t; } x2id_state_t;
typedef struct { typedef struct {
......
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