From 40942e34a0d7d65725f853d4745f7c71b09d410e Mon Sep 17 00:00:00 2001
From: Konstantinos Alexandris <alexandr@eurecom.fr>
Date: Wed, 22 Aug 2018 15:32:22 +0200
Subject: [PATCH] Initial commit on X2AP (add target eNBs as input)

---
 cmake_targets/CMakeLists.txt          |  14 ++-
 openair2/COMMON/x2ap_messages_def.h   |  21 ++++
 openair2/COMMON/x2ap_messages_types.h | 152 ++++++++++++++++++++++++++
 openair2/ENB_APP/enb_app.c            |  35 ++++++
 openair2/ENB_APP/enb_config.c         | 145 ++++++++++++++++++++++++
 openair2/ENB_APP/enb_config.h         |   1 +
 openair2/ENB_APP/enb_paramdef.h       |  49 ++++++++-
 openair2/X2AP/x2ap_common.c           |   6 +-
 8 files changed, 416 insertions(+), 7 deletions(-)

diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index 17e2072d00..4c33eee8e4 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -474,6 +474,16 @@ add_library(X2AP_LIB
 include_directories ("${X2AP_C_DIR}")
 include_directories ("${X2AP_DIR}")
 
+#add_library(X2AP_ENB
+ # ${X2AP_DIR}/x2ap_eNB.c
+ # ${X2AP_DIR}/x2ap_eNB_decoder.c
+ # ${X2AP_DIR}/x2ap_eNB_encoder.c
+ # ${X2AP_DIR}/x2ap_eNB_handler.c
+ # ${X2AP_DIR}/x2ap_eNB_itti_messaging.c
+ # ${X2AP_DIR}/x2ap_eNB_management_procedures.c
+ # ${X2AP_DIR}/x2ap_eNB_generate_messages.c
+ # )
+
 # Hardware dependant options
 ###################################
 add_list1_option(NB_ANTENNAS_RX "2" "Number of antennas in reception" "1" "2" "4")
@@ -1933,7 +1943,7 @@ add_executable(lte-softmodem
 
 target_link_libraries (lte-softmodem
   -Wl,--start-group
-  RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB SCHED_RU_LIB PHY_COMMON PHY PHY_RU LFDS L2
+  RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB SCHED_RU_LIB PHY_COMMON PHY PHY_RU LFDS L2
   ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7
   NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB
   -Wl,--end-group z dl)
@@ -2009,7 +2019,7 @@ add_executable(lte-uesoftmodem
 
 target_link_libraries (lte-uesoftmodem
   -Wl,--start-group
-  RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_UE PHY_RU LFDS L2_UE SIMU
+  RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_UE PHY_RU LFDS L2_UE SIMU
   ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES}
   NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB
   -Wl,--end-group z dl)
diff --git a/openair2/COMMON/x2ap_messages_def.h b/openair2/COMMON/x2ap_messages_def.h
index 4690bba42e..36842c13d0 100644
--- a/openair2/COMMON/x2ap_messages_def.h
+++ b/openair2/COMMON/x2ap_messages_def.h
@@ -19,3 +19,24 @@
  *      contact@openairinterface.org
  */
 
+/* eNB application layer -> X2AP messages */
+/* ITTI LOG messages */
+/* ENCODER */
+MESSAGE_DEF(X2AP_RESET_REQUST_LOG             , MESSAGE_PRIORITY_MED, IttiMsgText                      , x2ap_reset_request_log)
+MESSAGE_DEF(X2AP_RESOURCE_STATUS_RESPONSE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText                      , x2ap_resource_status_response_log)
+MESSAGE_DEF(X2AP_RESOURCE_STATUS_FAILURE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText                      , x2ap_resource_status_failure_log)
+
+/* Messages for X2AP logging */
+MESSAGE_DEF(X2AP_SETUP_REQUEST_LOG           , MESSAGE_PRIORITY_MED, IttiMsgText                      , x2ap_setup_request_log)
+
+
+/* eNB application layer -> X2AP messages */
+MESSAGE_DEF(X2AP_REGISTER_ENB_REQ          , MESSAGE_PRIORITY_MED, x2ap_register_enb_req_t          , x2ap_register_enb_req)
+
+/* X2AP -> eNB application layer messages */
+MESSAGE_DEF(X2AP_REGISTER_ENB_CNF          , MESSAGE_PRIORITY_MED, x2ap_register_enb_cnf_t          , x2ap_register_enb_cnf)
+MESSAGE_DEF(X2AP_DEREGISTERED_ENB_IND      , MESSAGE_PRIORITY_MED, x2ap_deregistered_enb_ind_t      , x2ap_deregistered_enb_ind)
+
+/* handover messages X2AP <-> RRC */
+MESSAGE_DEF(X2AP_HANDOVER_REQ              , MESSAGE_PRIORITY_MED, x2ap_handover_req_t              , x2ap_handover_req)
+MESSAGE_DEF(X2AP_HANDOVER_REQ_ACK          , MESSAGE_PRIORITY_MED, x2ap_handover_req_ack_t          , x2ap_handover_req_ack)
diff --git a/openair2/COMMON/x2ap_messages_types.h b/openair2/COMMON/x2ap_messages_types.h
index 4690bba42e..d3c324a35c 100644
--- a/openair2/COMMON/x2ap_messages_types.h
+++ b/openair2/COMMON/x2ap_messages_types.h
@@ -19,3 +19,155 @@
  *      contact@openairinterface.org
  */
 
+#ifndef X2AP_MESSAGES_TYPES_H_
+#define X2AP_MESSAGES_TYPES_H_
+
+#include "PhysCellId.h"
+
+//-------------------------------------------------------------------------------------------//
+// Defines to access message fields.
+
+#define X2AP_REGISTER_ENB_REQ(mSGpTR)           (mSGpTR)->ittiMsg.x2ap_register_enb_req
+#define X2AP_HANDOVER_REQ(mSGpTR)               (mSGpTR)->ittiMsg.x2ap_handover_req
+#define X2AP_HANDOVER_REQ_ACK(mSGpTR)           (mSGpTR)->ittiMsg.x2ap_handover_req_ack
+#define X2AP_REGISTER_ENB_CNF(mSGpTR)           (mSGpTR)->ittiMsg.x2ap_register_enb_cnf
+#define X2AP_DEREGISTERED_ENB_IND(mSGpTR)       (mSGpTR)->ittiMsg.x2ap_deregistered_enb_ind
+
+
+#define X2AP_MAX_NB_ENB_IP_ADDRESS 2
+
+// eNB application layer -> X2AP messages
+typedef struct x2ap_register_enb_req_s {
+  /* Unique eNB_id to identify the eNB within EPC.
+   * For macro eNB ids this field should be 20 bits long.
+   * For home eNB ids this field should be 28 bits long.
+   */
+  uint32_t eNB_id;
+  /* The type of the cell */
+  enum cell_type_e cell_type;
+
+  /* Optional name for the cell
+   * NOTE: the name can be NULL (i.e no name) and will be cropped to 150
+   * characters.
+   */
+  char *eNB_name;
+
+  /* Tracking area code */
+  uint16_t tac;
+
+  /* Mobile Country Code
+   * Mobile Network Code
+   */
+  uint16_t mcc;
+  uint16_t mnc;
+  uint8_t  mnc_digit_length;
+
+  /*
+   * EARFCN
+   */
+  uint16_t fdd_uL_EARFCN;
+  uint16_t fdd_dL_EARFCN;
+  uint16_t tdd_EARFCN;
+
+
+  uint16_t fdd_uL_Transmission_Bandwidth;
+  uint16_t fdd_dL_Transmission_Bandwidth;
+  uint16_t tdd_Transmission_Bandwidth;
+
+
+  /* The local eNB IP address to bind */
+  net_ip_address_t enb_x2_ip_address;
+
+  /* Nb of MME to connect to */
+  uint8_t          nb_x2;
+
+  /* List of target eNB to connect to for X2*/
+  net_ip_address_t target_enb_x2_ip_address[X2AP_MAX_NB_ENB_IP_ADDRESS];
+
+  /* Number of SCTP streams used for associations */
+  uint16_t sctp_in_streams;
+  uint16_t sctp_out_streams;
+} x2ap_register_enb_req_t;
+
+//-------------------------------------------------------------------------------------------//
+// X2AP -> eNB application layer messages
+typedef struct x2ap_register_enb_cnf_s {
+  /* Nb of connected eNBs*/
+  uint8_t          nb_x2;
+} x2ap_register_enb_cnf_t;
+
+typedef struct x2ap_deregistered_enb_ind_s {
+  /* Nb of connected eNBs */
+  uint8_t          nb_x2;
+} x2ap_deregistered_enb_ind_t;
+
+//-------------------------------------------------------------------------------------------//
+// X2AP <-> RRC
+typedef struct x2ap_gummei_s {
+  uint16_t mcc;
+  uint16_t mnc;
+  uint8_t  mnc_len;
+  uint8_t  mme_code;
+  uint16_t mme_group_id;
+} x2ap_gummei_t;
+
+typedef struct x2ap_lastvisitedcell_info_s {
+  uint16_t mcc;
+  uint16_t mnc;
+  uint8_t  mnc_len;
+  PhysCellId_t target_physCellId;
+  cell_type_t cell_type;
+  uint64_t time_UE_StayedInCell;
+}x2ap_lastvisitedcell_info_t;
+
+//used for src
+typedef struct x2ap_handover_req_s {
+  int source_rnti;                       /* TODO: to be fixed/remove */
+  int source_x2id;                       /* TODO: to be fixed/remove */
+
+  unsigned  old_eNB_ue_s1ap_id:24;
+
+  PhysCellId_t target_physCellId;
+
+  x2ap_gummei_t ue_gummei;
+
+  /*UE-ContextInformation */
+
+  /* MME UE id  */
+  uint32_t mme_ue_s1ap_id;
+
+  security_capabilities_t security_capabilities;
+
+  uint8_t      kenb[32]; // keNB or keNB*
+
+  /*next_hop_chaining_coun */
+  long int     kenb_ncc;
+
+  /* UE aggregate maximum bitrate */
+  ambr_t ue_ambr;
+
+  uint8_t nb_e_rabs_tobesetup;
+
+ /* list of e_rab setup-ed by RRC layers */
+  e_rab_setup_t e_rabs_tobesetup[S1AP_MAX_E_RAB];
+
+  /* ue_context_pP->ue_context.e_rab[i].param.sgw_addr; */
+
+  x2ap_lastvisitedcell_info_t lastvisitedcell_info;
+
+  /* TODO: this parameter has to be removed */
+  int target_mod_id;
+} x2ap_handover_req_t;
+
+typedef struct x2ap_handover_req_ack_s {
+  int source_rnti;                       /* TODO: to be fixed/remove */
+  int source_x2id;                       /* TODO: to be fixed/remove */
+  /* TODO: this parameter has to be removed */
+  int target_mod_id;
+  uint8_t rrc_buffer[1024 /* arbitrary, big enough */];
+  int rrc_buffer_size;
+
+  uint32_t mme_ue_s1ap_id;
+} x2ap_handover_req_ack_t;
+
+#endif /* X2AP_MESSAGES_TYPES_H_ */
diff --git a/openair2/ENB_APP/enb_app.c b/openair2/ENB_APP/enb_app.c
index 40c6aeac44..2857c5e3d4 100644
--- a/openair2/ENB_APP/enb_app.c
+++ b/openair2/ENB_APP/enb_app.c
@@ -46,6 +46,10 @@
 #   include "gtpv1u_eNB_task.h"
 # endif
 
+//#   include "x2ap_eNB.h"
+#   include "x2ap_messages_types.h"
+#   define X2AP_ENB_REGISTER_RETRY_DELAY   10
+
 #include "openair1/PHY/INIT/phy_init.h"
 extern unsigned char NB_eNB_INST;
 #endif
@@ -135,6 +139,30 @@ static uint32_t eNB_app_register(uint32_t enb_id_start, uint32_t enb_id_end)//,
 # endif
 #endif
 
+/*------------------------------------------------------------------------------*/
+static uint32_t eNB_app_register_x2(uint32_t enb_id_start, uint32_t enb_id_end)
+{
+  uint32_t         enb_id;
+  MessageDef      *msg_p;
+  uint32_t         register_enb_x2_pending = 0;
+
+  for (enb_id = enb_id_start; (enb_id < enb_id_end) ; enb_id++) {
+
+    {
+
+      msg_p = itti_alloc_new_message (TASK_ENB_APP, X2AP_REGISTER_ENB_REQ);
+
+      RCconfig_X2(msg_p, enb_id);
+
+	//itti_send_msg_to_task (TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
+
+      register_enb_x2_pending++;
+    }
+  }
+
+  return register_enb_x2_pending;
+}
+
 /*------------------------------------------------------------------------------*/
 void *eNB_app_task(void *args_p)
 {
@@ -147,6 +175,9 @@ void *eNB_app_task(void *args_p)
   uint32_t                        registered_enb;
   long                            enb_register_retry_timer_id;
 # endif
+  uint32_t                        x2_register_enb_pending;
+  //uint32_t                        x2_registered_enb;
+  //long                            x2_enb_register_retry_timer_id;
   uint32_t                        enb_id;
   MessageDef                     *msg_p           = NULL;
   instance_t                      instance;
@@ -192,6 +223,10 @@ void *eNB_app_task(void *args_p)
   itti_send_msg_to_task(TASK_L2L1, INSTANCE_DEFAULT, msg_p);
 # endif
 
+  /* Try to register each eNB with each other */
+ // x2_registered_enb = 0;
+  x2_register_enb_pending = eNB_app_register_x2 (enb_id_start, enb_id_end);
+
   do {
     // Wait for a message
     itti_receive_msg (TASK_ENB_APP, &msg_p);
diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c
index 2b6931effa..9f2b4137a4 100644
--- a/openair2/ENB_APP/enb_config.c
+++ b/openair2/ENB_APP/enb_config.c
@@ -2419,6 +2419,151 @@ int RCconfig_S1(MessageDef *msg_p, uint32_t i) {
 return 0;
 }
 
+int RCconfig_X2(MessageDef *msg_p, uint32_t i)
+{
+  int   j, k, l;
+
+  int   enb_id;
+
+  char *address = NULL;
+  char *cidr    = NULL;
+
+  paramdef_t ENBSParams[] = ENBSPARAMS_DESC;
+  paramdef_t ENBParams[]  = ENBPARAMS_DESC;
+  paramlist_def_t ENBParamList = {ENB_CONFIG_STRING_ENB_LIST,NULL,0};
+
+  /* get global parameters, defined outside any section in the config file */
+  config_get( ENBSParams,sizeof(ENBSParams)/sizeof(paramdef_t),NULL);
+/*#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)
+    if (strcasecmp( *(ENBSParams[ENB_ASN1_VERBOSITY_IDX].strptr), ENB_CONFIG_STRING_ASN1_VERBOSITY_NONE) == 0) {
+      asn_debug      = 0;
+      asn1_xer_print = 0;
+    } else if (strcasecmp( *(ENBSParams[ENB_ASN1_VERBOSITY_IDX].strptr), ENB_CONFIG_STRING_ASN1_VERBOSITY_INFO) == 0) {
+      asn_debug      = 1;
+      asn1_xer_print = 1;
+    } else if (strcasecmp(*(ENBSParams[ENB_ASN1_VERBOSITY_IDX].strptr) , ENB_CONFIG_STRING_ASN1_VERBOSITY_ANNOYING) == 0) {
+      asn_debug      = 1;
+      asn1_xer_print = 2;
+    } else {
+      asn_debug      = 0;
+      asn1_xer_print = 0;
+    }
+#endif */
+
+  AssertFatal(i < ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt,
+              "Failed to parse config file %s, %uth attribute %s \n",
+              RC.config_file_name, i, ENB_CONFIG_STRING_ACTIVE_ENBS);
+
+  if (ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt > 0) {
+    // Output a list of all eNBs.
+    config_getlist( &ENBParamList,ENBParams,sizeof(ENBParams)/sizeof(paramdef_t),NULL);
+    if (ENBParamList.numelt > 0) {
+      for (k = 0; k < ENBParamList.numelt; k++) {
+        if (ENBParamList.paramarray[k][ENB_ENB_ID_IDX].uptr == NULL) {
+          // Calculate a default eNB ID
+# if defined(ENABLE_USE_MME)
+          uint32_t hash;
+
+          hash = s1ap_generate_eNB_id ();
+          enb_id = k + (hash & 0xFFFF8);
+# else
+          enb_id = k;
+# endif
+        } else {
+          enb_id = *(ENBParamList.paramarray[k][ENB_ENB_ID_IDX].uptr);
+        }
+
+        // search if in active list
+        for (j = 0; j < ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt; j++) {
+          if (strcmp(ENBSParams[ENB_ACTIVE_ENBS_IDX].strlistptr[j], *(ENBParamList.paramarray[k][ENB_ENB_NAME_IDX].strptr)) == 0) {
+
+            paramdef_t X2Params[]  = X2PARAMS_DESC;
+            paramlist_def_t X2ParamList = {ENB_CONFIG_STRING_TARGET_ENB_X2_IP_ADDRESS,NULL,0};
+
+            paramdef_t SCTPParams[]  = SCTPPARAMS_DESC;
+            paramdef_t NETParams[]  =  NETPARAMS_DESC;
+            char aprefix[MAX_OPTNAME_SIZE*2 + 8];
+
+            /* Some default/random parameters */
+
+            X2AP_REGISTER_ENB_REQ (msg_p).eNB_id = enb_id;
+
+            if (strcmp(*(ENBParamList.paramarray[k][ENB_CELL_TYPE_IDX].strptr), "CELL_MACRO_ENB") == 0) {
+              X2AP_REGISTER_ENB_REQ (msg_p).cell_type = CELL_MACRO_ENB;
+            } else  if (strcmp(*(ENBParamList.paramarray[k][ENB_CELL_TYPE_IDX].strptr), "CELL_HOME_ENB") == 0) {
+              X2AP_REGISTER_ENB_REQ (msg_p).cell_type = CELL_HOME_ENB;
+            } else {
+              AssertFatal (0,
+                  "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for cell_type choice: CELL_MACRO_ENB or CELL_HOME_ENB !\n",
+                  RC.config_file_name, i, *(ENBParamList.paramarray[k][ENB_CELL_TYPE_IDX].strptr));
+            }
+
+            X2AP_REGISTER_ENB_REQ (msg_p).eNB_name         = strdup(*(ENBParamList.paramarray[k][ENB_ENB_NAME_IDX].strptr));
+            X2AP_REGISTER_ENB_REQ (msg_p).tac              = (uint16_t)atoi(*(ENBParamList.paramarray[k][ENB_TRACKING_AREA_CODE_IDX].strptr));
+            X2AP_REGISTER_ENB_REQ (msg_p).mcc              = (uint16_t)atoi(*(ENBParamList.paramarray[k][ENB_MOBILE_COUNTRY_CODE_IDX].strptr));
+            X2AP_REGISTER_ENB_REQ (msg_p).mnc              = (uint16_t)atoi(*(ENBParamList.paramarray[k][ENB_MOBILE_NETWORK_CODE_IDX].strptr));
+            X2AP_REGISTER_ENB_REQ (msg_p).mnc_digit_length = strlen(*(ENBParamList.paramarray[k][ENB_MOBILE_NETWORK_CODE_IDX].strptr));
+
+            AssertFatal((X2AP_REGISTER_ENB_REQ (msg_p).mnc_digit_length == 2) ||
+                        (X2AP_REGISTER_ENB_REQ (msg_p).mnc_digit_length == 3),
+                        "BAD MNC DIGIT LENGTH %d",
+                        X2AP_REGISTER_ENB_REQ (msg_p).mnc_digit_length);
+
+            sprintf(aprefix,"%s.[%i]",ENB_CONFIG_STRING_ENB_LIST,k);
+            config_getlist( &X2ParamList,X2Params,sizeof(X2Params)/sizeof(paramdef_t),aprefix);
+
+            if(X2ParamList.numelt>X2AP_MAX_NB_ENB_IP_ADDRESS){
+		 LOG_E(RRC,"value of X2ParamList.numelt %d must be lower than X2AP_MAX_NB_ENB_IP_ADDRESS %d value: reconsider to increase X2AP_MAX_NB_ENB_IP_ADDRESS\n",X2ParamList.numelt,X2AP_MAX_NB_ENB_IP_ADDRESS);
+		 exit(1);
+	    }
+
+            X2AP_REGISTER_ENB_REQ (msg_p).nb_x2 = 0;
+            for (l = 0; l < X2ParamList.numelt; l++) {
+              X2AP_REGISTER_ENB_REQ (msg_p).nb_x2 += 1;
+
+              strcpy(X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv4_address,*(X2ParamList.paramarray[l][ENB_X2_IPV4_ADDRESS_IDX].strptr));
+              strcpy(X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv6_address,*(X2ParamList.paramarray[l][ENB_X2_IPV6_ADDRESS_IDX].strptr));
+
+              if (strcmp(*(X2ParamList.paramarray[l][ENB_X2_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv4") == 0) {
+                X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv4 = 1;
+              } else if (strcmp(*(X2ParamList.paramarray[l][ENB_X2_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv6") == 0) {
+                X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv6 = 1;
+              } else if (strcmp(*(X2ParamList.paramarray[l][ENB_X2_IP_ADDRESS_PREFERENCE_IDX].strptr), "no") == 0) {
+                X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv4 = 1;
+                X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv6 = 1;
+              }
+            }
+
+            // SCTP SETTING
+            X2AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = SCTP_OUT_STREAMS;
+            X2AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams  = SCTP_IN_STREAMS;
+# if defined(ENABLE_USE_MME)
+            sprintf(aprefix,"%s.[%i].%s",ENB_CONFIG_STRING_ENB_LIST,k,ENB_CONFIG_STRING_SCTP_CONFIG);
+            config_get( SCTPParams,sizeof(SCTPParams)/sizeof(paramdef_t),aprefix);
+            X2AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams = (uint16_t)*(SCTPParams[ENB_SCTP_INSTREAMS_IDX].uptr);
+            X2AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = (uint16_t)*(SCTPParams[ENB_SCTP_OUTSTREAMS_IDX].uptr);
+#endif
+
+            sprintf(aprefix,"%s.[%i].%s",ENB_CONFIG_STRING_ENB_LIST,k,ENB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
+
+            // NETWORK_INTERFACES
+            config_get( NETParams,sizeof(NETParams)/sizeof(paramdef_t),aprefix);
+
+            cidr = *(NETParams[ENB_IPV4_ADDR_FOR_X2C_IDX].strptr);
+            address = strtok(cidr, "/");
+
+            X2AP_REGISTER_ENB_REQ (msg_p).enb_x2_ip_address.ipv6 = 0;
+            X2AP_REGISTER_ENB_REQ (msg_p).enb_x2_ip_address.ipv4 = 1;
+
+            strcpy(X2AP_REGISTER_ENB_REQ (msg_p).enb_x2_ip_address.ipv4_address, address);
+          }
+        }
+      }
+    }
+  }
+return 0;
+}
+
 void RCConfig(void) {
 
   paramlist_def_t MACRLCParamList = {CONFIG_STRING_MACRLC_LIST,NULL,0};
diff --git a/openair2/ENB_APP/enb_config.h b/openair2/ENB_APP/enb_config.h
index 96156a4bc4..c6359f1563 100644
--- a/openair2/ENB_APP/enb_config.h
+++ b/openair2/ENB_APP/enb_config.h
@@ -106,6 +106,7 @@ void                          ru_config_display(void);
 
 int RCconfig_RRC(MessageDef *msg_p, uint32_t i, eNB_RRC_INST *rrc);
 int RCconfig_S1(MessageDef *msg_p, uint32_t i);
+int RCconfig_X2(MessageDef *msg_p, uint32_t i);
 
 #endif /* ENB_CONFIG_H_ */
 /** @} */
diff --git a/openair2/ENB_APP/enb_paramdef.h b/openair2/ENB_APP/enb_paramdef.h
index 23b4c2a837..71d7d634c0 100755
--- a/openair2/ENB_APP/enb_paramdef.h
+++ b/openair2/ENB_APP/enb_paramdef.h
@@ -704,6 +704,31 @@ typedef enum {
 #define ENB_MME_IP_ADDRESS_ACTIVE_IDX     2
 #define ENB_MME_IP_ADDRESS_PREFERENCE_IDX 3
 /*---------------------------------------------------------------------------------------------------------------------------------------*/
+
+/* X2 configuration parameters section name */
+#define ENB_CONFIG_STRING_TARGET_ENB_X2_IP_ADDRESS                "target_enb_x2_ip_address"
+
+/* X2 configuration parameters names   */
+
+
+#define ENB_CONFIG_STRING_TARGET_ENB_X2_IPV4_ADDRESS              "ipv4"
+#define ENB_CONFIG_STRING_TARGET_ENB_X2_IPV6_ADDRESS              "ipv6"
+#define ENB_CONFIG_STRING_TARGET_ENB_X2_IP_ADDRESS_PREFERENCE     "preference"
+
+
+/*-------------------------------------------------------------------------------------------------------------------------------------*/
+/*                                            X2 configuration parameters                                                             */
+/*   optname                                          helpstr   paramflags    XXXptr       defXXXval         type           numelt     */
+/*-------------------------------------------------------------------------------------------------------------------------------------*/
+#define X2PARAMS_DESC {  \
+{ENB_CONFIG_STRING_TARGET_ENB_X2_IPV4_ADDRESS,                   NULL,      0,         uptr:NULL,   defstrval:NULL,   TYPE_STRING,   0},          \
+{ENB_CONFIG_STRING_TARGET_ENB_X2_IPV6_ADDRESS,                   NULL,      0,         uptr:NULL,   defstrval:NULL,   TYPE_STRING,   0},          \
+{ENB_CONFIG_STRING_TARGET_ENB_X2_IP_ADDRESS_PREFERENCE,          NULL,      0,         uptr:NULL,   defstrval:NULL,   TYPE_STRING,   0},          \
+}
+
+#define ENB_X2_IPV4_ADDRESS_IDX          0
+#define ENB_X2_IPV6_ADDRESS_IDX          1
+#define ENB_X2_IP_ADDRESS_PREFERENCE_IDX 2
 /*---------------------------------------------------------------------------------------------------------------------------------------*/
 /* SCTP configuration parameters section name */
 #define ENB_CONFIG_STRING_SCTP_CONFIG                    "SCTP"
@@ -735,6 +760,12 @@ typedef enum {
 #define ENB_INTERFACE_NAME_FOR_S1U_IDX             2
 #define ENB_IPV4_ADDR_FOR_S1U_IDX                  3
 #define ENB_PORT_FOR_S1U_IDX                       4
+#define ENB_INTERFACE_NAME_FOR_X2C		   5
+#define ENB_IPV4_ADDR_FOR_X2C_IDX		   6
+#define ENB_PORT_FOR_X2C			   7
+#define ENB_INTERFACE_NAME_FOR_X2U		   8
+#define ENB_IPV4_ADDR_FOR_X2U			   9
+#define ENB_PORT_FOR_X2U  			  10
 
 /* S1 interface configuration parameters names   */
 #define ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_S1_MME "ENB_INTERFACE_NAME_FOR_S1_MME"
@@ -743,8 +774,16 @@ typedef enum {
 #define ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_S1U         "ENB_IPV4_ADDRESS_FOR_S1U"
 #define ENB_CONFIG_STRING_ENB_PORT_FOR_S1U              "ENB_PORT_FOR_S1U"
 
+/* X2 interface configuration parameters names */
+#define ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_X2C    "ENB_INTERFACE_NAME_FOR_X2C"
+#define ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_X2C         "ENB_IPV4_ADDRESS_FOR_X2C"
+#define ENB_CONFIG_STRING_ENB_PORT_FOR_X2C              "ENB_PORT_FOR_X2C"
+#define ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_X2U    "ENB_INTERFACE_NAME_FOR_X2U"
+#define ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_X2U         "ENB_IPV4_ADDRESS_FOR_X2U"
+#define ENB_CONFIG_STRING_ENB_PORT_FOR_X2U              "ENB_PORT_FOR_X2U"
+
 /*--------------------------------------------------------------------------------------------------------------------------------------------------*/
-/*                                            S1 interface configuration parameters                                                                 */
+/*                                            S1/X2 interface configuration parameters                                                                 */
 /*   optname                                            helpstr   paramflags    XXXptr              defXXXval             type           numelt     */
 /*--------------------------------------------------------------------------------------------------------------------------------------------------*/
 #define NETPARAMS_DESC {  \
@@ -752,7 +791,13 @@ typedef enum {
 {ENB_CONFIG_STRING_ENB_IPV4_ADDRESS_FOR_S1_MME,          NULL,      0,         strptr:NULL,         defstrval:NULL,      TYPE_STRING,      0},      \
 {ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_S1U,           NULL,      0,         strptr:NULL,         defstrval:NULL,      TYPE_STRING,      0},      \
 {ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_S1U,                NULL,      0,         strptr:NULL,         defstrval:NULL,      TYPE_STRING,      0},      \
-{ENB_CONFIG_STRING_ENB_PORT_FOR_S1U,                     NULL,      0,         uptr:NULL,           defintval:2152L,     TYPE_UINT,        0}       \
+{ENB_CONFIG_STRING_ENB_PORT_FOR_S1U,                     NULL,      0,         uptr:NULL,           defintval:2152L,     TYPE_UINT,        0},      \
+{ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_X2C,           NULL,      0,         strptr:NULL,         defstrval:NULL,      TYPE_STRING,      0},      \
+{ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_X2C,                NULL,      0,         strptr:NULL,         defstrval:NULL,      TYPE_STRING,      0},      \
+{ENB_CONFIG_STRING_ENB_PORT_FOR_X2C,                     NULL,      0,         uptr:NULL,           defintval:2152L,     TYPE_UINT,        0},      \
+{ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_X2U,           NULL,      0,         strptr:NULL,         defstrval:NULL,      TYPE_STRING,      0},      \
+{ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_X2U,                NULL,      0,         strptr:NULL,         defstrval:NULL,      TYPE_STRING,      0},      \
+{ENB_CONFIG_STRING_ENB_PORT_FOR_X2U,                     NULL,      0,         uptr:NULL,           defintval:2152L,     TYPE_UINT,        0}       \
 }   
 
 
diff --git a/openair2/X2AP/x2ap_common.c b/openair2/X2AP/x2ap_common.c
index 2ac875155d..cc2954f77b 100644
--- a/openair2/X2AP/x2ap_common.c
+++ b/openair2/X2AP/x2ap_common.c
@@ -66,7 +66,7 @@ ssize_t x2ap_generate_initiating_message(
   pdu.present = X2AP_X2AP_PDU_PR_initiatingMessage;
   pdu.choice.initiatingMessage.procedureCode = procedureCode;
   pdu.choice.initiatingMessage.criticality   = criticality;
-  ANY_fromType_aper(&pdu.choice.initiatingMessage.value, td, sptr);
+  ANY_fromType_aper((ANY_t *)&pdu.choice.initiatingMessage.value, td, sptr);
 
   if (asn1_xer_print) {
     xer_fprint(stdout, &asn_DEF_X2AP_X2AP_PDU, (void *)&pdu);
@@ -98,7 +98,7 @@ ssize_t x2ap_generate_successfull_outcome(
   pdu.present = X2AP_X2AP_PDU_PR_successfulOutcome;
   pdu.choice.successfulOutcome.procedureCode = procedureCode;
   pdu.choice.successfulOutcome.criticality   = criticality;
-  ANY_fromType_aper(&pdu.choice.successfulOutcome.value, td, sptr);
+  ANY_fromType_aper((ANY_t *)&pdu.choice.successfulOutcome.value, td, sptr);
 
   if (asn1_xer_print) {
     xer_fprint(stdout, &asn_DEF_X2AP_X2AP_PDU, (void *)&pdu);
@@ -130,7 +130,7 @@ ssize_t x2ap_generate_unsuccessfull_outcome(
   pdu.present = X2AP_X2AP_PDU_PR_unsuccessfulOutcome;
   pdu.choice.successfulOutcome.procedureCode = procedureCode;
   pdu.choice.successfulOutcome.criticality   = criticality;
-  ANY_fromType_aper(&pdu.choice.successfulOutcome.value, td, sptr);
+  ANY_fromType_aper((ANY_t *)&pdu.choice.successfulOutcome.value, td, sptr);
 
   if (asn1_xer_print) {
     xer_fprint(stdout, &asn_DEF_X2AP_X2AP_PDU, (void *)&pdu);
-- 
GitLab