diff --git a/openair2/COMMON/x2ap_messages_def.h b/openair2/COMMON/x2ap_messages_def.h index 8438fd1037..b0f0190c19 100644 --- a/openair2/COMMON/x2ap_messages_def.h +++ b/openair2/COMMON/x2ap_messages_def.h @@ -52,6 +52,7 @@ MESSAGE_DEF(X2AP_UE_CONTEXT_RELEASE , MESSAGE_PRIORITY_MED, x2ap_ue_ MESSAGE_DEF(X2AP_SENB_ADDITION_REQ , MESSAGE_PRIORITY_MED, x2ap_senb_addition_req_t , x2ap_senb_addition_req) /*SGnb bearer addition messages X2AP <-> RRC */ +MESSAGE_DEF(X2AP_ENDC_SETUP_REQ , MESSAGE_PRIORITY_MED, x2ap_ENDC_setup_req_t , x2ap_ENDC_setup_req) MESSAGE_DEF(X2AP_ENDC_SGNB_ADDITION_REQ , MESSAGE_PRIORITY_MED, x2ap_ENDC_sgnb_addition_req_t , x2ap_ENDC_sgnb_addition_req) MESSAGE_DEF(X2AP_ENDC_SGNB_ADDITION_REQ_ACK , MESSAGE_PRIORITY_MED, x2ap_ENDC_sgnb_addition_req_ACK_t , x2ap_ENDC_sgnb_addition_req_ACK) MESSAGE_DEF(X2AP_ENDC_SGNB_RECONF_COMPLETE , MESSAGE_PRIORITY_MED, x2ap_ENDC_reconf_complete_t , x2ap_ENDC_sgnb_reconf_complete) diff --git a/openair2/COMMON/x2ap_messages_types.h b/openair2/COMMON/x2ap_messages_types.h index f0743e60a5..05e316114d 100644 --- a/openair2/COMMON/x2ap_messages_types.h +++ b/openair2/COMMON/x2ap_messages_types.h @@ -37,6 +37,7 @@ #define X2AP_DEREGISTERED_ENB_IND(mSGpTR) (mSGpTR)->ittiMsg.x2ap_deregistered_enb_ind #define X2AP_UE_CONTEXT_RELEASE(mSGpTR) (mSGpTR)->ittiMsg.x2ap_ue_context_release #define X2AP_HANDOVER_CANCEL(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_cancel +#define X2AP_ENDC_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_ENDC_setup_req #define X2AP_SENB_ADDITION_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_senb_addition_req #define X2AP_ENDC_SGNB_ADDITION_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_ENDC_sgnb_addition_req #define X2AP_ENDC_SGNB_ADDITION_REQ_ACK(mSGpTR) (mSGpTR)->ittiMsg.x2ap_ENDC_sgnb_addition_req_ACK @@ -288,10 +289,6 @@ typedef struct x2ap_senb_addition_req_s { }x2ap_senb_addition_req_t; - - - -//Panos: Have to see what should be the additional/different elements comparing to handover req ack typedef struct x2ap_senb_addition_req_ack_s { int MeNB_UE_X2_id; @@ -313,6 +310,13 @@ typedef struct x2ap_senb_addition_req_ack_s { } x2ap_senb_addition_req_ack_t; + +typedef struct x2ap_ENDC_setup_req_s { + uint32_t Nid_cell[MAX_NUM_CCs]; + int num_cc; + uint32_t servedNrCell_band[MAX_NUM_CCs]; +} x2ap_ENDC_setup_req_t; + typedef struct x2ap_ENDC_sgnb_addition_req_s { int ue_x2_id; LTE_PhysCellId_t target_physCellId; diff --git a/openair2/RRC/LTE/rrc_defs.h b/openair2/RRC/LTE/rrc_defs.h index c498e3c6fe..574d8bcfe1 100644 --- a/openair2/RRC/LTE/rrc_defs.h +++ b/openair2/RRC/LTE/rrc_defs.h @@ -790,6 +790,7 @@ typedef struct eNB_RRC_INST_s { int num_neigh_cells; int num_neigh_cells_cc[MAX_NUM_CCs]; uint32_t neigh_cells_id[MAX_NUM_NEIGH_CELLs][MAX_NUM_CCs]; + uint32_t nr_neigh_freq_band[MAX_NUM_NEIGH_CELLs][MAX_NUM_CCs]; // other RAN parameters int srb1_timer_poll_retransmit; diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index b6062df2c4..e252941d0d 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -1279,6 +1279,8 @@ rrc_eNB_generate_UECapabilityEnquiry( uint8_t size; T(T_ENB_RRC_UE_CAPABILITY_ENQUIRY, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); + int16_t eutra_band = RC.rrc[ctxt_pP->module_id]->configuration.eutra_band[0]; + uint32_t nr_band = RC.rrc[ctxt_pP->module_id]->nr_neigh_freq_band[0][0]; size = do_UECapabilityEnquiry( ctxt_pP, buffer, @@ -9023,6 +9025,27 @@ void rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX, VCD_FUNCTION_OUT); } +void rrc_eNB_process_ENDC_x2_setup_request(int mod_id, x2ap_ENDC_setup_req_t *m) { + if (RC.rrc[mod_id]->num_neigh_cells > MAX_NUM_NEIGH_CELLs) { + LOG_E(RRC, "Error: number of neighbouring cells is exceeded \n"); + return; + } + + if (m->num_cc > MAX_NUM_CCs) { + LOG_E(RRC, "Error: number of neighbouring cells carriers is exceeded \n"); + return; + } + + RC.rrc[mod_id]->num_neigh_cells++; + RC.rrc[mod_id]->num_neigh_cells_cc[RC.rrc[mod_id]->num_neigh_cells-1] = m->num_cc; + + for (int i=0; inum_cc; i++) { + RC.rrc[mod_id]->neigh_cells_id[RC.rrc[mod_id]->num_neigh_cells-1][i] = m->Nid_cell[i]; + RC.rrc[mod_id]->nr_neigh_freq_band[RC.rrc[mod_id]->num_neigh_cells-1][i] = m->servedNrCell_band[i]; + } + +} + void rrc_eNB_process_AdditionResponseInformation(const module_id_t enb_mod_idP, x2ap_ENDC_sgnb_addition_req_ACK_t *m) { NR_CG_Config_t *CG_Config = NULL; { @@ -9408,6 +9431,10 @@ void *rrc_enb_process_itti_msg(void *notUsed) { break; } + case X2AP_ENDC_SETUP_REQ: + rrc_eNB_process_ENDC_x2_setup_request(instance, &X2AP_ENDC_SETUP_REQ(msg_p)); + break; + case X2AP_ENDC_SGNB_ADDITION_REQ_ACK: { rrc_eNB_process_AdditionResponseInformation(ENB_INSTANCE_TO_MODULE_ID(instance), &X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg_p)); break; diff --git a/openair2/RRC/LTE/rrc_proto.h b/openair2/RRC/LTE/rrc_proto.h index 8f6baabcbf..c50ddf3189 100644 --- a/openair2/RRC/LTE/rrc_proto.h +++ b/openair2/RRC/LTE/rrc_proto.h @@ -360,6 +360,8 @@ void rrc_eNB_process_x2_setup_response(int mod_id, x2ap_setup_resp_t *m); void rrc_eNB_process_handoverPreparationInformation(int mod_id, x2ap_handover_req_t *m); +void rrc_eNB_process_ENDC_x2_setup_request(int mod_id, x2ap_ENDC_setup_req_t *m); + /**\brief Generate/decode the handover RRCConnectionReconfiguration at eNB \param module_idP Instance ID for eNB/CH \param frame Frame index diff --git a/openair2/X2AP/x2ap_eNB_defs.h b/openair2/X2AP/x2ap_eNB_defs.h index 6ab62ebf98..3d8efd8cd4 100644 --- a/openair2/X2AP/x2ap_eNB_defs.h +++ b/openair2/X2AP/x2ap_eNB_defs.h @@ -119,6 +119,8 @@ typedef struct x2ap_eNB_data_s { /* Nid cells */ uint32_t Nid_cell[MAX_NUM_CCs]; int num_cc; + /*Frequency band of NR neighbor cell supporting ENDC NSA */ + uint32_t servedNrCell_band[MAX_NUM_CCs]; /* Only meaningfull in virtual mode */ struct x2ap_eNB_instance_s *x2ap_eNB_instance; diff --git a/openair2/X2AP/x2ap_eNB_generate_messages.c b/openair2/X2AP/x2ap_eNB_generate_messages.c index a96fa14f48..81eecf1128 100644 --- a/openair2/X2AP/x2ap_eNB_generate_messages.c +++ b/openair2/X2AP/x2ap_eNB_generate_messages.c @@ -1317,7 +1317,7 @@ MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length freq_band = calloc(1, sizeof(X2AP_FreqBandNrItem_t)); if (freq_band == NULL) exit(1); - freq_band->freqBandIndicatorNr = 1; /* TODO: put correct value */ + freq_band->freqBandIndicatorNr = instance_p->eutra_band[0]; SULFreqBandItem = calloc(1, sizeof(X2AP_SupportedSULFreqBandItem_t)); SULFreqBandItem->freqBandIndicatorNr=80; /* TODO: put correct value */ diff --git a/openair2/X2AP/x2ap_eNB_handler.c b/openair2/X2AP/x2ap_eNB_handler.c index 1c6c98cd81..e5cf174caf 100644 --- a/openair2/X2AP/x2ap_eNB_handler.c +++ b/openair2/X2AP/x2ap_eNB_handler.c @@ -44,6 +44,7 @@ #include "msc.h" #include "assertions.h" #include "conversions.h" +#include "X2AP_FreqBandNrItem.h" static int x2ap_eNB_handle_x2_setup_request (instance_t instance, @@ -1354,13 +1355,13 @@ x2ap_eNB_handle_ENDC_x2_setup_request(instance_t instance, ServedNRcellsENDCX2ManagementList__Member *servedCellMember; x2ap_eNB_instance_t *instance_p; + MessageDef *msg; x2ap_eNB_data_t *x2ap_eNB_data; uint32_t gNB_id = 0; x2ap_eNB_data = NULL; DevAssert (pdu != NULL); x2_ENDC_SetupRequest = &pdu->choice.initiatingMessage.value.choice.ENDCX2SetupRequest; - /* * We received a new valid X2 Setup Request on a stream != 0. * * * * This should not happen -> reject eNB x2 setup request. @@ -1385,103 +1386,110 @@ x2ap_eNB_handle_ENDC_x2_setup_request(instance_t instance, X2AP_ProtocolIE_ID_id_InitiatingNodeType_EndcX2Setup, true); + msg = itti_alloc_new_message(TASK_X2AP, X2AP_ENDC_SETUP_REQ); if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); return -1; } else { if (ie->value.choice.InitiatingNodeType_EndcX2Setup.choice.init_en_gNB.list.count > 0) { + for (int i=0; ivalue.choice.InitiatingNodeType_EndcX2Setup.choice.init_en_gNB.list.count;i++) { + ie_GNB_ENDC = (X2AP_En_gNB_ENDCX2SetupReqIEs_t*) ie->value.choice.InitiatingNodeType_EndcX2Setup.choice.init_eNB.list.array[i]; + if (ie_GNB_ENDC == NULL ) { + X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + return -1; + } - for (int i=0; ivalue.choice.InitiatingNodeType_EndcX2Setup.choice.init_en_gNB.list.count;i++) { + else if (ie_GNB_ENDC->id == X2AP_ProtocolIE_ID_id_Globalen_gNB_ID) { + if (ie_GNB_ENDC->value.choice.GlobalGNB_ID.gNB_ID.choice.gNB_ID.size!= 28) { + //TODO: handle case were size != 28 -> notify ? reject ? + } + OCTET_STRING_TO_INT32(&ie_GNB_ENDC->value.choice.GlobalGNB_ID.gNB_ID.choice.gNB_ID,gNB_id); + X2AP_DEBUG("gNB id: %07x\n", gNB_id); - ie_GNB_ENDC = (X2AP_En_gNB_ENDCX2SetupReqIEs_t*) ie->value.choice.InitiatingNodeType_EndcX2Setup.choice.init_eNB.list.array[i]; - if (ie_GNB_ENDC == NULL ) { - X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); - return -1; - } + X2AP_DEBUG("Adding gNB to the list of associated gNBs\n"); + if ((x2ap_eNB_data = x2ap_is_eNB_id_in_list (gNB_id)) == NULL) { + /* + * eNB has not been found in list of associated eNB, + * * * * Add it to the tail of list and initialize data + */ + if ((x2ap_eNB_data = x2ap_is_eNB_assoc_id_in_list (assoc_id)) == NULL) { + /* + * ?? + */ + return -1; + } else { + x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING; + x2ap_eNB_data->eNB_id = gNB_id; + } + } else { + x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING; + /* + * eNB has been found in list, consider the x2 setup request as a reset connection, + * * * * reseting any previous UE state if sctp association is != than the previous one + */ + if (x2ap_eNB_data->assoc_id != assoc_id) { + /* + * ??: Send an overload cause... + */ + X2AP_ERROR("Rejecting x2 setup request as eNB id %d is already associated to an active sctp association" "Previous known: %d, new one: %d\n", gNB_id, x2ap_eNB_data->assoc_id, assoc_id); - else if (ie_GNB_ENDC->id == X2AP_ProtocolIE_ID_id_Globalen_gNB_ID) { - if (ie_GNB_ENDC->value.choice.GlobalGNB_ID.gNB_ID.choice.gNB_ID.size!= 28) { - //TODO: handle case were size != 28 -> notify ? reject ? - } - OCTET_STRING_TO_INT32(&ie_GNB_ENDC->value.choice.GlobalGNB_ID.gNB_ID.choice.gNB_ID,gNB_id); - X2AP_DEBUG("gNB id: %07x\n", gNB_id); + // Here we should be calling an ENDC specific setup_failure function instead + x2ap_eNB_generate_x2_setup_failure (instance, + assoc_id, + X2AP_Cause_PR_protocol, + X2AP_CauseProtocol_unspecified, + -1); + return -1; + } + /* + * * TODO: call the reset procedure + */ + } + } + else if (ie_GNB_ENDC->id == X2AP_ProtocolIE_ID_id_ServedNRcellsENDCX2ManagementList){ + if (ie_GNB_ENDC->value.choice.ServedNRcellsENDCX2ManagementList.list.count > 0) { + x2ap_eNB_data->num_cc = ie_GNB_ENDC->value.choice.ServedNRcellsENDCX2ManagementList.list.count; + X2AP_ENDC_SETUP_REQ(msg).num_cc = x2ap_eNB_data->num_cc; + for (int i=0; ivalue.choice.ServedNRcellsENDCX2ManagementList.list.count;i++) { + servedCellMember = (ServedNRcellsENDCX2ManagementList__Member *)ie_GNB_ENDC->value.choice.ServedNRcellsENDCX2ManagementList.list.array[i]; + x2ap_eNB_data->Nid_cell[i] = servedCellMember->servedNRCellInfo.nrpCI; + X2AP_ENDC_SETUP_REQ(msg).Nid_cell[i] = x2ap_eNB_data->Nid_cell[i]; + //servedCellMember->servedNRCellInfo.nrCellID.pLMN_Identity.buf[0] + if (servedCellMember->servedNRCellInfo.fiveGS_TAC != NULL) { + X2AP_INFO("TAC: %02x%02x%02x\n", + servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[0], + servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[1], + servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[2]); + } else { + X2AP_INFO("TAC: (NULL)\n"); + } - X2AP_DEBUG("Adding gNB to the list of associated gNBs\n"); - if ((x2ap_eNB_data = x2ap_is_eNB_id_in_list (gNB_id)) == NULL) { - /* - * eNB has not been found in list of associated eNB, - * * * * Add it to the tail of list and initialize data - */ - if ((x2ap_eNB_data = x2ap_is_eNB_assoc_id_in_list (assoc_id)) == NULL) { - /* - * ?? - */ - return -1; - } else { - x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING; - x2ap_eNB_data->eNB_id = gNB_id; - } - } else { - x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING; - - /* - * eNB has been found in list, consider the x2 setup request as a reset connection, - * * * * reseting any previous UE state if sctp association is != than the previous one - */ - if (x2ap_eNB_data->assoc_id != assoc_id) { - /* - * ??: Send an overload cause... - */ - X2AP_ERROR("Rejecting x2 setup request as eNB id %d is already associated to an active sctp association" "Previous known: %d, new one: %d\n", gNB_id, x2ap_eNB_data->assoc_id, assoc_id); - - // Panos: Here we should be calling an ENDC specific setup_failure function instead - x2ap_eNB_generate_x2_setup_failure (instance, - assoc_id, - X2AP_Cause_PR_protocol, - X2AP_CauseProtocol_unspecified, - -1); - return -1; - } - /* - * * TODO: call the reset procedure - */ - } - } - else if (ie_GNB_ENDC->id == X2AP_ProtocolIE_ID_id_ServedNRcellsENDCX2ManagementList){ - if (ie_GNB_ENDC->value.choice.ServedNRcellsENDCX2ManagementList.list.count > 0) { - x2ap_eNB_data->num_cc = ie_GNB_ENDC->value.choice.ServedNRcellsENDCX2ManagementList.list.count; - for (int i=0; ivalue.choice.ServedNRcellsENDCX2ManagementList.list.count;i++) { - servedCellMember = (ServedNRcellsENDCX2ManagementList__Member *)ie_GNB_ENDC->value.choice.ServedNRcellsENDCX2ManagementList.list.array[i]; - x2ap_eNB_data->Nid_cell[i] = servedCellMember->servedNRCellInfo.nrpCI; - //servedCellMember->servedNRCellInfo.nrCellID.pLMN_Identity.buf[0] - if (servedCellMember->servedNRCellInfo.fiveGS_TAC != NULL) { - X2AP_INFO("TAC: %02x%02x%02x\n", - servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[0], - servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[1], - servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[2]); - } else { - X2AP_INFO("TAC: (NULL)\n"); - } - - X2AP_INFO("PLMN: %02x%02x%02x\n", - servedCellMember->servedNRCellInfo.nrCellID.pLMN_Identity.buf[0], - servedCellMember->servedNRCellInfo.nrCellID.pLMN_Identity.buf[1], - servedCellMember->servedNRCellInfo.nrCellID.pLMN_Identity.buf[2]); - } - } - } - } + X2AP_INFO("PLMN: %02x%02x%02x\n", + servedCellMember->servedNRCellInfo.nrCellID.pLMN_Identity.buf[0], + servedCellMember->servedNRCellInfo.nrCellID.pLMN_Identity.buf[1], + servedCellMember->servedNRCellInfo.nrCellID.pLMN_Identity.buf[2]); + if(servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nRFreqInfo.freqBandListNr.list.count > 0){ + X2AP_FreqBandNrItem_t *FreqBandItem = servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nRFreqInfo.freqBandListNr.list.array[0]; + x2ap_eNB_data->servedNrCell_band[i] = FreqBandItem->freqBandIndicatorNr; + X2AP_ENDC_SETUP_REQ(msg).servedNrCell_band[i] = x2ap_eNB_data->servedNrCell_band[i]; + } + } + } + } + } } else { - X2AP_ERROR("%s %d: init_eNB list is empty \n",__FILE__,__LINE__); - return -1; + X2AP_ERROR("%s %d: init_eNB list is empty \n",__FILE__,__LINE__); + return -1; } } instance_p = x2ap_eNB_get_instance(instance); DevAssert(instance_p != NULL); + itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg); + return x2ap_eNB_generate_ENDC_x2_setup_response(instance_p, x2ap_eNB_data); }