From a2f41597c7438934a203ccf3cced35b6b65e8cee Mon Sep 17 00:00:00 2001
From: Sakthivel Velumani <velumani@eurecom.fr>
Date: Sat, 4 Jun 2022 13:50:55 +0530
Subject: [PATCH] Fixed bugs in E1 setup procedure E1 setup request decoding
 successful

---
 ci-scripts/conf_files/gNB_SA_CU.conf |  8 ++--
 common/utils/LOG/log.c               |  1 +
 openair2/E1AP/e1ap.c                 | 57 +++++++++++++++++++++++-----
 openair2/E1AP/e1ap_common.c          | 33 ++++++++++------
 openair2/E1AP/e1ap_common.h          |  4 +-
 openair2/GNB_APP/gnb_config.c        | 13 +++++--
 6 files changed, 87 insertions(+), 29 deletions(-)

diff --git a/ci-scripts/conf_files/gNB_SA_CU.conf b/ci-scripts/conf_files/gNB_SA_CU.conf
index 14bf78a43a1..253f4f180b8 100644
--- a/ci-scripts/conf_files/gNB_SA_CU.conf
+++ b/ci-scripts/conf_files/gNB_SA_CU.conf
@@ -182,13 +182,13 @@ gNBs =
                             }
                           );
 
-    E1_INTERFACE:
+    E1_INTERFACE =
     (
       {
-        type = "cu";
-        ipv4_cucp = "192.168.100.1";
+        type = "up";
+        ipv4_cucp = "127.0.0.100";
         port_cucp = 25;
-        ipv4_cuup = "192.168.100.2";
+        ipv4_cuup = "127.0.0.101";
         port_cuup = 25;
       }
     )
diff --git a/common/utils/LOG/log.c b/common/utils/LOG/log.c
index 043631d706a..b08838a9a79 100644
--- a/common/utils/LOG/log.c
+++ b/common/utils/LOG/log.c
@@ -485,6 +485,7 @@ int logInit (void)
   register_log_component("SDAP","",SDAP);
   register_log_component("S1AP","",S1AP);
   register_log_component("F1AP","",F1AP);
+  register_log_component("E1AP","",E1AP);
   register_log_component("M2AP","",M2AP);
   register_log_component("M3AP","",M3AP);
   register_log_component("SCTP","",SCTP);
diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c
index 9cc8173eaaa..8b6665fbfe4 100644
--- a/openair2/E1AP/e1ap.c
+++ b/openair2/E1AP/e1ap.c
@@ -92,7 +92,7 @@ int e1ap_handle_message(instance_t instance, uint32_t assoc_id,
   return ret;
 }
 
-void cuup_task_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind) {
+void cuxp_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,
@@ -205,7 +205,7 @@ int e1apCUUP_send_SETUP_REQUEST(instance_t instance) {
     MCC_MNC_TO_PLMNID(setup->plmns[i].mcc, setup->plmns[i].mnc, setup->plmns[i].mnc_digit_length, &supportedPLMN->pLMN_Identity);
   }
 
-  e1ap_encode_send(0, instance, &pdu, 0, __func__);
+  e1ap_encode_send(UPtype, instance, &pdu, 0, __func__);
   return 0;
 }
 
@@ -228,7 +228,7 @@ int e1apCUCP_send_SETUP_RESPONSE(instance_t instance,
   ieC1->value.present              = E1AP_GNB_CU_UP_E1SetupResponseIEs__value_PR_TransactionID;
   ieC1->value.choice.TransactionID = e1ap_setup_resp->transac_id;
 
-  e1ap_encode_send(0, instance, &pdu, 0, __func__);
+  e1ap_encode_send(CPtype, instance, &pdu, 0, __func__);
   return 0;
 }
 
@@ -259,7 +259,7 @@ int e1apCUCP_send_SETUP_FAILURE(instance_t instance,
   ieC2->value.choice.Cause.present = E1AP_Cause_PR_radioNetwork; //choose this accordingly
   ieC2->value.choice.Cause.choice.radioNetwork = E1AP_CauseRadioNetwork_unspecified;
 
-  e1ap_encode_send(0, instance, &pdu, 0, __func__);
+  e1ap_encode_send(CPtype, instance, &pdu, 0, __func__);
   return 0;
 }
 
@@ -408,7 +408,7 @@ int e1apCUUP_send_CONFIGURATION_UPDATE(instance_t instance) {
     TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &TNLAtoRemove->tNLAssociationTransportLayerAddress.choice.endpoint_IP_Address); // TODO: correct me
   }
 
-  e1ap_encode_send(0, instance, &pdu, 0, __func__);
+  e1ap_encode_send(UPtype, instance, &pdu, 0, __func__);
   return 0;
 }
 
@@ -632,7 +632,7 @@ int e1apCUCP_send_BEARER_CONTEXT_SETUP_REQUEST(instance_t instance,
     }
   }
 
-  e1ap_encode_send(0, instance, &pdu, 0, __func__);
+  e1ap_encode_send(CPtype, instance, &pdu, 0, __func__);
   return 0;
 }
 
@@ -757,7 +757,7 @@ int e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(instance_t instance,
       }
     }
   }
-  e1ap_encode_send(0, instance, &pdu, 0, __func__);
+  e1ap_encode_send(UPtype, instance, &pdu, 0, __func__);
   return 0;
 }
 
@@ -1116,6 +1116,27 @@ void cucp_task_send_sctp_init_req(instance_t instance, char *my_addr) {
   itti_send_msg_to_task(TASK_SCTP, instance, message_p);
 }
 
+void cucp_task_handle_sctp_association_ind(instance_t instance, sctp_new_association_ind_t *sctp_new_association_ind) {
+  createE1inst(CPtype, instance, NULL);
+  e1ap_setup_req_t *setup_req = &getCxtE1(CPtype, instance)->setupReq;
+  setup_req->assoc_id         = sctp_new_association_ind->assoc_id;
+  setup_req->sctp_in_streams  = sctp_new_association_ind->in_streams;
+  setup_req->sctp_out_streams = sctp_new_association_ind->out_streams;
+  setup_req->default_sctp_stream_id = 0;
+}
+
+void cucp_task_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp) {
+  DevAssert(sctp_new_association_resp != NULL);
+
+  if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
+    LOG_W(E1AP, "Received unsuccessful result for SCTP association (%u), instance %ld, cnx_id %u\n",
+          sctp_new_association_resp->sctp_state,
+          instance,
+          sctp_new_association_resp->ulp_cnx_id);
+    return;
+  }
+}
+
 void *E1AP_CUCP_task(void *arg) {
   LOG_I(E1AP, "Starting E1AP at CU CP\n");
   MessageDef *msg = NULL;
@@ -1123,11 +1144,24 @@ void *E1AP_CUCP_task(void *arg) {
 
   while (1) {
     itti_receive_msg(TASK_CUCP_E1, &msg);
+    instance_t myInstance=ITTI_MSG_DESTINATION_INSTANCE(msg);
 
     switch (ITTI_MSG_ID(msg)) {
+      case SCTP_NEW_ASSOCIATION_IND:
+        LOG_I(E1AP, "CUCP Task Received SCTP_NEW_ASSOCIATION_IND for instance %ld\n", myInstance);
+        cucp_task_handle_sctp_association_ind(ITTI_MSG_ORIGIN_INSTANCE(msg),
+                                              &msg->ittiMsg.sctp_new_association_ind);
+        break;
+
+      case SCTP_NEW_ASSOCIATION_RESP:
+        LOG_I(E1AP, "CUCP Task Received SCTP_NEW_ASSOCIATION_RESP for instance %ld\n", myInstance);
+        cucp_task_handle_sctp_association_resp(ITTI_MSG_ORIGIN_INSTANCE(msg),
+                                               &msg->ittiMsg.sctp_new_association_resp);
+        break;
+
       case E1AP_SETUP_REQ:
         LOG_I(E1AP, "CUCP Task Received E1AP_SETUP_REQ for instance %ld. Initializing SCTP listener\n",
-              ITTI_MSG_DESTINATION_INSTANCE(msg));
+              myInstance);
         e1ap_setup_req_t *req = &E1AP_SETUP_REQ(msg);
         char *ipaddr;
         if (req->CUCP_e1_ip_address.ipv4 == 0) {
@@ -1139,6 +1173,11 @@ void *E1AP_CUCP_task(void *arg) {
         cucp_task_send_sctp_init_req(0, ipaddr);
         break;
 
+      case SCTP_DATA_IND:
+        LOG_I(E1AP, "CUCP Task Received SCTP_DATA_IND\n");
+        cuxp_task_handle_sctp_data_ind(myInstance, &msg->ittiMsg.sctp_data_ind);
+        break;
+
       default:
         LOG_E(E1AP, "Unknown message received in TASK_CUCP_E1\n");
         break;
@@ -1172,7 +1211,7 @@ void *E1AP_CUUP_task(void *arg) {
 
       case SCTP_DATA_IND:
         LOG_I(E1AP, "CUUP Task Received SCTP_DATA_IND\n");
-        cuup_task_handle_sctp_data_ind(myInstance, &msg->ittiMsg.sctp_data_ind);
+        cuxp_task_handle_sctp_data_ind(myInstance, &msg->ittiMsg.sctp_data_ind);
         break;
 
       default:
diff --git a/openair2/E1AP/e1ap_common.c b/openair2/E1AP/e1ap_common.c
index 8b7d20dc3be..bc5ae0789d6 100644
--- a/openair2/E1AP/e1ap_common.c
+++ b/openair2/E1AP/e1ap_common.c
@@ -34,18 +34,29 @@ e1ap_upcp_inst_t *getCxtE1(E1_t type, instance_t instance) {
   return type ? e1ap_up_inst[instance] : e1ap_cp_inst[instance];
 }
 
-int e1ap_assoc_id(bool isCu, instance_t instance) {
-  return 0;
+int e1ap_assoc_id(E1_t type, instance_t instance) {
+  if (type == CPtype) {
+    AssertFatal(e1ap_cp_inst[instance] != NULL, "Trying to access uninitiated instance of CUCP\n");
+    return e1ap_cp_inst[instance]->setupReq.assoc_id;
+  } else if (type == UPtype) {
+    AssertFatal(e1ap_up_inst[instance] != NULL, "Trying to access uninitiated instance of CUUP\n");
+    return e1ap_up_inst[instance]->setupReq.assoc_id;
+  } else {
+    AssertFatal(false, "Unknown CU type\n");
+  }
+  return -1;
 }
 
 void createE1inst(E1_t type, instance_t instance, e1ap_setup_req_t *req) {
   if (type == CPtype) {
     AssertFatal(e1ap_cp_inst[instance] == NULL, "Double call to E1 CP instance %d\n", (int)instance);
     e1ap_cp_inst[instance] = (e1ap_upcp_inst_t *) calloc(1, sizeof(e1ap_upcp_inst_t));
-  } else {
+  } else if (type == UPtype) {
     AssertFatal(e1ap_up_inst[instance] == NULL, "Double call to E1 UP instance %d\n", (int)instance);
     e1ap_up_inst[instance] = (e1ap_upcp_inst_t *) calloc(1, sizeof(e1ap_upcp_inst_t));
     memcpy(&e1ap_up_inst[instance]->setupReq, req, sizeof(e1ap_setup_req_t));
+  } else {
+    AssertFatal(false, "Unknown CU type\n");
   }
 }
 
@@ -76,7 +87,7 @@ E1AP_TransactionID_t E1AP_get_next_transaction_identifier() {
   int freeIdx;
 
   while (!isTransacIdValid) {
-    genTransacId = rand();
+    genTransacId = rand() & 255;
     isTransacIdValid = check_transac_id(genTransacId, &freeIdx);
   }
 
@@ -143,7 +154,7 @@ int e1ap_decode_pdu(E1AP_E1AP_PDU_t *pdu, const uint8_t *const buffer, uint32_t
   asn_dec_rval_t dec_ret;
   DevAssert(buffer != NULL);
   dec_ret = aper_decode(NULL,
-                        &asn_DEF_F1AP_F1AP_PDU,
+                        &asn_DEF_E1AP_E1AP_PDU,
                         (void **)&pdu,
                         buffer,
                         length,
@@ -151,9 +162,9 @@ int e1ap_decode_pdu(E1AP_E1AP_PDU_t *pdu, const uint8_t *const buffer, uint32_t
                         0);
 
   if (asn1_xer_print_e1ap) {
-    LOG_E(F1AP, "----------------- ASN1 DECODER PRINT START----------------- \n");
+    LOG_E(E1AP, "----------------- ASN1 DECODER PRINT START----------------- \n");
     xer_fprint(stdout, &asn_DEF_E1AP_E1AP_PDU, pdu);
-    LOG_E(F1AP, "----------------- ASN1 DECODER PRINT END ----------------- \n");
+    LOG_E(E1AP, "----------------- ASN1 DECODER PRINT END ----------------- \n");
   }
 
   if (dec_ret.code != RC_OK) {
@@ -179,7 +190,7 @@ int e1ap_decode_pdu(E1AP_E1AP_PDU_t *pdu, const uint8_t *const buffer, uint32_t
   return -1;
 }
 
-int e1ap_encode_send(bool isCu, instance_t instance, E1AP_E1AP_PDU_t *pdu, uint16_t stream, const char *func) {
+int e1ap_encode_send(E1_t type, instance_t instance, E1AP_E1AP_PDU_t *pdu, uint16_t stream, const char *func) {
   DevAssert(pdu != NULL);
 
   if (asn1_xer_print_e1ap) {
@@ -197,15 +208,15 @@ int e1ap_encode_send(bool isCu, instance_t instance, E1AP_E1AP_PDU_t *pdu, uint1
   }
 
   void *buffer = NULL;
-  ssize_t encoded = aper_encode_to_new_buffer(&asn_DEF_E1AP_E1AP_PDU, 0, pdu, buffer);
+  ssize_t encoded = aper_encode_to_new_buffer(&asn_DEF_E1AP_E1AP_PDU, 0, pdu, &buffer);
 
   if (encoded < 0) {
     LOG_E(E1AP, "%s: Failed to encode E1AP message\n", func);
     return -1;
   } else {
-    MessageDef *message = itti_alloc_new_message(isCu?TASK_CUCP_E1:TASK_CUUP_E1, 0, SCTP_DATA_REQ);
+    MessageDef *message = itti_alloc_new_message((type==CPtype)?TASK_CUCP_E1:TASK_CUUP_E1, 0, SCTP_DATA_REQ);
     sctp_data_req_t *s = &message->ittiMsg.sctp_data_req;
-    s->assoc_id      = e1ap_assoc_id(isCu,instance);
+    s->assoc_id      = e1ap_assoc_id(type, instance);
     s->buffer        = buffer;
     s->buffer_length = encoded;
     s->stream        = stream;
diff --git a/openair2/E1AP/e1ap_common.h b/openair2/E1AP/e1ap_common.h
index c283bb6a1b2..72c4accaecb 100644
--- a/openair2/E1AP/e1ap_common.h
+++ b/openair2/E1AP/e1ap_common.h
@@ -36,9 +36,9 @@ void createE1inst(E1_t type, instance_t instance, e1ap_setup_req_t *req);
 
 bool check_transac_id(E1AP_TransactionID_t id, int *freeIdx);
 
-int e1ap_assoc_id(bool isCu, instance_t instance);
+int e1ap_assoc_id(E1_t type, instance_t instance);
 
-int e1ap_encode_send(bool isCu, instance_t instance, E1AP_E1AP_PDU_t *pdu, uint16_t stream, const char *func);
+int e1ap_encode_send(E1_t type, instance_t instance, E1AP_E1AP_PDU_t *pdu, uint16_t stream, const char *func);
 
 void e1ap_common_init();
 #endif /* E1AP_COMMON_H_ */
diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c
index 52316f8cc44..4d5b2ad6566 100644
--- a/openair2/GNB_APP/gnb_config.c
+++ b/openair2/GNB_APP/gnb_config.c
@@ -1835,6 +1835,8 @@ int RCconfig_NR_CU_E1(MessageDef *msg_p, uint32_t i) {
   paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST,NULL,0};
   paramlist_def_t GNBE1ParamList = {GNB_CONFIG_STRING_E1_PARAMETERS, NULL, 0};
   config_get(GNBSParams, sizeof(GNBSParams)/sizeof(paramdef_t), NULL);
+  char aprefix[MAX_OPTNAME_SIZE*2 + 8];
+  sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0);
   int num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt;
   AssertFatal (i < num_gnbs,
                "Failed to parse config file no %uth element in %s \n",i, GNB_CONFIG_STRING_ACTIVE_GNBS);
@@ -1843,8 +1845,9 @@ int RCconfig_NR_CU_E1(MessageDef *msg_p, uint32_t i) {
     config_getlist(&GNBParamList, GNBParams, sizeof(GNBParams)/sizeof(paramdef_t), NULL);
     AssertFatal(GNBParamList.paramarray[i][GNB_GNB_ID_IDX].uptr != NULL,
                 "gNB id %u is not defined in configuration file\n",i);
-    config_getlist(&GNBE1ParamList, GNBE1Params, sizeof(GNBE1Params)/sizeof(paramdef_t), NULL);
+    config_getlist(&GNBE1ParamList, GNBE1Params, sizeof(GNBE1Params)/sizeof(paramdef_t), aprefix);
     e1ap_setup_req_t *e1Setup = &E1AP_SETUP_REQ(msg_p);
+    msg_p->ittiMsgHeader.destinationInstance = 0;
     e1Setup->gNB_cu_up_id = *(GNBParamList.paramarray[0][GNB_GNB_ID_IDX].uptr);
 
     paramdef_t PLMNParams[] = GNBPLMNPARAMS_DESC;
@@ -1855,7 +1858,7 @@ int RCconfig_NR_CU_E1(MessageDef *msg_p, uint32_t i) {
     for (int I = 0; I < sizeof(PLMNParams) / sizeof(paramdef_t); ++I)
       PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]);
 
-    config_getlist(&PLMNParamList, PLMNParams, sizeof(PLMNParams)/sizeof(paramdef_t), NULL);
+    config_getlist(&PLMNParamList, PLMNParams, sizeof(PLMNParams)/sizeof(paramdef_t), aprefix);
     int numPLMNs = PLMNParamList.numelt;
     e1Setup->supported_plmns = numPLMNs;
 
@@ -1866,8 +1869,10 @@ int RCconfig_NR_CU_E1(MessageDef *msg_p, uint32_t i) {
     }
 
     strcpy(e1Setup->CUCP_e1_ip_address.ipv4_address, *(GNBE1ParamList.paramarray[0][GNB_CONFIG_E1_IPV4_ADDRESS_CUCP].strptr));
+    e1Setup->CUCP_e1_ip_address.ipv4 = 1;
     e1Setup->port_cucp = *GNBE1ParamList.paramarray[0][GNB_CONFIG_E1_PORT_CUCP].uptr;
     strcpy(e1Setup->CUUP_e1_ip_address.ipv4_address, *(GNBE1ParamList.paramarray[0][GNB_CONFIG_E1_IPV4_ADDRESS_CUUP].strptr));
+    e1Setup->CUUP_e1_ip_address.ipv4 = 1;
     e1Setup->port_cuup = *GNBE1ParamList.paramarray[0][GNB_CONFIG_E1_PORT_CUUP].uptr;
 
     e1Setup->cn_support = *GNBE1ParamList.paramarray[0][GNB_CONFIG_E1_CN_SUPPORT].uptr;
@@ -2314,7 +2319,9 @@ static ngran_node_t get_node_type(void)
 
   config_getlist( &MacRLC_ParamList,MacRLC_Params,sizeof(MacRLC_Params)/sizeof(paramdef_t), NULL);   
   config_getlist( &GNBParamList,GNBParams,sizeof(GNBParams)/sizeof(paramdef_t),NULL);  
-  config_getlist( &GNBE1ParamList, GNBE1Params, sizeof(GNBE1Params)/sizeof(paramdef_t), NULL);
+  char aprefix[MAX_OPTNAME_SIZE*2 + 8];
+  sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0);
+  config_getlist( &GNBE1ParamList, GNBE1Params, sizeof(GNBE1Params)/sizeof(paramdef_t), aprefix);
 
   if ( MacRLC_ParamList.numelt > 0) {
     RC.nb_nr_macrlc_inst = MacRLC_ParamList.numelt; 
-- 
GitLab