diff --git a/doc/E1-design.md b/doc/E1-design.md
index 983013dce7..4184c946ea 100644
--- a/doc/E1-design.md
+++ b/doc/E1-design.md
@@ -17,17 +17,22 @@ connection setup only in split-mode, the rest is the same for CU):
sequenceDiagram
participant c as CUCP
participant u as CUUP
- u->c: SCTP connection setup (in split mode)
- u->>c: E1AP Setup Request
- Note over c: Execute rrc_gNB_process_e1_setup_req()
- c->>u: E1AP Setup Response
+ Note over c,u: E1 Setup Procedure
+ u->c: SCTP connection setup (in split mode)
+ u->>c: E1 Setup Request
+ Note over c: Execute rrc_gNB_process_e1_setup_req()
+ c->>u: E1 Setup Response
+ c-->>u: E1 Setup Failure
+
+ Note over c,u: E1 Bearer Context Setup Procedure
Note over c: Receives PDU session setup request from AMF
c->>u: Bearer Context Setup Request
Note over u: Execute e1_bearer_context_setup()
Configure DRBs and create GTP Tunnels for F1-U and N3
u->>c: Bearer Context Setup Response
Note over c: Execute rrc_gNB_process_e1_setup_req()
Sends F1-U UL TNL info to DU and receives DL TNL info
+ Note over c,u: E1 Bearer Context Modification (CU-CP Initiated) Procedure
c->>u: Bearer Context Modification Request
Note over u: Execute e1_bearer_context_modif()
Updates GTP Tunnels with received info
u->>c: Bearer Context Modification Response
diff --git a/openair2/COMMON/e1ap_messages_def.h b/openair2/COMMON/e1ap_messages_def.h
index ea24ac9e18..6da8e85ee1 100644
--- a/openair2/COMMON/e1ap_messages_def.h
+++ b/openair2/COMMON/e1ap_messages_def.h
@@ -27,6 +27,8 @@ MESSAGE_DEF(E1AP_SETUP_REQ , MESSAGE_PRIORITY_MED , e1ap_setup_req_t , e1ap_set
/* E1AP -> eNB_DU or eNB_CU_RRC -> E1AP application layer messages */
MESSAGE_DEF(E1AP_SETUP_RESP , MESSAGE_PRIORITY_MED, e1ap_setup_resp_t , e1ap_setup_resp)
+/* E1AP Setup Failure: gNB-CU-CP -> gNB-CU-UP */
+MESSAGE_DEF(E1AP_SETUP_FAIL, MESSAGE_PRIORITY_MED, e1ap_setup_fail_t, e1ap_setup_fail)
MESSAGE_DEF(E1AP_BEARER_CONTEXT_SETUP_REQ , MESSAGE_PRIORITY_MED , e1ap_bearer_setup_req_t , e1ap_bearer_setup_req)
diff --git a/openair2/COMMON/e1ap_messages_types.h b/openair2/COMMON/e1ap_messages_types.h
index b6400b53b5..605441e5f7 100644
--- a/openair2/COMMON/e1ap_messages_types.h
+++ b/openair2/COMMON/e1ap_messages_types.h
@@ -44,6 +44,7 @@
#define E1AP_REGISTER_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_register_req
#define E1AP_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_setup_req
#define E1AP_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.e1ap_setup_resp
+#define E1AP_SETUP_FAIL(mSGpTR) (mSGpTR)->ittiMsg.e1ap_setup_fail
#define E1AP_BEARER_CONTEXT_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_setup_req
#define E1AP_BEARER_CONTEXT_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_setup_resp
#define E1AP_BEARER_CONTEXT_MODIFICATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_setup_req
@@ -94,6 +95,11 @@ typedef struct e1ap_setup_resp_s {
long transac_id;
} e1ap_setup_resp_t;
+/* E1AP Setup Failure */
+typedef struct e1ap_setup_fail_s {
+ long transac_id;
+} e1ap_setup_fail_t;
+
typedef struct cell_group_s {
long id;
} cell_group_t;
diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c
index 353b8931e1..baeb690440 100644
--- a/openair2/E1AP/e1ap.c
+++ b/openair2/E1AP/e1ap.c
@@ -257,25 +257,36 @@ void e1ap_send_SETUP_RESPONSE(sctp_assoc_t assoc_id, const e1ap_setup_resp_t *e1
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) */
+ /* 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) */
+ /* 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;
@@ -284,8 +295,12 @@ static void fill_SETUP_FAILURE(long transac_id, E1AP_E1AP_PDU_t *pdu)
ieC2->value.choice.Cause.choice.radioNetwork = E1AP_CauseRadioNetwork_unspecified;
}
+/**
+ * @brief E1 Setup Failure ASN1 messager encoder
+*/
void e1apCUCP_send_SETUP_FAILURE(sctp_assoc_t assoc_id, long transac_id)
{
+ 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__);
@@ -404,18 +419,31 @@ int e1apCUUP_handle_SETUP_RESPONSE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst
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;
}
@@ -1875,6 +1903,10 @@ void *E1AP_CUCP_task(void *arg) {
e1ap_send_SETUP_RESPONSE(assoc_id, &E1AP_SETUP_RESP(msg));
break;
+ case E1AP_SETUP_FAIL:
+ e1apCUCP_send_SETUP_FAILURE(assoc_id, E1AP_SETUP_FAIL(msg).transac_id);
+ break;
+
case E1AP_BEARER_CONTEXT_SETUP_REQ:
e1apCUCP_send_BEARER_CONTEXT_SETUP_REQUEST(assoc_id, &E1AP_BEARER_CONTEXT_SETUP_REQ(msg));
break;
diff --git a/openair2/RRC/NR/rrc_gNB_cuup.c b/openair2/RRC/NR/rrc_gNB_cuup.c
index 6c5ea8aef5..5abdbcfac7 100644
--- a/openair2/RRC/NR/rrc_gNB_cuup.c
+++ b/openair2/RRC/NR/rrc_gNB_cuup.c
@@ -122,6 +122,19 @@ sctp_assoc_t get_new_cuup_for_ue(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue
return ue_data.e1_assoc_id;
}
+static void e1ap_setup_failure(sctp_assoc_t assoc_id, uint64_t transac_id)
+{
+ 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;
+ LOG_I(NR_RRC, "Triggering E1AP Setup Failure for transac_id %ld (%ld), assoc_id %ld\n",
+ transac_id,
+ E1AP_SETUP_FAIL(msg_p).transac_id,
+ msg_p->ittiMsgHeader.originInstance);
+ itti_send_msg_to_task(TASK_CUCP_E1, 0 /*unused by callee*/, msg_p);
+}
+
int rrc_gNB_process_e1_setup_req(sctp_assoc_t assoc_id, e1ap_setup_req_t *req)
{
AssertFatal(req->supported_plmns <= PLMN_LIST_MAX_SIZE, "Supported PLMNs is more than PLMN_LIST_MAX_SIZE\n");
@@ -138,6 +151,7 @@ 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);
return -1;
}
}
@@ -151,11 +165,12 @@ 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);
return -1;
}
}
- LOG_I(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);
+ 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));