Commit d605e5ff authored by matzakos's avatar matzakos Committed by magounak

ENDC for 5G NSA support: Basic implementation of...

ENDC for 5G NSA support: Basic implementation of x2ap_gNB_generate_ENDC_x2_setup_response() and x2ap_gNB_handle_ENDC_x2_setup_response()
parent e7d51624
......@@ -151,7 +151,8 @@ void x2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa
printf("x2ap_eNB_handle_sctp_association_resp at 4\n");
dump_trees();
/* Prepare new x2 Setup Request */
x2ap_eNB_generate_x2_setup_request(instance_p, x2ap_enb_data_p);
x2ap_eNB_generate_ENDC_x2_setup_request(instance_p, x2ap_enb_data_p);
//x2ap_eNB_generate_x2_setup_request(instance_p, x2ap_enb_data_p);
}
static
......
......@@ -175,6 +175,12 @@ typedef struct x2ap_eNB_instance_s {
uint32_t fdd_earfcn_UL[MAX_NUM_CCs];
uint32_t subframeAssignment[MAX_NUM_CCs];
uint32_t specialSubframe[MAX_NUM_CCs];
//#ifdef Rel15
uint32_t tdd_nRARFCN[MAX_NUM_CCs];
int16_t nr_SCS[MAX_NUM_CCs];
//#endif
int num_cc;
net_ip_address_t target_enb_x2_ip_address[X2AP_MAX_NB_ENB_IP_ADDRESS];
......
......@@ -1225,9 +1225,11 @@ int x2ap_eNB_generate_senb_addition_request_ack (x2ap_eNB_instance_t *instance_p
return ret;
}
/*setup request message from an eNB to a gNB*/
int x2ap_eNB_generate_ENDC_x2_setup_request(
x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p)
{
printf("In x2ap_eNB_generate_ENDC_x2_setup_request \n");
X2AP_X2AP_PDU_t pdu;
X2AP_ENDCX2SetupRequest_t *out;
X2AP_ENDCX2SetupRequest_IEs_t *ie;
......@@ -1349,3 +1351,145 @@ int x2ap_eNB_generate_ENDC_x2_setup_request(
return ret;
}
/*setup request message from an eNB to a gNB*/
int x2ap_gNB_generate_ENDC_x2_setup_response(
x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p)
{
X2AP_X2AP_PDU_t pdu;
X2AP_ENDCX2SetupResponse_t *out;
X2AP_ENDCX2SetupResponse_IEs_t *ie;
X2AP_En_gNB_ENDCX2SetupReqAckIEs_t *ie_GNB_ENDC;
X2AP_PLMN_Identity_t *plmn;
ServedNRcellsENDCX2ManagementList__Member *servedCellMember;
uint8_t *buffer;
uint32_t len;
int ret = 0;
DevAssert(instance_p != NULL);
DevAssert(x2ap_eNB_data_p != NULL);
x2ap_eNB_data_p->state = X2AP_ENB_STATE_WAITING;
/* Prepare the X2AP message to encode */
memset(&pdu, 0, sizeof(pdu));
pdu.present = X2AP_X2AP_PDU_PR_initiatingMessage;
pdu.choice.successfulOutcome.procedureCode = X2AP_ProcedureCode_id_endcX2Setup;
pdu.choice.successfulOutcome.criticality = X2AP_Criticality_reject;
pdu.choice.successfulOutcome.value.present = X2AP_SuccessfulOutcome__value_PR_ENDCX2SetupResponse;
out = &pdu.choice.successfulOutcome.value.choice.ENDCX2SetupResponse;
ie = (X2AP_ENDCX2SetupResponse_IEs_t *)calloc(1, sizeof(X2AP_ENDCX2SetupResponse_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_RespondingNodeType_EndcX2Setup;
ie->value.present = X2AP_ENDCX2SetupResponse_IEs__value_PR_RespondingNodeType_EndcX2Setup;
ie->value.choice.RespondingNodeType_EndcX2Setup.present = X2AP_RespondingNodeType_EndcX2Setup_PR_respond_en_gNB;
ie_GNB_ENDC = (X2AP_En_gNB_ENDCX2SetupReqAckIEs_t *)calloc(1, sizeof(X2AP_En_gNB_ENDCX2SetupReqAckIEs_t));
ie_GNB_ENDC->id = X2AP_ProtocolIE_ID_id_Globalen_gNB_ID;
ie_GNB_ENDC->criticality = X2AP_Criticality_reject;
ie_GNB_ENDC->value.present = X2AP_En_gNB_ENDCX2SetupReqAckIEs__value_PR_GlobalGNB_ID;
ie_GNB_ENDC->value.choice.GlobalGNB_ID.gNB_ID.present = X2AP_GNB_ID_PR_gNB_ID;
INT32_TO_OCTET_STRING(instance_p->eNB_id,
&ie_GNB_ENDC->value.choice.GlobalGNB_ID.gNB_ID.choice.gNB_ID);
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
&ie_GNB_ENDC->value.choice.GlobalGNB_ID.pLMN_Identity);
ASN_SEQUENCE_ADD(&ie->value.choice.RespondingNodeType_EndcX2Setup.choice.respond_en_gNB.list, ie_GNB_ENDC);
ie_GNB_ENDC = (X2AP_En_gNB_ENDCX2SetupReqAckIEs_t *)calloc(1, sizeof(X2AP_En_gNB_ENDCX2SetupReqAckIEs_t));
ie_GNB_ENDC->id = X2AP_ProtocolIE_ID_id_ServedNRcellsENDCX2ManagementList;
ie_GNB_ENDC->criticality = X2AP_Criticality_reject;
ie_GNB_ENDC->value.present = X2AP_En_gNB_ENDCX2SetupReqAckIEs__value_PR_ServedNRcellsENDCX2ManagementList;
{
for (int i = 0; i<instance_p->num_cc; i++){
servedCellMember = (ServedNRcellsENDCX2ManagementList__Member *)calloc(1,sizeof(ServedNRcellsENDCX2ManagementList__Member));
{
servedCellMember->servedNRCellInfo.nrpCI = instance_p->Nid_cell[i];
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
&servedCellMember->servedNRCellInfo.nrCellID.pLMN_Identity);
NR_CELL_ID_TO_BIT_STRING(instance_p->eNB_id,
&servedCellMember->servedNRCellInfo.nrCellID.nRcellIdentifier);
plmn = (X2AP_PLMN_Identity_t *)calloc(1,sizeof(X2AP_PLMN_Identity_t));
{
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, plmn);
ASN_SEQUENCE_ADD(&servedCellMember->servedNRCellInfo.broadcastPLMNs.list, plmn);
}
if (instance_p->frame_type[i] == TDD) {
servedCellMember->servedNRCellInfo.nrModeInfo.present = X2AP_ServedNRCell_Information__nrModeInfo_PR_tdd;
servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_ARFCN = instance_p->tdd_nRARFCN[i];
/*Missing addition of Frequency Band List item here, can't find it... */
switch (instance_p->N_RB_DL[i]) {
case 50:
//This is not correct. Just to be able to test X2 only using an eNB instead of gNB
servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb51;
break;
case 93 :
servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb93;
break;
case 106:
servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb106;
break;
case 121:
servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb121;
break;
/*More cases to be added */
default:
AssertFatal(0,"Failed: Check value for N_RB_DL/N_RB_UL");
break;
}
instance_p->nr_SCS[i] = 30; // Hardcoded for now. Normally this should originate from the gNB config file
switch (instance_p->nr_SCS[i]) {
case 15:
servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRSCS = X2AP_NRSCS_scs15;
break;
case 30:
servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRSCS = X2AP_NRSCS_scs30;
break;
case 60:
servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRSCS = X2AP_NRSCS_scs60;
break;
case 120:
servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRSCS = X2AP_NRSCS_scs120;
break;
default:
AssertFatal(0,"Failed: Check value for nr_SCS");
break;
}
}
else {
AssertFatal(0,"nr_X2Setupresponse not supported for FDD!");
}
/*Don't know where to extract the value of measurementTimingConfiguration from. Set it to 0 for now */
INT16_TO_OCTET_STRING(0, &servedCellMember->servedNRCellInfo.measurementTimingConfiguration);
}
ASN_SEQUENCE_ADD(&ie_GNB_ENDC->value.choice.ServedNRcellsENDCX2ManagementList.list, servedCellMember);
}
}
ASN_SEQUENCE_ADD(&ie->value.choice.RespondingNodeType_EndcX2Setup.choice.respond_en_gNB.list, ie_GNB_ENDC);
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
X2AP_ERROR("Failed to encode X2 setup request\n");
return -1;
}
MSC_LOG_TX_MESSAGE (MSC_X2AP_SRC_ENB, MSC_X2AP_TARGET_ENB, NULL, 0, "0 X2Setup/initiatingMessage assoc_id %u", x2ap_eNB_data_p->assoc_id);
x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_eNB_data_p->assoc_id, buffer, len, 0);
return ret;
}
......@@ -68,4 +68,6 @@ int x2ap_eNB_generate_senb_addition_request_ack (x2ap_eNB_instance_t *instance_p
int x2ap_eNB_generate_ENDC_x2_setup_request(x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p);
int x2ap_gNB_generate_ENDC_x2_setup_response( x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p);
#endif /* X2AP_ENB_GENERATE_MESSAGES_H_ */
......@@ -108,6 +108,13 @@ int x2ap_gNB_handle_ENDC_x2_setup_request(instance_t instance,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu);
int
x2ap_gNB_handle_ENDC_x2_setup_response(instance_t instance,
uint32_t assoc_id,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu);
/* Handlers matrix. Only eNB related procedure present here */
x2ap_message_decoded_callback x2ap_messages_callback[][3] = {
{ x2ap_eNB_handle_handover_preparation, x2ap_eNB_handle_handover_response, 0 }, /* handoverPreparation */
......@@ -146,7 +153,7 @@ x2ap_message_decoded_callback x2ap_messages_callback[][3] = {
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 },
{ x2ap_gNB_handle_ENDC_x2_setup_request, 0, 0 },
{ x2ap_gNB_handle_ENDC_x2_setup_request, x2ap_gNB_handle_ENDC_x2_setup_response, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 }
......@@ -1332,6 +1339,7 @@ x2ap_gNB_handle_ENDC_x2_setup_request(instance_t instance,
x2ap_eNB_data_t *x2ap_eNB_data;
uint32_t eNB_id = 0;
x2ap_eNB_data = NULL;
DevAssert (pdu != NULL);
x2_ENDC_SetupRequest = &pdu->choice.initiatingMessage.value.choice.ENDCX2SetupRequest;
......@@ -1445,6 +1453,10 @@ x2ap_gNB_handle_ENDC_x2_setup_request(instance_t instance,
}
}
}
else {
X2AP_ERROR("%s %d: init_eNB list is empty \n",__FILE__,__LINE__);
return -1;
}
}
instance_p = x2ap_eNB_get_instance(instance);
......@@ -1454,3 +1466,145 @@ x2ap_gNB_handle_ENDC_x2_setup_request(instance_t instance,
return x2ap_eNB_generate_x2_setup_response(instance_p, x2ap_eNB_data);
}
int
x2ap_gNB_handle_ENDC_x2_setup_response(instance_t instance,
uint32_t assoc_id,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu)
{
X2AP_ENDCX2SetupResponse_t *x2_ENDC_SetupResponse;
X2AP_ENDCX2SetupResponse_IEs_t *ie;
X2AP_En_gNB_ENDCX2SetupReqAckIEs_t *ie_GNB_ENDC;
ServedNRcellsENDCX2ManagementList__Member *servedCellMember;
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *x2ap_eNB_data;
uint32_t gNB_id = 0;
x2ap_eNB_data = NULL;
DevAssert (pdu != NULL);
x2_ENDC_SetupResponse = &pdu->choice.successfulOutcome.value.choice.ENDCX2SetupResponse;
/*
* We received a new valid X2 Setup Request on a stream != 0.
* * * * This should not happen -> reject eNB x2 setup request.
*/
if (stream != 0) {
X2AP_ERROR("Received new x2 setup request on stream != 0\n");
/*
* Send a x2 setup failure with protocol cause unspecified
*/
// Panos: Here we should be calling an ENDC specific setup_failure function instead
return x2ap_eNB_generate_x2_setup_failure (instance,
assoc_id,
X2AP_Cause_PR_protocol,
X2AP_CauseProtocol_unspecified,
-1);
}
X2AP_DEBUG("Received a new X2 setup request\n");
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_ENDCX2SetupResponse_IEs_t, ie, x2_ENDC_SetupResponse,
X2AP_ProtocolIE_ID_id_RespondingNodeType_EndcX2Setup, true);
if (ie == NULL ) {
X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
return -1;
} else {
if (ie->value.choice.RespondingNodeType_EndcX2Setup.choice.respond_en_gNB.list.count > 0) {
//Panos: Here the container parameter in X2AP_FIND_PROTOCOLIE_BY_ID should be the x2_ENDC_SetupRequest
//message or the ie to which there are more nested information elements?
for (int i=0; i<ie->value.choice.RespondingNodeType_EndcX2Setup.choice.respond_en_gNB.list.count;i++) {
ie_GNB_ENDC = (X2AP_En_gNB_ENDCX2SetupReqAckIEs_t*) ie->value.choice.RespondingNodeType_EndcX2Setup.choice.respond_en_gNB.list.array[i];
if (ie_GNB_ENDC == NULL ) {
X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
return -1;
}
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);
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; i<ie_GNB_ENDC->value.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;
}
}
}
}
}
else {
X2AP_ERROR("%s %d: init_eNB list is empty \n",__FILE__,__LINE__);
return -1;
}
}
/* Optionaly set the target eNB name */
/* The association is now ready as source and target eNBs know parameters of each other.
* Mark the association as connected.
*/
x2ap_eNB_data->state = X2AP_ENB_STATE_READY;
instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
instance_p->x2_target_enb_associated_nb ++;
x2ap_handle_x2_setup_message(instance_p, x2ap_eNB_data, 0);
return 0;
}
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