2 ==================================================================================
4 Copyright (c) 2018-2019 AT&T Intellectual Property.
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
10 http://www.apache.org/licenses/LICENSE-2.0
12 Unless required by applicable law or agreed to in writing, softwares
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 ==================================================================================
20 /* Classes to handle E2 service model based on e2sm-gNB-X2-release-1-v040.asn */
27 e2sm_event_trigger::e2sm_event_trigger(void){
29 memset(&gNodeB_ID, 0, sizeof(GlobalGNB_ID_t));
32 event_trigger = ( E2SM_gNB_X2_eventTriggerDefinition_t *)calloc(1, sizeof( E2SM_gNB_X2_eventTriggerDefinition_t));
33 assert(event_trigger != 0);
35 // allocate space for gNodeB id (used for encoding)
36 gNodeB_ID.gNB_ID.choice.gNB_ID.buf = 0;
37 gNodeB_ID.gNB_ID.choice.gNB_ID.buf = (uint8_t *)calloc(4, sizeof(uint8_t));
38 assert(gNodeB_ID.gNB_ID.choice.gNB_ID.buf != 0);
40 // allocate space for plmn identity (used for encoding)
41 gNodeB_ID.pLMN_Identity.buf = 0;
42 gNodeB_ID.pLMN_Identity.buf = (uint8_t *) calloc(4, sizeof(uint8_t));
43 assert(gNodeB_ID.pLMN_Identity.buf != 0);
46 ie_list = ( struct InterfaceProtocolIE_Item *) calloc(INITIAL_LIST_SIZE, sizeof( struct InterfaceProtocolIE_Item));
48 ie_list_size = INITIAL_LIST_SIZE;
51 condition_list = (E2SM_gNB_X2_eventTriggerDefinition::E2SM_gNB_X2_eventTriggerDefinition__interfaceProtocolIE_List *) calloc(1, sizeof(E2SM_gNB_X2_eventTriggerDefinition::E2SM_gNB_X2_eventTriggerDefinition__interfaceProtocolIE_List ));
52 assert(condition_list != 0);
58 e2sm_event_trigger::~e2sm_event_trigger(void){
60 mdclog_write(MDCLOG_INFO, "Freeing event trigger object memory");
61 for(int i = 0; i < condition_list->list.size; i++){
62 condition_list->list.array[i] = 0;
65 if (condition_list->list.size > 0){
66 free(condition_list->list.array);
67 condition_list->list.array = 0;
68 condition_list->list.size = 0;
69 condition_list->list.count = 0;
75 free(gNodeB_ID.gNB_ID.choice.gNB_ID.buf);
76 gNodeB_ID.gNB_ID.choice.gNB_ID.buf = 0;
78 free(gNodeB_ID.pLMN_Identity.buf);
79 gNodeB_ID.pLMN_Identity.buf = 0;
84 event_trigger->interface_ID.choice.global_gNB_ID = 0;
85 event_trigger->interfaceProtocolIE_List = 0;
87 ASN_STRUCT_FREE(asn_DEF_E2SM_gNB_X2_eventTriggerDefinition, event_trigger);
88 mdclog_write(MDCLOG_INFO, "Freed event trigger object memory");
93 bool e2sm_event_trigger::encode_event_trigger(unsigned char *buf, size_t *size, e2sm_event_trigger_helper &helper){
96 res = set_fields(event_trigger, helper);
101 int ret_constr = asn_check_constraints(&asn_DEF_E2SM_gNB_X2_eventTriggerDefinition, event_trigger, errbuf, &errbuf_len);
103 error_string.assign(&errbuf[0], errbuf_len);
107 //xer_fprint(stdout, &asn_DEF_E2SM_gNB_X2_eventTriggerDefinition, event_trigger);
109 asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2SM_gNB_X2_eventTriggerDefinition, event_trigger, buf, *size);
111 if(retval.encoded == -1){
112 error_string.assign(strerror(errno));
115 else if (retval.encoded > *size){
116 std::stringstream ss;
117 ss <<"Error encoding event trigger definition. Reason = encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl;
118 error_string = ss.str();
122 *size = retval.encoded;
129 bool e2sm_event_trigger::set_fields(E2SM_gNB_X2_eventTriggerDefinition_t * ref_event_trigger, e2sm_event_trigger_helper & helper){
130 if(ref_event_trigger == 0){
131 error_string = "Invalid reference for Event Trigger Definition set fields";
135 // set the message type
136 ref_event_trigger->interfaceMessageType.procedureCode = helper.procedure_code;
137 ref_event_trigger->interfaceMessageType.typeOfMessage = helper.message_type;
139 ref_event_trigger->interfaceDirection = helper.interface_direction;
140 ref_event_trigger->interface_ID.present = Interface_ID_PR_global_gNB_ID;
142 ref_event_trigger->interface_ID.choice.global_gNB_ID = &gNodeB_ID;
144 // to do : need to put correct code here for upding plmn id and gNodeB
145 // for now just place holders :
146 //================================================================
147 memcpy(gNodeB_ID.pLMN_Identity.buf, helper.plmn_id.c_str(), 3);
148 gNodeB_ID.pLMN_Identity.size = 3;
150 memcpy(gNodeB_ID.gNB_ID.choice.gNB_ID.buf, helper.egNB_id.c_str(), 3);
151 gNodeB_ID.gNB_ID.choice.gNB_ID.size = 3;
153 // we only do global gNodeB id for now, not eNodeB
154 gNodeB_ID.gNB_ID.present = GNB_ID_PR_gNB_ID;
155 //================================================================
158 // Add in any requested IE items
159 std::vector<Item> * ref_ie_array = helper.get_list();
161 if (ref_ie_array->size() == 0){
162 event_trigger->interfaceProtocolIE_List = 0;
166 event_trigger->interfaceProtocolIE_List = condition_list;
169 if(ref_ie_array->size() > ie_list_size){
170 struct InterfaceProtocolIE_Item *new_ref = 0;
171 ie_list_size = 2 * ref_ie_array->size();
172 new_ref = (struct InterfaceProtocolIE_Item *)realloc(ie_list, ie_list_size);
173 assert(new_ref != 0);
177 // reset the count so that adds start from the beginning
178 ref_event_trigger->interfaceProtocolIE_List->list.count = 0;
180 for(unsigned int i = 0; i < ref_ie_array->size(); i++){
182 ie_list[i].interfaceProtocolIE_ID = (*ref_ie_array)[i].interface_id;
183 ie_list[i].interfaceProtocolIE_Test = (*ref_ie_array)[i].test;
185 //switch(ie_list[i].interfaceProtocolIE_Value.present){
186 switch((*ref_ie_array)[i].val_type){
188 case (InterfaceProtocolIE_Value_PR_valueInt):
189 ie_list[i].interfaceProtocolIE_Value.present = InterfaceProtocolIE_Value_PR_valueInt;
190 ie_list[i].interfaceProtocolIE_Value.choice.valueInt = (*ref_ie_array)[i].value_n;
193 case (InterfaceProtocolIE_Value_PR_valueEnum):
194 ie_list[i].interfaceProtocolIE_Value.present = InterfaceProtocolIE_Value_PR_valueEnum;
195 ie_list[i].interfaceProtocolIE_Value.choice.valueEnum = (*ref_ie_array)[i].value_n;
198 case (InterfaceProtocolIE_Value_PR_valueBool):
199 ie_list[i].interfaceProtocolIE_Value.present = InterfaceProtocolIE_Value_PR_valueBool;
200 ie_list[i].interfaceProtocolIE_Value.choice.valueBool = (*ref_ie_array)[i].value_n;
203 case (InterfaceProtocolIE_Value_PR_valueBitS):
204 ie_list[i].interfaceProtocolIE_Value.present = InterfaceProtocolIE_Value_PR_valueBitS;
205 ie_list[i].interfaceProtocolIE_Value.choice.valueBitS.buf = (uint8_t *)(*ref_ie_array)[i].value_s.c_str();
206 ie_list[i].interfaceProtocolIE_Value.choice.valueBitS.size = (*ref_ie_array)[i].value_s.length();
211 std::stringstream ss;
212 ss <<"Error ! " << __FILE__ << "," << __LINE__ << " illegal enum " << (*ref_ie_array)[i].val_type << " for interface Protocol IE value" << std::endl;
213 std::string error_string = ss.str();
218 ASN_SEQUENCE_ADD(ref_event_trigger->interfaceProtocolIE_List, &ie_list[i]);
226 bool e2sm_event_trigger::get_fields(E2SM_gNB_X2_eventTriggerDefinition_t * ref_event_trigger, e2sm_event_trigger_helper & helper){
228 if (ref_event_trigger == 0){
229 error_string = "Invalid reference for Event Trigger definition get fields";
233 helper.procedure_code = ref_event_trigger->interfaceMessageType.procedureCode;
234 helper.message_type = ref_event_trigger->interfaceMessageType.typeOfMessage;
235 helper.interface_direction = ref_event_trigger->interfaceDirection;
237 helper.plmn_id.assign((const char *)ref_event_trigger->interface_ID.choice.global_gNB_ID->pLMN_Identity.buf, ref_event_trigger->interface_ID.choice.global_gNB_ID->pLMN_Identity.size);
238 helper.egNB_id.assign((const char *)ref_event_trigger->interface_ID.choice.global_gNB_ID->gNB_ID.choice.gNB_ID.buf, ref_event_trigger->interface_ID.choice.global_gNB_ID->gNB_ID.choice.gNB_ID.size);
247 e2sm_indication::e2sm_indication(void) {
249 memset(&gNodeB_ID, 0, sizeof(GlobalGNB_ID_t));
251 // allocate space for gNodeB id (used for encoding)
252 gNodeB_ID.gNB_ID.choice.gNB_ID.buf = (uint8_t *)calloc(4, sizeof(uint8_t));
253 assert(gNodeB_ID.gNB_ID.choice.gNB_ID.buf != 0);
255 // allocate space for plmn identity (used for encoding)
256 gNodeB_ID.pLMN_Identity.buf = (uint8_t *) calloc(4, sizeof(uint8_t));
257 assert(gNodeB_ID.pLMN_Identity.buf != 0);
260 header = (E2SM_gNB_X2_indicationHeader_t *)calloc(1, sizeof(E2SM_gNB_X2_indicationHeader_t));
264 message = (E2SM_gNB_X2_indicationMessage_t *)calloc(1, sizeof(E2SM_gNB_X2_indicationMessage_t));
265 assert(message != 0);
268 e2sm_indication::~e2sm_indication(void){
269 mdclog_write(MDCLOG_INFO, "Freeing E2SM Indication object memory");
271 free(gNodeB_ID.gNB_ID.choice.gNB_ID.buf);
272 free(gNodeB_ID.pLMN_Identity.buf);
274 header->interface_ID.choice.global_gNB_ID = 0;
276 ASN_STRUCT_FREE(asn_DEF_E2SM_gNB_X2_indicationHeader, header);
278 message->interfaceMessage.buf = 0;
279 message->interfaceMessage.size = 0;
281 ASN_STRUCT_FREE(asn_DEF_E2SM_gNB_X2_indicationMessage, message);
282 mdclog_write(MDCLOG_INFO, "Freed E2SM Indication object memory");
288 bool e2sm_indication::encode_indication_header(unsigned char *buf, size_t *size, e2sm_header_helper &helper){
291 res = set_header_fields(header, helper);
296 int ret_constr = asn_check_constraints(&asn_DEF_E2SM_gNB_X2_indicationHeader, header, errbuf, &errbuf_len);
298 error_string.assign(&errbuf[0], errbuf_len);
299 error_string = "E2SM Indication Header Constraint failed : " + error_string;
304 asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2SM_gNB_X2_indicationHeader, header, buf, *size);
306 if(retval.encoded == -1){
307 error_string.assign(strerror(errno));
308 error_string = "Error encoding E2SM Indication Header. Reason = " + error_string;
311 else if (retval.encoded > *size){
312 std::stringstream ss;
313 ss <<"Error encoding E2SM Indication Header . Reason = encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl;
314 error_string = ss.str();
318 *size = retval.encoded;
325 bool e2sm_indication::encode_indication_message(unsigned char *buf, size_t *size, e2sm_message_helper &helper){
327 set_message_fields(message, helper);
329 int ret_constr = asn_check_constraints(&asn_DEF_E2SM_gNB_X2_indicationMessage, message, errbuf, &errbuf_len);
331 error_string.assign(&errbuf[0], errbuf_len);
332 error_string = "E2SM Indication Message Constraint failed : " + error_string;
336 asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2SM_gNB_X2_indicationMessage, message, buf, *size);
337 if(retval.encoded == -1){
338 error_string.assign(strerror(errno));
339 error_string = "Error encoding E2SM Indication Header. Reason = " + error_string;
342 else if (retval.encoded > *size){
343 std::stringstream ss;
344 ss <<"Error encoding E2SM Indication Message . Reason = encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl;
345 error_string = ss.str();
350 *size = retval.encoded;
358 // Used when generating an indication header
359 bool e2sm_indication::set_header_fields(E2SM_gNB_X2_indicationHeader_t *header, e2sm_header_helper &helper){
362 error_string = "Invalid reference for E2SM Indication Header set fields";
367 header->interfaceDirection = helper.interface_direction;
368 header->interface_ID.present = Interface_ID_PR_global_gNB_ID;
369 header->interface_ID.choice.global_gNB_ID = &gNodeB_ID;
372 // to do : need to put correct code here for upding plmn id and gNodeB
373 // for now just place holders :
374 memcpy(gNodeB_ID.pLMN_Identity.buf, helper.plmn_id.c_str(), 3);
375 gNodeB_ID.pLMN_Identity.size = 3;
377 memcpy(gNodeB_ID.gNB_ID.choice.gNB_ID.buf, helper.egNB_id.c_str(), 3);
378 gNodeB_ID.gNB_ID.choice.gNB_ID.size = 3;
380 // we only do global gNodeB id for now, not eNodeB
381 gNodeB_ID.gNB_ID.present = GNB_ID_PR_gNB_ID;
388 // used when decoding an indication header
389 bool e2sm_indication::get_header_fields(E2SM_gNB_X2_indicationHeader_t *header, e2sm_header_helper &helper){
392 error_string = "Invalid reference for E2SM Indication header get fields";
396 helper.interface_direction = header->interfaceDirection;
397 helper.plmn_id.assign((const char *)header->interface_ID.choice.global_gNB_ID->pLMN_Identity.buf, header->interface_ID.choice.global_gNB_ID->pLMN_Identity.size);
398 helper.egNB_id.assign((const char *)header->interface_ID.choice.global_gNB_ID->gNB_ID.choice.gNB_ID.buf, header->interface_ID.choice.global_gNB_ID->gNB_ID.choice.gNB_ID.size);
400 // to do : add code to decipher plmn and global gnodeb from ints (since that is likely the convention for packing)
407 // Used when generating an indication message
408 bool e2sm_indication::set_message_fields(E2SM_gNB_X2_indicationMessage_t *interface_message, e2sm_message_helper &helper){
410 if(interface_message == 0){
411 error_string = "Invalid reference for E2SM Indication Message set fields";
415 // interface-message is an octet string. just point it to the buffer
416 interface_message->interfaceMessage.buf = &(helper.x2ap_pdu[0]);
417 interface_message->interfaceMessage.size = helper.x2ap_pdu_size;
423 // used when decoding an indication message
424 bool e2sm_indication::get_message_fields( E2SM_gNB_X2_indicationMessage_t *interface_message, e2sm_message_helper &helper){
427 if(interface_message == 0){
428 error_string = "Invalid reference for E2SM Indication Message get fields";
432 // interface message is an octet string
433 helper.x2ap_pdu = interface_message->interfaceMessage.buf;;
434 helper.x2ap_pdu_size = interface_message->interfaceMessage.size;
443 e2sm_control::e2sm_control(void) {
445 memset(&gNodeB_ID, 0, sizeof(GlobalGNB_ID_t));
447 // allocate space for gNodeB id (used for encoding)
448 gNodeB_ID.gNB_ID.choice.gNB_ID.buf = (uint8_t *)calloc(4, sizeof(uint8_t));
449 assert(gNodeB_ID.gNB_ID.choice.gNB_ID.buf != 0);
451 // allocate space for plmn identity (used for encoding)
452 gNodeB_ID.pLMN_Identity.buf = (uint8_t *) calloc(4, sizeof(uint8_t));
453 assert(gNodeB_ID.pLMN_Identity.buf != 0);
456 header = (E2SM_gNB_X2_controlHeader_t *)calloc(1, sizeof(E2SM_gNB_X2_controlHeader_t));
460 message = (E2SM_gNB_X2_controlMessage_t *)calloc(1, sizeof(E2SM_gNB_X2_controlMessage_t));
461 assert(message != 0);
464 e2sm_control::~e2sm_control(void){
465 mdclog_write(MDCLOG_INFO, "Freeing E2SM Control object memory");
467 free(gNodeB_ID.gNB_ID.choice.gNB_ID.buf);
468 free(gNodeB_ID.pLMN_Identity.buf);
469 header->interface_ID.choice.global_gNB_ID = 0;
470 ASN_STRUCT_FREE(asn_DEF_E2SM_gNB_X2_controlHeader, header);
472 message->interfaceMessage.buf = 0;
473 ASN_STRUCT_FREE(asn_DEF_E2SM_gNB_X2_controlMessage, message);
475 mdclog_write(MDCLOG_INFO, "Freed E2SM Control object memory");
481 bool e2sm_control::encode_control_header(unsigned char *buf, size_t *size, e2sm_header_helper &helper){
484 res = set_header_fields(header, helper);
489 int ret_constr = asn_check_constraints(&asn_DEF_E2SM_gNB_X2_controlHeader, header, errbuf, &errbuf_len);
491 error_string.assign(&errbuf[0], errbuf_len);
492 error_string = "E2SM Control Header Constraint failed : " + error_string;
497 asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2SM_gNB_X2_controlHeader, header, buf, *size);
499 if(retval.encoded == -1){
500 error_string.assign(strerror(errno));
501 error_string = "Error encoding E2SM Control Header. Reason = " + error_string;
504 else if (retval.encoded > *size){
505 std::stringstream ss;
506 ss <<"Error encoding E2SM Control Header . Reason = encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl;
507 error_string = ss.str();
511 *size = retval.encoded;
518 bool e2sm_control::encode_control_message(unsigned char *buf, size_t *size, e2sm_message_helper &helper){
520 set_message_fields(message, helper);
522 int ret_constr = asn_check_constraints(&asn_DEF_E2SM_gNB_X2_controlMessage, message, errbuf, &errbuf_len);
524 error_string.assign(&errbuf[0], errbuf_len);
525 error_string = "E2SM Control Message Constraint failed : " + error_string;
529 asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2SM_gNB_X2_controlMessage, message, buf, *size);
530 if(retval.encoded == -1){
531 error_string.assign(strerror(errno));
532 error_string = "Error encoding E2SM Control Message. Reason = " + error_string;
535 else if (retval.encoded > *size){
536 std::stringstream ss;
537 ss <<"Error encoding E2SM Control Message . Reason = encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl;
538 error_string = ss.str();
543 *size = retval.encoded;
551 // Used when generating an indication header
552 bool e2sm_control::set_header_fields(E2SM_gNB_X2_controlHeader_t *header, e2sm_header_helper &helper){
555 error_string = "Invalid reference for E2SM Control Header set fields";
560 header->interfaceDirection = helper.interface_direction;
561 header->interface_ID.present = Interface_ID_PR_global_gNB_ID;
562 header->interface_ID.choice.global_gNB_ID = &gNodeB_ID;
565 // to do : need to put correct code here for upding plmn id and gNodeB
566 // for now just place holders :
567 memcpy(gNodeB_ID.pLMN_Identity.buf, helper.plmn_id.c_str(), 3);
568 gNodeB_ID.pLMN_Identity.size = 3;
570 memcpy(gNodeB_ID.gNB_ID.choice.gNB_ID.buf, helper.egNB_id.c_str(), 3);
571 gNodeB_ID.gNB_ID.choice.gNB_ID.size = 3;
573 // we only do global gNodeB id for now, not eNodeB
574 gNodeB_ID.gNB_ID.present = GNB_ID_PR_gNB_ID;
581 // used when decoding an indication header
582 bool e2sm_control::get_header_fields(E2SM_gNB_X2_controlHeader_t *header, e2sm_header_helper &helper){
585 error_string = "Invalid reference for E2SM Control header get fields";
589 helper.interface_direction = header->interfaceDirection;
590 helper.plmn_id.assign((const char *)header->interface_ID.choice.global_gNB_ID->pLMN_Identity.buf, header->interface_ID.choice.global_gNB_ID->pLMN_Identity.size);
591 helper.egNB_id.assign((const char *)header->interface_ID.choice.global_gNB_ID->gNB_ID.choice.gNB_ID.buf, header->interface_ID.choice.global_gNB_ID->gNB_ID.choice.gNB_ID.size);
593 // to do : add code to decipher plmn and global gnodeb from ints (since that is likely the convention for packing)
600 // Used when generating an indication message
601 bool e2sm_control::set_message_fields(E2SM_gNB_X2_controlMessage_t *interface_message, e2sm_message_helper &helper){
603 if(interface_message == 0){
604 error_string = "Invalid reference for E2SM Control Message set fields";
608 // interface-message is an octet string. just point it to the buffer
609 interface_message->interfaceMessage.buf = &(helper.x2ap_pdu[0]);
610 interface_message->interfaceMessage.size = helper.x2ap_pdu_size;
616 // used when decoding an indication message
617 bool e2sm_control::get_message_fields( E2SM_gNB_X2_controlMessage_t *interface_message, e2sm_message_helper &helper){
620 if(interface_message == 0){
621 error_string = "Invalid reference for E2SM Control Message get fields";
625 // interface message is an octet string
626 helper.x2ap_pdu = interface_message->interfaceMessage.buf;;
627 helper.x2ap_pdu_size = interface_message->interfaceMessage.size;