Merge remote-tracking branch 'origin/e1-setup-encdec-tests' into integration_2025_w04 (!3152)
E1 Setup enc/dec library and unit test This MR is adding a library for E1 Setup enc/dec functions: - E1 CU-UP Setup Request - E1 CU-UP Setup Response - E1 Setup Failure and relevant unit tests
This commit is contained in:
@@ -26,11 +26,11 @@ MESSAGE_DEF(E1AP_REGISTER_REQ, MESSAGE_PRIORITY_MED, e1ap_register_req_t, e1ap_r
|
||||
MESSAGE_DEF(E1AP_LOST_CONNECTION, MESSAGE_PRIORITY_MED, e1ap_lost_connection_t, e1ap_lost_connection)
|
||||
|
||||
/* E1AP Interface Management Messages */
|
||||
/* E1AP Setup Request: gNB-CU-UP -> gNB-CU-CP */
|
||||
/* GNB-CU-UP E1 Setup Request: gNB-CU-UP -> gNB-CU-CP */
|
||||
MESSAGE_DEF(E1AP_SETUP_REQ , MESSAGE_PRIORITY_MED , e1ap_setup_req_t , e1ap_setup_req)
|
||||
/* E1AP Setup Response: gNB-CU-CP -> gNB-CU-UP */
|
||||
/* GNB-CU-UP E1 Setup Response: gNB-CU-CP -> gNB-CU-UP */
|
||||
MESSAGE_DEF(E1AP_SETUP_RESP , MESSAGE_PRIORITY_MED, e1ap_setup_resp_t , e1ap_setup_resp)
|
||||
/* E1AP Setup Failure: gNB-CU-CP -> gNB-CU-UP */
|
||||
/* GNB-CU-UP E1 Setup Failure: gNB-CU-CP -> gNB-CU-UP */
|
||||
MESSAGE_DEF(E1AP_SETUP_FAIL, MESSAGE_PRIORITY_MED, e1ap_setup_fail_t, e1ap_setup_fail)
|
||||
|
||||
/* E1AP Bearer Context Management Procedures */
|
||||
|
||||
@@ -40,6 +40,9 @@
|
||||
#define E1AP_MAX_NUM_DRBS 32
|
||||
#define E1AP_MAX_NUM_UP_PARAM 4
|
||||
#define E1AP_SECURITY_KEY_SIZE 16 // keys have 128 bits length
|
||||
#define E1AP_MAX_TL_ADDRESSES 16
|
||||
#define E1AP_MAX_GTP_TL_ADDRESSES 16
|
||||
#define E1AP_MAX_NUM_ERRORS 256
|
||||
|
||||
#define E1AP_REGISTER_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_register_req
|
||||
#define E1AP_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_setup_req
|
||||
@@ -55,6 +58,80 @@
|
||||
|
||||
typedef net_ip_address_t e1ap_net_ip_address_t;
|
||||
|
||||
typedef enum {
|
||||
E1AP_RADIO_CAUSE_UNSPECIFIED = 0,
|
||||
E1AP_RADIO_CAUSE_UNKNOWN_ALREADY_ALLOCATED_GNB_CU_CP_UE_E1AP_ID,
|
||||
E1AP_RADIO_CAUSE_UNKNOWN_ALREADY_ALLOCATED_GNB_CU_UP_UE_E1AP_ID,
|
||||
E1AP_RADIO_CAUSE_UNKNOWN_INCONSISTENT_PAIR_UE_E1AP_ID,
|
||||
E1AP_RADIO_CAUSE_INTERACTION_WITH_OTHER_PROCEDURE,
|
||||
E1AP_RADIO_CAUSE_PDCP_COUNT_WRAP_AROUND,
|
||||
E1AP_RADIO_CAUSE_UNSUPPORTED_QCI_VALUE,
|
||||
E1AP_RADIO_CAUSE_UNSUPPORTED_5QI_VALUE,
|
||||
E1AP_RADIO_CAUSE_ENCRYPTION_ALGORITHMS_NOT_SUPPORTED,
|
||||
E1AP_RADIO_CAUSE_INTEGRITY_PROTECTION_ALGORITHMS_NOT_SUPPORTED,
|
||||
E1AP_RADIO_CAUSE_UP_INTEGRITY_PROTECTION_NOT_POSSIBLE,
|
||||
E1AP_RADIO_CAUSE_UP_CONFIDENTIALITY_PROTECTION_NOT_POSSIBLE,
|
||||
E1AP_RADIO_CAUSE_MULTIPLE_PDU_SESSION_ID_INSTANCES,
|
||||
E1AP_RADIO_CAUSE_UNKNOWN_PDU_SESSION_ID,
|
||||
E1AP_RADIO_CAUSE_MULTIPLE_QOS_FLOW_ID_INSTANCES,
|
||||
E1AP_RADIO_CAUSE_UNKNOWN_QOS_FLOW_ID,
|
||||
E1AP_RADIO_CAUSE_MULTIPLE_DRB_ID_INSTANCES,
|
||||
E1AP_RADIO_CAUSE_UNKNOWN_DRB_ID,
|
||||
E1AP_RADIO_CAUSE_INVALID_QOS_COMBINATION,
|
||||
E1AP_RADIO_CAUSE_PROCEDURE_CANCELLED,
|
||||
E1AP_RADIO_CAUSE_NORMAL_RELEASE,
|
||||
E1AP_RADIO_CAUSE_NO_RADIO_RESOURCES_AVAILABLE,
|
||||
E1AP_RADIO_CAUSE_ACTION_DESIRABLE_FOR_RADIO_REASONS,
|
||||
E1AP_RADIO_CAUSE_RESOURCES_NOT_AVAILABLE_FOR_SLICE,
|
||||
E1AP_RADIO_CAUSE_PDCP_CONFIG_NOT_SUPPORTED,
|
||||
E1AP_RADIO_CAUSE_UE_DL_MAX_INTEGRITY_PROTECTED_DATA_RATE_REASON,
|
||||
E1AP_RADIO_CAUSE_UP_INTEGRITY_PROTECTION_FAILURE,
|
||||
E1AP_RADIO_CAUSE_RELEASE_DUE_TO_PREEMPTION,
|
||||
E1AP_RADIO_CAUSE_RSN_NOT_AVAILABLE_FOR_UP,
|
||||
E1AP_RADIO_CAUSE_NPN_NOT_SUPPORTED,
|
||||
E1AP_RADIO_CAUSE_OTHER
|
||||
} e1ap_cause_radio_t;
|
||||
|
||||
typedef enum {
|
||||
E1AP_TRANSPORT_CAUSE_UNSPECIFIED = 0,
|
||||
E1AP_TRANSPORT_CAUSE_RESOURCE_UNAVAILABLE,
|
||||
E1AP_TRANSPORT_CAUSE_UNKNOWN_TNL_ADDRESS_FOR_IAB,
|
||||
E1AP_TRANSPORT_CAUSE_OTHER
|
||||
} e1ap_cause_transport_t;
|
||||
|
||||
typedef enum {
|
||||
E1AP_PROTOCOL_CAUSE_TRANSFER_SYNTAX_ERROR = 0,
|
||||
E1AP_PROTOCOL_CAUSE_ABSTRACT_SYNTAX_ERROR_REJECT,
|
||||
E1AP_PROTOCOL_CAUSE_ABSTRACT_SYNTAX_ERROR_IGNORE_NOTIFY,
|
||||
E1AP_PROTOCOL_CAUSE_MESSAGE_NOT_COMPATIBLE_WITH_RECEIVER_STATE,
|
||||
E1AP_PROTOCOL_CAUSE_SEMANTIC_ERROR,
|
||||
E1AP_PROTOCOL_CAUSE_ABSTRACT_SYNTAX_ERROR_FALSELY_CONSTRUCTED_MESSAGE,
|
||||
E1AP_PROTOCOL_CAUSE_UNSPECIFIED,
|
||||
E1AP_PROTOCOL_CAUSE_OTHER
|
||||
} e1ap_cause_protocol_t;
|
||||
|
||||
typedef enum {
|
||||
E1AP_MISC_CAUSE_CONTROL_PROCESSING_OVERLOAD,
|
||||
E1AP_MISC_CAUSE_NOT_ENOUGH_USER_PLANE_PROCESSING_RESOURCES,
|
||||
E1AP_MISC_CAUSE_HARDWARE_FAILURE,
|
||||
E1AP_MISC_CAUSE_OM_INTERVENTION,
|
||||
E1AP_MISC_CAUSE_UNSPECIFIED,
|
||||
E1AP_MISC_CAUSE_OTHER
|
||||
} e1ap_cause_misc_t;
|
||||
|
||||
typedef enum e1ap_cause_group_e {
|
||||
E1AP_CAUSE_NOTHING,
|
||||
E1AP_CAUSE_RADIO_NETWORK,
|
||||
E1AP_CAUSE_TRANSPORT,
|
||||
E1AP_CAUSE_PROTOCOL,
|
||||
E1AP_CAUSE_MISC
|
||||
} e1ap_cause_group_t;
|
||||
|
||||
typedef struct e1ap_cause_s {
|
||||
e1ap_cause_group_t type;
|
||||
uint8_t value;
|
||||
} e1ap_cause_t;
|
||||
|
||||
typedef enum BEARER_CONTEXT_STATUS_e {
|
||||
BEARER_ACTIVE = 0,
|
||||
BEARER_SUSPEND,
|
||||
@@ -72,12 +149,59 @@ typedef enum cell_group_id_e {
|
||||
SCG,
|
||||
} cell_group_id_t;
|
||||
|
||||
typedef enum CN_Support_e {
|
||||
cn_support_EPC = 0,
|
||||
cn_support_5GC,
|
||||
} cn_Support_t;
|
||||
|
||||
typedef struct PLMN_ID_s {
|
||||
int mcc;
|
||||
int mnc;
|
||||
int mnc_digit_length;
|
||||
} PLMN_ID_t;
|
||||
|
||||
typedef enum { CRITICALITY_REJECT = 0, CRITICALITY_IGNORE, CRITICALITY_NOTIFY } criticality_t;
|
||||
|
||||
typedef enum {
|
||||
ERROR_TYPE_NOT_UNDERSTOOD = 0,
|
||||
ERROR_TYPE_MISSING,
|
||||
} error_type_t;
|
||||
|
||||
typedef enum {
|
||||
TRIGGERING_MSG_INITIATING = 0,
|
||||
TRIGGERING_MSG_SUCCESSFUL_OUTCOME,
|
||||
TRIGGERING_MSG_UNSUCCESSFUL_OUTCOME
|
||||
} triggering_msg_t;
|
||||
|
||||
typedef struct criticality_diagnostics_ie_s {
|
||||
criticality_t criticality;
|
||||
int ie_id;
|
||||
error_type_t error_type;
|
||||
} criticality_diagnostics_ie_t;
|
||||
|
||||
typedef struct criticality_diagnostics_s {
|
||||
int *procedure_code;
|
||||
triggering_msg_t *triggering_msg;
|
||||
criticality_t *procedure_criticality;
|
||||
int num_errors;
|
||||
criticality_diagnostics_ie_t errors[E1AP_MAX_NUM_ERRORS];
|
||||
} criticality_diagnostics_t;
|
||||
|
||||
typedef struct {
|
||||
in_addr_t ipsec_tl_address;
|
||||
uint8_t num_gtp_tl_addresses;
|
||||
in_addr_t gtp_tl_addresses[E1AP_MAX_GTP_TL_ADDRESSES];
|
||||
} tnl_address_info_item_t;
|
||||
|
||||
typedef struct {
|
||||
// Transport UP LayerAddresses Info to Add List
|
||||
tnl_address_info_item_t addresses_to_add[E1AP_MAX_TL_ADDRESSES];
|
||||
uint8_t num_addresses_to_add;
|
||||
// Transport UP Layer Addresses Info to Remove List
|
||||
tnl_address_info_item_t addresses_to_remove[E1AP_MAX_TL_ADDRESSES];
|
||||
uint8_t num_addresses_to_remove;
|
||||
} tnl_address_info_t;
|
||||
|
||||
typedef nssai_t e1ap_nssai_t;
|
||||
|
||||
typedef struct e1ap_net_config_t {
|
||||
@@ -91,11 +215,14 @@ typedef struct e1ap_net_config_t {
|
||||
uint16_t remotePortN3;
|
||||
} e1ap_net_config_t;
|
||||
|
||||
/* GNB-CU-UP E1 Setup Request */
|
||||
typedef struct e1ap_setup_req_s {
|
||||
uint64_t gNB_cu_up_id;
|
||||
char * gNB_cu_up_name;
|
||||
uint64_t transac_id;
|
||||
int supported_plmns;
|
||||
// CN Support
|
||||
cn_Support_t cn_support;
|
||||
struct {
|
||||
PLMN_ID_t id;
|
||||
int supported_slices;
|
||||
@@ -103,6 +230,11 @@ typedef struct e1ap_setup_req_s {
|
||||
} plmn[E1AP_MAX_NUM_PLMNS];
|
||||
} e1ap_setup_req_t;
|
||||
|
||||
typedef struct e1ap_cucp_setup_req_s {
|
||||
char* gNB_cu_cp_name;
|
||||
uint64_t transac_id;
|
||||
} e1ap_cucp_setup_req_t;
|
||||
|
||||
typedef struct e1ap_register_req_t {
|
||||
e1ap_setup_req_t setup_req;
|
||||
e1ap_net_config_t net_config;
|
||||
@@ -110,12 +242,20 @@ typedef struct e1ap_register_req_t {
|
||||
} e1ap_register_req_t;
|
||||
|
||||
typedef struct e1ap_setup_resp_s {
|
||||
// Transaction ID
|
||||
long transac_id;
|
||||
// gNB-CU-CP Name
|
||||
char* gNB_cu_cp_name;
|
||||
// Transport Network Layer Address Info
|
||||
tnl_address_info_t* tnla_info;
|
||||
} e1ap_setup_resp_t;
|
||||
|
||||
/* E1AP Setup Failure */
|
||||
typedef struct e1ap_setup_fail_s {
|
||||
long transac_id;
|
||||
e1ap_cause_t cause;
|
||||
long *time_to_wait;
|
||||
criticality_diagnostics_t *crit_diag;
|
||||
} e1ap_setup_fail_t;
|
||||
|
||||
typedef struct up_params_s {
|
||||
|
||||
+35
-234
@@ -34,6 +34,7 @@
|
||||
#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);
|
||||
@@ -161,221 +162,20 @@ int e1ap_send_ERROR_INDICATION(instance_t instance, E1AP_ErrorIndication_t *Erro
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
E1 Setup: can be sent on both ways, to be refined
|
||||
*/
|
||||
static void fill_SETUP_REQUEST(e1ap_setup_req_t *setup, E1AP_E1AP_PDU_t *pdu)
|
||||
{
|
||||
/* Create */
|
||||
/* 0. pdu Type */
|
||||
pdu->present = E1AP_E1AP_PDU_PR_initiatingMessage;
|
||||
asn1cCalloc(pdu->choice.initiatingMessage, initMsg);
|
||||
initMsg->procedureCode = E1AP_ProcedureCode_id_gNB_CU_UP_E1Setup;
|
||||
initMsg->criticality = E1AP_Criticality_reject;
|
||||
initMsg->value.present = E1AP_InitiatingMessage__value_PR_GNB_CU_UP_E1SetupRequest;
|
||||
E1AP_GNB_CU_UP_E1SetupRequest_t *e1SetupUP = &initMsg->value.choice.GNB_CU_UP_E1SetupRequest;
|
||||
/* mandatory */
|
||||
/* c1. Transaction ID (integer value) */
|
||||
asn1cSequenceAdd(e1SetupUP->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ieC1);
|
||||
ieC1->id = E1AP_ProtocolIE_ID_id_TransactionID;
|
||||
ieC1->criticality = E1AP_Criticality_reject;
|
||||
ieC1->value.present = E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_TransactionID;
|
||||
setup->transac_id = E1AP_get_next_transaction_identifier();
|
||||
ieC1->value.choice.TransactionID = setup->transac_id;
|
||||
LOG_D(E1AP, "Transaction ID of setup request %ld\n", setup->transac_id);
|
||||
/* mandatory */
|
||||
/* c2. GNB_CU_ID (integer value) */
|
||||
asn1cSequenceAdd(e1SetupUP->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ieC2);
|
||||
ieC2->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_ID;
|
||||
ieC2->criticality = E1AP_Criticality_reject;
|
||||
ieC2->value.present = E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_GNB_CU_UP_ID;
|
||||
asn_int642INTEGER(&ieC2->value.choice.GNB_CU_UP_ID, setup->gNB_cu_up_id);
|
||||
|
||||
/* optional */
|
||||
if (setup->gNB_cu_up_name) {
|
||||
asn1cSequenceAdd(e1SetupUP->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ieC3);
|
||||
ieC3->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_Name;
|
||||
ieC3->criticality = E1AP_Criticality_ignore;
|
||||
ieC3->value.present = E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_GNB_CU_UP_Name;
|
||||
OCTET_STRING_fromBuf(&ieC3->value.choice.GNB_CU_UP_Name, setup->gNB_cu_up_name, strlen(setup->gNB_cu_up_name));
|
||||
}
|
||||
|
||||
/* mandatory */
|
||||
/* c4. CN Support */
|
||||
asn1cSequenceAdd(e1SetupUP->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ieC4);
|
||||
ieC4->id = E1AP_ProtocolIE_ID_id_CNSupport;
|
||||
ieC4->criticality = E1AP_Criticality_reject;
|
||||
ieC4->value.present = E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_CNSupport;
|
||||
ieC4->value.choice.CNSupport = E1AP_CNSupport_c_5gc; /* only 5GC supported */
|
||||
|
||||
/* mandatory */
|
||||
/* c5. Supported PLMNs */
|
||||
asn1cSequenceAdd(e1SetupUP->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ieC5);
|
||||
ieC5->id = E1AP_ProtocolIE_ID_id_SupportedPLMNs;
|
||||
ieC5->criticality = E1AP_Criticality_reject;
|
||||
ieC5->value.present = E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_SupportedPLMNs_List;
|
||||
|
||||
int numSupportedPLMNs = setup->supported_plmns;
|
||||
|
||||
for (int i = 0; i < numSupportedPLMNs; i++) {
|
||||
asn1cSequenceAdd(ieC5->value.choice.SupportedPLMNs_List.list, E1AP_SupportedPLMNs_Item_t, supportedPLMN);
|
||||
/* 5.1 PLMN Identity */
|
||||
PLMN_ID_t *id = &setup->plmn[i].id;
|
||||
MCC_MNC_TO_PLMNID(id->mcc, id->mnc, id->mnc_digit_length, &supportedPLMN->pLMN_Identity);
|
||||
|
||||
int n = setup->plmn[i].supported_slices;
|
||||
if (setup->plmn[i].slice != NULL && n > 0) {
|
||||
supportedPLMN->slice_Support_List = calloc(1, sizeof(*supportedPLMN->slice_Support_List));
|
||||
AssertFatal(supportedPLMN->slice_Support_List != NULL, "out of memory\n");
|
||||
for (int s = 0; s < n; ++s) {
|
||||
asn1cSequenceAdd(supportedPLMN->slice_Support_List->list, E1AP_Slice_Support_Item_t, slice);
|
||||
e1ap_nssai_t *nssai = &setup->plmn[i].slice[s];
|
||||
INT8_TO_OCTET_STRING(nssai->sst, &slice->sNSSAI.sST);
|
||||
if (nssai->sd != 0xffffff) {
|
||||
slice->sNSSAI.sD = malloc(sizeof(*slice->sNSSAI.sD));
|
||||
AssertFatal(slice->sNSSAI.sD != NULL, "out of memory\n");
|
||||
INT24_TO_OCTET_STRING(nssai->sd, slice->sNSSAI.sD);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void fill_SETUP_RESPONSE(const e1ap_setup_resp_t *e1ap_setup_resp, E1AP_E1AP_PDU_t *pdu)
|
||||
{
|
||||
/* Create */
|
||||
/* 0. pdu Type */
|
||||
pdu->present = E1AP_E1AP_PDU_PR_successfulOutcome;
|
||||
asn1cCalloc(pdu->choice.successfulOutcome, initMsg);
|
||||
initMsg->procedureCode = E1AP_ProcedureCode_id_gNB_CU_UP_E1Setup;
|
||||
initMsg->criticality = E1AP_Criticality_reject;
|
||||
initMsg->value.present = E1AP_SuccessfulOutcome__value_PR_GNB_CU_UP_E1SetupResponse;
|
||||
E1AP_GNB_CU_UP_E1SetupResponse_t *out = &pdu->choice.successfulOutcome->value.choice.GNB_CU_UP_E1SetupResponse;
|
||||
/* mandatory */
|
||||
/* c1. Transaction ID (integer value) */
|
||||
asn1cSequenceAdd(out->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupResponseIEs_t, ieC1);
|
||||
ieC1->id = E1AP_ProtocolIE_ID_id_TransactionID;
|
||||
ieC1->criticality = E1AP_Criticality_reject;
|
||||
ieC1->value.present = E1AP_GNB_CU_UP_E1SetupResponseIEs__value_PR_TransactionID;
|
||||
ieC1->value.choice.TransactionID = e1ap_setup_resp->transac_id;
|
||||
}
|
||||
|
||||
void e1ap_send_SETUP_RESPONSE(sctp_assoc_t assoc_id, const e1ap_setup_resp_t *e1ap_setup_resp)
|
||||
{
|
||||
E1AP_E1AP_PDU_t pdu = {0};
|
||||
fill_SETUP_RESPONSE(e1ap_setup_resp, &pdu);
|
||||
e1ap_encode_send(CPtype, assoc_id, &pdu, 0, __func__);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief E1 Setup Failure ASN1 messager builder
|
||||
* @ref 9.2.1.6 GNB-CU-UP E1 SETUP FAILURE of 3GPP TS 38.463
|
||||
*/
|
||||
static void fill_SETUP_FAILURE(long transac_id, E1AP_E1AP_PDU_t *pdu)
|
||||
{
|
||||
/* Create */
|
||||
/* 0. pdu Type */
|
||||
pdu->present = E1AP_E1AP_PDU_PR_unsuccessfulOutcome;
|
||||
asn1cCalloc(pdu->choice.unsuccessfulOutcome, initMsg);
|
||||
/* mandatory */
|
||||
/**
|
||||
* Message Type IE
|
||||
* - procedureCode (integer)
|
||||
* - Type of Message (choice)
|
||||
* @ref clause 9.3.1.1 of 3GPP TS 38.463
|
||||
*/
|
||||
initMsg->procedureCode = E1AP_ProcedureCode_id_gNB_CU_UP_E1Setup;
|
||||
initMsg->criticality = E1AP_Criticality_reject;
|
||||
initMsg->value.present = E1AP_UnsuccessfulOutcome__value_PR_GNB_CU_UP_E1SetupFailure;
|
||||
E1AP_GNB_CU_UP_E1SetupFailure_t *out = &pdu->choice.unsuccessfulOutcome->value.choice.GNB_CU_UP_E1SetupFailure;
|
||||
/* mandatory */
|
||||
/* c1. Transaction ID (integer value), clause 9.3.1.53 of 3GPP TS 38.463 */
|
||||
asn1cSequenceAdd(out->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupFailureIEs_t, ieC1);
|
||||
ieC1->id = E1AP_ProtocolIE_ID_id_TransactionID;
|
||||
ieC1->criticality = E1AP_Criticality_reject;
|
||||
ieC1->value.present = E1AP_GNB_CU_UP_E1SetupFailureIEs__value_PR_TransactionID;
|
||||
ieC1->value.choice.TransactionID = transac_id;
|
||||
/* mandatory */
|
||||
/* c2. cause (integer value), clause 9.3.1.2 of 3GPP TS 38.463 */
|
||||
asn1cSequenceAdd(out->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupFailureIEs_t, ieC2);
|
||||
ieC2->id = E1AP_ProtocolIE_ID_id_Cause;
|
||||
ieC2->criticality = E1AP_Criticality_ignore;
|
||||
ieC2->value.present = E1AP_GNB_CU_UP_E1SetupFailureIEs__value_PR_Cause;
|
||||
ieC2->value.choice.Cause.present = E1AP_Cause_PR_radioNetwork; //choose this accordingly
|
||||
ieC2->value.choice.Cause.choice.radioNetwork = E1AP_CauseRadioNetwork_unspecified;
|
||||
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
|
||||
*/
|
||||
void e1apCUCP_send_SETUP_FAILURE(sctp_assoc_t assoc_id, long transac_id)
|
||||
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", transac_id);
|
||||
E1AP_E1AP_PDU_t pdu = {0};
|
||||
fill_SETUP_FAILURE(transac_id, &pdu);
|
||||
e1ap_encode_send(CPtype, assoc_id, &pdu, 0, __func__);
|
||||
}
|
||||
|
||||
static void extract_SETUP_REQUEST(const E1AP_E1AP_PDU_t *pdu, e1ap_setup_req_t *req)
|
||||
{
|
||||
E1AP_GNB_CU_UP_E1SetupRequestIEs_t *ie;
|
||||
E1AP_GNB_CU_UP_E1SetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.GNB_CU_UP_E1SetupRequest;
|
||||
|
||||
/* transac_id */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ie, in, E1AP_ProtocolIE_ID_id_TransactionID, true);
|
||||
req->transac_id = ie->value.choice.TransactionID;
|
||||
LOG_D(E1AP, "gNB CU UP E1 setup request transaction ID: %ld\n", req->transac_id);
|
||||
|
||||
/* gNB CU UP ID */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ie, in, E1AP_ProtocolIE_ID_id_gNB_CU_UP_ID, true);
|
||||
asn_INTEGER2ulong(&ie->value.choice.GNB_CU_UP_ID, &req->gNB_cu_up_id);
|
||||
LOG_D(E1AP, "gNB CU UP ID: %ld\n", req->gNB_cu_up_id);
|
||||
|
||||
/* gNB CU UP name */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ie, in, E1AP_ProtocolIE_ID_id_gNB_CU_UP_Name, false);
|
||||
req->gNB_cu_up_name = NULL;
|
||||
if (ie != NULL) {
|
||||
req->gNB_cu_up_name = calloc(ie->value.choice.GNB_CU_UP_Name.size + 1, sizeof(char));
|
||||
AssertFatal(req->gNB_cu_up_name != NULL, "out of memory\n");
|
||||
memcpy(req->gNB_cu_up_name, ie->value.choice.GNB_CU_UP_Name.buf, ie->value.choice.GNB_CU_UP_Name.size);
|
||||
LOG_D(E1AP, "req->gNB_cu_up_name %s\n", req->gNB_cu_up_name);
|
||||
}
|
||||
|
||||
/* CN Support */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ie, in, E1AP_ProtocolIE_ID_id_CNSupport, true);
|
||||
AssertFatal(ie->value.choice.CNSupport == E1AP_CNSupport_c_5gc, "only 5GC CN Support supported\n");
|
||||
|
||||
/* Supported PLMNs */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ie, in, E1AP_ProtocolIE_ID_id_SupportedPLMNs, true);
|
||||
req->supported_plmns = ie->value.choice.SupportedPLMNs_List.list.count;
|
||||
LOG_D(E1AP, "Number of supported PLMNs: %d\n", req->supported_plmns);
|
||||
|
||||
for (int i = 0; i < req->supported_plmns; i++) {
|
||||
E1AP_SupportedPLMNs_Item_t *supported_plmn_item =
|
||||
(E1AP_SupportedPLMNs_Item_t *)(ie->value.choice.SupportedPLMNs_List.list.array[i]);
|
||||
|
||||
/* PLMN Identity */
|
||||
PLMN_ID_t *id = &req->plmn[i].id;
|
||||
PLMNID_TO_MCC_MNC(&supported_plmn_item->pLMN_Identity, id->mcc, id->mnc, id->mnc_digit_length);
|
||||
LOG_D(E1AP, "MCC %d MNC %d\n", id->mcc, id->mnc);
|
||||
|
||||
/* NSSAI */
|
||||
if (supported_plmn_item->slice_Support_List) {
|
||||
int n = supported_plmn_item->slice_Support_List->list.count;
|
||||
req->plmn[i].supported_slices = n;
|
||||
req->plmn[i].slice = calloc(n, sizeof(*req->plmn[i].slice));
|
||||
AssertFatal(req->plmn[i].slice != NULL, "out of memory\n");
|
||||
for (int s = 0; s < n; ++s) {
|
||||
e1ap_nssai_t *slice = &req->plmn[i].slice[s];
|
||||
const E1AP_SNSSAI_t *es = &supported_plmn_item->slice_Support_List->list.array[s]->sNSSAI;
|
||||
OCTET_STRING_TO_INT8(&es->sST, slice->sst);
|
||||
slice->sd = 0xffffff;
|
||||
if (es->sD != NULL)
|
||||
OCTET_STRING_TO_INT24(es->sD, slice->sd);
|
||||
LOG_D(E1AP, "SST %d SD %06x\n", slice->sst, slice->sd);
|
||||
}
|
||||
}
|
||||
}
|
||||
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)
|
||||
@@ -383,13 +183,20 @@ int e1apCUCP_handle_SETUP_REQUEST(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst,
|
||||
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);
|
||||
extract_SETUP_REQUEST(pdu, &E1AP_SETUP_REQ(msg_p));
|
||||
// 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 {
|
||||
e1apCUCP_send_SETUP_FAILURE(assoc_id, E1AP_SETUP_REQ(msg_p).transac_id);
|
||||
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;
|
||||
}
|
||||
@@ -399,28 +206,19 @@ int e1apCUCP_handle_SETUP_REQUEST(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst,
|
||||
|
||||
int e1apCUUP_handle_SETUP_RESPONSE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu)
|
||||
{
|
||||
LOG_D(E1AP, "%s\n", __func__);
|
||||
DevAssert(pdu->present == E1AP_E1AP_PDU_PR_successfulOutcome);
|
||||
DevAssert(pdu->choice.successfulOutcome->procedureCode == E1AP_ProcedureCode_id_gNB_CU_UP_E1Setup);
|
||||
DevAssert(pdu->choice.successfulOutcome->criticality == E1AP_Criticality_reject);
|
||||
DevAssert(pdu->choice.successfulOutcome->value.present == E1AP_SuccessfulOutcome__value_PR_GNB_CU_UP_E1SetupResponse);
|
||||
const E1AP_GNB_CU_UP_E1SetupResponse_t *in = &pdu->choice.successfulOutcome->value.choice.GNB_CU_UP_E1SetupResponse;
|
||||
E1AP_GNB_CU_UP_E1SetupResponseIEs_t *ie;
|
||||
|
||||
/* transac_id */
|
||||
long transaction_id;
|
||||
// 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;
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(E1AP_GNB_CU_UP_E1SetupResponseIEs_t, ie, in, E1AP_ProtocolIE_ID_id_TransactionID, true);
|
||||
transaction_id = ie->value.choice.TransactionID;
|
||||
LOG_D(E1AP, "gNB CU UP E1 setup response transaction ID: %ld\n", transaction_id);
|
||||
|
||||
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);
|
||||
|
||||
/* do the required processing */
|
||||
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1276,9 +1074,10 @@ static void e1_task_send_sctp_association_req(long task_id, instance_t instance,
|
||||
|
||||
static void e1apCUUP_send_SETUP_REQUEST(sctp_assoc_t assoc_id, e1ap_setup_req_t *setup)
|
||||
{
|
||||
E1AP_E1AP_PDU_t pdu = {0};
|
||||
fill_SETUP_REQUEST(setup, &pdu);
|
||||
e1ap_encode_send(UPtype, assoc_id, &pdu, 0, __func__);
|
||||
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__);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1443,10 +1242,12 @@ void *E1AP_CUCP_task(void *arg)
|
||||
|
||||
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).transac_id);
|
||||
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:
|
||||
|
||||
@@ -101,6 +101,9 @@ MessageDef *RCconfig_NR_CU_E1(const E1_t *entity)
|
||||
if (*gnbParms[GNB_GNB_NAME_IDX].strptr)
|
||||
e1Setup->gNB_cu_up_name = *(gnbParms[GNB_GNB_NAME_IDX].strptr);
|
||||
|
||||
// Only 5GC supported
|
||||
e1Setup->cn_support = cn_support_5GC;
|
||||
|
||||
paramdef_t PLMNParams[] = GNBPLMNPARAMS_DESC;
|
||||
paramlist_def_t PLMNParamList = {GNB_CONFIG_STRING_PLMN_LIST, NULL, 0};
|
||||
/* map parameter checking array instances to parameter definition array instances */
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
add_library(e1ap_lib OBJECT
|
||||
e1ap_bearer_context_management.c
|
||||
e1ap_interface_management.c
|
||||
)
|
||||
|
||||
target_link_libraries(e1ap_lib PRIVATE asn1_e1ap)
|
||||
|
||||
@@ -0,0 +1,727 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "common/utils/assertions.h"
|
||||
#include "openair3/UTILS/conversions.h"
|
||||
#include "common/utils/oai_asn1.h"
|
||||
#include "common/utils/utils.h"
|
||||
|
||||
#include "e1ap_lib_common.h"
|
||||
#include "e1ap_lib_includes.h"
|
||||
#include "e1ap_messages_types.h"
|
||||
#include "e1ap_interface_management.h"
|
||||
|
||||
void encode_criticality_diagnostics(const criticality_diagnostics_t *msg, E1AP_CriticalityDiagnostics_t *out)
|
||||
{
|
||||
// Procedure Code (O)
|
||||
if (msg->procedure_code) {
|
||||
out->procedureCode = calloc_or_fail(1, sizeof(*out->procedureCode));
|
||||
*out->procedureCode = *msg->procedure_code;
|
||||
}
|
||||
// Triggering Message (O)
|
||||
if (msg->triggering_msg) {
|
||||
out->triggeringMessage = calloc_or_fail(1, sizeof(*out->triggeringMessage));
|
||||
*out->triggeringMessage = *msg->triggering_msg;
|
||||
}
|
||||
// Procedure Criticality (O)
|
||||
if (msg->procedure_criticality) {
|
||||
out->procedureCriticality = calloc_or_fail(1, sizeof(*out->procedureCriticality));
|
||||
*out->procedureCriticality = *msg->procedure_criticality;
|
||||
}
|
||||
for (int i = 0; i < msg->num_errors; i++) {
|
||||
out->iEsCriticalityDiagnostics = calloc_or_fail(1, sizeof(*out->iEsCriticalityDiagnostics));
|
||||
asn1cSequenceAdd(out->iEsCriticalityDiagnostics->list, struct E1AP_CriticalityDiagnostics_IE_List__Member, ieC0);
|
||||
ieC0->iE_ID = msg->errors[i].ie_id;
|
||||
ieC0->typeOfError = msg->errors[i].error_type;
|
||||
ieC0->iECriticality = msg->errors[i].criticality;
|
||||
}
|
||||
}
|
||||
|
||||
bool decode_criticality_diagnostics(const E1AP_CriticalityDiagnostics_t *in, criticality_diagnostics_t *out)
|
||||
{
|
||||
// Procedure Code (O)
|
||||
if (in->procedureCode) {
|
||||
out->procedure_code = malloc_or_fail(sizeof(*out->procedure_code));
|
||||
*out->procedure_code = *in->procedureCode;
|
||||
}
|
||||
// Triggering Message (O)
|
||||
if (in->triggeringMessage) {
|
||||
out->triggering_msg = malloc_or_fail(sizeof(*out->triggering_msg));
|
||||
*out->triggering_msg = *in->triggeringMessage;
|
||||
}
|
||||
// Procedure Criticality (O)
|
||||
if (in->procedureCriticality) {
|
||||
out->procedure_criticality = malloc_or_fail(sizeof(*out->procedure_criticality));
|
||||
*out->procedure_criticality = *in->procedureCriticality;
|
||||
}
|
||||
// Criticality Diagnostics IE list
|
||||
if (in->iEsCriticalityDiagnostics) {
|
||||
for (int i = 0; i < in->iEsCriticalityDiagnostics->list.count; i++) {
|
||||
struct E1AP_CriticalityDiagnostics_IE_List__Member *ie = in->iEsCriticalityDiagnostics->list.array[i];
|
||||
out->num_errors++;
|
||||
out->errors[i].ie_id = ie->iE_ID;
|
||||
out->errors[i].error_type = ie->typeOfError;
|
||||
out->errors[i].criticality = ie->iECriticality;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ====================================
|
||||
* GNB-CU-UP E1 SETUP REQUEST
|
||||
* ==================================== */
|
||||
|
||||
/**
|
||||
* @brief Encode GNB-CU-UP E1 Setup Request
|
||||
*/
|
||||
E1AP_E1AP_PDU_t *encode_e1ap_cuup_setup_request(const e1ap_setup_req_t *msg)
|
||||
{
|
||||
E1AP_E1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu));
|
||||
// Message Type (M)
|
||||
pdu->present = E1AP_E1AP_PDU_PR_initiatingMessage;
|
||||
asn1cCalloc(pdu->choice.initiatingMessage, m);
|
||||
m->procedureCode = E1AP_ProcedureCode_id_gNB_CU_UP_E1Setup;
|
||||
m->criticality = E1AP_Criticality_reject;
|
||||
m->value.present = E1AP_InitiatingMessage__value_PR_GNB_CU_UP_E1SetupRequest;
|
||||
E1AP_GNB_CU_UP_E1SetupRequest_t *e1SetupUP = &m->value.choice.GNB_CU_UP_E1SetupRequest;
|
||||
// Transaction ID (M)
|
||||
asn1cSequenceAdd(e1SetupUP->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ieC1);
|
||||
ieC1->id = E1AP_ProtocolIE_ID_id_TransactionID;
|
||||
ieC1->criticality = E1AP_Criticality_reject;
|
||||
ieC1->value.present = E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_TransactionID;
|
||||
ieC1->value.choice.TransactionID = msg->transac_id;
|
||||
// gNB-CU-UP ID (M)
|
||||
asn1cSequenceAdd(e1SetupUP->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ieC2);
|
||||
ieC2->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_ID;
|
||||
ieC2->criticality = E1AP_Criticality_reject;
|
||||
ieC2->value.present = E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_GNB_CU_UP_ID;
|
||||
asn_int642INTEGER(&ieC2->value.choice.GNB_CU_UP_ID, msg->gNB_cu_up_id);
|
||||
// gNB-CU-UP Name (O)
|
||||
if (msg->gNB_cu_up_name) {
|
||||
asn1cSequenceAdd(e1SetupUP->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ieC3);
|
||||
ieC3->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_Name;
|
||||
ieC3->criticality = E1AP_Criticality_ignore;
|
||||
ieC3->value.present = E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_GNB_CU_UP_Name;
|
||||
OCTET_STRING_fromBuf(&ieC3->value.choice.GNB_CU_UP_Name, msg->gNB_cu_up_name, strlen(msg->gNB_cu_up_name));
|
||||
}
|
||||
// CN Support (M)
|
||||
asn1cSequenceAdd(e1SetupUP->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ieC4);
|
||||
ieC4->id = E1AP_ProtocolIE_ID_id_CNSupport;
|
||||
ieC4->criticality = E1AP_Criticality_reject;
|
||||
ieC4->value.present = E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_CNSupport;
|
||||
DevAssert(msg->cn_support == cn_support_5GC); /* only 5GC supported */
|
||||
ieC4->value.choice.CNSupport = msg->cn_support == cn_support_5GC ? E1AP_CNSupport_c_5gc : E1AP_CNSupport_c_epc;
|
||||
// Supported PLMNs (1..<maxnoofSPLMNs>)
|
||||
asn1cSequenceAdd(e1SetupUP->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ieC5);
|
||||
ieC5->id = E1AP_ProtocolIE_ID_id_SupportedPLMNs;
|
||||
ieC5->criticality = E1AP_Criticality_reject;
|
||||
ieC5->value.present = E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_SupportedPLMNs_List;
|
||||
for (int i = 0; i < msg->supported_plmns; i++) {
|
||||
asn1cSequenceAdd(ieC5->value.choice.SupportedPLMNs_List.list, E1AP_SupportedPLMNs_Item_t, supportedPLMN);
|
||||
// PLMN Identity (M)
|
||||
const PLMN_ID_t *id = &msg->plmn[i].id;
|
||||
MCC_MNC_TO_PLMNID(id->mcc, id->mnc, id->mnc_digit_length, &supportedPLMN->pLMN_Identity);
|
||||
// Slice Support List (O)
|
||||
int n = msg->plmn[i].supported_slices;
|
||||
if (msg->plmn[i].slice != NULL && n > 0) {
|
||||
supportedPLMN->slice_Support_List = calloc_or_fail(1, sizeof(*supportedPLMN->slice_Support_List));
|
||||
for (int s = 0; s < n; ++s) {
|
||||
asn1cSequenceAdd(supportedPLMN->slice_Support_List->list, E1AP_Slice_Support_Item_t, slice);
|
||||
e1ap_nssai_t *nssai = &msg->plmn[i].slice[s];
|
||||
INT8_TO_OCTET_STRING(nssai->sst, &slice->sNSSAI.sST);
|
||||
if (nssai->sd != 0xffffff) {
|
||||
slice->sNSSAI.sD = malloc_or_fail(sizeof(*slice->sNSSAI.sD));
|
||||
INT24_TO_OCTET_STRING(nssai->sd, slice->sNSSAI.sD);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return pdu;
|
||||
}
|
||||
|
||||
bool decode_e1ap_cuup_setup_request(const E1AP_E1AP_PDU_t *pdu, e1ap_setup_req_t *out)
|
||||
{
|
||||
E1AP_GNB_CU_UP_E1SetupRequestIEs_t *ie;
|
||||
E1AP_GNB_CU_UP_E1SetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.GNB_CU_UP_E1SetupRequest;
|
||||
// Transaction ID (M)
|
||||
E1AP_LIB_FIND_IE(E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ie, in, E1AP_ProtocolIE_ID_id_TransactionID, true);
|
||||
// gNB-CU-UP ID (M)
|
||||
E1AP_LIB_FIND_IE(E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ie, in, E1AP_ProtocolIE_ID_id_gNB_CU_UP_ID, true);
|
||||
// CN Support (M)
|
||||
E1AP_LIB_FIND_IE(E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ie, in, E1AP_ProtocolIE_ID_id_CNSupport, true);
|
||||
// Supported PLMNs (1..<maxnoofSPLMNs>)
|
||||
E1AP_LIB_FIND_IE(E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ie, in, E1AP_ProtocolIE_ID_id_SupportedPLMNs, true);
|
||||
// Loop over all IEs
|
||||
for (int i = 0; i < in->protocolIEs.list.count; i++) {
|
||||
ie = in->protocolIEs.list.array[i];
|
||||
AssertFatal(ie != NULL, "in->protocolIEs.list.array[i] shall not be null");
|
||||
switch (ie->id) {
|
||||
case E1AP_ProtocolIE_ID_id_TransactionID:
|
||||
_E1_EQ_CHECK_INT(ie->value.present, E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_TransactionID);
|
||||
out->transac_id = ie->value.choice.TransactionID;
|
||||
break;
|
||||
case E1AP_ProtocolIE_ID_id_gNB_CU_UP_ID:
|
||||
_E1_EQ_CHECK_INT(ie->value.present, E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_GNB_CU_UP_ID);
|
||||
asn_INTEGER2ulong(&ie->value.choice.GNB_CU_UP_ID, &out->gNB_cu_up_id);
|
||||
break;
|
||||
case E1AP_ProtocolIE_ID_id_gNB_CU_UP_Name:
|
||||
_E1_EQ_CHECK_INT(ie->value.present, E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_GNB_CU_UP_Name);
|
||||
// gNB-CU-UP Name (O)
|
||||
E1AP_LIB_FIND_IE(E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ie, in, E1AP_ProtocolIE_ID_id_gNB_CU_UP_Name, false);
|
||||
if (ie != NULL) {
|
||||
out->gNB_cu_up_name = calloc_or_fail(ie->value.choice.GNB_CU_UP_Name.size + 1, sizeof(char));
|
||||
memcpy(out->gNB_cu_up_name, ie->value.choice.GNB_CU_UP_Name.buf, ie->value.choice.GNB_CU_UP_Name.size);
|
||||
}
|
||||
break;
|
||||
case E1AP_ProtocolIE_ID_id_CNSupport:
|
||||
_E1_EQ_CHECK_INT(ie->value.present, E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_CNSupport);
|
||||
_E1_EQ_CHECK_INT(ie->value.choice.CNSupport, E1AP_CNSupport_c_5gc); // only 5GC CN Support supported
|
||||
out->cn_support = ie->value.choice.CNSupport;
|
||||
break;
|
||||
case E1AP_ProtocolIE_ID_id_SupportedPLMNs:
|
||||
_E1_EQ_CHECK_INT(ie->value.present, E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_SupportedPLMNs_List);
|
||||
out->supported_plmns = ie->value.choice.SupportedPLMNs_List.list.count;
|
||||
|
||||
for (int i = 0; i < out->supported_plmns; i++) {
|
||||
E1AP_SupportedPLMNs_Item_t *supported_plmn_item =
|
||||
(E1AP_SupportedPLMNs_Item_t *)(ie->value.choice.SupportedPLMNs_List.list.array[i]);
|
||||
|
||||
/* PLMN Identity */
|
||||
PLMN_ID_t *id = &out->plmn[i].id;
|
||||
PLMNID_TO_MCC_MNC(&supported_plmn_item->pLMN_Identity, id->mcc, id->mnc, id->mnc_digit_length);
|
||||
|
||||
/* NSSAI */
|
||||
if (supported_plmn_item->slice_Support_List) {
|
||||
int n = supported_plmn_item->slice_Support_List->list.count;
|
||||
out->plmn[i].supported_slices = n;
|
||||
out->plmn[i].slice = calloc_or_fail(n, sizeof(*out->plmn[i].slice));
|
||||
for (int s = 0; s < n; ++s) {
|
||||
e1ap_nssai_t *slice = &out->plmn[i].slice[s];
|
||||
const E1AP_SNSSAI_t *es = &supported_plmn_item->slice_Support_List->list.array[s]->sNSSAI;
|
||||
OCTET_STRING_TO_INT8(&es->sST, slice->sst);
|
||||
slice->sd = 0xffffff;
|
||||
if (es->sD != NULL)
|
||||
OCTET_STRING_TO_INT24(es->sD, slice->sd);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
PRINT_ERROR("Handle for this IE %ld is not implemented (or) invalid IE detected\n", ie->id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deep copy function for E1 CUUP Setup Request
|
||||
*/
|
||||
e1ap_setup_req_t cp_e1ap_cuup_setup_request(const e1ap_setup_req_t *msg)
|
||||
{
|
||||
e1ap_setup_req_t cp = {0};
|
||||
cp = *msg;
|
||||
if (msg->gNB_cu_up_name) {
|
||||
cp.gNB_cu_up_name = strdup(msg->gNB_cu_up_name);
|
||||
}
|
||||
for (int i = 0; i < msg->supported_plmns; i++) {
|
||||
if (msg->plmn[i].slice && msg->plmn[i].supported_slices > 0) {
|
||||
cp.plmn[i].slice = calloc_or_fail(msg->plmn[i].supported_slices, sizeof(*cp.plmn[i].slice));
|
||||
for (int s = 0; s < msg->plmn[i].supported_slices; ++s) {
|
||||
cp.plmn[i].slice[s] = msg->plmn[i].slice[s];
|
||||
}
|
||||
}
|
||||
}
|
||||
return cp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free memory allocated for E1 CUUP Setup Request
|
||||
*/
|
||||
void free_e1ap_cuup_setup_request(e1ap_setup_req_t *msg)
|
||||
{
|
||||
// gNB-CU-UP Name
|
||||
free(msg->gNB_cu_up_name);
|
||||
// Slice support lists within PLMNs
|
||||
for (int i = 0; i < msg->supported_plmns; i++) {
|
||||
free(msg->plmn[i].slice);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Equality check function for E1 CUUP Setup Request
|
||||
*/
|
||||
bool eq_e1ap_cuup_setup_request(const e1ap_setup_req_t *a, const e1ap_setup_req_t *b)
|
||||
{
|
||||
_E1_EQ_CHECK_INT(a->transac_id, b->transac_id);
|
||||
_E1_EQ_CHECK_INT(a->gNB_cu_up_id, b->gNB_cu_up_id);
|
||||
if (a->gNB_cu_up_name && b->gNB_cu_up_name)
|
||||
_E1_EQ_CHECK_STR(a->gNB_cu_up_name, b->gNB_cu_up_name)
|
||||
_E1_EQ_CHECK_INT(a->supported_plmns, b->supported_plmns);
|
||||
for (int i = 0; i < a->supported_plmns; i++) {
|
||||
_E1_EQ_CHECK_INT(a->plmn[i].id.mcc, b->plmn[i].id.mcc);
|
||||
_E1_EQ_CHECK_INT(a->plmn[i].id.mnc, b->plmn[i].id.mnc);
|
||||
_E1_EQ_CHECK_INT(a->plmn[i].id.mnc_digit_length, b->plmn[i].id.mnc_digit_length);
|
||||
_E1_EQ_CHECK_INT(a->plmn[i].supported_slices, b->plmn[i].supported_slices);
|
||||
for (int s = 0; s < a->plmn[i].supported_slices; ++s) {
|
||||
_E1_EQ_CHECK_INT(a->plmn[i].slice[s].sst, b->plmn[i].slice[s].sst);
|
||||
_E1_EQ_CHECK_INT(a->plmn[i].slice[s].sd, b->plmn[i].slice[s].sd);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ====================================
|
||||
* GNB-CU-UP E1 SETUP RESPONSE
|
||||
* ==================================== */
|
||||
|
||||
/**
|
||||
* @brief Encode GNB-CU-UP E1 Setup Response
|
||||
*/
|
||||
E1AP_E1AP_PDU_t *encode_e1ap_cuup_setup_response(const e1ap_setup_resp_t *msg)
|
||||
{
|
||||
E1AP_E1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu));
|
||||
/* Create */
|
||||
/* 0. pdu Type */
|
||||
pdu->present = E1AP_E1AP_PDU_PR_successfulOutcome;
|
||||
asn1cCalloc(pdu->choice.successfulOutcome, initMsg);
|
||||
initMsg->procedureCode = E1AP_ProcedureCode_id_gNB_CU_UP_E1Setup;
|
||||
initMsg->criticality = E1AP_Criticality_reject;
|
||||
initMsg->value.present = E1AP_SuccessfulOutcome__value_PR_GNB_CU_UP_E1SetupResponse;
|
||||
E1AP_GNB_CU_UP_E1SetupResponse_t *out = &pdu->choice.successfulOutcome->value.choice.GNB_CU_UP_E1SetupResponse;
|
||||
// Transaction ID (M)
|
||||
asn1cSequenceAdd(out->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupResponseIEs_t, ieC1);
|
||||
ieC1->id = E1AP_ProtocolIE_ID_id_TransactionID;
|
||||
ieC1->criticality = E1AP_Criticality_reject;
|
||||
ieC1->value.present = E1AP_GNB_CU_UP_E1SetupResponseIEs__value_PR_TransactionID;
|
||||
ieC1->value.choice.TransactionID = msg->transac_id;
|
||||
// Encode gNB_CU_CP_Name (O)
|
||||
if (msg->gNB_cu_cp_name) {
|
||||
asn1cSequenceAdd(out->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupResponseIEs_t, ieC2);
|
||||
ieC2->id = E1AP_ProtocolIE_ID_id_gNB_CU_CP_Name;
|
||||
ieC2->criticality = E1AP_Criticality_ignore;
|
||||
ieC2->value.present = E1AP_GNB_CU_UP_E1SetupResponseIEs__value_PR_GNB_CU_CP_Name;
|
||||
OCTET_STRING_fromBuf(&ieC2->value.choice.GNB_CU_CP_Name, msg->gNB_cu_cp_name, strlen(msg->gNB_cu_cp_name));
|
||||
}
|
||||
// Encode TNLA Info (O)
|
||||
if (msg->tnla_info) {
|
||||
asn1cSequenceAdd(out->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupResponseIEs_t, ieC3);
|
||||
ieC3->id = E1AP_ProtocolIE_ID_id_Transport_Layer_Address_Info;
|
||||
ieC3->criticality = E1AP_Criticality_ignore;
|
||||
ieC3->value.present = E1AP_GNB_CU_UP_E1SetupResponseIEs__value_PR_Transport_Layer_Address_Info;
|
||||
// Transport UP Layer Addresses Info to Add List
|
||||
for (int i = 0; i < msg->tnla_info->num_addresses_to_add; i++) {
|
||||
E1AP_Transport_UP_Layer_Addresses_Info_To_Add_List_t *a = calloc_or_fail(1, sizeof(*a));
|
||||
ieC3->value.choice.Transport_Layer_Address_Info.transport_UP_Layer_Addresses_Info_To_Add_List =
|
||||
(struct E1AP_Transport_UP_Layer_Addresses_Info_To_Add_List *)a;
|
||||
asn1cSequenceAdd(a->list, E1AP_Transport_UP_Layer_Addresses_Info_To_Add_Item_t, ieC4);
|
||||
in_addr_t *ipsec = &msg->tnla_info->addresses_to_add[i].ipsec_tl_address;
|
||||
TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(*ipsec, &ieC4->iP_SecTransportLayerAddress);
|
||||
for (int j = 0; j < msg->tnla_info->addresses_to_add[i].num_gtp_tl_addresses; j++) {
|
||||
E1AP_GTPTLAs_t *g = calloc_or_fail(1, sizeof(*g));
|
||||
ieC4->gTPTransportLayerAddressesToAdd = (struct E1AP_GTPTLAs *)g;
|
||||
asn1cSequenceAdd(g->list, E1AP_GTPTLA_Item_t, ieC5);
|
||||
in_addr_t *gtp_tlna = &msg->tnla_info->addresses_to_add[i].gtp_tl_addresses[j];
|
||||
TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(*gtp_tlna, &ieC5->gTPTransportLayerAddresses);
|
||||
}
|
||||
}
|
||||
// Transport UP Layer Addresses Info to Remove List
|
||||
for (int i = 0; i < msg->tnla_info->num_addresses_to_remove; i++) {
|
||||
E1AP_Transport_UP_Layer_Addresses_Info_To_Remove_List_t *a = calloc_or_fail(1, sizeof(*a));
|
||||
ieC3->value.choice.Transport_Layer_Address_Info.transport_UP_Layer_Addresses_Info_To_Remove_List =
|
||||
(struct E1AP_Transport_UP_Layer_Addresses_Info_To_Remove_List *)a;
|
||||
asn1cSequenceAdd(a->list, E1AP_Transport_UP_Layer_Addresses_Info_To_Remove_Item_t, ieC4);
|
||||
in_addr_t *ipsec = &msg->tnla_info->addresses_to_remove[i].ipsec_tl_address;
|
||||
TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(*ipsec, &ieC4->iP_SecTransportLayerAddress);
|
||||
for (int j = 0; j < msg->tnla_info->addresses_to_remove[i].num_gtp_tl_addresses; j++) {
|
||||
E1AP_GTPTLAs_t *g = calloc_or_fail(1, sizeof(*g));
|
||||
ieC4->gTPTransportLayerAddressesToRemove = (struct E1AP_GTPTLAs *)g;
|
||||
asn1cSequenceAdd(g->list, E1AP_GTPTLA_Item_t, ieC5);
|
||||
in_addr_t *gtp_tlna = &msg->tnla_info->addresses_to_remove[i].gtp_tl_addresses[j];
|
||||
TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(*gtp_tlna, &ieC5->gTPTransportLayerAddresses);
|
||||
}
|
||||
}
|
||||
}
|
||||
return pdu;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decode GNB-CU-UP E1 Setup Response
|
||||
*/
|
||||
bool decode_e1ap_cuup_setup_response(const E1AP_E1AP_PDU_t *pdu, e1ap_setup_resp_t *out)
|
||||
{
|
||||
_E1_EQ_CHECK_INT(pdu->present, E1AP_E1AP_PDU_PR_successfulOutcome);
|
||||
_E1_EQ_CHECK_INT(pdu->choice.successfulOutcome->procedureCode, E1AP_ProcedureCode_id_gNB_CU_UP_E1Setup);
|
||||
_E1_EQ_CHECK_INT(pdu->choice.successfulOutcome->value.present, E1AP_SuccessfulOutcome__value_PR_GNB_CU_UP_E1SetupResponse);
|
||||
const E1AP_GNB_CU_UP_E1SetupResponse_t *in = &pdu->choice.successfulOutcome->value.choice.GNB_CU_UP_E1SetupResponse;
|
||||
E1AP_GNB_CU_UP_E1SetupResponseIEs_t *ie;
|
||||
// Transaction ID (M)
|
||||
E1AP_LIB_FIND_IE(E1AP_GNB_CU_UP_E1SetupResponseIEs_t, ie, in, E1AP_ProtocolIE_ID_id_TransactionID, true);
|
||||
// Decode TNLA Info (O)
|
||||
for (int i = 0; i < in->protocolIEs.list.count; i++) {
|
||||
ie = in->protocolIEs.list.array[i];
|
||||
AssertFatal(ie != NULL, "in->protocolIEs.list.array[i] shall not be null");
|
||||
switch (ie->id) {
|
||||
case E1AP_ProtocolIE_ID_id_TransactionID:
|
||||
out->transac_id = ie->value.choice.TransactionID;
|
||||
break;
|
||||
|
||||
case E1AP_ProtocolIE_ID_id_gNB_CU_CP_Name:
|
||||
// gNB-CU-CP Name (O)
|
||||
E1AP_LIB_FIND_IE(E1AP_GNB_CU_UP_E1SetupResponseIEs_t, ie, in, E1AP_ProtocolIE_ID_id_gNB_CU_CP_Name, false);
|
||||
_E1_EQ_CHECK_INT(ie->value.present, E1AP_GNB_CU_UP_E1SetupResponseIEs__value_PR_GNB_CU_CP_Name);
|
||||
if (ie != NULL) {
|
||||
out->gNB_cu_cp_name = calloc_or_fail(ie->value.choice.GNB_CU_CP_Name.size + 1, sizeof(char));
|
||||
memcpy(out->gNB_cu_cp_name, ie->value.choice.GNB_CU_CP_Name.buf, ie->value.choice.GNB_CU_CP_Name.size);
|
||||
}
|
||||
break;
|
||||
|
||||
case E1AP_ProtocolIE_ID_id_Transport_Layer_Address_Info:
|
||||
E1AP_LIB_FIND_IE(E1AP_GNB_CU_UP_E1SetupResponseIEs_t, ie, in, E1AP_ProtocolIE_ID_id_Transport_Layer_Address_Info, false);
|
||||
out->tnla_info = calloc_or_fail(1, sizeof(*out->tnla_info));
|
||||
// Transport UP Layer Addresses Info to Add List
|
||||
const E1AP_Transport_UP_Layer_Addresses_Info_To_Add_List_t *a =
|
||||
ie->value.choice.Transport_Layer_Address_Info.transport_UP_Layer_Addresses_Info_To_Add_List;
|
||||
out->tnla_info->num_addresses_to_add = a->list.count;
|
||||
for (int i = 0; i < a->list.count; i++) {
|
||||
const E1AP_Transport_UP_Layer_Addresses_Info_To_Add_Item_t *item = a->list.array[i];
|
||||
tnl_address_info_item_t *to_add = &out->tnla_info->addresses_to_add[i];
|
||||
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&item->iP_SecTransportLayerAddress, to_add->ipsec_tl_address);
|
||||
const E1AP_GTPTLAs_t *gtp_list = item->gTPTransportLayerAddressesToAdd;
|
||||
to_add->num_gtp_tl_addresses = gtp_list->list.count;
|
||||
for (int j = 0; j < gtp_list->list.count; j++) {
|
||||
const E1AP_GTPTLA_Item_t *gtp_item = gtp_list->list.array[j];
|
||||
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(>p_item->gTPTransportLayerAddresses, to_add->gtp_tl_addresses[j]);
|
||||
}
|
||||
}
|
||||
// Transport UP Layer Addresses Info to Remove List
|
||||
const E1AP_Transport_UP_Layer_Addresses_Info_To_Remove_List_t *r =
|
||||
ie->value.choice.Transport_Layer_Address_Info.transport_UP_Layer_Addresses_Info_To_Remove_List;
|
||||
out->tnla_info->num_addresses_to_remove = r->list.count;
|
||||
|
||||
for (int i = 0; i < r->list.count; i++) {
|
||||
const E1AP_Transport_UP_Layer_Addresses_Info_To_Remove_Item_t *item = r->list.array[i];
|
||||
tnl_address_info_item_t *to_remove = &out->tnla_info->addresses_to_remove[i];
|
||||
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&item->iP_SecTransportLayerAddress, to_remove->ipsec_tl_address);
|
||||
|
||||
const E1AP_GTPTLAs_t *gtp_list = item->gTPTransportLayerAddressesToRemove;
|
||||
to_remove->num_gtp_tl_addresses = gtp_list->list.count;
|
||||
for (int j = 0; j < gtp_list->list.count; j++) {
|
||||
const E1AP_GTPTLA_Item_t *gtp_item = gtp_list->list.array[j];
|
||||
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(>p_item->gTPTransportLayerAddresses, to_remove->gtp_tl_addresses[j]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
PRINT_ERROR("Handle for this IE %ld is not implemented (or) invalid IE detected\n", ie->id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deep copy GNB-CU-UP E1 Setup Response
|
||||
*/
|
||||
e1ap_setup_resp_t cp_e1ap_cuup_setup_response(const e1ap_setup_resp_t *msg)
|
||||
{
|
||||
e1ap_setup_resp_t cp = {0};
|
||||
cp.transac_id = msg->transac_id;
|
||||
if (msg->gNB_cu_cp_name) {
|
||||
cp.gNB_cu_cp_name = strdup(msg->gNB_cu_cp_name);
|
||||
}
|
||||
if (msg->tnla_info) {
|
||||
cp.tnla_info = calloc_or_fail(1, sizeof(*cp.tnla_info));
|
||||
*cp.tnla_info = *msg->tnla_info;
|
||||
}
|
||||
return cp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free GNB-CU-UP E1 Setup Response
|
||||
*/
|
||||
void free_e1ap_cuup_setup_response(e1ap_setup_resp_t *msg)
|
||||
{
|
||||
free(msg->gNB_cu_cp_name);
|
||||
free(msg->tnla_info);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Equality check for GNB-CU-UP E1 Setup Response
|
||||
*/
|
||||
bool eq_e1ap_cuup_setup_response(const e1ap_setup_resp_t *a, const e1ap_setup_resp_t *b)
|
||||
{
|
||||
_E1_EQ_CHECK_LONG(a->transac_id, b->transac_id);
|
||||
if ((a->gNB_cu_cp_name && !b->gNB_cu_cp_name) || (!a->gNB_cu_cp_name && b->gNB_cu_cp_name))
|
||||
return false;
|
||||
if (a->gNB_cu_cp_name && b->gNB_cu_cp_name)
|
||||
_E1_EQ_CHECK_STR(a->gNB_cu_cp_name, b->gNB_cu_cp_name);
|
||||
if ((a->tnla_info && !b->tnla_info) || (!a->tnla_info && b->tnla_info))
|
||||
return false;
|
||||
if (a->tnla_info && b->tnla_info) {
|
||||
_E1_EQ_CHECK_INT(a->tnla_info->num_addresses_to_add, b->tnla_info->num_addresses_to_add);
|
||||
_E1_EQ_CHECK_INT(a->tnla_info->num_addresses_to_remove, b->tnla_info->num_addresses_to_remove);
|
||||
for (int i = 0; i < a->tnla_info->num_addresses_to_add; i++) {
|
||||
tnl_address_info_item_t *a_to_add = &a->tnla_info->addresses_to_add[i];
|
||||
tnl_address_info_item_t *b_to_add = &b->tnla_info->addresses_to_add[i];
|
||||
_E1_EQ_CHECK_LONG(a_to_add->ipsec_tl_address, b_to_add->ipsec_tl_address);
|
||||
for (int j = 0; j < a_to_add->num_gtp_tl_addresses; j++) {
|
||||
_E1_EQ_CHECK_LONG(a_to_add->gtp_tl_addresses[j], b_to_add->gtp_tl_addresses[j]);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < a->tnla_info->num_addresses_to_remove; i++) {
|
||||
tnl_address_info_item_t *a_to_rem = &a->tnla_info->addresses_to_remove[i];
|
||||
tnl_address_info_item_t *b_to_rem = &b->tnla_info->addresses_to_remove[i];
|
||||
_E1_EQ_CHECK_LONG(a_to_rem->ipsec_tl_address, b_to_rem->ipsec_tl_address);
|
||||
for (int j = 0; j < a_to_rem->num_gtp_tl_addresses; j++) {
|
||||
_E1_EQ_CHECK_LONG(a_to_rem->gtp_tl_addresses[j], b_to_rem->gtp_tl_addresses[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ====================================
|
||||
* GNB-CU-UP E1 SETUP FAILURE
|
||||
* ==================================== */
|
||||
|
||||
static E1AP_Cause_t encode_e1ap_cause_ie(const e1ap_cause_t *cause)
|
||||
{
|
||||
E1AP_Cause_t ie;
|
||||
switch (cause->type) {
|
||||
case E1AP_CAUSE_RADIO_NETWORK:
|
||||
ie.present = E1AP_Cause_PR_radioNetwork;
|
||||
ie.choice.radioNetwork = cause->value;
|
||||
break;
|
||||
case E1AP_CAUSE_TRANSPORT:
|
||||
ie.present = E1AP_Cause_PR_transport;
|
||||
ie.choice.transport = cause->value;
|
||||
break;
|
||||
case E1AP_CAUSE_PROTOCOL:
|
||||
ie.present = E1AP_Cause_PR_protocol;
|
||||
ie.choice.protocol = cause->value;
|
||||
break;
|
||||
case E1AP_CAUSE_MISC:
|
||||
ie.present = E1AP_Cause_PR_misc;
|
||||
ie.choice.misc = cause->value;
|
||||
break;
|
||||
default:
|
||||
ie.present = E1AP_Cause_PR_NOTHING;
|
||||
break;
|
||||
}
|
||||
return ie;
|
||||
}
|
||||
|
||||
static e1ap_cause_t decode_e1ap_cause_ie(const E1AP_Cause_t *ie)
|
||||
{
|
||||
e1ap_cause_t cause;
|
||||
// Decode the 'choice' field based on the 'present' value
|
||||
switch (ie->present) {
|
||||
case E1AP_Cause_PR_radioNetwork:
|
||||
cause.value = ie->choice.radioNetwork;
|
||||
cause.type = E1AP_CAUSE_RADIO_NETWORK;
|
||||
break;
|
||||
case E1AP_Cause_PR_transport:
|
||||
cause.value = ie->choice.transport;
|
||||
cause.type = E1AP_CAUSE_TRANSPORT;
|
||||
break;
|
||||
case E1AP_Cause_PR_protocol:
|
||||
cause.value = ie->choice.protocol;
|
||||
cause.type = E1AP_CAUSE_PROTOCOL;
|
||||
break;
|
||||
case E1AP_Cause_PR_misc:
|
||||
cause.value = ie->choice.misc;
|
||||
cause.type = E1AP_CAUSE_MISC;
|
||||
break;
|
||||
default:
|
||||
cause.type = E1AP_CAUSE_NOTHING;
|
||||
break;
|
||||
}
|
||||
return cause;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encoder for GNB-CU-UP E1 Setup Failure
|
||||
* @ref 9.2.1.6 GNB-CU-UP E1 SETUP FAILURE of 3GPP TS 38.463
|
||||
*/
|
||||
E1AP_E1AP_PDU_t *encode_e1ap_cuup_setup_failure(const e1ap_setup_fail_t *msg)
|
||||
{
|
||||
E1AP_E1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(E1AP_E1AP_PDU_t));
|
||||
// Allocate and populate the unsuccessfulOutcome structure
|
||||
pdu->present = E1AP_E1AP_PDU_PR_unsuccessfulOutcome;
|
||||
asn1cCalloc(pdu->choice.unsuccessfulOutcome, initMsg);
|
||||
initMsg->procedureCode = E1AP_ProcedureCode_id_gNB_CU_UP_E1Setup;
|
||||
initMsg->criticality = E1AP_Criticality_reject;
|
||||
initMsg->value.present = E1AP_UnsuccessfulOutcome__value_PR_GNB_CU_UP_E1SetupFailure;
|
||||
E1AP_GNB_CU_UP_E1SetupFailure_t *out = &pdu->choice.unsuccessfulOutcome->value.choice.GNB_CU_UP_E1SetupFailure;
|
||||
// Transaction ID
|
||||
asn1cSequenceAdd(out->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupFailureIEs_t, ie1);
|
||||
ie1->id = E1AP_ProtocolIE_ID_id_TransactionID;
|
||||
ie1->criticality = E1AP_Criticality_reject;
|
||||
ie1->value.present = E1AP_GNB_CU_UP_E1SetupFailureIEs__value_PR_TransactionID;
|
||||
ie1->value.choice.TransactionID = msg->transac_id;
|
||||
// Cause
|
||||
asn1cSequenceAdd(out->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupFailureIEs_t, ie2);
|
||||
ie2->id = E1AP_ProtocolIE_ID_id_Cause;
|
||||
ie2->criticality = E1AP_Criticality_ignore;
|
||||
ie2->value.present = E1AP_GNB_CU_UP_E1SetupFailureIEs__value_PR_Cause;
|
||||
ie2->value.choice.Cause = encode_e1ap_cause_ie(&msg->cause);
|
||||
// Time To Wait (O)
|
||||
if (msg->time_to_wait) {
|
||||
asn1cSequenceAdd(out->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupFailureIEs_t, ie3);
|
||||
ie3->id = E1AP_ProtocolIE_ID_id_TimeToWait;
|
||||
ie3->criticality = E1AP_Criticality_ignore;
|
||||
ie3->value.present = E1AP_GNB_CU_UP_E1SetupFailureIEs__value_PR_TimeToWait;
|
||||
ie3->value.choice.TimeToWait = *msg->time_to_wait;
|
||||
}
|
||||
// Criticality Diagnostics (O)
|
||||
if (msg->crit_diag) {
|
||||
asn1cSequenceAdd(out->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupFailureIEs_t, ie4);
|
||||
ie4->id = E1AP_ProtocolIE_ID_id_CriticalityDiagnostics;
|
||||
ie4->criticality = E1AP_Criticality_ignore;
|
||||
ie4->value.present = E1AP_GNB_CU_UP_E1SetupFailureIEs__value_PR_CriticalityDiagnostics;
|
||||
encode_criticality_diagnostics(msg->crit_diag, &ie4->value.choice.CriticalityDiagnostics);
|
||||
}
|
||||
return pdu;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decoder for GNB-CU-UP E1 Setup Failure
|
||||
*/
|
||||
bool decode_e1ap_cuup_setup_failure(const E1AP_E1AP_PDU_t *pdu, e1ap_setup_fail_t *out)
|
||||
{
|
||||
_E1_EQ_CHECK_INT(pdu->present, E1AP_E1AP_PDU_PR_unsuccessfulOutcome);
|
||||
_E1_EQ_CHECK_INT(pdu->choice.unsuccessfulOutcome->procedureCode, E1AP_ProcedureCode_id_gNB_CU_UP_E1Setup);
|
||||
const E1AP_GNB_CU_UP_E1SetupFailure_t *in = &pdu->choice.unsuccessfulOutcome->value.choice.GNB_CU_UP_E1SetupFailure;
|
||||
E1AP_GNB_CU_UP_E1SetupFailureIEs_t *ie;
|
||||
// Check mandatory IEs first
|
||||
E1AP_LIB_FIND_IE(E1AP_GNB_CU_UP_E1SetupFailureIEs_t, ie, in, E1AP_ProtocolIE_ID_id_TransactionID, true);
|
||||
E1AP_LIB_FIND_IE(E1AP_GNB_CU_UP_E1SetupFailureIEs_t, ie, in, E1AP_ProtocolIE_ID_id_Cause, true);
|
||||
for (int i = 0; i < in->protocolIEs.list.count; i++) {
|
||||
ie = in->protocolIEs.list.array[i];
|
||||
AssertFatal(ie != NULL, "in->protocolIEs.list.array[i] shall not be null");
|
||||
switch (ie->id) {
|
||||
case E1AP_ProtocolIE_ID_id_TransactionID:
|
||||
out->transac_id = ie->value.choice.TransactionID;
|
||||
break;
|
||||
case E1AP_ProtocolIE_ID_id_Cause:
|
||||
// Cause
|
||||
E1AP_LIB_FIND_IE(E1AP_GNB_CU_UP_E1SetupFailureIEs_t, ie, in, E1AP_ProtocolIE_ID_id_Cause, true);
|
||||
out->cause = decode_e1ap_cause_ie(&ie->value.choice.Cause);
|
||||
break;
|
||||
case E1AP_ProtocolIE_ID_id_Transport_Layer_Address_Info:
|
||||
// Time To Wait (O)
|
||||
E1AP_LIB_FIND_IE(E1AP_GNB_CU_UP_E1SetupFailureIEs_t, ie, in, E1AP_ProtocolIE_ID_id_TimeToWait, false);
|
||||
out->time_to_wait = calloc_or_fail(1, sizeof(*out->time_to_wait));
|
||||
*out->time_to_wait = ie->value.choice.TimeToWait;
|
||||
break;
|
||||
case E1AP_ProtocolIE_ID_id_CriticalityDiagnostics:
|
||||
// Criticality Diagnostics (O)
|
||||
E1AP_LIB_FIND_IE(E1AP_GNB_CU_UP_E1SetupFailureIEs_t, ie, in, E1AP_ProtocolIE_ID_id_CriticalityDiagnostics, false);
|
||||
out->crit_diag = calloc_or_fail(1, sizeof(*out->crit_diag));
|
||||
decode_criticality_diagnostics(&ie->value.choice.CriticalityDiagnostics, out->crit_diag);
|
||||
break;
|
||||
default:
|
||||
PRINT_ERROR("Handle for this IE %ld is not implemented (or) invalid IE detected\n", ie->id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deep copy of GNB-CU-UP E1 Setup Failure message
|
||||
*/
|
||||
e1ap_setup_fail_t cp_e1ap_cuup_setup_failure(const e1ap_setup_fail_t *msg)
|
||||
{
|
||||
e1ap_setup_fail_t cp = {0};
|
||||
cp.transac_id = msg->transac_id;
|
||||
cp.cause = msg->cause;
|
||||
if (msg->time_to_wait) {
|
||||
cp.time_to_wait = calloc_or_fail(1, sizeof(*cp.time_to_wait));
|
||||
*cp.time_to_wait = *msg->time_to_wait;
|
||||
}
|
||||
if (msg->crit_diag) {
|
||||
cp.crit_diag = calloc_or_fail(1, sizeof(*cp.crit_diag));
|
||||
*cp.crit_diag = *msg->crit_diag;
|
||||
if (msg->crit_diag->procedure_code) {
|
||||
cp.crit_diag->procedure_code = calloc_or_fail(1, sizeof(*cp.crit_diag->procedure_code));
|
||||
*cp.crit_diag->procedure_code = *msg->crit_diag->procedure_code;
|
||||
}
|
||||
if (msg->crit_diag->procedure_criticality) {
|
||||
cp.crit_diag->procedure_criticality = calloc_or_fail(1, sizeof(*cp.crit_diag->procedure_criticality));
|
||||
*cp.crit_diag->procedure_criticality = *msg->crit_diag->procedure_criticality;
|
||||
}
|
||||
if (msg->crit_diag->triggering_msg) {
|
||||
cp.crit_diag->triggering_msg = calloc_or_fail(1, sizeof(*cp.crit_diag->triggering_msg));
|
||||
*cp.crit_diag->triggering_msg = *msg->crit_diag->triggering_msg;
|
||||
}
|
||||
}
|
||||
return cp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free memory allocated for GNB-CU-UP E1 Setup Failure message
|
||||
*/
|
||||
void free_e1ap_cuup_setup_failure(e1ap_setup_fail_t *msg)
|
||||
{
|
||||
free(msg->time_to_wait);
|
||||
if (msg->crit_diag) {
|
||||
free(msg->crit_diag->triggering_msg);
|
||||
free(msg->crit_diag->procedure_code);
|
||||
free(msg->crit_diag->procedure_criticality);
|
||||
}
|
||||
free(msg->crit_diag);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Equality check for GNB-CU-UP E1 Setup Failure message
|
||||
*/
|
||||
bool eq_e1ap_cuup_setup_failure(const e1ap_setup_fail_t *a, const e1ap_setup_fail_t *b)
|
||||
{
|
||||
_E1_EQ_CHECK_LONG(a->transac_id, b->transac_id);
|
||||
_E1_EQ_CHECK_INT(a->cause.type, b->cause.type);
|
||||
_E1_EQ_CHECK_INT(a->cause.value, b->cause.value);
|
||||
if (a->time_to_wait && b->time_to_wait)
|
||||
_E1_EQ_CHECK_LONG(*a->time_to_wait, *b->time_to_wait);
|
||||
if (a->crit_diag && b->crit_diag) {
|
||||
if (a->crit_diag->procedure_code && b->crit_diag->procedure_code)
|
||||
_E1_EQ_CHECK_LONG(*(a->crit_diag->procedure_code), *(b->crit_diag->procedure_code));
|
||||
if (a->crit_diag->triggering_msg && b->crit_diag->triggering_msg)
|
||||
_E1_EQ_CHECK_LONG(*(a->crit_diag->triggering_msg), *(b->crit_diag->triggering_msg));
|
||||
if (a->crit_diag->procedure_criticality && b->crit_diag->procedure_criticality)
|
||||
_E1_EQ_CHECK_LONG(*(a->crit_diag->procedure_criticality), *(b->crit_diag->procedure_criticality));
|
||||
_E1_EQ_CHECK_INT(a->crit_diag->num_errors, b->crit_diag->num_errors);
|
||||
for (int i = 0; i < a->crit_diag->num_errors; i++) {
|
||||
const criticality_diagnostics_ie_t *a_err = &a->crit_diag->errors[i];
|
||||
const criticality_diagnostics_ie_t *b_err = &b->crit_diag->errors[i];
|
||||
_E1_EQ_CHECK_INT(a_err->ie_id, b_err->ie_id);
|
||||
_E1_EQ_CHECK_INT(a_err->error_type, b_err->error_type);
|
||||
_E1_EQ_CHECK_INT(a_err->criticality, b_err->criticality);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef E1AP_INTERFACE_MANAGEMENT_H_
|
||||
#define E1AP_INTERFACE_MANAGEMENT_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "openair2/COMMON/e1ap_messages_types.h"
|
||||
#include "common/platform_types.h"
|
||||
|
||||
/* GNB-CU-UP E1 Setup Request */
|
||||
struct E1AP_E1AP_PDU *encode_e1ap_cuup_setup_request(const e1ap_setup_req_t *msg);
|
||||
bool decode_e1ap_cuup_setup_request(const struct E1AP_E1AP_PDU *pdu, e1ap_setup_req_t *out);
|
||||
e1ap_setup_req_t cp_e1ap_cuup_setup_request(const e1ap_setup_req_t *msg);
|
||||
void free_e1ap_cuup_setup_request(e1ap_setup_req_t *msg);
|
||||
bool eq_e1ap_cuup_setup_request(const e1ap_setup_req_t *a, const e1ap_setup_req_t *b);
|
||||
|
||||
/* GNB-CU-UP E1 Setup Response */
|
||||
struct E1AP_E1AP_PDU *encode_e1ap_cuup_setup_response(const e1ap_setup_resp_t *msg);
|
||||
bool decode_e1ap_cuup_setup_response(const struct E1AP_E1AP_PDU *pdu, e1ap_setup_resp_t *out);
|
||||
e1ap_setup_resp_t cp_e1ap_cuup_setup_response(const e1ap_setup_resp_t *msg);
|
||||
void free_e1ap_cuup_setup_response(e1ap_setup_resp_t *msg);
|
||||
bool eq_e1ap_cuup_setup_response(const e1ap_setup_resp_t *a, const e1ap_setup_resp_t *b);
|
||||
|
||||
/* GNB-CU-UP E1 Setup Failure */
|
||||
struct E1AP_E1AP_PDU *encode_e1ap_cuup_setup_failure(const e1ap_setup_fail_t *msg);
|
||||
bool decode_e1ap_cuup_setup_failure(const struct E1AP_E1AP_PDU *pdu, e1ap_setup_fail_t *out);
|
||||
e1ap_setup_fail_t cp_e1ap_cuup_setup_failure(const e1ap_setup_fail_t *msg);
|
||||
void free_e1ap_cuup_setup_failure(e1ap_setup_fail_t *msg);
|
||||
bool eq_e1ap_cuup_setup_failure(const e1ap_setup_fail_t *a, const e1ap_setup_fail_t *b);
|
||||
|
||||
#endif /* E1AP_INTERFACE_MANAGEMENT_H_ */
|
||||
@@ -25,6 +25,8 @@
|
||||
#include "E1AP_E1AP-PDU.h"
|
||||
#include "E1AP_ProcedureCode.h"
|
||||
#include "E1AP_SuccessfulOutcome.h"
|
||||
#include "E1AP_UnsuccessfulOutcome.h"
|
||||
#include "E1AP_CriticalityDiagnostics-IE-List.h"
|
||||
#include "E1AP_InitiatingMessage.h"
|
||||
#include "E1AP_ProtocolIE-ID.h"
|
||||
#include "E1AP_ProtocolIE-Field.h"
|
||||
@@ -53,5 +55,16 @@
|
||||
#include "E1AP_QoS-Flow-Item.h"
|
||||
#include "E1AP_DRB-Failed-List-NG-RAN.h"
|
||||
#include "E1AP_DRB-Failed-Item-NG-RAN.h"
|
||||
// E1 Setup
|
||||
#include "E1AP_SupportedPLMNs-Item.h"
|
||||
#include "E1AP_Slice-Support-List.h"
|
||||
#include "E1AP_Slice-Support-Item.h"
|
||||
#include "E1AP_ProtocolIE-Field.h"
|
||||
#include "E1AP_Transport-UP-Layer-Addresses-Info-To-Add-List.h"
|
||||
#include "E1AP_Transport-UP-Layer-Addresses-Info-To-Add-Item.h"
|
||||
#include "E1AP_Transport-UP-Layer-Addresses-Info-To-Remove-List.h"
|
||||
#include "E1AP_Transport-UP-Layer-Addresses-Info-To-Remove-Item.h"
|
||||
#include "E1AP_GTPTLAs.h"
|
||||
#include "E1AP_GTPTLA-Item.h"
|
||||
|
||||
#endif /* E1AP_LIB_INCLUDES_H_ */
|
||||
|
||||
@@ -30,8 +30,10 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "E1AP/lib/e1ap_bearer_context_management.h"
|
||||
#include "E1AP/lib/e1ap_lib_includes.h"
|
||||
#include "common/utils/utils.h"
|
||||
#include "e1ap_bearer_context_management.h"
|
||||
#include "e1ap_interface_management.h"
|
||||
#include "e1ap_lib_includes.h"
|
||||
#include "common/utils/assertions.h"
|
||||
|
||||
void exit_function(const char *file, const char *function, const int line, const char *s, const int assert)
|
||||
@@ -216,10 +218,131 @@ static void test_bearer_context_setup_response(void)
|
||||
free_e1ap_context_setup_response(&orig);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test CU-UP Setup Request encoding/decoding
|
||||
*/
|
||||
static void test_e1_cuup_setup_request(void)
|
||||
{
|
||||
e1ap_setup_req_t orig = {.gNB_cu_up_id = 1234,
|
||||
.gNB_cu_up_name = strdup("OAI CU-UP"),
|
||||
.transac_id = 42,
|
||||
.supported_plmns = 1,
|
||||
.cn_support = cn_support_5GC,
|
||||
.plmn[0] = {.id = {.mcc = 001, .mnc = 01, .mnc_digit_length = 2},
|
||||
.supported_slices = 1}};
|
||||
orig.plmn[0].slice = malloc_or_fail(sizeof(*orig.plmn[0].slice));
|
||||
orig.plmn[0].slice->sst = 0x01;
|
||||
orig.plmn[0].slice->sd = 0x01;
|
||||
|
||||
E1AP_E1AP_PDU_t *encoded = encode_e1ap_cuup_setup_request(&orig);
|
||||
E1AP_E1AP_PDU_t *decoded_msg = e1ap_encode_decode(encoded);
|
||||
e1ap_msg_free(encoded);
|
||||
|
||||
e1ap_setup_req_t decoded = {0};
|
||||
bool ret = decode_e1ap_cuup_setup_request(decoded_msg, &decoded);
|
||||
AssertFatal(ret, "Failed to decode setup request");
|
||||
e1ap_msg_free(decoded_msg);
|
||||
|
||||
ret = eq_e1ap_cuup_setup_request(&orig, &decoded);
|
||||
AssertFatal(ret, "Decoded setup request doesn't match original");
|
||||
free_e1ap_cuup_setup_request(&decoded);
|
||||
|
||||
e1ap_setup_req_t cp = cp_e1ap_cuup_setup_request(&orig);
|
||||
ret = eq_e1ap_cuup_setup_request(&orig, &cp);
|
||||
AssertFatal(ret, "eq_e1ap_cuup_setup_request(): copied message doesn't match\n");
|
||||
|
||||
free_e1ap_cuup_setup_request(&orig);
|
||||
free_e1ap_cuup_setup_request(&cp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test CU-UP Setup Response encoding/decoding
|
||||
*/
|
||||
static void test_e1_cuup_setup_response(void)
|
||||
{
|
||||
e1ap_setup_resp_t orig = {.transac_id = 42,
|
||||
.gNB_cu_cp_name = strdup("OAI CU-CP"),
|
||||
.tnla_info = malloc(sizeof(tnl_address_info_t))};
|
||||
orig.tnla_info->num_addresses_to_add = 1;
|
||||
orig.tnla_info->num_addresses_to_remove = 1;
|
||||
orig.tnla_info->addresses_to_add[0].num_gtp_tl_addresses = 1;
|
||||
orig.tnla_info->addresses_to_add[0].ipsec_tl_address = 0xC0A80001;
|
||||
orig.tnla_info->addresses_to_add[0].gtp_tl_addresses[0] = 0xC0A80002;
|
||||
orig.tnla_info->num_addresses_to_remove = 1;
|
||||
orig.tnla_info->addresses_to_remove[0].num_gtp_tl_addresses = 1;
|
||||
orig.tnla_info->addresses_to_remove[0].ipsec_tl_address = 0xC0A80003;
|
||||
orig.tnla_info->addresses_to_remove[0].gtp_tl_addresses[0] = 0xC0A80004;
|
||||
|
||||
E1AP_E1AP_PDU_t *encoded = encode_e1ap_cuup_setup_response(&orig);
|
||||
E1AP_E1AP_PDU_t *decoded_msg = e1ap_encode_decode(encoded);
|
||||
e1ap_msg_free(encoded);
|
||||
|
||||
e1ap_setup_resp_t decoded = {0};
|
||||
bool ret = decode_e1ap_cuup_setup_response(decoded_msg, &decoded);
|
||||
AssertFatal(ret, "Failed to decode setup response");
|
||||
e1ap_msg_free(decoded_msg);
|
||||
|
||||
ret = eq_e1ap_cuup_setup_response(&orig, &decoded);
|
||||
AssertFatal(ret, "Decoded setup response doesn't match original");
|
||||
free_e1ap_cuup_setup_response(&decoded);
|
||||
|
||||
e1ap_setup_resp_t cp = cp_e1ap_cuup_setup_response(&orig);
|
||||
ret = eq_e1ap_cuup_setup_response(&orig, &cp);
|
||||
AssertFatal(ret, "eq_e1ap_cuup_setup_response(): copied message doesn't match\n");
|
||||
|
||||
free_e1ap_cuup_setup_response(&orig);
|
||||
free_e1ap_cuup_setup_response(&cp);
|
||||
}
|
||||
|
||||
// Test for E1AP CU-UP Setup Failure
|
||||
static void test_e1_cuup_setup_failure(void)
|
||||
{
|
||||
e1ap_setup_fail_t orig = {.transac_id = 42,
|
||||
.cause.type = E1AP_CAUSE_RADIO_NETWORK,
|
||||
.cause.value = E1AP_RADIO_CAUSE_NORMAL_RELEASE,
|
||||
.time_to_wait = malloc_or_fail(sizeof(long)),
|
||||
.crit_diag = malloc_or_fail(sizeof(criticality_diagnostics_t))};
|
||||
*orig.time_to_wait = 5;
|
||||
orig.crit_diag->procedure_code = malloc_or_fail(sizeof(*orig.crit_diag->procedure_code));
|
||||
*orig.crit_diag->procedure_code = 99;
|
||||
orig.crit_diag->triggering_msg = malloc_or_fail(sizeof(*orig.crit_diag->triggering_msg));
|
||||
*orig.crit_diag->triggering_msg = TRIGGERING_MSG_SUCCESSFUL_OUTCOME;
|
||||
orig.crit_diag->procedure_criticality = malloc_or_fail(sizeof(*orig.crit_diag->procedure_criticality));
|
||||
*orig.crit_diag->procedure_criticality = CRITICALITY_IGNORE;
|
||||
orig.crit_diag->num_errors = 1;
|
||||
orig.crit_diag->errors[0].ie_id = 66;
|
||||
orig.crit_diag->errors[0].error_type = ERROR_TYPE_MISSING;
|
||||
orig.crit_diag->errors[0].criticality = CRITICALITY_IGNORE;
|
||||
|
||||
E1AP_E1AP_PDU_t *encoded = encode_e1ap_cuup_setup_failure(&orig);
|
||||
E1AP_E1AP_PDU_t *decoded_msg = e1ap_encode_decode(encoded);
|
||||
e1ap_msg_free(encoded);
|
||||
|
||||
e1ap_setup_fail_t decoded = {0};
|
||||
bool ret = decode_e1ap_cuup_setup_failure(decoded_msg, &decoded);
|
||||
AssertFatal(ret, "Failed to decode setup failure");
|
||||
e1ap_msg_free(decoded_msg);
|
||||
|
||||
ret = eq_e1ap_cuup_setup_failure(&orig, &decoded);
|
||||
AssertFatal(ret, "Decoded setup failure doesn't match original");
|
||||
free_e1ap_cuup_setup_failure(&decoded);
|
||||
|
||||
e1ap_setup_fail_t cp = cp_e1ap_cuup_setup_failure(&orig);
|
||||
ret = eq_e1ap_cuup_setup_failure(&orig, &cp);
|
||||
AssertFatal(ret, "eq_e1ap_cuup_setup_failure(): copied message doesn't match\n");
|
||||
|
||||
free_e1ap_cuup_setup_failure(&cp);
|
||||
free_e1ap_cuup_setup_failure(&orig);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// E1 Bearer Context Setup
|
||||
test_bearer_context_setup_request();
|
||||
test_bearer_context_setup_response();
|
||||
// E1 Interface Management
|
||||
test_e1_cuup_setup_request();
|
||||
test_e1_cuup_setup_response();
|
||||
test_e1_cuup_setup_failure();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration_release(gNB_RRC_INST *rrc,
|
||||
bool ue_associated_to_cuup(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue);
|
||||
sctp_assoc_t get_existing_cuup_for_ue(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue);
|
||||
sctp_assoc_t get_new_cuup_for_ue(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue, int sst, int sd);
|
||||
int rrc_gNB_process_e1_setup_req(sctp_assoc_t assoc_id, e1ap_setup_req_t *req);
|
||||
int rrc_gNB_process_e1_setup_req(sctp_assoc_t assoc_id, const e1ap_setup_req_t *req);
|
||||
bool is_cuup_associated(gNB_RRC_INST *rrc);
|
||||
|
||||
/* Process indication of E1 connection loss on CU-CP */
|
||||
|
||||
@@ -95,6 +95,7 @@
|
||||
#include "x2ap_messages_types.h"
|
||||
#include "xer_encoder.h"
|
||||
#include "E1AP/lib/e1ap_bearer_context_management.h"
|
||||
#include "E1AP/lib/e1ap_interface_management.h"
|
||||
|
||||
#ifdef E2_AGENT
|
||||
#include "openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h"
|
||||
@@ -2643,6 +2644,7 @@ void *rrc_gnb_task(void *args_p) {
|
||||
|
||||
case E1AP_SETUP_REQ:
|
||||
rrc_gNB_process_e1_setup_req(msg_p->ittiMsgHeader.originInstance, &E1AP_SETUP_REQ(msg_p));
|
||||
free_e1ap_cuup_setup_request(&E1AP_SETUP_REQ(msg_p));
|
||||
break;
|
||||
|
||||
case E1AP_BEARER_CONTEXT_SETUP_RESP:
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "openair2/F1AP/f1ap_ids.h"
|
||||
#include "rrc_messages_types.h"
|
||||
#include "tree.h"
|
||||
#include "e1ap_interface_management.h"
|
||||
|
||||
static int cuup_compare(const nr_rrc_cuup_container_t *a, const nr_rrc_cuup_container_t *b)
|
||||
{
|
||||
@@ -154,12 +155,13 @@ sctp_assoc_t get_new_cuup_for_ue(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue
|
||||
/**
|
||||
* @brief Trigger E1AP Setup Failure on CU-CP
|
||||
*/
|
||||
static void e1ap_setup_failure(sctp_assoc_t assoc_id, uint64_t transac_id)
|
||||
static void e1ap_setup_failure(sctp_assoc_t assoc_id, uint64_t transac_id, e1ap_cause_t cause)
|
||||
{
|
||||
MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_GNB, 0, E1AP_SETUP_FAIL);
|
||||
msg_p->ittiMsgHeader.originInstance = assoc_id;
|
||||
e1ap_setup_fail_t *setup_fail = &E1AP_SETUP_FAIL(msg_p);
|
||||
setup_fail->transac_id = transac_id;
|
||||
setup_fail->cause = cause;
|
||||
LOG_I(NR_RRC, "Triggering E1AP Setup Failure for transac_id %ld, assoc_id %ld\n",
|
||||
transac_id,
|
||||
msg_p->ittiMsgHeader.originInstance);
|
||||
@@ -169,7 +171,7 @@ static void e1ap_setup_failure(sctp_assoc_t assoc_id, uint64_t transac_id)
|
||||
/**
|
||||
* @brief E1AP Setup Request processing on CU-CP
|
||||
*/
|
||||
int rrc_gNB_process_e1_setup_req(sctp_assoc_t assoc_id, e1ap_setup_req_t *req)
|
||||
int rrc_gNB_process_e1_setup_req(sctp_assoc_t assoc_id, const e1ap_setup_req_t *req)
|
||||
{
|
||||
AssertFatal(req->supported_plmns <= PLMN_LIST_MAX_SIZE, "Supported PLMNs is more than PLMN_LIST_MAX_SIZE\n");
|
||||
gNB_RRC_INST *rrc = RC.nrrrc[0];
|
||||
@@ -185,13 +187,14 @@ int rrc_gNB_process_e1_setup_req(sctp_assoc_t assoc_id, e1ap_setup_req_t *req)
|
||||
c->setup_req->gNB_cu_up_id,
|
||||
c->setup_req->gNB_cu_up_name,
|
||||
c->assoc_id);
|
||||
e1ap_setup_failure(assoc_id, req->transac_id);
|
||||
e1ap_cause_t cause = { .type = E1AP_CAUSE_RADIO_NETWORK, .value = E1AP_RADIO_CAUSE_UNKNOWN_ALREADY_ALLOCATED_GNB_CU_UP_UE_E1AP_ID};
|
||||
e1ap_setup_failure(assoc_id, req->transac_id, cause);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < req->supported_plmns; i++) {
|
||||
PLMN_ID_t *id = &req->plmn[i].id;
|
||||
const PLMN_ID_t *id = &req->plmn[i].id;
|
||||
if (rrc->configuration.mcc[i] != id->mcc || rrc->configuration.mnc[i] != id->mnc) {
|
||||
LOG_E(NR_RRC,
|
||||
"PLMNs received from CUUP (mcc:%d, mnc:%d) did not match with PLMNs in RRC (mcc:%d, mnc:%d)\n",
|
||||
@@ -199,16 +202,16 @@ int rrc_gNB_process_e1_setup_req(sctp_assoc_t assoc_id, e1ap_setup_req_t *req)
|
||||
id->mnc,
|
||||
rrc->configuration.mcc[i],
|
||||
rrc->configuration.mnc[i]);
|
||||
e1ap_setup_failure(assoc_id, req->transac_id);
|
||||
e1ap_cause_t cause = { .type = E1AP_CAUSE_RADIO_NETWORK, .value = E1AP_RADIO_CAUSE_OTHER};
|
||||
e1ap_setup_failure(assoc_id, req->transac_id, cause);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_I(NR_RRC, "Accepting new CU-UP ID %ld name %s (assoc_id %d)\n", req->gNB_cu_up_id, req->gNB_cu_up_name, assoc_id);
|
||||
nr_rrc_cuup_container_t *cuup = malloc(sizeof(*cuup));
|
||||
AssertFatal(cuup, "out of memory\n");
|
||||
cuup->setup_req = malloc(sizeof(*cuup->setup_req));
|
||||
*cuup->setup_req = *req;
|
||||
nr_rrc_cuup_container_t *cuup = malloc_or_fail(sizeof(*cuup));
|
||||
cuup->setup_req = malloc_or_fail(sizeof(*cuup->setup_req));
|
||||
*cuup->setup_req = cp_e1ap_cuup_setup_request(req);
|
||||
cuup->assoc_id = assoc_id;
|
||||
RB_INSERT(rrc_cuup_tree, &rrc->cuups, cuup);
|
||||
rrc->num_cuups++;
|
||||
|
||||
Reference in New Issue
Block a user