Enhanced SIM for E2AP v1 for TS UC
[sim/e2-interface.git] / e2sim / e2apv1sim / src / ASN1 / lib / asn_x2ap.cpp
diff --git a/e2sim/e2apv1sim/src/ASN1/lib/asn_x2ap.cpp b/e2sim/e2apv1sim/src/ASN1/lib/asn_x2ap.cpp
new file mode 100644 (file)
index 0000000..dae9ca8
--- /dev/null
@@ -0,0 +1,428 @@
+/*****************************************************************************
+#                                                                            *
+# Copyright 2019 AT&T Intellectual Property                                  *
+# Copyright 2019 Nokia                                                       *
+#                                                                            *
+# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0                            *
+#                                                                            *
+# 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.                                             *
+#                                                                            *
+******************************************************************************/
+
+#include "asn_x2ap.hpp"
+#include "asn_x2ap_wrapper.hpp"
+
+/*-----------------------------------------------------------------------
+                              COMMON ROUTINES
+-------------------------------------------------------------------------
+*/
+x2ap_pdu_t* new_x2ap_pdu(void)
+{
+    X2APpduWrapper* pduWrapper = new X2APpduWrapper();
+    return reinterpret_cast<x2ap_pdu_t*>(pduWrapper);
+}
+
+void x2ap_asn_print(x2ap_pdu_t* pdu, char* buf, size_t buf_size)
+{
+  X2APpduWrapper* pduWrapper = reinterpret_cast<X2APpduWrapper*>(pdu);
+
+  buf[0] = 0;
+
+  strncat(buf, asn::get_printed(pduWrapper->ref_pdu()).c_str(), buf_size - 1);
+}
+
+int x2ap_asn_per_encode(x2ap_pdu_t* pdu, unsigned char* buf, size_t buf_size,
+                                          char* err_buf, size_t err_buf_size)
+{
+  X2APpduWrapper* pduWrapper = reinterpret_cast<X2APpduWrapper*>(pdu);
+
+  asn::per::EncoderCtx ctx{ buf, buf_size };
+
+  if (!asn::per::pack(pduWrapper->ref_pdu(), ctx)) {
+      err_buf[0] = 0;
+      // strncat(err_buf, ctx.refErrorCtx().toString().c_str(), err_buf_size - 1);
+      return -1;
+  } else {
+    return static_cast<int>(ctx.refBuffer().getBytesUsed());
+  }
+
+}
+
+int x2ap_asn_per_decode(x2ap_pdu_t* pdu, unsigned char const* buf, size_t buf_size,
+                                          char* err_buf, size_t err_buf_size)
+{
+  X2APpduWrapper* pduWrapper = reinterpret_cast<X2APpduWrapper*>(pdu);
+
+  asn::per::DecoderCtx ctx{ buf,
+                            buf_size,
+                            pduWrapper->m_allocation_buffer,
+                            pduWrapper->m_allocation_buffer_size };
+
+  if (!asn::per::unpack(pduWrapper->ref_pdu(), ctx)) {
+      err_buf[0] = 0;
+      // strncat(err_buf, ctx.refErrorCtx().toString().c_str(), err_buf_size - 1);
+      return -1;
+  }
+
+  return 0;
+
+}
+
+int x2ap_get_index(x2ap_pdu_t* pdu)
+{
+  X2APpduWrapper* pduWrapper = reinterpret_cast<X2APpduWrapper*>(pdu);
+
+  return pduWrapper->ref_pdu().get_index();
+}
+
+int x2ap_get_procedureCode(x2ap_pdu_t* pdu)
+{
+  X2APpduWrapper* pduWrapper = reinterpret_cast<X2APpduWrapper*>(pdu);
+
+  switch(pduWrapper->ref_pdu().get_index())
+  {
+    case 1:
+      return pduWrapper->ref_pdu().get_initiatingMessage()->ref_procedureCode().get();
+      break;
+
+    case 2:
+      return pduWrapper->ref_pdu().get_successfulOutcome()->ref_procedureCode().get();
+      break;
+
+    case 3:
+      return pduWrapper->ref_pdu().get_unsuccessfulOutcome()->ref_procedureCode().get();
+      break;
+
+    default:
+      return -1;
+  }
+
+}
+
+/*-----------------------------------------------------------------------
+                              MESSAGE GENERATORS
+-------------------------------------------------------------------------
+*/
+//X2Setup
+bool x2ap_init_X2SetupRequest(x2ap_pdu_t* pdu)
+{
+    X2APpduWrapper* pduWrapper = reinterpret_cast<X2APpduWrapper*>(pdu);
+
+    //Initialization
+    pduWrapper->ref_pdu().select_initiatingMessage();
+    pduWrapper->ref_pdu().select_initiatingMessage().clear();
+    pduWrapper->ref_pdu().select_initiatingMessage().ref_procedureCode().select_id_x2Setup();
+    pduWrapper->ref_pdu().select_initiatingMessage().ref_criticality().select_id_x2Setup();
+    pduWrapper->ref_pdu().select_initiatingMessage().ref_value().select_id_x2Setup();
+
+    return true;
+}
+
+bool x2ap_create_X2SetupRequest(x2ap_pdu_t* pdu, eNB_config &cfg)
+{
+  X2APpduWrapper* pduWrapper = reinterpret_cast<X2APpduWrapper*>(pdu);
+
+  /* Initiaization */
+  pduWrapper->ref_pdu().select_initiatingMessage().ref_procedureCode().select_id_x2Setup();
+  pduWrapper->ref_pdu().select_initiatingMessage().ref_criticality().select_id_x2Setup();
+
+  X2SetupRequest* container =
+    &(pduWrapper->ref_pdu().select_initiatingMessage().ref_value().select_id_x2Setup());
+
+  using IE_value_t = X2SetupRequest::protocolIEs_t::value_type;
+
+  /* X2SetupRequest-IEs : GlobalENB-ID*/
+  IE_value_t* val_GlobalENB_ID = new IE_value_t;
+  container->ref_protocolIEs().push_back(*val_GlobalENB_ID);
+
+  val_GlobalENB_ID->ref_id().select_id_GlobalENB_ID();
+  val_GlobalENB_ID->ref_criticality().select_id_GlobalENB_ID();
+  val_GlobalENB_ID->ref_value().select_id_GlobalENB_ID().ref_pLMN_Identity()
+                                         .set(3, cfg.pLMN_Identity);
+
+  val_GlobalENB_ID->ref_value().select_id_GlobalENB_ID().ref_eNB_ID()
+                  .select_macro_eNB_ID().set_buffer(20, cfg.macro_eNB_ID);
+
+  /* X2SetupRequest-IEs : ServedCells*/
+  IE_value_t* val_ServedCells = new IE_value_t;
+  container->ref_protocolIEs().push_back(*val_ServedCells);
+
+  val_ServedCells->ref_id().select_id_ServedCells();
+  val_ServedCells->ref_criticality().select_id_ServedCells();
+  val_ServedCells->ref_value().select_id_ServedCells();
+
+  //Add servedCellInfo
+  ServedCells::value_type* elm = new ServedCells::value_type();
+  ServedCell_Information* info = &(elm->ref_servedCellInfo());
+  {
+    //Set ServedCell-Information: pCI, cellId, tAC, broadcastPLMNs, eUTRA-Mode-Info
+    info->ref_pCI().set(cfg.pCI);
+    info->ref_cellId().ref_pLMN_Identity().set(3, cfg.pLMN_Identity);
+    info->ref_cellId().ref_eUTRANcellIdentifier().set_buffer(28, cfg.eUTRANcellIdentifier);
+    info->ref_tAC().set(2, cfg.tAC);
+
+    BroadcastPLMNs_Item::value_type* item = new BroadcastPLMNs_Item::value_type();
+    item->set(3, cfg.pLMN_Identity);
+    info->ref_broadcastPLMNs().push_back(*item);
+
+    info->ref_eUTRA_Mode_Info().select_fDD().ref_uL_EARFCN().set(cfg.uL_EARFCN);
+    info->ref_eUTRA_Mode_Info().select_fDD().ref_dL_EARFCN().set(cfg.dL_EARFCN);
+    info->ref_eUTRA_Mode_Info().select_fDD().ref_uL_Transmission_Bandwidth()
+          .set(static_cast<Transmission_Bandwidth::index_t>(cfg.uL_Bandwidth));
+    info->ref_eUTRA_Mode_Info().select_fDD().ref_dL_Transmission_Bandwidth()
+          .set(static_cast<Transmission_Bandwidth::index_t>(cfg.dL_Bandwidth));
+  }
+  val_ServedCells->ref_value().select_id_ServedCells().push_back(*elm);
+
+  return true;
+}
+
+bool x2ap_create_X2SetupResponse(x2ap_pdu_t* pdu, eNB_config &cfg)
+{
+  X2APpduWrapper* pduWrapper = reinterpret_cast<X2APpduWrapper*>(pdu);
+
+  /* Initiaization */
+  pduWrapper->ref_pdu().select_successfulOutcome().ref_procedureCode().select_id_x2Setup();
+  pduWrapper->ref_pdu().select_successfulOutcome().ref_criticality().select_id_x2Setup();
+
+  X2SetupResponse* container =
+    &(pduWrapper->ref_pdu().select_successfulOutcome().ref_value().select_id_x2Setup());
+
+  using IE_value_t = X2SetupResponse::protocolIEs_t::value_type;
+
+  /* X2SetupResponse-IEs : GlobalENB-ID*/
+  IE_value_t* val_GlobalENB_ID = new IE_value_t;
+  container->ref_protocolIEs().push_back(*val_GlobalENB_ID);
+
+  val_GlobalENB_ID->ref_id().select_id_GlobalENB_ID();
+  val_GlobalENB_ID->ref_criticality().select_id_GlobalENB_ID();
+  val_GlobalENB_ID->ref_value().select_id_GlobalENB_ID().ref_pLMN_Identity()
+                                         .set(3, cfg.pLMN_Identity);
+
+  val_GlobalENB_ID->ref_value().select_id_GlobalENB_ID().ref_eNB_ID()
+                  .select_macro_eNB_ID().set_buffer(20, cfg.macro_eNB_ID);
+
+  /* X2SetupResponse-IEs : ServedCells*/
+  IE_value_t* val_ServedCells = new IE_value_t;
+  container->ref_protocolIEs().push_back(*val_ServedCells);
+
+  val_ServedCells->ref_id().select_id_ServedCells();
+  val_ServedCells->ref_criticality().select_id_ServedCells();
+  val_ServedCells->ref_value().select_id_ServedCells();
+
+  //Add servedCellInfo
+  ServedCells::value_type* elm = new ServedCells::value_type();
+  ServedCell_Information* info = &(elm->ref_servedCellInfo());
+  {
+    //Set ServedCell-Information: pCI, cellId, tAC, broadcastPLMNs, eUTRA-Mode-Info
+    info->ref_pCI().set(cfg.pCI);
+    info->ref_cellId().ref_pLMN_Identity().set(3, cfg.pLMN_Identity);
+    info->ref_cellId().ref_eUTRANcellIdentifier().set_buffer(28, cfg.eUTRANcellIdentifier);
+    info->ref_tAC().set(2, cfg.tAC);
+
+    BroadcastPLMNs_Item::value_type* item = new BroadcastPLMNs_Item::value_type();
+    item->set(3, cfg.pLMN_Identity);
+    info->ref_broadcastPLMNs().push_back(*item);
+
+    info->ref_eUTRA_Mode_Info().select_fDD().ref_uL_EARFCN().set(cfg.uL_EARFCN);
+    info->ref_eUTRA_Mode_Info().select_fDD().ref_dL_EARFCN().set(cfg.dL_EARFCN);
+    info->ref_eUTRA_Mode_Info().select_fDD().ref_uL_Transmission_Bandwidth()
+          .set(static_cast<Transmission_Bandwidth::index_t>(cfg.uL_Bandwidth));
+    info->ref_eUTRA_Mode_Info().select_fDD().ref_dL_Transmission_Bandwidth()
+          .set(static_cast<Transmission_Bandwidth::index_t>(cfg.dL_Bandwidth));
+  }
+  val_ServedCells->ref_value().select_id_ServedCells().push_back(*elm);
+
+  return true;
+}
+
+bool x2ap_create_X2SetupFailure(x2ap_pdu_t* pdu)
+{
+  X2APpduWrapper* pduWrapper = reinterpret_cast<X2APpduWrapper*>(pdu);
+
+  /* Initiaization */
+  pduWrapper->ref_pdu().select_unsuccessfulOutcome().ref_procedureCode().select_id_x2Setup();
+  pduWrapper->ref_pdu().select_unsuccessfulOutcome().ref_criticality().select_id_x2Setup();
+
+  X2SetupFailure* container =
+    &(pduWrapper->ref_pdu().select_unsuccessfulOutcome().ref_value().select_id_x2Setup());
+
+  using IE_value_t = X2SetupFailure::protocolIEs_t::value_type;
+
+  /* X2SetupFailure-IEs << id-Cause */
+  IE_value_t* val_cause = new IE_value_t;
+  container->ref_protocolIEs().push_back(*val_cause);
+
+  val_cause->ref_id().select_id_Cause();
+  val_cause->ref_criticality().select_id_Cause();
+
+  /* Cause << radioNetwork */
+  val_cause->ref_value().select_id_Cause().select_radioNetwork();
+
+  /* CauseRadioNetwork = ho-target-not-allowed (enum = 8)*/
+  val_cause->ref_value().select_id_Cause().select_radioNetwork()
+                        .set(static_cast<CauseRadioNetwork::index_t>(8));
+
+  return true;
+}
+
+//ENDCX2Setup
+bool x2ap_create_ENDCX2SetupRequest(x2ap_pdu_t* pdu, eNB_config &cfg)
+{
+  X2APpduWrapper* pduWrapper = reinterpret_cast<X2APpduWrapper*>(pdu);
+
+  /* Initiaization */
+  pduWrapper->ref_pdu().select_initiatingMessage().ref_procedureCode().select_id_endcX2Setup();
+  pduWrapper->ref_pdu().select_initiatingMessage().ref_criticality().select_id_endcX2Setup();
+
+  ENDCX2SetupRequest* container =
+    &(pduWrapper->ref_pdu().select_initiatingMessage().ref_value().select_id_endcX2Setup());
+
+  using IE_value_t = ENDCX2SetupRequest::protocolIEs_t::value_type;
+
+  /* ENDCX2SetupRequest-IEs = id-InitiatingNodeType-EndcX2Setup  */
+  IE_value_t* ie = new IE_value_t;
+  container->ref_protocolIEs().push_back(*ie);
+  ie->ref_id().select_id_InitiatingNodeType_EndcX2Setup();
+  ie->ref_criticality().select_id_InitiatingNodeType_EndcX2Setup();
+  ie->ref_value().select_id_InitiatingNodeType_EndcX2Setup();
+
+  /* InitiatingNodeType-EndcX2Setup = init-eNB {ENB-ENDCX2SetupReqIEs} */
+  ie->ref_value().select_id_InitiatingNodeType_EndcX2Setup().select_init_eNB();
+
+  using eNB_val_t = InitiatingNodeType_EndcX2Setup::init_eNB_t::value_type;
+
+  ProtocolIE_Container<ENB_ENDCX2SetupReqIEs>* eNB_node =
+    &(ie->ref_value().select_id_InitiatingNodeType_EndcX2Setup().select_init_eNB());
+
+  /* ENB-ENDCX2SetupReqIEs <-- id-GlobalENB-ID */
+  eNB_val_t* val_GlobalENB_ID = new eNB_val_t;
+  eNB_node->push_back(*val_GlobalENB_ID);
+
+  val_GlobalENB_ID->ref_id().select_id_GlobalENB_ID();
+  val_GlobalENB_ID->ref_criticality().select_id_GlobalENB_ID();
+  val_GlobalENB_ID->ref_value().select_id_GlobalENB_ID()
+                      .ref_pLMN_Identity().set(3, cfg.pLMN_Identity);
+  val_GlobalENB_ID->ref_value().select_id_GlobalENB_ID().ref_eNB_ID()
+                  .select_macro_eNB_ID().set_buffer(20, cfg.macro_eNB_ID);
+
+  /* ENB-ENDCX2SetupReqIEs <-- id-ServedEUTRAcellsENDCX2ManagementList */
+  eNB_val_t* val_EUTRAlist = new eNB_val_t;
+  eNB_node->push_back(*val_EUTRAlist);
+
+  val_EUTRAlist->ref_id().select_id_ServedEUTRAcellsENDCX2ManagementList();
+  val_EUTRAlist->ref_criticality().select_id_ServedEUTRAcellsENDCX2ManagementList();
+  val_EUTRAlist->ref_value().select_id_ServedEUTRAcellsENDCX2ManagementList();
+
+  /* ServedEUTRAcellsENDCX2ManagementList <-- servedEUTRACellInfo */
+  ServedEUTRAcellsENDCX2ManagementList::value_type* elm =
+                        new ServedEUTRAcellsENDCX2ManagementList::value_type();
+  ServedCell_Information* info = &(elm->ref_servedEUTRACellInfo());
+  {
+    //Set ServedCell-Information: pCI, cellId, tAC, broadcastPLMNs, eUTRA-Mode-Info
+    info->ref_pCI().set(cfg.pCI);
+    info->ref_cellId().ref_pLMN_Identity().set(3, cfg.pLMN_Identity);
+    info->ref_cellId().ref_eUTRANcellIdentifier().set_buffer(28, cfg.eUTRANcellIdentifier);
+    info->ref_tAC().set(2, cfg.tAC);
+
+    BroadcastPLMNs_Item::value_type* item = new BroadcastPLMNs_Item::value_type();
+    item->set(3, cfg.pLMN_Identity);
+    info->ref_broadcastPLMNs().push_back(*item);
+
+    info->ref_eUTRA_Mode_Info().select_fDD().ref_uL_EARFCN().set(cfg.uL_EARFCN);
+    info->ref_eUTRA_Mode_Info().select_fDD().ref_dL_EARFCN().set(cfg.dL_EARFCN);
+    info->ref_eUTRA_Mode_Info().select_fDD().ref_uL_Transmission_Bandwidth()
+          .set(static_cast<Transmission_Bandwidth::index_t>(cfg.uL_Bandwidth));
+    info->ref_eUTRA_Mode_Info().select_fDD().ref_dL_Transmission_Bandwidth()
+          .set(static_cast<Transmission_Bandwidth::index_t>(cfg.dL_Bandwidth));
+  }
+  val_EUTRAlist->ref_value().select_id_ServedEUTRAcellsENDCX2ManagementList()
+                                                        .push_back(*elm);
+
+  return true;
+}
+
+/*-----------------------------------------------------------------------
+                              TESTS
+-------------------------------------------------------------------------
+*/
+void test_X2Setup_codec(void)
+{
+  x2ap_pdu_t* pdu = new_x2ap_pdu();
+
+  eNB_config cfg;
+  x2ap_create_X2SetupRequest(pdu, cfg);
+
+  char pdu_str[1024];
+  x2ap_asn_print(pdu, pdu_str, sizeof(pdu_str));
+  printf("%s\n", pdu_str);
+
+  //Test encode
+  unsigned char packed_buf[4096];
+  char          err_buf[1024];
+
+  int packed_len = x2ap_asn_per_encode(pdu, packed_buf, sizeof(packed_buf),
+                                            err_buf, sizeof(err_buf));
+  if(packed_len != -1) {
+    printf("Encode successful, packed_len = %d\n", packed_len);
+  } else {
+    printf("Encode Error: %s\n", err_buf);
+  }
+
+  //Test encode error
+  x2ap_pdu_t* pdu1 = new_x2ap_pdu();
+  x2ap_init_X2SetupRequest(pdu1);
+
+  int packed_len1 = x2ap_asn_per_encode(pdu1, packed_buf, sizeof(packed_buf),
+                                            err_buf, sizeof(err_buf));
+  if(packed_len1 != -1) {
+    printf("Encode successful, packed_len = %d\n", packed_len1);
+  } else {
+    printf("Encode Error: %s\n", err_buf);
+  }
+
+  //Test decode
+  x2ap_pdu_t* pdu2 = new_x2ap_pdu();
+  int rc = x2ap_asn_per_decode(pdu2, packed_buf, packed_len, err_buf, sizeof(err_buf));
+  if(rc == -1) {
+    printf("Decode error: %s\n", err_buf);
+  } else {
+    printf("Decode successful\n");
+  }
+
+  x2ap_asn_print(pdu2, pdu_str, sizeof(pdu_str));
+  printf("%s\n", pdu_str);
+
+  printf("index = %d\n", x2ap_get_index(pdu2));
+  printf("procedureCode = %d\n", x2ap_get_procedureCode(pdu2));
+
+
+  //Test decode error
+  x2ap_pdu_t* pdu3 = new_x2ap_pdu();
+  int rc2 = x2ap_asn_per_decode(pdu3, packed_buf, 1, err_buf, sizeof(err_buf));
+  if(rc2 == -1) {
+    printf("Decode error: %s\n", err_buf);
+  } else {
+    printf("Decode successful\n");
+  }
+
+  //Test X2SetupResponse
+  x2ap_pdu_t* pdu_resp = new_x2ap_pdu();
+  x2ap_create_X2SetupResponse(pdu_resp, cfg);
+  x2ap_asn_print(pdu_resp, pdu_str, sizeof(pdu_str));
+  printf("%s\n", pdu_str);
+
+  //Test X2SetupFailure
+  x2ap_pdu_t* pdu_failure = new_x2ap_pdu();
+  x2ap_create_X2SetupFailure(pdu_failure);
+  x2ap_asn_print(pdu_failure, pdu_str, sizeof(pdu_str));
+  printf("%s \n", pdu_str);
+}