--- /dev/null
+# ns3-o-ran-e2
+
+================================
+
+This ns-3 module enables the support for running multiple terminations of an O-RAN-compliant E2 interface inside the simulation process. It has been developed by a team at the [Institute for the Wireless Internet of Things (WIoT)](https://wiot.northeastern.edu) at Northeastern University, in collaboration with the University of Padova and with support from Mavenir.
+
+# References
+
+TBD
+<!-- More information can be found in the paper TODO -->
+
+# How to use
+
+This module can be used with an extension of the [ns3-mmWave module](https://github.com/nyuwireless-unipd/ns3-mmwave) that will soon be released. The module needs to be cloned in the contrib folder. The [e2sim library](https://github.com/o-ran-sc/sim-e2-interface) needs to be installed.
+
+We will provide further instructions as part of this README file.
+
+# Authors
+
+The ns3-o-ran-e2 module is the result of the development effort carried out by different people. The main contributors are:
+
+- Andrea Lacava, Northeastern University and Sapienza University of Rome
+- Michele Polese, Northeastern University
+- Tommaso Zugno, University of Padova
--- /dev/null
+Example Module Documentation
+----------------------------
+
+.. include:: replace.txt
+.. highlight:: cpp
+
+.. heading hierarchy:
+ ------------- Chapter
+ ************* Section (#.#)
+ ============= Subsection (#.#.#)
+ ############# Paragraph (no number)
+
+This is a suggested outline for adding new module documentation to |ns3|.
+See ``src/click/doc/click.rst`` for an example.
+
+The introductory paragraph is for describing what this code is trying to
+model.
+
+For consistency (italicized formatting), please use |ns3| to refer to
+ns-3 in the documentation (and likewise, |ns2| for ns-2). These macros
+are defined in the file ``replace.txt``.
+
+Model Description
+*****************
+
+The source code for the new module lives in the directory ``contrib/oran-interface``.
+
+Add here a basic description of what is being modeled.
+
+Design
+======
+
+Briefly describe the software design of the model and how it fits into
+the existing ns-3 architecture.
+
+Scope and Limitations
+=====================
+
+What can the model do? What can it not do? Please use this section to
+describe the scope and limitations of the model.
+
+References
+==========
+
+Add academic citations here, such as if you published a paper on this
+model, or if readers should read a particular specification or other work.
+
+Usage
+*****
+
+This section is principally concerned with the usage of your model, using
+the public API. Focus first on most common usage patterns, then go
+into more advanced topics.
+
+Building New Module
+===================
+
+Include this subsection only if there are special build instructions or
+platform limitations.
+
+Helpers
+=======
+
+What helper API will users typically use? Describe it here.
+
+Attributes
+==========
+
+What classes hold attributes, and what are the key ones worth mentioning?
+
+Output
+======
+
+What kind of data does the model generate? What are the key trace
+sources? What kind of logging output can be enabled?
+
+Advanced Usage
+==============
+
+Go into further details (such as using the API outside of the helpers)
+in additional sections, as needed.
+
+Examples
+========
+
+What examples using this new code are available? Describe them here.
+
+Troubleshooting
+===============
+
+Add any tips for avoiding pitfalls, etc.
+
+Validation
+**********
+
+Describe how the model has been tested/validated. What tests run in the
+test suite? How much API and code is covered by the tests? Again,
+references to outside published work may help here.
--- /dev/null
+/* -*- 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/core-module.h"
+#include "ns3/oran-interface.h"
+
+extern "C" {
+ // #include "OCUCP-PF-Container.h"
+ #include "OCTET_STRING.h"
+ #include "asn_application.h"
+ // #include "E2SM-KPM-IndicationMessage.h"
+ // #include "FQIPERSlicesPerPlmnListItem.h"
+ // #include "E2SM-KPM-RANfunction-Description.h"
+ // #include "E2SM-KPM-IndicationHeader-Format1.h"
+ // #include "E2SM-KPM-IndicationHeader.h"
+ // #include "Timestamp.h"
+ #include "E2AP-PDU.h"
+ #include "RICsubscriptionRequest.h"
+ #include "RICsubscriptionResponse.h"
+ #include "RICactionType.h"
+ #include "ProtocolIE-Field.h"
+ #include "ProtocolIE-SingleContainer.h"
+ #include "InitiatingMessage.h"
+}
+
+#include "e2sim.hpp"
+
+using namespace ns3;
+
+int
+main (int argc, char *argv[])
+{
+ E2Sim e2sim;
+ e2sim.run_loop (argc, argv);
+
+ Simulator::Run ();
+ Simulator::Destroy ();
+ return 0;
+}
--- /dev/null
+/* -*- 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/core-module.h"
+#include "ns3/oran-interface.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("L3RrcExample");
+
+Ptr<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>
+CreateL3RrcUeSpecificSinrNeigh (long neighCellId, long sinr)
+{
+ Ptr<L3RrcMeasurements> l3RrcMeasurement = Create<L3RrcMeasurements> (RRCEvent_b1);
+ Ptr<MeasResultNr> measResultNr = Create<MeasResultNr> (neighCellId);
+ Ptr<MeasQuantityResultsWrap> measQuantityResultWrap = Create<MeasQuantityResultsWrap> ();
+ measQuantityResultWrap->AddSinr (sinr);
+ measResultNr->AddCellResults (MeasResultNr::SSB, measQuantityResultWrap->GetPointer ());
+
+ l3RrcMeasurement->AddMeasResultNRNeighCells (
+ measResultNr->GetPointer ()); // MAX 8 UE per message (standard)
+
+ return l3RrcMeasurement;
+}
+
+
+// The memory leaks occurring in this file are wanted because L3-RRC is usually freed after use in the Ric Indication Message
+
+int
+main (int argc, char *argv[])
+{
+ LogComponentEnableAll (LOG_PREFIX_ALL);
+ LogComponentEnable ("L3RrcExample", LOG_LEVEL_ALL);
+ LogComponentEnable ("Asn1Types", LOG_LEVEL_ALL);
+
+ // 1 UE-specific (L3) SINR from NR serving cells
+ NS_LOG_INFO ("1 UE-specific (L3) SINR from NR serving cells");
+ Ptr<L3RrcMeasurements> l3RrcMeasurement1 = CreateL3RrcUeSpecificSinrServing (1, 1, 10);
+ xer_fprint (stderr, &asn_DEF_L3_RRC_Measurements, l3RrcMeasurement1->GetPointer ());
+
+ // 2 UE-specific (L3) SINR from NR neighboring cells
+ NS_LOG_INFO ("2 UE-specific (L3) SINR from NR neighboring cells");
+ Ptr<L3RrcMeasurements> l3RrcMeasurement2 = CreateL3RrcUeSpecificSinrNeigh (2, 20);
+
+ // 3 UE-specific (L3) SINR report from NR neighboring cells
+ NS_LOG_INFO ("3 UE-specific (L3) SINR report from NR neighboring cells");
+ long neighCellId3 = 3;
+ long sinr3 = 30;
+
+ Ptr<MeasResultNr> measResultNr3 = Create<MeasResultNr> (neighCellId3);
+ Ptr<MeasQuantityResultsWrap> measQuantityResultWrap3 = Create<MeasQuantityResultsWrap> ();
+ measQuantityResultWrap3->AddSinr (sinr3);
+ measResultNr3->AddCellResults (MeasResultNr::SSB, measQuantityResultWrap3->GetPointer ());
+
+ l3RrcMeasurement2->AddMeasResultNRNeighCells (measResultNr3->GetPointer ());
+
+ xer_fprint (stderr, &asn_DEF_L3_RRC_Measurements, l3RrcMeasurement2->GetPointer ());
+
+ // 4 UE-specific (L3) SINR from LTE serving cells
+ NS_LOG_INFO ("4 UE-specific (L3) SINR from LTE serving cells");
+ long eutraPhysCellId4 = 4;
+ long servCellId4 = 4;
+ long sinr4 = 40;
+ Ptr<L3RrcMeasurements> l3RrcMeasurement4 =
+ CreateL3RrcUeSpecificSinrServing (servCellId4, eutraPhysCellId4, sinr4);
+ xer_fprint (stderr, &asn_DEF_L3_RRC_Measurements, l3RrcMeasurement4->GetPointer ());
+
+
+ // 5 UE-specific (L3) SINR from LTE neighboring cells
+ NS_LOG_INFO ("5 UE-specific (L3) SINR from LTE neighboring cells");
+ long neighCellId5 = 5;
+ long sinr5 = 50;
+ Ptr<L3RrcMeasurements> l3RrcMeasurement3 = Create<L3RrcMeasurements> (RRCEvent_a5);
+ Ptr<MeasResultEutra> measResultEutra5 = Create<MeasResultEutra> (neighCellId5);
+ measResultEutra5->AddSinr (sinr5);
+ l3RrcMeasurement3->AddMeasResultEUTRANeighCells (measResultEutra5->GetPointer ());
+ xer_fprint (stderr, &asn_DEF_L3_RRC_Measurements, l3RrcMeasurement3->GetPointer ());
+
+
+ return 0;
+}
--- /dev/null
+/* -*- 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/core-module.h"
+#include "ns3/oran-interface.h"
+#include "encode_e2apv1.hpp"
+#include <errno.h>
+
+
+using namespace ns3;
+
+Ptr<E2Termination> e2Term;
+// TODO create getters for these parameters in e2Term
+std::string plmId = "111";
+uint16_t cellId = 1;
+const std::string gnb = std::to_string (cellId);
+
+/**
+* Creates an empty RIC Report message and send it to the RIC
+*
+* \param params the RIC Subscription Request parameters
+*/
+static void BuildAndSendReportMessage (E2Termination::RicSubscriptionRequest_rval_s params)
+{
+ KpmIndicationHeader::KpmRicIndicationHeaderValues headerValues;
+ headerValues.m_plmId = plmId;
+ headerValues.m_gnbId = cellId;
+ headerValues.m_nrCellId = cellId;
+
+ Ptr<KpmIndicationHeader> header = Create<KpmIndicationHeader> (KpmIndicationHeader::GlobalE2nodeType::gNB, headerValues);
+
+ KpmIndicationMessage::KpmIndicationMessageValues msgValues;
+
+ Ptr<OCuUpContainerValues> cuUpValues = Create<OCuUpContainerValues> ();
+ cuUpValues->m_plmId = plmId;
+ cuUpValues->m_pDCPBytesUL = 100;
+ cuUpValues->m_pDCPBytesDL = 100;
+ msgValues.m_pmContainerValues = cuUpValues;
+
+ Ptr<MeasurementItemList> ue0DummyValues = Create<MeasurementItemList> ("UE-0");
+ ue0DummyValues->AddItem<long> ("DRB.PdcpSduVolumeDl_Filter.UEID", 6);
+ ue0DummyValues->AddItem<long> ("QosFlow.PdcpPduVolumeDL_Filter.UEID", 7);
+ ue0DummyValues->AddItem<long> ("Tot.PdcpSduNbrDl.UEID", 8);
+ ue0DummyValues->AddItem<long> ("DRB.PdcpPduNbrDl.Qos.UEID", 9);
+ ue0DummyValues->AddItem<double> ("DRB.IPThpDl.UEID", 10.0);
+ ue0DummyValues->AddItem<double> ("DRB.IPLateDl.UEID", 11.0);
+ msgValues.m_ueIndications.insert (ue0DummyValues);
+
+ Ptr<MeasurementItemList> ue1DummyValues = Create<MeasurementItemList> ("UE-1");;
+ ue1DummyValues->AddItem<long> ("DRB.PdcpSduVolumeDl_Filter.UEID", 6);
+ ue1DummyValues->AddItem<long> ("QosFlow.PdcpPduVolumeDL_Filter.UEID", 7);
+ ue1DummyValues->AddItem<long> ("Tot.PdcpSduNbrDl.UEID", 8);
+ ue1DummyValues->AddItem<long> ("DRB.PdcpPduNbrDl.Qos.UEID", 9);
+ ue1DummyValues->AddItem<double> ("DRB.IPThpDl.UEID", 10.0);
+ ue1DummyValues->AddItem<double> ("DRB.IPLateDl.UEID", 11.0);
+ msgValues.m_ueIndications.insert (ue1DummyValues);
+
+ Ptr<KpmIndicationMessage> msg = Create<KpmIndicationMessage> (msgValues);
+
+ E2AP_PDU *pdu_cuup_ue = new E2AP_PDU;
+ encoding::generate_e2apv1_indication_request_parameterized(pdu_cuup_ue,
+ params.requestorId,
+ params.instanceId,
+ params.ranFuncionId,
+ params.actionId,
+ 1, // TODO sequence number
+ (uint8_t*) header->m_buffer, // buffer containing the encoded header
+ header->m_size, // size of the encoded header
+ (uint8_t*) msg->m_buffer, // buffer containing the encoded message
+ msg->m_size); // size of the encoded message
+ e2Term->SendE2Message (pdu_cuup_ue);
+ delete pdu_cuup_ue;
+
+}
+
+/**
+* KPM Subscription Request callback.
+* This function is triggered whenever a RIC Subscription Request for
+* the KPM RAN Function is received.
+*
+* \param pdu request message
+*/
+static void KpmSubscriptionCallback (E2AP_PDU_t* sub_req_pdu)
+{
+ NS_LOG_UNCOND ("\n\nReceived RIC Subscription Request");
+
+ E2Termination::RicSubscriptionRequest_rval_s params = e2Term->ProcessRicSubscriptionRequest (sub_req_pdu);
+ NS_LOG_UNCOND ("requestorId " << +params.requestorId <<
+ ", instanceId " << +params.instanceId <<
+ ", ranFuncionId " << +params.ranFuncionId <<
+ ", actionId " << +params.actionId);
+
+ BuildAndSendReportMessage (params);
+}
+
+/**
+* RIC Control Message callback.
+* This function is triggered whenever a RIC Control Message is received.
+*
+* \param pdu request message
+*/
+static void
+RicControlMessageCallback (E2AP_PDU_t *ric_ctrl_pdu)
+{
+ NS_LOG_UNCOND ("\n\nReceived RIC Control Message");
+
+ RicControlMessage msg = RicControlMessage (ric_ctrl_pdu);
+ // TODO log something
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ LogComponentEnable ("Asn1Types", LOG_LEVEL_ALL);
+ LogComponentEnable ("RicControlMessage", LOG_LEVEL_ALL);
+ e2Term = CreateObject<E2Termination> ("10.244.0.191", 36422, 38472, gnb, plmId);
+ Ptr<KpmFunctionDescription> kpmFd = Create<KpmFunctionDescription> ();
+ e2Term->RegisterKpmCallbackToE2Sm (200, kpmFd, &KpmSubscriptionCallback);
+ Ptr<RicControlFunctionDescription> rcFd = Create<RicControlFunctionDescription> ();
+ e2Term->RegisterSmCallbackToE2Sm (300, rcFd, &RicControlMessageCallback);
+
+ return 0;
+}
--- /dev/null
+/* -*- 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/core-module.h"
+#include "ns3/oran-interface.h"
+
+using namespace ns3;
+
+
+
+int
+main (int argc, char *argv[])
+{
+ LogComponentEnable ("Asn1Types", LOG_LEVEL_ALL);
+ LogComponentEnable ("RicControlMessage", LOG_LEVEL_ALL);
+ Ptr<RicControlFunctionDescription> rcFd = Create<RicControlFunctionDescription> ();
+
+ return 0;
+}
--- /dev/null
+/* -*- 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/core-module.h"
+#include "ns3/oran-interface.h"
+#include <errno.h>
+
+using namespace ns3;
+
+/**
+* Create and encode RIC Indication messages.
+* Prints the encoded messages in XML format.
+*/
+int
+main (int argc, char *argv[])
+{
+ // LogComponentEnable ("Asn1Types", LOG_LEVEL_ALL);
+ LogComponentEnable ("KpmIndication", LOG_LEVEL_INFO);
+ LogComponentEnable ("KpmFunctionDescription", LOG_LEVEL_INFO);
+
+ std::string plmId = "111";
+ std::string gnbId = "1";
+ uint16_t nrCellId = 5;
+
+ uint64_t timestamp = 1630068655325;
+ // "12:58:04.123456";
+ uint64_t timestamp2 = 1630068679511;
+ // "12:58:05.123457";
+ uint64_t timestamp3 = 1630068680196;
+ // "12:58:06.123458";
+ uint64_t timestamp4 = 1630068681372;
+ // "12:58:07.123459";
+
+ NS_LOG_UNCOND ("----------- Begin of Kpm Indication header -----------");
+
+ KpmIndicationHeader::KpmRicIndicationHeaderValues headerValues;
+ headerValues.m_plmId = plmId;
+ headerValues.m_gnbId = gnbId;
+ headerValues.m_nrCellId = nrCellId;
+ headerValues.m_timestamp = timestamp;
+
+KpmIndicationHeader::KpmRicIndicationHeaderValues headerValues2;
+ headerValues2.m_plmId = plmId;
+ headerValues2.m_gnbId = gnbId;
+ headerValues2.m_nrCellId = nrCellId;
+ headerValues2.m_timestamp = timestamp2;
+
+ KpmIndicationHeader::KpmRicIndicationHeaderValues headerValues3;
+ headerValues3.m_plmId = plmId;
+ headerValues3.m_gnbId = gnbId;
+ headerValues3.m_nrCellId = nrCellId;
+ headerValues3.m_timestamp = timestamp3;
+
+ KpmIndicationHeader::KpmRicIndicationHeaderValues headerValues4;
+ headerValues4.m_plmId = plmId;
+ headerValues4.m_gnbId = gnbId;
+ headerValues4.m_nrCellId = nrCellId;
+ headerValues4.m_timestamp = timestamp4;
+
+ Ptr<KpmIndicationHeader> header = Create<KpmIndicationHeader> (KpmIndicationHeader::GlobalE2nodeType::eNB, headerValues);
+ Ptr<KpmIndicationHeader> header2 = Create<KpmIndicationHeader> (KpmIndicationHeader::GlobalE2nodeType::gNB, headerValues2);
+ Ptr<KpmIndicationHeader> header3 = Create<KpmIndicationHeader> (KpmIndicationHeader::GlobalE2nodeType::ng_eNB, headerValues3);
+ Ptr<KpmIndicationHeader> header4 = Create<KpmIndicationHeader> (KpmIndicationHeader::GlobalE2nodeType::en_gNB, headerValues4);
+
+ NS_LOG_UNCOND ("----------- End of the Kpm Indication header -----------");
+ return 0;
+
+ KpmIndicationMessage::KpmIndicationMessageValues msgValues1;
+
+ NS_LOG_UNCOND ("----------- Begin of the CU-UP message -----------");
+
+ // Begin example CU-UP
+ // uncomment this to test CU-UP
+
+ Ptr<OCuUpContainerValues> cuUpValues = Create<OCuUpContainerValues> ();
+ cuUpValues->m_plmId = plmId;
+ cuUpValues->m_pDCPBytesUL = 100;
+ cuUpValues->m_pDCPBytesDL = 100;
+
+ Ptr<MeasurementItemList> ue0DummyValues = Create<MeasurementItemList> ("UE-0");
+ ue0DummyValues->AddItem<long> ("DRB.PdcpSduVolumeDl_Filter.UEID", 6);
+ ue0DummyValues->AddItem<long> ("QosFlow.PdcpPduVolumeDL_Filter.UEID", 7);
+ ue0DummyValues->AddItem<long> ("Tot.PdcpSduNbrDl.UEID", 8);
+ ue0DummyValues->AddItem<long> ("DRB.PdcpPduNbrDl.Qos.UEID", 9);
+ ue0DummyValues->AddItem<double> ("DRB.IPThpDl.UEID", 10.0);
+ ue0DummyValues->AddItem<double> ("DRB.IPLateDl.UEID", 11.0);
+ msgValues1.m_ueIndications.insert (ue0DummyValues);
+
+ Ptr<MeasurementItemList> ue1DummyValues = Create<MeasurementItemList> ("UE-1");
+ ue1DummyValues->AddItem<long> ("DRB.PdcpSduVolumeDl_Filter.UEID", 6);
+ ue1DummyValues->AddItem<long> ("QosFlow.PdcpPduVolumeDL_Filter.UEID", 7);
+ ue1DummyValues->AddItem<long> ("Tot.PdcpSduNbrDl.UEID", 8);
+ ue1DummyValues->AddItem<long> ("DRB.PdcpPduNbrDl.Qos.UEID", 9);
+ ue1DummyValues->AddItem<double> ("DRB.IPThpDl.UEID", 10.0);
+ ue1DummyValues->AddItem<double> ("DRB.IPLateDl.UEID", 11.0);
+ msgValues1.m_ueIndications.insert(ue1DummyValues);
+ msgValues1.m_pmContainerValues = cuUpValues;
+
+ Ptr<KpmIndicationMessage> msg = Create<KpmIndicationMessage> (msgValues1);
+
+ NS_LOG_UNCOND ("----------- End of the CU-UP message -----------");
+
+ NS_LOG_UNCOND ("----------- Begin of the CU-CP message -----------");
+ KpmIndicationMessage::KpmIndicationMessageValues msgValues2;
+ msgValues2.m_cellObjectId = "NRCellCU";
+ Ptr<OCuCpContainerValues> cuCpValues = Create<OCuCpContainerValues> ();
+ cuCpValues->m_numActiveUes = 100;
+
+ Ptr<MeasurementItemList> ue2DummyValues =
+ Create<MeasurementItemList> ("UE-2");
+ ue2DummyValues->AddItem<long> ("DRB.EstabSucc.5QI.UEID", 6);
+ ue2DummyValues->AddItem<long> ("DRB.RelActNbr.5QI.UEID", 7);
+ msgValues2.m_ueIndications.insert (ue2DummyValues);
+
+ Ptr<MeasurementItemList> ue3DummyValues =
+ Create<MeasurementItemList> ("UE-3");
+ ue3DummyValues->AddItem<long> ("DRB.EstabSucc.5QI.UEID", 6);
+ ue3DummyValues->AddItem<long> ("DRB.RelActNbr.5QI.UEID", 7);
+ msgValues2.m_ueIndications.insert (ue3DummyValues);
+
+ Ptr<MeasurementItemList> ue4DummyValues =
+ Create<MeasurementItemList> ("UE-4");
+
+ Ptr<L3RrcMeasurements> l3RrcMeasurement = Create<L3RrcMeasurements> (RRCEvent_b1);
+ Ptr<ServingCellMeasurementsWrap> servingCellMeasurements =
+ Create<ServingCellMeasurementsWrap> (ServingCellMeasurements_PR_nr_measResultServingMOList);
+
+ Ptr<MeasResultNr> measResultNr = Create<MeasResultNr> (39);
+ Ptr<MeasQuantityResultsWrap> measQuantityResultWrap = Create<MeasQuantityResultsWrap> ();
+ measQuantityResultWrap->AddSinr (20);
+ measResultNr->AddCellResults (MeasResultNr::SSB, measQuantityResultWrap->GetPointer ());
+ Ptr<MeasResultServMo> measResultServMo =
+ Create<MeasResultServMo> (10, measResultNr->GetValue ());
+ servingCellMeasurements->AddMeasResultServMo (measResultServMo->GetPointer ());
+ l3RrcMeasurement->AddServingCellMeasurement (servingCellMeasurements->GetPointer ());
+
+ ue4DummyValues->AddItem<Ptr<L3RrcMeasurements>> ("calla",l3RrcMeasurement);
+ ue4DummyValues->AddItem<long> ("DRB.RelActNbr.5QI.UEID", 7);
+ msgValues2.m_ueIndications.insert (ue4DummyValues);
+ msgValues2.m_pmContainerValues = cuCpValues;
+
+ Ptr<KpmIndicationMessage> msg2 = Create<KpmIndicationMessage> (msgValues2);
+ NS_LOG_UNCOND ("----------- End of the CU-CP message -----------");
+
+ NS_LOG_UNCOND ("----------- Begin test of the DU message -----------");
+ KpmIndicationMessage::KpmIndicationMessageValues msgValues3;
+ msgValues3.m_cellObjectId = "NRCellCU";
+
+ Ptr<ODuContainerValues> oDuContainerVal = Create<ODuContainerValues> ();
+ Ptr<CellResourceReport> cellResRep = Create<CellResourceReport> ();
+ cellResRep->m_plmId = "111";
+ // std::stringstream ss;
+ // ss << std::hex << 1340012;
+ cellResRep->m_nrCellId = 2;
+ cellResRep->dlAvailablePrbs = 6;
+ cellResRep->ulAvailablePrbs = 6;
+
+ Ptr<CellResourceReport> cellResRep2 = Create<CellResourceReport> ();
+ cellResRep2->m_plmId = "444";
+ cellResRep2->m_nrCellId = 3;
+ cellResRep2->dlAvailablePrbs = 5;
+ cellResRep2->ulAvailablePrbs = 5;
+
+ Ptr<ServedPlmnPerCell> servedPlmnPerCell = Create<ServedPlmnPerCell> ();
+ servedPlmnPerCell->m_plmId = "121";
+ servedPlmnPerCell->m_nrCellId = 3;
+
+ Ptr<ServedPlmnPerCell> servedPlmnPerCell2 = Create<ServedPlmnPerCell> ();
+ servedPlmnPerCell2->m_plmId = "121";
+ servedPlmnPerCell2->m_nrCellId = 2;
+
+ Ptr<EpcDuPmContainer> epcDuVal = Create<EpcDuPmContainer> ();
+ epcDuVal->m_qci = 1;
+ epcDuVal->m_dlPrbUsage = 1;
+ epcDuVal->m_ulPrbUsage = 2;
+
+ Ptr<EpcDuPmContainer> epcDuVal2 = Create<EpcDuPmContainer> ();
+ epcDuVal2->m_qci = 1;
+ epcDuVal2->m_dlPrbUsage = 3;
+ epcDuVal2->m_ulPrbUsage = 4;
+
+ servedPlmnPerCell->m_perQciReportItems.insert (epcDuVal);
+ servedPlmnPerCell->m_perQciReportItems.insert (epcDuVal2);
+ servedPlmnPerCell2->m_perQciReportItems.insert (epcDuVal);
+ servedPlmnPerCell2->m_perQciReportItems.insert (epcDuVal2);
+ cellResRep->m_servedPlmnPerCellItems.insert (servedPlmnPerCell2);
+ cellResRep->m_servedPlmnPerCellItems.insert (servedPlmnPerCell);
+ cellResRep2->m_servedPlmnPerCellItems.insert (servedPlmnPerCell2);
+ cellResRep2->m_servedPlmnPerCellItems.insert (servedPlmnPerCell);
+
+ oDuContainerVal->m_cellResourceReportItems.insert (cellResRep);
+ oDuContainerVal->m_cellResourceReportItems.insert (cellResRep2);
+
+ Ptr<MeasurementItemList> ue5DummyValues = Create<MeasurementItemList> ("UE-5");
+ ue5DummyValues->AddItem<long> ("DRB.EstabSucc.5QI.UEID", 6);
+ ue5DummyValues->AddItem<long> ("DRB.RelActNbr.5QI.UEID", 7);
+ msgValues3.m_ueIndications.insert (ue5DummyValues);
+
+ msgValues3.m_pmContainerValues = oDuContainerVal;
+ Ptr<KpmIndicationMessage> msg3 = Create<KpmIndicationMessage> (msgValues3);
+
+ NS_LOG_UNCOND ("----------- End test of the DU message -----------");
+
+ NS_LOG_UNCOND ("----------- Begin test of the KpmFunctionDescription -----------");
+ Ptr<KpmFunctionDescription> fd = Create<KpmFunctionDescription> ();
+ NS_LOG_UNCOND ("----------- End test of the KpmFunctionDescription -----------");
+
+ return 0;
+}
--- /dev/null
+/* -*- 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/core-module.h"
+#include "ns3/oran-interface.h"
+#include <errno.h>
+
+using namespace ns3;
+
+/**
+* Test field for the wrappers and their functions
+*/
+int
+main (int argc, char *argv[])
+{
+ // LogComponentEnable ("Asn1Types", LOG_LEVEL_ALL);
+ std::string test = "test";
+// Ptr<OctetString> one = Create<OctetString> (test, test.size ());
+ // Ptr<OctetString> due = Create<OctetString> (test, test.size ());
+ // Ptr<Snssai> snssai = Create<Snssai> ("test");
+
+ // std::cout << due->DecodeContent() << std::endl;
+
+ std::vector<Ptr<NrCellId>> nrCellIds;
+ for (uint16_t i = 0; i < 20; i++)
+ {
+ nrCellIds.push_back(Create<NrCellId> (i));
+ NS_LOG_UNCOND ("Count: " << i << " , value: ");
+ xer_fprint (stdout, &asn_DEF_BIT_STRING, nrCellIds[i]->GetPointer ());
+ }
+
+ return 0;
+}
--- /dev/null
+# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+ obj = bld.create_ns3_program('e2sim-integration-example', ['oran-interface'])
+ obj.source = 'e2sim-integration-example.cc'
+
+ obj = bld.create_ns3_program('oran-interface-example', ['oran-interface'])
+ obj.source = 'oran-interface-example.cc'
+
+ obj = bld.create_ns3_program('ric-indication-messages', ['oran-interface'])
+ obj.source = 'ric-indication-messages.cc'
+
+ obj = bld.create_ns3_program('ric-control-function-desc', ['oran-interface'])
+ obj.source = 'ric-control-function-desc.cc'
+
+ obj = bld.create_ns3_program('l3-rrc-example', ['oran-interface'])
+ obj.source = 'l3-rrc-example.cc'
+
+ obj = bld.create_ns3_program('test-wrappers', ['oran-interface'])
+ obj.source = 'test-wrappers.cc'
--- /dev/null
+/* -*- 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/indication-message-helper.h>
+
+namespace ns3 {
+
+IndicationMessageHelper::IndicationMessageHelper (IndicationMessageType type, bool isOffline,
+ bool reducedPmValues)
+ : m_type (type), m_offline (isOffline), m_reducedPmValues (reducedPmValues)
+{
+
+ if (!m_offline)
+ {
+ switch (type)
+ {
+ case IndicationMessageType::CuUp:
+ m_cuUpValues = Create<OCuUpContainerValues> ();
+ break;
+
+ case IndicationMessageType::CuCp:
+ m_cuCpValues = Create<OCuCpContainerValues> ();
+ m_msgValues.m_cellObjectId = "NRCellCU";
+ break;
+
+ case IndicationMessageType::Du:
+ m_duValues = Create<ODuContainerValues> ();
+ break;
+
+ default:
+
+ break;
+ }
+ }
+}
+
+void
+IndicationMessageHelper::FillBaseCuUpValues (std::string plmId)
+{
+ NS_ABORT_MSG_IF (m_type != IndicationMessageType::CuUp, "Wrong function for this object");
+ m_cuUpValues->m_plmId = plmId;
+ m_msgValues.m_pmContainerValues = m_cuUpValues;
+}
+
+void
+IndicationMessageHelper::FillBaseCuCpValues (uint16_t numActiveUes)
+{
+ NS_ABORT_MSG_IF (m_type != IndicationMessageType::CuCp, "Wrong function for this object");
+ m_cuCpValues->m_numActiveUes = numActiveUes;
+ m_msgValues.m_pmContainerValues = m_cuCpValues;
+}
+
+IndicationMessageHelper::~IndicationMessageHelper ()
+{
+}
+
+Ptr<KpmIndicationMessage>
+IndicationMessageHelper::CreateIndicationMessage ()
+{
+ return Create<KpmIndicationMessage> (m_msgValues);
+}
+
+} // namespace ns3
\ No newline at end of file
--- /dev/null
+/* -*- 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>
+ */
+
+#ifndef INDICATION_MESSAGE_HELPER_H
+#define INDICATION_MESSAGE_HELPER_H
+
+#include <ns3/kpm-indication.h>
+
+namespace ns3 {
+
+class IndicationMessageHelper : public Object
+{
+public:
+ enum class IndicationMessageType { CuCp = 0, CuUp = 1, Du = 2 };
+ IndicationMessageHelper (IndicationMessageType type, bool isOffline, bool reducedPmValues);
+
+ ~IndicationMessageHelper ();
+
+ Ptr<KpmIndicationMessage> CreateIndicationMessage ();
+
+ bool const &
+ IsOffline () const
+ {
+ return m_offline;
+ }
+
+protected:
+ void FillBaseCuUpValues (std::string plmId);
+
+ void FillBaseCuCpValues (uint16_t numActiveUes);
+
+ IndicationMessageType m_type;
+ bool m_offline;
+ bool m_reducedPmValues;
+ KpmIndicationMessage::KpmIndicationMessageValues m_msgValues;
+ Ptr<OCuUpContainerValues> m_cuUpValues;
+ Ptr<OCuCpContainerValues> m_cuCpValues;
+ Ptr<ODuContainerValues> m_duValues;
+};
+
+} // namespace ns3
+
+#endif /* INDICATION_MESSAGE_HELPER_H */
\ No newline at end of file
--- /dev/null
+/* -*- 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/lte-indication-message-helper.h>
+
+namespace ns3 {
+
+LteIndicationMessageHelper::LteIndicationMessageHelper (IndicationMessageType type, bool isOffline,
+ bool reducedPmValues)
+ : IndicationMessageHelper (type, isOffline, reducedPmValues)
+{
+ NS_ABORT_MSG_IF (type == IndicationMessageType::Du,
+ "Wrong type for LTE Indication Message, expected CuUp or CuCp");
+}
+
+void
+LteIndicationMessageHelper::AddCuUpUePmItem (std::string ueImsiComplete, long txBytes,
+ long txDlPackets, double pdcpThroughput,
+ double pdcpLatency)
+{
+ Ptr<MeasurementItemList> ueVal = Create<MeasurementItemList> (ueImsiComplete);
+
+ if (!m_reducedPmValues)
+ {
+ // UE-specific PDCP SDU volume from LTE eNB. Unit is Mbits
+ ueVal->AddItem<long> ("DRB.PdcpSduVolumeDl_Filter.UEID", txBytes);
+
+ // UE-specific number of PDCP SDUs from LTE eNB
+ ueVal->AddItem<long> ("Tot.PdcpSduNbrDl.UEID", txDlPackets);
+
+ // UE-specific Downlink IP combined EN-DC throughput from LTE eNB. Unit is kbps
+ ueVal->AddItem<double> ("DRB.PdcpSduBitRateDl.UEID", pdcpThroughput);
+
+ //UE-specific Downlink IP combined EN-DC throughput from LTE eNB
+ ueVal->AddItem<double> ("DRB.PdcpSduDelayDl.UEID", pdcpLatency);
+ }
+
+ m_msgValues.m_ueIndications.insert (ueVal);
+}
+
+void
+LteIndicationMessageHelper::AddCuUpCellPmItem (double cellAverageLatency)
+{
+ if (!m_reducedPmValues)
+ {
+ Ptr<MeasurementItemList> cellVal = Create<MeasurementItemList> ();
+ cellVal->AddItem<double> ("DRB.PdcpSduDelayDl", cellAverageLatency);
+ m_msgValues.m_cellMeasurementItems = cellVal;
+ }
+}
+
+void
+LteIndicationMessageHelper::FillCuUpValues (std::string plmId, long pdcpBytesUl, long pdcpBytesDl)
+{
+ m_cuUpValues->m_pDCPBytesUL = pdcpBytesUl;
+ m_cuUpValues->m_pDCPBytesDL = pdcpBytesDl;
+ FillBaseCuUpValues (plmId);
+}
+
+void
+LteIndicationMessageHelper::FillCuCpValues (uint16_t numActiveUes)
+{
+ FillBaseCuCpValues (numActiveUes);
+}
+
+void
+LteIndicationMessageHelper::AddCuCpUePmItem (std::string ueImsiComplete, long numDrb,
+ long drbRelAct)
+{
+
+ Ptr<MeasurementItemList> ueVal = Create<MeasurementItemList> (ueImsiComplete);
+ if (!m_reducedPmValues)
+ {
+ ueVal->AddItem<long> ("DRB.EstabSucc.5QI.UEID", numDrb);
+ ueVal->AddItem<long> ("DRB.RelActNbr.5QI.UEID", drbRelAct); // not modeled in the simulator
+ }
+ m_msgValues.m_ueIndications.insert (ueVal);
+}
+
+LteIndicationMessageHelper::~LteIndicationMessageHelper ()
+{
+}
+
+} // namespace ns3
\ No newline at end of file
--- /dev/null
+/* -*- 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>
+ */
+
+#ifndef LTE_INDICATION_MESSAGE_HELPER_H
+#define LTE_INDICATION_MESSAGE_HELPER_H
+
+#include <ns3/indication-message-helper.h>
+
+namespace ns3 {
+
+class LteIndicationMessageHelper : public IndicationMessageHelper
+{
+public:
+ LteIndicationMessageHelper (IndicationMessageType type, bool isOffline, bool reducedPmValues);
+
+ ~LteIndicationMessageHelper ();
+
+ void FillCuUpValues (std::string plmId, long pdcpBytesUl, long pdcpBytesDl);
+
+ void AddCuUpUePmItem (std::string ueImsiComplete, long txBytes, long txDlPackets,
+ double pdcpThroughput, double pdcpLatency);
+
+ void AddCuUpCellPmItem (double cellAverageLatency);
+
+ void FillCuCpValues (uint16_t numActiveUes);
+
+ void AddCuCpUePmItem (std::string ueImsiComplete, long numDrb, long drbRelAct);
+
+private:
+};
+
+} // namespace ns3
+
+#endif /* LTE_INDICATION_MESSAGE_HELPER_H */
\ No newline at end of file
--- /dev/null
+/* -*- 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/mmwave-indication-message-helper.h>
+
+namespace ns3 {
+
+MmWaveIndicationMessageHelper::MmWaveIndicationMessageHelper (IndicationMessageType type,
+ bool isOffline, bool reducedPmValues)
+ : IndicationMessageHelper (type, isOffline, reducedPmValues)
+{
+}
+
+void
+MmWaveIndicationMessageHelper::AddCuUpUePmItem (std::string ueImsiComplete,
+ long txPdcpPduBytesNrRlc, long txPdcpPduNrRlc)
+{
+ Ptr<MeasurementItemList> ueVal = Create<MeasurementItemList> (ueImsiComplete);
+ if (!m_reducedPmValues)
+ {
+ // UE-specific PDCP PDU volume transmitted to NR gNB (Unit is Kbits)
+ ueVal->AddItem<long> ("QosFlow.PdcpPduVolumeDL_Filter.UEID", txPdcpPduBytesNrRlc);
+
+ // UE-specific number of PDCP PDUs split with NR gNB
+ ueVal->AddItem<long> ("DRB.PdcpPduNbrDl.Qos.UEID", txPdcpPduNrRlc);
+ }
+
+ m_msgValues.m_ueIndications.insert (ueVal);
+}
+
+void
+MmWaveIndicationMessageHelper::FillCuUpValues (std::string plmId)
+{
+ FillBaseCuUpValues (plmId);
+}
+
+void
+MmWaveIndicationMessageHelper::FillCuCpValues (uint16_t numActiveUes)
+{
+ FillBaseCuCpValues (numActiveUes);
+}
+
+void
+MmWaveIndicationMessageHelper::FillDuValues (std::string cellObjectId)
+{
+ m_msgValues.m_cellObjectId = cellObjectId;
+ m_msgValues.m_pmContainerValues = m_duValues;
+}
+
+void
+MmWaveIndicationMessageHelper::AddDuUePmItem (
+ std::string ueImsiComplete, long macPduUe, long macPduInitialUe, long macQpsk, long mac16Qam,
+ long mac64Qam, long macRetx, long macVolume, long macPrb, long macMac04, long macMac59,
+ long macMac1014, long macMac1519, long macMac2024, long macMac2529, long macSinrBin1,
+ long macSinrBin2, long macSinrBin3, long macSinrBin4, long macSinrBin5, long macSinrBin6,
+ long macSinrBin7, long rlcBufferOccup, double drbThrDlUeid)
+{
+
+ Ptr<MeasurementItemList> ueVal = Create<MeasurementItemList> (ueImsiComplete);
+ if (!m_reducedPmValues)
+ {
+ ueVal->AddItem<long> ("TB.TotNbrDl.1.UEID", macPduUe);
+ ueVal->AddItem<long> ("TB.TotNbrDlInitial.UEID", macPduInitialUe);
+ ueVal->AddItem<long> ("TB.TotNbrDlInitial.Qpsk.UEID", macQpsk);
+ ueVal->AddItem<long> ("TB.TotNbrDlInitial.16Qam.UEID", mac16Qam);
+ ueVal->AddItem<long> ("TB.TotNbrDlInitial.64Qam.UEID", mac64Qam);
+ ueVal->AddItem<long> ("TB.ErrTotalNbrDl.1.UEID", macRetx);
+ ueVal->AddItem<long> ("QosFlow.PdcpPduVolumeDL_Filter.UEID", macVolume);
+ ueVal->AddItem<long> ("RRU.PrbUsedDl.UEID", (long) std::ceil (macPrb));
+ ueVal->AddItem<long> ("CARR.PDSCHMCSDist.Bin1.UEID", macMac04);
+ ueVal->AddItem<long> ("CARR.PDSCHMCSDist.Bin2.UEID", macMac59);
+ ueVal->AddItem<long> ("CARR.PDSCHMCSDist.Bin3.UEID", macMac1014);
+ ueVal->AddItem<long> ("CARR.PDSCHMCSDist.Bin4.UEID", macMac1519);
+ ueVal->AddItem<long> ("CARR.PDSCHMCSDist.Bin5.UEID", macMac2024);
+ ueVal->AddItem<long> ("CARR.PDSCHMCSDist.Bin6.UEID", macMac2529);
+ ueVal->AddItem<long> ("L1M.RS-SINR.Bin34.UEID", macSinrBin1);
+ ueVal->AddItem<long> ("L1M.RS-SINR.Bin46.UEID", macSinrBin2);
+ ueVal->AddItem<long> ("L1M.RS-SINR.Bin58.UEID", macSinrBin3);
+ ueVal->AddItem<long> ("L1M.RS-SINR.Bin70.UEID", macSinrBin4);
+ ueVal->AddItem<long> ("L1M.RS-SINR.Bin82.UEID", macSinrBin5);
+ ueVal->AddItem<long> ("L1M.RS-SINR.Bin94.UEID", macSinrBin6);
+ ueVal->AddItem<long> ("L1M.RS-SINR.Bin127.UEID", macSinrBin7);
+ ueVal->AddItem<long> ("DRB.BufferSize.Qos.UEID", rlcBufferOccup);
+ }
+
+ // This value is not requested anymore, so it has been removed from the delivery, but it will be still logged;
+ // ueVal->AddItem<double> ("DRB.UEThpDlPdcpBased.UEID", drbThrDlPdcpBasedUeid);
+
+ ueVal->AddItem<double> ("DRB.UEThpDl.UEID", drbThrDlUeid);
+
+ m_msgValues.m_ueIndications.insert (ueVal);
+}
+
+void
+MmWaveIndicationMessageHelper::AddDuCellPmItem (
+ long macPduCellSpecific, long macPduInitialCellSpecific, long macQpskCellSpecific,
+ long mac16QamCellSpecific, long mac64QamCellSpecific, double prbUtilizationDl,
+ long macRetxCellSpecific, long macVolumeCellSpecific, long macMac04CellSpecific,
+ long macMac59CellSpecific, long macMac1014CellSpecific, long macMac1519CellSpecific,
+ long macMac2024CellSpecific, long macMac2529CellSpecific, long macSinrBin1CellSpecific,
+ long macSinrBin2CellSpecific, long macSinrBin3CellSpecific, long macSinrBin4CellSpecific,
+ long macSinrBin5CellSpecific, long macSinrBin6CellSpecific, long macSinrBin7CellSpecific,
+ long rlcBufferOccupCellSpecific, long activeUeDl)
+{
+ Ptr<MeasurementItemList> cellVal = Create<MeasurementItemList> ();
+
+ if (!m_reducedPmValues)
+ {
+ cellVal->AddItem<long> ("TB.TotNbrDl.1", macPduCellSpecific);
+ cellVal->AddItem<long> ("TB.TotNbrDlInitial", macPduInitialCellSpecific);
+ }
+
+ cellVal->AddItem<long> ("TB.TotNbrDlInitial.Qpsk", macQpskCellSpecific);
+ cellVal->AddItem<long> ("TB.TotNbrDlInitial.16Qam", mac16QamCellSpecific);
+ cellVal->AddItem<long> ("TB.TotNbrDlInitial.64Qam", mac64QamCellSpecific);
+ cellVal->AddItem<long> ("RRU.PrbUsedDl", (long) std::ceil (prbUtilizationDl));
+
+ if (!m_reducedPmValues)
+ {
+ cellVal->AddItem<long> ("TB.ErrTotalNbrDl.1", macRetxCellSpecific);
+ cellVal->AddItem<long> ("QosFlow.PdcpPduVolumeDL_Filter", macVolumeCellSpecific);
+ cellVal->AddItem<long> ("CARR.PDSCHMCSDist.Bin1", macMac04CellSpecific);
+ cellVal->AddItem<long> ("CARR.PDSCHMCSDist.Bin2", macMac59CellSpecific);
+ cellVal->AddItem<long> ("CARR.PDSCHMCSDist.Bin3", macMac1014CellSpecific);
+ cellVal->AddItem<long> ("CARR.PDSCHMCSDist.Bin4", macMac1519CellSpecific);
+ cellVal->AddItem<long> ("CARR.PDSCHMCSDist.Bin5", macMac2024CellSpecific);
+ cellVal->AddItem<long> ("CARR.PDSCHMCSDist.Bin6", macMac2529CellSpecific);
+ cellVal->AddItem<long> ("L1M.RS-SINR.Bin34", macSinrBin1CellSpecific);
+ cellVal->AddItem<long> ("L1M.RS-SINR.Bin46", macSinrBin2CellSpecific);
+ cellVal->AddItem<long> ("L1M.RS-SINR.Bin58", macSinrBin3CellSpecific);
+ cellVal->AddItem<long> ("L1M.RS-SINR.Bin70", macSinrBin4CellSpecific);
+ cellVal->AddItem<long> ("L1M.RS-SINR.Bin82", macSinrBin5CellSpecific);
+ cellVal->AddItem<long> ("L1M.RS-SINR.Bin94", macSinrBin6CellSpecific);
+ cellVal->AddItem<long> ("L1M.RS-SINR.Bin127", macSinrBin7CellSpecific);
+ cellVal->AddItem<long> ("DRB.BufferSize.Qos", rlcBufferOccupCellSpecific);
+ }
+
+ cellVal->AddItem<long> ("DRB.MeanActiveUeDl",activeUeDl);
+
+ m_msgValues.m_cellMeasurementItems = cellVal;
+}
+
+void
+MmWaveIndicationMessageHelper::AddDuCellResRepPmItem (Ptr<CellResourceReport> cellResRep)
+{
+ m_duValues->m_cellResourceReportItems.insert (cellResRep);
+}
+
+void
+MmWaveIndicationMessageHelper::AddCuCpUePmItem (std::string ueImsiComplete, long numDrb,
+ long drbRelAct,
+ Ptr<L3RrcMeasurements> l3RrcMeasurementServing,
+ Ptr<L3RrcMeasurements> l3RrcMeasurementNeigh)
+{
+
+ Ptr<MeasurementItemList> ueVal = Create<MeasurementItemList> (ueImsiComplete);
+ if (!m_reducedPmValues)
+ {
+ ueVal->AddItem<long> ("DRB.EstabSucc.5QI.UEID", numDrb);
+ ueVal->AddItem<long> ("DRB.RelActNbr.5QI.UEID", drbRelAct); // not modeled in the simulator
+ }
+
+ ueVal->AddItem<Ptr<L3RrcMeasurements>> ("HO.SrcCellQual.RS-SINR.UEID", l3RrcMeasurementServing);
+ ueVal->AddItem<Ptr<L3RrcMeasurements>> ("HO.TrgtCellQual.RS-SINR.UEID", l3RrcMeasurementNeigh);
+
+ m_msgValues.m_ueIndications.insert (ueVal);
+}
+
+MmWaveIndicationMessageHelper::~MmWaveIndicationMessageHelper ()
+{
+}
+
+} // namespace ns3
\ No newline at end of file
--- /dev/null
+/* -*- 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>
+ */
+
+#ifndef MMWAVE_INDICATION_MESSAGE_HELPER_H
+#define MMWAVE_INDICATION_MESSAGE_HELPER_H
+
+#include <ns3/indication-message-helper.h>
+
+namespace ns3 {
+
+class MmWaveIndicationMessageHelper : public IndicationMessageHelper
+{
+public:
+ MmWaveIndicationMessageHelper (IndicationMessageType type, bool isOffline, bool reducedPmValues);
+
+ ~MmWaveIndicationMessageHelper ();
+
+ void FillCuUpValues (std::string plmId);
+
+ void AddCuUpUePmItem (std::string ueImsiComplete, long txPdcpPduBytesNrRlc, long txPdcpPduNrRlc);
+
+ void FillCuCpValues (uint16_t numActiveUes);
+
+ void FillDuValues (std::string cellObjectId);
+
+ void AddDuUePmItem (std::string ueImsiComplete, long macPduUe, long macPduInitialUe, long macQpsk,
+ long mac16Qam, long mac64Qam, long macRetx, long macVolume, long macPrb,
+ long macMac04, long macMac59, long macMac1014, long macMac1519,
+ long macMac2024, long macMac2529, long macSinrBin1, long macSinrBin2,
+ long macSinrBin3, long macSinrBin4, long macSinrBin5, long macSinrBin6,
+ long macSinrBin7, long rlcBufferOccup, double drbThrDlUeid);
+
+ void AddDuCellPmItem (
+ long macPduCellSpecific, long macPduInitialCellSpecific, long macQpskCellSpecific,
+ long mac16QamCellSpecific, long mac64QamCellSpecific, double prbUtilizationDl,
+ long macRetxCellSpecific, long macVolumeCellSpecific, long macMac04CellSpecific,
+ long macMac59CellSpecific, long macMac1014CellSpecific, long macMac1519CellSpecific,
+ long macMac2024CellSpecific, long macMac2529CellSpecific, long macSinrBin1CellSpecific,
+ long macSinrBin2CellSpecific, long macSinrBin3CellSpecific, long macSinrBin4CellSpecific,
+ long macSinrBin5CellSpecific, long macSinrBin6CellSpecific, long macSinrBin7CellSpecific,
+ long rlcBufferOccupCellSpecific, long activeUeDl);
+ void AddDuCellResRepPmItem (Ptr<CellResourceReport> cellResRep);
+ void AddCuCpUePmItem (std::string ueImsiComplete, long numDrb, long drbRelAct,
+ Ptr<L3RrcMeasurements> l3RrcMeasurementServing,
+ Ptr<L3RrcMeasurements> l3RrcMeasurementNeigh);
+
+private:
+};
+
+} // namespace ns3
+
+#endif /* MMWAVE_INDICATION_MESSAGE_HELPER_H */
\ No newline at end of file
--- /dev/null
+/* -*- 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 "oran-interface-helper.h"
+
+namespace ns3 {
+
+/* ... */
+
+
+}
+
--- /dev/null
+/* -*- 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>
+ */
+
+#ifndef ORAN_INTERFACE_HELPER_H
+#define ORAN_INTERFACE_HELPER_H
+
+#include "ns3/oran-interface.h"
+
+namespace ns3 {
+
+/* ... */
+
+}
+
+#endif /* ORAN_INTERFACE_HELPER_H */
+
--- /dev/null
+/* -*- 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
--- /dev/null
+/* -*- 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>
+ */
+
+#ifndef ASN1C_TYPES_H
+#define ASN1C_TYPES_H
+
+#include "ns3/object.h"
+#include <ns3/math.h>
+
+extern "C" {
+ #include "OCTET_STRING.h"
+ #include "BIT_STRING.h"
+ #include "PM-Info-Item.h"
+ #include "SNSSAI.h"
+ #include "RRCEvent.h"
+ #include "L3-RRC-Measurements.h"
+ #include "ServingCellMeasurements.h"
+ #include "MeasResultNeighCells.h"
+ #include "MeasResultNR.h"
+ #include "MeasResultEUTRA.h"
+ #include "MeasResultPCell.h"
+ #include "MeasResultListEUTRA.h"
+ #include "MeasResultListNR.h"
+ #include "MeasResultServMO.h"
+ #include "MeasResultServMOList.h"
+ #include "MeasQuantityResults.h"
+ #include "ResultsPerSSB-Index.h"
+ #include "ResultsPerCSI-RS-Index.h"
+ #include "E2SM-RC-ControlMessage-Format1.h"
+ #include "RANParameter-Item.h"
+ #include "RANParameter-ValueType.h"
+ #include "RANParameter-ELEMENT.h"
+ #include "RANParameter-STRUCTURE.h"
+}
+
+namespace ns3 {
+
+/**
+* Wrapper for class for OCTET STRING
+*/
+class OctetString : public SimpleRefCount<OctetString>
+{
+public:
+ OctetString (std::string value, size_t size);
+ OctetString (void *value, size_t size);
+ ~OctetString ();
+ OCTET_STRING_t *GetPointer ();
+ OCTET_STRING_t GetValue ();
+ std::string DecodeContent ();
+
+private:
+ void CreateBaseOctetString (size_t size);
+ OCTET_STRING_t *m_octetString;
+};
+
+/**
+* Wrapper for class for BIT STRING
+*/
+class BitString : public SimpleRefCount<BitString>
+{
+public:
+ BitString (std::string value, size_t size);
+ BitString (std::string value, size_t size, size_t bits_unused);
+ ~BitString ();
+ BIT_STRING_t *GetPointer ();
+ BIT_STRING_t GetValue ();
+ // TODO maybe a to string or a decode method should be created
+
+private:
+ BIT_STRING_t *m_bitString;
+};
+
+class NrCellId : public SimpleRefCount<NrCellId>
+{
+public:
+ NrCellId (uint16_t value);
+ virtual ~NrCellId ();
+ BIT_STRING_t *GetPointer ();
+ BIT_STRING_t GetValue ();
+
+private:
+ Ptr<BitString> m_bitString;
+};
+
+/**
+* Wrapper for class for S-NSSAI
+*/
+class Snssai : public SimpleRefCount<Snssai>
+{
+public:
+ Snssai (std::string sst);
+ Snssai (std::string sst, std::string sd);
+ ~Snssai ();
+ SNSSAI_t *GetPointer ();
+ SNSSAI_t GetValue ();
+
+private:
+ OCTET_STRING_t *m_sst;
+ OCTET_STRING_t *m_sd;
+ SNSSAI_t *m_sNssai;
+};
+
+/**
+* Wrapper for class for MeasQuantityResults_t
+*/
+class MeasQuantityResultsWrap : public SimpleRefCount<MeasQuantityResultsWrap>
+{
+public:
+ MeasQuantityResultsWrap ();
+ ~MeasQuantityResultsWrap ();
+ MeasQuantityResults_t *GetPointer ();
+ MeasQuantityResults_t GetValue ();
+ void AddRsrp (long rsrp);
+ void AddRsrq (long rsrq);
+ void AddSinr (long sinr);
+
+private:
+ MeasQuantityResults_t *m_measQuantityResults;
+};
+
+/**
+* Wrapper for class for ResultsPerCSI_RS_Index_t
+*/
+class ResultsPerCsiRsIndex : public SimpleRefCount<ResultsPerCsiRsIndex>
+{
+public:
+ ResultsPerCsiRsIndex (long csiRsIndex, MeasQuantityResults_t *csiRsResults);
+ ResultsPerCsiRsIndex (long csiRsIndex);
+ ResultsPerCSI_RS_Index_t *GetPointer ();
+ ResultsPerCSI_RS_Index_t GetValue ();
+
+private:
+ ResultsPerCSI_RS_Index_t *m_resultsPerCsiRsIndex;
+};
+
+/**
+* Wrapper for class for ResultsPerSSB_Index_t
+*/
+class ResultsPerSSBIndex : public SimpleRefCount<ResultsPerSSBIndex>
+{
+public:
+ ResultsPerSSBIndex (long ssbIndex, MeasQuantityResults_t *ssbResults);
+ ResultsPerSSBIndex (long ssbIndex);
+ ResultsPerSSB_Index_t *GetPointer ();
+ ResultsPerSSB_Index_t GetValue ();
+
+private:
+ ResultsPerSSB_Index_t *m_resultsPerSSBIndex;
+};
+
+/**
+* Wrapper for class for MeasResultNR_t
+*/
+class MeasResultNr : public SimpleRefCount<MeasResultNr>
+{
+public:
+ enum ResultCell { SSB = 0, CSI_RS = 1 };
+ MeasResultNr (long physCellId);
+ MeasResultNr ();
+ ~MeasResultNr ();
+ MeasResultNR_t *GetPointer ();
+ MeasResultNR_t GetValue ();
+ void AddCellResults (ResultCell cell, MeasQuantityResults_t *results);
+ void AddPerSsbIndexResults (ResultsPerSSB_Index_t *resultsSsbIndex);
+ void AddPerCsiRsIndexResults (ResultsPerCSI_RS_Index_t *resultsCsiRsIndex);
+ void AddPhyCellId (long physCellId);
+
+private:
+ MeasResultNR_t *m_measResultNr;
+ bool m_shouldFree;
+};
+
+/**
+* Wrapper for class for MeasResultEUTRA_t
+*/
+class MeasResultEutra : public SimpleRefCount<MeasResultEutra>
+{
+public:
+ MeasResultEutra (long eutraPhysCellId, long rsrp, long rsrq, long sinr);
+ MeasResultEutra (long eutraPhysCellId);
+ MeasResultEUTRA_t *GetPointer ();
+ MeasResultEUTRA_t GetValue ();
+ void AddRsrp (long rsrp);
+ void AddRsrq (long rsrq);
+ void AddSinr (long sinr);
+
+private:
+ MeasResultEUTRA_t *m_measResultEutra;
+};
+
+/**
+* Wrapper for class for MeasResultPCell_t
+*/
+class MeasResultPCellWrap : public SimpleRefCount<MeasResultPCellWrap>
+{
+public:
+ MeasResultPCellWrap (long eutraPhysCellId, long rsrpResult, long rsrqResult);
+ MeasResultPCellWrap (long eutraPhysCellId);
+ MeasResultPCell_t *GetPointer ();
+ MeasResultPCell_t GetValue ();
+ void AddRsrpResult (long rsrpResult);
+ void AddRsrqResult (long rsrqResult);
+
+private:
+ MeasResultPCell_t *m_measResultPCell;
+};
+
+/**
+* Wrapper for class for MeasResultServMO_t
+*/
+class MeasResultServMo : public SimpleRefCount<MeasResultServMo>
+{
+public:
+ MeasResultServMo (long servCellId, MeasResultNR_t measResultServingCell,
+ MeasResultNR_t *measResultBestNeighCell);
+ MeasResultServMo (long servCellId, MeasResultNR_t measResultServingCell);
+ MeasResultServMO_t *GetPointer ();
+ MeasResultServMO_t GetValue ();
+
+private:
+ MeasResultServMO_t *m_measResultServMo;
+};
+
+/**
+* Wrapper for class for ServingCellMeasurements_t
+*/
+class ServingCellMeasurementsWrap : public SimpleRefCount<ServingCellMeasurementsWrap>
+{
+public:
+ ServingCellMeasurementsWrap (ServingCellMeasurements_PR present);
+ ServingCellMeasurements_t *GetPointer ();
+ ServingCellMeasurements_t GetValue ();
+ void AddMeasResultPCell (MeasResultPCell_t *measResultPCell);
+ void AddMeasResultServMo (MeasResultServMO_t *measResultServMO);
+
+private:
+ ServingCellMeasurements_t *m_servingCellMeasurements;
+ MeasResultServMOList_t *m_nr_measResultServingMOList;
+};
+
+/**
+* Wrapper for class for L3 RRC Measurements
+*/
+class L3RrcMeasurements : public SimpleRefCount<L3RrcMeasurements>
+{
+public:
+ int MAX_MEAS_RESULTS_ITEMS = 8; // Maximum 8 per UE (standard)
+ L3RrcMeasurements (RRCEvent_t rrcEvent);
+ L3RrcMeasurements (L3_RRC_Measurements_t *l3RrcMeasurements);
+ ~L3RrcMeasurements ();
+ L3_RRC_Measurements_t *GetPointer ();
+ L3_RRC_Measurements_t GetValue ();
+
+ void AddMeasResultEUTRANeighCells (MeasResultEUTRA_t *measResultItemEUTRA);
+ void AddMeasResultNRNeighCells (MeasResultNR_t *measResultItemNR);
+ void AddServingCellMeasurement (ServingCellMeasurements_t *servingCellMeasurements);
+ void AddNeighbourCellMeasurement (long neighCellId, long sinr);
+
+ static Ptr<L3RrcMeasurements> CreateL3RrcUeSpecificSinrServing (long servingCellId,
+ long physCellId, long sinr);
+
+ static Ptr<L3RrcMeasurements> CreateL3RrcUeSpecificSinrNeigh ();
+
+ // TODO change definition and return the values (to be used for decoding)
+ static void ExtractMeasurementsFromL3RrcMeas (L3_RRC_Measurements_t *l3RrcMeasurements);
+
+ /**
+ * Returns the input SINR on a 0-127 scale
+ *
+ * Refer to 3GPP TS 38.133 V17.2.0(2021-06), Table 10.1.16.1-1: SS-SINR and CSI-SINR measurement report mapping
+ *
+ * @param sinr
+ * @return double
+ */
+ static double ThreeGppMapSinr (double sinr);
+
+private:
+ void addMeasResultNeighCells (MeasResultNeighCells_PR present);
+ L3_RRC_Measurements_t *m_l3RrcMeasurements;
+ MeasResultListEUTRA_t *m_measResultListEUTRA;
+ MeasResultListNR_t *m_measResultListNR;
+ int m_measItemsCounter;
+};
+
+/**
+* Wrapper for class for PM_Info_Item_t
+*/
+class MeasurementItem : public SimpleRefCount<MeasurementItem>
+{
+public:
+ MeasurementItem (std::string name, long value);
+ MeasurementItem (std::string name, double value);
+ MeasurementItem (std::string name, Ptr<L3RrcMeasurements> value);
+ ~MeasurementItem ();
+ PM_Info_Item_t *GetPointer ();
+ PM_Info_Item_t GetValue ();
+
+private:
+ MeasurementItem (std::string name);
+ void CreateMeasurementValue (MeasurementValue_PR measurementValue_PR);
+ // Main struct to be compiled
+ PM_Info_Item_t *m_measurementItem;
+
+ // Accessory structs that we must track to release memory after use
+ MeasurementTypeName_t *m_measName;
+ MeasurementValue_t *m_pmVal;
+ MeasurementType_t *m_pmType;
+};
+
+/**
+* Wrapper for class for RANParameter_Item_t
+*/
+class RANParameterItem : public SimpleRefCount<RANParameterItem>
+{
+public:
+ enum ValueType{ Nothing = 0, Int = 1, OctectString = 2 };
+ RANParameterItem (RANParameter_Item_t *ranParameterItem);
+ ~RANParameterItem ();
+ RANParameter_Item_t *GetPointer ();
+ RANParameter_Item_t GetValue ();
+
+ ValueType m_valueType;
+ long m_valueInt;
+ Ptr<OctetString> m_valueStr;
+
+ static std::vector<RANParameterItem>
+ ExtractRANParametersFromRANParameter (RANParameter_Item_t *ranParameterItem);
+
+private:
+ // Main struct
+ RANParameter_Item_t *m_ranParameterItem;
+ BOOLEAN_t *m_keyFlag;
+};
+
+} // namespace ns3
+#endif /* ASN1C_TYPES_H */
--- /dev/null
+/* -*- 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/function-description.h>
+#include <ns3/asn1c-types.h>
+#include <ns3/log.h>
+
+
+namespace ns3 {
+
+NS_LOG_COMPONENT_DEFINE ("FunctionDescription");
+
+FunctionDescription::FunctionDescription ()
+{
+// E2SM_KPM_RANfunction_Description_t *descriptor = new E2SM_KPM_RANfunction_Description_t ();
+// FillAndEncodeKpmFunctionDescription (descriptor);
+// ASN_STRUCT_FREE_CONTENTS_ONLY (asn_DEF_E2SM_KPM_RANfunction_Description, descriptor);
+// delete descriptor;
+ m_size = 0;
+}
+
+FunctionDescription::~FunctionDescription ()
+{
+ free (m_buffer);
+ m_size = 0;
+}
+
+// TODO improve
+// void
+// FunctionDescription::Encode (E2SM_KPM_RANfunction_Description_t *descriptor)
+// {
+// asn_codec_ctx_t *opt_cod = 0; // disable stack bounds checking
+// // encode the structure into the e2smbuffer
+// asn_encode_to_new_buffer_result_s encodedMsg = asn_encode_to_new_buffer (
+// opt_cod, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2SM_KPM_RANfunction_Description, descriptor);
+
+// if (encodedMsg.result.encoded < 0)
+// {
+// NS_FATAL_ERROR ("Error during the encoding of the RIC Indication Header, errno: "
+// << strerror (errno) << ", failed_type " << encodedMsg.result.failed_type->name
+// << ", structure_ptr " << encodedMsg.result.structure_ptr);
+// }
+
+// m_buffer = encodedMsg.buffer;
+// m_size = encodedMsg.result.encoded;
+// }
+
+} // namespace ns3
--- /dev/null
+/* -*- 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>
+ */
+
+#ifndef FUNCTION_DESCRIPTION_H
+#define FUNCTION_DESCRIPTION_H
+
+#include "ns3/object.h"
+
+// extern "C" {
+// #include "E2SM-KPM-RANfunction-Description.h"
+// #include "E2SM-KPM-IndicationHeader.h"
+// #include "E2SM-KPM-IndicationMessage.h"
+// #include "RAN-Container.h"
+// #include "PF-Container.h"
+// #include "OCUUP-PF-Container.h"
+// #include "PF-ContainerListItem.h"
+// #include "asn1c-types.h"
+// }
+
+namespace ns3 {
+
+ class FunctionDescription : public SimpleRefCount<FunctionDescription>
+ {
+ public:
+ FunctionDescription ();
+ ~FunctionDescription ();
+
+ void* m_buffer;
+ size_t m_size;
+
+ // TODO improve the abstraction
+// private:
+// virtual void Encode (E2SM_KPM_RANfunction_Description_t* descriptor);
+ };
+
+}
+
+#endif /* FUNCTION_DESCRIPTION_H */
--- /dev/null
+/* -*- 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/kpm-function-description.h>
+#include <ns3/asn1c-types.h>
+#include <ns3/log.h>
+
+extern "C" {
+#include "RIC-EventTriggerStyle-Item.h"
+#include "RIC-ReportStyle-Item.h"
+}
+
+namespace ns3 {
+
+NS_LOG_COMPONENT_DEFINE ("KpmFunctionDescription");
+
+KpmFunctionDescription::KpmFunctionDescription ()
+{
+ E2SM_KPM_RANfunction_Description_t *descriptor = new E2SM_KPM_RANfunction_Description_t ();
+ FillAndEncodeKpmFunctionDescription (descriptor);
+ ASN_STRUCT_FREE_CONTENTS_ONLY (asn_DEF_E2SM_KPM_RANfunction_Description, descriptor);
+ delete descriptor;
+}
+
+KpmFunctionDescription::~KpmFunctionDescription ()
+{
+ free (m_buffer);
+ m_size = 0;
+}
+
+void
+KpmFunctionDescription::Encode (E2SM_KPM_RANfunction_Description_t *descriptor)
+{
+ asn_codec_ctx_t *opt_cod = 0; // disable stack bounds checking
+ // encode the structure into the e2smbuffer
+ asn_encode_to_new_buffer_result_s encodedMsg = asn_encode_to_new_buffer (
+ opt_cod, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2SM_KPM_RANfunction_Description, descriptor);
+
+ if (encodedMsg.result.encoded < 0)
+ {
+ NS_FATAL_ERROR ("Error during the encoding of the RIC Indication Header, errno: "
+ << strerror (errno) << ", failed_type " << encodedMsg.result.failed_type->name
+ << ", structure_ptr " << encodedMsg.result.structure_ptr);
+ }
+
+ m_buffer = encodedMsg.buffer;
+ m_size = encodedMsg.result.encoded;
+}
+
+void
+KpmFunctionDescription::FillAndEncodeKpmFunctionDescription (
+ E2SM_KPM_RANfunction_Description_t *ranfunc_desc)
+{
+ std::string shortNameBuffer = "ORAN-WG3-KPM";
+ uint8_t *descriptionBuffer = (uint8_t *) "KPM monitor";
+ uint8_t *oidBuffer = (uint8_t *) "OID123"; // this is optional, dummy value
+
+ Ptr<OctetString> shortName = Create<OctetString> (shortNameBuffer, shortNameBuffer.size ());
+
+ ranfunc_desc->ranFunction_Name.ranFunction_ShortName = shortName->GetValue ();
+
+ long *inst = (long *) calloc (1, sizeof (long));
+
+ // ranfunc_desc->ranFunction_Name.ranFunction_Description = (OCTET_STRING_t*)calloc(1, sizeof(OCTET_STRING_t));
+ ranfunc_desc->ranFunction_Name.ranFunction_Description.buf =
+ (uint8_t *) calloc (1, strlen ((char *) descriptionBuffer));
+ memcpy (ranfunc_desc->ranFunction_Name.ranFunction_Description.buf, descriptionBuffer,
+ strlen ((char *) descriptionBuffer));
+ ranfunc_desc->ranFunction_Name.ranFunction_Description.size = strlen ((char *) descriptionBuffer);
+ ranfunc_desc->ranFunction_Name.ranFunction_Instance = inst;
+
+ // ranfunc_desc->ranFunction_Name.ranFunction_E2SM_OID = (OCTET_STRING_t*)calloc(1, sizeof(OCTET_STRING_t));
+ ranfunc_desc->ranFunction_Name.ranFunction_E2SM_OID.buf =
+ (uint8_t *) calloc (1, strlen ((char *) oidBuffer));
+ memcpy (ranfunc_desc->ranFunction_Name.ranFunction_E2SM_OID.buf, oidBuffer,
+ strlen ((char *) oidBuffer));
+ ranfunc_desc->ranFunction_Name.ranFunction_E2SM_OID.size = strlen ((char *) oidBuffer);
+
+ RIC_EventTriggerStyle_Item_t *trigger_style =
+ (RIC_EventTriggerStyle_Item_t *) calloc (1, sizeof (RIC_EventTriggerStyle_Item_t));
+ trigger_style->ric_EventTriggerStyle_Type = 1;
+ uint8_t *eventTriggerStyleNameBuffer = (uint8_t *) "Periodic report";
+ // trigger_style->ric_EventTriggerStyle_Name = (OCTET_STRING_t*)calloc(1, sizeof(OCTET_STRING_t));
+ trigger_style->ric_EventTriggerStyle_Name.buf =
+ (uint8_t *) calloc (1, strlen ((char *) eventTriggerStyleNameBuffer));
+ memcpy (trigger_style->ric_EventTriggerStyle_Name.buf, eventTriggerStyleNameBuffer,
+ strlen ((char *) eventTriggerStyleNameBuffer));
+ trigger_style->ric_EventTriggerStyle_Name.size = strlen ((char *) eventTriggerStyleNameBuffer);
+ trigger_style->ric_EventTriggerFormat_Type = 1;
+
+ ranfunc_desc->ric_EventTriggerStyle_List =
+ (E2SM_KPM_RANfunction_Description::
+ E2SM_KPM_RANfunction_Description__ric_EventTriggerStyle_List *)
+ calloc (1, sizeof (E2SM_KPM_RANfunction_Description::
+ E2SM_KPM_RANfunction_Description__ric_EventTriggerStyle_List));
+
+ ASN_SEQUENCE_ADD (&ranfunc_desc->ric_EventTriggerStyle_List->list, trigger_style);
+
+ RIC_ReportStyle_Item_t *report_style1 =
+ (RIC_ReportStyle_Item_t *) calloc (1, sizeof (RIC_ReportStyle_Item_t));
+ report_style1->ric_ReportStyle_Type = 1;
+
+ uint8_t *reportStyleNameBuffer =
+ (uint8_t *) "O-CU-CP Measurement Container for the EPC connected deployment";
+
+ // report_style1->ric_ReportStyle_Name = (OCTET_STRING_t*)calloc(1, sizeof(OCTET_STRING_t));
+ report_style1->ric_ReportStyle_Name.buf =
+ (uint8_t *) calloc (1, strlen ((char *) reportStyleNameBuffer));
+ memcpy (report_style1->ric_ReportStyle_Name.buf, reportStyleNameBuffer,
+ strlen ((char *) reportStyleNameBuffer));
+ report_style1->ric_ReportStyle_Name.size = strlen ((char *) reportStyleNameBuffer);
+ report_style1->ric_ReportIndicationHeaderFormat_Type = 1;
+ report_style1->ric_ReportIndicationMessageFormat_Type = 1;
+ ranfunc_desc->ric_ReportStyle_List =
+ (E2SM_KPM_RANfunction_Description::E2SM_KPM_RANfunction_Description__ric_ReportStyle_List *)
+ calloc (1, sizeof (E2SM_KPM_RANfunction_Description::
+ E2SM_KPM_RANfunction_Description__ric_ReportStyle_List));
+
+ ASN_SEQUENCE_ADD (&ranfunc_desc->ric_ReportStyle_List->list, report_style1);
+
+ Encode (ranfunc_desc);
+
+ NS_LOG_INFO (xer_fprint (stderr, &asn_DEF_E2SM_KPM_RANfunction_Description, ranfunc_desc));
+}
+
+} // namespace ns3
--- /dev/null
+/* -*- 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>
+ */
+
+#ifndef KPM_FUNCTION_DESCRIPTION_H
+#define KPM_FUNCTION_DESCRIPTION_H
+
+#include "ns3/object.h"
+#include <ns3/function-description.h>
+
+extern "C" {
+ #include "E2SM-KPM-RANfunction-Description.h"
+ #include "E2SM-KPM-IndicationHeader.h"
+ #include "E2SM-KPM-IndicationMessage.h"
+ #include "RAN-Container.h"
+ #include "PF-Container.h"
+ #include "OCUUP-PF-Container.h"
+ #include "PF-ContainerListItem.h"
+ #include "asn1c-types.h"
+}
+
+namespace ns3 {
+
+ class KpmFunctionDescription : public FunctionDescription
+ {
+ public:
+ KpmFunctionDescription ();
+ ~KpmFunctionDescription ();
+
+ private:
+ /**
+ * Encodes the RAN Function Description item for the KPM Service Model.
+ *
+ * \param kpmFunctionDescription the RAN Function Description item
+ */
+ void FillAndEncodeKpmFunctionDescription (E2SM_KPM_RANfunction_Description_t* descriptor);
+ void Encode (E2SM_KPM_RANfunction_Description_t* descriptor);
+ };
+
+}
+
+#endif /* KPM_FUNCTION_DESCRIPTION_H */
--- /dev/null
+/* -*- 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/kpm-indication.h>
+#include <ns3/asn1c-types.h>
+#include <ns3/log.h>
+
+extern "C" {
+#include "E2SM-KPM-IndicationHeader-Format1.h"
+#include "E2SM-KPM-IndicationMessage-Format1.h"
+#include "GlobalE2node-ID.h"
+#include "GlobalE2node-gNB-ID.h"
+#include "GlobalE2node-eNB-ID.h"
+#include "GlobalE2node-ng-eNB-ID.h"
+#include "GlobalE2node-en-gNB-ID.h"
+#include "NRCGI.h"
+#include "PM-Containers-Item.h"
+#include "RIC-EventTriggerStyle-Item.h"
+#include "RIC-ReportStyle-Item.h"
+#include "TimeStamp.h"
+#include "CUUPMeasurement-Container.h"
+#include "PlmnID-Item.h"
+#include "EPC-CUUP-PM-Format.h"
+#include "PerQCIReportListItemFormat.h"
+#include "PerUE-PM-Item.h"
+#include "PM-Info-Item.h"
+#include "MeasurementInfoList.h"
+#include "CellObjectID.h"
+#include "CellResourceReportListItem.h"
+#include "ServedPlmnPerCellListItem.h"
+#include "EPC-DU-PM-Container.h"
+#include "PerQCIReportListItem.h"
+}
+
+namespace ns3 {
+
+NS_LOG_COMPONENT_DEFINE ("KpmIndication");
+
+KpmIndicationHeader::KpmIndicationHeader (GlobalE2nodeType nodeType,KpmRicIndicationHeaderValues values)
+{
+ m_nodeType = nodeType;
+ E2SM_KPM_IndicationHeader_t *descriptor = new E2SM_KPM_IndicationHeader_t;
+ FillAndEncodeKpmRicIndicationHeader (descriptor, values);
+ delete descriptor;
+}
+
+KpmIndicationHeader::~KpmIndicationHeader ()
+{
+ NS_LOG_FUNCTION (this);
+ free (m_buffer);
+ m_size = 0;
+}
+
+void
+KpmIndicationHeader::Encode (E2SM_KPM_IndicationHeader_t *descriptor)
+{
+ asn_codec_ctx_t *opt_cod = 0; // disable stack bounds checking
+ asn_encode_to_new_buffer_result_s encodedHeader = asn_encode_to_new_buffer (
+ opt_cod, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2SM_KPM_IndicationHeader, descriptor);
+
+ if (encodedHeader.result.encoded < 0)
+ {
+ NS_FATAL_ERROR ("Error during the encoding of the RIC Indication Header, errno: "
+ << strerror (errno) << ", failed_type "
+ << encodedHeader.result.failed_type->name << ", structure_ptr "
+ << encodedHeader.result.structure_ptr);
+ }
+
+ m_buffer = encodedHeader.buffer;
+ m_size = encodedHeader.result.encoded;
+}
+
+void
+KpmIndicationHeader::FillAndEncodeKpmRicIndicationHeader (E2SM_KPM_IndicationHeader_t *descriptor,
+ KpmRicIndicationHeaderValues values)
+{
+
+ E2SM_KPM_IndicationHeader_Format1_t *ind_header = (E2SM_KPM_IndicationHeader_Format1_t *) calloc (
+ 1, sizeof (E2SM_KPM_IndicationHeader_Format1_t));
+
+ Ptr<OctetString> plmnid = Create<OctetString> (values.m_plmId, 3);
+ Ptr<BitString> cellId_bstring;
+
+ GlobalE2node_ID *globalE2nodeIdBuf = (GlobalE2node_ID *) calloc (1, sizeof (GlobalE2node_ID));
+ ind_header->id_GlobalE2node_ID = *globalE2nodeIdBuf;
+
+ switch (m_nodeType)
+ {
+ case gNB: {
+ static int sizeGnb = 4; // 3GPP Specs
+
+ cellId_bstring = Create<BitString> (values.m_gnbId, sizeGnb);
+
+ ind_header->id_GlobalE2node_ID.present = GlobalE2node_ID_PR_gNB;
+ GlobalE2node_gNB_ID_t *globalE2node_gNB_ID =
+ (GlobalE2node_gNB_ID_t *) calloc (1, sizeof (GlobalE2node_gNB_ID_t));
+ globalE2node_gNB_ID->global_gNB_ID.plmn_id = plmnid->GetValue ();
+ globalE2node_gNB_ID->global_gNB_ID.gnb_id.present = GNB_ID_Choice_PR_gnb_ID;
+ globalE2node_gNB_ID->global_gNB_ID.gnb_id.choice.gnb_ID = cellId_bstring->GetValue ();
+ ind_header->id_GlobalE2node_ID.choice.gNB = globalE2node_gNB_ID;
+ }
+ break;
+
+ case eNB: {
+ static int sizeEnb =
+ 3; // 3GPP TS 36.413 version 14.8.0 Release 14, Section 9.2.1.37 Global eNB ID
+ static int unsedSizeEnb = 4;
+
+ cellId_bstring = Create<BitString> (values.m_gnbId, sizeEnb, unsedSizeEnb);
+
+ ind_header->id_GlobalE2node_ID.present = GlobalE2node_ID_PR_eNB;
+ GlobalE2node_eNB_ID_t *globalE2node_eNB_ID =
+ (GlobalE2node_eNB_ID_t *) calloc (1, sizeof (GlobalE2node_eNB_ID_t));
+ globalE2node_eNB_ID->global_eNB_ID.pLMN_Identity = plmnid->GetValue ();
+ globalE2node_eNB_ID->global_eNB_ID.eNB_ID.present = ENB_ID_PR_macro_eNB_ID;
+ globalE2node_eNB_ID->global_eNB_ID.eNB_ID.choice.macro_eNB_ID = cellId_bstring->GetValue ();
+ ind_header->id_GlobalE2node_ID.choice.eNB = globalE2node_eNB_ID;
+ }
+ break;
+
+ case ng_eNB: {
+ static int sizeEnb =
+ 3; // 3GPP TS 36.413 version 14.8.0 Release 14, Section 9.2.1.37 Global eNB ID
+ static int unsedSizeEnb = 4;
+
+ cellId_bstring = Create<BitString> (values.m_gnbId, sizeEnb, unsedSizeEnb);
+
+ ind_header->id_GlobalE2node_ID.present = GlobalE2node_ID_PR_ng_eNB;
+ GlobalE2node_ng_eNB_ID_t *globalE2node_ng_eNB_ID =
+ (GlobalE2node_ng_eNB_ID_t *) calloc (1, sizeof (GlobalE2node_ng_eNB_ID_t));
+
+ globalE2node_ng_eNB_ID->global_ng_eNB_ID.plmn_id = plmnid->GetValue ();
+ globalE2node_ng_eNB_ID->global_ng_eNB_ID.enb_id.present = ENB_ID_Choice_PR_enb_ID_macro;
+ globalE2node_ng_eNB_ID->global_ng_eNB_ID.enb_id.choice.enb_ID_macro =
+ cellId_bstring->GetValue ();
+ ind_header->id_GlobalE2node_ID.choice.ng_eNB = globalE2node_ng_eNB_ID;
+ }
+ break;
+
+ case en_gNB: {
+ static int sizeGnb = 4; // 3GPP Specs
+ cellId_bstring = Create<BitString> (values.m_gnbId, sizeGnb);
+
+ ind_header->id_GlobalE2node_ID.present = GlobalE2node_ID_PR_en_gNB;
+ GlobalE2node_en_gNB_ID_t *globalE2node_en_gNB_ID =
+ (GlobalE2node_en_gNB_ID_t *) calloc (1, sizeof (GlobalE2node_en_gNB_ID_t));
+ globalE2node_en_gNB_ID->global_gNB_ID.pLMN_Identity = plmnid->GetValue ();
+ globalE2node_en_gNB_ID->global_gNB_ID.gNB_ID.present = ENGNB_ID_PR_gNB_ID;
+ globalE2node_en_gNB_ID->global_gNB_ID.gNB_ID.choice.gNB_ID = cellId_bstring->GetValue ();
+ ind_header->id_GlobalE2node_ID.choice.en_gNB = globalE2node_en_gNB_ID;
+ }
+ break;
+
+ default:
+ NS_FATAL_ERROR (
+ "Unrecognized node type for KpmRicIndicationHeader, value passed: " << m_nodeType);
+ break;
+ }
+
+ NS_LOG_DEBUG ("Timestamp received: " << values.m_timestamp);
+ long bigEndianTimestamp = htobe64 (values.m_timestamp);
+ NS_LOG_DEBUG ("Timestamp inverted: " << bigEndianTimestamp);
+
+ Ptr<OctetString> ts = Create<OctetString> ((void *) &bigEndianTimestamp, TIMESTAMP_LIMIT_SIZE);
+ //NS_LOG_INFO (xer_fprint (stderr, &asn_DEF_OCTET_STRING, ts->GetPointer() ));
+
+ // Ptr<OctetString> ts2 = Create<OctetString> ((void *) &values.m_timestamp, TIMESTAMP_LIMIT_SIZE);
+ // NS_LOG_INFO (xer_fprint (stderr, &asn_DEF_OCTET_STRING, ts2->GetPointer()));
+
+ ind_header->collectionStartTime = ts->GetValue ();
+
+
+ NS_LOG_INFO (xer_fprint (stderr, &asn_DEF_E2SM_KPM_IndicationHeader_Format1, ind_header));
+
+ descriptor->present = E2SM_KPM_IndicationHeader_PR_indicationHeader_Format1;
+ descriptor->choice.indicationHeader_Format1 = ind_header;
+
+ Encode (descriptor);
+ ASN_STRUCT_FREE (asn_DEF_E2SM_KPM_IndicationHeader_Format1, ind_header);
+ free (globalE2nodeIdBuf);
+ // TraceMessage (&asn_DEF_E2SM_KPM_IndicationHeader, header, "RIC Indication Header");
+}
+
+KpmIndicationMessage::KpmIndicationMessage (KpmIndicationMessageValues values)
+{
+ E2SM_KPM_IndicationMessage_t *descriptor = new E2SM_KPM_IndicationMessage_t ();
+ CheckConstraints (values);
+ FillAndEncodeKpmIndicationMessage (descriptor, values);
+ delete descriptor;
+}
+
+KpmIndicationMessage::~KpmIndicationMessage ()
+{
+ free (m_buffer);
+ m_size = 0;
+}
+
+void
+KpmIndicationMessage::CheckConstraints (KpmIndicationMessageValues values)
+{
+ // TODO remove?
+ // if (values.m_crnti.length () != 2)
+ // {
+ // NS_FATAL_ERROR ("C-RNTI should have length 2");
+ // }
+ // if (values.m_plmId.length () != 3)
+ // {
+ // NS_FATAL_ERROR ("PLMID should have length 3");
+ // }
+ // if (values.m_nrCellId.length () != 5)
+ // {
+ // NS_FATAL_ERROR ("NR Cell ID should have length 5");
+ // }
+ // TODO add other constraints
+}
+
+void
+KpmIndicationMessage::Encode (E2SM_KPM_IndicationMessage_t *descriptor)
+{
+ asn_codec_ctx_t *opt_cod = 0; // disable stack bounds checking
+ asn_encode_to_new_buffer_result_s encodedMsg = asn_encode_to_new_buffer (
+ opt_cod, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2SM_KPM_IndicationMessage, descriptor);
+
+ if (encodedMsg.result.encoded < 0)
+ {
+ NS_FATAL_ERROR ("Error during the encoding of the RIC Indication Message, errno: "
+ << strerror (errno) << ", failed_type " << encodedMsg.result.failed_type->name
+ << ", structure_ptr " << encodedMsg.result.structure_ptr);
+ }
+
+ m_buffer = encodedMsg.buffer;
+ m_size = encodedMsg.result.encoded;
+}
+
+void
+KpmIndicationMessage::FillPmContainer (PF_Container_t *ranContainer, Ptr<PmContainerValues> values)
+{
+ Ptr<OCuUpContainerValues> cuUpVal = DynamicCast<OCuUpContainerValues> (values);
+ Ptr<OCuCpContainerValues> cuCpVal = DynamicCast<OCuCpContainerValues> (values);
+ Ptr<ODuContainerValues> duVal = DynamicCast<ODuContainerValues> (values);
+
+ if (cuUpVal)
+ {
+ FillOCuUpContainer (ranContainer, cuUpVal);
+ }
+ else if (cuCpVal)
+ {
+ FillOCuCpContainer (ranContainer, cuCpVal);
+ }
+ else if (duVal)
+ {
+ FillODuContainer (ranContainer, duVal);
+ }
+ else
+ {
+ NS_FATAL_ERROR ("Unknown PM Container type");
+ }
+}
+
+void
+KpmIndicationMessage::FillOCuUpContainer (PF_Container_t *ranContainer,
+ Ptr<OCuUpContainerValues> values)
+{
+ OCUUP_PF_Container_t* ocuup = (OCUUP_PF_Container_t*) calloc (1, sizeof (OCUUP_PF_Container_t));
+ PF_ContainerListItem_t* pcli = (PF_ContainerListItem_t*) calloc (1, sizeof (PF_ContainerListItem_t));
+ pcli->interface_type = NI_Type_x2_u;
+
+ CUUPMeasurement_Container_t* cuuppmc = (CUUPMeasurement_Container_t*) calloc (1, sizeof (CUUPMeasurement_Container_t));
+ PlmnID_Item_t* plmnItem = (PlmnID_Item_t*) calloc (1, sizeof (PlmnID_Item_t));
+ Ptr<OctetString> plmnidstr = Create<OctetString> (values->m_plmId, 3);
+ plmnItem->pLMN_Identity = plmnidstr->GetValue ();
+
+ EPC_CUUP_PM_Format_t* cuuppmf = (EPC_CUUP_PM_Format_t*) calloc (1, sizeof (EPC_CUUP_PM_Format_t));
+ plmnItem->cu_UP_PM_EPC = cuuppmf;
+ PerQCIReportListItemFormat_t* pqrli = (PerQCIReportListItemFormat_t*) calloc (1, sizeof (PerQCIReportListItemFormat_t));
+ pqrli->drbqci = 0;
+
+ INTEGER_t *pDCPBytesDL = (INTEGER_t *) calloc (1, sizeof (INTEGER_t));
+ INTEGER_t *pDCPBytesUL = (INTEGER_t *) calloc (1, sizeof (INTEGER_t));
+
+ asn_long2INTEGER (pDCPBytesDL, values->m_pDCPBytesDL);
+ asn_long2INTEGER (pDCPBytesUL, values->m_pDCPBytesUL);
+
+ pqrli->pDCPBytesDL = pDCPBytesDL;
+ pqrli->pDCPBytesUL = pDCPBytesUL;
+
+ ASN_SEQUENCE_ADD (&cuuppmf->perQCIReportList_cuup.list, pqrli);
+
+ ASN_SEQUENCE_ADD (&cuuppmc->plmnList.list, plmnItem);
+
+ pcli->o_CU_UP_PM_Container = *cuuppmc;
+ ASN_SEQUENCE_ADD (&ocuup->pf_ContainerList, pcli);
+ ranContainer->choice.oCU_UP = ocuup;
+ ranContainer->present = PF_Container_PR_oCU_UP;
+
+ free (cuuppmc);
+}
+
+void
+KpmIndicationMessage::FillOCuCpContainer (PF_Container_t *ranContainer,
+ Ptr<OCuCpContainerValues> values)
+{
+ OCUCP_PF_Container_t *ocucp = (OCUCP_PF_Container_t *) calloc (1, sizeof(OCUCP_PF_Container_t));
+ long *numActiveUes = (long *) calloc (1, sizeof (long));
+ *numActiveUes = long(values->m_numActiveUes);
+ ocucp->cu_CP_Resource_Status.numberOfActive_UEs = numActiveUes;
+ ranContainer->choice.oCU_CP = ocucp;
+ ranContainer->present = PF_Container_PR_oCU_CP;
+}
+
+void
+KpmIndicationMessage::FillODuContainer (PF_Container_t *ranContainer,
+ Ptr<ODuContainerValues> values)
+{
+ ODU_PF_Container_t *odu = (ODU_PF_Container_t *) calloc (1, sizeof (ODU_PF_Container_t));
+
+ for (auto cellReport : values->m_cellResourceReportItems)
+ {
+ NS_LOG_LOGIC ("O-DU: Add Cell Resource Report Item");
+ CellResourceReportListItem_t *crrli =
+ (CellResourceReportListItem_t *) calloc (1, sizeof (CellResourceReportListItem_t));
+
+ Ptr<OctetString> plmnid = Create<OctetString> (cellReport->m_plmId, 3);
+ Ptr<NrCellId> nrcellid = Create<NrCellId> (cellReport->m_nrCellId);
+ crrli->nRCGI.pLMN_Identity = plmnid->GetValue ();
+ crrli->nRCGI.nRCellIdentity = nrcellid->GetValue ();
+
+ long *dlAvailablePrbs = (long *) calloc (1, sizeof (long));
+ *dlAvailablePrbs = cellReport->dlAvailablePrbs;
+ crrli->dl_TotalofAvailablePRBs = dlAvailablePrbs;
+
+ long *ulAvailablePrbs = (long *) calloc (1, sizeof (long));
+ *ulAvailablePrbs = cellReport->ulAvailablePrbs;
+ crrli->ul_TotalofAvailablePRBs = ulAvailablePrbs;
+ ASN_SEQUENCE_ADD (&odu->cellResourceReportList.list, crrli);
+
+ for (auto servedPlmnCell : cellReport->m_servedPlmnPerCellItems)
+ {
+ NS_LOG_LOGIC ("O-DU: Add Served Plmn Per Cell Item");
+ ServedPlmnPerCellListItem_t *sppcl =
+ (ServedPlmnPerCellListItem_t *) calloc (1, sizeof (ServedPlmnPerCellListItem_t));
+ Ptr<OctetString> servedPlmnId = Create<OctetString> (servedPlmnCell->m_plmId, 3);
+ sppcl->pLMN_Identity = servedPlmnId->GetValue ();
+
+ EPC_DU_PM_Container_t *edpc =
+ (EPC_DU_PM_Container_t *) calloc (1, sizeof (EPC_DU_PM_Container_t));
+
+ for (auto perQciReportItem : servedPlmnCell->m_perQciReportItems)
+ {
+ NS_LOG_LOGIC ("O-DU: Add Per QCI Report Item");
+ PerQCIReportListItem_t *pqrl =
+ (PerQCIReportListItem_t *) calloc (1, sizeof (PerQCIReportListItem_t));
+ pqrl->qci = perQciReportItem->m_qci;
+
+ NS_ABORT_MSG_IF ((perQciReportItem->m_dlPrbUsage < 0) | (perQciReportItem->m_dlPrbUsage > 100),
+ "As per ASN definition, dl_PRBUsage should be between 0 and 100");
+ long *dlUsedPrbs = (long *) calloc (1, sizeof (long));
+ *dlUsedPrbs = perQciReportItem->m_dlPrbUsage;
+ pqrl->dl_PRBUsage = dlUsedPrbs;
+ NS_LOG_LOGIC ("DL PRBs " << dlUsedPrbs);
+
+ NS_ABORT_MSG_IF ((perQciReportItem->m_ulPrbUsage < 0) | (perQciReportItem->m_ulPrbUsage > 100),
+ "As per ASN definition, ul_PRBUsage should be between 0 and 100");
+ long *ulUsedPrbs = (long *) calloc (1, sizeof (long));
+ *ulUsedPrbs = perQciReportItem->m_ulPrbUsage;
+ pqrl->ul_PRBUsage = ulUsedPrbs;
+ ASN_SEQUENCE_ADD (&edpc->perQCIReportList_du.list, pqrl);
+ }
+
+ sppcl->du_PM_EPC = edpc;
+ ASN_SEQUENCE_ADD (&crrli->servedPlmnPerCellList.list, sppcl);
+ }
+ }
+ ranContainer->choice.oDU = odu;
+ ranContainer->present = PF_Container_PR_oDU;
+}
+
+void
+KpmIndicationMessage::FillAndEncodeKpmIndicationMessage (E2SM_KPM_IndicationMessage_t *descriptor,
+ KpmIndicationMessageValues values)
+{
+ // Create and fill the RAN Container
+ PF_Container_t *ranContainer = (PF_Container_t *) calloc (1, sizeof (PF_Container_t));
+ FillPmContainer (ranContainer, values.m_pmContainerValues);
+
+ //------- now fill the message
+ PM_Containers_Item_t *containers_list =
+ (PM_Containers_Item_t *) calloc (1, sizeof (PM_Containers_Item_t));
+ containers_list->performanceContainer = ranContainer;
+
+ E2SM_KPM_IndicationMessage_Format1_t *format = (E2SM_KPM_IndicationMessage_Format1_t *) calloc (
+ 1, sizeof (E2SM_KPM_IndicationMessage_Format1_t));
+
+ ASN_SEQUENCE_ADD (&format->pm_Containers.list, containers_list);
+
+ // Cell Object ID
+ CellObjectID_t *cellObjectID = (CellObjectID_t *) calloc (1, sizeof (CellObjectID_t));
+ cellObjectID->size = values.m_cellObjectId.length ();
+ cellObjectID->buf = (uint8_t *) calloc (1, cellObjectID->size);
+ memcpy (cellObjectID->buf, values.m_cellObjectId.c_str (), values.m_cellObjectId.length ());
+ format->cellObjectID = *cellObjectID;
+
+ // Measurement Information List
+ if (values.m_cellMeasurementItems)
+ {
+ format->list_of_PM_Information = (E2SM_KPM_IndicationMessage_Format1::
+ E2SM_KPM_IndicationMessage_Format1__list_of_PM_Information *)
+ calloc (1, sizeof (E2SM_KPM_IndicationMessage_Format1::
+ E2SM_KPM_IndicationMessage_Format1__list_of_PM_Information));
+ for (auto item : values.m_cellMeasurementItems->GetItems ())
+ {
+ ASN_SEQUENCE_ADD (&format->list_of_PM_Information->list, item->GetPointer ());
+ }
+ }
+
+ // List of matched UEs
+ if (values.m_ueIndications.size () > 0)
+ {
+ format->list_of_matched_UEs = (E2SM_KPM_IndicationMessage_Format1_t::E2SM_KPM_IndicationMessage_Format1__list_of_matched_UEs*)
+ calloc (1, sizeof (E2SM_KPM_IndicationMessage_Format1_t::E2SM_KPM_IndicationMessage_Format1__list_of_matched_UEs));
+
+
+ for (auto ueIndication : values.m_ueIndications)
+ {
+ PerUE_PM_Item_t *perUEItem = (PerUE_PM_Item_t *) calloc (1, sizeof (PerUE_PM_Item_t));
+
+ // UE Identity
+ perUEItem->ueId = ueIndication->GetId ();
+ // xer_fprint (stderr, &asn_DEF_UE_Identity, &perUEItem->ueId);
+ // NS_LOG_UNCOND ("Values " << ueIndication->m_drbIPLateDlUEID);
+
+ // List of Measurements PM information
+ perUEItem->list_of_PM_Information =
+ (PerUE_PM_Item::PerUE_PM_Item__list_of_PM_Information *) calloc (
+ 1, sizeof (PerUE_PM_Item::PerUE_PM_Item__list_of_PM_Information));
+
+ for (auto measurementItem : ueIndication->GetItems ())
+ {
+ ASN_SEQUENCE_ADD (&perUEItem->list_of_PM_Information->list,
+ measurementItem->GetPointer ());
+ }
+ ASN_SEQUENCE_ADD (&format->list_of_matched_UEs->list, perUEItem);
+ }
+ }
+
+ descriptor->present = E2SM_KPM_IndicationMessage_PR_indicationMessage_Format1;
+ descriptor->choice.indicationMessage_Format1 = format;
+
+
+ NS_LOG_INFO (xer_fprint (stderr, &asn_DEF_E2SM_KPM_IndicationMessage_Format1, format));
+
+ // xer_fprint (stderr, &asn_DEF_PF_Container, ranContainer);
+ Encode (descriptor);
+
+ free (cellObjectID);
+ // free (ranContainer);
+ ASN_STRUCT_FREE (asn_DEF_E2SM_KPM_IndicationMessage_Format1, format);
+}
+
+MeasurementItemList::MeasurementItemList ()
+{
+ m_id = NULL;
+}
+
+MeasurementItemList::MeasurementItemList (std::string id)
+{
+ m_id = Create<OctetString> (id, id.length ());
+}
+
+MeasurementItemList::~MeasurementItemList (){};
+
+std::vector<Ptr<MeasurementItem>>
+MeasurementItemList::GetItems ()
+{
+ return m_items;
+}
+
+OCTET_STRING_t
+MeasurementItemList::GetId ()
+{
+ NS_ABORT_IF (m_id == NULL);
+ return m_id->GetValue ();
+}
+
+} // namespace ns3
--- /dev/null
+/* -*- 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>
+ */
+
+#ifndef KPM_INDICATION_H
+#define KPM_INDICATION_H
+
+#include "ns3/object.h"
+#include <set>
+
+extern "C" {
+ #include "E2SM-KPM-RANfunction-Description.h"
+ #include "E2SM-KPM-IndicationHeader.h"
+ #include "E2SM-KPM-IndicationMessage.h"
+ #include "RAN-Container.h"
+ #include "PF-Container.h"
+ #include "OCUUP-PF-Container.h"
+ #include "OCUCP-PF-Container.h"
+ #include "ODU-PF-Container.h"
+ #include "PF-ContainerListItem.h"
+ #include "asn1c-types.h"
+}
+
+namespace ns3 {
+
+ class KpmIndicationHeader : public SimpleRefCount<KpmIndicationHeader>
+ {
+ public:
+ enum GlobalE2nodeType { gNB = 0, eNB = 1, ng_eNB = 2, en_gNB = 3 };
+
+ const static int TIMESTAMP_LIMIT_SIZE = 8;
+ /**
+ * Holds the values to be used to fill the RIC Indication header
+ */
+ struct KpmRicIndicationHeaderValues
+ {
+ // E2SM-KPM Indication Header Format 1
+ // KPM Node ID IE
+ std::string m_gnbId; //!< gNB ID bit string
+ // TODO not supported
+ // uint64_t m_cuUpId; //!< gNB-CU-UP ID, integer [0, 2^36-1], optional
+
+ // Cell Global ID (NR CGI) IE
+ uint16_t m_nrCellId; //!< NR, bit string
+
+ // PLMN ID IE
+ std::string m_plmId; //!< PLMN identity, octet string, 3 bytes
+
+ // Slice ID (S-NSSAI) IE // TODO not supported
+ // std::string m_sst; //!< SNSSAI sST, 1 byte
+ // std::string m_sd; //!< SNSSAI sD, 3 bytes, optional
+
+ // FiveQI IE // TODO not supported
+ // uint8_t m_fiveqi; //!< fiveQI, integer [0, 255], optional
+
+ // QCI IE // TODO not supported
+ // long m_qci; //!< QCI, integer [0, 255], optional
+
+ // TODO this value is placed in a fiels which seems not to be defined
+ // in the specs. See line 301 in encode_kpm.cpp
+ // the field is called gNB_DU_ID
+ // it should be part of KPM Node ID IE
+ // m_duId
+
+ // TODO this value is placed in a fiels which seems not to be defined
+ // in the specs. See line 290 in encode_kpm.cpp, the field is called
+ // gNB_Name
+ // m_cuUpName
+
+ // CollectionTimeStamp
+ uint64_t m_timestamp;
+ };
+
+ KpmIndicationHeader (GlobalE2nodeType nodeType,KpmRicIndicationHeaderValues values);
+ ~KpmIndicationHeader ();
+ void* m_buffer;
+ size_t m_size;
+
+ private:
+ /**
+ * Fills the KPM INDICATION Header descriptor
+ * This function fills the RIC Indication Header with the provided
+ * values
+ *
+ * \param descriptor object representing the KPM INDICATION Header
+ * \param values struct holding the values to be used to fill the header
+ */
+ void FillAndEncodeKpmRicIndicationHeader (E2SM_KPM_IndicationHeader_t* descriptor,
+ KpmRicIndicationHeaderValues values);
+
+ void Encode (E2SM_KPM_IndicationHeader_t* descriptor);
+
+ GlobalE2nodeType m_nodeType;
+ };
+
+ class MeasurementItemList : public SimpleRefCount<MeasurementItemList>
+ {
+ private:
+ Ptr<OctetString> m_id; // ID, contains the UE IMSI if used to carry UE-specific measurement items
+ std::vector<Ptr<MeasurementItem>> m_items; //!< list of Measurement Information Items
+ public:
+ MeasurementItemList ();
+ MeasurementItemList (std::string ueId);
+ ~MeasurementItemList ();
+
+ // NOTE defined here to avoid undefined references
+ template<class T>
+ void AddItem (std::string name, T value)
+ {
+ Ptr<MeasurementItem> item = Create<MeasurementItem> (name, value);
+ m_items.push_back (item);
+ }
+
+ std::vector<Ptr<MeasurementItem>> GetItems();
+ OCTET_STRING_t GetId ();
+ };
+
+ /**
+ * Base class to carry PM Container values
+ */
+ class PmContainerValues : public SimpleRefCount<PmContainerValues>
+ {
+ public:
+ virtual ~PmContainerValues () = default;
+ };
+
+ /**
+ * Contains the values to be inserted in the O-CU-CP Measurement Container
+ */
+ class OCuCpContainerValues : public PmContainerValues
+ {
+ public:
+ uint16_t m_numActiveUes; //!< mean number of RRC connections
+ };
+
+ /**
+ * Contains the values to be inserted in the O-CU-UP Measurement Container
+ */
+ class OCuUpContainerValues : public PmContainerValues
+ {
+ public:
+ std::string m_plmId; //!< PLMN identity, octet string, 3 bytes
+ long m_pDCPBytesUL; //!< total PDCP bytes transmitted UL
+ long m_pDCPBytesDL; //!< total PDCP bytes transmitted DL
+ };
+
+ /**
+ * Contains the values to be inserted in the O-DU EPC Measurement Container
+ */
+ class EpcDuPmContainer : public SimpleRefCount<EpcDuPmContainer>
+ {
+ public:
+ long m_qci; //!< QCI value
+ long m_dlPrbUsage; //!< Used number of PRBs in an average of DL for the monitored slice during E2 reporting period
+ long m_ulPrbUsage; //!< Used number of PRBs in an average of UL for the monitored slice during E2 reporting period
+ virtual ~EpcDuPmContainer () = default;
+ };
+
+ /**
+ * Contains the values to be inserted in the O-DU 5GC Measurement Container
+ */
+ class FiveGcDuPmContainer : public SimpleRefCount<FiveGcDuPmContainer>
+ {
+ public:
+ // Snssai m_sliceId; //!< S-NSSAI
+ long m_fiveQi; //!< 5QI value
+ long m_dlPrbUsage; //!< Used number of PRBs in an average of DL for the monitored slice during E2 reporting period
+ long m_ulPrbUsage; //!< Used number of PRBs in an average of UL for the monitored slice during E2 reporting period
+ virtual ~FiveGcDuPmContainer () = default;
+ };
+
+ class ServedPlmnPerCell : public SimpleRefCount<ServedPlmnPerCell>
+ {
+ public:
+ std::string m_plmId; //!< PLMN identity, octet string, 3 bytes
+ uint16_t m_nrCellId;
+ std::set<Ptr<EpcDuPmContainer>> m_perQciReportItems;
+ };
+
+ class CellResourceReport : public SimpleRefCount<CellResourceReport>
+ {
+ public:
+ std::string m_plmId; //!< PLMN identity, octet string, 3 bytes
+ uint16_t m_nrCellId;
+ long dlAvailablePrbs;
+ long ulAvailablePrbs;
+ std::set<Ptr<ServedPlmnPerCell>> m_servedPlmnPerCellItems;
+ };
+
+ /**
+ * Contains the values to be inserted in the O-DU Measurement Container
+ */
+ class ODuContainerValues : public PmContainerValues
+ {
+ public:
+ std::set<Ptr<CellResourceReport>> m_cellResourceReportItems;
+ };
+
+ class KpmIndicationMessage : public SimpleRefCount<KpmIndicationMessage>
+ {
+ public:
+
+ /**
+ * Holds the values to be used to fill the RIC Indication Message
+ */
+ struct KpmIndicationMessageValues
+ {
+ std::string m_cellObjectId; //!< Cell Object ID
+ Ptr<PmContainerValues> m_pmContainerValues; //!< struct containing values to be inserted in the PM Container
+ Ptr<MeasurementItemList> m_cellMeasurementItems; //!< list of cell-specific Measurement Information Items
+ std::set<Ptr<MeasurementItemList>> m_ueIndications; //!< list of Measurement Information Items
+ };
+
+ KpmIndicationMessage (KpmIndicationMessageValues values);
+ ~KpmIndicationMessage ();
+
+ void* m_buffer;
+ size_t m_size;
+
+ private:
+ static void CheckConstraints (KpmIndicationMessageValues values);
+ void FillPmContainer (PF_Container_t *ranContainer,
+ Ptr<PmContainerValues> values);
+ void FillOCuUpContainer (PF_Container_t *ranContainer,
+ Ptr<OCuUpContainerValues> values);
+ void FillOCuCpContainer (PF_Container_t *ranContainer,
+ Ptr<OCuCpContainerValues> values);
+ void FillODuContainer (PF_Container_t *ranContainer,
+ Ptr<ODuContainerValues> values);
+ void FillAndEncodeKpmIndicationMessage (E2SM_KPM_IndicationMessage_t *descriptor,
+ KpmIndicationMessageValues values);
+ void Encode (E2SM_KPM_IndicationMessage_t *descriptor);
+ };
+}
+
+#endif /* KPM_INDICATION_H */
--- /dev/null
+/* -*- 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/oran-interface.h>
+#include <ns3/asn1c-types.h>
+
+#include <ns3/log.h>
+#include <thread>
+#include "encode_e2apv1.hpp"
+
+extern "C" {
+ #include "RICsubscriptionRequest.h"
+ #include "RICactionType.h"
+ #include "ProtocolIE-Field.h"
+ #include "InitiatingMessage.h"
+}
+
+namespace ns3 {
+
+NS_LOG_COMPONENT_DEFINE ("E2Termination");
+
+NS_OBJECT_ENSURE_REGISTERED (E2Termination);
+
+TypeId E2Termination::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::E2Termination")
+ .SetParent<Object>()
+ .AddConstructor<E2Termination>();
+ return tid;
+}
+
+E2Termination::E2Termination ()
+{
+ NS_FATAL_ERROR("Do not use the default constructor");
+}
+
+E2Termination::E2Termination(const std::string ricAddress,
+ const uint16_t ricPort,
+ const uint16_t clientPort,
+ const std::string gnbId,
+ const std::string plmnId)
+ : m_ricAddress (ricAddress),
+ m_ricPort (ricPort),
+ m_clientPort (clientPort),
+ m_gnbId (gnbId),
+ m_plmnId(plmnId)
+{
+ NS_LOG_FUNCTION (this);
+ m_e2sim = new E2Sim;
+
+ // create a new file which will be used to trace the encoded messages
+ // TODO create an appropriate log class to handle these messages
+ // FILE* f = fopen ("messages.txt", "w");
+ // fclose (f);
+}
+
+void
+E2Termination::RegisterFunctionDescToE2Sm (long ranFunctionId, Ptr<FunctionDescription> ranFunctionDescription)
+{
+ // create an octet string and copy the e2smbuffer
+ OCTET_STRING_t *rfdBuf = (OCTET_STRING_t *) calloc (1, sizeof (OCTET_STRING_t));
+ rfdBuf->buf = (uint8_t *) calloc (1, ranFunctionDescription->m_size);
+ rfdBuf->size = ranFunctionDescription->m_size;
+ memcpy (rfdBuf->buf, ranFunctionDescription->m_buffer, ranFunctionDescription->m_size);
+
+ m_e2sim->register_e2sm (ranFunctionId, rfdBuf);
+}
+
+void
+E2Termination::RegisterKpmCallbackToE2Sm (long ranFunctionId, Ptr<FunctionDescription> ranFunctionDescription,
+ SubscriptionCallback sbCb)
+{
+ RegisterFunctionDescToE2Sm (ranFunctionId,ranFunctionDescription);
+ m_e2sim->register_subscription_callback (ranFunctionId, sbCb);
+}
+
+void
+E2Termination::RegisterSmCallbackToE2Sm (long ranFunctionId, Ptr<FunctionDescription> ranFunctionDescription, SmCallback smCb)
+{
+ RegisterFunctionDescToE2Sm (ranFunctionId,ranFunctionDescription);
+ m_e2sim->register_sm_callback (ranFunctionId, smCb);
+}
+
+void E2Termination::Start ()
+{
+ NS_LOG_FUNCTION (this);
+
+ NS_ABORT_MSG_IF(m_ricAddress.empty(), "Set the RIC information first");
+
+ // create a thread to host e2sim execution
+ std::thread e2simThread (&E2Termination::DoStart, this);
+ e2simThread.detach ();
+}
+
+void E2Termination::DoStart ()
+{
+ NS_LOG_FUNCTION (this);
+
+ // start e2sim main loop
+ // char second[14]; // RIC ADDRESS
+ // std::strcpy (second, m_ricAddress.c_str ());
+ // char third[6]; // RIC PORT
+ // std::strcpy (third, std::to_string (m_ricPort).c_str ());
+ // char fourth[5]; // GNB ID value
+ // std::strncpy (fourth, m_gnbId.c_str (), 4);
+ // char fifth[6]; // CLIENT PORT
+ // std::strcpy (fifth, std::to_string (m_clientPort).c_str ());
+ // char sixth[4]; //PLMN ID
+ // std::strcpy (sixth, m_plmnId.c_str ());
+
+ NS_LOG_INFO ("In ns3::E2Term: GNB" << m_gnbId << ", clientPort " << m_clientPort << ", ricPort "
+ << m_ricPort << ", PlmnID "
+ << m_plmnId);
+
+ // char* argv [] = {nullptr, &second [0], &third [0], &fourth[0], &fifth[0],&sixth[0]};
+ m_e2sim->run_loop (m_ricAddress, m_ricPort, m_clientPort, m_gnbId, m_plmnId);
+}
+
+E2Termination::~E2Termination ()
+{
+ NS_LOG_FUNCTION (this);
+ delete m_e2sim;
+}
+
+E2Termination::RicSubscriptionRequest_rval_s
+E2Termination::ProcessRicSubscriptionRequest (E2AP_PDU_t* sub_req_pdu)
+{
+ //Record RIC Request ID
+ //Go through RIC action to be Setup List
+ //Find first entry with REPORT action Type
+ //Record ricActionID
+ //Encode subscription response
+
+ RICsubscriptionRequest_t orig_req = sub_req_pdu->choice.initiatingMessage->value.choice.RICsubscriptionRequest;
+
+ // RICsubscriptionResponse_IEs_t *ricreqid = (RICsubscriptionResponse_IEs_t*)calloc(1, sizeof(RICsubscriptionResponse_IEs_t));
+
+ int count = orig_req.protocolIEs.list.count;
+ int size = orig_req.protocolIEs.list.size;
+
+ RICsubscriptionRequest_IEs_t **ies = (RICsubscriptionRequest_IEs_t**)orig_req.protocolIEs.list.array;
+
+ NS_LOG_DEBUG ("Number of IEs " << count);
+ NS_LOG_DEBUG ("Size of IEs " << size);
+
+ RICsubscriptionRequest_IEs__value_PR pres;
+
+ uint16_t reqRequestorId {};
+ uint16_t reqInstanceId {};
+ uint16_t ranFuncionId {};
+ uint8_t reqActionId {};
+
+ std::vector<long> actionIdsAccept;
+ std::vector<long> actionIdsReject;
+
+ // iterate over the IEs
+ for (int i = 0; i < count; i++)
+ {
+ RICsubscriptionRequest_IEs_t *next_ie = ies[i];
+ pres = next_ie->value.present; // value of the current IE
+
+ switch(pres)
+ {
+ // IE containing the RIC Request ID
+ case RICsubscriptionRequest_IEs__value_PR_RICrequestID:
+ {
+ NS_LOG_DEBUG ("Processing RIC Request ID field");
+ RICrequestID_t reqId = next_ie->value.choice.RICrequestID;
+ reqRequestorId = reqId.ricRequestorID;
+ reqInstanceId = reqId.ricInstanceID;
+ NS_LOG_DEBUG ( "RIC Requestor ID " << reqRequestorId);
+ NS_LOG_DEBUG ( "RIC Instance ID " << reqInstanceId);
+ break;
+ }
+ // IE containing the RAN Function ID
+ case RICsubscriptionRequest_IEs__value_PR_RANfunctionID:
+ {
+ NS_LOG_DEBUG ("Processing RAN Function ID field");
+ ranFuncionId = next_ie->value.choice.RANfunctionID;
+ NS_LOG_DEBUG ("RAN Function ID " << ranFuncionId);
+ break;
+ }
+ case RICsubscriptionRequest_IEs__value_PR_RICsubscriptionDetails:
+ {
+ NS_LOG_DEBUG ("Processing RIC Subscription Details field");
+ RICsubscriptionDetails_t subDetails = next_ie->value.choice.RICsubscriptionDetails;
+
+ // RIC Event Trigger Definition
+ RICeventTriggerDefinition_t triggerDef = subDetails.ricEventTriggerDefinition;
+
+ // TODO How to decode this field?
+ uint8_t size = 20;
+ uint8_t *buf = (uint8_t *)calloc(1,size);
+ memcpy(buf, &triggerDef, size);
+ NS_LOG_DEBUG ("RIC Event Trigger Definition " << std::to_string (*buf));
+
+ // Sequence of actions
+ RICactions_ToBeSetup_List_t actionList = subDetails.ricAction_ToBeSetup_List;
+ // TODO We are ignoring the trigger definition
+
+ int actionCount = actionList.list.count;
+ NS_LOG_DEBUG ("Number of actions " << actionCount);
+
+ auto **item_array = actionList.list.array;
+ bool foundAction = false;
+
+ for (int i = 0; i < actionCount; i++)
+ {
+ auto *next_item = item_array[i];
+ RICactionID_t actionId = ((RICaction_ToBeSetup_ItemIEs*)next_item)->value.choice.RICaction_ToBeSetup_Item.ricActionID;
+ RICactionType_t actionType = ((RICaction_ToBeSetup_ItemIEs*)next_item)->value.choice.RICaction_ToBeSetup_Item.ricActionType;
+
+ //We identify the first action whose type is REPORT
+ //That is the only one accepted; all others are rejected
+ if (!foundAction && (actionType == RICactionType_report || actionType == RICactionType_insert))
+ {
+ reqActionId = actionId;
+ actionIdsAccept.push_back(reqActionId);
+ NS_LOG_DEBUG ("Action ID " << actionId << " accepted");
+ foundAction = true;
+ }
+ else
+ {
+ reqActionId = actionId;
+ NS_LOG_DEBUG ("Action ID " << actionId << " rejected");
+ // actionIdsReject.push_back(reqActionId);
+ }
+ }
+ break;
+ }
+ default:
+ {
+ NS_LOG_DEBUG ("in case default");
+ break;
+ }
+ }
+ }
+
+ NS_LOG_DEBUG ("Create RIC Subscription Response");
+
+ E2AP_PDU *e2ap_pdu = (E2AP_PDU*)calloc(1,sizeof(E2AP_PDU));
+
+ long *accept_array = &actionIdsAccept[0];
+ long *reject_array = &actionIdsReject[0];
+ int accept_size = actionIdsAccept.size();
+ int reject_size = actionIdsReject.size();
+
+ encoding::generate_e2apv1_subscription_response_success(e2ap_pdu, accept_array, reject_array, accept_size, reject_size, reqRequestorId, reqInstanceId);
+
+ NS_LOG_DEBUG ("Send RIC Subscription Response");
+ m_e2sim->encode_and_send_sctp_data(e2ap_pdu);
+
+ RicSubscriptionRequest_rval_s reqParams;
+ reqParams.requestorId = reqRequestorId;
+ reqParams.instanceId = reqInstanceId;
+ reqParams.ranFuncionId = ranFuncionId;
+ reqParams.actionId = reqActionId;
+ return reqParams;
+}
+
+void
+E2Termination::SendE2Message (E2AP_PDU* pdu)
+{
+ m_e2sim->encode_and_send_sctp_data (pdu);
+}
+
+}
--- /dev/null
+/* -*- 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>
+ */
+
+#ifndef ORAN_INTERFACE_H
+#define ORAN_INTERFACE_H
+
+#include "ns3/object.h"
+#include <ns3/kpm-indication.h>
+#include <ns3/kpm-function-description.h>
+#include <ns3/ric-control-function-description.h>
+#include <ns3/ric-control-message.h>
+#include "e2sim.hpp"
+
+namespace ns3 {
+
+ class E2Termination : public Object
+ {
+ public:
+
+ E2Termination();
+
+ /**
+ *
+ * \param ricAddress RIC IP address
+ * \param ricPort RIC port
+ * \param clientPort the local port to which the client will bind
+ * \param gnbId the GNB ID
+ * \param plmnId the PLMN ID
+ */
+ E2Termination(const std::string ricAddress,
+ const uint16_t ricPort,
+ const uint16_t clientPort,
+ const std::string gnbId,
+ const std::string plmnId);
+
+ virtual ~E2Termination ();
+
+ /**
+ * inherited from Object
+ * @return
+ */
+ static TypeId GetTypeId();
+
+ /**
+ * Start the E2 termination.
+ * Create a separate thread to host the execution of e2sim. The thread will
+ * execute the method DoStart.
+ */
+ void Start ();
+
+ /**
+ * Register an E2 Service Model.
+ * Create a RAN Function Description item containing the configurations
+ * for the SM, add it to the list of supported RAN functions, and
+ * register a callback.
+ * Whenever a RIC Subscription Request to this RAN Function is received,
+ * the callback is triggered.
+ *
+ * \param ranFunctionId ID used to identify the KPM RAN Function
+ * \param ranFunctionDescription
+ * \param cb callback that will be triggered if the RIC subscribes to
+ * this function
+ */
+ void RegisterKpmCallbackToE2Sm (long ranFunctionId,
+ Ptr<FunctionDescription> ranFunctionDescription,
+ SubscriptionCallback sbCb);
+
+ /**
+ * Register an E2 Service Model.
+ * Create a RAN Function Description item containing the configurations
+ * for the SM, add it to the list of supported RAN functions, and
+ * register a callback.
+ * Whenever a Sm message to this RAN Function is received,
+ * the callback is triggered.
+ *
+ * \param ranFunctionId ID used to identify the KPM RAN Function
+ * \param ranFunctionDescription
+ * \param cb callback that will be triggered if the RIC subscribes to
+ * this function
+ */
+ void RegisterSmCallbackToE2Sm (long ranFunctionId,
+ Ptr<FunctionDescription> ranFunctionDescription,
+ SmCallback smCb);
+
+ /**
+ * Struct holding the values returned by ProcessRicSubscriptionRequest
+ */
+ struct RicSubscriptionRequest_rval_s
+ {
+ uint16_t requestorId; //!< RIC Requestor ID
+ uint16_t instanceId; //!< RIC Instance ID
+ uint16_t ranFuncionId; //!< RAN Function ID
+ uint8_t actionId; //!< RIC Action ID
+ };
+
+ /**
+ * Process RIC Subscription Request.
+ * This function processes the RIC Subscription Request and sends the
+ * RIC Subscription Response.
+ *
+ * \param sub_req_pdu request message
+ * \return RIC subscription request parameters
+ */
+ RicSubscriptionRequest_rval_s ProcessRicSubscriptionRequest (E2AP_PDU_t* sub_req_pdu);
+
+ /**
+ * Sends an E2 message to the RIC
+ * This function encodes and sends an E2 message to the RIC
+ *
+ * \param pdu the PDU of the message
+ */
+ void SendE2Message (E2AP_PDU* pdu);
+
+ private:
+ /**
+ * Run the e2sim main loop.
+ * Starts the e2sim main loop, it will open a socket towards the RIC and
+ * start the reception routine.
+ */
+ void DoStart ();
+
+ /**
+ * \brief Accessory function to populate to the registration of the ran function description to e2sim
+ *
+ * \param ranFunctionId
+ * \param ranFunctionDescription
+ */
+ void RegisterFunctionDescToE2Sm (long ranFunctionId,
+ Ptr<FunctionDescription> ranFunctionDescription);
+
+ E2Sim* m_e2sim; //!< pointer to an instance of the O-RAN E2 simulator
+ std::string m_ricAddress; //!< IP address of the RIC
+ uint16_t m_ricPort; //!< port of the RIC
+ uint16_t m_clientPort; //!< local bind port
+ std::string m_gnbId; //!< GNB id
+ std::string m_plmnId; //!< PLMN Id
+ };
+}
+
+#endif /* ORAN_INTERFACE_H */
--- /dev/null
+/* -*- 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/ric-control-function-description.h>
+#include <ns3/asn1c-types.h>
+#include <ns3/log.h>
+
+extern "C" {
+ #include "RIC-ControlStyle-Item.h"
+ #include "RIC-ControlAction-Item.h"
+ #include "RAN-ControlParameter-Item.h"
+}
+
+namespace ns3 {
+
+NS_LOG_COMPONENT_DEFINE ("RicControlFunctionDescription");
+
+RicControlFunctionDescription::RicControlFunctionDescription ()
+{
+ E2SM_RC_RANFunctionDefinition_t *descriptor = new E2SM_RC_RANFunctionDefinition_t ();
+ FillAndEncodeRCFunctionDescription (descriptor);
+ ASN_STRUCT_FREE_CONTENTS_ONLY (asn_DEF_E2SM_RC_RANFunctionDefinition, descriptor);
+ delete descriptor;
+}
+
+RicControlFunctionDescription::~RicControlFunctionDescription ()
+{
+
+}
+
+void
+RicControlFunctionDescription::Encode (E2SM_RC_RANFunctionDefinition_t *descriptor)
+{
+ asn_codec_ctx_t *opt_cod = 0; // disable stack bounds checking
+ // encode the structure into the e2smbuffer
+ asn_encode_to_new_buffer_result_s encodedMsg = asn_encode_to_new_buffer (
+ opt_cod, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2SM_RC_RANFunctionDefinition, descriptor);
+
+ if (encodedMsg.result.encoded < 0)
+ {
+ NS_FATAL_ERROR ("Error during the encoding of the RIC Indication Header, errno: "
+ << strerror (errno) << ", failed_type " << encodedMsg.result.failed_type->name
+ << ", structure_ptr " << encodedMsg.result.structure_ptr);
+ }
+
+ m_buffer = encodedMsg.buffer;
+ m_size = encodedMsg.result.encoded;
+}
+
+void
+RicControlFunctionDescription::FillAndEncodeRCFunctionDescription (
+ E2SM_RC_RANFunctionDefinition_t *ranfunc_desc)
+{
+
+ std::string shortNameBuffer = "ORAN-WG3-RC";
+
+ Ptr<OctetString> shortName = Create<OctetString> (shortNameBuffer, shortNameBuffer.size ());
+
+ ranfunc_desc->ranFunction_Name.ranFunction_ShortName = shortName->GetValue ();
+
+ // This part is not in the specs, maybe it can be removed?
+
+ uint8_t *descriptionBuffer = (uint8_t *) "RIC Control Definitions";
+ uint8_t *oidBuffer = (uint8_t *) "OID123"; // this is optional, dummy value
+
+ long *inst = (long *) calloc (1, sizeof (long));
+
+ ranfunc_desc->ranFunction_Name.ranFunction_Description.buf =
+ (uint8_t *) calloc (1, strlen ((char *) descriptionBuffer));
+ memcpy (ranfunc_desc->ranFunction_Name.ranFunction_Description.buf, descriptionBuffer,
+ strlen ((char *) descriptionBuffer));
+ ranfunc_desc->ranFunction_Name.ranFunction_Description.size = strlen ((char *) descriptionBuffer);
+ ranfunc_desc->ranFunction_Name.ranFunction_Instance = inst;
+ ranfunc_desc->ranFunction_Name.ranFunction_E2SM_OID.buf =
+ (uint8_t *) calloc (1, strlen ((char *) oidBuffer));
+ memcpy (ranfunc_desc->ranFunction_Name.ranFunction_E2SM_OID.buf, oidBuffer,
+ strlen ((char *) oidBuffer));
+ ranfunc_desc->ranFunction_Name.ranFunction_E2SM_OID.size = strlen ((char *) oidBuffer);
+
+ // End part of of specs
+
+ RIC_ControlStyle_Item_t *control_style0 =
+ (RIC_ControlStyle_Item_t *) calloc (1, sizeof (RIC_ControlStyle_Item_t));
+ control_style0->ric_ControlStyle_Type = 1;
+
+ uint8_t *controlStyleName0Buffer = (uint8_t *) "Radio Bearer Control";
+ size_t controlStyleName0BufferSize = strlen ((char *) controlStyleName0Buffer);
+ control_style0->ric_ControlStyle_Name.buf = (uint8_t *) calloc (1, controlStyleName0BufferSize);
+ memcpy (control_style0->ric_ControlStyle_Name.buf, controlStyleName0Buffer,
+ controlStyleName0BufferSize);
+ control_style0->ric_ControlStyle_Name.size = controlStyleName0BufferSize;
+
+ // these two were not present in the spec in this control style but just in the second, remove if they lead to crash
+ control_style0->ric_ControlMessageFormat_Type = 1;
+ control_style0->ric_ControlHeaderFormat_Type = 1;
+
+ control_style0->ric_ControlAction_List =
+ (RIC_ControlStyle_Item::RIC_ControlStyle_Item__ric_ControlAction_List *) calloc (
+ 1, sizeof (RIC_ControlStyle_Item::RIC_ControlStyle_Item__ric_ControlAction_List));
+
+ RIC_ControlAction_Item_t *control_action0 =
+ (RIC_ControlAction_Item_t *) calloc (1, sizeof (RIC_ControlAction_Item_t));
+
+ control_action0->ric_ControlAction_ID = 6;
+ uint8_t *controlActionName0Buffer = (uint8_t *) "DRB split ratio control";
+ size_t controlActionName0BufferSize = strlen ((char *) controlActionName0Buffer);
+ control_action0->ric_ControlAction_Name.buf =
+ (uint8_t *) calloc (1, controlActionName0BufferSize);
+ memcpy (control_action0->ric_ControlAction_Name.buf, controlActionName0Buffer,
+ controlActionName0BufferSize);
+ control_action0->ric_ControlAction_Name.size = controlActionName0BufferSize;
+ control_action0->ran_ControlParameters_List =
+ (RIC_ControlAction_Item::RIC_ControlAction_Item__ran_ControlParameters_List *) calloc (
+ 1, sizeof (RIC_ControlAction_Item::RIC_ControlAction_Item__ran_ControlParameters_List));
+
+ RAN_ControlParameter_Item_t *ranParameter0 =
+ (RAN_ControlParameter_Item_t *) calloc (1, sizeof (RAN_ControlParameter_Item_t));
+ uint8_t *ranParameter0NameBuffer = (uint8_t *) "Downlink PDCP Data Split";
+ size_t ranParameter0NameBufferSize = strlen ((char *) ranParameter0NameBuffer);
+ ranParameter0->ranParameter_Name.buf = (uint8_t *) calloc (1, ranParameter0NameBufferSize);
+ memcpy (ranParameter0->ranParameter_Name.buf, ranParameter0NameBuffer,
+ ranParameter0NameBufferSize);
+ ranParameter0->ranParameter_Name.size = ranParameter0NameBufferSize;
+ ranParameter0->ranParameter_ID = 3;
+
+ RAN_ControlParameter_Item_t *ranParameter1 =
+ (RAN_ControlParameter_Item_t *) calloc (1, sizeof (RAN_ControlParameter_Item_t));
+ uint8_t *ranParameter1NameBuffer = (uint8_t *) "Uplink PDCP Data Split Threshold";
+ size_t ranParameter1NameBufferSize = strlen ((char *) ranParameter1NameBuffer);
+ ranParameter1->ranParameter_Name.buf = (uint8_t *) calloc (1, ranParameter1NameBufferSize);
+ memcpy (ranParameter1->ranParameter_Name.buf, ranParameter1NameBuffer,
+ ranParameter1NameBufferSize);
+ ranParameter1->ranParameter_ID = 2;
+
+ ASN_SEQUENCE_ADD (&control_action0->ran_ControlParameters_List->list, ranParameter0);
+ ASN_SEQUENCE_ADD (&control_action0->ran_ControlParameters_List->list, ranParameter1);
+
+ ASN_SEQUENCE_ADD (&control_style0->ric_ControlAction_List->list, control_action0);
+
+ RIC_ControlStyle_Item_t *control_style1 =
+ (RIC_ControlStyle_Item_t *) calloc (1, sizeof (RIC_ControlStyle_Item_t));
+ control_style1->ric_ControlStyle_Type = 3;
+
+ uint8_t *controlStyleName1Buffer = (uint8_t *) "Radio Bearer Control";
+ size_t controlStyleName1BufferSize = strlen ((char *) controlStyleName1Buffer);
+ control_style1->ric_ControlStyle_Name.buf = (uint8_t *) calloc (1, controlStyleName1BufferSize);
+ memcpy (control_style1->ric_ControlStyle_Name.buf, controlStyleName1Buffer,
+ controlStyleName1BufferSize);
+ control_style1->ric_ControlStyle_Name.size = controlStyleName1BufferSize;
+
+ control_style1->ric_ControlMessageFormat_Type = 1;
+ control_style1->ric_ControlHeaderFormat_Type = 1;
+
+ control_style1->ric_ControlAction_List =
+ (RIC_ControlStyle_Item::RIC_ControlStyle_Item__ric_ControlAction_List *) calloc (
+ 1, sizeof (RIC_ControlStyle_Item::RIC_ControlStyle_Item__ric_ControlAction_List));
+
+ RIC_ControlAction_Item_t *control_action1 =
+ (RIC_ControlAction_Item_t *) calloc (1, sizeof (RIC_ControlAction_Item_t));
+
+ control_action1->ric_ControlAction_ID = 1;
+ uint8_t *controlActionName1Buffer = (uint8_t *) "Handover control";
+ size_t controlActionName1BufferSize = strlen ((char *) controlActionName1Buffer);
+ control_action1->ric_ControlAction_Name.buf =
+ (uint8_t *) calloc (1, controlActionName1BufferSize);
+ memcpy (control_action1->ric_ControlAction_Name.buf, controlActionName1Buffer,
+ controlActionName1BufferSize);
+ control_action1->ric_ControlAction_Name.size = controlActionName1BufferSize;
+ control_action1->ran_ControlParameters_List =
+ (RIC_ControlAction_Item::RIC_ControlAction_Item__ran_ControlParameters_List *) calloc (
+ 1, sizeof (RIC_ControlAction_Item::RIC_ControlAction_Item__ran_ControlParameters_List));
+
+ RAN_ControlParameter_Item_t *ranParameter2 =
+ (RAN_ControlParameter_Item_t *) calloc (1, sizeof (RAN_ControlParameter_Item_t));
+ uint8_t *ranParameter2NameBuffer = (uint8_t *) "NR CGI";
+ size_t ranParameter2NameBufferSize = strlen ((char *) ranParameter2NameBuffer);
+ ranParameter2->ranParameter_Name.buf = (uint8_t *) calloc (1, ranParameter2NameBufferSize);
+ memcpy (ranParameter2->ranParameter_Name.buf, ranParameter2NameBuffer,
+ ranParameter2NameBufferSize);
+ ranParameter2->ranParameter_Name.size = ranParameter2NameBufferSize;
+ ranParameter2->ranParameter_ID = 4;
+
+ RAN_ControlParameter_Item_t *ranParameter3 =
+ (RAN_ControlParameter_Item_t *) calloc (1, sizeof (RAN_ControlParameter_Item_t));
+ uint8_t *ranParameter3NameBuffer = (uint8_t *) "E-UTRA CGI";
+ size_t ranParameter3NameBufferSize = strlen ((char *) ranParameter3NameBuffer);
+ ranParameter3->ranParameter_Name.buf = (uint8_t *) calloc (1, ranParameter3NameBufferSize);
+ memcpy (ranParameter3->ranParameter_Name.buf, ranParameter3NameBuffer,
+ ranParameter3NameBufferSize);
+ ranParameter3->ranParameter_Name.size = ranParameter3NameBufferSize;
+ ranParameter3->ranParameter_ID = 6;
+
+ ASN_SEQUENCE_ADD (&control_action1->ran_ControlParameters_List->list, ranParameter2);
+ ASN_SEQUENCE_ADD (&control_action1->ran_ControlParameters_List->list, ranParameter3);
+
+ ASN_SEQUENCE_ADD (&control_style1->ric_ControlAction_List->list, control_action1);
+
+ ranfunc_desc->ric_ControlStyle_List =
+ (E2SM_RC_RANFunctionDefinition::E2SM_RC_RANFunctionDefinition__ric_ControlStyle_List *)
+ calloc (1, sizeof (E2SM_RC_RANFunctionDefinition::
+ E2SM_RC_RANFunctionDefinition__ric_ControlStyle_List));
+
+ ASN_SEQUENCE_ADD (&ranfunc_desc->ric_ControlStyle_List->list, control_style0);
+ ASN_SEQUENCE_ADD (&ranfunc_desc->ric_ControlStyle_List->list, control_style1);
+
+ Encode (ranfunc_desc);
+
+ NS_LOG_INFO (xer_fprint (stderr, &asn_DEF_E2SM_RC_RANFunctionDefinition, ranfunc_desc));
+}
+
+} // namespace ns3
--- /dev/null
+/* -*- 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>
+ */
+
+#ifndef RIC_CONTROL_FUNCTION_DESCRIPTION_H
+#define RIC_CONTROL_FUNCTION_DESCRIPTION_H
+
+#include <ns3/function-description.h>
+#include "ns3/object.h"
+
+extern "C" {
+ #include "E2SM-RC-RANFunctionDefinition.h"
+}
+
+namespace ns3 {
+
+ class RicControlFunctionDescription : public FunctionDescription
+ {
+ public:
+ RicControlFunctionDescription ();
+ ~RicControlFunctionDescription ();
+
+
+ private:
+
+ void FillAndEncodeRCFunctionDescription (E2SM_RC_RANFunctionDefinition_t* descriptor);
+ void Encode (E2SM_RC_RANFunctionDefinition_t* descriptor);
+ };
+}
+
+#endif /* RIC_CONTROL_FUNCTION_DESCRIPTION_H */
--- /dev/null
+/* -*- 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/ric-control-message.h>
+#include <ns3/asn1c-types.h>
+#include <ns3/log.h>
+#include <bitset>
+namespace ns3 {
+
+NS_LOG_COMPONENT_DEFINE ("RicControlMessage");
+
+
+RicControlMessage::RicControlMessage (E2AP_PDU_t* pdu)
+{
+ DecodeRicControlMessage (pdu);
+ NS_LOG_INFO ("End of RicControlMessage::RicControlMessage()");
+}
+
+RicControlMessage::~RicControlMessage ()
+{
+
+}
+
+void
+RicControlMessage::DecodeRicControlMessage(E2AP_PDU_t* pdu)
+{
+ InitiatingMessage_t* mess = pdu->choice.initiatingMessage;
+ auto *request = (RICcontrolRequest_t *) &mess->value.choice.RICcontrolRequest;
+ NS_LOG_INFO (xer_fprint(stderr, &asn_DEF_RICcontrolRequest, request));
+
+ size_t count = request->protocolIEs.list.count;
+ if (count <= 0) {
+ NS_LOG_ERROR("[E2SM] received empty list");
+ return;
+ }
+
+ for (size_t i = 0; i < count; i++)
+ {
+ RICcontrolRequest_IEs_t *ie = request->protocolIEs.list.array [i];
+ switch (ie->value.present) {
+ case RICcontrolRequest_IEs__value_PR_RICrequestID: {
+ NS_LOG_DEBUG("[E2SM] RICcontrolRequest_IEs__value_PR_RICrequestID");
+ m_ricRequestId = ie->value.choice.RICrequestID;
+ switch (m_ricRequestId.ricRequestorID) {
+ case 1001: {
+ NS_LOG_DEBUG("TS xApp message");
+ m_requestType = ControlMessageRequestIdType::TS;
+ break;
+ }
+ case 1002: {
+ NS_LOG_DEBUG("QoS xApp message");
+ m_requestType = ControlMessageRequestIdType::QoS;
+ break;
+ }
+ }
+ break;
+ }
+ case RICcontrolRequest_IEs__value_PR_RANfunctionID: {
+ m_ranFunctionId = ie->value.choice.RANfunctionID;
+
+ NS_LOG_DEBUG("[E2SM] RICcontrolRequest_IEs__value_PR_RANfunctionID");
+ break;
+ }
+ case RICcontrolRequest_IEs__value_PR_RICcallProcessID: {
+ m_ricCallProcessId = ie->value.choice.RICcallProcessID;
+ NS_LOG_DEBUG("[E2SM] RICcontrolRequest_IEs__value_PR_RICcallProcessID");
+ break;
+ }
+ case RICcontrolRequest_IEs__value_PR_RICcontrolHeader: {
+ NS_LOG_DEBUG("[E2SM] RICcontrolRequest_IEs__value_PR_RICcontrolHeader");
+ // xer_fprint(stderr, &asn_DEF_RICcontrolHeader, &ie->value.choice.RICcontrolHeader);
+
+ auto *e2smControlHeader = (E2SM_RC_ControlHeader_t *) calloc(1,
+ sizeof(E2SM_RC_ControlHeader_t));
+ ASN_STRUCT_RESET(asn_DEF_E2SM_RC_ControlHeader, e2smControlHeader);
+ asn_decode (nullptr, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2SM_RC_ControlHeader,
+ (void **) &e2smControlHeader, ie->value.choice.RICcontrolHeader.buf,
+ ie->value.choice.RICcontrolHeader.size);
+
+ NS_LOG_INFO (xer_fprint (stderr, &asn_DEF_E2SM_RC_ControlHeader, e2smControlHeader));
+ if (e2smControlHeader->present == E2SM_RC_ControlHeader_PR_controlHeader_Format1) {
+ m_e2SmRcControlHeaderFormat1 = e2smControlHeader->choice.controlHeader_Format1;
+ //m_e2SmRcControlHeaderFormat1->ric_ControlAction_ID;
+ //m_e2SmRcControlHeaderFormat1->ric_ControlStyle_Type;
+ //m_e2SmRcControlHeaderFormat1->ueId;
+ } else {
+ NS_LOG_DEBUG("[E2SM] Error in checking format of E2SM Control Header");
+ }
+ break;
+ }
+ case RICcontrolRequest_IEs__value_PR_RICcontrolMessage: {
+ NS_LOG_DEBUG("[E2SM] RICcontrolRequest_IEs__value_PR_RICcontrolMessage");
+ // xer_fprint(stderr, &asn_DEF_RICcontrolMessage, &ie->value.choice.RICcontrolMessage);
+
+ auto *e2SmControlMessage = (E2SM_RC_ControlMessage_t *) calloc(1,
+ sizeof(E2SM_RC_ControlMessage_t));
+ ASN_STRUCT_RESET(asn_DEF_E2SM_RC_ControlMessage, e2SmControlMessage);
+
+ asn_decode (nullptr, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2SM_RC_ControlMessage,
+ (void **) &e2SmControlMessage, ie->value.choice.RICcontrolMessage.buf,
+ ie->value.choice.RICcontrolMessage.size);
+
+ NS_LOG_INFO (xer_fprint(stderr, &asn_DEF_E2SM_RC_ControlMessage, e2SmControlMessage));
+
+ if (e2SmControlMessage->present == E2SM_RC_ControlMessage_PR_controlMessage_Format1)
+ {
+ NS_LOG_DEBUG ("[E2SM] E2SM_RC_ControlMessage_PR_controlMessage_Format1");
+ E2SM_RC_ControlMessage_Format1_t *e2SmRcControlMessageFormat1 =
+ e2SmControlMessage->choice.controlMessage_Format1;
+ m_valuesExtracted =
+ ExtractRANParametersFromControlMessage (e2SmRcControlMessageFormat1);
+ if (m_requestType == ControlMessageRequestIdType::TS)
+ {
+ // Get and parse the secondaty cell id according to 3GPP TS 38.473, Section 9.2.2.1
+ for (RANParameterItem item : m_valuesExtracted)
+ {
+ if (item.m_valueType == RANParameterItem::ValueType::OctectString)
+ {
+ // First 3 digits are the PLMNID (always 111), last digit is CellId
+ std::string cgi = item.m_valueStr->DecodeContent ();
+ NS_LOG_INFO ("Decoded CGI value is: " << cgi);
+ m_secondaryCellId = cgi.back();
+ }
+ }
+ }
+ }
+ else
+ {
+ NS_LOG_DEBUG("[E2SM] Error in checking format of E2SM Control Message");
+ }
+ break;
+ }
+ case RICcontrolRequest_IEs__value_PR_RICcontrolAckRequest: {
+ NS_LOG_DEBUG("[E2SM] RICcontrolRequest_IEs__value_PR_RICcontrolAckRequest");
+
+ switch (ie->value.choice.RICcontrolAckRequest) {
+ case RICcontrolAckRequest_noAck: {
+ NS_LOG_DEBUG("[E2SM] RIC Control ack value: NO ACK");
+ break;
+ }
+ case RICcontrolAckRequest_ack: {
+ NS_LOG_DEBUG("[E2SM] RIC Control ack value: ACK");
+ break;
+ }
+ case RICcontrolAckRequest_nAck: {
+ NS_LOG_DEBUG("[E2SM] RIC Control ack value: NACK");
+ break;
+ }
+ default: {
+ NS_LOG_DEBUG("[E2SM] RIC Control ack value unknown");
+ break;
+ }
+ }
+ break;
+ }
+ case RICcontrolRequest_IEs__value_PR_NOTHING: {
+ NS_LOG_DEBUG("[E2SM] RICcontrolRequest_IEs__value_PR_NOTHING");
+ NS_LOG_DEBUG("[E2SM] Nothing");
+ break;
+ }
+ default: {
+ NS_LOG_DEBUG("[E2SM] RIC Control value unknown");
+ break;
+ }
+ }
+ }
+
+ NS_LOG_INFO ("End of DecodeRicControlMessage");
+}
+
+std::string
+RicControlMessage::GetSecondaryCellIdHO ()
+{
+ return m_secondaryCellId;
+}
+
+std::vector<RANParameterItem>
+RicControlMessage::ExtractRANParametersFromControlMessage (
+ E2SM_RC_ControlMessage_Format1_t *e2SmRcControlMessageFormat1)
+{
+ std::vector<RANParameterItem> ranParameterList;
+ int count = e2SmRcControlMessageFormat1->ranParameters_List->list.count;
+ for (int i = 0; i < count; i++)
+ {
+ RANParameter_Item_t *ranParameterItem =
+ e2SmRcControlMessageFormat1->ranParameters_List->list.array[i];
+ for (RANParameterItem extractedParameter :
+ RANParameterItem::ExtractRANParametersFromRANParameter (ranParameterItem))
+ {
+ ranParameterList.push_back (extractedParameter);
+ }
+ }
+
+ return ranParameterList;
+}
+
+} // namespace ns3
--- /dev/null
+/* -*- 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>
+ */
+
+#ifndef RIC_CONTROL_MESSAGE_H
+#define RIC_CONTROL_MESSAGE_H
+
+#include "ns3/object.h"
+#include <ns3/asn1c-types.h>
+
+extern "C" {
+ #include "E2AP-PDU.h"
+ #include "E2SM-RC-ControlHeader.h"
+ #include "E2SM-RC-ControlMessage.h"
+ #include "E2SM-RC-ControlHeader-Format1.h"
+ #include "E2SM-RC-ControlMessage-Format1.h"
+ #include "RICcontrolRequest.h"
+ #include "ProtocolIE-Field.h"
+ #include "InitiatingMessage.h"
+ #include "CellGlobalID.h"
+ #include "NRCGI.h"
+ }
+
+namespace ns3 {
+
+ class RicControlMessage : public SimpleRefCount<RicControlMessage>
+ {
+ public:
+ enum ControlMessageRequestIdType { TS = 1001, QoS = 1002 };
+ RicControlMessage (E2AP_PDU_t *pdu);
+ ~RicControlMessage ();
+
+ ControlMessageRequestIdType m_requestType;
+
+ static std::vector<RANParameterItem> ExtractRANParametersFromControlMessage (
+ E2SM_RC_ControlMessage_Format1_t *e2SmRcControlMessageFormat1);
+
+ std::vector<RANParameterItem> m_valuesExtracted;
+ RANfunctionID_t m_ranFunctionId;
+ RICrequestID_t m_ricRequestId;
+ RICcallProcessID_t m_ricCallProcessId;
+ E2SM_RC_ControlHeader_Format1_t *m_e2SmRcControlHeaderFormat1;
+ std::string GetSecondaryCellIdHO ();
+
+ private:
+ /**
+ * Decodes the RIC Control message .
+ *
+ * \param pdu PDU passed by the RIC
+ */
+ void DecodeRicControlMessage (E2AP_PDU_t *pdu);
+ std::string m_secondaryCellId;
+ };
+}
+
+#endif /* RIC_CONTROL_MESSAGE_H */
--- /dev/null
+/* -*- 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 a header file from your module to test.
+#include "ns3/oran-interface.h"
+
+// An essential include is test.h
+#include "ns3/test.h"
+
+// Do not put your test classes in namespace ns3. You may find it useful
+// to use the using directive to access the ns3 namespace directly
+using namespace ns3;
+
+// This is an example TestCase.
+class OranInterfaceTestCase1 : public TestCase
+{
+public:
+ OranInterfaceTestCase1 ();
+ virtual ~OranInterfaceTestCase1 ();
+
+private:
+ virtual void DoRun (void);
+};
+
+// Add some help text to this case to describe what it is intended to test
+OranInterfaceTestCase1::OranInterfaceTestCase1 ()
+ : TestCase ("OranInterface test case (does nothing)")
+{
+}
+
+// This destructor does nothing but we include it as a reminder that
+// the test case should clean up after itself
+OranInterfaceTestCase1::~OranInterfaceTestCase1 ()
+{
+}
+
+//
+// This method is the pure virtual method from class TestCase that every
+// TestCase must implement
+//
+void
+OranInterfaceTestCase1::DoRun (void)
+{
+ // A wide variety of test macros are available in src/core/test.h
+ NS_TEST_ASSERT_MSG_EQ (true, true, "true doesn't equal true for some reason");
+ // Use this one for floating point comparisons
+ NS_TEST_ASSERT_MSG_EQ_TOL (0.01, 0.01, 0.001, "Numbers are not equal within tolerance");
+}
+
+// The TestSuite class names the TestSuite, identifies what type of TestSuite,
+// and enables the TestCases to be run. Typically, only the constructor for
+// this class must be defined
+//
+class OranInterfaceTestSuite : public TestSuite
+{
+public:
+ OranInterfaceTestSuite ();
+};
+
+OranInterfaceTestSuite::OranInterfaceTestSuite ()
+ : TestSuite ("oran-interface", UNIT)
+{
+ // TestDuration for TestCase can be QUICK, EXTENSIVE or TAKES_FOREVER
+ AddTestCase (new OranInterfaceTestCase1, TestCase::QUICK);
+}
+
+// Do not forget to allocate an instance of this TestSuite
+static OranInterfaceTestSuite soranInterfaceTestSuite;
+
--- /dev/null
+# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+# def options(opt):
+# pass
+
+def configure(conf):
+ conf.env.append_value('CXXFLAGS', '-I/usr/local/include/e2sim')
+ conf.env.append_value("LINKFLAGS", ["-L/usr/local/lib"])
+ conf.env.append_value("LIB", ["e2sim"])
+
+def build(bld):
+ module = bld.create_ns3_module('oran-interface', ['core'])
+ module.source = [
+ 'model/oran-interface.cc',
+ 'model/asn1c-types.cc',
+ 'model/function-description.cc',
+ 'model/kpm-indication.cc',
+ 'model/kpm-function-description.cc',
+ 'model/ric-control-message.cc',
+ 'model/ric-control-function-description.cc',
+ 'helper/oran-interface-helper.cc',
+ 'helper/indication-message-helper.cc',
+ 'helper/lte-indication-message-helper.cc',
+ 'helper/mmwave-indication-message-helper.cc'
+ ]
+
+ module_test = bld.create_ns3_module_test_library('oran-interface')
+ module_test.source = [
+ 'test/oran-interface-test-suite.cc',
+ ]
+ # Tests encapsulating example programs should be listed here
+ if (bld.env['ENABLE_EXAMPLES']):
+ module_test.source.extend([
+ # 'test/oran-interface-examples-test-suite.cc',
+ ])
+
+ headers = bld(features='ns3header')
+ headers.module = 'oran-interface'
+ headers.source = [
+ 'model/oran-interface.h',
+ 'model/asn1c-types.h',
+ 'model/function-description.h',
+ 'model/kpm-indication.h',
+ 'model/kpm-function-description.h',
+ 'model/ric-control-message.h',
+ 'model/ric-control-function-description.h',
+ 'helper/oran-interface-helper.h',
+ 'helper/indication-message-helper.h',
+ 'helper/lte-indication-message-helper.h',
+ 'helper/mmwave-indication-message-helper.h',
+ ]
+
+ if bld.env.ENABLE_EXAMPLES:
+ bld.recurse('examples')
+
+
+ # bld.ns3_python_bindings()