First release
[sim/ns3-o-ran-e2.git] / model / kpm-indication.cc
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2022 Northeastern University
4  * Copyright (c) 2022 Sapienza, University of Rome
5  * Copyright (c) 2022 University of Padova
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation;
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * Author: Andrea Lacava <thecave003@gmail.com>
21  *                 Tommaso Zugno <tommasozugno@gmail.com>
22  *                 Michele Polese <michele.polese@gmail.com>
23  */
24
25 #include <ns3/kpm-indication.h>
26 #include <ns3/asn1c-types.h>
27 #include <ns3/log.h>
28
29 extern "C" {
30 #include "E2SM-KPM-IndicationHeader-Format1.h"
31 #include "E2SM-KPM-IndicationMessage-Format1.h"
32 #include "GlobalE2node-ID.h"
33 #include "GlobalE2node-gNB-ID.h"
34 #include "GlobalE2node-eNB-ID.h"
35 #include "GlobalE2node-ng-eNB-ID.h"
36 #include "GlobalE2node-en-gNB-ID.h"
37 #include "NRCGI.h"
38 #include "PM-Containers-Item.h"
39 #include "RIC-EventTriggerStyle-Item.h"
40 #include "RIC-ReportStyle-Item.h"
41 #include "TimeStamp.h"
42 #include "CUUPMeasurement-Container.h"
43 #include "PlmnID-Item.h"
44 #include "EPC-CUUP-PM-Format.h"
45 #include "PerQCIReportListItemFormat.h"
46 #include "PerUE-PM-Item.h"
47 #include "PM-Info-Item.h"
48 #include "MeasurementInfoList.h"
49 #include "CellObjectID.h"
50 #include "CellResourceReportListItem.h"
51 #include "ServedPlmnPerCellListItem.h"
52 #include "EPC-DU-PM-Container.h"
53 #include "PerQCIReportListItem.h"
54 }
55
56 namespace ns3 {
57
58 NS_LOG_COMPONENT_DEFINE ("KpmIndication");
59
60 KpmIndicationHeader::KpmIndicationHeader (GlobalE2nodeType nodeType,KpmRicIndicationHeaderValues values)
61 {
62   m_nodeType = nodeType;
63   E2SM_KPM_IndicationHeader_t *descriptor = new E2SM_KPM_IndicationHeader_t;
64   FillAndEncodeKpmRicIndicationHeader (descriptor, values);
65   delete descriptor;
66 }
67
68 KpmIndicationHeader::~KpmIndicationHeader ()
69 {
70   NS_LOG_FUNCTION (this);
71   free (m_buffer);
72   m_size = 0;
73 }
74
75 void
76 KpmIndicationHeader::Encode (E2SM_KPM_IndicationHeader_t *descriptor)
77 {
78   asn_codec_ctx_t *opt_cod = 0; // disable stack bounds checking
79   asn_encode_to_new_buffer_result_s encodedHeader = asn_encode_to_new_buffer (
80       opt_cod, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2SM_KPM_IndicationHeader, descriptor);
81
82   if (encodedHeader.result.encoded < 0)
83     {
84       NS_FATAL_ERROR ("Error during the encoding of the RIC Indication Header, errno: "
85                       << strerror (errno) << ", failed_type "
86                       << encodedHeader.result.failed_type->name << ", structure_ptr "
87                       << encodedHeader.result.structure_ptr);
88     }
89
90   m_buffer = encodedHeader.buffer;
91   m_size = encodedHeader.result.encoded;
92 }
93
94 void
95 KpmIndicationHeader::FillAndEncodeKpmRicIndicationHeader (E2SM_KPM_IndicationHeader_t *descriptor,
96                                                           KpmRicIndicationHeaderValues values)
97 {
98
99   E2SM_KPM_IndicationHeader_Format1_t *ind_header = (E2SM_KPM_IndicationHeader_Format1_t *) calloc (
100       1, sizeof (E2SM_KPM_IndicationHeader_Format1_t));
101
102   Ptr<OctetString> plmnid = Create<OctetString> (values.m_plmId, 3);
103   Ptr<BitString> cellId_bstring;
104
105   GlobalE2node_ID *globalE2nodeIdBuf = (GlobalE2node_ID *) calloc (1, sizeof (GlobalE2node_ID));
106   ind_header->id_GlobalE2node_ID = *globalE2nodeIdBuf;
107
108   switch (m_nodeType)
109     {
110       case gNB: {
111         static int sizeGnb = 4; // 3GPP Specs
112         
113         cellId_bstring = Create<BitString> (values.m_gnbId, sizeGnb);
114
115         ind_header->id_GlobalE2node_ID.present = GlobalE2node_ID_PR_gNB;
116         GlobalE2node_gNB_ID_t *globalE2node_gNB_ID =
117             (GlobalE2node_gNB_ID_t *) calloc (1, sizeof (GlobalE2node_gNB_ID_t));
118         globalE2node_gNB_ID->global_gNB_ID.plmn_id = plmnid->GetValue ();
119         globalE2node_gNB_ID->global_gNB_ID.gnb_id.present = GNB_ID_Choice_PR_gnb_ID;
120         globalE2node_gNB_ID->global_gNB_ID.gnb_id.choice.gnb_ID = cellId_bstring->GetValue ();
121         ind_header->id_GlobalE2node_ID.choice.gNB = globalE2node_gNB_ID;
122       }
123       break;
124
125       case eNB: {
126         static int sizeEnb =
127             3; // 3GPP TS 36.413 version 14.8.0 Release 14, Section 9.2.1.37 Global eNB ID
128         static int unsedSizeEnb = 4;
129         
130         cellId_bstring = Create<BitString> (values.m_gnbId, sizeEnb, unsedSizeEnb);
131         
132         ind_header->id_GlobalE2node_ID.present = GlobalE2node_ID_PR_eNB;
133         GlobalE2node_eNB_ID_t *globalE2node_eNB_ID =
134             (GlobalE2node_eNB_ID_t *) calloc (1, sizeof (GlobalE2node_eNB_ID_t));
135         globalE2node_eNB_ID->global_eNB_ID.pLMN_Identity = plmnid->GetValue ();
136         globalE2node_eNB_ID->global_eNB_ID.eNB_ID.present = ENB_ID_PR_macro_eNB_ID;
137         globalE2node_eNB_ID->global_eNB_ID.eNB_ID.choice.macro_eNB_ID = cellId_bstring->GetValue ();
138         ind_header->id_GlobalE2node_ID.choice.eNB = globalE2node_eNB_ID;
139       }
140       break;
141
142       case ng_eNB: {
143         static int sizeEnb =
144             3; // 3GPP TS 36.413 version 14.8.0 Release 14, Section 9.2.1.37 Global eNB ID
145         static int unsedSizeEnb = 4;
146
147         cellId_bstring = Create<BitString> (values.m_gnbId, sizeEnb, unsedSizeEnb);
148
149         ind_header->id_GlobalE2node_ID.present = GlobalE2node_ID_PR_ng_eNB;
150         GlobalE2node_ng_eNB_ID_t *globalE2node_ng_eNB_ID =
151             (GlobalE2node_ng_eNB_ID_t *) calloc (1, sizeof (GlobalE2node_ng_eNB_ID_t));
152
153         globalE2node_ng_eNB_ID->global_ng_eNB_ID.plmn_id = plmnid->GetValue ();
154         globalE2node_ng_eNB_ID->global_ng_eNB_ID.enb_id.present = ENB_ID_Choice_PR_enb_ID_macro;
155         globalE2node_ng_eNB_ID->global_ng_eNB_ID.enb_id.choice.enb_ID_macro =
156             cellId_bstring->GetValue ();
157         ind_header->id_GlobalE2node_ID.choice.ng_eNB = globalE2node_ng_eNB_ID;
158       }
159       break;
160
161       case en_gNB: {
162         static int sizeGnb = 4; // 3GPP Specs
163         cellId_bstring = Create<BitString> (values.m_gnbId, sizeGnb);
164
165         ind_header->id_GlobalE2node_ID.present = GlobalE2node_ID_PR_en_gNB;
166         GlobalE2node_en_gNB_ID_t *globalE2node_en_gNB_ID =
167             (GlobalE2node_en_gNB_ID_t *) calloc (1, sizeof (GlobalE2node_en_gNB_ID_t));
168         globalE2node_en_gNB_ID->global_gNB_ID.pLMN_Identity = plmnid->GetValue ();
169         globalE2node_en_gNB_ID->global_gNB_ID.gNB_ID.present = ENGNB_ID_PR_gNB_ID;
170         globalE2node_en_gNB_ID->global_gNB_ID.gNB_ID.choice.gNB_ID = cellId_bstring->GetValue ();
171         ind_header->id_GlobalE2node_ID.choice.en_gNB = globalE2node_en_gNB_ID;
172       }
173       break;
174
175     default:
176       NS_FATAL_ERROR (
177           "Unrecognized node type for KpmRicIndicationHeader, value passed: " << m_nodeType);
178       break;
179     }
180
181     NS_LOG_DEBUG ("Timestamp received: " << values.m_timestamp);
182     long bigEndianTimestamp = htobe64 (values.m_timestamp);
183     NS_LOG_DEBUG ("Timestamp inverted: " << bigEndianTimestamp);
184     
185     Ptr<OctetString> ts = Create<OctetString> ((void *) &bigEndianTimestamp, TIMESTAMP_LIMIT_SIZE);
186     //NS_LOG_INFO (xer_fprint (stderr, &asn_DEF_OCTET_STRING, ts->GetPointer() ));
187     
188     // Ptr<OctetString> ts2 = Create<OctetString> ((void *) &values.m_timestamp, TIMESTAMP_LIMIT_SIZE);
189     // NS_LOG_INFO (xer_fprint (stderr, &asn_DEF_OCTET_STRING, ts2->GetPointer()));
190
191     ind_header->collectionStartTime = ts->GetValue ();
192
193
194     NS_LOG_INFO (xer_fprint (stderr, &asn_DEF_E2SM_KPM_IndicationHeader_Format1, ind_header));
195
196     descriptor->present = E2SM_KPM_IndicationHeader_PR_indicationHeader_Format1;
197     descriptor->choice.indicationHeader_Format1 = ind_header;
198
199     Encode (descriptor);
200     ASN_STRUCT_FREE (asn_DEF_E2SM_KPM_IndicationHeader_Format1, ind_header);
201     free (globalE2nodeIdBuf);
202     // TraceMessage (&asn_DEF_E2SM_KPM_IndicationHeader, header, "RIC Indication Header");
203 }
204
205 KpmIndicationMessage::KpmIndicationMessage (KpmIndicationMessageValues values)
206 {
207   E2SM_KPM_IndicationMessage_t *descriptor = new E2SM_KPM_IndicationMessage_t ();
208   CheckConstraints (values);
209   FillAndEncodeKpmIndicationMessage (descriptor, values);
210   delete descriptor;
211 }
212
213 KpmIndicationMessage::~KpmIndicationMessage ()
214 {
215   free (m_buffer);
216   m_size = 0;
217 }
218
219 void
220 KpmIndicationMessage::CheckConstraints (KpmIndicationMessageValues values)
221 {
222   // TODO remove?
223   // if (values.m_crnti.length () != 2)
224   //   {
225   //     NS_FATAL_ERROR ("C-RNTI should have length 2");
226   //   }
227   // if (values.m_plmId.length () != 3)
228   //   {
229   //     NS_FATAL_ERROR ("PLMID should have length 3");
230   //   }
231   // if (values.m_nrCellId.length () != 5)
232   //   {
233   //     NS_FATAL_ERROR ("NR Cell ID should have length 5");
234   //   }
235   // TODO add other constraints
236 }
237
238 void
239 KpmIndicationMessage::Encode (E2SM_KPM_IndicationMessage_t *descriptor)
240 {
241   asn_codec_ctx_t *opt_cod = 0; // disable stack bounds checking
242   asn_encode_to_new_buffer_result_s encodedMsg = asn_encode_to_new_buffer (
243       opt_cod, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2SM_KPM_IndicationMessage, descriptor);
244
245   if (encodedMsg.result.encoded < 0)
246     {
247       NS_FATAL_ERROR ("Error during the encoding of the RIC Indication Message, errno: "
248                       << strerror (errno) << ", failed_type " << encodedMsg.result.failed_type->name
249                       << ", structure_ptr " << encodedMsg.result.structure_ptr);
250     }
251
252   m_buffer = encodedMsg.buffer;
253   m_size = encodedMsg.result.encoded;
254 }
255
256 void
257 KpmIndicationMessage::FillPmContainer (PF_Container_t *ranContainer, Ptr<PmContainerValues> values)
258 {
259   Ptr<OCuUpContainerValues> cuUpVal = DynamicCast<OCuUpContainerValues> (values);
260   Ptr<OCuCpContainerValues> cuCpVal = DynamicCast<OCuCpContainerValues> (values);
261   Ptr<ODuContainerValues> duVal = DynamicCast<ODuContainerValues> (values);
262
263   if (cuUpVal)
264     {
265       FillOCuUpContainer (ranContainer, cuUpVal);
266     }
267   else if (cuCpVal)
268     {
269       FillOCuCpContainer (ranContainer, cuCpVal);
270     }
271   else if (duVal)
272    {
273      FillODuContainer (ranContainer, duVal);
274    }
275   else
276     {
277       NS_FATAL_ERROR ("Unknown PM Container type");
278     }
279 }
280
281 void
282 KpmIndicationMessage::FillOCuUpContainer (PF_Container_t *ranContainer,
283                                           Ptr<OCuUpContainerValues> values)
284 {
285   OCUUP_PF_Container_t* ocuup = (OCUUP_PF_Container_t*) calloc (1, sizeof (OCUUP_PF_Container_t));
286   PF_ContainerListItem_t* pcli = (PF_ContainerListItem_t*) calloc (1, sizeof (PF_ContainerListItem_t));
287   pcli->interface_type = NI_Type_x2_u;
288   
289   CUUPMeasurement_Container_t* cuuppmc = (CUUPMeasurement_Container_t*) calloc (1, sizeof (CUUPMeasurement_Container_t)); 
290   PlmnID_Item_t* plmnItem = (PlmnID_Item_t*) calloc (1, sizeof (PlmnID_Item_t)); 
291   Ptr<OctetString> plmnidstr = Create<OctetString> (values->m_plmId, 3);
292   plmnItem->pLMN_Identity = plmnidstr->GetValue ();
293   
294   EPC_CUUP_PM_Format_t* cuuppmf = (EPC_CUUP_PM_Format_t*) calloc (1, sizeof (EPC_CUUP_PM_Format_t));
295   plmnItem->cu_UP_PM_EPC = cuuppmf;
296   PerQCIReportListItemFormat_t* pqrli = (PerQCIReportListItemFormat_t*) calloc (1, sizeof (PerQCIReportListItemFormat_t));
297   pqrli->drbqci = 0;
298
299   INTEGER_t *pDCPBytesDL = (INTEGER_t *) calloc (1, sizeof (INTEGER_t));
300   INTEGER_t *pDCPBytesUL = (INTEGER_t *) calloc (1, sizeof (INTEGER_t));
301
302   asn_long2INTEGER (pDCPBytesDL, values->m_pDCPBytesDL);
303   asn_long2INTEGER (pDCPBytesUL, values->m_pDCPBytesUL);
304
305   pqrli->pDCPBytesDL = pDCPBytesDL;
306   pqrli->pDCPBytesUL = pDCPBytesUL;
307
308   ASN_SEQUENCE_ADD (&cuuppmf->perQCIReportList_cuup.list, pqrli);
309
310   ASN_SEQUENCE_ADD (&cuuppmc->plmnList.list, plmnItem);
311
312   pcli->o_CU_UP_PM_Container = *cuuppmc;
313   ASN_SEQUENCE_ADD (&ocuup->pf_ContainerList, pcli);
314   ranContainer->choice.oCU_UP = ocuup;
315   ranContainer->present = PF_Container_PR_oCU_UP;
316
317   free (cuuppmc);
318 }
319
320 void
321 KpmIndicationMessage::FillOCuCpContainer (PF_Container_t *ranContainer,
322                                           Ptr<OCuCpContainerValues> values)
323 {
324   OCUCP_PF_Container_t *ocucp = (OCUCP_PF_Container_t *) calloc (1, sizeof(OCUCP_PF_Container_t));
325   long *numActiveUes = (long *) calloc (1, sizeof (long));
326   *numActiveUes = long(values->m_numActiveUes);
327   ocucp->cu_CP_Resource_Status.numberOfActive_UEs = numActiveUes;
328   ranContainer->choice.oCU_CP = ocucp;
329   ranContainer->present = PF_Container_PR_oCU_CP;
330 }
331
332 void
333 KpmIndicationMessage::FillODuContainer (PF_Container_t *ranContainer,
334                                         Ptr<ODuContainerValues> values)
335 {
336   ODU_PF_Container_t *odu = (ODU_PF_Container_t *) calloc (1, sizeof (ODU_PF_Container_t));
337   
338   for (auto cellReport : values->m_cellResourceReportItems)
339     {
340       NS_LOG_LOGIC ("O-DU: Add Cell Resource Report Item");
341       CellResourceReportListItem_t *crrli =
342           (CellResourceReportListItem_t *) calloc (1, sizeof (CellResourceReportListItem_t));
343
344       Ptr<OctetString> plmnid = Create<OctetString> (cellReport->m_plmId, 3);
345       Ptr<NrCellId> nrcellid = Create<NrCellId> (cellReport->m_nrCellId);
346       crrli->nRCGI.pLMN_Identity = plmnid->GetValue ();
347       crrli->nRCGI.nRCellIdentity = nrcellid->GetValue ();
348
349       long *dlAvailablePrbs = (long *) calloc (1, sizeof (long));
350       *dlAvailablePrbs = cellReport->dlAvailablePrbs;
351       crrli->dl_TotalofAvailablePRBs = dlAvailablePrbs;
352       
353       long *ulAvailablePrbs = (long *) calloc (1, sizeof (long));
354       *ulAvailablePrbs = cellReport->ulAvailablePrbs;
355       crrli->ul_TotalofAvailablePRBs = ulAvailablePrbs;
356       ASN_SEQUENCE_ADD (&odu->cellResourceReportList.list, crrli);
357       
358       for (auto servedPlmnCell : cellReport->m_servedPlmnPerCellItems)
359         {
360           NS_LOG_LOGIC ("O-DU: Add Served Plmn Per Cell Item");
361           ServedPlmnPerCellListItem_t *sppcl =
362               (ServedPlmnPerCellListItem_t *) calloc (1, sizeof (ServedPlmnPerCellListItem_t));
363           Ptr<OctetString> servedPlmnId = Create<OctetString> (servedPlmnCell->m_plmId, 3);
364           sppcl->pLMN_Identity = servedPlmnId->GetValue ();
365           
366           EPC_DU_PM_Container_t *edpc =
367               (EPC_DU_PM_Container_t *) calloc (1, sizeof (EPC_DU_PM_Container_t));
368
369           for (auto perQciReportItem : servedPlmnCell->m_perQciReportItems)
370             {
371               NS_LOG_LOGIC ("O-DU: Add Per QCI Report Item");
372               PerQCIReportListItem_t *pqrl =
373                   (PerQCIReportListItem_t *) calloc (1, sizeof (PerQCIReportListItem_t));
374               pqrl->qci = perQciReportItem->m_qci;
375               
376               NS_ABORT_MSG_IF ((perQciReportItem->m_dlPrbUsage < 0) | (perQciReportItem->m_dlPrbUsage > 100), 
377                               "As per ASN definition, dl_PRBUsage should be between 0 and 100");
378               long *dlUsedPrbs = (long *) calloc (1, sizeof (long));
379               *dlUsedPrbs = perQciReportItem->m_dlPrbUsage;
380               pqrl->dl_PRBUsage = dlUsedPrbs;
381               NS_LOG_LOGIC ("DL PRBs " << dlUsedPrbs);
382               
383               NS_ABORT_MSG_IF ((perQciReportItem->m_ulPrbUsage < 0) | (perQciReportItem->m_ulPrbUsage > 100), 
384                               "As per ASN definition, ul_PRBUsage should be between 0 and 100");
385               long *ulUsedPrbs = (long *) calloc (1, sizeof (long));
386               *ulUsedPrbs = perQciReportItem->m_ulPrbUsage;
387               pqrl->ul_PRBUsage = ulUsedPrbs;
388               ASN_SEQUENCE_ADD (&edpc->perQCIReportList_du.list, pqrl);
389             }
390
391           sppcl->du_PM_EPC = edpc;
392           ASN_SEQUENCE_ADD (&crrli->servedPlmnPerCellList.list, sppcl);
393         }
394     }
395   ranContainer->choice.oDU = odu;
396   ranContainer->present = PF_Container_PR_oDU;
397 }
398
399 void
400 KpmIndicationMessage::FillAndEncodeKpmIndicationMessage (E2SM_KPM_IndicationMessage_t *descriptor,
401                                                          KpmIndicationMessageValues values)
402 {
403   // Create and fill the RAN Container
404   PF_Container_t *ranContainer = (PF_Container_t *) calloc (1, sizeof (PF_Container_t));
405   FillPmContainer (ranContainer, values.m_pmContainerValues);
406
407   //------- now fill the message
408   PM_Containers_Item_t *containers_list =
409       (PM_Containers_Item_t *) calloc (1, sizeof (PM_Containers_Item_t));
410   containers_list->performanceContainer = ranContainer;
411
412   E2SM_KPM_IndicationMessage_Format1_t *format = (E2SM_KPM_IndicationMessage_Format1_t *) calloc (
413       1, sizeof (E2SM_KPM_IndicationMessage_Format1_t));
414
415   ASN_SEQUENCE_ADD (&format->pm_Containers.list, containers_list);
416
417   // Cell Object ID
418   CellObjectID_t *cellObjectID = (CellObjectID_t *) calloc (1, sizeof (CellObjectID_t));
419   cellObjectID->size = values.m_cellObjectId.length ();
420   cellObjectID->buf = (uint8_t *) calloc (1, cellObjectID->size);
421   memcpy (cellObjectID->buf, values.m_cellObjectId.c_str (), values.m_cellObjectId.length ());
422   format->cellObjectID = *cellObjectID;
423   
424   // Measurement Information List
425   if (values.m_cellMeasurementItems)
426   {
427       format->list_of_PM_Information = (E2SM_KPM_IndicationMessage_Format1::
428                                         E2SM_KPM_IndicationMessage_Format1__list_of_PM_Information *) 
429                                         calloc (1, sizeof (E2SM_KPM_IndicationMessage_Format1::
430                                         E2SM_KPM_IndicationMessage_Format1__list_of_PM_Information));
431     for (auto item : values.m_cellMeasurementItems->GetItems ())
432     {
433       ASN_SEQUENCE_ADD (&format->list_of_PM_Information->list, item->GetPointer ());
434     }
435   }
436   
437   // List of matched UEs
438   if (values.m_ueIndications.size () > 0)
439   {
440     format->list_of_matched_UEs = (E2SM_KPM_IndicationMessage_Format1_t::E2SM_KPM_IndicationMessage_Format1__list_of_matched_UEs*) 
441                                    calloc (1, sizeof (E2SM_KPM_IndicationMessage_Format1_t::E2SM_KPM_IndicationMessage_Format1__list_of_matched_UEs));
442
443
444     for (auto ueIndication : values.m_ueIndications)
445       {
446         PerUE_PM_Item_t *perUEItem = (PerUE_PM_Item_t *) calloc (1, sizeof (PerUE_PM_Item_t));
447
448         // UE Identity
449         perUEItem->ueId = ueIndication->GetId ();
450         // xer_fprint (stderr, &asn_DEF_UE_Identity, &perUEItem->ueId);
451         // NS_LOG_UNCOND ("Values " << ueIndication->m_drbIPLateDlUEID);
452
453         // List of Measurements PM information
454         perUEItem->list_of_PM_Information =
455             (PerUE_PM_Item::PerUE_PM_Item__list_of_PM_Information *) calloc (
456                 1, sizeof (PerUE_PM_Item::PerUE_PM_Item__list_of_PM_Information));
457
458         for (auto measurementItem : ueIndication->GetItems ())
459         {
460           ASN_SEQUENCE_ADD (&perUEItem->list_of_PM_Information->list,
461             measurementItem->GetPointer ());
462         }
463         ASN_SEQUENCE_ADD (&format->list_of_matched_UEs->list, perUEItem);
464       }
465   }
466
467   descriptor->present = E2SM_KPM_IndicationMessage_PR_indicationMessage_Format1;
468   descriptor->choice.indicationMessage_Format1 = format;
469   
470   
471   NS_LOG_INFO (xer_fprint (stderr, &asn_DEF_E2SM_KPM_IndicationMessage_Format1, format));
472
473   // xer_fprint (stderr, &asn_DEF_PF_Container, ranContainer);
474   Encode (descriptor);
475
476   free (cellObjectID);
477   // free (ranContainer);
478   ASN_STRUCT_FREE (asn_DEF_E2SM_KPM_IndicationMessage_Format1, format);
479 }
480
481 MeasurementItemList::MeasurementItemList ()
482 {
483   m_id = NULL;
484 }
485
486 MeasurementItemList::MeasurementItemList (std::string id)
487 {
488   m_id = Create<OctetString> (id, id.length ());
489 }
490
491 MeasurementItemList::~MeasurementItemList (){};
492
493 std::vector<Ptr<MeasurementItem>>
494 MeasurementItemList::GetItems ()
495 {
496   return m_items;
497 }
498
499 OCTET_STRING_t
500 MeasurementItemList::GetId ()
501 {
502   NS_ABORT_IF (m_id == NULL);
503   return m_id->GetValue ();
504 }
505
506 } // namespace ns3