/* * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The OpenAirInterface Software Alliance licenses this file to You under * the OAI Public License, Version 1.1 (the "License"); you may not use this file * except in compliance with the License. * You may obtain a copy of the License at * * http://www.openairinterface.org/?page_id=698 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *------------------------------------------------------------------------------- * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ /*! \file f1ap_du_interface_management.c * \brief f1ap interface management for DU * \author EURECOM/NTUST * \date 2018 * \version 0.1 * \company Eurecom * \email: navid.nikaein@eurecom.fr, bing-kai.hong@eurecom.fr * \note * \warning */ #include "f1ap_common.h" #include "f1ap_encoder.h" #include "f1ap_itti_messaging.h" #include "f1ap_du_interface_management.h" #include "lib/f1ap_interface_management.h" #include "openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h" #include "assertions.h" #include "GNB_APP/gnb_paramdef.h" int DU_handle_RESET(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { LOG_D(F1AP, "DU_handle_RESET\n");\ F1AP_Reset_t *container; F1AP_ResetIEs_t *ie; DevAssert(pdu != NULL); container = &pdu->choice.initiatingMessage->value.choice.Reset; /* Reset == Non UE-related procedure -> stream 0 */ if (stream != 0) { LOG_W(F1AP, "[SCTP %d] Received Reset on stream != 0 (%d)\n", assoc_id, stream); } MessageDef *msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_RESET); msg_p->ittiMsgHeader.originInstance = assoc_id; f1ap_reset_t *f1ap_reset = &F1AP_RESET(msg_p); /* Transaction ID */ F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_ResetIEs_t, ie, container, F1AP_ProtocolIE_ID_id_TransactionID, true); f1ap_reset->transaction_id = ie->value.choice.TransactionID; LOG_D(F1AP, "req->transaction_id %lu \n", f1ap_reset->transaction_id); /* Cause */ F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_ResetIEs_t, ie, container, F1AP_ProtocolIE_ID_id_Cause, true); switch(ie->value.choice.Cause.present) { case F1AP_Cause_PR_radioNetwork: LOG_D(F1AP, "Cause: Radio Network\n"); f1ap_reset->cause = F1AP_CAUSE_RADIO_NETWORK; f1ap_reset->cause_value = ie->value.choice.Cause.choice.radioNetwork; break; case F1AP_Cause_PR_transport: LOG_D(F1AP, "Cause: Transport\n"); f1ap_reset->cause = F1AP_CAUSE_TRANSPORT; f1ap_reset->cause_value = ie->value.choice.Cause.choice.transport; break; case F1AP_Cause_PR_protocol: LOG_D(F1AP, "Cause: Protocol\n"); f1ap_reset->cause = F1AP_CAUSE_PROTOCOL; f1ap_reset->cause_value = ie->value.choice.Cause.choice.protocol; break; case F1AP_Cause_PR_misc: LOG_D(F1AP, "Cause: Misc\n"); f1ap_reset->cause = F1AP_CAUSE_MISC; f1ap_reset->cause_value = ie->value.choice.Cause.choice.misc; break; default: AssertFatal(1==0,"Unknown cause\n"); } /* ResetType */ F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_ResetIEs_t, ie, container, F1AP_ProtocolIE_ID_id_ResetType, true); switch(ie->value.choice.ResetType.present) { case F1AP_ResetType_PR_f1_Interface: LOG_D(F1AP, "ResetType: F1 Interface\n"); f1ap_reset->reset_type = F1AP_RESET_ALL; break; case F1AP_ResetType_PR_partOfF1_Interface: LOG_D(F1AP, "ResetType: Part of F1 Interface\n"); f1ap_reset->reset_type = F1AP_RESET_PART_OF_F1_INTERFACE; break; default: AssertFatal(1==0,"Unknown reset type\n"); } /* Part of F1 Interface */ if (f1ap_reset->reset_type == F1AP_RESET_PART_OF_F1_INTERFACE) { AssertFatal(1==0, "Not implemented yet\n"); } f1_reset_cu_initiated(f1ap_reset); return 0; } int DU_send_RESET_ACKNOWLEDGE(sctp_assoc_t assoc_id, const f1ap_reset_ack_t *ack) { F1AP_F1AP_PDU_t *pdu = encode_f1ap_reset_ack(ack); if (!pdu) { LOG_E(F1AP, "failed to create ASN.1 message for reset acknowledge\n"); return -1; } /* encode */ uint8_t *buffer; uint32_t len; int encoded = f1ap_encode_pdu(pdu, &buffer, &len); ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); if (encoded <= 0) { LOG_E(F1AP, "Failed to encode F1ResetAcknowledge\n"); return -1; } f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } /** * @brief F1AP Setup Request */ int DU_send_F1_SETUP_REQUEST(sctp_assoc_t assoc_id, const f1ap_setup_req_t *setup_req) { LOG_D(F1AP, "DU_send_F1_SETUP_REQUEST\n"); F1AP_F1AP_PDU_t *pdu = encode_f1ap_setup_request(setup_req); uint8_t *buffer; uint32_t len; /* encode */ if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 setup request\n"); /* free PDU */ ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return -1; } /* free PDU */ ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); /* Send to ITTI */ f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } int DU_handle_F1_SETUP_RESPONSE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { LOG_D(F1AP, "DU_handle_F1_SETUP_RESPONSE\n"); /* Decode */ f1ap_setup_resp_t resp = {0}; if (!decode_f1ap_setup_response(pdu, &resp)) { LOG_E(F1AP, "cannot decode F1AP Setup Response\n"); free_f1ap_setup_response(&resp); return -1; } LOG_D(F1AP, "Sending F1AP_SETUP_RESP ITTI message\n"); f1_setup_response(&resp); // free F1AP message after use free_f1ap_setup_response(&resp); return 0; } /** * @brief F1 Setup Failure handler (DU) */ int DU_handle_F1_SETUP_FAILURE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { f1ap_setup_failure_t fail; if (!decode_f1ap_setup_failure(pdu, &fail)) { LOG_E(F1AP, "Failed to decode F1AP Setup Failure\n"); return -1; } f1_setup_failure(&fail); return 0; } /** * @brief F1 gNB-DU Configuration Update: encoding and ITTI transmission */ int DU_send_gNB_DU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, f1ap_gnb_du_configuration_update_t *msg) { uint8_t *buffer=NULL; uint32_t len=0; /* encode F1AP message */ F1AP_F1AP_PDU_t *pdu = encode_f1ap_du_configuration_update(msg); /* free anfter encoding */ free_f1ap_du_configuration_update(msg); /* encode F1AP pdu */ if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 gNB-DU CONFIGURATION UPDATE\n"); return -1; } /* transfer the message */ ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } /** * @brief F1 gNB-CU Configuration Update decoding and message transfer */ int DU_handle_gNB_CU_CONFIGURATION_UPDATE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { LOG_D(F1AP, "DU_handle_gNB_CU_CONFIGURATION_UPDATE\n"); f1ap_gnb_cu_configuration_update_t in = {0}; if (!decode_f1ap_cu_configuration_update(pdu, &in)) { LOG_E(F1AP, "Failed to decode F1AP Setup Failure\n"); free_f1ap_cu_configuration_update(&in); return -1; } MessageDef *msg_p = itti_alloc_new_message (TASK_DU_F1, 0, F1AP_GNB_CU_CONFIGURATION_UPDATE); f1ap_gnb_cu_configuration_update_t *msg = &F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p); // RRC thread will free it *msg = in; // copy F1 message to ITTI LOG_D(F1AP, "Sending F1AP_GNB_CU_CONFIGURATION_UPDATE ITTI message \n"); itti_send_msg_to_task(TASK_GNB_APP, GNB_MODULE_ID_TO_INSTANCE(assoc_id), msg_p); return 0; } /** * @brief F1 gNB-DU Configuration Update Acknowledge decoding and message transfer */ int DU_handle_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { // Decoding f1ap_gnb_du_configuration_update_acknowledge_t in = {0}; if (!decode_f1ap_du_configuration_update_acknowledge(pdu, &in)) { LOG_E(F1AP, "Failed to decode gNB-DU Configuration Update Acknowledge\n"); free_f1ap_du_configuration_update_acknowledge(&in); return -1; } gnb_du_configuration_update_acknowledge(&in); free_f1ap_du_configuration_update_acknowledge(&in); return 0; } int DU_send_gNB_CU_CONFIGURATION_UPDATE_FAILURE(sctp_assoc_t assoc_id, f1ap_gnb_cu_configuration_update_failure_t *GNBCUConfigurationUpdateFailure) { AssertFatal(1==0,"received gNB CU CONFIGURATION UPDATE FAILURE with cause %d\n", GNBCUConfigurationUpdateFailure->cause); } /** * @brief Encode and transfer F1 GNB CU Configuration Update Acknowledge message */ int DU_send_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(sctp_assoc_t assoc_id, f1ap_gnb_cu_configuration_update_acknowledge_t *msg) { uint8_t *buffer = NULL; uint32_t len = 0; /* encode F1 message */ F1AP_F1AP_PDU_t *pdu = encode_f1ap_cu_configuration_update_acknowledge(msg); /* encode F1AP PDU */ if (!pdu || f1ap_encode_pdu(pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode GNB-CU-Configuration-Update-Acknowledge\n"); ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return -1; } ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; }