SIM-119: Update value of MeasurementTypeName and MeasurementTypeID to constraint
[sim/e2-interface.git] / e2sim / e2sm_examples / kpm_e2sm / src / kpm / kpm_callbacks.cpp
1 /*****************************************************************************
2 #                                                                            *
3 # Copyright 2020 AT&T Intellectual Property                                  *
4 #                                                                            *
5 # Licensed under the Apache License, Version 2.0 (the "License");            *
6 # you may not use this file except in compliance with the License.           *
7 # You may obtain a copy of the License at                                    *
8 #                                                                            *
9 #      http://www.apache.org/licenses/LICENSE-2.0                            *
10 #                                                                            *
11 # Unless required by applicable law or agreed to in writing, software        *
12 # distributed under the License is distributed on an "AS IS" BASIS,          *
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
14 # See the License for the specific language governing permissions and        *
15 # limitations under the License.                                             *
16 #                                                                            *
17 ******************************************************************************/
18
19 #include <iostream>
20 #include <fstream>
21 #include <vector>
22
23
24
25 extern "C" {
26   #include "OCTET_STRING.h"
27   #include "asn_application.h"
28   #include "E2SM-KPM-IndicationMessage.h"
29   #include "E2SM-KPM-RANfunction-Description.h"
30   #include "E2SM-KPM-IndicationHeader-Format1.h"
31   #include "E2SM-KPM-IndicationHeader.h"
32   #include "E2AP-PDU.h"
33   #include "RICsubscriptionRequest.h"
34   #include "RICsubscriptionResponse.h"
35   #include "RICactionType.h"
36   #include "ProtocolIE-Field.h"
37   #include "ProtocolIE-SingleContainer.h"
38   #include "InitiatingMessage.h"
39 }
40
41 #include "kpm_callbacks.hpp"
42 #include "encode_kpm.hpp"
43
44 #include "encode_e2apv1.hpp"
45
46 #include <nlohmann/json.hpp>
47 #include <thread>
48 #include <chrono>
49
50 #include "viavi_connector.hpp"
51 #include "errno.h"
52 #include "e2sim_defs.h"
53 #include <cstdlib>
54
55 using json = nlohmann::json;
56
57 using namespace std;
58 class E2Sim;
59 int gFuncId;
60
61 E2Sim e2sim;
62
63 int main(int argc, char* argv[]) {
64
65   LOG_I("Starting KPM simulator");
66
67   uint8_t *nrcellid_buf = (uint8_t*)calloc(1,5);
68   nrcellid_buf[0] = 0x22;
69   nrcellid_buf[1] = 0x5B;
70   nrcellid_buf[2] = 0xD6;
71   nrcellid_buf[3] = 0x00;
72   nrcellid_buf[4] = 0x70;
73
74   asn_codec_ctx_t *opt_cod;
75   
76   E2SM_KPM_RANfunction_Description_t *ranfunc_desc =
77     (E2SM_KPM_RANfunction_Description_t*)calloc(1,sizeof(E2SM_KPM_RANfunction_Description_t));
78   encode_kpm_function_description(ranfunc_desc);
79   
80   uint8_t e2smbuffer[8192] = {0, };
81   size_t e2smbuffer_size = 8192;
82   
83   asn_enc_rval_t er =
84     asn_encode_to_buffer(opt_cod,
85                          ATS_ALIGNED_BASIC_PER,
86                          &asn_DEF_E2SM_KPM_RANfunction_Description,
87                          ranfunc_desc, e2smbuffer, e2smbuffer_size);
88   
89   if(er.encoded == -1) {
90         LOG_I("Failed to serialize function description data. Detail: %s.", asn_DEF_E2SM_KPM_RANfunction_Description.name);
91   } else if(er.encoded > e2smbuffer_size) {
92         LOG_I("Buffer of size %zu is too small for %s, need %zu", e2smbuffer_size, asn_DEF_E2SM_KPM_RANfunction_Description.name, er.encoded);
93   }
94
95   uint8_t *ranfuncdesc = (uint8_t*)calloc(1,er.encoded);
96   memcpy(ranfuncdesc, e2smbuffer, er.encoded);
97   
98   OCTET_STRING_t *ranfunc_ostr = (OCTET_STRING_t*)calloc(1,sizeof(OCTET_STRING_t));
99   ranfunc_ostr->buf = (uint8_t*)calloc(1,er.encoded);
100   ranfunc_ostr->size = er.encoded;
101   memcpy(ranfunc_ostr->buf,e2smbuffer,er.encoded);
102
103   const char* func_id_str = std::getenv("RAN_FUNC_ID");
104   ::gFuncId = func_id_str == nullptr ? 0 : std::stoi(func_id_str);
105
106   e2sim.register_e2sm(gFuncId, ranfunc_ostr);
107   e2sim.register_subscription_callback(gFuncId, &callback_kpm_subscription_request);
108   e2sim.run_loop(argc, argv);
109
110 }
111
112 void get_cell_id(uint8_t *nrcellid_buf, char *cid_return_buf) {
113
114   uint8_t nr0 = nrcellid_buf[0] >> 4;
115   uint8_t nr1 = nrcellid_buf[0] << 4;
116   nr1 = nr1 >> 4;
117
118   uint8_t nr2 = nrcellid_buf[1] >> 4;
119   uint8_t nr3 = nrcellid_buf[1] << 4;
120   nr3 = nr3 >> 4;
121
122   uint8_t nr4 = nrcellid_buf[2] >> 4;
123   uint8_t nr5 = nrcellid_buf[2] << 4;
124   nr5 = nr5 >> 4;
125
126   uint8_t nr6 = nrcellid_buf[3] >> 4;
127   uint8_t nr7 = nrcellid_buf[3] << 4;
128   nr7 = nr7 >> 4;
129
130   uint8_t nr8 = nrcellid_buf[4] >> 4;
131   
132   sprintf(cid_return_buf, "373437%d%d%d%d%d%d%d%d%d", nr0,nr1,nr2,nr3,nr4,nr5,nr6,nr7,nr8);  
133
134 }
135
136 void run_report_loop(long requestorId, long instanceId, long ranFunctionId, long actionId)
137 {
138   std::filebuf reports_json;
139   std::streambuf *input_filebuf = &reports_json;
140
141   std::unique_ptr<viavi::RICTesterReceiver> viavi_connector;
142   if (!reports_json.open("/playpen/src/reports.json", std::ios::in)) {
143     std::cerr << "Can't open reports.json, enabling VIAVI connector instead..." << endl;
144         viavi_connector.reset(new viavi::RICTesterReceiver {3001, nullptr});
145         input_filebuf = viavi_connector->get_data_filebuf();
146   }
147
148   std::istream input {input_filebuf};
149
150   long seqNum = 1;
151
152   std::string str;
153   
154   while ( getline(input, str) ) {
155
156     json all_ues_json;
157
158     long fqival = 9;
159     long qcival = 9;
160
161     uint8_t *plmnid_buf = (uint8_t*)"747";
162     uint8_t *sst_buf = (uint8_t*)"1";
163     uint8_t *sd_buf = (uint8_t*)"100";
164     
165
166     LOG_I("Current line: %s", str.c_str());
167
168     bool valid = false;
169
170     try {
171       all_ues_json = json::parse(str);
172       valid = true;
173     } catch (...) {
174       LOG_I("Exception on reading json");
175           exit(1);
176     }
177
178     if (valid) {
179
180       std::string first_key = all_ues_json.begin().key();
181       LOG_I("First key is %s\n", first_key.c_str());
182       
183       if (first_key.compare("ueMeasReport") == 0) {
184
185                 json::json_pointer du_id(std::string("/ueMeasReport/du-id"));
186                 int duid = all_ues_json[du_id].get<int>();
187         
188                 LOG_I("Start sending UE measurement reports with DU id %d", duid);
189
190                 int numMeasReports = (all_ues_json["/ueMeasReport/ueMeasReportList"_json_pointer]).size();
191                 
192                 for (int i = 0; i < numMeasReports; i++) {
193                         int nextCellId;
194                         int nextRsrp;
195                         int nextRsrq;
196                         int nextRssinr;
197                         float tput;
198                         int prb_usage;
199                         std::string ueId;
200
201                         json::json_pointer p001(std::string("/ueMeasReport/ueMeasReportList/") + std::to_string(i) +"/ue-id");
202                         ueId = all_ues_json[p001].get<std::string>();
203
204                         LOG_I("Preparing report data for UE %d with id %s", i, ueId);
205                         
206                         json::json_pointer p0(std::string("/ueMeasReport/ueMeasReportList/") + std::to_string(i) +"/throughput");
207                         tput = all_ues_json[p0].get<float>();
208                         
209                         json::json_pointer p00(std::string("/ueMeasReport/ueMeasReportList/") + std::to_string(i) +"/prb_usage");
210                         prb_usage = all_ues_json[p00].get<int>();
211                         
212                         json::json_pointer p1(std::string("/ueMeasReport/ueMeasReportList/") + std::to_string(i) +"/nrCellIdentity");
213                         nextCellId = all_ues_json[p1].get<int>();
214                         
215                         json::json_pointer p2(std::string("/ueMeasReport/ueMeasReportList/") + std::to_string(i) +"/servingCellRfReport/rsrp");
216                         nextRsrp = all_ues_json[p2].get<int>();
217                         
218                         json::json_pointer p3(std::string("/ueMeasReport/ueMeasReportList/") + std::to_string(i) +"/servingCellRfReport/rsrq");
219                         nextRsrq = all_ues_json[p3].get<int>();
220                         
221                         json::json_pointer p4(std::string("/ueMeasReport/ueMeasReportList/") + std::to_string(i) +"/servingCellRfReport/rssinr");
222                         nextRssinr = all_ues_json[p4].get<int>();
223                         
224                         json::json_pointer p5(std::string("/ueMeasReport/ueMeasReportList/") + std::to_string(i) +"/neighbourCellList");
225                         
226                         uint8_t crnti_buf[3] = {0, };
227
228                         if (ueId.find("Pedestrian") != string::npos) {
229                                 std::string ind = ueId.substr(11);
230                                 int indval = std::stoi(ind);
231
232                                 if (indval < 10) {
233                                 crnti_buf[1] = indval;
234                                 crnti_buf[0] = 0;
235                                 } else {
236                                 crnti_buf[0] = indval/10;
237                                 crnti_buf[1] = indval % 10;
238                                 }
239                                 
240                         } else if (ueId.find("Car") != string::npos) {
241                                 crnti_buf[0] = 4;
242                                 crnti_buf[1] = 1;
243                         }
244                                         
245                         std::string serving_str = "{\"rsrp\": " + std::to_string(nextRsrp) + ", \"rsrq\": " +
246                                 std::to_string(nextRsrq) + ", \"rssinr\": " + std::to_string(nextRssinr) + "}";
247                         const uint8_t *serving_buf = reinterpret_cast<const uint8_t*>(serving_str.c_str());     
248                         
249                         int numNeighborCells = (all_ues_json[p5]).size();
250                         
251                         std::string neighbor_str = "[";
252                         
253                         int nextNbCell;
254                         int nextNbRsrp;
255                         int nextNbRsrq;
256                         int nextNbRssinr;
257                         
258                         for (int j = 0; j < numNeighborCells; j++) {
259                                 json::json_pointer p8(std::string("/ueMeasReport/ueMeasReportList/") + std::to_string(i) +"/neighbourCellList/" + std::to_string(j) + "/nbCellIdentity");
260                                 nextNbCell = all_ues_json[p8].get<int>();
261                                 json::json_pointer p9(std::string("/ueMeasReport/ueMeasReportList/") + std::to_string(i)
262                                                 +"/neighbourCellList/" + std::to_string(j) + "/nbCellRfReport/rsrp");
263                                 nextNbRsrp = all_ues_json[p9].get<int>();
264                                 
265                                 json::json_pointer p10(std::string("/ueMeasReport/ueMeasReportList/") + std::to_string(i)
266                                                 +"/neighbourCellList/" + std::to_string(j) + "/nbCellRfReport/rsrq");
267                                 nextNbRsrq = all_ues_json[p10].get<int>();
268                                 
269                                 json::json_pointer p11(std::string("/ueMeasReport/ueMeasReportList/") + std::to_string(i)
270                                                 +"/neighbourCellList/" + std::to_string(j) + "/nbCellRfReport/rssinr");
271                                 nextNbRssinr = all_ues_json[p11].get<int>();
272                                 
273                                 if (j != 0) {
274                                         neighbor_str += ",";
275                                 }
276
277
278                                 uint8_t neighbor_cellid_buf[6] = {0, };
279                                 neighbor_cellid_buf[0] = 0x22;
280                                 neighbor_cellid_buf[1] = 0x5B;
281                                 neighbor_cellid_buf[2] = 0xD6;
282                                 neighbor_cellid_buf[3] = nextNbCell;
283                                 neighbor_cellid_buf[4] = 0x70;
284                                 
285                                 char cid_buf[25] = {0, };
286                                 get_cell_id(neighbor_cellid_buf,cid_buf);
287                                 
288                                 
289                                 neighbor_str += "{\"CID\" : \"" + std::string(cid_buf) + "\", \"Cell-RF\" : {\"rsrp\": " + std::to_string(nextNbRsrp) +
290                                 ", \"rsrq\": " + std::to_string(nextNbRsrq) + ", \"rssinr\": " + std::to_string(nextNbRssinr) + "}}";
291                                 
292                         }
293                         
294                         neighbor_str += "]";
295                         
296                         LOG_I("This is neighbor str %s\n", neighbor_str.c_str());
297                                                                 
298                         const uint8_t *neighbor_buf = reinterpret_cast<const uint8_t*>(neighbor_str.c_str());
299
300
301                         uint8_t nrcellid_buf[6] = {0, };
302                         nrcellid_buf[0] = 0x22;
303                         nrcellid_buf[1] = 0x5B;
304                         nrcellid_buf[2] = 0xD6;
305                         nrcellid_buf[3] = nextCellId;
306                         nrcellid_buf[4] = 0x70;
307
308                         uint8_t gnbid_buf[4] = {0, };
309                         gnbid_buf[0] = 0x22;
310                         gnbid_buf[1] = 0x5B;
311                         gnbid_buf[2] = 0xD6;
312
313                         uint8_t cuupid_buf[2] = {0, };
314                         cuupid_buf[0] = 20000;
315
316                         uint8_t duid_buf[2] = {0, };
317                         duid_buf[0] = 20000;
318
319                         uint8_t *cuupname_buf = (uint8_t*)"GNBCUUP5";     
320                         
321                         
322                         E2SM_KPM_IndicationMessage_t *ind_msg_cucp_ue =
323                                 (E2SM_KPM_IndicationMessage_t*)calloc(1,sizeof(E2SM_KPM_IndicationMessage_t));
324                         
325                         ue_meas_kpm_report_indication_message_initialized(ind_msg_cucp_ue, nrcellid_buf, crnti_buf, serving_buf, neighbor_buf);
326                         
327                         uint8_t e2sm_message_buf_cucp_ue[8192] = {0, };
328                         size_t e2sm_message_buf_size_cucp_ue = 8192;
329                         
330                         asn_codec_ctx_t *opt_cod;
331                         
332                         asn_enc_rval_t er_message_cucp_ue = asn_encode_to_buffer(opt_cod,
333                                                                                 ATS_ALIGNED_BASIC_PER,
334                                                                                 &asn_DEF_E2SM_KPM_IndicationMessage,
335                                                                                 ind_msg_cucp_ue, e2sm_message_buf_cucp_ue, e2sm_message_buf_size_cucp_ue);
336                         
337                         if(er_message_cucp_ue.encoded == -1) {
338                                 LOG_I("Failed to serialize message data. Detail: %s.\n", asn_DEF_E2SM_KPM_IndicationMessage.name);
339                                 exit(1);
340                         } else if(er_message_cucp_ue.encoded > e2sm_message_buf_size_cucp_ue) {
341                                 LOG_I("Buffer of size %zu is too small for %s, need %zu\n", e2sm_message_buf_size_cucp_ue, asn_DEF_E2SM_KPM_IndicationMessage.name, er_message_cucp_ue.encoded);
342                                 exit(1);
343                         } else {
344                                 LOG_I("Encoded UE indication message succesfully, size in bytes: %zu", er_message_cucp_ue.encoded)
345                         }
346
347                         ASN_STRUCT_FREE(asn_DEF_E2SM_KPM_IndicationMessage, ind_msg_cucp_ue); 
348
349                         E2SM_KPM_IndicationHeader_t* ind_header_cucp_ue =
350                                 (E2SM_KPM_IndicationHeader_t*)calloc(1,sizeof(E2SM_KPM_IndicationHeader_t));
351                         kpm_report_indication_header_initialized(ind_header_cucp_ue, plmnid_buf, sst_buf, sd_buf, fqival, qcival, nrcellid_buf, gnbid_buf, 0, cuupid_buf, duid_buf, cuupname_buf);
352
353                         asn_codec_ctx_t *opt_cod1;
354                         uint8_t e2sm_header_buf_cucp_ue[8192] = {0, };
355                         size_t e2sm_header_buf_size_cucp_ue = 8192;
356                         
357                         asn_enc_rval_t er_header_cucp_ue = asn_encode_to_buffer(opt_cod1,
358                                                                                 ATS_ALIGNED_BASIC_PER,
359                                                                                 &asn_DEF_E2SM_KPM_IndicationHeader,
360                                                                                 ind_header_cucp_ue, e2sm_header_buf_cucp_ue, e2sm_header_buf_size_cucp_ue);
361
362                         if(er_header_cucp_ue.encoded == -1) {
363                                 LOG_I("Failed to serialize data. Detail: %s.\n", asn_DEF_E2SM_KPM_IndicationHeader.name);
364                                 exit(1);
365                         } else if(er_header_cucp_ue.encoded > e2sm_header_buf_size_cucp_ue) {
366                                 LOG_I("Buffer of size %zu is too small for %s, need %zu\n", e2sm_header_buf_size_cucp_ue, asn_DEF_E2SM_KPM_IndicationHeader.name, er_header_cucp_ue.encoded);
367                                 exit(1);
368                         } else {
369                                 LOG_I("Encoded UE indication header succesfully, size in bytes: %zu", er_header_cucp_ue.encoded);
370                                 for(int i = 0; i < er_header_cucp_ue.encoded; i ++) {
371                                         printf("%x ", e2sm_header_buf_cucp_ue[i]);
372                                 }
373                                 
374                         }
375                         
376
377                         ASN_STRUCT_FREE(asn_DEF_E2SM_KPM_IndicationHeader, ind_header_cucp_ue);
378                         
379                         E2AP_PDU *pdu_cucp_ue = (E2AP_PDU*)calloc(1,sizeof(E2AP_PDU));
380                         
381                         encoding::generate_e2apv1_indication_request_parameterized(pdu_cucp_ue, requestorId,
382                                                                                         instanceId, ranFunctionId,
383                                                                                         actionId, seqNum, e2sm_header_buf_cucp_ue,
384                                                                                         er_header_cucp_ue.encoded, e2sm_message_buf_cucp_ue,
385                                                                                         er_message_cucp_ue.encoded);
386                         
387                         e2sim.encode_and_send_sctp_data(pdu_cucp_ue);
388                         LOG_I("Measurement report for UE %d has been sent", i);
389                         seqNum++;
390                         std::this_thread::sleep_for (std::chrono::milliseconds(50));
391                 }
392       } else if (first_key.compare("cellMeasReport") == 0) {
393
394                 json::json_pointer du_id(std::string("/cellMeasReport/du-id"));
395                 int duid = all_ues_json[du_id].get<int>();
396         
397                 LOG_I("Start sending Cell measurement reports with DU id %d", duid);
398                 
399                 int numMeasReports = (all_ues_json["/cellMeasReport/cellMeasReportList"_json_pointer]).size();
400                 
401                 for (int i = 0; i < numMeasReports; i++) {
402                         int nextCellId;
403
404                         float bytes_dl;
405                         float bytes_ul;
406                         int prb_dl;
407                         int prb_ul;
408                         int cellid;
409
410                         json::json_pointer p00(std::string("/cellMeasReport/cellMeasReportList/") + std::to_string(i) +"/nrCellIdentity");
411                         cellid = all_ues_json[p00].get<int>();
412
413                         LOG_I("Preparing report data for Cell %d with id %d", i, cellid);
414                         
415                         json::json_pointer p0(std::string("/cellMeasReport/cellMeasReportList/") + std::to_string(i) +"/pdcpByteMeasReport/pdcpBytesDl");
416                         bytes_dl = all_ues_json[p0].get<float>();
417
418                         json::json_pointer p1(std::string("/cellMeasReport/cellMeasReportList/") + std::to_string(i) +"/pdcpByteMeasReport/pdcpBytesUl");
419                         bytes_ul = all_ues_json[p1].get<float>();
420                         
421                         json::json_pointer p2(std::string("/cellMeasReport/cellMeasReportList/") + std::to_string(i) +"/prbMeasReport/availPrbDl");
422                         prb_dl = all_ues_json[p2].get<int>();
423
424                         json::json_pointer p3(std::string("/cellMeasReport/cellMeasReportList/") + std::to_string(i) +"/prbMeasReport/availPrbUl");
425                         prb_ul = all_ues_json[p3].get<int>();
426
427                         
428                         uint8_t *sst_buf = (uint8_t*)"1";
429                         uint8_t *sd_buf = (uint8_t*)"100";
430                         uint8_t *plmnid_buf = (uint8_t*)"747";
431
432                         uint8_t nrcellid_buf[6] = {0, };
433                         nrcellid_buf[0] = 0x22;
434                         nrcellid_buf[1] = 0x5B;
435                         nrcellid_buf[2] = 0xD6;
436                         nrcellid_buf[3] = cellid;
437                         nrcellid_buf[4] = 0x70;
438
439                         uint8_t gnbid_buf[4] = {0, };
440                         gnbid_buf[0] = 0x22;
441                         gnbid_buf[1] = 0x5B;
442                         gnbid_buf[2] = 0xD6;
443
444                         uint8_t cuupid_buf[2] = {0, };
445                         cuupid_buf[0] = 20000;
446
447                         uint8_t duid_buf[2] = {0, };
448                         duid_buf[0] = 20000;
449
450                         uint8_t *cuupname_buf = (uint8_t*)"GNBCUUP5";             
451
452                         //Encoding Style 1 Message Body
453                         
454                         LOG_I("Encoding Style 1 Message body");   
455                         asn_codec_ctx_t *opt_cod2;
456                         
457                         E2SM_KPM_IndicationMessage_t *ind_message_style1 =
458                                 (E2SM_KPM_IndicationMessage_t*)calloc(1,sizeof(E2SM_KPM_IndicationMessage_t));
459                         E2AP_PDU *pdu_style1 = (E2AP_PDU*)calloc(1,sizeof(E2AP_PDU));
460                         
461                         long fiveqi = 7;
462                         long *l_dl_prbs = (long*)calloc(1, sizeof(long));
463                         long *l_ul_prbs = (long*)calloc(1, sizeof(long));
464                         *l_dl_prbs = (long)prb_dl;
465                         *l_ul_prbs = (long)prb_ul;
466                         
467                         cell_meas_kpm_report_indication_message_style_1_initialized(ind_message_style1, fiveqi,
468                                                                 prb_dl, prb_ul, nrcellid_buf, l_dl_prbs, l_ul_prbs);
469                         
470                         uint8_t e2sm_message_buf_style1[8192] = {0, };
471                         size_t e2sm_message_buf_size_style1 = 8192;
472                         
473                         asn_enc_rval_t er_message_style1 = asn_encode_to_buffer(opt_cod2,
474                                                                                 ATS_ALIGNED_BASIC_PER,
475                                                                                 &asn_DEF_E2SM_KPM_IndicationMessage,
476                                                                                 ind_message_style1,
477                                                                                 e2sm_message_buf_style1, e2sm_message_buf_size_style1);
478                         
479                         if(er_message_style1.encoded == -1) {
480                                 LOG_I("Failed to serialize data. Detail: %s.", asn_DEF_E2SM_KPM_IndicationMessage.name);
481                                 exit(1);
482                         } else if(er_message_style1.encoded > e2sm_message_buf_size_style1) {
483                                 LOG_I("Buffer of size %zu is too small for %s, need %zu\n", e2sm_message_buf_size_style1, asn_DEF_E2SM_KPM_IndicationMessage.name, er_message_style1.encoded);
484                                 exit(1);
485                         } else {
486                                 LOG_I("Encoded Cell indication message succesfully, size in bytes: %ld", er_message_style1.encoded)
487                         }
488
489                         ASN_STRUCT_FREE(asn_DEF_E2SM_KPM_IndicationMessage, ind_message_style1);
490                         
491                         uint8_t *cpid_buf2 = (uint8_t*)"CPID";
492                         
493                         E2SM_KPM_IndicationHeader_t* ind_header_style1 =
494                                 (E2SM_KPM_IndicationHeader_t*)calloc(1,sizeof(E2SM_KPM_IndicationHeader_t));
495                         kpm_report_indication_header_initialized(ind_header_style1, plmnid_buf, sst_buf, sd_buf, fqival, qcival, nrcellid_buf, gnbid_buf, 0, cuupid_buf, duid_buf, cuupname_buf);
496
497                         uint8_t e2sm_header_buf_style1[8192] = {0, };
498                         size_t e2sm_header_buf_size_style1 = 8192;
499                         
500                         asn_enc_rval_t er_header_style1 = asn_encode_to_buffer(opt_cod2,
501                                                                                 ATS_ALIGNED_BASIC_PER,
502                                                                                 &asn_DEF_E2SM_KPM_IndicationHeader,
503                                                                                 ind_header_style1,
504                                                                                 e2sm_header_buf_style1, e2sm_header_buf_size_style1);
505
506                         if(er_header_style1.encoded == -1) {
507                                 LOG_I("Failed to serialize data. Detail: %s.\n", asn_DEF_E2SM_KPM_IndicationHeader.name);
508                                 exit(1);
509                         } else if(er_header_style1.encoded > e2sm_header_buf_size_style1) {
510                                 LOG_I("Buffer of size %zu is too small for %s, need %zu\n", e2sm_header_buf_size_style1, asn_DEF_E2SM_KPM_IndicationHeader.name, er_header_style1.encoded);
511                                 exit(1);
512                         } else {
513                                 LOG_I("Encoded Cell indication header succesfully, size in bytes: %d", er_header_style1.encoded)
514                         }
515
516                         ASN_STRUCT_FREE(asn_DEF_E2SM_KPM_IndicationHeader, ind_header_style1);
517                         
518                         encoding::generate_e2apv1_indication_request_parameterized(pdu_style1, requestorId,
519                                                                                         instanceId, ranFunctionId,
520                                                                                         actionId, seqNum, e2sm_header_buf_style1,
521                                                                                         er_header_style1.encoded,
522                                                                                         e2sm_message_buf_style1, er_message_style1.encoded);
523
524                         e2sim.encode_and_send_sctp_data(pdu_style1);
525                         seqNum++;
526                         LOG_I("Measurement report for Cell %d has been sent\n", i);
527                         std::this_thread::sleep_for (std::chrono::milliseconds(50));      
528                         
529                 }
530           }                                                
531     }
532   }
533 }
534
535
536 void callback_kpm_subscription_request(E2AP_PDU_t *sub_req_pdu) {
537
538   //Record RIC Request ID
539   //Go through RIC action to be Setup List
540   //Find first entry with REPORT action Type
541   //Record ricActionID
542   //Encode subscription response
543
544   RICsubscriptionRequest_t orig_req =
545     sub_req_pdu->choice.initiatingMessage->value.choice.RICsubscriptionRequest;
546   
547   RICsubscriptionResponse_IEs_t *ricreqid =
548     (RICsubscriptionResponse_IEs_t*)calloc(1, sizeof(RICsubscriptionResponse_IEs_t));
549                                            
550   int count = orig_req.protocolIEs.list.count;
551   int size = orig_req.protocolIEs.list.size;
552   
553   RICsubscriptionRequest_IEs_t **ies = (RICsubscriptionRequest_IEs_t**)orig_req.protocolIEs.list.array;
554
555   RICsubscriptionRequest_IEs__value_PR pres;
556
557   long reqRequestorId;
558   long reqInstanceId;
559   long reqActionId;
560
561   std::vector<long> actionIdsAccept;
562   std::vector<long> actionIdsReject;
563
564   for (int i=0; i < count; i++) {
565     RICsubscriptionRequest_IEs_t *next_ie = ies[i];
566     pres = next_ie->value.present;
567     
568     LOG_I("The next present value %d", pres);
569
570     switch(pres) {
571                 case RICsubscriptionRequest_IEs__value_PR_RICrequestID: {
572                         LOG_I("in case request id");
573                         RICrequestID_t reqId = next_ie->value.choice.RICrequestID;
574                         long requestorId = reqId.ricRequestorID;
575                         long instanceId = reqId.ricInstanceID;
576
577                         LOG_I("requestorId: %ld, InstanceID: %ld", requestorId, instanceId);
578
579                         reqRequestorId = requestorId;
580                         reqInstanceId = instanceId;
581
582                         break;
583                 }
584                 case RICsubscriptionRequest_IEs__value_PR_RANfunctionID: {
585                         LOG_I("in case ran func id");
586                         break;
587                 }
588                 case RICsubscriptionRequest_IEs__value_PR_RICsubscriptionDetails: {
589                         RICsubscriptionDetails_t subDetails = next_ie->value.choice.RICsubscriptionDetails;
590                         RICeventTriggerDefinition_t triggerDef = subDetails.ricEventTriggerDefinition;
591                         RICactions_ToBeSetup_List_t actionList = subDetails.ricAction_ToBeSetup_List;
592                         //We are ignoring the trigger definition
593
594                         //We identify the first action whose type is REPORT
595                         //That is the only one accepted; all others are rejected
596
597                         int actionCount = actionList.list.count;
598                         LOG_I("Action count%d", actionCount);
599
600                         auto **item_array = actionList.list.array;
601
602                         bool foundAction = false;
603
604                         for (int i=0; i < actionCount; i++) {
605                                 auto *next_item = item_array[i];
606                                 RICactionID_t actionId = ((RICaction_ToBeSetup_ItemIEs*)next_item)->value.choice.RICaction_ToBeSetup_Item.ricActionID;
607                                 RICactionType_t actionType = ((RICaction_ToBeSetup_ItemIEs*)next_item)->value.choice.RICaction_ToBeSetup_Item.ricActionType;
608
609                                 if (!foundAction && actionType == RICactionType_report) {
610                                         reqActionId = actionId;
611                                         actionIdsAccept.push_back(reqActionId);
612                                         foundAction = true;
613                                 } else {
614                                         reqActionId = actionId;
615                                         actionIdsReject.push_back(reqActionId);
616                                 }
617                         }
618
619                         break;
620                 }
621                 default: {
622                         break;
623                 }
624     }
625     
626   }
627
628   LOG_I("After Processing Subscription Request");
629
630   for (int i=0; i < actionIdsAccept.size(); i++) {
631     LOG_D("Action ID %d %ld\n", i, actionIdsAccept.at(i));
632   }
633
634   E2AP_PDU *e2ap_pdu = (E2AP_PDU*)calloc(1,sizeof(E2AP_PDU));
635
636   long *accept_array = &actionIdsAccept[0];
637   long *reject_array = &actionIdsReject[0];
638   int accept_size = actionIdsAccept.size();
639   int reject_size = actionIdsReject.size();
640
641   encoding::generate_e2apv1_subscription_response_success(e2ap_pdu, accept_array, reject_array, accept_size, reject_size, reqRequestorId, reqInstanceId);
642   
643   LOG_I("Encode and sending E2AP subscription success response via SCTP");
644   e2sim.encode_and_send_sctp_data(e2ap_pdu);
645
646   LOG_I("Now generating data for subscription request");
647   run_report_loop(reqRequestorId, reqInstanceId, gFuncId, reqActionId);
648
649 }