Files
openairinterface5g/openair2/E1AP/e1ap.c
T
Robert Schmidt 459e20fe99 E1AP: correctly free entire PDU
Free memory including the "base pointer". Fix two places in which it was
on the stack to harmonize. The only stack variable is in reception of
new E1 messages (e1ap_handle_message()), which uses
ASN_STRUCT_FREE_CONTENTS_ONLY().

This fixes bugs similar to these logs:

    Direct leak of 40 byte(s) in 1 object(s) allocated from:
        #0 0x7f418f4e68a3 in calloc (/lib64/libasan.so.8+0xe68a3) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f)
        #1 0x00000049e367 in calloc_or_fail /home/richie/oai/common/utils/utils.h:74
        #2 0x00000049e367 in encode_e1_bearer_context_release_command /home/richie/oai/openair2/E1AP/lib/e1ap_bearer_context_management.c:1235
        #3 0x000000482951 in e1apCUCP_send_BEARER_CONTEXT_RELEASE_COMMAND /home/richie/oai/openair2/E1AP/e1ap.c:546
        #4 0x000000482951 in E1AP_CUCP_task /home/richie/oai/openair2/E1AP/e1ap.c:856
        #5 0x7f418f428ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f)

    Direct leak of 40 byte(s) in 1 object(s) allocated from:
        #0 0x7f418f4e68a3 in calloc (/lib64/libasan.so.8+0xe68a3) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f)
        #1 0x00000049380a in calloc_or_fail /home/richie/oai/common/utils/utils.h:74
        #2 0x00000049380a in encode_E1_bearer_context_setup_request /home/richie/oai/openair2/E1AP/lib/e1ap_bearer_context_management.c:578
        #3 0x00000047f6a2 in e1apCUCP_send_BEARER_CONTEXT_SETUP_REQUEST /home/richie/oai/openair2/E1AP/e1ap.c:378
        #4 0x0000004829f8 in E1AP_CUCP_task /home/richie/oai/openair2/E1AP/e1ap.c:846
        #5 0x7f418f428ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f)

    Direct leak of 40 byte(s) in 1 object(s) allocated from:
        #0 0x7f418f4e68a3 in calloc (/lib64/libasan.so.8+0xe68a3) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f)
        #1 0x00000046ede7 in calloc_or_fail /home/richie/oai/common/utils/utils.h:74
        #2 0x00000046ede7 in encode_e1ap_cuup_setup_response /home/richie/oai/openair2/E1AP/lib/e1ap_interface_management.c:305
        #3 0x00000047e412 in e1ap_send_SETUP_RESPONSE /home/richie/oai/openair2/E1AP/e1ap.c:167
        #4 0x000000482a68 in E1AP_CUCP_task /home/richie/oai/openair2/E1AP/e1ap.c:836
        #5 0x7f418f428ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f)
2025-10-30 08:04:39 +01:00

965 lines
36 KiB
C

/*
* 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
*
* Author and copyright: Laurent Thomas, open-cells.com
*
* 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
*/
#include "e1ap.h"
#include "e1ap_common.h"
#include "gnb_config.h"
#include "openair2/SDAP/nr_sdap/nr_sdap_entity.h"
#include "openair3/UTILS/conversions.h"
#include "openair2/RRC/NR/MESSAGES/asn1_msg.h"
#include "common/openairinterface5g_limits.h"
#include "common/utils/LOG/log.h"
#include "openair2/F1AP/f1ap_common.h"
#include "e1ap_default_values.h"
#include "gtp_itf.h"
#include "openair2/LAYER2/nr_pdcp/cucp_cuup_handler.h"
#include "lib/e1ap_bearer_context_management.h"
#include "lib/e1ap_interface_management.h"
#define E1AP_NUM_MSG_HANDLERS 14
typedef int (*e1ap_message_processing_t)(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *message_p);
/**
* @brief E1AP messages handlers
*/
const e1ap_message_processing_t e1ap_message_processing[E1AP_NUM_MSG_HANDLERS][3] = {
{0, 0, 0}, /* Reset */
{0, 0, 0}, /* ErrorIndication */
{0, 0, 0}, /* privateMessage */
{e1apCUCP_handle_SETUP_REQUEST, e1apCUUP_handle_SETUP_RESPONSE, e1apCUUP_handle_SETUP_FAILURE}, /* gNBCUUPE1Setup */
{0, 0, 0}, /* gNBCUCPE1Setup */
{0, 0, 0}, /* gNBCUUPConfigurationUpdate */
{0, 0, 0}, /* gNBCUCPConfigurationUpdate */
{0, 0, 0}, /* E1Release */
{e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST,
e1apCUCP_handle_BEARER_CONTEXT_SETUP_RESPONSE,
e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE}, /* bearerContextSetup */
{e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST,
e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_RESPONSE,
e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_FAILURE}, /* bearerContextModification */
{0, 0, 0}, /* bearerContextModificationRequired */
{e1apCUUP_handle_BEARER_CONTEXT_RELEASE_COMMAND, e1apCUCP_handle_BEARER_CONTEXT_RELEASE_COMPLETE, 0}, /* bearerContextRelease */
{0, 0, 0}, /* bearerContextReleaseRequired */
{0, 0, 0} /* bearerContextInactivityNotification */
};
const char *const e1ap_direction2String(int e1ap_dir)
{
static const char *e1ap_direction_String[] = {
"", /* Nothing */
"Initiating message", /* initiating message */
"Successfull outcome", /* successfull outcome */
"UnSuccessfull outcome", /* successfull outcome */
};
return (e1ap_direction_String[e1ap_dir]);
}
static int e1ap_handle_message(instance_t instance, sctp_assoc_t assoc_id, const uint8_t *const data, const uint32_t data_length)
{
E1AP_E1AP_PDU_t pdu = {0};
int ret;
DevAssert(data != NULL);
if (e1ap_decode_pdu(&pdu, data, data_length) < 0) {
LOG_E(E1AP, "Failed to decode PDU\n");
return -1;
}
const E1AP_ProcedureCode_t procedureCode = pdu.choice.initiatingMessage->procedureCode;
/* Checking procedure Code and direction of message */
if ((procedureCode >= E1AP_NUM_MSG_HANDLERS) || (pdu.present > E1AP_E1AP_PDU_PR_unsuccessfulOutcome)
|| (pdu.present <= E1AP_E1AP_PDU_PR_NOTHING)) {
LOG_E(E1AP, "[SCTP %d] Either procedureCode %ld or direction %d exceed expected\n", assoc_id, procedureCode, pdu.present);
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_E1AP_E1AP_PDU, &pdu);
return -1;
}
if (e1ap_message_processing[procedureCode][pdu.present - 1] == NULL) {
// No handler present. This can mean not implemented or no procedure for eNB
// (wrong direction).
LOG_E(E1AP,
"[SCTP %d] No handler for procedureCode %ld in %s\n",
assoc_id,
procedureCode,
e1ap_direction2String(pdu.present - 1));
ret = -1;
} else {
/* Calling the right handler */
LOG_D(E1AP, "Calling handler with instance %ld\n", instance);
ret = (*e1ap_message_processing[procedureCode][pdu.present - 1])(assoc_id, getCxtE1(instance), &pdu);
}
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_E1AP_E1AP_PDU, &pdu);
return ret;
}
static void e1_task_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind)
{
int result;
DevAssert(sctp_data_ind != NULL);
e1ap_handle_message(instance, sctp_data_ind->assoc_id, sctp_data_ind->buffer, sctp_data_ind->buffer_length);
result = itti_free(TASK_UNKNOWN, sctp_data_ind->buffer);
AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
}
int e1ap_send_RESET(bool isCu, sctp_assoc_t assoc_id, E1AP_Reset_t *Reset)
{
AssertFatal(false, "Not implemented yet\n");
E1AP_E1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu));
return e1ap_encode_send(isCu, assoc_id, pdu, 0, __func__);
}
int e1ap_send_RESET_ACKNOWLEDGE(instance_t instance, E1AP_Reset_t *Reset)
{
AssertFatal(false, "Not implemented yet\n");
return -1;
}
int e1ap_handle_RESET(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, E1AP_E1AP_PDU_t *pdu)
{
AssertFatal(false, "Not implemented yet\n");
return -1;
}
int e1ap_handle_RESET_ACKNOWLEDGE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, E1AP_E1AP_PDU_t *pdu)
{
AssertFatal(false, "Not implemented yet\n");
return -1;
}
/*
Error Indication
*/
int e1ap_handle_ERROR_INDICATION(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, E1AP_E1AP_PDU_t *pdu)
{
AssertFatal(false, "Not implemented yet\n");
return -1;
}
int e1ap_send_ERROR_INDICATION(instance_t instance, E1AP_ErrorIndication_t *ErrorIndication)
{
AssertFatal(false, "Not implemented yet\n");
return -1;
}
void e1ap_send_SETUP_RESPONSE(sctp_assoc_t assoc_id, const e1ap_setup_resp_t *e1ap_setup_resp)
{
E1AP_E1AP_PDU_t *pdu = encode_e1ap_cuup_setup_response(e1ap_setup_resp);
e1ap_encode_send(CPtype, assoc_id, pdu, 0, __func__);
}
/**
* @brief E1 Setup Failure ASN1 messager encoder
*/
static void e1apCUCP_send_SETUP_FAILURE(sctp_assoc_t assoc_id, const e1ap_setup_fail_t *msg)
{
LOG_D(E1AP, "CU-CP: Encoding E1AP Setup Failure for transac_id %ld...\n", msg->transac_id);
E1AP_E1AP_PDU_t *pdu = encode_e1ap_cuup_setup_failure(msg);
e1ap_encode_send(CPtype, assoc_id, pdu, 0, __func__);
}
int e1apCUCP_handle_SETUP_REQUEST(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu)
{
DevAssert(pdu != NULL);
/* Create ITTI message and send to queue */
MessageDef *msg_p = itti_alloc_new_message(TASK_CUCP_E1, 0 /*unused by callee*/, E1AP_SETUP_REQ);
// Decode E1 CU-UP Setup Request
if (!decode_e1ap_cuup_setup_request(pdu, &E1AP_SETUP_REQ(msg_p))) {
free_e1ap_cuup_setup_request(&E1AP_SETUP_REQ(msg_p));
return -1;
}
msg_p->ittiMsgHeader.originInstance = assoc_id;
if (E1AP_SETUP_REQ(msg_p).supported_plmns > 0) {
itti_send_msg_to_task(TASK_RRC_GNB, 0 /*unused by callee*/, msg_p);
} else {
e1ap_cause_t cause = { .type = E1AP_CAUSE_PROTOCOL, .value = E1AP_PROTOCOL_CAUSE_SEMANTIC_ERROR};
e1ap_setup_fail_t setup_fail = {.transac_id = E1AP_SETUP_REQ(msg_p).transac_id, .cause = cause};
e1apCUCP_send_SETUP_FAILURE(assoc_id, &setup_fail);
itti_free(TASK_CUCP_E1, msg_p);
return -1;
}
return 0;
}
int e1apCUUP_handle_SETUP_RESPONSE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu)
{
// Decode E1 CU-UP Setup Response
e1ap_setup_resp_t out = {0};
if (!decode_e1ap_cuup_setup_response(pdu, &out)) {
free_e1ap_cuup_setup_response(&out);
return -1;
}
long old_transaction_id = inst->cuup.setupReq.transac_id;
if (old_transaction_id != out.transac_id) {
LOG_E(E1AP, "Transaction IDs do not match %ld != %ld\n", old_transaction_id, out.transac_id);
free_e1ap_cuup_setup_response(&out);
return -1;
}
free_e1ap_cuup_setup_response(&out);
e1_reset(); // reset all UE contexts, if any: see 38.463 sec 8.2.3
return 0;
}
/**
* @brief E1 Setup Failure ASN1 messager decoder on CU-UP
*/
int e1apCUUP_handle_SETUP_FAILURE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu)
{
LOG_D(E1AP, "CU-UP: Decoding E1AP Setup Failure...\n");
E1AP_GNB_CU_UP_E1SetupFailureIEs_t *ie;
DevAssert(pdu != NULL);
E1AP_GNB_CU_UP_E1SetupFailure_t *in = &pdu->choice.unsuccessfulOutcome->value.choice.GNB_CU_UP_E1SetupFailure;
/* Transaction ID */
F1AP_FIND_PROTOCOLIE_BY_ID(E1AP_GNB_CU_UP_E1SetupFailureIEs_t, ie, in, E1AP_ProtocolIE_ID_id_TransactionID, true);
long transaction_id;
long old_transaction_id = inst->cuup.setupReq.transac_id;
transaction_id = ie->value.choice.TransactionID;
if (old_transaction_id != transaction_id)
LOG_E(E1AP, "Transaction IDs do not match %ld != %ld\n", old_transaction_id, transaction_id);
E1AP_free_transaction_identifier(transaction_id);
/* Cause */
F1AP_FIND_PROTOCOLIE_BY_ID(E1AP_GNB_CU_UP_E1SetupFailureIEs_t, ie, in, E1AP_ProtocolIE_ID_id_Cause, true);
LOG_E(E1AP, "received E1 Setup Failure, please check the CU-CP output and the CU-UP parameters\n");
exit(1);
return 0;
}
static void fill_CONFIGURATION_UPDATE(E1AP_E1AP_PDU_t *pdu)
{
/* Create */
/* 0. pdu Type */
pdu->present = E1AP_E1AP_PDU_PR_initiatingMessage;
asn1cCalloc(pdu->choice.initiatingMessage, msg);
msg->procedureCode = E1AP_ProcedureCode_id_gNB_CU_UP_ConfigurationUpdate;
msg->criticality = E1AP_Criticality_reject;
msg->value.present = E1AP_InitiatingMessage__value_PR_GNB_CU_UP_ConfigurationUpdate;
E1AP_GNB_CU_UP_ConfigurationUpdate_t *out = &pdu->choice.initiatingMessage->value.choice.GNB_CU_UP_ConfigurationUpdate;
/* mandatory */
/* c1. Transaction ID (integer value) */
asn1cSequenceAdd(out->protocolIEs.list, E1AP_GNB_CU_UP_ConfigurationUpdateIEs_t, ieC1);
ieC1->id = E1AP_ProtocolIE_ID_id_TransactionID;
ieC1->criticality = E1AP_Criticality_reject;
ieC1->value.present = E1AP_GNB_CU_UP_ConfigurationUpdateIEs__value_PR_TransactionID;
ieC1->value.choice.TransactionID = 0;//get this from stored transaction IDs in CU
/* mandatory */
/* c2. Supported PLMNs */
asn1cSequenceAdd(out->protocolIEs.list, E1AP_GNB_CU_UP_ConfigurationUpdateIEs_t, ieC2);
ieC2->id = E1AP_ProtocolIE_ID_id_SupportedPLMNs;
ieC2->criticality = E1AP_Criticality_reject;
ieC2->value.present = E1AP_GNB_CU_UP_ConfigurationUpdateIEs__value_PR_SupportedPLMNs_List;
int numSupportedPLMNs = 1;
for (int i = 0; i < numSupportedPLMNs; i++) {
asn1cSequenceAdd(ieC2->value.choice.SupportedPLMNs_List.list, E1AP_SupportedPLMNs_Item_t, supportedPLMN);
/* 5.1 PLMN Identity */
OCTET_STRING_fromBuf(&supportedPLMN->pLMN_Identity, "OAI", strlen("OAI"));
}
/* mandatory */
/* c3. TNLA to remove list */
asn1cSequenceAdd(out->protocolIEs.list, E1AP_GNB_CU_UP_ConfigurationUpdateIEs_t, ieC3);
ieC3->id = E1AP_ProtocolIE_ID_id_GNB_CU_UP_TNLA_To_Remove_List;
ieC3->criticality = E1AP_Criticality_reject;
ieC3->value.present = E1AP_GNB_CU_UP_ConfigurationUpdateIEs__value_PR_GNB_CU_UP_TNLA_To_Remove_List;
int numTNLAtoRemoveList = 1;
for (int i = 0; i < numTNLAtoRemoveList; i++) {
asn1cSequenceAdd(ieC2->value.choice.GNB_CU_UP_TNLA_To_Remove_List.list, E1AP_GNB_CU_UP_TNLA_To_Remove_Item_t, TNLAtoRemove);
TNLAtoRemove->tNLAssociationTransportLayerAddress.present = E1AP_CP_TNL_Information_PR_endpoint_IP_Address;
TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &TNLAtoRemove->tNLAssociationTransportLayerAddress.choice.endpoint_IP_Address); // TODO: correct me
}
}
/*
E1 configuration update: can be sent in both ways, to be refined
*/
void e1apCUUP_send_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id)
{
E1AP_E1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu));
fill_CONFIGURATION_UPDATE(pdu);
e1ap_encode_send(UPtype, assoc_id, pdu, 0, __func__);
}
int e1apCUCP_send_gNB_DU_CONFIGURATION_FAILURE(void)
{
AssertFatal(false, "Not implemented yet\n");
return -1;
}
int e1apCUCP_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(void)
{
AssertFatal(false, "Not implemented yet\n");
return -1;
}
int e1apCUCP_handle_CONFIGURATION_UPDATE(E1AP_E1AP_PDU_t *pdu)
{
/*
E1AP_GNB_CU_UP_E1SetupRequestIEs_t *ie;
DevAssert(pdu != NULL);
E1AP_GNB_CU_UP_E1SetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.GNB_CU_UP_E1SetupRequest;
*/
AssertFatal(false, "Not implemented yet\n");
return -1;
}
int e1apCUUP_handle_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(sctp_assoc_t assoc_id, uint32_t stream, E1AP_E1AP_PDU_t *pdu)
{
AssertFatal(false, "Not implemented yet\n");
return -1;
}
int e1apCUUP_handle_gNB_DU_CONFIGURATION_FAILURE(sctp_assoc_t assoc_id, uint32_t stream, E1AP_E1AP_PDU_t *pdu)
{
AssertFatal(false, "Not implemented yet\n");
return -1;
}
/*
E1 release
*/
int e1ap_send_RELEASE_REQUEST(instance_t instance)
{
AssertFatal(false, "Not implemented yet\n");
return -1;
}
int e1ap_send_RELEASE_ACKNOWLEDGE(instance_t instance)
{
AssertFatal(false, "Not implemented yet\n");
return -1;
}
int e1ap_handle_RELEASE_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, E1AP_E1AP_PDU_t *pdu)
{
AssertFatal(false, "Not implemented yet\n");
return -1;
}
int e1ap_handle_RELEASE_ACKNOWLEDGE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, E1AP_E1AP_PDU_t *pdu)
{
AssertFatal(false, "Not implemented yet\n");
return -1;
}
void e1apCUCP_send_BEARER_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, e1ap_bearer_setup_req_t *const bearerCxt)
{
E1AP_E1AP_PDU_t *pdu = encode_E1_bearer_context_setup_request(bearerCxt);
e1ap_encode_send(CPtype, assoc_id, pdu, 0, __func__);
}
void e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, const e1ap_bearer_setup_resp_t *resp)
{
// Encode
E1AP_E1AP_PDU_t *pdu = encode_E1_bearer_context_setup_response(resp);
e1ap_encode_send(UPtype, assoc_id, pdu, 0, __func__);
}
static void e1apCUUP_send_BEARER_CONTEXT_SETUP_FAILURE(sctp_assoc_t assoc_id, const e1ap_bearer_context_setup_failure_t *msg)
{
E1AP_E1AP_PDU_t *pdu = encode_E1_bearer_context_setup_failure(msg);
e1ap_encode_send(UPtype, assoc_id, pdu, 0, __func__);
}
int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu)
{
// Decode E1AP message
e1ap_bearer_setup_req_t bearerCxt = {0};
if (!decode_E1_bearer_context_setup_request(pdu, &bearerCxt)) {
LOG_E(E1AP, "Failed to decode E1 Bearer Context Setup Request\n");
return -1;
}
e1_bearer_context_setup(&bearerCxt);
return 0;
}
int e1apCUCP_handle_BEARER_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu)
{
MessageDef *msg = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_BEARER_CONTEXT_SETUP_RESP);
// Decode
e1ap_bearer_setup_resp_t *bearerCxt = &E1AP_BEARER_CONTEXT_SETUP_RESP(msg);
if (!decode_E1_bearer_context_setup_response(pdu, bearerCxt)) {
LOG_E(E1AP, "Failed to decode Bearer Context Setup Response\n");
return -1;
}
msg->ittiMsgHeader.originInstance = assoc_id;
// Fixme: instance is the NGAP instance, no good way to set it here
instance_t instance = 0;
itti_send_msg_to_task(TASK_RRC_GNB, instance, msg);
return 0;
}
int e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu)
{
e1ap_bearer_context_setup_failure_t fail = {0};
if (!decode_E1_bearer_context_setup_failure(&fail, pdu)) {
LOG_E(E1AP, "Failed to decode Bearer Context Setup Failure\n");
free_e1_bearer_context_setup_failure(&fail);
return -1;
}
LOG_E(E1AP, "Received Bearer Context Setup Failure with cause value%d \n", fail.cause.value);
MessageDef *msg = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_BEARER_CONTEXT_SETUP_FAILURE);
E1AP_BEARER_CONTEXT_SETUP_FAILURE(msg) = fail;
msg->ittiMsgHeader.originInstance = assoc_id;
instance_t instance = 0;
itti_send_msg_to_task(TASK_RRC_GNB, instance, msg);
return 0;
}
static void e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, e1ap_bearer_mod_req_t *const bearerCxt)
{
E1AP_E1AP_PDU_t *pdu = encode_E1_bearer_context_mod_request(bearerCxt);
e1ap_encode_send(CPtype, assoc_id, pdu, 0, __func__);
}
static int e1apCUUP_send_BEARER_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id, const e1ap_bearer_modif_resp_t *resp)
{
E1AP_E1AP_PDU_t *pdu = encode_E1_bearer_context_mod_response(resp);
return e1ap_encode_send(UPtype, assoc_id, pdu, 0, __func__);
}
static int e1apCUUP_send_BEARER_CONTEXT_MODIFICATION_FAILURE(sctp_assoc_t assoc_id, const e1ap_bearer_context_mod_failure_t *out)
{
E1AP_E1AP_PDU_t *pdu = encode_E1_bearer_context_mod_failure(out);
e1ap_encode_send(UPtype, assoc_id, pdu, 0, __func__);
return 0;
}
/**
* @brief Extract Bearer Context Modification Request from E1AP PDU
* and prepare Bearer Context Modification Response
*/
int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id,
e1ap_upcp_inst_t *e1_inst,
const E1AP_E1AP_PDU_t *pdu)
{
e1ap_bearer_mod_req_t bearerCxt = {0};
if (!decode_E1_bearer_context_mod_request(pdu, &bearerCxt)) {
LOG_E(E1AP, "Failed to handle Bearer Context Modification Request\n");
free_e1ap_context_mod_request(&bearerCxt);
return -1;
}
e1_bearer_context_modif(&bearerCxt);
free_e1ap_context_mod_request(&bearerCxt);
return 0;
}
int e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id,
e1ap_upcp_inst_t *e1_inst,
const E1AP_E1AP_PDU_t *pdu)
{
MessageDef *msg = itti_alloc_new_message(TASK_CUUP_E1, 0, E1AP_BEARER_CONTEXT_MODIFICATION_RESP);
e1ap_bearer_modif_resp_t *modif = &E1AP_BEARER_CONTEXT_MODIFICATION_RESP(msg);
if(!decode_E1_bearer_context_mod_response(modif, pdu)) {
free_e1ap_context_mod_response(modif);
return -1;
}
itti_send_msg_to_task(TASK_RRC_GNB, 0, msg);
return 0;
}
int e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_FAILURE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu)
{
e1ap_bearer_context_mod_failure_t failure = {0};
if (!decode_E1_bearer_context_mod_failure(&failure, pdu)) {
free_E1_bearer_context_mod_failure(&failure);
return -1;
}
LOG_E(E1AP,
"Received Bearer Context Modification Failure from CU-UP %d with cause value %d \n",
failure.gNB_cu_up_ue_id,
failure.cause.value);
MessageDef *msg = itti_alloc_new_message(TASK_CUUP_E1, 0, E1AP_BEARER_CONTEXT_MODIFICATION_FAIL);
E1AP_BEARER_CONTEXT_MODIFICATION_FAIL(msg) = cp_E1_bearer_context_mod_failure(&failure);
itti_send_msg_to_task(TASK_RRC_GNB, 0, msg);
return 0;
}
int e1apCUUP_send_BEARER_CONTEXT_MODIFICATION_REQUIRED(instance_t instance)
{
AssertFatal(false, "Not implemented yet\n");
return -1;
}
int e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_CONFIRM(instance_t instance)
{
AssertFatal(false, "Not implemented yet\n");
return -1;
}
int e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_REQUIRED(instance_t instance,
sctp_assoc_t assoc_id,
uint32_t stream,
E1AP_E1AP_PDU_t *pdu)
{
AssertFatal(false, "Not implemented yet\n");
return -1;
}
int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_CONFIRM(instance_t instance,
sctp_assoc_t assoc_id,
uint32_t stream,
E1AP_E1AP_PDU_t *pdu)
{
AssertFatal(false, "Not implemented yet\n");
return -1;
}
/*
BEARER CONTEXT RELEASE
*/
static int e1apCUCP_send_BEARER_CONTEXT_RELEASE_COMMAND(sctp_assoc_t assoc_id, e1ap_bearer_release_cmd_t *const cmd)
{
E1AP_E1AP_PDU_t *pdu = encode_e1_bearer_context_release_command(cmd);
return e1ap_encode_send(CPtype, assoc_id, pdu, 0, __func__);
}
int e1apCUUP_send_BEARER_CONTEXT_RELEASE_COMPLETE(sctp_assoc_t assoc_id, const e1ap_bearer_release_cplt_t *cplt)
{
E1AP_E1AP_PDU_t *pdu = encode_e1_bearer_context_release_complete(cplt);
return e1ap_encode_send(CPtype, assoc_id, pdu, 0, __func__);
}
int e1apCUUP_send_BEARER_CONTEXT_RELEASE_REQUEST(instance_t instance)
{
AssertFatal(false, "Not implemented yet\n");
return -1;
}
int e1apCUUP_handle_BEARER_CONTEXT_RELEASE_COMMAND(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu)
{
e1ap_bearer_release_cmd_t release = {0};
if(!decode_e1_bearer_context_release_command(&release, pdu)) {
free_e1_bearer_context_release_command(&release);
return -1;
}
e1_bearer_release_cmd(&release);
return 0;
}
int e1apCUCP_handle_BEARER_CONTEXT_RELEASE_COMPLETE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu)
{
e1ap_bearer_release_cplt_t bearerCxt = {0};
if(!decode_e1_bearer_context_release_complete(&bearerCxt, pdu)) {
free_e1_bearer_context_release_complete(&bearerCxt);
return -1;
}
MessageDef *msg = itti_alloc_new_message(TASK_CUUP_E1, 0, E1AP_BEARER_CONTEXT_RELEASE_CPLT);
e1ap_bearer_release_cplt_t *cplt = &E1AP_BEARER_CONTEXT_RELEASE_CPLT(msg);
*cplt = cp_bearer_context_release_complete(&bearerCxt);
itti_send_msg_to_task(TASK_RRC_GNB, 0, msg);
return 0;
}
int e1apCUCP_handle_BEARER_CONTEXT_RELEASE_REQUEST(instance_t instance,
sctp_assoc_t assoc_id,
uint32_t stream,
E1AP_E1AP_PDU_t *pdu)
{
AssertFatal(false, "Not implemented yet\n");
return -1;
}
/*
BEARER CONTEXT INACTIVITY NOTIFICATION
*/
int e1apCUUP_send_BEARER_CONTEXT_INACTIVITY_NOTIFICATION(instance_t instance)
{
AssertFatal(false, "Not implemented yet\n");
return -1;
}
int e1apCUCP_handle_BEARER_CONTEXT_INACTIVITY_NOTIFICATION(instance_t instance,
sctp_assoc_t assoc_id,
uint32_t stream,
E1AP_E1AP_PDU_t *pdu)
{
AssertFatal(false, "Not implemented yet\n");
return -1;
}
/*
DL DATA
*/
int e1apCUUP_send_DL_DATA_NOTIFICATION(instance_t instance)
{
AssertFatal(false, "Not implemented yet\n");
return -1;
}
int e1apCUUP_send_DATA_USAGE_REPORT(instance_t instance)
{
AssertFatal(false, "Not implemented yet\n");
return -1;
}
int e1apCUCP_handle_DL_DATA_NOTIFICATION(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, E1AP_E1AP_PDU_t *pdu)
{
AssertFatal(false, "Not implemented yet\n");
return -1;
}
int e1apCUCP_handle_send_DATA_USAGE_REPORT(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, E1AP_E1AP_PDU_t *pdu)
{
AssertFatal(false, "Not implemented yet\n");
return -1;
}
static instance_t cuup_task_create_gtpu_instance_to_du(eth_params_t *IPaddrs)
{
openAddr_t tmp = {0};
strncpy(tmp.originHost, IPaddrs->my_addr, sizeof(tmp.originHost) - 1);
sprintf(tmp.originService, "%d", IPaddrs->my_portd);
sprintf(tmp.destinationService, "%d", IPaddrs->remote_portd);
return gtpv1Init(tmp);
}
static void e1_task_send_sctp_association_req(long task_id, instance_t instance, e1ap_net_config_t *e1ap_nc)
{
DevAssert(e1ap_nc != NULL);
getCxtE1(instance)->sockState = SCTP_STATE_CLOSED;
MessageDef *message_p = itti_alloc_new_message(task_id, 0, SCTP_NEW_ASSOCIATION_REQ);
sctp_new_association_req_t *sctp_new_req = &message_p->ittiMsg.sctp_new_association_req;
sctp_new_req->ulp_cnx_id = instance;
sctp_new_req->port = E1AP_PORT_NUMBER;
sctp_new_req->ppid = E1AP_SCTP_PPID;
// remote
sctp_new_req->remote_address = e1ap_nc->CUCP_e1_ip_address;
// local
sctp_new_req->local_address = e1ap_nc->CUUP_e1_ip_address;
itti_send_msg_to_task(TASK_SCTP, instance, message_p);
}
static void e1apCUUP_send_SETUP_REQUEST(sctp_assoc_t assoc_id, e1ap_setup_req_t *setup)
{
setup->transac_id = E1AP_get_next_transaction_identifier();
LOG_D(E1AP, "Transaction ID of setup request %ld\n", setup->transac_id);
E1AP_E1AP_PDU_t *pdu = encode_e1ap_cuup_setup_request(setup);
e1ap_encode_send(UPtype, assoc_id, pdu, 0, __func__);
}
/**
* @brief SCTP association response handler (CU-CP to/from CU-UP)
* it behaves differently depending on the type of E1 instance,
* CUCP: informs RRC of E1 connection loss with CU-UP
* CUUP: triggers a new SCTP association request by sending an ITTI to the CU-UP task
* @param type indicates whether the handler is for the CU-CP or CU-UP
*/
static void e1_task_handle_sctp_association_resp(E1_t type,
instance_t instance,
sctp_new_association_resp_t *sctp_new_association_resp)
{
DevAssert(sctp_new_association_resp != NULL);
getCxtE1(instance)->sockState = sctp_new_association_resp->sctp_state;
// Handle SCTP establishment failure
if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
if (type == CPtype) {
// Inform RRC that the CU-UP is gone
LOG_W(E1AP,
"Lost connection (%s) with CU-UP (assoc_id %d)\n",
sctp_state_s[sctp_new_association_resp->sctp_state],
sctp_new_association_resp->assoc_id);
MessageDef *message_p = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_LOST_CONNECTION);
message_p->ittiMsgHeader.originInstance = sctp_new_association_resp->assoc_id;
itti_send_msg_to_task(TASK_RRC_GNB, instance, message_p);
} else if (type == UPtype) {
// Trigger new E1 association when no CU-CP is connected
LOG_W(E1AP,
"Lost connection (%s) with CU-CP (assoc_id %d): trigger new E1 association\n",
sctp_state_s[sctp_new_association_resp->sctp_state],
sctp_new_association_resp->assoc_id);
long timer_id;
timer_setup(1, 0, TASK_CUUP_E1, 0, TIMER_ONE_SHOT, NULL, &timer_id);
}
return;
}
if (type == UPtype) {
e1ap_upcp_inst_t *inst = getCxtE1(instance);
inst->cuup.assoc_id = sctp_new_association_resp->assoc_id;
e1ap_net_config_t *nc = &inst->net_config;
eth_params_t IPaddr = {0};
IPaddr.my_addr = nc->localAddressF1U;
IPaddr.my_portd = nc->localPortF1U;
IPaddr.remote_portd = nc->remotePortF1U;
if (getCxtE1(instance)->gtpInstF1U < 0)
getCxtE1(instance)->gtpInstF1U = cuup_task_create_gtpu_instance_to_du(&IPaddr);
if (getCxtE1(instance)->gtpInstF1U < 0)
LOG_E(E1AP, "Failed to create CUUP F1-U UDP listener\n");
extern instance_t CUuniqInstance;
CUuniqInstance = getCxtE1(instance)->gtpInstF1U;
cuup_init_n3(instance);
e1apCUUP_send_SETUP_REQUEST(inst->cuup.assoc_id, &inst->cuup.setupReq);
}
}
void cuup_init_n3(instance_t instance)
{
if (getCxtE1(instance)->gtpInstN3 < 0) {
e1ap_net_config_t *nc = &getCxtE1(instance)->net_config;
openAddr_t tmp = {0};
strcpy(tmp.originHost, nc->localAddressN3);
sprintf(tmp.originService, "%d", nc->localPortN3);
sprintf(tmp.destinationService, "%d", nc->remotePortN3);
LOG_I(GTPU, "Configuring GTPu address : %s, port : %s\n", tmp.originHost, tmp.originService);
// Fixme: fully inconsistent instances management
// dirty global var is a bad fix
extern instance_t legacyInstanceMapping;
legacyInstanceMapping = getCxtE1(instance)->gtpInstN3 = gtpv1Init(tmp);
}
if (getCxtE1(instance)->gtpInstN3 < 0)
LOG_E(E1AP, "Failed to create CUUP N3 UDP listener\n");
extern instance_t *N3GTPUInst;
N3GTPUInst = &getCxtE1(instance)->gtpInstN3;
}
void cucp_task_send_sctp_init_req(instance_t instance, char *my_addr)
{
size_t addr_len = strlen(my_addr) + 1;
LOG_I(E1AP, "E1AP_CUCP_SCTP_REQ(create socket) for %s len %ld\n", my_addr, addr_len);
MessageDef *message_p = itti_alloc_new_message_sized(TASK_CUCP_E1, 0, SCTP_INIT_MSG, sizeof(sctp_init_t) + addr_len);
sctp_init_t *init = &SCTP_INIT_MSG(message_p);
init->port = E1AP_PORT_NUMBER;
init->ppid = E1AP_SCTP_PPID;
char *addr_buf = (char *) (init + 1); // address after sctp_init ITTI message end, allocated above
init->bind_address = addr_buf;
memcpy(addr_buf, my_addr, addr_len);
itti_send_msg_to_task(TASK_SCTP, instance, message_p);
}
void e1_task_handle_sctp_association_ind(E1_t type, instance_t instance, sctp_new_association_ind_t *sctp_new_ind)
{
if (!getCxtE1(instance))
createE1inst(type, instance, 0, NULL, NULL);
e1ap_upcp_inst_t *inst = getCxtE1(instance);
inst->sockState = SCTP_STATE_ESTABLISHED;
if (type == UPtype)
inst->cuup.assoc_id = sctp_new_ind->assoc_id;
}
/**
* @brief Handle the timer triggered by a connection loss with CU-CP
* it uses a stored network configuration and send a new SCTP association request
*/
static void e1apHandleTimer(instance_t myInstance)
{
LOG_W(E1AP, "Try to reconnect to CP\n");
if (getCxtE1(myInstance)->sockState != SCTP_STATE_ESTABLISHED)
e1_task_send_sctp_association_req(TASK_CUUP_E1, myInstance, &getCxtE1(myInstance)->net_config);
}
/**
* @brief E1AP Centralized Unit Control Plane (CU-CP) task function.
*
* This is the main task loop for the E1AP CUCP module:
* it listens for incoming messages from the Inter-Task Interface (ITTI)
* and calls the relevant handlers for each message type.
*
*/
void *E1AP_CUCP_task(void *arg)
{
LOG_I(E1AP, "Starting E1AP at CU CP\n");
MessageDef *msg = NULL;
e1ap_common_init();
int result;
while (1) {
itti_receive_msg(TASK_CUCP_E1, &msg);
instance_t myInstance = ITTI_MSG_DESTINATION_INSTANCE(msg);
const int msgType = ITTI_MSG_ID(msg);
LOG_D(E1AP, "CUCP received %s for instance %ld\n", messages_info[msgType].name, myInstance);
sctp_assoc_t assoc_id = msg->ittiMsgHeader.originInstance;
switch (ITTI_MSG_ID(msg)) {
case SCTP_NEW_ASSOCIATION_IND:
e1_task_handle_sctp_association_ind(CPtype, ITTI_MSG_ORIGIN_INSTANCE(msg), &msg->ittiMsg.sctp_new_association_ind);
break;
case SCTP_NEW_ASSOCIATION_RESP:
e1_task_handle_sctp_association_resp(CPtype, ITTI_MSG_ORIGIN_INSTANCE(msg), &msg->ittiMsg.sctp_new_association_resp);
break;
case E1AP_REGISTER_REQ: {
// note: we use E1AP_REGISTER_REQ only to set up sockets, the
// E1AP_SETUP_REQ is not used and comes through the socket from the
// CU-UP later!
e1ap_net_config_t *nc = &E1AP_REGISTER_REQ(msg).net_config;
AssertFatal(nc->CUCP_e1_ip_address.ipv4 != 0, "No IPv4 address configured\n");
cucp_task_send_sctp_init_req(0, nc->CUCP_e1_ip_address.ipv4_address);
} break;
case E1AP_SETUP_REQ:
AssertFatal(false, "should not receive E1AP_SETUP_REQ in CU-CP!\n");
break;
case SCTP_DATA_IND:
e1_task_handle_sctp_data_ind(myInstance, &msg->ittiMsg.sctp_data_ind);
break;
case E1AP_SETUP_RESP:
e1ap_send_SETUP_RESPONSE(assoc_id, &E1AP_SETUP_RESP(msg));
free_e1ap_cuup_setup_response(&E1AP_SETUP_RESP(msg));
break;
case E1AP_SETUP_FAIL:
e1apCUCP_send_SETUP_FAILURE(assoc_id, &E1AP_SETUP_FAIL(msg));
free_e1ap_cuup_setup_failure(&E1AP_SETUP_FAIL(msg));
break;
case E1AP_BEARER_CONTEXT_SETUP_REQ:
e1apCUCP_send_BEARER_CONTEXT_SETUP_REQUEST(assoc_id, &E1AP_BEARER_CONTEXT_SETUP_REQ(msg));
free_e1ap_context_setup_request(&E1AP_BEARER_CONTEXT_SETUP_REQ(msg));
break;
case E1AP_BEARER_CONTEXT_MODIFICATION_REQ:
e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(assoc_id, &E1AP_BEARER_CONTEXT_MODIFICATION_REQ(msg));
free_e1ap_context_mod_request(&E1AP_BEARER_CONTEXT_MODIFICATION_REQ(msg));
break;
case E1AP_BEARER_CONTEXT_RELEASE_CMD:
e1apCUCP_send_BEARER_CONTEXT_RELEASE_COMMAND(assoc_id, &E1AP_BEARER_CONTEXT_RELEASE_CMD(msg));
free_e1_bearer_context_release_command(&E1AP_BEARER_CONTEXT_RELEASE_CMD(msg));
break;
default:
LOG_E(E1AP, "Unknown message received in TASK_CUCP_E1\n");
break;
}
result = itti_free(ITTI_MSG_ORIGIN_ID(msg), msg);
AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d) in E1AP_CUCP_task!\n", result);
msg = NULL;
}
}
/**
* @brief E1AP Centralized Unit User Plane (CU-UP) task function.
*
* This is the main task loop for the E1AP CUUP module:
* it listens for incoming messages from the Inter-Task Interface (ITTI)
* and calls the relevant handlers for each message type.
*
*/
void *E1AP_CUUP_task(void *arg)
{
LOG_I(E1AP, "Starting E1AP at CU UP\n");
e1ap_common_init();
int result;
// SCTP
while (1) {
MessageDef *msg = NULL;
itti_receive_msg(TASK_CUUP_E1, &msg);
const instance_t myInstance = ITTI_MSG_DESTINATION_INSTANCE(msg);
const int msgType = ITTI_MSG_ID(msg);
LOG_D(E1AP, "CUUP received %s for instance %ld\n", messages_info[msgType].name, myInstance);
switch (msgType) {
case E1AP_REGISTER_REQ: {
/* E1AP Register Request triggered at startup
create a new E1 instance and send the first association request */
e1ap_register_req_t *reg_req = &E1AP_REGISTER_REQ(msg);
createE1inst(UPtype, myInstance, reg_req->gnb_id, &reg_req->net_config, &reg_req->setup_req);
e1_task_send_sctp_association_req(TASK_CUUP_E1, myInstance, &reg_req->net_config);
} break;
case SCTP_NEW_ASSOCIATION_RESP:
e1_task_handle_sctp_association_resp(UPtype, myInstance, &msg->ittiMsg.sctp_new_association_resp);
if (getCxtE1(myInstance)->sockState == SCTP_STATE_ESTABLISHED)
LOG_A(E1AP, "E1 connection established (%s)\n", sctp_state_s[getCxtE1(myInstance)->sockState]);
break;
case SCTP_DATA_IND:
e1_task_handle_sctp_data_ind(myInstance, &msg->ittiMsg.sctp_data_ind);
break;
case TIMER_HAS_EXPIRED:
// Timer triggered by a connection loss with CU-CP
e1apHandleTimer(myInstance);
break;
case E1AP_BEARER_CONTEXT_SETUP_RESP: {
const e1ap_bearer_setup_resp_t *resp = &E1AP_BEARER_CONTEXT_SETUP_RESP(msg);
const e1ap_upcp_inst_t *inst = getCxtE1(myInstance);
AssertFatal(inst, "no E1 instance found for instance %ld\n", myInstance);
e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(inst->cuup.assoc_id, resp);
free_e1ap_context_setup_response(resp);
} break;
case E1AP_BEARER_CONTEXT_SETUP_FAILURE: {
const e1ap_bearer_context_setup_failure_t *fail = &E1AP_BEARER_CONTEXT_SETUP_FAILURE(msg);
const e1ap_upcp_inst_t *inst = getCxtE1(myInstance);
AssertFatal(inst, "no E1 instance found for instance %ld\n", myInstance);
e1apCUUP_send_BEARER_CONTEXT_SETUP_FAILURE(inst->cuup.assoc_id, fail);
free_e1_bearer_context_setup_failure(fail);
} break;
case E1AP_BEARER_CONTEXT_MODIFICATION_RESP: {
const e1ap_bearer_modif_resp_t *resp = &E1AP_BEARER_CONTEXT_MODIFICATION_RESP(msg);
const e1ap_upcp_inst_t *inst = getCxtE1(myInstance);
AssertFatal(inst, "no E1 instance found for instance %ld\n", myInstance);
e1apCUUP_send_BEARER_CONTEXT_MODIFICATION_RESPONSE(inst->cuup.assoc_id, resp);
free_e1ap_context_mod_response(resp);
} break;
case E1AP_BEARER_CONTEXT_MODIFICATION_FAIL: {
const e1ap_bearer_context_mod_failure_t *fail = &E1AP_BEARER_CONTEXT_MODIFICATION_FAIL(msg);
const e1ap_upcp_inst_t *inst = getCxtE1(myInstance);
AssertFatal(inst, "no E1 instance found for instance %ld\n", myInstance);
e1apCUUP_send_BEARER_CONTEXT_MODIFICATION_FAILURE(inst->cuup.assoc_id, fail);
free_E1_bearer_context_mod_failure(fail);
} break;
case E1AP_BEARER_CONTEXT_RELEASE_CPLT: {
const e1ap_bearer_release_cplt_t *cplt = &E1AP_BEARER_CONTEXT_RELEASE_CPLT(msg);
const e1ap_upcp_inst_t *inst = getCxtE1(myInstance);
AssertFatal(inst, "no E1 instance found for instance %ld\n", myInstance);
e1apCUUP_send_BEARER_CONTEXT_RELEASE_COMPLETE(inst->cuup.assoc_id, cplt);
} break;
default:
LOG_E(E1AP, "Unknown message received in TASK_CUUP_E1\n");
break;
}
result = itti_free(ITTI_MSG_ORIGIN_ID(msg), msg);
AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d) in E1AP_CUUP_task!\n", result);
msg = NULL;
}
}