Enhanced SIM for E2AP v1 for TS UC
[sim/e2-interface.git] / e2sim / e2apv1sim / src / ASN1 / lib / asn_x2ap.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
20 #include "asn_x2ap.hpp"
21 #include "asn_x2ap_wrapper.hpp"
22
23 /*-----------------------------------------------------------------------
24                               COMMON ROUTINES
25 -------------------------------------------------------------------------
26 */
27 x2ap_pdu_t* new_x2ap_pdu(void)
28 {
29     X2APpduWrapper* pduWrapper = new X2APpduWrapper();
30     return reinterpret_cast<x2ap_pdu_t*>(pduWrapper);
31 }
32
33 void x2ap_asn_print(x2ap_pdu_t* pdu, char* buf, size_t buf_size)
34 {
35   X2APpduWrapper* pduWrapper = reinterpret_cast<X2APpduWrapper*>(pdu);
36
37   buf[0] = 0;
38
39   strncat(buf, asn::get_printed(pduWrapper->ref_pdu()).c_str(), buf_size - 1);
40 }
41
42 int x2ap_asn_per_encode(x2ap_pdu_t* pdu, unsigned char* buf, size_t buf_size,
43                                           char* err_buf, size_t err_buf_size)
44 {
45   X2APpduWrapper* pduWrapper = reinterpret_cast<X2APpduWrapper*>(pdu);
46
47   asn::per::EncoderCtx ctx{ buf, buf_size };
48
49   if (!asn::per::pack(pduWrapper->ref_pdu(), ctx)) {
50       err_buf[0] = 0;
51       // strncat(err_buf, ctx.refErrorCtx().toString().c_str(), err_buf_size - 1);
52       return -1;
53   } else {
54     return static_cast<int>(ctx.refBuffer().getBytesUsed());
55   }
56
57 }
58
59 int x2ap_asn_per_decode(x2ap_pdu_t* pdu, unsigned char const* buf, size_t buf_size,
60                                           char* err_buf, size_t err_buf_size)
61 {
62   X2APpduWrapper* pduWrapper = reinterpret_cast<X2APpduWrapper*>(pdu);
63
64   asn::per::DecoderCtx ctx{ buf,
65                             buf_size,
66                             pduWrapper->m_allocation_buffer,
67                             pduWrapper->m_allocation_buffer_size };
68
69   if (!asn::per::unpack(pduWrapper->ref_pdu(), ctx)) {
70       err_buf[0] = 0;
71       // strncat(err_buf, ctx.refErrorCtx().toString().c_str(), err_buf_size - 1);
72       return -1;
73   }
74
75   return 0;
76
77 }
78
79 int x2ap_get_index(x2ap_pdu_t* pdu)
80 {
81   X2APpduWrapper* pduWrapper = reinterpret_cast<X2APpduWrapper*>(pdu);
82
83   return pduWrapper->ref_pdu().get_index();
84 }
85
86 int x2ap_get_procedureCode(x2ap_pdu_t* pdu)
87 {
88   X2APpduWrapper* pduWrapper = reinterpret_cast<X2APpduWrapper*>(pdu);
89
90   switch(pduWrapper->ref_pdu().get_index())
91   {
92     case 1:
93       return pduWrapper->ref_pdu().get_initiatingMessage()->ref_procedureCode().get();
94       break;
95
96     case 2:
97       return pduWrapper->ref_pdu().get_successfulOutcome()->ref_procedureCode().get();
98       break;
99
100     case 3:
101       return pduWrapper->ref_pdu().get_unsuccessfulOutcome()->ref_procedureCode().get();
102       break;
103
104     default:
105       return -1;
106   }
107
108 }
109
110 /*-----------------------------------------------------------------------
111                               MESSAGE GENERATORS
112 -------------------------------------------------------------------------
113 */
114 //X2Setup
115 bool x2ap_init_X2SetupRequest(x2ap_pdu_t* pdu)
116 {
117     X2APpduWrapper* pduWrapper = reinterpret_cast<X2APpduWrapper*>(pdu);
118
119     //Initialization
120     pduWrapper->ref_pdu().select_initiatingMessage();
121     pduWrapper->ref_pdu().select_initiatingMessage().clear();
122     pduWrapper->ref_pdu().select_initiatingMessage().ref_procedureCode().select_id_x2Setup();
123     pduWrapper->ref_pdu().select_initiatingMessage().ref_criticality().select_id_x2Setup();
124     pduWrapper->ref_pdu().select_initiatingMessage().ref_value().select_id_x2Setup();
125
126     return true;
127 }
128
129 bool x2ap_create_X2SetupRequest(x2ap_pdu_t* pdu, eNB_config &cfg)
130 {
131   X2APpduWrapper* pduWrapper = reinterpret_cast<X2APpduWrapper*>(pdu);
132
133   /* Initiaization */
134   pduWrapper->ref_pdu().select_initiatingMessage().ref_procedureCode().select_id_x2Setup();
135   pduWrapper->ref_pdu().select_initiatingMessage().ref_criticality().select_id_x2Setup();
136
137   X2SetupRequest* container =
138     &(pduWrapper->ref_pdu().select_initiatingMessage().ref_value().select_id_x2Setup());
139
140   using IE_value_t = X2SetupRequest::protocolIEs_t::value_type;
141
142   /* X2SetupRequest-IEs : GlobalENB-ID*/
143   IE_value_t* val_GlobalENB_ID = new IE_value_t;
144   container->ref_protocolIEs().push_back(*val_GlobalENB_ID);
145
146   val_GlobalENB_ID->ref_id().select_id_GlobalENB_ID();
147   val_GlobalENB_ID->ref_criticality().select_id_GlobalENB_ID();
148   val_GlobalENB_ID->ref_value().select_id_GlobalENB_ID().ref_pLMN_Identity()
149                                          .set(3, cfg.pLMN_Identity);
150
151   val_GlobalENB_ID->ref_value().select_id_GlobalENB_ID().ref_eNB_ID()
152                   .select_macro_eNB_ID().set_buffer(20, cfg.macro_eNB_ID);
153
154   /* X2SetupRequest-IEs : ServedCells*/
155   IE_value_t* val_ServedCells = new IE_value_t;
156   container->ref_protocolIEs().push_back(*val_ServedCells);
157
158   val_ServedCells->ref_id().select_id_ServedCells();
159   val_ServedCells->ref_criticality().select_id_ServedCells();
160   val_ServedCells->ref_value().select_id_ServedCells();
161
162   //Add servedCellInfo
163   ServedCells::value_type* elm = new ServedCells::value_type();
164   ServedCell_Information* info = &(elm->ref_servedCellInfo());
165   {
166     //Set ServedCell-Information: pCI, cellId, tAC, broadcastPLMNs, eUTRA-Mode-Info
167     info->ref_pCI().set(cfg.pCI);
168     info->ref_cellId().ref_pLMN_Identity().set(3, cfg.pLMN_Identity);
169     info->ref_cellId().ref_eUTRANcellIdentifier().set_buffer(28, cfg.eUTRANcellIdentifier);
170     info->ref_tAC().set(2, cfg.tAC);
171
172     BroadcastPLMNs_Item::value_type* item = new BroadcastPLMNs_Item::value_type();
173     item->set(3, cfg.pLMN_Identity);
174     info->ref_broadcastPLMNs().push_back(*item);
175
176     info->ref_eUTRA_Mode_Info().select_fDD().ref_uL_EARFCN().set(cfg.uL_EARFCN);
177     info->ref_eUTRA_Mode_Info().select_fDD().ref_dL_EARFCN().set(cfg.dL_EARFCN);
178     info->ref_eUTRA_Mode_Info().select_fDD().ref_uL_Transmission_Bandwidth()
179           .set(static_cast<Transmission_Bandwidth::index_t>(cfg.uL_Bandwidth));
180     info->ref_eUTRA_Mode_Info().select_fDD().ref_dL_Transmission_Bandwidth()
181           .set(static_cast<Transmission_Bandwidth::index_t>(cfg.dL_Bandwidth));
182   }
183   val_ServedCells->ref_value().select_id_ServedCells().push_back(*elm);
184
185   return true;
186 }
187
188 bool x2ap_create_X2SetupResponse(x2ap_pdu_t* pdu, eNB_config &cfg)
189 {
190   X2APpduWrapper* pduWrapper = reinterpret_cast<X2APpduWrapper*>(pdu);
191
192   /* Initiaization */
193   pduWrapper->ref_pdu().select_successfulOutcome().ref_procedureCode().select_id_x2Setup();
194   pduWrapper->ref_pdu().select_successfulOutcome().ref_criticality().select_id_x2Setup();
195
196   X2SetupResponse* container =
197     &(pduWrapper->ref_pdu().select_successfulOutcome().ref_value().select_id_x2Setup());
198
199   using IE_value_t = X2SetupResponse::protocolIEs_t::value_type;
200
201   /* X2SetupResponse-IEs : GlobalENB-ID*/
202   IE_value_t* val_GlobalENB_ID = new IE_value_t;
203   container->ref_protocolIEs().push_back(*val_GlobalENB_ID);
204
205   val_GlobalENB_ID->ref_id().select_id_GlobalENB_ID();
206   val_GlobalENB_ID->ref_criticality().select_id_GlobalENB_ID();
207   val_GlobalENB_ID->ref_value().select_id_GlobalENB_ID().ref_pLMN_Identity()
208                                          .set(3, cfg.pLMN_Identity);
209
210   val_GlobalENB_ID->ref_value().select_id_GlobalENB_ID().ref_eNB_ID()
211                   .select_macro_eNB_ID().set_buffer(20, cfg.macro_eNB_ID);
212
213   /* X2SetupResponse-IEs : ServedCells*/
214   IE_value_t* val_ServedCells = new IE_value_t;
215   container->ref_protocolIEs().push_back(*val_ServedCells);
216
217   val_ServedCells->ref_id().select_id_ServedCells();
218   val_ServedCells->ref_criticality().select_id_ServedCells();
219   val_ServedCells->ref_value().select_id_ServedCells();
220
221   //Add servedCellInfo
222   ServedCells::value_type* elm = new ServedCells::value_type();
223   ServedCell_Information* info = &(elm->ref_servedCellInfo());
224   {
225     //Set ServedCell-Information: pCI, cellId, tAC, broadcastPLMNs, eUTRA-Mode-Info
226     info->ref_pCI().set(cfg.pCI);
227     info->ref_cellId().ref_pLMN_Identity().set(3, cfg.pLMN_Identity);
228     info->ref_cellId().ref_eUTRANcellIdentifier().set_buffer(28, cfg.eUTRANcellIdentifier);
229     info->ref_tAC().set(2, cfg.tAC);
230
231     BroadcastPLMNs_Item::value_type* item = new BroadcastPLMNs_Item::value_type();
232     item->set(3, cfg.pLMN_Identity);
233     info->ref_broadcastPLMNs().push_back(*item);
234
235     info->ref_eUTRA_Mode_Info().select_fDD().ref_uL_EARFCN().set(cfg.uL_EARFCN);
236     info->ref_eUTRA_Mode_Info().select_fDD().ref_dL_EARFCN().set(cfg.dL_EARFCN);
237     info->ref_eUTRA_Mode_Info().select_fDD().ref_uL_Transmission_Bandwidth()
238           .set(static_cast<Transmission_Bandwidth::index_t>(cfg.uL_Bandwidth));
239     info->ref_eUTRA_Mode_Info().select_fDD().ref_dL_Transmission_Bandwidth()
240           .set(static_cast<Transmission_Bandwidth::index_t>(cfg.dL_Bandwidth));
241   }
242   val_ServedCells->ref_value().select_id_ServedCells().push_back(*elm);
243
244   return true;
245 }
246
247 bool x2ap_create_X2SetupFailure(x2ap_pdu_t* pdu)
248 {
249   X2APpduWrapper* pduWrapper = reinterpret_cast<X2APpduWrapper*>(pdu);
250
251   /* Initiaization */
252   pduWrapper->ref_pdu().select_unsuccessfulOutcome().ref_procedureCode().select_id_x2Setup();
253   pduWrapper->ref_pdu().select_unsuccessfulOutcome().ref_criticality().select_id_x2Setup();
254
255   X2SetupFailure* container =
256     &(pduWrapper->ref_pdu().select_unsuccessfulOutcome().ref_value().select_id_x2Setup());
257
258   using IE_value_t = X2SetupFailure::protocolIEs_t::value_type;
259
260   /* X2SetupFailure-IEs << id-Cause */
261   IE_value_t* val_cause = new IE_value_t;
262   container->ref_protocolIEs().push_back(*val_cause);
263
264   val_cause->ref_id().select_id_Cause();
265   val_cause->ref_criticality().select_id_Cause();
266
267   /* Cause << radioNetwork */
268   val_cause->ref_value().select_id_Cause().select_radioNetwork();
269
270   /* CauseRadioNetwork = ho-target-not-allowed (enum = 8)*/
271   val_cause->ref_value().select_id_Cause().select_radioNetwork()
272                         .set(static_cast<CauseRadioNetwork::index_t>(8));
273
274   return true;
275 }
276
277 //ENDCX2Setup
278 bool x2ap_create_ENDCX2SetupRequest(x2ap_pdu_t* pdu, eNB_config &cfg)
279 {
280   X2APpduWrapper* pduWrapper = reinterpret_cast<X2APpduWrapper*>(pdu);
281
282   /* Initiaization */
283   pduWrapper->ref_pdu().select_initiatingMessage().ref_procedureCode().select_id_endcX2Setup();
284   pduWrapper->ref_pdu().select_initiatingMessage().ref_criticality().select_id_endcX2Setup();
285
286   ENDCX2SetupRequest* container =
287     &(pduWrapper->ref_pdu().select_initiatingMessage().ref_value().select_id_endcX2Setup());
288
289   using IE_value_t = ENDCX2SetupRequest::protocolIEs_t::value_type;
290
291   /* ENDCX2SetupRequest-IEs = id-InitiatingNodeType-EndcX2Setup  */
292   IE_value_t* ie = new IE_value_t;
293   container->ref_protocolIEs().push_back(*ie);
294   ie->ref_id().select_id_InitiatingNodeType_EndcX2Setup();
295   ie->ref_criticality().select_id_InitiatingNodeType_EndcX2Setup();
296   ie->ref_value().select_id_InitiatingNodeType_EndcX2Setup();
297
298   /* InitiatingNodeType-EndcX2Setup = init-eNB {ENB-ENDCX2SetupReqIEs} */
299   ie->ref_value().select_id_InitiatingNodeType_EndcX2Setup().select_init_eNB();
300
301   using eNB_val_t = InitiatingNodeType_EndcX2Setup::init_eNB_t::value_type;
302
303   ProtocolIE_Container<ENB_ENDCX2SetupReqIEs>* eNB_node =
304     &(ie->ref_value().select_id_InitiatingNodeType_EndcX2Setup().select_init_eNB());
305
306   /* ENB-ENDCX2SetupReqIEs <-- id-GlobalENB-ID */
307   eNB_val_t* val_GlobalENB_ID = new eNB_val_t;
308   eNB_node->push_back(*val_GlobalENB_ID);
309
310   val_GlobalENB_ID->ref_id().select_id_GlobalENB_ID();
311   val_GlobalENB_ID->ref_criticality().select_id_GlobalENB_ID();
312   val_GlobalENB_ID->ref_value().select_id_GlobalENB_ID()
313                       .ref_pLMN_Identity().set(3, cfg.pLMN_Identity);
314   val_GlobalENB_ID->ref_value().select_id_GlobalENB_ID().ref_eNB_ID()
315                   .select_macro_eNB_ID().set_buffer(20, cfg.macro_eNB_ID);
316
317   /* ENB-ENDCX2SetupReqIEs <-- id-ServedEUTRAcellsENDCX2ManagementList */
318   eNB_val_t* val_EUTRAlist = new eNB_val_t;
319   eNB_node->push_back(*val_EUTRAlist);
320
321   val_EUTRAlist->ref_id().select_id_ServedEUTRAcellsENDCX2ManagementList();
322   val_EUTRAlist->ref_criticality().select_id_ServedEUTRAcellsENDCX2ManagementList();
323   val_EUTRAlist->ref_value().select_id_ServedEUTRAcellsENDCX2ManagementList();
324
325   /* ServedEUTRAcellsENDCX2ManagementList <-- servedEUTRACellInfo */
326   ServedEUTRAcellsENDCX2ManagementList::value_type* elm =
327                         new ServedEUTRAcellsENDCX2ManagementList::value_type();
328   ServedCell_Information* info = &(elm->ref_servedEUTRACellInfo());
329   {
330     //Set ServedCell-Information: pCI, cellId, tAC, broadcastPLMNs, eUTRA-Mode-Info
331     info->ref_pCI().set(cfg.pCI);
332     info->ref_cellId().ref_pLMN_Identity().set(3, cfg.pLMN_Identity);
333     info->ref_cellId().ref_eUTRANcellIdentifier().set_buffer(28, cfg.eUTRANcellIdentifier);
334     info->ref_tAC().set(2, cfg.tAC);
335
336     BroadcastPLMNs_Item::value_type* item = new BroadcastPLMNs_Item::value_type();
337     item->set(3, cfg.pLMN_Identity);
338     info->ref_broadcastPLMNs().push_back(*item);
339
340     info->ref_eUTRA_Mode_Info().select_fDD().ref_uL_EARFCN().set(cfg.uL_EARFCN);
341     info->ref_eUTRA_Mode_Info().select_fDD().ref_dL_EARFCN().set(cfg.dL_EARFCN);
342     info->ref_eUTRA_Mode_Info().select_fDD().ref_uL_Transmission_Bandwidth()
343           .set(static_cast<Transmission_Bandwidth::index_t>(cfg.uL_Bandwidth));
344     info->ref_eUTRA_Mode_Info().select_fDD().ref_dL_Transmission_Bandwidth()
345           .set(static_cast<Transmission_Bandwidth::index_t>(cfg.dL_Bandwidth));
346   }
347   val_EUTRAlist->ref_value().select_id_ServedEUTRAcellsENDCX2ManagementList()
348                                                         .push_back(*elm);
349
350   return true;
351 }
352
353 /*-----------------------------------------------------------------------
354                               TESTS
355 -------------------------------------------------------------------------
356 */
357 void test_X2Setup_codec(void)
358 {
359   x2ap_pdu_t* pdu = new_x2ap_pdu();
360
361   eNB_config cfg;
362   x2ap_create_X2SetupRequest(pdu, cfg);
363
364   char pdu_str[1024];
365   x2ap_asn_print(pdu, pdu_str, sizeof(pdu_str));
366   printf("%s\n", pdu_str);
367
368   //Test encode
369   unsigned char packed_buf[4096];
370   char          err_buf[1024];
371
372   int packed_len = x2ap_asn_per_encode(pdu, packed_buf, sizeof(packed_buf),
373                                             err_buf, sizeof(err_buf));
374   if(packed_len != -1) {
375     printf("Encode successful, packed_len = %d\n", packed_len);
376   } else {
377     printf("Encode Error: %s\n", err_buf);
378   }
379
380   //Test encode error
381   x2ap_pdu_t* pdu1 = new_x2ap_pdu();
382   x2ap_init_X2SetupRequest(pdu1);
383
384   int packed_len1 = x2ap_asn_per_encode(pdu1, packed_buf, sizeof(packed_buf),
385                                             err_buf, sizeof(err_buf));
386   if(packed_len1 != -1) {
387     printf("Encode successful, packed_len = %d\n", packed_len1);
388   } else {
389     printf("Encode Error: %s\n", err_buf);
390   }
391
392   //Test decode
393   x2ap_pdu_t* pdu2 = new_x2ap_pdu();
394   int rc = x2ap_asn_per_decode(pdu2, packed_buf, packed_len, err_buf, sizeof(err_buf));
395   if(rc == -1) {
396     printf("Decode error: %s\n", err_buf);
397   } else {
398     printf("Decode successful\n");
399   }
400
401   x2ap_asn_print(pdu2, pdu_str, sizeof(pdu_str));
402   printf("%s\n", pdu_str);
403
404   printf("index = %d\n", x2ap_get_index(pdu2));
405   printf("procedureCode = %d\n", x2ap_get_procedureCode(pdu2));
406
407
408   //Test decode error
409   x2ap_pdu_t* pdu3 = new_x2ap_pdu();
410   int rc2 = x2ap_asn_per_decode(pdu3, packed_buf, 1, err_buf, sizeof(err_buf));
411   if(rc2 == -1) {
412     printf("Decode error: %s\n", err_buf);
413   } else {
414     printf("Decode successful\n");
415   }
416
417   //Test X2SetupResponse
418   x2ap_pdu_t* pdu_resp = new_x2ap_pdu();
419   x2ap_create_X2SetupResponse(pdu_resp, cfg);
420   x2ap_asn_print(pdu_resp, pdu_str, sizeof(pdu_str));
421   printf("%s\n", pdu_str);
422
423   //Test X2SetupFailure
424   x2ap_pdu_t* pdu_failure = new_x2ap_pdu();
425   x2ap_create_X2SetupFailure(pdu_failure);
426   x2ap_asn_print(pdu_failure, pdu_str, sizeof(pdu_str));
427   printf("%s \n", pdu_str);
428 }