Enhanced SIM for E2AP v1 for TS UC
[sim/e2-interface.git] / e2sim / e2apv1sim / src / ASN1 / lib / asn_e2ap.cpp
1 /*****************************************************************************
2 #                                                                            *
3 # Copyright 2019 AT&T Intellectual Property                                  *
4 # Copyright 2019 Nokia                                                       *
5 #                                                                            *
6 # Licensed under the Apache License, Version 2.0 (the "License");            *
7 # you may not use this file except in compliance with the License.           *
8 # You may obtain a copy of the License at                                    *
9 #                                                                            *
10 #      http://www.apache.org/licenses/LICENSE-2.0                            *
11 #                                                                            *
12 # Unless required by applicable law or agreed to in writing, software        *
13 # distributed under the License is distributed on an "AS IS" BASIS,          *
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
15 # See the License for the specific language governing permissions and        *
16 # limitations under the License.                                             *
17 #                                                                            *
18 ******************************************************************************/
19 #include "asn_e2ap.hpp"
20 #include "asn_e2ap_wrapper.hpp"
21
22 /*-----------------------------------------------------------------------
23                               COMMON ROUTINES
24 -------------------------------------------------------------------------
25 */
26 e2ap_pdu_t* new_e2ap_pdu(void)
27 {
28     E2APpduWrapper* pduWrapper = new E2APpduWrapper();
29     return reinterpret_cast<e2ap_pdu_t*>(pduWrapper);
30 }
31
32 void e2ap_asn_print(e2ap_pdu_t* pdu, char* buf, size_t buf_size)
33 {
34   E2APpduWrapper* pduWrapper = reinterpret_cast<E2APpduWrapper*>(pdu);
35
36   buf[0] = 0;
37
38   strncat(buf, asn::get_printed(pduWrapper->ref_pdu()).c_str(), buf_size - 1);
39 }
40
41 int e2ap_asn_per_encode(e2ap_pdu_t* pdu, unsigned char* buf, size_t buf_size,
42                                           char* err_buf, size_t err_buf_size)
43 {
44   E2APpduWrapper* pduWrapper = reinterpret_cast<E2APpduWrapper*>(pdu);
45
46   asn::per::EncoderCtx ctx{ buf, buf_size };
47
48   if (!asn::per::pack(pduWrapper->ref_pdu(), ctx)) {
49       err_buf[0] = 0;
50       //strncat(err_buf, ctx.refErrorCtx().toString().c_str(), err_buf_size - 1);
51       return -1;
52   } else {
53     return static_cast<int>(ctx.refBuffer().getBytesUsed());
54   }
55
56 }
57
58 int e2ap_asn_per_decode(e2ap_pdu_t* pdu, unsigned char const* buf, size_t buf_size,
59                                           char* err_buf, size_t err_buf_size)
60 {
61   E2APpduWrapper* pduWrapper = reinterpret_cast<E2APpduWrapper*>(pdu);
62
63   asn::per::DecoderCtx ctx{ buf,
64                             buf_size,
65                             pduWrapper->m_allocation_buffer,
66                             pduWrapper->m_allocation_buffer_size };
67
68   if (!asn::per::unpack(pduWrapper->ref_pdu(), ctx)) {
69       err_buf[0] = 0;
70       //strncat(err_buf, ctx.refErrorCtx().toString().c_str(), err_buf_size - 1);
71       return -1;
72   }
73
74   return 0;
75
76 }
77
78 int e2ap_get_index(e2ap_pdu_t* pdu)
79 {
80   E2APpduWrapper* pduWrapper = reinterpret_cast<E2APpduWrapper*>(pdu);
81
82   return pduWrapper->ref_pdu().get_index();
83 }
84
85 int e2ap_get_procedureCode(e2ap_pdu_t* pdu)
86 {
87   E2APpduWrapper* pduWrapper = reinterpret_cast<E2APpduWrapper*>(pdu);
88
89   switch(pduWrapper->ref_pdu().get_index())
90   {
91     case 1:
92       return pduWrapper->ref_pdu().get_initiatingMessage()->ref_procedureCode().get();
93       break;
94
95     case 2:
96       return pduWrapper->ref_pdu().get_successfulOutcome()->ref_procedureCode().get();
97       break;
98
99     case 3:
100       return pduWrapper->ref_pdu().get_unsuccessfulOutcome()->ref_procedureCode().get();
101       break;
102
103     default:
104       return -1;
105   }
106
107 }
108
109 /*-----------------------------------------------------------------------
110                               MESSAGE GENERATORS
111 -------------------------------------------------------------------------
112 */
113 //X2Setup
114 bool e2ap_init_X2SetupRequest(e2ap_pdu_t* pdu)
115 {
116   E2APpduWrapper* pduWrapper = reinterpret_cast<E2APpduWrapper*>(pdu);
117
118   //Initialization
119   pduWrapper->ref_pdu().select_initiatingMessage();
120   pduWrapper->ref_pdu().select_initiatingMessage().clear();
121   pduWrapper->ref_pdu().select_initiatingMessage().ref_procedureCode().select_id_x2Setup();
122   pduWrapper->ref_pdu().select_initiatingMessage().ref_criticality().select_id_x2Setup();
123   pduWrapper->ref_pdu().select_initiatingMessage().ref_value().select_id_x2Setup();
124
125   return true;
126 }
127
128 bool e2ap_create_X2SetupRequest(e2ap_pdu_t* pdu, eNB_config &cfg)
129 {
130   E2APpduWrapper* pduWrapper = reinterpret_cast<E2APpduWrapper*>(pdu);
131
132   /* Initiaization */
133   pduWrapper->ref_pdu().select_initiatingMessage().ref_procedureCode().select_id_x2Setup();
134   pduWrapper->ref_pdu().select_initiatingMessage().ref_criticality().select_id_x2Setup();
135
136   X2SetupRequest* container =
137     &(pduWrapper->ref_pdu().select_initiatingMessage().ref_value().select_id_x2Setup());
138
139   using IE_value_t = X2SetupRequest::protocolIEs_t::value_type;
140
141   /* X2SetupRequest-IEs : GlobalENB-ID*/
142   IE_value_t* val_GlobalENB_ID = new IE_value_t;
143   container->ref_protocolIEs().push_back(*val_GlobalENB_ID);
144
145   val_GlobalENB_ID->ref_id().select_id_GlobalENB_ID();
146   val_GlobalENB_ID->ref_criticality().select_id_GlobalENB_ID();
147   val_GlobalENB_ID->ref_value().select_id_GlobalENB_ID().ref_pLMN_Identity()
148                                          .set(3, cfg.pLMN_Identity);
149   val_GlobalENB_ID->ref_value().select_id_GlobalENB_ID().ref_eNB_ID()
150                   .select_macro_eNB_ID().set_buffer(20, cfg.macro_eNB_ID);
151
152   /* X2SetupRequest-IEs : ServedCells*/
153   IE_value_t* val_ServedCells = new IE_value_t;
154   container->ref_protocolIEs().push_back(*val_ServedCells);
155
156   val_ServedCells->ref_id().select_id_ServedCells();
157   val_ServedCells->ref_criticality().select_id_ServedCells();
158   val_ServedCells->ref_value().select_id_ServedCells();
159
160   //Add servedCellInfo
161   ServedCells::value_type* elm = new ServedCells::value_type();
162   ServedCell_Information* info = &(elm->ref_servedCellInfo());
163   {
164     //Set ServedCell-Information: pCI, cellId, tAC, broadcastPLMNs, eUTRA-Mode-Info
165     info->ref_pCI().set(cfg.pCI);
166     info->ref_cellId().ref_pLMN_Identity().set(3, cfg.pLMN_Identity);
167     info->ref_cellId().ref_eUTRANcellIdentifier().set_buffer(28, cfg.eUTRANcellIdentifier);
168     info->ref_tAC().set(2, cfg.tAC);
169
170     BroadcastPLMNs_Item::value_type* item = new BroadcastPLMNs_Item::value_type();
171     item->set(3, cfg.pLMN_Identity);
172     info->ref_broadcastPLMNs().push_back(*item);
173
174     info->ref_eUTRA_Mode_Info().select_fDD().ref_uL_EARFCN().set(cfg.uL_EARFCN);
175     info->ref_eUTRA_Mode_Info().select_fDD().ref_dL_EARFCN().set(cfg.dL_EARFCN);
176     info->ref_eUTRA_Mode_Info().select_fDD().ref_uL_Transmission_Bandwidth()
177           .set(static_cast<Transmission_Bandwidth::index_t>(cfg.uL_Bandwidth));
178     info->ref_eUTRA_Mode_Info().select_fDD().ref_dL_Transmission_Bandwidth()
179           .set(static_cast<Transmission_Bandwidth::index_t>(cfg.dL_Bandwidth));
180   }
181   val_ServedCells->ref_value().select_id_ServedCells().push_back(*elm);
182
183   return true;
184 }
185
186 bool e2ap_create_X2SetupResponse(e2ap_pdu_t* pdu, eNB_config &cfg)
187 {
188   E2APpduWrapper* pduWrapper = reinterpret_cast<E2APpduWrapper*>(pdu);
189
190   /* Initiaization */
191   pduWrapper->ref_pdu().select_successfulOutcome().ref_procedureCode().select_id_x2Setup();
192   pduWrapper->ref_pdu().select_successfulOutcome().ref_criticality().select_id_x2Setup();
193
194   X2SetupResponse* container =
195     &(pduWrapper->ref_pdu().select_successfulOutcome().ref_value().select_id_x2Setup());
196
197   using IE_value_t = X2SetupResponse::protocolIEs_t::value_type;
198
199   /* X2SetupResponse-IEs : GlobalENB-ID*/
200   IE_value_t* val_GlobalENB_ID = new IE_value_t;
201   container->ref_protocolIEs().push_back(*val_GlobalENB_ID);
202
203   val_GlobalENB_ID->ref_id().select_id_GlobalENB_ID();
204   val_GlobalENB_ID->ref_criticality().select_id_GlobalENB_ID();
205   val_GlobalENB_ID->ref_value().select_id_GlobalENB_ID().ref_pLMN_Identity()
206                                          .set(3, cfg.pLMN_Identity);
207
208   val_GlobalENB_ID->ref_value().select_id_GlobalENB_ID().ref_eNB_ID()
209                   .select_macro_eNB_ID().set_buffer(20, cfg.macro_eNB_ID);
210
211   /* X2SetupResponse-IEs : ServedCells*/
212   IE_value_t* val_ServedCells = new IE_value_t;
213   container->ref_protocolIEs().push_back(*val_ServedCells);
214
215   val_ServedCells->ref_id().select_id_ServedCells();
216   val_ServedCells->ref_criticality().select_id_ServedCells();
217   val_ServedCells->ref_value().select_id_ServedCells();
218
219   //Add servedCellInfo
220   ServedCells::value_type* elm = new ServedCells::value_type();
221   ServedCell_Information* info = &(elm->ref_servedCellInfo());
222   {
223     //Set ServedCell-Information: pCI, cellId, tAC, broadcastPLMNs, eUTRA-Mode-Info
224     info->ref_pCI().set(cfg.pCI);
225     info->ref_cellId().ref_pLMN_Identity().set(3, cfg.pLMN_Identity);
226     info->ref_cellId().ref_eUTRANcellIdentifier().set_buffer(28, cfg.eUTRANcellIdentifier);
227     info->ref_tAC().set(2, cfg.tAC);
228
229     BroadcastPLMNs_Item::value_type* item = new BroadcastPLMNs_Item::value_type();
230     item->set(3, cfg.pLMN_Identity);
231     info->ref_broadcastPLMNs().push_back(*item);
232
233     info->ref_eUTRA_Mode_Info().select_fDD().ref_uL_EARFCN().set(cfg.uL_EARFCN);
234     info->ref_eUTRA_Mode_Info().select_fDD().ref_dL_EARFCN().set(cfg.dL_EARFCN);
235     info->ref_eUTRA_Mode_Info().select_fDD().ref_uL_Transmission_Bandwidth()
236           .set(static_cast<Transmission_Bandwidth::index_t>(cfg.uL_Bandwidth));
237     info->ref_eUTRA_Mode_Info().select_fDD().ref_dL_Transmission_Bandwidth()
238           .set(static_cast<Transmission_Bandwidth::index_t>(cfg.dL_Bandwidth));
239   }
240   val_ServedCells->ref_value().select_id_ServedCells().push_back(*elm);
241
242   return true;
243 }
244
245 bool e2ap_create_X2SetupFailure(e2ap_pdu_t* pdu)
246 {
247   E2APpduWrapper* pduWrapper = reinterpret_cast<E2APpduWrapper*>(pdu);
248
249   /* Initiaization */
250   pduWrapper->ref_pdu().select_unsuccessfulOutcome().ref_procedureCode().select_id_x2Setup();
251   pduWrapper->ref_pdu().select_unsuccessfulOutcome().ref_criticality().select_id_x2Setup();
252
253   X2SetupFailure* container =
254     &(pduWrapper->ref_pdu().select_unsuccessfulOutcome().ref_value().select_id_x2Setup());
255
256   using IE_value_t = X2SetupFailure::protocolIEs_t::value_type;
257
258   /* X2SetupFailure-IEs << id-Cause */
259   IE_value_t* val_cause = new IE_value_t;
260   container->ref_protocolIEs().push_back(*val_cause);
261
262   val_cause->ref_id().select_id_Cause();
263   val_cause->ref_criticality().select_id_Cause();
264
265   /* Cause << radioNetwork */
266   val_cause->ref_value().select_id_Cause().select_radioNetwork();
267
268   /* CauseRadioNetwork = ho-target-not-allowed (enum = 8)*/
269   val_cause->ref_value().select_id_Cause().select_radioNetwork()
270                         .set(static_cast<CauseRadioNetwork::index_t>(8));
271
272   return true;
273 }
274
275 //ENDCX2Setup
276 bool e2ap_create_ENDCX2SetupRequest(e2ap_pdu_t* pdu, eNB_config &cfg)
277 {
278   E2APpduWrapper* pduWrapper = reinterpret_cast<E2APpduWrapper*>(pdu);
279
280   /* Initiaization */
281   pduWrapper->ref_pdu().select_initiatingMessage().ref_procedureCode().select_id_endcX2Setup();
282   pduWrapper->ref_pdu().select_initiatingMessage().ref_criticality().select_id_endcX2Setup();
283
284   ENDCX2SetupRequest* container =
285     &(pduWrapper->ref_pdu().select_initiatingMessage().ref_value().select_id_endcX2Setup());
286
287   using IE_value_t = ENDCX2SetupRequest::protocolIEs_t::value_type;
288
289   /* ENDCX2SetupRequest-IEs = id-InitiatingNodeType-EndcX2Setup  */
290   IE_value_t* ie = new IE_value_t;
291   container->ref_protocolIEs().push_back(*ie);
292   ie->ref_id().select_id_InitiatingNodeType_EndcX2Setup();
293   ie->ref_criticality().select_id_InitiatingNodeType_EndcX2Setup();
294   ie->ref_value().select_id_InitiatingNodeType_EndcX2Setup();
295
296   /* InitiatingNodeType-EndcX2Setup = init-eNB {ENB-ENDCX2SetupReqIEs} */
297   ie->ref_value().select_id_InitiatingNodeType_EndcX2Setup().select_init_eNB();
298
299   using eNB_val_t = InitiatingNodeType_EndcX2Setup::init_eNB_t::value_type;
300
301   ProtocolIE_Container<ENB_ENDCX2SetupReqIEs>* eNB_node =
302     &(ie->ref_value().select_id_InitiatingNodeType_EndcX2Setup().select_init_eNB());
303
304   /* ENB-ENDCX2SetupReqIEs <-- id-GlobalENB-ID */
305   eNB_val_t* val_GlobalENB_ID = new eNB_val_t;
306   eNB_node->push_back(*val_GlobalENB_ID);
307
308   val_GlobalENB_ID->ref_id().select_id_GlobalENB_ID();
309   val_GlobalENB_ID->ref_criticality().select_id_GlobalENB_ID();
310   val_GlobalENB_ID->ref_value().select_id_GlobalENB_ID()
311                       .ref_pLMN_Identity().set(3, cfg.pLMN_Identity);
312   val_GlobalENB_ID->ref_value().select_id_GlobalENB_ID().ref_eNB_ID()
313                   .select_macro_eNB_ID().set_buffer(20, cfg.macro_eNB_ID);
314
315   /* ENB-ENDCX2SetupReqIEs <-- id-ServedEUTRAcellsENDCX2ManagementList */
316   eNB_val_t* val_EUTRAlist = new eNB_val_t;
317   eNB_node->push_back(*val_EUTRAlist);
318
319   val_EUTRAlist->ref_id().select_id_ServedEUTRAcellsENDCX2ManagementList();
320   val_EUTRAlist->ref_criticality().select_id_ServedEUTRAcellsENDCX2ManagementList();
321   val_EUTRAlist->ref_value().select_id_ServedEUTRAcellsENDCX2ManagementList();
322
323   /* ServedEUTRAcellsENDCX2ManagementList <-- servedEUTRACellInfo */
324   ServedEUTRAcellsENDCX2ManagementList::value_type* elm =
325                         new ServedEUTRAcellsENDCX2ManagementList::value_type();
326   ServedCell_Information* info = &(elm->ref_servedEUTRACellInfo());
327   {
328     //Set ServedCell-Information: pCI, cellId, tAC, broadcastPLMNs, eUTRA-Mode-Info
329     info->ref_pCI().set(cfg.pCI);
330     info->ref_cellId().ref_pLMN_Identity().set(3, cfg.pLMN_Identity);
331     info->ref_cellId().ref_eUTRANcellIdentifier().set_buffer(28, cfg.eUTRANcellIdentifier);
332     info->ref_tAC().set(2, cfg.tAC);
333
334     BroadcastPLMNs_Item::value_type* item = new BroadcastPLMNs_Item::value_type();
335     item->set(3, cfg.pLMN_Identity);
336     info->ref_broadcastPLMNs().push_back(*item);
337
338     info->ref_eUTRA_Mode_Info().select_fDD().ref_uL_EARFCN().set(cfg.uL_EARFCN);
339     info->ref_eUTRA_Mode_Info().select_fDD().ref_dL_EARFCN().set(cfg.dL_EARFCN);
340     info->ref_eUTRA_Mode_Info().select_fDD().ref_uL_Transmission_Bandwidth()
341           .set(static_cast<Transmission_Bandwidth::index_t>(cfg.uL_Bandwidth));
342     info->ref_eUTRA_Mode_Info().select_fDD().ref_dL_Transmission_Bandwidth()
343           .set(static_cast<Transmission_Bandwidth::index_t>(cfg.dL_Bandwidth));
344   }
345   val_EUTRAlist->ref_value().select_id_ServedEUTRAcellsENDCX2ManagementList()
346                                                         .push_back(*elm);
347
348   return true;
349 }
350
351 bool e2ap_create_ENDCX2SetupResponse(e2ap_pdu_t* pdu, gNB_config &gnb_cfg)
352 {
353   E2APpduWrapper* pduWrapper = reinterpret_cast<E2APpduWrapper*>(pdu);
354
355   /* Initiaization */
356   pduWrapper->ref_pdu().select_successfulOutcome().ref_procedureCode().select_id_endcX2Setup();
357   pduWrapper->ref_pdu().select_successfulOutcome().ref_criticality().select_id_endcX2Setup();
358
359   ENDCX2SetupResponse* container =
360     &(pduWrapper->ref_pdu().select_successfulOutcome().ref_value().select_id_endcX2Setup());
361
362   using IE_value_t = ENDCX2SetupResponse::protocolIEs_t::value_type;
363
364   /* ENDCX2SetupRequest-IEs = id-RespondingNodeType-EndcX2Setup  */
365   IE_value_t* ie = new IE_value_t;
366   container->ref_protocolIEs().push_back(*ie);
367   ie->ref_id().select_id_RespondingNodeType_EndcX2Setup();
368   ie->ref_criticality().select_id_RespondingNodeType_EndcX2Setup();
369   ie->ref_value().select_id_RespondingNodeType_EndcX2Setup();
370
371   /* RespondingNodeType-EndcX2Setup = respond-en-gNB {En-gNB-ENDCX2SetupReqAckIEs} */
372   ie->ref_value().select_id_RespondingNodeType_EndcX2Setup().select_respond_en_gNB();
373
374   using gNB_val_t = RespondingNodeType_EndcX2Setup::respond_en_gNB_t::value_type;
375
376   ProtocolIE_Container<En_gNB_ENDCX2SetupReqAckIEs>* gNB_node =
377     &(ie->ref_value().select_id_RespondingNodeType_EndcX2Setup().select_respond_en_gNB());
378
379   /* En-gNB-ENDCX2SetupReqAckIEs << id-Globalen-gNB-ID */
380   gNB_val_t* val_Globalen_gNB_ID = new gNB_val_t;
381   gNB_node->push_back(*val_Globalen_gNB_ID);
382
383   val_Globalen_gNB_ID->ref_id().select_id_Globalen_gNB_ID();
384   val_Globalen_gNB_ID->ref_criticality().select_id_Globalen_gNB_ID();
385   val_Globalen_gNB_ID->ref_value().select_id_Globalen_gNB_ID()
386             .ref_pLMN_Identity().set(3, gnb_cfg.pLMN_Identity);
387   val_Globalen_gNB_ID->ref_value().select_id_Globalen_gNB_ID().ref_gNB_ID()
388     .select_gNB_ID().set_buffer(22, gnb_cfg.gNB_ID);
389
390   /* En-gNB-ENDCX2SetupReqAckIEs << id-ServedNRcellsENDCX2ManagementList */
391   gNB_val_t* val_ServedNRCells = new gNB_val_t;
392   gNB_node->push_back(*val_ServedNRCells);
393
394   val_ServedNRCells->ref_id().select_id_ServedNRcellsENDCX2ManagementList();
395   val_ServedNRCells->ref_criticality().select_id_ServedNRcellsENDCX2ManagementList();
396   val_ServedNRCells->ref_value().select_id_ServedNRcellsENDCX2ManagementList();
397
398   /* ServedNRcellsENDCX2ManagementList <-- servedNRCellInfo*/
399   ServedNRcellsENDCX2ManagementList::value_type* elm =
400                           new ServedNRcellsENDCX2ManagementList::value_type();
401
402   /*
403   ServedNRCell-Information ::= SEQUENCE {
404         nrpCI                           NRPCI,
405         nrCellID                        NRCGI,
406         fiveGS-TAC                      FiveGS-TAC      OPTIONAL,
407         configured-TAC          TAC                     OPTIONAL,
408         broadcastPLMNs          BroadcastPLMNs-Item,
409         nrModeInfo                      CHOICE {
410                 fdd             FDD-InfoServedNRCell-Information,
411                 tdd             TDD-InfoServedNRCell-Information,
412                 ...
413         },
414         measurementTimingConfiguration  OCTET STRING,
415         iE-Extensions                                           ProtocolExtensionContainer { {ServedNRCell-Information-ExtIEs} } OPTIONAL,
416         ...
417   }
418   */
419   ServedNRCell_Information* info = &(elm->ref_servedNRCellInfo());
420   {
421     // nrpCI                            NRPCI,
422     info->ref_nrpCI().set(gnb_cfg.nrpCI);
423
424     /* nrCellID                 NRCGI,
425
426       NRCGI ::= SEQUENCE {
427         pLMN-Identity                           PLMN-Identity,
428         nRcellIdentifier                                NRCellIdentifier,
429         iE-Extensions                           ProtocolExtensionContainer { {NRCGI-ExtIEs} } OPTIONAL,
430         ...
431       }
432     */
433     info->ref_nrCellID().ref_pLMN_Identity().set(3, gnb_cfg.pLMN_Identity);
434     info->ref_nrCellID().ref_nRcellIdentifier().set_buffer(36, gnb_cfg.nRcellIdentifier);
435
436     /* broadcastPLMNs           BroadcastPLMNs-Item */
437     BroadcastPLMNs_Item::value_type* item = new BroadcastPLMNs_Item::value_type();
438     item->set(3, gnb_cfg.pLMN_Identity);
439     info->ref_broadcastPLMNs().push_back(*item);
440
441     /* nrModeInfo                       CHOICE {
442                 fdd             FDD-InfoServedNRCell-Information,
443                 tdd             TDD-InfoServedNRCell-Information,
444                 ...
445         },
446
447     FDD-InfoServedNRCell-Information ::= SEQUENCE {
448         ul-NRFreqInfo                           NRFreqInfo,
449         dl-NRFreqInfo                           NRFreqInfo,
450         ul-NR-TxBW                              NR-TxBW,
451         dl-NR-TxBW                              NR-TxBW,
452         iE-Extensions                   ProtocolExtensionContainer { {FDD-InfoServedNRCell-Information-ExtIEs} }                OPTIONAL,
453         ...
454     }
455
456     NRFreqInfo ::= SEQUENCE{
457         nRARFCN                 INTEGER (0.. 3279165),
458         freqBandListNr  SEQUENCE (SIZE(1..maxnoofNrCellBands)) OF FreqBandNrItem,
459         sULInformation  SULInformation          OPTIONAL,
460         iE-Extensions   ProtocolExtensionContainer { {NRFreqInfo-ExtIEs} } OPTIONAL,
461
462         ...
463     }
464
465     */
466     info->ref_nrModeInfo().select_fdd().ref_ul_NRFreqInfo().ref_nRARFCN().set(gnb_cfg.uL_nRARFCN);
467     info->ref_nrModeInfo().select_fdd().ref_dl_NRFreqInfo().ref_nRARFCN().set(gnb_cfg.dL_nRARFCN);
468
469     /*
470     FreqBandNrItem ::= SEQUENCE {
471         freqBandIndicatorNr                     INTEGER (1..1024,...),
472         supportedSULBandList    SEQUENCE (SIZE(0..maxnoofNrCellBands)) OF SupportedSULFreqBandItem,
473         iE-Extensions                           ProtocolExtensionContainer { {FreqBandNrItem-ExtIEs} } OPTIONAL,
474         ...
475     }
476     */
477     //uplink
478     asn::sequenceof<NRFreqInfo::freqBandListNr_t_elm>::value_type* ul_band_item =
479                           new asn::sequenceof<NRFreqInfo::freqBandListNr_t_elm>::value_type();
480     {
481       ul_band_item->ref_freqBandIndicatorNr().set(gnb_cfg.ul_freqBandIndicatorNr);
482
483       /*
484       SupportedSULFreqBandItem ::= SEQUENCE {
485         freqBandIndicatorNr                     INTEGER (1..1024,...),
486         iE-Extensions                   ProtocolExtensionContainer { {SupportedSULFreqBandItem-ExtIEs} }                OPTIONAL,
487         ...
488       }
489       */
490
491       asn::sequenceof<FreqBandNrItem::supportedSULBandList_t_elm>::value_type* ul_supported_band_item =
492           new asn::sequenceof<FreqBandNrItem::supportedSULBandList_t_elm>::value_type();
493
494       ul_supported_band_item->ref_freqBandIndicatorNr().set(gnb_cfg.ul_freqBandIndicatorNr);
495
496       ul_band_item->ref_supportedSULBandList().push_back(*ul_supported_band_item);
497     }
498     info->ref_nrModeInfo().select_fdd().ref_ul_NRFreqInfo()
499                                     .ref_freqBandListNr().push_back(*ul_band_item);
500
501     //downlink
502     asn::sequenceof<NRFreqInfo::freqBandListNr_t_elm>::value_type* dl_band_item =
503                           new asn::sequenceof<NRFreqInfo::freqBandListNr_t_elm>::value_type();
504     {
505       dl_band_item->ref_freqBandIndicatorNr().set(gnb_cfg.dl_freqBandIndicatorNr);
506
507       /*
508       SupportedSULFreqBandItem ::= SEQUENCE {
509         freqBandIndicatorNr                     INTEGER (1..1024,...),
510         iE-Extensions                   ProtocolExtensionContainer { {SupportedSULFreqBandItem-ExtIEs} }                OPTIONAL,
511         ...
512       }
513       */
514
515       asn::sequenceof<FreqBandNrItem::supportedSULBandList_t_elm>::value_type* dl_supported_band_item =
516           new asn::sequenceof<FreqBandNrItem::supportedSULBandList_t_elm>::value_type();
517
518       dl_supported_band_item->ref_freqBandIndicatorNr().set(gnb_cfg.dl_freqBandIndicatorNr);
519
520       dl_band_item->ref_supportedSULBandList().push_back(*dl_supported_band_item);
521     }
522     info->ref_nrModeInfo().select_fdd().ref_dl_NRFreqInfo()
523                                     .ref_freqBandListNr().push_back(*dl_band_item);
524
525     /*
526     NR-TxBW     ::= SEQUENCE {
527         nRSCS   NRSCS,
528         nRNRB   NRNRB,
529         iE-Extensions                           ProtocolExtensionContainer { {NR-TxBW-ExtIEs} } OPTIONAL,
530         ...
531     }
532     */
533     {
534       info->ref_nrModeInfo().select_fdd().ref_ul_NR_TxBW().ref_nRNRB()
535                           .set( static_cast<NRNRB::index_t>(gnb_cfg.uL_NRNRB) );
536       info->ref_nrModeInfo().select_fdd().ref_ul_NR_TxBW().ref_nRSCS()
537                           .set( static_cast<NRSCS::index_t>(gnb_cfg.uL_NRSCS) );
538
539       info->ref_nrModeInfo().select_fdd().ref_dl_NR_TxBW().ref_nRNRB()
540                           .set( static_cast<NRNRB::index_t>(gnb_cfg.dL_NRNRB) );
541       info->ref_nrModeInfo().select_fdd().ref_dl_NR_TxBW().ref_nRSCS()
542                           .set( static_cast<NRSCS::index_t>(gnb_cfg.dL_NRSCS) );
543     }
544
545     /*
546     measurementTimingConfiguration      OCTET STRING,
547     */
548     info->ref_measurementTimingConfiguration().set(gnb_cfg.measurementTimingConfiguration);
549   }
550   val_ServedNRCells->ref_value().select_id_ServedNRcellsENDCX2ManagementList().push_back(*elm);
551
552
553
554   return true;
555 }
556
557 bool e2ap_create_ENDCX2SetupFailure(e2ap_pdu_t* pdu)
558 {
559
560   E2APpduWrapper* pduWrapper = reinterpret_cast<E2APpduWrapper*>(pdu);
561
562   /* Initiaization */
563   pduWrapper->ref_pdu().select_unsuccessfulOutcome().ref_procedureCode().select_id_endcX2Setup();
564   pduWrapper->ref_pdu().select_unsuccessfulOutcome().ref_criticality().select_id_endcX2Setup();
565
566   ENDCX2SetupFailure* container =
567         &(pduWrapper->ref_pdu().select_unsuccessfulOutcome().ref_value().select_id_endcX2Setup());
568
569   using IE_value_t = ENDCX2SetupFailure::protocolIEs_t::value_type;
570
571   /* ENDCX2SetupFailure-IEs := id-Cause*/
572   IE_value_t* val_cause = new IE_value_t;
573   container->ref_protocolIEs().push_back(*val_cause);
574
575   val_cause->ref_id().select_id_Cause();
576   val_cause->ref_criticality().select_id_Cause();
577
578   /* Cause << radioNetwork */
579   val_cause->ref_value().select_id_Cause().select_radioNetwork();
580
581   /* CauseRadioNetwork = ho-target-not-allowed (enum = 8)*/
582   val_cause->ref_value().select_id_Cause().select_radioNetwork()
583         .set(static_cast<CauseRadioNetwork::index_t>(8));
584
585   return true;
586 }
587
588 //RICSubscription
589 bool e2ap_create_RICsubscriptionRequest(e2ap_pdu_t* pdu, RICsubscription_params_t &params)
590 {
591   E2APpduWrapper* pduWrapper = reinterpret_cast<E2APpduWrapper*>(pdu);
592
593   /* Initiaization */
594   pduWrapper->ref_pdu().select_initiatingMessage()
595                               .ref_procedureCode().select_id_ricSubscription();
596   pduWrapper->ref_pdu().select_initiatingMessage()
597                                 .ref_criticality().select_id_ricSubscription();
598
599   RICsubscriptionRequest* container = &(pduWrapper->ref_pdu()
600         .select_initiatingMessage().ref_value().select_id_ricSubscription());
601
602   using IE_value_t = RICsubscriptionRequest::protocolIEs_t::value_type;
603
604   /* RICsubscriptionRequest-IEs :  RICrequestID */
605   IE_value_t* ie_RICrequestID = new IE_value_t;
606   container->ref_protocolIEs().push_back(*ie_RICrequestID);
607
608   ie_RICrequestID->ref_id().select_id_RICrequestID();
609   ie_RICrequestID->ref_criticality().select_id_RICrequestID();
610   ie_RICrequestID->ref_value().select_id_RICrequestID()
611                                 .ref_ricRequestorID().set(params.request_id);
612   ie_RICrequestID->ref_value().select_id_RICrequestID()
613                       .ref_ricRequestSequenceNumber().set(params.seq_number);
614
615   /* RICsubscriptionRequest-IEs :  RANfunctionID */
616   IE_value_t* ie_RANfunctionID = new IE_value_t;
617   container->ref_protocolIEs().push_back(*ie_RANfunctionID);
618
619   ie_RANfunctionID->ref_id().select_id_RANfunctionID();
620   ie_RANfunctionID->ref_criticality().select_id_RANfunctionID();
621   ie_RANfunctionID->ref_value().select_id_RANfunctionID().set(params.ran_func_id);
622
623
624   /*
625   RICsubscription ::= SEQUENCE {
626         ricEventTriggerDefinition       RICeventTriggerDefinition,
627         ricAction-ToBeSetup-List        RICactions-ToBeSetup-List,
628         ...
629   }
630
631   RICeventTriggerDefinition ::= OCTET STRING
632   RICactions-ToBeSetup-List ::= SEQUENCE (SIZE(1..maxofRICactionID)) OF ProtocolIE-Single-Container { {RICaction-ToBeSetup-ItemIEs} }
633
634   RICaction-ToBeSetup-ItemIEs   X2AP-PROTOCOL-IES ::= {
635         { ID id-RICaction-ToBeSetup-Item         CRITICALITY ignore     TYPE RICaction-ToBeSetup-Item   PRESENCE mandatory },
636         ...
637   }
638
639   RICaction-ToBeSetup-Item ::= SEQUENCE {
640         ricActionID                                     RICactionID,
641         ricActionType                           RICactionType,
642         ricActionDefinition                     RICactionDefinition     OPTIONAL,
643         ricSubsequentAction                     RICsubsequentAction     OPTIONAL,
644         ...
645   }
646
647   RICactionID ::= INTEGER (0..255)
648
649   RICactionType ::= ENUMERATED{
650         report,
651         insert,
652         policy,
653         ...
654   }
655   */
656
657   /* RICsubscriptionRequest-IEs :  RICsubscription */
658   IE_value_t* ie_RICsubscription = new IE_value_t;
659   container->ref_protocolIEs().push_back(*ie_RICsubscription);
660
661   ie_RICsubscription->ref_id().select_id_RICsubscription();
662   ie_RICsubscription->ref_criticality().select_id_RICsubscription();
663
664   // RICeventTriggerDefinition
665   ie_RICsubscription->ref_value().select_id_RICsubscription()
666     .ref_ricEventTriggerDefinition().set<std::string>(params.event_trigger_def);
667
668   //RICactions-ToBeSetup-List
669   for( auto const  &action : params.actionList)
670   {
671     RICactions_ToBeSetup_List::value_type* item =
672                                   new RICactions_ToBeSetup_List::value_type();
673
674     ie_RICsubscription->ref_value().select_id_RICsubscription()
675                             .ref_ricAction_ToBeSetup_List().push_back(*item);
676
677     item->ref_id().select_id_RICaction_ToBeSetup_Item();
678     item->ref_criticality().select_id_RICaction_ToBeSetup_Item();
679     item->ref_value().select_id_RICaction_ToBeSetup_Item()
680                                     .ref_ricActionID().set(action.action_id);
681     item->ref_value().select_id_RICaction_ToBeSetup_Item()
682                                 .ref_ricActionType().set(action.action_type);
683
684   }
685
686   return true;
687 }
688
689 bool e2ap_parse_RICsubscriptionRequest(e2ap_pdu_t* pdu, RICsubscription_params_t &params)
690 {
691   E2APpduWrapper* pduWrapper = reinterpret_cast<E2APpduWrapper*>(pdu);
692
693   RICsubscriptionRequest* container = &(pduWrapper->ref_pdu()
694         .select_initiatingMessage().ref_value().select_id_ricSubscription());
695
696
697   for(auto &e : container->ref_protocolIEs())
698   {
699     /*See struct RICsubscriptionRequest_IEs*/
700     size_t type = e.ref_value().get_index();
701
702     switch(type)
703     {
704       case 1: //RICrequestID
705         {
706           params.request_id = e.ref_value().select_id_RICrequestID().ref_ricRequestorID().get();
707           params.seq_number = e.ref_value().select_id_RICrequestID().ref_ricRequestSequenceNumber().get();
708         }
709         break;
710
711       case 2: //RANfunctionID
712         params.ran_func_id = e.ref_value().select_id_RANfunctionID().get();
713         break;
714
715       case 3: //RICsubscription
716         {
717           auto event = e.ref_value().select_id_RICsubscription().ref_ricEventTriggerDefinition().get();
718           (params.event_trigger_def).assign(std::string(event.data(), event.data() + event.size()));
719
720           //ricAction_ToBeSetup_List
721           for (auto  & f : e.ref_value().select_id_RICsubscription().ref_ricAction_ToBeSetup_List())
722           {
723             RIC_action_t action;
724             action.action_id = f.ref_value()
725                 .select_id_RICaction_ToBeSetup_Item().ref_ricActionID().get();
726             action.action_type = static_cast<enum_RICactionType>(f.ref_value()
727               .select_id_RICaction_ToBeSetup_Item().ref_ricActionType().get());
728
729             params.actionList.push_back(action);
730           }
731         }
732         break;
733
734       default:
735         printf("Unknown IE type = %d\n", (int)type);
736         return false;
737     }
738   }
739
740   return true;
741 }
742
743 bool e2ap_create_RICsubscriptionResponse(e2ap_pdu_t* pdu, RICsubscription_params_t &params)
744 {
745   E2APpduWrapper* pduWrapper = reinterpret_cast<E2APpduWrapper*>(pdu);
746
747   /* Initiaization */
748   pduWrapper->ref_pdu().select_successfulOutcome().ref_procedureCode().select_id_ricSubscription();
749   pduWrapper->ref_pdu().select_successfulOutcome().ref_criticality().select_id_ricSubscription();
750
751   RICsubscriptionResponse* container = &(pduWrapper->ref_pdu()
752         .select_successfulOutcome().ref_value().select_id_ricSubscription());
753
754   using IE_value_t = RICsubscriptionResponse::protocolIEs_t::value_type;
755
756   /* RICsubscriptionResponse-IEs :  RICrequestID */
757   IE_value_t* ie_RICrequestID = new IE_value_t;
758   container->ref_protocolIEs().push_back(*ie_RICrequestID);
759
760   ie_RICrequestID->ref_id().select_id_RICrequestID();
761   ie_RICrequestID->ref_criticality().select_id_RICrequestID();
762   ie_RICrequestID->ref_value().select_id_RICrequestID()
763                                 .ref_ricRequestorID().set(params.request_id);
764   ie_RICrequestID->ref_value().select_id_RICrequestID()
765                       .ref_ricRequestSequenceNumber().set(params.seq_number);
766
767   /* RICsubscriptionResponse-IEs :  RANfunctionID */
768   IE_value_t* ie_RANfunctionID = new IE_value_t;
769   container->ref_protocolIEs().push_back(*ie_RANfunctionID);
770
771   ie_RANfunctionID->ref_id().select_id_RANfunctionID();
772   ie_RANfunctionID->ref_criticality().select_id_RANfunctionID();
773   ie_RANfunctionID->ref_value().select_id_RANfunctionID().set(params.ran_func_id);
774
775   /* RICsubscriptionResponse-IEs :  RICaction-Admitted-List */
776   IE_value_t* ie_admittedList = new IE_value_t;
777   container->ref_protocolIEs().push_back(*ie_admittedList);
778
779   ie_admittedList->ref_id().select_id_RICactions_Admitted();
780   ie_admittedList->ref_criticality().select_id_RICactions_Admitted();
781
782   /* RICsubscriptionResponse-IEs :  RICaction-NotAdmitted-List */
783   IE_value_t* ie_notAdmittedList = new IE_value_t;
784   container->ref_protocolIEs().push_back(*ie_notAdmittedList);
785
786   ie_notAdmittedList->ref_id().select_id_RICactions_NotAdmitted();
787   ie_notAdmittedList->ref_criticality().select_id_RICactions_NotAdmitted();
788
789   //add action to admitted and not-admitted list
790   for(auto const &a : params.actionList)
791   {
792     if(a.isAdmitted)
793     {
794       RICaction_Admitted_List::value_type* item = new RICaction_Admitted_List::value_type();
795
796       ie_admittedList->ref_value().select_id_RICactions_Admitted().push_back(*item);
797
798       item->ref_id().select_id_RICaction_Admitted_Item();
799       item->ref_criticality().select_id_RICaction_Admitted_Item();
800       item->ref_value().select_id_RICaction_Admitted_Item().ref_ricActionID().set(a.action_id);
801     }
802     else
803     {
804       RICaction_NotAdmitted_List::value_type* item = new RICaction_NotAdmitted_List::value_type();
805
806       ie_notAdmittedList->ref_value().select_id_RICactions_NotAdmitted().push_back(*item);
807
808       item->ref_id().select_id_RICaction_NotAdmitted_Item();
809       item->ref_criticality().select_id_RICaction_NotAdmitted_Item();
810       item->ref_value().select_id_RICaction_NotAdmitted_Item().ref_ricActionID().set(a.action_id);
811
812       // set cause and sub-cause
813       switch(a.notAdmitted_cause)
814       {
815         case RICcause_radioNetwork:
816           item->ref_value().select_id_RICaction_NotAdmitted_Item().ref_ricCause().select_radioNetwork().set(a.notAdmitted_subCause);
817           break;
818
819         case RICcause_transport:
820           item->ref_value().select_id_RICaction_NotAdmitted_Item().ref_ricCause().select_transport().set(a.notAdmitted_subCause);
821           break;
822
823         case RICcause_protocol:
824           item->ref_value().select_id_RICaction_NotAdmitted_Item().ref_ricCause().select_protocol().set(a.notAdmitted_subCause);
825           break;
826
827         case RICcause_misc:
828           item->ref_value().select_id_RICaction_NotAdmitted_Item().ref_ricCause().select_misc().set(a.notAdmitted_subCause);
829           break;
830
831         case RICcause_ric:
832           item->ref_value().select_id_RICaction_NotAdmitted_Item().ref_ricCause().select_ric().set(a.notAdmitted_subCause);
833           break;
834
835         default:
836           printf("Unknown cause for action not admitted = %d", (int)a.notAdmitted_cause);
837       }
838     }
839   }
840
841   return true;
842 }
843
844 bool e2ap_create_RICsubscriptionFailure(e2ap_pdu_t* pdu, RICsubscription_params_t &params)
845 {
846   E2APpduWrapper* pduWrapper = reinterpret_cast<E2APpduWrapper*>(pdu);
847
848   /* Initiaization */
849   pduWrapper->ref_pdu().select_unsuccessfulOutcome().ref_procedureCode().select_id_ricSubscription();
850   pduWrapper->ref_pdu().select_unsuccessfulOutcome().ref_criticality().select_id_ricSubscription();
851
852   RICsubscriptionFailure* container = &(pduWrapper->ref_pdu()
853         .select_unsuccessfulOutcome().ref_value().select_id_ricSubscription());
854
855   using IE_value_t = RICsubscriptionFailure::protocolIEs_t::value_type;
856
857   /* RICsubscriptionFailure-IEs :  RICrequestID */
858   IE_value_t* ie_RICrequestID = new IE_value_t;
859   container->ref_protocolIEs().push_back(*ie_RICrequestID);
860
861   ie_RICrequestID->ref_id().select_id_RICrequestID();
862   ie_RICrequestID->ref_criticality().select_id_RICrequestID();
863   ie_RICrequestID->ref_value().select_id_RICrequestID()
864                                 .ref_ricRequestorID().set(params.request_id);
865   ie_RICrequestID->ref_value().select_id_RICrequestID()
866                       .ref_ricRequestSequenceNumber().set(params.seq_number);
867
868   /* RICsubscriptionFailure-IEs :  RANfunctionID */
869   IE_value_t* ie_RANfunctionID = new IE_value_t;
870   container->ref_protocolIEs().push_back(*ie_RANfunctionID);
871
872   ie_RANfunctionID->ref_id().select_id_RANfunctionID();
873   ie_RANfunctionID->ref_criticality().select_id_RANfunctionID();
874   ie_RANfunctionID->ref_value().select_id_RANfunctionID().set(params.ran_func_id);
875
876   /* RICsubscriptionFailure-IEs :  RICaction-NotAdmitted-List */
877   IE_value_t* ie_notAdmittedList = new IE_value_t;
878   container->ref_protocolIEs().push_back(*ie_notAdmittedList);
879
880   ie_notAdmittedList->ref_id().select_id_RICactions_NotAdmitted();
881   ie_notAdmittedList->ref_criticality().select_id_RICactions_NotAdmitted();
882
883   for(auto const &a : params.actionList)
884   {
885     if(!a.isAdmitted)
886     {
887       RICaction_NotAdmitted_List::value_type* item = new RICaction_NotAdmitted_List::value_type();
888
889       ie_notAdmittedList->ref_value().select_id_RICactions_NotAdmitted().push_back(*item);
890
891       item->ref_id().select_id_RICaction_NotAdmitted_Item();
892       item->ref_criticality().select_id_RICaction_NotAdmitted_Item();
893       item->ref_value().select_id_RICaction_NotAdmitted_Item().ref_ricActionID().set(a.action_id);
894
895       // set cause and sub-cause
896       switch(a.notAdmitted_cause)
897       {
898         case RICcause_radioNetwork:
899           item->ref_value().select_id_RICaction_NotAdmitted_Item().ref_ricCause().select_radioNetwork().set(a.notAdmitted_subCause);
900           break;
901
902         case RICcause_transport:
903           item->ref_value().select_id_RICaction_NotAdmitted_Item().ref_ricCause().select_transport().set(a.notAdmitted_subCause);
904           break;
905
906         case RICcause_protocol:
907           item->ref_value().select_id_RICaction_NotAdmitted_Item().ref_ricCause().select_protocol().set(a.notAdmitted_subCause);
908           break;
909
910         case RICcause_misc:
911           item->ref_value().select_id_RICaction_NotAdmitted_Item().ref_ricCause().select_misc().set(a.notAdmitted_subCause);
912           break;
913
914         case RICcause_ric:
915           item->ref_value().select_id_RICaction_NotAdmitted_Item().ref_ricCause().select_ric().set(a.notAdmitted_subCause);
916           break;
917
918         default:
919           printf("Unknown cause for action not admitted = %d", (int)a.notAdmitted_cause);
920       }
921     }
922   }
923
924   return true;
925 }
926
927
928 /*-----------------------------------------------------------------------
929                               TESTS
930 -------------------------------------------------------------------------
931 */
932 void test_E2AP_X2Setup_codec(void)
933 {
934   e2ap_pdu_t* pdu = new_e2ap_pdu();
935
936   // e2ap_init_X2SetupRequest(pdu);
937   eNB_config cfg;
938   e2ap_create_X2SetupRequest(pdu, cfg);
939
940   char pdu_str[1024];
941   e2ap_asn_print(pdu, pdu_str, sizeof(pdu_str));
942   printf("%s\n", pdu_str);
943
944   //Test encode
945   unsigned char packed_buf[4096];
946   char          err_buf[1024];
947
948   int packed_len = e2ap_asn_per_encode(pdu, packed_buf, sizeof(packed_buf),
949                                             err_buf, sizeof(err_buf));
950   if(packed_len != -1) {
951     printf("Encode successful, packed_len = %d\n", packed_len);
952   } else {
953     printf("Encode Error: %s\n", err_buf);
954   }
955
956   //Test decode
957   e2ap_pdu_t* pdu2 = new_e2ap_pdu();
958   int rc = e2ap_asn_per_decode(pdu2, packed_buf, packed_len, err_buf, sizeof(err_buf));
959   if(rc == -1) {
960     printf("Decode error: %s\n", err_buf);
961   } else {
962     printf("Decode successful\n");
963   }
964
965   e2ap_asn_print(pdu2, pdu_str, sizeof(pdu_str));
966   printf("%s\n", pdu_str);
967
968   printf("index = %d\n", e2ap_get_index(pdu2));
969   printf("procedureCode = %d\n", e2ap_get_procedureCode(pdu2));
970
971   //Test X2SetupResponse
972   e2ap_pdu_t* pdu_resp = new_e2ap_pdu();
973   e2ap_create_X2SetupResponse(pdu_resp, cfg);
974   e2ap_asn_print(pdu_resp, pdu_str, sizeof(pdu_str));
975   printf("%s\n", pdu_str);
976
977   //Test X2SetupFailure
978   e2ap_pdu_t* pdu_failure = new_e2ap_pdu();
979   e2ap_create_X2SetupFailure(pdu_failure);
980   e2ap_asn_print(pdu_failure, pdu_str, sizeof(pdu_str));
981   printf("%s \n", pdu_str);
982 }