1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
3 * Copyright (c) 2022 Northeastern University
4 * Copyright (c) 2022 Sapienza, University of Rome
5 * Copyright (c) 2022 University of Padova
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;
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.
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
20 * Author: Andrea Lacava <thecave003@gmail.com>
21 * Tommaso Zugno <tommasozugno@gmail.com>
22 * Michele Polese <michele.polese@gmail.com>
25 #include <ns3/kpm-indication.h>
26 #include <ns3/asn1c-types.h>
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"
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"
58 NS_LOG_COMPONENT_DEFINE ("KpmIndication");
60 KpmIndicationHeader::KpmIndicationHeader (GlobalE2nodeType nodeType,KpmRicIndicationHeaderValues values)
62 m_nodeType = nodeType;
63 E2SM_KPM_IndicationHeader_t *descriptor = new E2SM_KPM_IndicationHeader_t;
64 FillAndEncodeKpmRicIndicationHeader (descriptor, values);
68 KpmIndicationHeader::~KpmIndicationHeader ()
70 NS_LOG_FUNCTION (this);
76 KpmIndicationHeader::Encode (E2SM_KPM_IndicationHeader_t *descriptor)
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);
82 if (encodedHeader.result.encoded < 0)
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);
90 m_buffer = encodedHeader.buffer;
91 m_size = encodedHeader.result.encoded;
95 KpmIndicationHeader::FillAndEncodeKpmRicIndicationHeader (E2SM_KPM_IndicationHeader_t *descriptor,
96 KpmRicIndicationHeaderValues values)
99 E2SM_KPM_IndicationHeader_Format1_t *ind_header = (E2SM_KPM_IndicationHeader_Format1_t *) calloc (
100 1, sizeof (E2SM_KPM_IndicationHeader_Format1_t));
102 Ptr<OctetString> plmnid = Create<OctetString> (values.m_plmId, 3);
103 Ptr<BitString> cellId_bstring;
105 GlobalE2node_ID *globalE2nodeIdBuf = (GlobalE2node_ID *) calloc (1, sizeof (GlobalE2node_ID));
106 ind_header->id_GlobalE2node_ID = *globalE2nodeIdBuf;
111 static int sizeGnb = 4; // 3GPP Specs
113 cellId_bstring = Create<BitString> (values.m_gnbId, sizeGnb);
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;
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;
130 cellId_bstring = Create<BitString> (values.m_gnbId, sizeEnb, unsedSizeEnb);
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;
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;
147 cellId_bstring = Create<BitString> (values.m_gnbId, sizeEnb, unsedSizeEnb);
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));
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;
162 static int sizeGnb = 4; // 3GPP Specs
163 cellId_bstring = Create<BitString> (values.m_gnbId, sizeGnb);
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;
177 "Unrecognized node type for KpmRicIndicationHeader, value passed: " << m_nodeType);
181 NS_LOG_DEBUG ("Timestamp received: " << values.m_timestamp);
182 long bigEndianTimestamp = htobe64 (values.m_timestamp);
183 NS_LOG_DEBUG ("Timestamp inverted: " << bigEndianTimestamp);
185 Ptr<OctetString> ts = Create<OctetString> ((void *) &bigEndianTimestamp, TIMESTAMP_LIMIT_SIZE);
186 //NS_LOG_INFO (xer_fprint (stderr, &asn_DEF_OCTET_STRING, ts->GetPointer() ));
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()));
191 ind_header->collectionStartTime = ts->GetValue ();
194 NS_LOG_INFO (xer_fprint (stderr, &asn_DEF_E2SM_KPM_IndicationHeader_Format1, ind_header));
196 descriptor->present = E2SM_KPM_IndicationHeader_PR_indicationHeader_Format1;
197 descriptor->choice.indicationHeader_Format1 = ind_header;
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");
205 KpmIndicationMessage::KpmIndicationMessage (KpmIndicationMessageValues values)
207 E2SM_KPM_IndicationMessage_t *descriptor = new E2SM_KPM_IndicationMessage_t ();
208 CheckConstraints (values);
209 FillAndEncodeKpmIndicationMessage (descriptor, values);
213 KpmIndicationMessage::~KpmIndicationMessage ()
220 KpmIndicationMessage::CheckConstraints (KpmIndicationMessageValues values)
223 // if (values.m_crnti.length () != 2)
225 // NS_FATAL_ERROR ("C-RNTI should have length 2");
227 // if (values.m_plmId.length () != 3)
229 // NS_FATAL_ERROR ("PLMID should have length 3");
231 // if (values.m_nrCellId.length () != 5)
233 // NS_FATAL_ERROR ("NR Cell ID should have length 5");
235 // TODO add other constraints
239 KpmIndicationMessage::Encode (E2SM_KPM_IndicationMessage_t *descriptor)
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);
245 if (encodedMsg.result.encoded < 0)
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);
252 m_buffer = encodedMsg.buffer;
253 m_size = encodedMsg.result.encoded;
257 KpmIndicationMessage::FillPmContainer (PF_Container_t *ranContainer, Ptr<PmContainerValues> values)
259 Ptr<OCuUpContainerValues> cuUpVal = DynamicCast<OCuUpContainerValues> (values);
260 Ptr<OCuCpContainerValues> cuCpVal = DynamicCast<OCuCpContainerValues> (values);
261 Ptr<ODuContainerValues> duVal = DynamicCast<ODuContainerValues> (values);
265 FillOCuUpContainer (ranContainer, cuUpVal);
269 FillOCuCpContainer (ranContainer, cuCpVal);
273 FillODuContainer (ranContainer, duVal);
277 NS_FATAL_ERROR ("Unknown PM Container type");
282 KpmIndicationMessage::FillOCuUpContainer (PF_Container_t *ranContainer,
283 Ptr<OCuUpContainerValues> values)
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;
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 ();
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));
299 INTEGER_t *pDCPBytesDL = (INTEGER_t *) calloc (1, sizeof (INTEGER_t));
300 INTEGER_t *pDCPBytesUL = (INTEGER_t *) calloc (1, sizeof (INTEGER_t));
302 asn_long2INTEGER (pDCPBytesDL, values->m_pDCPBytesDL);
303 asn_long2INTEGER (pDCPBytesUL, values->m_pDCPBytesUL);
305 pqrli->pDCPBytesDL = pDCPBytesDL;
306 pqrli->pDCPBytesUL = pDCPBytesUL;
308 ASN_SEQUENCE_ADD (&cuuppmf->perQCIReportList_cuup.list, pqrli);
310 ASN_SEQUENCE_ADD (&cuuppmc->plmnList.list, plmnItem);
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;
321 KpmIndicationMessage::FillOCuCpContainer (PF_Container_t *ranContainer,
322 Ptr<OCuCpContainerValues> values)
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;
333 KpmIndicationMessage::FillODuContainer (PF_Container_t *ranContainer,
334 Ptr<ODuContainerValues> values)
336 ODU_PF_Container_t *odu = (ODU_PF_Container_t *) calloc (1, sizeof (ODU_PF_Container_t));
338 for (auto cellReport : values->m_cellResourceReportItems)
340 NS_LOG_LOGIC ("O-DU: Add Cell Resource Report Item");
341 CellResourceReportListItem_t *crrli =
342 (CellResourceReportListItem_t *) calloc (1, sizeof (CellResourceReportListItem_t));
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 ();
349 long *dlAvailablePrbs = (long *) calloc (1, sizeof (long));
350 *dlAvailablePrbs = cellReport->dlAvailablePrbs;
351 crrli->dl_TotalofAvailablePRBs = dlAvailablePrbs;
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);
358 for (auto servedPlmnCell : cellReport->m_servedPlmnPerCellItems)
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 ();
366 EPC_DU_PM_Container_t *edpc =
367 (EPC_DU_PM_Container_t *) calloc (1, sizeof (EPC_DU_PM_Container_t));
369 for (auto perQciReportItem : servedPlmnCell->m_perQciReportItems)
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;
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);
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);
391 sppcl->du_PM_EPC = edpc;
392 ASN_SEQUENCE_ADD (&crrli->servedPlmnPerCellList.list, sppcl);
395 ranContainer->choice.oDU = odu;
396 ranContainer->present = PF_Container_PR_oDU;
400 KpmIndicationMessage::FillAndEncodeKpmIndicationMessage (E2SM_KPM_IndicationMessage_t *descriptor,
401 KpmIndicationMessageValues values)
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);
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;
412 E2SM_KPM_IndicationMessage_Format1_t *format = (E2SM_KPM_IndicationMessage_Format1_t *) calloc (
413 1, sizeof (E2SM_KPM_IndicationMessage_Format1_t));
415 ASN_SEQUENCE_ADD (&format->pm_Containers.list, containers_list);
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;
424 // Measurement Information List
425 if (values.m_cellMeasurementItems)
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 ())
433 ASN_SEQUENCE_ADD (&format->list_of_PM_Information->list, item->GetPointer ());
437 // List of matched UEs
438 if (values.m_ueIndications.size () > 0)
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));
444 for (auto ueIndication : values.m_ueIndications)
446 PerUE_PM_Item_t *perUEItem = (PerUE_PM_Item_t *) calloc (1, sizeof (PerUE_PM_Item_t));
449 perUEItem->ueId = ueIndication->GetId ();
450 // xer_fprint (stderr, &asn_DEF_UE_Identity, &perUEItem->ueId);
451 // NS_LOG_UNCOND ("Values " << ueIndication->m_drbIPLateDlUEID);
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));
458 for (auto measurementItem : ueIndication->GetItems ())
460 ASN_SEQUENCE_ADD (&perUEItem->list_of_PM_Information->list,
461 measurementItem->GetPointer ());
463 ASN_SEQUENCE_ADD (&format->list_of_matched_UEs->list, perUEItem);
467 descriptor->present = E2SM_KPM_IndicationMessage_PR_indicationMessage_Format1;
468 descriptor->choice.indicationMessage_Format1 = format;
471 NS_LOG_INFO (xer_fprint (stderr, &asn_DEF_E2SM_KPM_IndicationMessage_Format1, format));
473 // xer_fprint (stderr, &asn_DEF_PF_Container, ranContainer);
477 // free (ranContainer);
478 ASN_STRUCT_FREE (asn_DEF_E2SM_KPM_IndicationMessage_Format1, format);
481 MeasurementItemList::MeasurementItemList ()
486 MeasurementItemList::MeasurementItemList (std::string id)
488 m_id = Create<OctetString> (id, id.length ());
491 MeasurementItemList::~MeasurementItemList (){};
493 std::vector<Ptr<MeasurementItem>>
494 MeasurementItemList::GetItems ()
500 MeasurementItemList::GetId ()
502 NS_ABORT_IF (m_id == NULL);
503 return m_id->GetValue ();