First release
[sim/ns3-o-ran-e2.git] / model / asn1c-types.cc
diff --git a/model/asn1c-types.cc b/model/asn1c-types.cc
new file mode 100644 (file)
index 0000000..7dbcfb2
--- /dev/null
@@ -0,0 +1,963 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2022 Northeastern University
+ * Copyright (c) 2022 Sapienza, University of Rome
+ * Copyright (c) 2022 University of Padova
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Andrea Lacava <thecave003@gmail.com>
+ *                Tommaso Zugno <tommasozugno@gmail.com>
+ *                Michele Polese <michele.polese@gmail.com>
+ */
+
+#include <ns3/asn1c-types.h>
+#include <ns3/log.h>
+
+NS_LOG_COMPONENT_DEFINE ("Asn1Types");
+
+namespace ns3 {
+
+OctetString::OctetString (std::string value, size_t size)
+{
+  NS_LOG_FUNCTION (this);
+  CreateBaseOctetString (size);
+  memcpy (m_octetString->buf, value.c_str (), size);
+}
+
+void OctetString::CreateBaseOctetString (size_t size)
+{
+  NS_LOG_FUNCTION (this);
+  m_octetString = (OCTET_STRING_t *) calloc (1, sizeof (OCTET_STRING_t));
+  m_octetString->buf = (uint8_t *) calloc (1, size);
+  m_octetString->size = size;
+}
+
+OctetString::OctetString (void *value, size_t size)
+{
+  NS_LOG_FUNCTION (this);
+  CreateBaseOctetString (size);
+  memcpy (m_octetString->buf, value, size);
+}
+
+OctetString::~OctetString ()
+{
+  NS_LOG_FUNCTION (this);
+  // if (m_octetString->buf != NULL)
+    // free (m_octetString->buf);
+  free (m_octetString);
+}
+
+OCTET_STRING_t *
+OctetString::GetPointer ()
+{
+  return m_octetString;
+}
+
+OCTET_STRING_t
+OctetString::GetValue ()
+{
+  return *m_octetString;
+}
+
+std::string OctetString::DecodeContent(){
+  int size = this->GetValue ().size;
+  char out[size + 1];
+  std::memcpy (out, this->GetValue ().buf, size);
+  out[size] = '\0';
+
+  return std::string (out);
+}
+
+BitString::BitString (std::string value, size_t size)
+
+{
+  NS_LOG_FUNCTION (this);
+  m_bitString = (BIT_STRING_t *) calloc (1, sizeof (BIT_STRING_t));
+  m_bitString->buf = (uint8_t *) calloc (1, size);
+  m_bitString->size = size;
+  memcpy (m_bitString->buf, value.c_str(), size);
+}
+
+BitString::BitString (std::string value, size_t size, size_t bits_unused)
+    : BitString::BitString (value, size)
+{
+  NS_LOG_FUNCTION (this);
+  m_bitString->bits_unused = bits_unused;
+}
+
+BitString::~BitString ()
+{
+  NS_LOG_FUNCTION (this);
+  free (m_bitString);
+}
+
+BIT_STRING_t *
+BitString::GetPointer ()
+{
+  return m_bitString;
+}
+
+BIT_STRING_t
+BitString::GetValue ()
+{
+  return *m_bitString;
+}
+
+NrCellId::NrCellId (uint16_t value)
+{
+  NS_LOG_FUNCTION (this);
+  
+  // TODO check why with more than 15 cells is not working
+  // if (value > 15)
+  // {
+  //   NS_FATAL_ERROR ("TODO: update the encoding to support more than 15 cells");
+  // }
+  
+  // convert value to a char array
+  // char ar [5] {};
+  // ar [4] = value * 16; // multiply by 16 to obtain a left shift of 4 bits
+  uint16_t shifted = value * 16;
+  std::string str_shift = std::to_string (shifted);
+  m_bitString = Create<BitString> (str_shift, 5, 4);
+}
+
+NrCellId::~NrCellId ()
+{  
+}
+
+BIT_STRING_t
+NrCellId::GetValue ()
+{
+  return m_bitString->GetValue ();
+}
+
+BIT_STRING_t*
+NrCellId::GetPointer ()
+{
+  return m_bitString->GetPointer ();
+}
+
+Snssai::Snssai (std::string sst)
+{
+  m_sNssai = (SNSSAI_t *) calloc (1, sizeof (SNSSAI_t));
+  m_sst = (OCTET_STRING_t *) calloc (1, sizeof (OCTET_STRING_t));
+  m_sst->buf = (uint8_t *) calloc (1, sst.size ());
+  m_sst->size = sst.size ();
+  memcpy (m_sst->buf, sst.c_str (), sst.size ());
+  m_sNssai->sST = *m_sst;
+}
+Snssai::Snssai (std::string sst, std::string sd) : Snssai (sst)
+{
+  m_sd = (OCTET_STRING_t *) calloc (1, sizeof (OCTET_STRING_t));
+  m_sd->buf = (uint8_t *) calloc (1, sst.size ());
+  m_sd->size = sd.size ();
+  memcpy (m_sd->buf, sd.c_str (), sd.size ());
+  m_sNssai->sD = m_sd;
+}
+
+Snssai::~Snssai ()
+{
+  if (m_sNssai != NULL)
+    ASN_STRUCT_FREE (asn_DEF_SNSSAI, m_sNssai);
+
+  // if (m_sst != NULL)
+  //   ASN_STRUCT_FREE (asn_DEF_OCTET_STRING, m_sst);
+  // if (m_sd != NULL)
+  //   ASN_STRUCT_FREE (asn_DEF_OCTET_STRING, m_sd);
+}
+
+SNSSAI_t *
+Snssai::GetPointer ()
+{
+  return m_sNssai;
+}
+
+SNSSAI_t
+Snssai::GetValue ()
+{
+  return *m_sNssai;
+}
+
+void
+MeasQuantityResultsWrap::AddRsrp (long rsrp)
+{
+
+  m_measQuantityResults->rsrp = (RSRP_Range_t *) calloc (1, sizeof (RSRP_Range_t));
+  *m_measQuantityResults->rsrp = rsrp;
+}
+
+void
+MeasQuantityResultsWrap::AddRsrq (long rsrq)
+{
+  m_measQuantityResults->rsrq = (RSRQ_Range_t *) calloc (1, sizeof (RSRQ_Range_t));
+  *m_measQuantityResults->rsrq = rsrq;
+}
+
+void
+MeasQuantityResultsWrap::AddSinr (long sinr)
+{
+  m_measQuantityResults->sinr = (SINR_Range_t *) calloc (1, sizeof (SINR_Range_t));
+  *m_measQuantityResults->sinr = sinr;
+}
+
+MeasQuantityResultsWrap::MeasQuantityResultsWrap ()
+{
+  m_measQuantityResults = (MeasQuantityResults_t *) calloc (1, sizeof (MeasQuantityResults_t));
+}
+
+MeasQuantityResultsWrap::~MeasQuantityResultsWrap ()
+{
+  // if (m_measQuantityResults->sinr != NULL)
+  //   ASN_STRUCT_FREE (asn_DEF_SINR_Range, m_measQuantityResults->sinr);
+
+  // if (m_measQuantityResults->rsrp != NULL)
+  //   ASN_STRUCT_FREE (asn_DEF_RSRP_Range, m_measQuantityResults->rsrp);
+
+  // if (m_measQuantityResults->rsrq != NULL)
+  //   ASN_STRUCT_FREE (asn_DEF_RSRQ_Range, m_measQuantityResults->rsrq);
+
+  // if (m_measQuantityResults != NULL){
+  //     free (m_measQuantityResults);
+  //   }
+}
+
+MeasQuantityResults_t *
+MeasQuantityResultsWrap::GetPointer ()
+{
+  return m_measQuantityResults;
+}
+
+MeasQuantityResults_t
+MeasQuantityResultsWrap::GetValue ()
+{
+  return *m_measQuantityResults;
+}
+
+ResultsPerCsiRsIndex::ResultsPerCsiRsIndex (long csiRsIndex, MeasQuantityResults_t *csiRsResults)
+    : ResultsPerCsiRsIndex (csiRsIndex)
+{
+  m_resultsPerCsiRsIndex->csi_RS_Results = csiRsResults;
+}
+
+ResultsPerCsiRsIndex::ResultsPerCsiRsIndex (long csiRsIndex)
+{
+  m_resultsPerCsiRsIndex =
+      (ResultsPerCSI_RS_Index_t *) calloc (1, sizeof (ResultsPerCSI_RS_Index_t));
+  m_resultsPerCsiRsIndex->csi_RS_Index = csiRsIndex;
+}
+
+ResultsPerCSI_RS_Index_t *
+ResultsPerCsiRsIndex::GetPointer ()
+{
+  return m_resultsPerCsiRsIndex;
+}
+
+ResultsPerCSI_RS_Index_t
+ResultsPerCsiRsIndex::GetValue ()
+{
+  return *m_resultsPerCsiRsIndex;
+}
+
+ResultsPerSSBIndex::ResultsPerSSBIndex (long ssbIndex, MeasQuantityResults_t *ssbResults)
+    : ResultsPerSSBIndex (ssbIndex)
+{
+  m_resultsPerSSBIndex->ssb_Results = ssbResults;
+}
+
+ResultsPerSSBIndex::ResultsPerSSBIndex (long ssbIndex)
+{
+  m_resultsPerSSBIndex = (ResultsPerSSB_Index_t *) calloc (1, sizeof (ResultsPerSSB_Index_t));
+  m_resultsPerSSBIndex->ssb_Index = ssbIndex;
+}
+
+ResultsPerSSB_Index_t *
+ResultsPerSSBIndex::GetPointer ()
+{
+  return m_resultsPerSSBIndex;
+}
+
+ResultsPerSSB_Index_t
+ResultsPerSSBIndex::GetValue ()
+{
+  return *m_resultsPerSSBIndex;
+}
+
+void
+MeasResultNr::AddCellResults (MeasResultNr::ResultCell cell, MeasQuantityResults_t *results)
+{
+  switch (cell)
+    {
+    case MeasResultNr::ResultCell::SSB:
+
+      m_measResultNr->measResult.cellResults.resultsSSB_Cell = results;
+      break;
+
+    case MeasResultNr::ResultCell::CSI_RS:
+
+      m_measResultNr->measResult.cellResults.resultsCSI_RS_Cell = results;
+      break;
+
+    default:
+      NS_LOG_ERROR ("Unrecognized cell identifier.");
+      break;
+    }
+}
+
+void
+MeasResultNr::AddPerSsbIndexResults (ResultsPerSSB_Index_t *resultsSSB_Index)
+{
+  ASN_SEQUENCE_ADD (m_measResultNr->measResult.rsIndexResults->resultsSSB_Indexes,
+                    resultsSSB_Index);
+}
+
+void
+MeasResultNr::AddPerCsiRsIndexResults (ResultsPerCSI_RS_Index_t *resultsCSI_RS_Index)
+{
+  ASN_SEQUENCE_ADD (m_measResultNr->measResult.rsIndexResults->resultsCSI_RS_Indexes,
+                    resultsCSI_RS_Index);
+}
+
+void MeasResultNr::AddPhyCellId (long physCellId)
+{
+  PhysCellId_t *s_physCellId = (PhysCellId_t *) calloc (1, sizeof (PhysCellId_t));
+  *s_physCellId = physCellId;
+  m_measResultNr->physCellId = s_physCellId;
+}
+
+MeasResultNr::MeasResultNr (long physCellId) : MeasResultNr ()
+{
+  AddPhyCellId (physCellId);
+}
+
+MeasResultNr::MeasResultNr ()
+{
+  m_measResultNr = (MeasResultNR_t *) calloc (1, sizeof (MeasResultNR_t));
+  m_shouldFree = false;
+}
+
+MeasResultNr::~MeasResultNr ()
+{
+  if (m_shouldFree)
+    {
+      free (m_measResultNr);
+    }
+}
+
+MeasResultNR_t *
+MeasResultNr::GetPointer ()
+{
+  // Fallback procedure, this should not happen if correctly used;
+  m_shouldFree = false;
+  return m_measResultNr;
+}
+
+MeasResultNR_t
+MeasResultNr::GetValue ()
+{
+  m_shouldFree = true;
+  return *m_measResultNr;
+}
+
+MeasResultEutra::MeasResultEutra (long eutraPhysCellId, long rsrp, long rsrq, long sinr)
+    : MeasResultEutra (eutraPhysCellId)
+{
+  AddRsrp (rsrp);
+  AddRsrq (rsrq);
+  AddSinr (sinr);
+}
+
+MeasResultEutra::MeasResultEutra (long eutraPhysCellId)
+{
+  m_measResultEutra = (MeasResultEUTRA_t *) calloc (1, sizeof (MeasResultEUTRA_t));
+  m_measResultEutra->eutra_PhysCellId = eutraPhysCellId;
+}
+
+void
+MeasResultEutra::AddRsrp (long rsrp)
+{
+  m_measResultEutra->measResult.rsrp =
+      (RSRP_RangeEUTRA_t *) calloc (1, sizeof (RSRP_RangeEUTRA_t));
+  *m_measResultEutra->measResult.rsrp = rsrp;
+}
+void
+MeasResultEutra::AddRsrq (long rsrq)
+{
+  m_measResultEutra->measResult.rsrq =
+      (RSRQ_RangeEUTRA_t *) calloc (1, sizeof (RSRQ_RangeEUTRA_t));
+  *m_measResultEutra->measResult.rsrq = rsrq;
+}
+void
+MeasResultEutra::AddSinr (long sinr)
+{
+  m_measResultEutra->measResult.sinr =
+      (SINR_RangeEUTRA_t *) calloc (1, sizeof (SINR_RangeEUTRA_t));
+  *m_measResultEutra->measResult.sinr = sinr;
+}
+
+MeasResultEUTRA_t *
+MeasResultEutra::GetPointer ()
+{
+  return m_measResultEutra;
+}
+
+MeasResultEUTRA_t
+MeasResultEutra::GetValue ()
+{
+  return *m_measResultEutra;
+}
+
+MeasResultPCellWrap::MeasResultPCellWrap (long eutraPhysCellId, long rsrpResult, long rsrqResult)
+    : MeasResultPCellWrap (eutraPhysCellId)
+{
+  AddRsrpResult (rsrpResult);
+  AddRsrqResult (rsrqResult);
+}
+
+MeasResultPCellWrap::MeasResultPCellWrap (long eutraPhysCellId)
+{
+  m_measResultPCell = (MeasResultPCell_t *) calloc (1, sizeof (MeasResultPCell_t));
+  m_measResultPCell->eutra_PhysCellId = eutraPhysCellId;
+}
+
+void
+MeasResultPCellWrap::AddRsrpResult (long rsrpResult)
+{
+  m_measResultPCell->rsrpResult = rsrpResult;
+}
+
+void
+MeasResultPCellWrap::AddRsrqResult (long rsrqResult)
+{
+  m_measResultPCell->rsrqResult = rsrqResult;
+}
+
+MeasResultPCell_t *
+MeasResultPCellWrap::GetPointer ()
+{
+  return m_measResultPCell;
+}
+
+MeasResultPCell_t
+MeasResultPCellWrap::GetValue ()
+{
+  return *m_measResultPCell;
+}
+
+MeasResultServMo::MeasResultServMo (long servCellId, MeasResultNR_t measResultServingCell,
+                                    MeasResultNR_t *measResultBestNeighCell)
+    : MeasResultServMo (servCellId, measResultServingCell)
+{
+  m_measResultServMo->measResultBestNeighCell = measResultBestNeighCell;
+}
+
+MeasResultServMo::MeasResultServMo (long servCellId, MeasResultNR_t measResultServingCell)
+{
+  m_measResultServMo = (MeasResultServMO_t *) calloc (1, sizeof (MeasResultServMO_t));
+  m_measResultServMo->servCellId = servCellId;
+  m_measResultServMo->measResultServingCell = measResultServingCell;
+}
+
+MeasResultServMO_t *
+MeasResultServMo::GetPointer ()
+{
+  return m_measResultServMo;
+}
+
+MeasResultServMO_t
+MeasResultServMo::GetValue ()
+{
+  return *m_measResultServMo;
+}
+
+void
+ServingCellMeasurementsWrap::AddMeasResultPCell (MeasResultPCell_t *measResultPCell)
+{
+  if (m_servingCellMeasurements->present != ServingCellMeasurements_PR_eutra_measResultPCell)
+    {
+      NS_LOG_ERROR ("Wrong measurement item for this present, it will not be added.");
+    }
+  m_servingCellMeasurements->choice.eutra_measResultPCell = measResultPCell;
+}
+
+void
+ServingCellMeasurementsWrap::AddMeasResultServMo (MeasResultServMO_t *measResultServMO)
+{
+  if (m_servingCellMeasurements->present != ServingCellMeasurements_PR_nr_measResultServingMOList)
+    {
+      NS_LOG_ERROR ("Wrong measurement item for this present, it will not be added.");
+    }
+
+  ASN_SEQUENCE_ADD (&m_nr_measResultServingMOList->list, measResultServMO);
+}
+
+ServingCellMeasurementsWrap::ServingCellMeasurementsWrap (ServingCellMeasurements_PR present)
+{
+  m_servingCellMeasurements =
+      (ServingCellMeasurements_t *) calloc (1, sizeof (ServingCellMeasurements_t));
+  m_servingCellMeasurements->present = present;
+
+  if (m_servingCellMeasurements->present == ServingCellMeasurements_PR_nr_measResultServingMOList)
+    {
+      m_nr_measResultServingMOList =
+          (MeasResultServMOList_t *) calloc (1, sizeof (MeasResultServMOList_t));
+      m_servingCellMeasurements->choice.nr_measResultServingMOList = m_nr_measResultServingMOList;
+    }
+}
+
+ServingCellMeasurements_t *
+ServingCellMeasurementsWrap::GetPointer ()
+{
+  return m_servingCellMeasurements;
+}
+
+ServingCellMeasurements_t
+ServingCellMeasurementsWrap::GetValue ()
+{
+  return *m_servingCellMeasurements;
+}
+
+Ptr<L3RrcMeasurements>
+L3RrcMeasurements::CreateL3RrcUeSpecificSinrServing (long servingCellId, long physCellId, long sinr)
+{
+  Ptr<L3RrcMeasurements> l3RrcMeasurement = Create<L3RrcMeasurements> (RRCEvent_b1);
+  Ptr<ServingCellMeasurementsWrap> servingCellMeasurements =
+      Create<ServingCellMeasurementsWrap> (ServingCellMeasurements_PR_nr_measResultServingMOList);
+
+  Ptr<MeasResultNr> measResultNr = Create<MeasResultNr> (physCellId);
+  Ptr<MeasQuantityResultsWrap> measQuantityResultWrap = Create<MeasQuantityResultsWrap> ();
+  measQuantityResultWrap->AddSinr (sinr);
+  measResultNr->AddCellResults (MeasResultNr::SSB, measQuantityResultWrap->GetPointer ());
+  Ptr<MeasResultServMo> measResultServMo =
+      Create<MeasResultServMo> (servingCellId, measResultNr->GetValue ());
+  servingCellMeasurements->AddMeasResultServMo (measResultServMo->GetPointer ());
+  l3RrcMeasurement->AddServingCellMeasurement (servingCellMeasurements->GetPointer ());
+  return l3RrcMeasurement;
+}
+
+Ptr<L3RrcMeasurements>
+L3RrcMeasurements::CreateL3RrcUeSpecificSinrNeigh ()
+{
+  return Create<L3RrcMeasurements> (RRCEvent_b1);
+}
+
+void
+L3RrcMeasurements::AddNeighbourCellMeasurement (long neighCellId, long sinr)
+{
+  Ptr<MeasResultNr> measResultNr = Create<MeasResultNr> (neighCellId);
+  Ptr<MeasQuantityResultsWrap> measQuantityResultWrap = Create<MeasQuantityResultsWrap> ();
+  measQuantityResultWrap->AddSinr (sinr);
+  measResultNr->AddCellResults (MeasResultNr::SSB, measQuantityResultWrap->GetPointer ());
+
+  this->AddMeasResultNRNeighCells (measResultNr->GetPointer ()); // MAX 8 UE per message (standard)
+}
+
+void
+L3RrcMeasurements::AddServingCellMeasurement (ServingCellMeasurements_t *servingCellMeasurements)
+{
+  m_l3RrcMeasurements->servingCellMeasurements = servingCellMeasurements;
+}
+
+void
+L3RrcMeasurements::AddMeasResultEUTRANeighCells (MeasResultEUTRA_t *measResultItemEUTRA)
+{
+  if (m_measItemsCounter == L3RrcMeasurements::MAX_MEAS_RESULTS_ITEMS)
+    {
+      NS_LOG_ERROR ("Maximum number of items ("
+                    << L3RrcMeasurements::MAX_MEAS_RESULTS_ITEMS
+                    << ")for the standard reached. This item will not be "
+                       "inserted in the list");
+      return;
+    }
+
+  if (m_l3RrcMeasurements->measResultNeighCells == NULL)
+    {
+      addMeasResultNeighCells (MeasResultNeighCells_PR_measResultListEUTRA);
+    }
+
+  if (m_l3RrcMeasurements->measResultNeighCells->present !=
+      MeasResultNeighCells_PR_measResultListEUTRA)
+    {
+      NS_LOG_ERROR ("Wrong measurement item for this list, it will not be added.");
+      return;
+    }
+
+  m_measItemsCounter++;
+  ASN_SEQUENCE_ADD (&m_measResultListEUTRA->list, measResultItemEUTRA);
+}
+
+void
+L3RrcMeasurements::AddMeasResultNRNeighCells (MeasResultNR_t *measResultItemNR)
+{
+  if (m_measItemsCounter == L3RrcMeasurements::MAX_MEAS_RESULTS_ITEMS)
+    {
+      NS_LOG_ERROR ("Maximum number of items ("
+                    << L3RrcMeasurements::MAX_MEAS_RESULTS_ITEMS
+                    << ")for the standard reached. This item will not be "
+                       "inserted in the list");
+      return;
+    }
+
+  if (m_l3RrcMeasurements->measResultNeighCells == NULL)
+    {
+      addMeasResultNeighCells (MeasResultNeighCells_PR_measResultListNR);
+    }
+
+  if (m_l3RrcMeasurements->measResultNeighCells->present !=
+      MeasResultNeighCells_PR_measResultListNR)
+    {
+      NS_LOG_ERROR ("Wrong measurement item for this list, it will not be added.");
+      return;
+    }
+
+  m_measItemsCounter++;
+  ASN_SEQUENCE_ADD (&m_measResultListNR->list, measResultItemNR);
+}
+
+void
+L3RrcMeasurements::addMeasResultNeighCells (MeasResultNeighCells_PR present)
+{
+  m_l3RrcMeasurements->measResultNeighCells =
+      (MeasResultNeighCells_t *) calloc (1, sizeof (MeasResultNeighCells_t));
+  m_l3RrcMeasurements->measResultNeighCells->present = present;
+
+  switch (present)
+    {
+      case MeasResultNeighCells_PR_measResultListEUTRA: {
+        m_measResultListEUTRA =
+            (MeasResultListEUTRA_t *) calloc (1, sizeof (MeasResultListEUTRA_t));
+        m_l3RrcMeasurements->measResultNeighCells->choice.measResultListEUTRA =
+            m_measResultListEUTRA;
+        break;
+      }
+
+      case MeasResultNeighCells_PR_measResultListNR: {
+        m_measResultListNR = (MeasResultListNR_t *) calloc (1, sizeof (MeasResultListNR_t));
+        m_l3RrcMeasurements->measResultNeighCells->choice.measResultListNR = m_measResultListNR;
+        break;
+      }
+
+      default: {
+        NS_LOG_ERROR ("Unrecognized present for Measurment result.");
+        break;
+      }
+    }
+}
+
+L3RrcMeasurements::L3RrcMeasurements (RRCEvent_t rrcEvent)
+{
+  m_l3RrcMeasurements = (L3_RRC_Measurements_t *) calloc (1, sizeof (L3_RRC_Measurements_t));
+  m_l3RrcMeasurements->rrcEvent = rrcEvent;
+  m_measItemsCounter = 0;
+}
+
+L3RrcMeasurements::L3RrcMeasurements (L3_RRC_Measurements_t *l3RrcMeasurements)
+{
+  m_l3RrcMeasurements = l3RrcMeasurements;
+}
+
+L3RrcMeasurements::~L3RrcMeasurements ()
+{
+  // Memory deallocation is handled by RIC Indication Message 
+  // if (m_l3RrcMeasurements != NULL)
+  //   {
+  //     ASN_STRUCT_FREE (asn_DEF_L3_RRC_Measurements, m_l3RrcMeasurements);
+  //   }
+}
+
+L3_RRC_Measurements *
+L3RrcMeasurements::GetPointer ()
+{
+  return m_l3RrcMeasurements;
+}
+
+L3_RRC_Measurements
+L3RrcMeasurements::GetValue ()
+{
+  return *m_l3RrcMeasurements;
+}
+
+// TODO change definition and return the values
+// this function shall be finished for decoding
+void
+L3RrcMeasurements::ExtractMeasurementsFromL3RrcMeas (L3_RRC_Measurements_t *l3RrcMeasurements)
+{
+  RRCEvent_t rrcEvent = l3RrcMeasurements->rrcEvent; // Mandatory
+  switch (rrcEvent)
+    {
+      case RRCEvent_b1: {
+        NS_LOG_DEBUG ("RRCEvent_b1");
+      }
+      break;
+
+      case RRCEvent_a3: {
+        NS_LOG_DEBUG ("RRCEvent_a3");
+      }
+      break;
+      case RRCEvent_a5: {
+        NS_LOG_DEBUG ("RRCEvent_a5");
+      }
+      break;
+      case RRCEvent_periodic: {
+        NS_LOG_DEBUG ("RRCEvent_periodic");
+      }
+      break;
+
+      default: {
+        NS_LOG_ERROR ("Rrc event unrecognised");
+      }
+      break;
+    }
+
+  if (l3RrcMeasurements->measResultNeighCells)
+    {
+      MeasResultNeighCells_t *measResultNeighCells = l3RrcMeasurements->measResultNeighCells;
+      switch (measResultNeighCells->present)
+        {
+          case MeasResultNeighCells_PR_NOTHING: { /* No components present */
+            NS_LOG_DEBUG ("No components present");
+          }
+          break;
+          case MeasResultNeighCells_PR_measResultListNR: {
+            NS_LOG_DEBUG ("MeasResultNeighCells_PR_measResultListNR");
+            //  measResultNeighCells->choice.measResultListNR
+          }
+          break;
+          case MeasResultNeighCells_PR_measResultListEUTRA: {
+            NS_LOG_DEBUG ("MeasResultNeighCells_PR_measResultListEUTRA");
+          }
+          break;
+        default:
+          NS_LOG_ERROR ("measResultNeighCells present unrecognised");
+          break;
+        }
+    }
+  if (l3RrcMeasurements->servingCellMeasurements)
+    {
+      ServingCellMeasurements_t *servingCellMeasurements =
+          l3RrcMeasurements->servingCellMeasurements;
+      switch (servingCellMeasurements->present)
+        {
+          case ServingCellMeasurements_PR_NOTHING: { /* No components present */
+            NS_LOG_DEBUG ("No components present");
+          }
+          break;
+          case ServingCellMeasurements_PR_nr_measResultServingMOList: {
+            NS_LOG_DEBUG ("ServingCellMeasurements_PR_nr_measResultServingMOList");
+          }
+          break;
+          case ServingCellMeasurements_PR_eutra_measResultPCell: {
+            NS_LOG_DEBUG ("ServingCellMeasurements_PR_eutra_measResultPCell");
+          }
+          break;
+        default:
+          NS_LOG_ERROR ("servingCellMeasurements present unrecognised");
+          break;
+        }
+    }
+}
+
+double 
+L3RrcMeasurements::ThreeGppMapSinr (double sinr)
+{
+  double inputEnd = 40;
+  double inputStart = -23;
+  double outputStart = 0;
+  double outputEnd = 127;
+  double outputSinr;
+  double slope = (outputEnd - outputStart) / (inputEnd - inputStart);
+
+  if (sinr < inputStart)
+    {
+      outputSinr = outputStart;
+    }
+  else if (sinr > inputEnd)
+    {
+      outputSinr = outputEnd;
+    }
+  else
+    {
+      outputSinr = outputStart + std::round (slope * (sinr - inputStart));
+    }
+
+  NS_LOG_DEBUG ("input sinr" << sinr << " output sinr" << outputSinr);
+
+  return outputSinr;
+}
+
+MeasurementItem::MeasurementItem (std::string name)
+{
+
+  m_measurementItem = (PM_Info_Item_t *) calloc (1, sizeof (PM_Info_Item_t));
+  m_pmType = (MeasurementType_t *) calloc (1, sizeof (MeasurementType_t));
+  m_measurementItem->pmType = *m_pmType;
+
+  m_measName =
+      (MeasurementTypeName_t *) calloc (1, sizeof (MeasurementTypeName_t));
+  m_measName->buf = (uint8_t *) calloc (1, sizeof (OCTET_STRING));
+  m_measName->size = name.length ();
+  memcpy (m_measName->buf, name.c_str (), m_measName->size);
+
+  m_measurementItem->pmType.choice.measName = *m_measName;
+  m_measurementItem->pmType.present = MeasurementType_PR_measName;
+}
+
+MeasurementItem::MeasurementItem (std::string name, long value) : MeasurementItem (name)
+{
+  NS_LOG_FUNCTION (this << name << "long" << value);
+  this->CreateMeasurementValue (MeasurementValue_PR_valueInt);
+  m_measurementItem->pmVal.choice.valueInt = value;
+}
+
+MeasurementItem::MeasurementItem (std::string name, double value) : MeasurementItem (name)
+{
+  NS_LOG_FUNCTION (this << name << "double" << value);
+  this->CreateMeasurementValue (MeasurementValue_PR_valueReal);
+  m_measurementItem->pmVal.choice.valueReal = value;
+}
+
+MeasurementItem::MeasurementItem (std::string name, Ptr<L3RrcMeasurements>value)
+    : MeasurementItem (name)
+{
+  NS_LOG_FUNCTION (this << name << "L3 RRC" << value);
+  this->CreateMeasurementValue (MeasurementValue_PR_valueRRC);
+  m_measurementItem->pmVal.choice.valueRRC = value->GetPointer ();
+}
+
+void
+MeasurementItem::CreateMeasurementValue (MeasurementValue_PR measurementValue_PR)
+{
+  m_pmVal = ((MeasurementValue_t *) calloc (1, sizeof (MeasurementValue_t)));
+  m_measurementItem->pmVal = *m_pmVal;
+  m_measurementItem->pmVal.present = measurementValue_PR;
+}
+
+MeasurementItem::~MeasurementItem ()
+{
+  NS_LOG_FUNCTION (this);
+  if (m_pmVal != NULL)
+    ASN_STRUCT_FREE (asn_DEF_MeasurementValue, m_pmVal);
+
+  if (m_measName != NULL)
+    {
+      free (m_measName);
+    }
+
+  if (m_pmType != NULL)
+    ASN_STRUCT_FREE (asn_DEF_MeasurementType, m_pmType);
+}
+
+PM_Info_Item_t *
+MeasurementItem::GetPointer ()
+{
+  return m_measurementItem;
+}
+
+PM_Info_Item_t
+MeasurementItem::GetValue ()
+{
+  return *m_measurementItem;
+}
+
+RANParameterItem::RANParameterItem (RANParameter_Item_t *ranParameterItem)
+{
+  m_ranParameterItem = ranParameterItem;
+}
+
+RANParameterItem::~RANParameterItem ()
+{
+  if (m_ranParameterItem != NULL)
+    ASN_STRUCT_FREE (asn_DEF_RANParameter_Item, m_ranParameterItem);
+}
+
+std::vector<RANParameterItem>
+RANParameterItem::ExtractRANParametersFromRANParameter (RANParameter_Item_t *ranParameterItem)
+{
+  std::vector<RANParameterItem> ranParameterList;
+
+  // NS_LOG_DEBUG ("RAN Parameter examined:");
+  // xer_fprint (stderr, &asn_DEF_RANParameter_Item, ranParameterItem);
+  // NS_LOG_DEBUG ("----");
+  // NS_LOG_DEBUG (" ID " << ranParameterItem->ranParameterItem_ID);
+
+  switch (ranParameterItem->ranParameterItem_valueType->present)
+    {
+      case RANParameter_ValueType_PR_NOTHING: {
+        NS_LOG_DEBUG ("[E2SM] RANParameter_ValueType_PR_NOTHING");
+        break;
+      }
+      case RANParameter_ValueType_PR_ranParameter_Element: {
+        RANParameterItem newItem =
+            RANParameterItem (ranParameterItem);
+        NS_LOG_DEBUG ("[E2SM] RANParameter_ValueType_PR_ranParameter_Element");
+        RANParameter_ELEMENT_t *ranParameterElement =
+            ranParameterItem->ranParameterItem_valueType->choice.ranParameter_Element;
+        newItem.m_keyFlag = &ranParameterElement->keyFlag;
+        switch (ranParameterElement->ranParameter_Value.present)
+          {
+            case RANParameter_Value_PR_NOTHING: {
+              NS_LOG_DEBUG ("[E2SM] RANParameter_Value_PR_NOTHING");
+              newItem.m_valueType = ValueType::Nothing;
+              break;
+            }
+            case RANParameter_Value_PR_valueInt: {
+              NS_LOG_DEBUG ("[E2SM] RANParameter_Value_PR_valueInt");
+              newItem.m_valueInt = ranParameterElement->ranParameter_Value.choice.valueInt;
+              newItem.m_valueType = ValueType::Int;
+              NS_LOG_DEBUG ("[E2SM] Value: " << newItem.m_valueInt);
+              break;
+            }
+            case RANParameter_Value_PR_valueOctS: {
+              NS_LOG_DEBUG ("[E2SM] RANParameter_Value_PR_valueOctS");
+              newItem.m_valueStr = Create<OctetString> (
+                  (void *) ranParameterElement->ranParameter_Value.choice.valueOctS.buf,
+                  ranParameterElement->ranParameter_Value.choice.valueOctS.size);
+              newItem.m_valueType = ValueType::OctectString;
+              NS_LOG_DEBUG ("[E2SM] Value: OctectString");
+              break;
+            }
+          }
+        ranParameterList.push_back (newItem);
+        break;
+      }
+      case RANParameter_ValueType_PR_ranParameter_Structure: {
+        NS_LOG_DEBUG ("[E2SM] RANParameter_ValueType_PR_ranParameter_Structure");
+        RANParameter_STRUCTURE_t *ranParameterStructure =
+            ranParameterItem->ranParameterItem_valueType->choice.ranParameter_Structure;
+        int count = ranParameterStructure->sequence_of_ranParameters.list.count;
+        for (int i = 0; i < count; i++)
+          {
+            RANParameter_Item_t *childRanItem =
+                ranParameterStructure->sequence_of_ranParameters.list.array[i];
+
+            for (RANParameterItem extractedParameter : ExtractRANParametersFromRANParameter (childRanItem))
+              {
+                ranParameterList.push_back (extractedParameter);
+              }
+          }
+        break;
+      }
+      case RANParameter_ValueType_PR_ranParameter_List: {
+        NS_LOG_DEBUG ("[E2SM] RANParameter_ValueType_PR_ranParameter_List");
+        // No list passed for the moment from RIC, thus no parsed as case
+        // ranParameterItem->ranParameterItem_valueType->choice.ranParameter_List;
+        break;
+      }
+    }
+
+  return ranParameterList;
+}
+
+
+}; // namespace ns3