From 6df19a4dacb4fcb6edb35a32af9c8f5c07c95e37 Mon Sep 17 00:00:00 2001 From: sjana Date: Thu, 19 Mar 2020 12:06:12 -0400 Subject: [PATCH] Initial commit of source directory Issue-ID: RICAPP-63 Signed-off-by: sjana Change-Id: I6a13d89aa00887369187928acd5b14d31c1d6368 --- src/Makefile | 76 +++ src/README | 25 + src/hw_xapp_main.cc | 96 +++ src/routes.txt | 19 + src/run_xapp.sh | 38 ++ src/xapp-asn/e2ap/e2ap_control.cc | 266 +++++++++ src/xapp-asn/e2ap/e2ap_control.hpp | 66 +++ src/xapp-asn/e2ap/e2ap_control_helper.hpp | 50 ++ src/xapp-asn/e2ap/e2ap_control_response.cc | 415 +++++++++++++ src/xapp-asn/e2ap/e2ap_control_response.hpp | 79 +++ src/xapp-asn/e2ap/e2ap_indication.cc | 283 +++++++++ src/xapp-asn/e2ap/e2ap_indication.hpp | 67 +++ src/xapp-asn/e2ap/e2ap_indication_helper.hpp | 47 ++ src/xapp-asn/e2ap/generic_helpers.hpp | 49 ++ src/xapp-asn/e2ap/response_helper.hpp | 181 ++++++ src/xapp-asn/e2ap/subscription_delete_request.cc | 180 ++++++ src/xapp-asn/e2ap/subscription_delete_request.hpp | 67 +++ src/xapp-asn/e2ap/subscription_delete_response.cc | 292 +++++++++ src/xapp-asn/e2ap/subscription_delete_response.hpp | 79 +++ src/xapp-asn/e2ap/subscription_helper.hpp | 195 ++++++ src/xapp-asn/e2ap/subscription_request.cc | 308 ++++++++++ src/xapp-asn/e2ap/subscription_request.hpp | 73 +++ src/xapp-asn/e2ap/subscription_response.cc | 583 ++++++++++++++++++ src/xapp-asn/e2ap/subscription_response.hpp | 81 +++ src/xapp-asn/e2sm/e2sm.cc | 660 +++++++++++++++++++++ src/xapp-asn/e2sm/e2sm.hpp | 145 +++++ src/xapp-asn/e2sm/e2sm_helpers.hpp | 113 ++++ src/xapp-mgmt/msgs_proc.cc | 282 +++++++++ src/xapp-mgmt/msgs_proc.hpp | 68 +++ src/xapp-mgmt/subs_mgmt.cc | 358 +++++++++++ src/xapp-mgmt/subs_mgmt.hpp | 334 +++++++++++ src/xapp-utils/xapp_config.cc | 226 +++++++ src/xapp-utils/xapp_config.hpp | 86 +++ src/xapp-utils/xapp_rmr.cc | 121 ++++ src/xapp-utils/xapp_rmr.hpp | 117 ++++ src/xapp-utils/xapp_sdl.cc | 47 ++ src/xapp-utils/xapp_sdl.hpp | 61 ++ src/xapp.cc | 156 +++++ src/xapp.hpp | 78 +++ 39 files changed, 6467 insertions(+) create mode 100755 src/Makefile create mode 100644 src/README create mode 100644 src/hw_xapp_main.cc create mode 100644 src/routes.txt create mode 100755 src/run_xapp.sh create mode 100644 src/xapp-asn/e2ap/e2ap_control.cc create mode 100644 src/xapp-asn/e2ap/e2ap_control.hpp create mode 100644 src/xapp-asn/e2ap/e2ap_control_helper.hpp create mode 100644 src/xapp-asn/e2ap/e2ap_control_response.cc create mode 100644 src/xapp-asn/e2ap/e2ap_control_response.hpp create mode 100644 src/xapp-asn/e2ap/e2ap_indication.cc create mode 100644 src/xapp-asn/e2ap/e2ap_indication.hpp create mode 100644 src/xapp-asn/e2ap/e2ap_indication_helper.hpp create mode 100644 src/xapp-asn/e2ap/generic_helpers.hpp create mode 100644 src/xapp-asn/e2ap/response_helper.hpp create mode 100644 src/xapp-asn/e2ap/subscription_delete_request.cc create mode 100644 src/xapp-asn/e2ap/subscription_delete_request.hpp create mode 100644 src/xapp-asn/e2ap/subscription_delete_response.cc create mode 100644 src/xapp-asn/e2ap/subscription_delete_response.hpp create mode 100644 src/xapp-asn/e2ap/subscription_helper.hpp create mode 100644 src/xapp-asn/e2ap/subscription_request.cc create mode 100644 src/xapp-asn/e2ap/subscription_request.hpp create mode 100644 src/xapp-asn/e2ap/subscription_response.cc create mode 100644 src/xapp-asn/e2ap/subscription_response.hpp create mode 100644 src/xapp-asn/e2sm/e2sm.cc create mode 100644 src/xapp-asn/e2sm/e2sm.hpp create mode 100644 src/xapp-asn/e2sm/e2sm_helpers.hpp create mode 100644 src/xapp-mgmt/msgs_proc.cc create mode 100644 src/xapp-mgmt/msgs_proc.hpp create mode 100644 src/xapp-mgmt/subs_mgmt.cc create mode 100644 src/xapp-mgmt/subs_mgmt.hpp create mode 100644 src/xapp-utils/xapp_config.cc create mode 100644 src/xapp-utils/xapp_config.hpp create mode 100755 src/xapp-utils/xapp_rmr.cc create mode 100755 src/xapp-utils/xapp_rmr.hpp create mode 100644 src/xapp-utils/xapp_sdl.cc create mode 100644 src/xapp-utils/xapp_sdl.hpp create mode 100644 src/xapp.cc create mode 100644 src/xapp.hpp diff --git a/src/Makefile b/src/Makefile new file mode 100755 index 0000000..700b0d5 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,76 @@ +CXX:= g++ --std=c++14 -O2 +CC:= gcc -O2 + +SRC:=./ +HWSRC:=./ +UTILSRC=./xapp-utils +MSGSRC:=./xapp-mgmt + +ASNSRC:=../asn1c_defs +E2APSRC:=./xapp-asn/e2ap +E2SMSRC:=./xapp-asn/e2sm + +####### Logging library and flags +CLOGFLAGS:= `pkg-config mdclog --cflags` +LOG_LIBS:= `pkg-config mdclog --libs` +CURL_LIBS:= `pkg-config libcurl --libs` + +######## Keep include dirs separate so we have transparency +BASEFLAGS= -Wall -std=c++14 $(CLOGFLAGS) +C_BASEFLAGS= -Wall $(CLOGFLAGS) -DASN_DISABLE_OER_SUPPORT + +XAPPFLAGS= -I./ +HWFLAGS= -I./ +UTILFLAGS= -I$(UTILSRC) +MSGFLAGS= -I$(MSGSRC) + +ASNFLAGS=-I$(ASNSRC) -DASN_DISABLE_OER_SUPPORT +E2APFLAGS = -I$(E2APSRC) +E2SMFLAGS = -I$(E2SMSRC) + +########libs +LIBS= -lsdl -lrmr_nng -lnng -lpthread -lm $(LOG_LIBS) $(CURL_LIBS) +COV_FLAGS= -fprofile-arcs -ftest-coverage + +####### +HWXAPP_SRC= hw_xapp_main.cc +XAPP_SRC= xapp.cc +UTIL_SRC= $(wildcard $(UTILSRC)/*.cc) +MSG_SRC= $(wildcard $(MSGSRC)/*.cc) + +E2AP_SRC= $(wildcard $(E2APSRC)/*.cc) +E2SM_SRC= $(wildcard $(E2SMSRC)/*.cc) +ASN1C_SRC= $(wildcard $(ASNSRC)/*.c) + +##############Objects +UTIL_OBJ=${UTIL_SRC:.cc=.o} +XAPP_OBJ=${XAPP_SRC:.cc=.o} +HWXAPP_OBJ= ${HWXAPP_SRC:.cc=.o} +MSG_OBJ= ${MSG_SRC:.cc=.o} + +E2AP_OBJ = $(E2AP_SRC:.cc=.o) +E2SM_OBJ = $(E2SM_SRC:.cc=.o) +ASN1C_MODULES = $(ASN1C_SRC:.c=.o) + +$(ASN1C_MODULES): export CFLAGS = $(C_BASEFLAGS) $(ASNFLAGS) +$(UTIL_OBJ):export CPPFLAGS=$(BASEFLAGS) $(UTILFLAGS) $(E2APFLAGS) $(E2SMFLAGS) $(ASNFLAGS) $(MSGFLAGS) + +$(MSG_OBJ):export CPPFLAGS=$(BASEFLAGS) $(MSGFLAGS) $(ASNFLAGS) $(E2APFLAGS) $(E2SMFLAGS) +$(E2AP_OBJ): export CPPFLAGS = $(BASEFLAGS) $(ASNFLAGS) $(E2APFLAGS) +$(E2SM_OBJ): export CPPFLAGS = $(BASEFLAGS) $(ASNFLAGS) $(E2SMFLAGS) +$(XAPP_OBJ): export CPPFLAGS = $(BASEFLAGS) $(XAPPFLAGS) $(UTILFLAGS) $(MSGFLAGS) $(E2APFLAGS) $(E2SMFLAGS) $(ASNFLAGS) + +$(HWXAPP_OBJ):export CPPFLAGS=$(BASEFLAGS) $(HWFLAGS) $(XAPPFLAGS) $(UTILFLAGS) $(MSGFLAGS) $(E2APFLAGS) $(E2SMFLAGS) $(ASNFLAGS) + +OBJ= $(HWXAPP_OBJ) $(UTIL_OBJ) $(MSG_OBJ) $(ASN1C_MODULES) $(E2AP_OBJ) $(E2SM_OBJ) $(XAPP_OBJ) + +print-% : ; @echo $* = $($*) + +hw_xapp_main: $(OBJ) + $(CXX) -o $@ $(OBJ) $(LIBS) $(CPPFLAGS) $(CLOGFLAGS) + +install: hw_xapp_main + install -D hw_xapp_main /usr/local/bin/hw_xapp_main + +clean: + -rm *.o $(ASNSRC)/*.o $(E2APSRC)/*.o $(UTILSRC)/*.o $(E2SMSRC)/*.o $(MSGSRC)/*.o $(SRC)/*.o hw_xapp_main diff --git a/src/README b/src/README new file mode 100644 index 0000000..2c70d42 --- /dev/null +++ b/src/README @@ -0,0 +1,25 @@ +================================================================================== + + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== + +This repository consists of HelloWorld Xapp developed in C++. Its envisioned to be the most simplest example Xapp. +It is required to have following features + +1) E2 Subscription Handling +2) A1 Policy Handling +3) SDL Access +4) Health Check +5)... diff --git a/src/hw_xapp_main.cc b/src/hw_xapp_main.cc new file mode 100644 index 0000000..3c45e6a --- /dev/null +++ b/src/hw_xapp_main.cc @@ -0,0 +1,96 @@ +/* +================================================================================== + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== +*/ +/* + * hw_xapp_main.cc + * Created on: Dec, 2019 + * Author: Shraboni Jana + */ + +#include "xapp.hpp" +#include "subscription_request.hpp" +#include "xapp_sdl.hpp" + +void signalHandler( int signum ) { + cout << "Interrupt signal (" << signum << ") received.\n"; + exit(signum); +} + +int main(int argc, char *argv[]){ + + //get configuration + XappSettings config; + //change the priority depending upon application requirement + config.loadDefaultSettings(); + config.loadEnvVarSettings(); + config.loadCmdlineSettings(argc, argv); + + //getting the listening port and xapp name info + std::string port = config[XappSettings::SettingName::HW_PORTS]; + std::string name = config[XappSettings::SettingName::XAPP_NAME]; + + + //initialize rmr + std::unique_ptr rmr; + rmr = std::make_unique(name,port); + rmr->xapp_rmr_init(); + + //Register signal handler to stop + signal(SIGINT, signalHandler); + signal(SIGTERM, signalHandler); + + //Test SDL. + XappSDL sdl = XappSDL("hw-xapp"); + + //Initiate the Xapp functionality + std::unique_ptr hw_xapp = std::make_unique(std::ref(config), std::ref(*rmr),std::ref(sdl)); + + + //define the startup mode. + hw_xapp->startup(); + + //Register Callback Handlers + //Register E2 Msg Handlers - Subscription/Indication. + //Register A1 Msg Handlers. + //Register Callback Handlers + + + //start the receiver thread listening at HW_PORT + //currently only one receiver thread. In total how many receiver threads depend on the xapp developer. + //Register all the handlers required and start the receiver + + //register_msgproc(RIC_SUB_RESP, sub_handler); + //register_msgproc(RIC_SUB_DEL_RESP, sub_handler); + //register_msgproc(RIC_SUB_FAILURE, sub_handler); + + + hw_xapp->start_xapp_receiver(); + sleep(5); + + + //Delete all subscriptions if any based on Xapp Mode. + //xapp->shutdown(); + + while(1){ + sleep(1); + } + + return 0; +} + + + diff --git a/src/routes.txt b/src/routes.txt new file mode 100644 index 0000000..3dd7cdd --- /dev/null +++ b/src/routes.txt @@ -0,0 +1,19 @@ +newrt|start +rte|0|localhost:4560 +rte|2|localhost:38000 +rte|100|localhost:4560 +rte|10002|localhost:4560 +rte|10005|localhost:4560 +rte|10003|localhost:38000 +rte|12010|localhost:38000 +rte|12020|localhost:38000 +rte|12011|localhost:4560 +rte|12012|localhost:4560 +rte|12021|localhost:4560 +rte|12022|localhost:4560 +rte|20000|localhost:4560 +rte|12040|localhost:38000 +rte|20001|localhost:4566 +rte|20011|localhost:4560 +rte|20012|localhost:4560 +newrt|end diff --git a/src/run_xapp.sh b/src/run_xapp.sh new file mode 100755 index 0000000..1eff6b1 --- /dev/null +++ b/src/run_xapp.sh @@ -0,0 +1,38 @@ +#! /bin/bash +/* +================================================================================== + + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== + */ +export RMR_SEED_RT="routes.txt" +export RMR_RTG_SVC="9999" +export XAPP_NAME="HELLOWORLD_XAPP" +export HW_PORTS="4560" +export MSG_MAX_BUFFER="2048" +export THREADS="1" +export VERBOSE="0" +export CONFIG_FILE="config/config-file.json" +export GNODEB="NYC123" +export XAPP_ID="3489-er492k-92389" +export A1_SCHEMA_FILE="schemas/hwxapp-policy.json" +export VES_SCHEMA_FILE="schemas/hwxapp-ves.json" +export VES_COLLECTOR_URL="127.0.0.1:6350" +export VES_MEASUREMENT_INTERVAL="10" +export LOG_LEVEL="MDCLOG_ERR" +export OPERATING_MODE="CONTROL" + + + diff --git a/src/xapp-asn/e2ap/e2ap_control.cc b/src/xapp-asn/e2ap/e2ap_control.cc new file mode 100644 index 0000000..e66ddec --- /dev/null +++ b/src/xapp-asn/e2ap/e2ap_control.cc @@ -0,0 +1,266 @@ +/* +================================================================================== + + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== +*/ +/* + * ric_control_request.c + * + * Created on: Jul 11, 2019 + * Author: sjana, Ashwin Sridharan + */ + +#include "e2ap_control.hpp" + +// Set up memory allocations for each IE for encoding +// We are responsible for memory management for each IE for encoding +// Hence destructor should clear out memory +// When decoding, we rely on asn1c macro (ASN_STRUCT_FREE to be called +// for releasing memory by external calling function) +ric_control_request::ric_control_request(void){ + + e2ap_pdu_obj = 0; + e2ap_pdu_obj = (E2N_E2AP_PDU_t * )calloc(1, sizeof(E2N_E2AP_PDU_t)); + assert(e2ap_pdu_obj != 0); + + initMsg = 0; + initMsg = (E2N_InitiatingMessage_t * )calloc(1, sizeof(E2N_InitiatingMessage_t)); + assert(initMsg != 0); + + IE_array = 0; + IE_array = (E2N_RICcontrolRequest_IEs_t *)calloc(NUM_CONTROL_REQUEST_IES, sizeof(E2N_RICcontrolRequest_IEs_t)); + assert(IE_array != 0); + + e2ap_pdu_obj->present = E2N_E2AP_PDU_PR_initiatingMessage; + e2ap_pdu_obj->choice.initiatingMessage = initMsg; + + +}; + + +// Clear assigned protocolIE list from RIC control_request IE container +ric_control_request::~ric_control_request(void){ + + mdclog_write(MDCLOG_DEBUG, "Freeing E2AP Control Request object memory"); + + E2N_RICcontrolRequest_t *ricControl_Request = &(initMsg->value.choice.RICcontrolRequest); + for(int i = 0; i < ricControl_Request->protocolIEs.list.size; i++){ + ricControl_Request->protocolIEs.list.array[i] = 0; + } + + if (ricControl_Request->protocolIEs.list.size > 0){ + free(ricControl_Request->protocolIEs.list.array); + ricControl_Request->protocolIEs.list.size = 0; + ricControl_Request->protocolIEs.list.count = 0; + } + + free(IE_array); + free(initMsg); + e2ap_pdu_obj->choice.initiatingMessage = 0; + + ASN_STRUCT_FREE(asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj); + mdclog_write(MDCLOG_DEBUG, "Freed E2N_E2AP Control Request object mempory"); + +} + + +bool ric_control_request::encode_e2ap_control_request(unsigned char *buf, size_t *size, ric_control_helper & dinput){ + + initMsg->procedureCode = E2N_ProcedureCode_id_ricControl; + initMsg->criticality = E2N_Criticality_ignore; + initMsg->value.present = E2N_InitiatingMessage__value_PR_RICcontrolRequest; + + bool res; + + res = set_fields(initMsg, dinput); + if (!res){ + return false; + } + + int ret_constr = asn_check_constraints(&asn_DEF_E2N_E2AP_PDU, (void *) e2ap_pdu_obj, errbuf, &errbuf_len); + if(ret_constr){ + error_string.assign(errbuf, errbuf_len); + error_string = "Constraints failed for encoding control . Reason = " + error_string; + return false; + } + + //xer_fprint(stdout, &asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj); + + asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj, buf, *size); + + if(retval.encoded == -1){ + error_string.assign(strerror(errno)); + return false; + } + else { + if(*size < retval.encoded){ + std::stringstream ss; + ss <<"Error encoding event trigger definition. Reason = encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl; + error_string = ss.str(); + return false; + } + } + + *size = retval.encoded; + return true; + +} + +bool ric_control_request::set_fields(E2N_InitiatingMessage_t *initMsg, ric_control_helper &dinput){ + unsigned int ie_index; + + if (initMsg == 0){ + error_string = "Invalid reference for E2AP Control_Request message in set_fields"; + return false; + } + + E2N_RICcontrolRequest_t * ric_control_request = &(initMsg->value.choice.RICcontrolRequest); + ric_control_request->protocolIEs.list.count = 0; // reset + + // for(i = 0; i < NUM_CONTROL_REQUEST_IES;i++){ + // memset(&(IE_array[i]), 0, sizeof(RICcontrolRequest_IEs_t)); + // } + + // Mandatory IE + ie_index = 0; + E2N_RICcontrolRequest_IEs_t *ies_ricreq = &IE_array[ie_index]; + ies_ricreq->criticality = E2N_Criticality_reject; + ies_ricreq->id = E2N_ProtocolIE_ID_id_RICrequestID; + ies_ricreq->value.present = E2N_RICcontrolRequest_IEs__value_PR_RICrequestID; + E2N_RICrequestID_t *ricrequest_ie = &ies_ricreq->value.choice.RICrequestID; + ricrequest_ie->ricRequestorID = dinput.req_id; + ricrequest_ie->ricRequestSequenceNumber = dinput.req_seq_no; + ASN_SEQUENCE_ADD(&(ric_control_request->protocolIEs), &(IE_array[ie_index])); + + // Mandatory IE + ie_index = 1; + E2N_RICcontrolRequest_IEs_t *ies_ranfunc = &IE_array[ie_index]; + ies_ranfunc->criticality = E2N_Criticality_reject; + ies_ranfunc->id = E2N_ProtocolIE_ID_id_RANfunctionID; + ies_ranfunc->value.present = E2N_RICcontrolRequest_IEs__value_PR_RANfunctionID; + E2N_RANfunctionID_t *ranfunction_ie = &ies_ranfunc->value.choice.RANfunctionID; + *ranfunction_ie = dinput.func_id; + ASN_SEQUENCE_ADD(&(ric_control_request->protocolIEs), &(IE_array[ie_index])); + + + // Mandatory IE + ie_index = 2; + E2N_RICcontrolRequest_IEs_t *ies_richead = &IE_array[ie_index]; + ies_richead->criticality = E2N_Criticality_reject; + ies_richead->id = E2N_ProtocolIE_ID_id_RICcontrolHeader; + ies_richead->value.present = E2N_RICcontrolRequest_IEs__value_PR_RICcontrolHeader; + E2N_RICcontrolHeader_t *richeader_ie = &ies_richead->value.choice.RICcontrolHeader; + richeader_ie->buf = dinput.control_header; + richeader_ie->size = dinput.control_header_size; + ASN_SEQUENCE_ADD(&(ric_control_request->protocolIEs), &(IE_array[ie_index])); + + // Mandatory IE + ie_index = 3; + E2N_RICcontrolRequest_IEs_t *ies_indmsg = &IE_array[ie_index]; + ies_indmsg->criticality = E2N_Criticality_reject; + ies_indmsg->id = E2N_ProtocolIE_ID_id_RICcontrolMessage; + ies_indmsg->value.present = E2N_RICcontrolRequest_IEs__value_PR_RICcontrolMessage; + E2N_RICcontrolMessage_t *ricmsg_ie = &ies_indmsg->value.choice.RICcontrolMessage; + ricmsg_ie->buf = dinput.control_msg; + ricmsg_ie->size = dinput.control_msg_size; + ASN_SEQUENCE_ADD(&(ric_control_request->protocolIEs), &(IE_array[ie_index])); + + // Optional IE + ie_index = 4; + if (dinput.control_ack >= 0){ + E2N_RICcontrolRequest_IEs_t *ies_indtyp = &IE_array[ie_index]; + ies_indtyp->criticality = E2N_Criticality_reject; + ies_indtyp->id = E2N_ProtocolIE_ID_id_RICcontrolAckRequest; + ies_indtyp->value.present = E2N_RICcontrolRequest_IEs__value_PR_RICcontrolAckRequest; + E2N_RICcontrolAckRequest_t *ricackreq_ie = &ies_indtyp->value.choice.RICcontrolAckRequest; + *ricackreq_ie = dinput.control_ack; + ASN_SEQUENCE_ADD(&(ric_control_request->protocolIEs), &(IE_array[ie_index])); + } + + // Optional IE + ie_index = 5; + if(dinput.call_process_id_size > 0){ + E2N_RICcontrolRequest_IEs_t *ies_callprocid = &IE_array[ie_index]; + ies_callprocid->criticality = E2N_Criticality_reject; + ies_callprocid->id = E2N_ProtocolIE_ID_id_RICcallProcessID; + ies_callprocid->value.present = E2N_RICcontrolRequest_IEs__value_PR_RICcallProcessID; + E2N_RICcallProcessID_t *riccallprocessid_ie = &ies_callprocid->value.choice.RICcallProcessID; + riccallprocessid_ie->buf = dinput.call_process_id; + riccallprocessid_ie->size = dinput.call_process_id_size; + ASN_SEQUENCE_ADD(&(ric_control_request->protocolIEs), &(IE_array[ie_index])); + + } + return true; + +}; + + + + +bool ric_control_request:: get_fields(E2N_InitiatingMessage_t * init_msg, ric_control_helper &dout) +{ + if (init_msg == 0){ + error_string = "Invalid reference for E2AP Control_Request message in get_fields"; + return false; + } + + + for(int edx = 0; edx < init_msg->value.choice.RICcontrolRequest.protocolIEs.list.count; edx++) { + E2N_RICcontrolRequest_IEs_t *memb_ptr = init_msg->value.choice.RICcontrolRequest.protocolIEs.list.array[edx]; + + switch(memb_ptr->id) + { + case (E2N_ProtocolIE_ID_id_RICcontrolHeader): + dout.control_header = memb_ptr->value.choice.RICcontrolHeader.buf; + dout.control_header_size = memb_ptr->value.choice.RICcontrolHeader.size; + break; + + case (E2N_ProtocolIE_ID_id_RICcontrolMessage): + dout.control_msg = memb_ptr->value.choice.RICcontrolMessage.buf; + dout.control_msg_size = memb_ptr->value.choice.RICcontrolMessage.size; + break; + + case (E2N_ProtocolIE_ID_id_RICcallProcessID): + dout.call_process_id = memb_ptr->value.choice.RICcallProcessID.buf; + dout.call_process_id_size = memb_ptr->value.choice.RICcallProcessID.size; + break; + + case (E2N_ProtocolIE_ID_id_RICrequestID): + dout.req_id = memb_ptr->value.choice.RICrequestID.ricRequestorID; + dout.req_seq_no = memb_ptr->value.choice.RICrequestID.ricRequestSequenceNumber; + break; + + case (E2N_ProtocolIE_ID_id_RANfunctionID): + dout.func_id = memb_ptr->value.choice.RANfunctionID; + break; + + case (E2N_ProtocolIE_ID_id_RICcontrolAckRequest): + dout.control_ack = memb_ptr->value.choice.RICcontrolAckRequest; + break; + + default: + break; + } + + } + + return true; + +} + +E2N_InitiatingMessage_t * ric_control_request::get_message(void) { + return initMsg; +} diff --git a/src/xapp-asn/e2ap/e2ap_control.hpp b/src/xapp-asn/e2ap/e2ap_control.hpp new file mode 100644 index 0000000..57a2e2d --- /dev/null +++ b/src/xapp-asn/e2ap/e2ap_control.hpp @@ -0,0 +1,66 @@ +/* +================================================================================== + + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== +*/ +/* + * ric_indication.h + * + * Created on: Jul 11, 2019 + * Author: sjana, Ashwin Sridharan + */ + +#ifndef E2AP_RIC_CONTROL_REQUEST_H_ +#define E2AP_RIC_CONTROL_REQUEST_H_ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include "e2ap_control_helper.hpp" + +#define NUM_CONTROL_REQUEST_IES 6 + + +class ric_control_request{ + +public: + ric_control_request(void); + ~ric_control_request(void); + + bool encode_e2ap_control_request(unsigned char *, size_t *, ric_control_helper &); + E2N_InitiatingMessage_t * get_message (void) ; + bool set_fields(E2N_InitiatingMessage_t *, ric_control_helper &); + bool get_fields(E2N_InitiatingMessage_t *, ric_control_helper &); + std::string get_error(void) const {return error_string ; }; +private: + + E2N_E2AP_PDU_t * e2ap_pdu_obj; + E2N_InitiatingMessage_t *initMsg; + E2N_RICcontrolRequest_IEs_t *IE_array; + std::string error_string; + + char errbuf[128]; + size_t errbuf_len = 128; +}; + + +#endif /* E2AP_RIC_CONTROL_REQUEST_H_ */ diff --git a/src/xapp-asn/e2ap/e2ap_control_helper.hpp b/src/xapp-asn/e2ap/e2ap_control_helper.hpp new file mode 100644 index 0000000..11f668c --- /dev/null +++ b/src/xapp-asn/e2ap/e2ap_control_helper.hpp @@ -0,0 +1,50 @@ +/* +================================================================================== + + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== +*/ +/* + * ric_indication.h + * + * Created on: Jul 11, 2019 + * Author: sjana, Ashwin Sridharan + */ + +#ifndef CONTROL_HELPER_H +#define CONTROL_HELPER_H + +// control and indication helper objects are very similar and can be merged into one +// currently leaving them as two distnict entities till final design becomes clear + +typedef struct ric_control_helper ric_control_helper; + +struct ric_control_helper{ + ric_control_helper(void):req_id(1), req_seq_no(1), func_id(0), action_id(1), control_ack(-1), cause(0), sub_cause(0), control_status(1), control_msg(0), control_msg_size(0), control_header(0), control_header_size(0), call_process_id(0), call_process_id_size(0){}; + + long int req_id, req_seq_no, func_id, action_id, control_ack, cause, sub_cause, control_status; + + unsigned char* control_msg; + size_t control_msg_size; + + unsigned char* control_header; + size_t control_header_size; + + unsigned char *call_process_id; + size_t call_process_id_size; + +}; + +#endif diff --git a/src/xapp-asn/e2ap/e2ap_control_response.cc b/src/xapp-asn/e2ap/e2ap_control_response.cc new file mode 100644 index 0000000..23ef9ae --- /dev/null +++ b/src/xapp-asn/e2ap/e2ap_control_response.cc @@ -0,0 +1,415 @@ +/* +================================================================================== + + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== +*/ +/* + * ric_control_response.c + * + * Created on: Jul 11, 2019 + * Author: sjana, Ashwin Sridharan + */ + +#include "e2ap_control_response.hpp" + +// Set up the initiating message and also allocate protocolIEs in container +// Note : this bypasses requirement to use ASN_SEQUENCE_ADD. We can directly +// assign pointers to the array in ProtocolIE. However, this also leaves us on the +// hook to manually clear the memory + +ric_control_response::ric_control_response(void){ + + e2ap_pdu_obj = 0; + e2ap_pdu_obj = (E2N_E2AP_PDU_t * )calloc(1, sizeof(E2N_E2AP_PDU_t)); + assert(e2ap_pdu_obj != 0); + + successMsg = 0; + successMsg = (E2N_SuccessfulOutcome_t * )calloc(1, sizeof(E2N_SuccessfulOutcome_t)); + assert(successMsg != 0); + + successMsg->procedureCode = E2N_ProcedureCode_id_ricControl; + successMsg->criticality = E2N_Criticality_reject; + successMsg->value.present = E2N_SuccessfulOutcome__value_PR_RICcontrolAcknowledge; + + + unsuccessMsg = 0; + unsuccessMsg = (E2N_UnsuccessfulOutcome_t * )calloc(1, sizeof(E2N_UnsuccessfulOutcome_t)); + assert(unsuccessMsg != 0); + + + unsuccessMsg->procedureCode = E2N_ProcedureCode_id_ricControl; + unsuccessMsg->criticality = E2N_Criticality_reject; + unsuccessMsg->value.present = E2N_UnsuccessfulOutcome__value_PR_RICcontrolFailure; + + IE_array = 0; + IE_array = (E2N_RICcontrolAcknowledge_IEs_t *)calloc(NUM_CONTROL_ACKNOWLEDGE_IES, sizeof(E2N_RICcontrolAcknowledge_IEs_t)); + assert(IE_array != 0); + + E2N_RICcontrolAcknowledge_t * ric_acknowledge = &(successMsg->value.choice.RICcontrolAcknowledge); + for(int i = 0; i < NUM_CONTROL_ACKNOWLEDGE_IES; i++){ + ASN_SEQUENCE_ADD(&(ric_acknowledge->protocolIEs), &(IE_array[i])); + } + + + IE_failure_array = 0; + IE_failure_array = (E2N_RICcontrolFailure_IEs_t *)calloc(NUM_CONTROL_FAILURE_IES, sizeof(E2N_RICcontrolFailure_IEs_t)); + assert(IE_failure_array != 0); + + E2N_RICcontrolFailure_t * ric_failure = &(unsuccessMsg->value.choice.RICcontrolFailure); + for(int i = 0; i < NUM_CONTROL_FAILURE_IES; i++){ + ASN_SEQUENCE_ADD(&(ric_failure->protocolIEs), &(IE_failure_array[i])); + } + +}; + + +// Clear assigned protocolIE list from RIC control_request IE container +ric_control_response::~ric_control_response(void){ + + mdclog_write(MDCLOG_DEBUG, "Freeing E2AP Control Response object memory"); + + E2N_RICcontrolAcknowledge_t * ric_acknowledge = &(successMsg->value.choice.RICcontrolAcknowledge); + for(int i = 0; i < ric_acknowledge->protocolIEs.list.size; i++){ + ric_acknowledge->protocolIEs.list.array[i] = 0; + } + if (ric_acknowledge->protocolIEs.list.size > 0){ + free(ric_acknowledge->protocolIEs.list.array); + ric_acknowledge->protocolIEs.list.array = 0; + ric_acknowledge->protocolIEs.list.count = 0; + } + + E2N_RICcontrolFailure_t * ric_failure = &(unsuccessMsg->value.choice.RICcontrolFailure); + for(int i = 0; i < ric_failure->protocolIEs.list.size; i++){ + ric_failure->protocolIEs.list.array[i] = 0; + } + if (ric_failure->protocolIEs.list.size > 0){ + free(ric_failure->protocolIEs.list.array); + ric_failure->protocolIEs.list.array = 0; + ric_failure->protocolIEs.list.count = 0; + } + + free(IE_array); + free(IE_failure_array); + free(successMsg); + free(unsuccessMsg); + + e2ap_pdu_obj->choice.initiatingMessage = 0; + e2ap_pdu_obj->present = E2N_E2AP_PDU_PR_initiatingMessage; + + ASN_STRUCT_FREE(asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj); + mdclog_write(MDCLOG_DEBUG, "Freed E2AP Control Response object mempory"); +} + + +bool ric_control_response::encode_e2ap_control_response(unsigned char *buf, size_t *size, ric_control_helper & dinput, bool is_success){ + + bool res; + if (is_success){ + res = set_fields(successMsg, dinput); + } + else{ + res = set_fields(unsuccessMsg, dinput); + } + + if (!res){ + return false; + } + + + if (is_success){ + e2ap_pdu_obj->choice.successfulOutcome = successMsg; + e2ap_pdu_obj->present = E2N_E2AP_PDU_PR_successfulOutcome ; + } + else{ + e2ap_pdu_obj->choice.unsuccessfulOutcome = unsuccessMsg; + e2ap_pdu_obj->present = E2N_E2AP_PDU_PR_unsuccessfulOutcome ; + + } + + //xer_fprint(stdout, &asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj); + + int ret_constr = asn_check_constraints(&asn_DEF_E2N_E2AP_PDU, (void *) e2ap_pdu_obj, errbuf, &errbuf_len); + if(ret_constr){ + error_string.assign(errbuf, errbuf_len); + error_string = "Constraints failed for encoding control response. Reason = " + error_string; + return false; + } + + asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj, buf, *size); + + if(retval.encoded == -1){ + error_string.assign(strerror(errno)); + return false; + } + else { + if(*size < retval.encoded){ + std::stringstream ss; + ss <<"Error encoding E2AP Control response . Reason = encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl; + error_string = ss.str(); + return false; + } + } + + *size = retval.encoded; + return true; + +} + +bool ric_control_response::set_fields(E2N_SuccessfulOutcome_t *successMsg, ric_control_helper &dinput){ + unsigned int ie_index; + + if (successMsg == 0){ + error_string = "Invalid reference for E2AP Control Acknowledge in set_fields"; + return false; + } + + // for(i = 0; i < NUM_CONTROL_ACKNOWLEDGE_IES;i++){ + // memset(&(IE_array[i]), 0, sizeof(RICcontrolAcknowledge_IEs_t)); + // } + + //E2N_RICcontrolAcknowledge_t * ric_acknowledge = &(successMsg->value.choice.RICcontrolAcknowledge); + //ric_acknowledge->protocolIEs.list.count = 0; + + ie_index = 0; + E2N_RICcontrolAcknowledge_IEs_t *ies_ricreq = &IE_array[ie_index]; + ies_ricreq->criticality = E2N_Criticality_reject; + ies_ricreq->id = E2N_ProtocolIE_ID_id_RICrequestID; + ies_ricreq->value.present = E2N_RICcontrolAcknowledge_IEs__value_PR_RICrequestID; + E2N_RICrequestID_t *ricrequest_ie = &ies_ricreq->value.choice.RICrequestID; + ricrequest_ie->ricRequestorID = dinput.req_id; + ricrequest_ie->ricRequestSequenceNumber = dinput.req_seq_no; + //ASN_SEQUENCE_ADD(&(ric_acknowledge->protocolIEs), ies_ricreq); + + ie_index = 1; + E2N_RICcontrolAcknowledge_IEs_t *ies_ranfunc = &IE_array[ie_index]; + ies_ranfunc->criticality = E2N_Criticality_reject; + ies_ranfunc->id = E2N_ProtocolIE_ID_id_RANfunctionID; + ies_ranfunc->value.present = E2N_RICcontrolAcknowledge_IEs__value_PR_RANfunctionID; + E2N_RANfunctionID_t *ranfunction_ie = &ies_ranfunc->value.choice.RANfunctionID; + *ranfunction_ie = dinput.func_id; + //ASN_SEQUENCE_ADD(&(ric_acknowledge->protocolIEs), ies_ranfunc); + + // ie_index = 2; + // E2N_RICcontrolAcknowledge_IEs_t *ies_riccallprocessid = &IE_array[ie_index]; + // ies_riccallprocessid->criticality = E2N_Criticality_reject; + // ies_riccallprocessid->id = E2N_ProtocolIE_ID_id_RICcallProcessID; + // ies_riccallprocessid->value.present = E2N_RICcontrolAcknowledge_IEs__value_PR_RICcallProcessID; + // RICcallProcessID_t *riccallprocessid_ie = &ies_riccallprocessid->value.choice.RICcallProcessID; + // riccallprocessid_ie->buf = dinput.call_process_id; + // riccallprocessid_ie->size = dinput.call_process_id_size; + // ASN_SEQUENCE_ADD(&(ric_acknowledge->protocolIEs), ies_riccallprocessid); + + ie_index = 2; + E2N_RICcontrolAcknowledge_IEs_t *ies_ric_cause = &IE_array[ie_index]; + ies_ric_cause->criticality = E2N_Criticality_reject; + ies_ric_cause->id = E2N_ProtocolIE_ID_id_RICcontrolStatus; + ies_ric_cause->value.present = E2N_RICcontrolAcknowledge_IEs__value_PR_RICcontrolStatus; + ies_ric_cause->value.choice.RICcontrolStatus = dinput.control_status; + //ASN_SEQUENCE_ADD(&(ric_acknowledge->protocolIEs), ies_ric_cause); + + return true; + +}; + +bool ric_control_response::set_fields(E2N_UnsuccessfulOutcome_t *unsuccessMsg, ric_control_helper &dinput){ + unsigned int ie_index; + + if (unsuccessMsg == 0){ + error_string = "Invalid reference for E2AP Control Failure in set_fields"; + return false; + } + + // for(i = 0; i < NUM_CONTROL_FAILURE_IES;i++){ + // memset(&(IE_failure_array[i]), 0, sizeof(RICcontrolFailure_IEs_t)); + // } + + //E2N_RICcontrolFailure_t * ric_failure = &(unsuccessMsg->value.choice.RICcontrolFailure); + //ric_failure->protocolIEs.list.count = 0; + + ie_index = 0; + E2N_RICcontrolFailure_IEs_t *ies_ricreq = &IE_failure_array[ie_index]; + ies_ricreq->criticality = E2N_Criticality_reject; + ies_ricreq->id = E2N_ProtocolIE_ID_id_RICrequestID; + ies_ricreq->value.present = E2N_RICcontrolFailure_IEs__value_PR_RICrequestID; + E2N_RICrequestID_t *ricrequest_ie = &(ies_ricreq->value.choice.RICrequestID); + ricrequest_ie->ricRequestorID = dinput.req_id; + ricrequest_ie->ricRequestSequenceNumber = dinput.req_seq_no; + //ASN_SEQUENCE_ADD(&(ric_failure->protocolIEs), ies_ricreq); + + ie_index = 1; + E2N_RICcontrolFailure_IEs_t *ies_ranfunc = &IE_failure_array[ie_index]; + ies_ranfunc->criticality = E2N_Criticality_reject; + ies_ranfunc->id = E2N_ProtocolIE_ID_id_RANfunctionID; + ies_ranfunc->value.present = E2N_RICcontrolFailure_IEs__value_PR_RANfunctionID; + E2N_RANfunctionID_t *ranfunction_ie = &(ies_ranfunc->value.choice.RANfunctionID); + *ranfunction_ie = dinput.func_id; + //ASN_SEQUENCE_ADD(&(ric_failure->protocolIEs), ies_ranfunc); + + // ie_index = 2; + // E2N_RICcontrolFailure_IEs_t *ies_riccallprocessid = &IE_failure_array[i]; + // ies_riccallprocessid->criticality = E2N_Criticality_reject; + // ies_riccallprocessid->id = E2N_ProtocolIE_ID_id_RICcallProcessID; + // ies_riccallprocessid->value.present = E2N_RICcontrolFailure_IEs__value_PR_RICcallProcessID; + // RICcallProcessID_t *riccallprocessid_ie = &(ies_riccallprocessid->value.choice.RICcallProcessID); + // riccallprocessid_ie->buf = dinput.call_process_id; + // riccallprocessid_ie->size = dinput.call_process_id_size; + // ASN_SEQUENCE_ADD(&(ric_failure->protocolIEs), ies_riccallprocessid); + + ie_index = 2; + E2N_RICcontrolFailure_IEs_t *ies_ric_cause = &IE_failure_array[ie_index]; + ies_ric_cause->criticality = E2N_Criticality_ignore; + ies_ric_cause->id = E2N_ProtocolIE_ID_id_RICcause; + ies_ric_cause->value.present = E2N_RICcontrolFailure_IEs__value_PR_RICcause; + E2N_RICcause_t * ric_cause = &(ies_ric_cause->value.choice.RICcause); + ric_cause->present = (E2N_RICcause_PR)dinput.cause; + + switch(dinput.cause){ + case E2N_RICcause_PR_radioNetwork: + ric_cause->choice.radioNetwork = dinput.sub_cause; + break; + case E2N_RICcause_PR_transport: + ric_cause->choice.transport = dinput.sub_cause; + break; + case E2N_RICcause_PR_protocol: + ric_cause->choice.protocol= dinput.sub_cause; + break; + case E2N_RICcause_PR_misc: + ric_cause->choice.misc = dinput.sub_cause; + break; + case E2N_RICcause_PR_ric: + ric_cause->choice.ric = dinput.sub_cause; + break; + default: + std::cout <<"Error ! Illegal cause enum" << dinput.cause << std::endl; + return false; + } + + //ASN_SEQUENCE_ADD(&(ric_failure->protocolIEs), ies_ric_cause); + return true; + +}; + + + + +bool ric_control_response:: get_fields(E2N_SuccessfulOutcome_t * success_msg, ric_control_helper &dout) +{ + if (success_msg == 0){ + error_string = "Invalid reference for E2AP Control Acknowledge message in get_fields"; + return false; + } + + + for(int edx = 0; edx < success_msg->value.choice.RICcontrolAcknowledge.protocolIEs.list.count; edx++) { + E2N_RICcontrolAcknowledge_IEs_t *memb_ptr = success_msg->value.choice.RICcontrolAcknowledge.protocolIEs.list.array[edx]; + + switch(memb_ptr->id) + { + + case (E2N_ProtocolIE_ID_id_RICcallProcessID): + dout.call_process_id = memb_ptr->value.choice.RICcallProcessID.buf; + dout.call_process_id_size = memb_ptr->value.choice.RICcallProcessID.size; + break; + + case (E2N_ProtocolIE_ID_id_RICrequestID): + dout.req_id = memb_ptr->value.choice.RICrequestID.ricRequestorID; + dout.req_seq_no = memb_ptr->value.choice.RICrequestID.ricRequestSequenceNumber; + break; + + case (E2N_ProtocolIE_ID_id_RANfunctionID): + dout.func_id = memb_ptr->value.choice.RANfunctionID; + break; + + case (E2N_ProtocolIE_ID_id_RICcause): + dout.control_status = memb_ptr->value.choice.RICcontrolStatus; + break; + + } + + } + + return true; + +} + + +bool ric_control_response:: get_fields(E2N_UnsuccessfulOutcome_t * unsuccess_msg, ric_control_helper &dout) +{ + if (unsuccess_msg == 0){ + error_string = "Invalid reference for E2AP Control Failure message in get_fields"; + return false; + } + + + for(int edx = 0; edx < unsuccess_msg->value.choice.RICcontrolFailure.protocolIEs.list.count; edx++) { + E2N_RICcontrolFailure_IEs_t *memb_ptr = unsuccess_msg->value.choice.RICcontrolFailure.protocolIEs.list.array[edx]; + + switch(memb_ptr->id) + { + + case (E2N_ProtocolIE_ID_id_RICcallProcessID): + dout.call_process_id = memb_ptr->value.choice.RICcallProcessID.buf; + dout.call_process_id_size = memb_ptr->value.choice.RICcallProcessID.size; + break; + + case (E2N_ProtocolIE_ID_id_RICrequestID): + dout.req_id = memb_ptr->value.choice.RICrequestID.ricRequestorID; + dout.req_seq_no = memb_ptr->value.choice.RICrequestID.ricRequestSequenceNumber; + break; + + case (E2N_ProtocolIE_ID_id_RANfunctionID): + dout.func_id = memb_ptr->value.choice.RANfunctionID; + break; + + + case (E2N_ProtocolIE_ID_id_RICcause): + dout.cause = memb_ptr->value.choice.RICcause.present; + switch(dout.cause){ + case E2N_RICcause_PR_radioNetwork : + dout.sub_cause = memb_ptr->value.choice.RICcause.choice.radioNetwork; + break; + + case E2N_RICcause_PR_transport : + dout.sub_cause = memb_ptr->value.choice.RICcause.choice.transport; + break; + + case E2N_RICcause_PR_protocol : + dout.sub_cause = memb_ptr->value.choice.RICcause.choice.protocol; + break; + + case E2N_RICcause_PR_misc : + dout.sub_cause = memb_ptr->value.choice.RICcause.choice.misc; + break; + + case E2N_RICcause_PR_ric : + dout.sub_cause = memb_ptr->value.choice.RICcause.choice.ric; + break; + + default: + dout.sub_cause = -1; + break; + } + + default: + break; + } + + } + + return true; + +} + diff --git a/src/xapp-asn/e2ap/e2ap_control_response.hpp b/src/xapp-asn/e2ap/e2ap_control_response.hpp new file mode 100644 index 0000000..6880e48 --- /dev/null +++ b/src/xapp-asn/e2ap/e2ap_control_response.hpp @@ -0,0 +1,79 @@ +/* +================================================================================== + + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== +*/ +/* + * ric_indication.h + * + * Created on: Jul 11, 2019 + * Author: sjana, Ashwin Sridharan + */ + +#ifndef E2AP_RIC_CONTROL_RESPONSE_H_ +#define E2AP_RIC_CONTROL_RESPONSE_H_ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "e2ap_control_helper.hpp" + +#define NUM_CONTROL_ACKNOWLEDGE_IES 3 +#define NUM_CONTROL_FAILURE_IES 3 + + +class ric_control_response{ + +public: + ric_control_response(void); + ~ric_control_response(void); + + bool encode_e2ap_control_response(unsigned char *, size_t *, ric_control_helper &, bool); + + + bool set_fields(E2N_SuccessfulOutcome_t *, ric_control_helper &); + bool get_fields(E2N_SuccessfulOutcome_t *, ric_control_helper &); + + bool set_fields(E2N_UnsuccessfulOutcome_t *, ric_control_helper &); + bool get_fields(E2N_UnsuccessfulOutcome_t *, ric_control_helper &); + + std::string get_error(void) const {return error_string ; }; + +private: + + E2N_E2AP_PDU_t * e2ap_pdu_obj; + E2N_SuccessfulOutcome_t * successMsg; + E2N_UnsuccessfulOutcome_t * unsuccessMsg; + + E2N_RICcontrolAcknowledge_IEs_t *IE_array; + E2N_RICcontrolFailure_IEs_t *IE_failure_array; + + std::string error_string; + + char errbuf[128]; + size_t errbuf_len = 128; +}; + + +#endif /* E2AP_RIC_CONTROL_RESPONSE_H_ */ diff --git a/src/xapp-asn/e2ap/e2ap_indication.cc b/src/xapp-asn/e2ap/e2ap_indication.cc new file mode 100644 index 0000000..33b2095 --- /dev/null +++ b/src/xapp-asn/e2ap/e2ap_indication.cc @@ -0,0 +1,283 @@ +/* +================================================================================== + + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== +*/ +/* + * ric_indication.c + * + * Created on: Jul 11, 2019 + * Author: sjana, Ashwin Sridharan + */ + +#include "e2ap_indication.hpp" + +// Set up memory allocations for each IE for encoding +// We are responsible for memory management for each IE for encoding +// Hence destructor should clear out memory +// When decoding, we rely on asn1c macro (ASN_STRUCT_FREE to be called +// for releasing memory by external calling function) +ric_indication::ric_indication(void){ + + e2ap_pdu_obj = 0; + e2ap_pdu_obj = (E2N_E2AP_PDU_t * )calloc(1, sizeof(E2N_E2AP_PDU_t)); + assert(e2ap_pdu_obj != 0); + + initMsg = 0; + initMsg = (E2N_InitiatingMessage_t * )calloc(1, sizeof(E2N_InitiatingMessage_t)); + assert(initMsg != 0); + + IE_array = 0; + IE_array = (E2N_RICindication_IEs_t *)calloc(NUM_INDICATION_IES, sizeof(E2N_RICindication_IEs_t)); + assert(IE_array != 0); + + e2ap_pdu_obj->present = E2N_E2AP_PDU_PR_initiatingMessage; + e2ap_pdu_obj->choice.initiatingMessage = initMsg; + + + + +}; + + + +// Clear assigned protocolIE list from RIC indication IE container +ric_indication::~ric_indication(void){ + + mdclog_write(MDCLOG_DEBUG, "Freeing E2AP Indication object memory"); + E2N_RICindication_t *ricIndication = &(initMsg->value.choice.RICindication); + for(int i = 0; i < ricIndication->protocolIEs.list.size; i++){ + ricIndication->protocolIEs.list.array[i] = 0; + } + if (ricIndication->protocolIEs.list.size > 0){ + free(ricIndication->protocolIEs.list.array); + ricIndication->protocolIEs.list.array = 0; + ricIndication->protocolIEs.list.count = 0; + ricIndication->protocolIEs.list.size = 0; + } + + free(IE_array); + ASN_STRUCT_FREE(asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj); + mdclog_write(MDCLOG_DEBUG, "Freed E2AP Indication object mempory"); +} + + +bool ric_indication::encode_e2ap_indication(unsigned char *buf, size_t *size, ric_indication_helper & dinput){ + + initMsg->procedureCode = E2N_ProcedureCode_id_ricIndication; + initMsg->criticality = E2N_Criticality_ignore; + initMsg->value.present = E2N_InitiatingMessage__value_PR_RICindication; + + bool res; + asn_enc_rval_t retval; + + res = set_fields(initMsg, dinput); + if (!res){ + return false; + } + + int ret_constr = asn_check_constraints(&asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj, errbuf, &errbuf_len); + if(ret_constr){ + error_string.assign(&errbuf[0], errbuf_len); + error_string = "Error encoding E2AP Indication message. Reason = " + error_string; + return false; + } + + // std::cout <<"Constraint check ok ...." << std::endl; + // xer_fprint(stdout, &asn_DEF_E2AP_PDU, e2ap_pdu_obj); + + retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj, buf, *size); + if(retval.encoded == -1){ + error_string.assign(strerror(errno)); + return false; + } + + else { + if(*size < retval.encoded){ + std::stringstream ss; + ss <<"Error encoding E2AP Indication . Reason = encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl; + error_string = ss.str(); + return false; + } + } + + *size = retval.encoded; + return true; + +} + +bool ric_indication::set_fields(E2N_InitiatingMessage_t *initMsg, ric_indication_helper &dinput){ + unsigned int ie_index; + + if (initMsg == 0){ + error_string = "Invalid reference for E2AP Indication message in set_fields"; + return false; + } + + + E2N_RICindication_t * ric_indication = &(initMsg->value.choice.RICindication); + ric_indication->protocolIEs.list.count = 0; + + ie_index = 0; + + E2N_RICindication_IEs_t *ies_ricreq = &IE_array[ie_index]; + ies_ricreq->criticality = E2N_Criticality_reject; + ies_ricreq->id = E2N_ProtocolIE_ID_id_RICrequestID; + ies_ricreq->value.present = E2N_RICindication_IEs__value_PR_RICrequestID; + E2N_RICrequestID_t *ricrequest_ie = &ies_ricreq->value.choice.RICrequestID; + ricrequest_ie->ricRequestorID = dinput.req_id; + ricrequest_ie->ricRequestSequenceNumber = dinput.req_seq_no; + ASN_SEQUENCE_ADD(&(ric_indication->protocolIEs), &(IE_array[ie_index])); + + ie_index = 1; + E2N_RICindication_IEs_t *ies_ranfunc = &IE_array[ie_index]; + ies_ranfunc->criticality = E2N_Criticality_reject; + ies_ranfunc->id = E2N_ProtocolIE_ID_id_RANfunctionID; + ies_ranfunc->value.present = E2N_RICindication_IEs__value_PR_RANfunctionID; + E2N_RANfunctionID_t *ranfunction_ie = &ies_ranfunc->value.choice.RANfunctionID; + *ranfunction_ie = dinput.func_id; + ASN_SEQUENCE_ADD(&(ric_indication->protocolIEs), &(IE_array[ie_index])); + + ie_index = 2; + E2N_RICindication_IEs_t *ies_actid = &IE_array[ie_index]; + ies_actid->criticality = E2N_Criticality_reject; + ies_actid->id = E2N_ProtocolIE_ID_id_RICactionID; + ies_actid->value.present = E2N_RICindication_IEs__value_PR_RICactionID; + E2N_RICactionID_t *ricaction_ie = &ies_actid->value.choice.RICactionID; + *ricaction_ie = dinput.action_id; + ASN_SEQUENCE_ADD(&(ric_indication->protocolIEs), &(IE_array[ie_index])); + + ie_index = 3; + E2N_RICindication_IEs_t *ies_ricsn = &IE_array[ie_index]; + ies_ricsn->criticality = E2N_Criticality_reject; + ies_ricsn->id = E2N_ProtocolIE_ID_id_RICindicationSN; + ies_ricsn->value.present = E2N_RICindication_IEs__value_PR_RICindicationSN; + E2N_RICindicationSN_t *ricsn_ie = &ies_ricsn->value.choice.RICindicationSN; + *ricsn_ie = dinput.indication_sn; + ASN_SEQUENCE_ADD(&(ric_indication->protocolIEs), &(IE_array[ie_index])); + + + ie_index = 4; + E2N_RICindication_IEs_t *ies_indtyp = &IE_array[ie_index]; + ies_indtyp->criticality = E2N_Criticality_reject; + ies_indtyp->id = E2N_ProtocolIE_ID_id_RICindicationType; + ies_indtyp->value.present = E2N_RICindication_IEs__value_PR_RICindicationType; + E2N_RICindicationType_t *rictype_ie = &ies_indtyp->value.choice.RICindicationType; + *rictype_ie = dinput.indication_type; + ASN_SEQUENCE_ADD(&(ric_indication->protocolIEs), &(IE_array[ie_index])); + + ie_index = 5; + E2N_RICindication_IEs_t *ies_richead = &IE_array[ie_index]; + ies_richead->criticality = E2N_Criticality_reject; + ies_richead->id = E2N_ProtocolIE_ID_id_RICindicationHeader; + ies_richead->value.present = E2N_RICindication_IEs__value_PR_RICindicationHeader; + E2N_RICindicationHeader_t *richeader_ie = &ies_richead->value.choice.RICindicationHeader; + richeader_ie->buf = dinput.indication_header; + richeader_ie->size = dinput.indication_header_size; + ASN_SEQUENCE_ADD(&(ric_indication->protocolIEs), &(IE_array[ie_index])); + + ie_index = 6; + E2N_RICindication_IEs_t *ies_indmsg = &IE_array[ie_index]; + ies_indmsg->criticality = E2N_Criticality_reject; + ies_indmsg->id = E2N_ProtocolIE_ID_id_RICindicationMessage; + ies_indmsg->value.present = E2N_RICindication_IEs__value_PR_RICindicationMessage; + E2N_RICindicationMessage_t *ricmsg_ie = &ies_indmsg->value.choice.RICindicationMessage; + ricmsg_ie->buf = dinput.indication_msg; + ricmsg_ie->size = dinput.indication_msg_size; + ASN_SEQUENCE_ADD(&(ric_indication->protocolIEs), &(IE_array[ie_index])); + + + // optional call process id .. + if (dinput.call_process_id_size > 0){ + ie_index = 7; + E2N_RICindication_IEs_t *ies_ind_callprocessid = &IE_array[ie_index]; + ies_ind_callprocessid->criticality = E2N_Criticality_reject; + ies_ind_callprocessid->id = E2N_ProtocolIE_ID_id_RICcallProcessID; + ies_ind_callprocessid->value.present = E2N_RICindication_IEs__value_PR_RICcallProcessID; + E2N_RICcallProcessID_t *riccallprocessid_ie = &ies_ind_callprocessid->value.choice.RICcallProcessID; + riccallprocessid_ie->buf = dinput.indication_msg; + riccallprocessid_ie->size = dinput.indication_msg_size; + ASN_SEQUENCE_ADD(&(ric_indication->protocolIEs), &(IE_array[ie_index])); + } + + return true; + +}; + + + + +bool ric_indication:: get_fields(E2N_InitiatingMessage_t * init_msg, ric_indication_helper &dout) +{ + if (init_msg == 0){ + error_string = "Invalid reference for E2AP Indication message in get_fields"; + return false; + } + + + for(int edx = 0; edx < init_msg->value.choice.RICindication.protocolIEs.list.count; edx++) { + E2N_RICindication_IEs_t *memb_ptr = init_msg->value.choice.RICindication.protocolIEs.list.array[edx]; + + switch(memb_ptr->id) + { + case (E2N_ProtocolIE_ID_id_RICindicationHeader): + dout.indication_header = memb_ptr->value.choice.RICindicationHeader.buf; + dout.indication_header_size = memb_ptr->value.choice.RICindicationHeader.size; + break; + + case (E2N_ProtocolIE_ID_id_RICindicationMessage): + dout.indication_msg = memb_ptr->value.choice.RICindicationMessage.buf; + dout.indication_msg_size = memb_ptr->value.choice.RICindicationMessage.size; + break; + + case (E2N_ProtocolIE_ID_id_RICrequestID): + dout.req_id = memb_ptr->value.choice.RICrequestID.ricRequestorID; + dout.req_seq_no = memb_ptr->value.choice.RICrequestID.ricRequestSequenceNumber; + break; + + case (E2N_ProtocolIE_ID_id_RANfunctionID): + dout.func_id = memb_ptr->value.choice.RANfunctionID; + break; + + case (E2N_ProtocolIE_ID_id_RICindicationSN): + dout.indication_sn = memb_ptr->value.choice.RICindicationSN; + break; + + case (E2N_ProtocolIE_ID_id_RICindicationType): + dout.indication_type = memb_ptr->value.choice.RICindicationType; + break; + + case (E2N_ProtocolIE_ID_id_RICactionID): + dout.action_id = memb_ptr->value.choice.RICactionID; + break; + + case (E2N_ProtocolIE_ID_id_RICcallProcessID): + dout.call_process_id = memb_ptr->value.choice.RICcallProcessID.buf; + dout.call_process_id_size = memb_ptr->value.choice.RICcallProcessID.size; + + default: + break; + } + + } + + return true; + +} + +E2N_InitiatingMessage_t * ric_indication::get_message(void) { + return initMsg; +} diff --git a/src/xapp-asn/e2ap/e2ap_indication.hpp b/src/xapp-asn/e2ap/e2ap_indication.hpp new file mode 100644 index 0000000..af43086 --- /dev/null +++ b/src/xapp-asn/e2ap/e2ap_indication.hpp @@ -0,0 +1,67 @@ +/* +================================================================================== + + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== +*/ +/* + * ric_indication.h + * + * Created on: Jul 11, 2019 + * Author: sjana, Ashwin Sridharan + */ + +#ifndef E2AP_RIC_INDICATION_H_ +#define E2AP_RIC_INDICATION_H_ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include "e2ap_indication_helper.hpp" + +#define NUM_INDICATION_IES 8 + + + +class ric_indication{ + +public: + ric_indication(void); + ~ric_indication(void); + + bool encode_e2ap_indication(unsigned char *, size_t *, ric_indication_helper &); + E2N_InitiatingMessage_t * get_message (void) ; + bool set_fields(E2N_InitiatingMessage_t *, ric_indication_helper &); + bool get_fields(E2N_InitiatingMessage_t *, ric_indication_helper &); + std::string get_error(void) const {return error_string ; }; + +private: + + E2N_E2AP_PDU_t * e2ap_pdu_obj; + E2N_InitiatingMessage_t *initMsg; + E2N_RICindication_IEs_t *IE_array; + std::string error_string; + char errbuf[128]; + size_t errbuf_len = 128; +}; + + +#endif /* E2AP_RIC_INDICATION_H_ */ diff --git a/src/xapp-asn/e2ap/e2ap_indication_helper.hpp b/src/xapp-asn/e2ap/e2ap_indication_helper.hpp new file mode 100644 index 0000000..276a2a7 --- /dev/null +++ b/src/xapp-asn/e2ap/e2ap_indication_helper.hpp @@ -0,0 +1,47 @@ +/* +================================================================================== + + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== +*/ +/* + * ric_indication.h + * + * Created on: Jul 11, 2019 + * Author: sjana, Ashwin Sridharan + */ + + +#ifndef E2AP_INDICATION_HELPER_ +#define E2AP_INDICATION_HELPER_ + +typedef struct ric_indication_helper ric_indication_helper; + +struct ric_indication_helper{ + ric_indication_helper(void) : req_id(1), req_seq_no(1), func_id(0), action_id(1), indication_type(0), indication_sn(0), indication_msg(0), indication_msg_size(0), indication_header(0), indication_header_size(0), call_process_id(0), call_process_id_size(0) {}; + long int req_id, req_seq_no, func_id, action_id, indication_type, indication_sn; + + unsigned char* indication_msg; + size_t indication_msg_size; + + unsigned char* indication_header; + size_t indication_header_size; + + unsigned char *call_process_id; + size_t call_process_id_size; + +}; + +#endif diff --git a/src/xapp-asn/e2ap/generic_helpers.hpp b/src/xapp-asn/e2ap/generic_helpers.hpp new file mode 100644 index 0000000..32c019a --- /dev/null +++ b/src/xapp-asn/e2ap/generic_helpers.hpp @@ -0,0 +1,49 @@ +/* +================================================================================== + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== +*/ + + +#pragma once +#ifndef GENERIC_HELPERS +#define GENERIC_HELPERS + +#include + +/* Utilities */ + +class octet_helper { + +public: + octet_helper(void):_ref(NULL), _size(0){}; + octet_helper(const void *ref, int size):_ref(ref), _size(size){}; + void set_ref(const void *ref){ + _ref = ref; + } + + void set_size(size_t size){ + _size = size; + } + + const void * get_ref(void){return _ref ; }; + size_t get_size(void) const {return _size ; } ; + +private: + const void *_ref; + size_t _size; +}; + +#endif diff --git a/src/xapp-asn/e2ap/response_helper.hpp b/src/xapp-asn/e2ap/response_helper.hpp new file mode 100644 index 0000000..b370ff2 --- /dev/null +++ b/src/xapp-asn/e2ap/response_helper.hpp @@ -0,0 +1,181 @@ +/* +================================================================================== + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== +*/ + +#pragma once + +#ifndef S_RESPONSE_HELPER_ +#define S_RESPONSE_HELPER_ + +#include +#include + +/* Simple structure to store action for RICaction of the Subscription response based on E2 v0.31 */ +struct ActionResponse { +public: + ActionResponse(int id): _is_admit(true), _id(id), _cause(-1), _sub_cause(-1){}; + ActionResponse(int id, int cause, int sub_cause): _is_admit(false), _id(id), _cause(cause), _sub_cause(sub_cause){}; + + int get_id() const{ + return _id; + }; + + int get_cause() const{ + return _cause; + }; + + int get_sub_cause() const{ + return _sub_cause; + }; + + bool is_admitted(void){ + return _is_admit; + }; + +private: + + bool _is_admit; + int _id, _cause, _sub_cause; + +}; + + +struct subscription_response_helper { + +public: + + using action_t = std::vector; + + subscription_response_helper(void){ + _action_admitted_ref = std::make_unique(); + _action_not_admitted_ref = std::make_unique(); + + }; + + // copy operator + subscription_response_helper(const subscription_response_helper &he ){ + _action_admitted_ref = std::make_unique(); + _action_not_admitted_ref = std::make_unique(); + + _req_id = he.get_request_id(); + _req_seq_no = he.get_req_seq(); + _func_id = he.get_function_id(); + + // Take care of the actions + for (auto const & e: *(he.get_admitted_list())){ + add_action(e.get_id()); + } + + for(auto const & e: *(he.get_not_admitted_list())){ + add_action(e.get_id(), e.get_cause(), e.get_sub_cause()); + }; + } + + + // assignment operator + void operator=(const subscription_response_helper & he){ + _action_admitted_ref = std::make_unique(); + _action_not_admitted_ref = std::make_unique(); + + _req_id = he.get_request_id(); + _req_seq_no = he.get_req_seq(); + _func_id = he.get_function_id(); + + + // Take care of the actions + for (auto const & e: *(he.get_admitted_list())){ + add_action(e.get_id()); + } + + for(auto const & e: *(he.get_not_admitted_list())){ + add_action(e.get_id(), e.get_cause(), e.get_sub_cause()); + }; + + } + + action_t * get_admitted_list (void ) const {return _action_admitted_ref.get();}; + action_t * get_not_admitted_list (void ) const{return _action_not_admitted_ref.get();}; + + void set_request(int id, int seq_no){ + _req_id = id; + _req_seq_no = seq_no; + + }; + + void clear(void){ + _action_admitted_ref.get()->clear(); + _action_not_admitted_ref.get()->clear(); + } + + + void set_function_id(int id){ + _func_id = id; + }; + + void add_action(int id){ + ActionResponse a(id) ; + _action_admitted_ref.get()->push_back(a); + }; + + void add_action(int id, int cause, int sub_cause){ + ActionResponse a (id, cause, sub_cause); + _action_not_admitted_ref.get()->push_back(a); + }; + + + int get_request_id(void) const{ + return _req_id; + } + + int get_req_seq(void) const{ + return _req_seq_no; + } + + int get_function_id(void) const{ + return _func_id; + } + + std::string to_string(void){ + std::string Info; + Info += "Request ID = " + std::to_string(_req_id) + "\n"; + Info += "Request Sequence No = " + std::to_string(_req_seq_no) + "\n"; + Info += "RAN Function ID = " + std::to_string(_func_id) + "\n"; + Info += "Actions Admitted =\n"; + int i = 0; + for(auto & e: *(_action_admitted_ref)){ + Info += std::to_string(i) + ": ID=" + std::to_string(e.get_id()) + "\n"; + i++; + } + Info += "Actions Not Admitted =\n"; + i = 0; + for(auto & e: *(_action_not_admitted_ref)){ + Info += std::to_string(i) + ": ID=" + std::to_string(e.get_id()) + ": Cause =" + std::to_string(e.get_cause()) + ": Sub-Cause=" + std::to_string(e.get_sub_cause()) + "\n"; + i++; + } + + return Info; + } + +private: + int _req_id, _req_seq_no, _func_id; + std::unique_ptr _action_admitted_ref; + std::unique_ptr _action_not_admitted_ref; + +}; + + +#endif diff --git a/src/xapp-asn/e2ap/subscription_delete_request.cc b/src/xapp-asn/e2ap/subscription_delete_request.cc new file mode 100644 index 0000000..d103d2e --- /dev/null +++ b/src/xapp-asn/e2ap/subscription_delete_request.cc @@ -0,0 +1,180 @@ + + +/* +================================================================================== + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== +*/ + + +#include "subscription_delete_request.hpp" + +subscription_delete::subscription_delete(void){ + + _name = "default"; + + e2ap_pdu_obj = (E2N_E2AP_PDU_t * )calloc(1, sizeof(E2N_E2AP_PDU_t)); + assert(e2ap_pdu_obj != 0); + + initMsg = (E2N_InitiatingMessage_t * )calloc(1, sizeof(E2N_InitiatingMessage_t)); + assert(initMsg != 0); + + IE_array = (E2N_RICsubscriptionDeleteRequest_IEs_t *)calloc(NUM_SUBSCRIPTION_DELETE_IES, sizeof(E2N_RICsubscriptionDeleteRequest_IEs_t)); + assert(IE_array != 0); + + E2N_RICsubscriptionDeleteRequest_t * subscription_delete = &(initMsg->value.choice.RICsubscriptionDeleteRequest); + for(int i = 0; i < NUM_SUBSCRIPTION_DELETE_IES; i++){ + ASN_SEQUENCE_ADD(&subscription_delete->protocolIEs, &(IE_array[i])); + } + +}; + + + +// Clear assigned protocolIE list from RIC indication IE container +subscription_delete::~subscription_delete(void){ + + mdclog_write(MDCLOG_DEBUG, "Freeing subscription delete request object memory"); + E2N_RICsubscriptionDeleteRequest_t * subscription_delete = &(initMsg->value.choice.RICsubscriptionDeleteRequest); + + for(int i = 0; i < subscription_delete->protocolIEs.list.size; i++){ + subscription_delete->protocolIEs.list.array[i] = 0; + } + + if (subscription_delete->protocolIEs.list.size > 0){ + free(subscription_delete->protocolIEs.list.array); + subscription_delete->protocolIEs.list.count = 0; + subscription_delete->protocolIEs.list.size = 0; + subscription_delete->protocolIEs.list.array = 0; + } + + free(IE_array); + free(initMsg); + e2ap_pdu_obj->choice.initiatingMessage = 0; + + ASN_STRUCT_FREE(asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj); + mdclog_write(MDCLOG_DEBUG, "Freed subscription delete request object memory"); + + +}; + + +bool subscription_delete::encode_e2ap_subscription(unsigned char *buf, size_t *size, subscription_helper &dinput){ + + e2ap_pdu_obj->choice.initiatingMessage = initMsg; + e2ap_pdu_obj->present = E2N_E2AP_PDU_PR_initiatingMessage; + set_fields( dinput); + + initMsg->procedureCode = E2N_ProcedureCode_id_ricSubscriptionDelete; + initMsg->criticality = E2N_Criticality_reject; + initMsg->value.present = E2N_InitiatingMessage__value_PR_RICsubscriptionDeleteRequest; + + //xer_fprint(stdout, &asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj); + + int ret_constr = asn_check_constraints(&asn_DEF_E2N_E2AP_PDU, (void *) e2ap_pdu_obj, errbuf, &errbuf_len); + if(ret_constr){ + error_string.assign(errbuf, errbuf_len); + error_string = "Constraints failed for encoding subscription delete request. Reason = " + error_string; + return false; + } + + asn_enc_rval_t res = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj, buf, *size); + + if(res.encoded == -1){ + error_string.assign(strerror(errno)); + error_string = "Error encoding Subscription Delete Request. Reason = " + error_string; + return false; + } + else { + if(*size < res.encoded){ + std::stringstream ss; + ss <<"Error encoding Subscription Delete Request . Reason = encoded pdu size " << res.encoded << " exceeds buffer size " << *size << std::endl; + error_string = ss.str(); + res.encoded = -1; + return false; + } + } + + *size = res.encoded; + return true; + +} + + +bool subscription_delete::set_fields( subscription_helper &helper){ + unsigned int ie_index; + + ie_index = 0; + E2N_RICsubscriptionDeleteRequest_IEs_t *ies_ricreq = &IE_array[ie_index]; + ies_ricreq->criticality = E2N_Criticality_reject; + ies_ricreq->id = E2N_ProtocolIE_ID_id_RICrequestID; + ies_ricreq->value.present = E2N_RICsubscriptionDeleteRequest_IEs__value_PR_RICrequestID; + E2N_RICrequestID_t *ricrequest_ie = &ies_ricreq->value.choice.RICrequestID; + ricrequest_ie->ricRequestorID = helper.get_request_id(); + ricrequest_ie->ricRequestSequenceNumber = helper.get_req_seq(); + + + + ie_index = 1; + E2N_RICsubscriptionDeleteRequest_IEs_t *ies_ranfunc = &IE_array[ie_index]; + ies_ranfunc->criticality = E2N_Criticality_reject; + ies_ranfunc->id = E2N_ProtocolIE_ID_id_RANfunctionID; + ies_ranfunc->value.present = E2N_RICsubscriptionDeleteRequest_IEs__value_PR_RANfunctionID; + E2N_RANfunctionID_t *ranfunction_ie = &ies_ranfunc->value.choice.RANfunctionID; + *ranfunction_ie = helper.get_function_id(); + + + return true; +}; + + + + +bool subscription_delete:: get_fields(E2N_InitiatingMessage_t * init_msg, subscription_helper & dout) +{ + + if (init_msg == 0){ + error_string = "Invalid reference for initiating message for get string"; + return false; + } + + E2N_RICrequestID_t *requestid; + E2N_RANfunctionID_t * ranfunctionid; + + for(int edx = 0; edx < init_msg->value.choice.RICsubscriptionDeleteRequest.protocolIEs.list.count; edx++) { + E2N_RICsubscriptionDeleteRequest_IEs_t *memb_ptr = init_msg->value.choice.RICsubscriptionDeleteRequest.protocolIEs.list.array[edx]; + + switch(memb_ptr->id) + { + case (E2N_ProtocolIE_ID_id_RICrequestID): + requestid = &memb_ptr->value.choice.RICrequestID; + dout.set_request(requestid->ricRequestorID, requestid->ricRequestSequenceNumber); + break; + + case (E2N_ProtocolIE_ID_id_RANfunctionID): + ranfunctionid = &memb_ptr->value.choice.RANfunctionID; + dout.set_function_id(*ranfunctionid); + break; + + } + + //asn_fprint(stdout, &asn_DEF_E2N_E2AP_PDU, e2pdu); + } + + return true; +} + + + diff --git a/src/xapp-asn/e2ap/subscription_delete_request.hpp b/src/xapp-asn/e2ap/subscription_delete_request.hpp new file mode 100644 index 0000000..e3c1d4e --- /dev/null +++ b/src/xapp-asn/e2ap/subscription_delete_request.hpp @@ -0,0 +1,67 @@ +/* +================================================================================== + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== +*/ + +#pragma once + +#ifndef S_DELETE_ +#define S_DELETE_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "subscription_helper.hpp" + +#define NUM_SUBSCRIPTION_DELETE_IES 2 + +class subscription_delete{ +public: + + subscription_delete(void); + ~subscription_delete(void); + + bool encode_e2ap_subscription(unsigned char *, size_t *, subscription_helper &); + bool set_fields(subscription_helper &); + bool get_fields(E2N_InitiatingMessage_t *, subscription_helper &); + + std::string get_error(void) const { + return error_string ; + } + +private: + + E2N_InitiatingMessage_t *initMsg; + E2N_E2AP_PDU_t * e2ap_pdu_obj; + + E2N_RICsubscriptionDeleteRequest_IEs_t * IE_array; + + + char errbuf[128]; + size_t errbuf_len = 128; + std::string _name; + std::string error_string; +}; + + + +#endif diff --git a/src/xapp-asn/e2ap/subscription_delete_response.cc b/src/xapp-asn/e2ap/subscription_delete_response.cc new file mode 100644 index 0000000..c1c166c --- /dev/null +++ b/src/xapp-asn/e2ap/subscription_delete_response.cc @@ -0,0 +1,292 @@ +/* +================================================================================== + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== +*/ + + +#include "subscription_delete_response.hpp" + +/* The xAPP need only worry about the get_fields from a response, since it does +not generate a response. Generating response however is included to support testing. +*/ + + +// Primarly for generation +subscription_delete_response::subscription_delete_response(void){ + + e2ap_pdu_obj = 0; + e2ap_pdu_obj = (E2N_E2AP_PDU_t *)calloc(1, sizeof(E2N_E2AP_PDU_t)); + assert(e2ap_pdu_obj != 0); + + successMsg = 0; + successMsg = (E2N_SuccessfulOutcome_t *)calloc(1, sizeof(E2N_SuccessfulOutcome_t)); + assert(successMsg != 0); + + unsuccessMsg = 0; + unsuccessMsg = (E2N_UnsuccessfulOutcome_t *)calloc(1, sizeof(E2N_UnsuccessfulOutcome_t)); + assert(unsuccessMsg != 0); + + IE_array = 0; + IE_array = (E2N_RICsubscriptionDeleteResponse_IEs_t *)calloc(NUM_SUBSCRIPTION_DELETE_RESPONSE_IES, sizeof(E2N_RICsubscriptionDeleteResponse_IEs_t)); + assert(IE_array != 0); + + IE_Failure_array = 0; + IE_Failure_array = (E2N_RICsubscriptionDeleteFailure_IEs_t *)calloc(NUM_SUBSCRIPTION_DELETE_FAILURE_IES, sizeof(E2N_RICsubscriptionDeleteFailure_IEs_t)); + assert(IE_Failure_array != 0); + + + +}; + + + +// Clear assigned protocolIE list from E2N_RIC indication IE container +subscription_delete_response::~subscription_delete_response(void){ + + mdclog_write(MDCLOG_DEBUG, "Freeing subscription delete response memory"); + E2N_RICsubscriptionDeleteResponse_t * ric_subscription_delete_response = &(successMsg->value.choice.RICsubscriptionDeleteResponse); + + for(unsigned int i = 0; i < ric_subscription_delete_response->protocolIEs.list.size ; i++){ + ric_subscription_delete_response->protocolIEs.list.array[i] = 0; + } + + + E2N_RICsubscriptionDeleteFailure_t * ric_subscription_failure = &(unsuccessMsg->value.choice.RICsubscriptionDeleteFailure); + for(unsigned int i = 0; i < ric_subscription_failure->protocolIEs.list.size; i++){ + ric_subscription_failure->protocolIEs.list.array[i] = 0; + } + + free(IE_array); + free(IE_Failure_array); + + ASN_STRUCT_FREE(asn_DEF_E2N_SuccessfulOutcome, successMsg); + + ASN_STRUCT_FREE(asn_DEF_E2N_UnsuccessfulOutcome, unsuccessMsg); + + e2ap_pdu_obj->choice.successfulOutcome = NULL; + e2ap_pdu_obj->choice.unsuccessfulOutcome = NULL; + + ASN_STRUCT_FREE(asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj); + mdclog_write(MDCLOG_DEBUG, "Freed subscription delete response memory"); + +}; + + +bool subscription_delete_response::encode_e2ap_subscription_delete_response(unsigned char *buf, size_t *size, subscription_response_helper &dinput, bool is_success){ + + bool res; + + if(is_success){ + res = set_fields(successMsg, dinput); + if (!res){ + return false; + } + e2ap_pdu_obj->present = E2N_E2AP_PDU_PR_successfulOutcome; + e2ap_pdu_obj->choice.successfulOutcome = successMsg; + } + else{ + res = set_fields(unsuccessMsg, dinput); + if(! res){ + return false; + } + e2ap_pdu_obj->present = E2N_E2AP_PDU_PR_unsuccessfulOutcome; + e2ap_pdu_obj->choice.unsuccessfulOutcome = unsuccessMsg; + } + + + int ret_constr = asn_check_constraints(&asn_DEF_E2N_E2AP_PDU, (void *) e2ap_pdu_obj, errbuf, &errbuf_len); + if(ret_constr){ + error_string.assign(errbuf, errbuf_len); + return false; + } + + //xer_fprint(stdout, &asn_DEF_E2AP_PDU, e2ap_pdu_obj); + + asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj, buf, *size); + + if(retval.encoded == -1){ + error_string.assign(strerror(errno)); + error_string = "Error encoding subcription delete response. Reason = " + error_string; + return false; + } + else { + if(*size < retval.encoded){ + std::stringstream ss; + ss <<"Error encoding Subscription Delete Response . Reason = encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl; + error_string = ss.str(); + retval.encoded = -1; + return false; + } + } + + *size = retval.encoded; + return true; + +} + +bool subscription_delete_response::set_fields(E2N_SuccessfulOutcome_t *success, subscription_response_helper &helper){ + + if (success == 0){ + error_string = "Invalid reference to success message in set fields subscription delete response"; + return false; + } + + unsigned int ie_index; + + success->procedureCode = E2N_ProcedureCode_id_ricSubscriptionDelete; + success->criticality = E2N_Criticality_reject; + success->value.present = E2N_SuccessfulOutcome__value_PR_RICsubscriptionDeleteResponse; + + E2N_RICsubscriptionDeleteResponse_t * subscription_delete_response = &(success->value.choice.RICsubscriptionDeleteResponse); + subscription_delete_response->protocolIEs.list.count = 0; + + ie_index = 0; + E2N_RICsubscriptionDeleteResponse_IEs_t *ies_ricreq = &IE_array[ie_index]; + + ies_ricreq->criticality = E2N_Criticality_reject; + ies_ricreq->id = E2N_ProtocolIE_ID_id_RICrequestID; + ies_ricreq->value.present = E2N_RICsubscriptionDeleteResponse_IEs__value_PR_RICrequestID; + E2N_RICrequestID_t *ricrequest_ie = &ies_ricreq->value.choice.RICrequestID; + ricrequest_ie->ricRequestorID = helper.get_request_id(); + ricrequest_ie->ricRequestSequenceNumber = helper.get_req_seq(); + ASN_SEQUENCE_ADD(&subscription_delete_response->protocolIEs, ies_ricreq); + + + ie_index = 1; + E2N_RICsubscriptionDeleteResponse_IEs_t *ies_ranfunc = &IE_array[ie_index]; + ies_ranfunc->criticality = E2N_Criticality_reject; + ies_ranfunc->id = E2N_ProtocolIE_ID_id_RANfunctionID; + ies_ranfunc->value.present = E2N_RICsubscriptionDeleteResponse_IEs__value_PR_RANfunctionID; + E2N_RANfunctionID_t *ranfunction_ie = &ies_ranfunc->value.choice.RANfunctionID; + *ranfunction_ie = helper.get_function_id(); + ASN_SEQUENCE_ADD(&subscription_delete_response->protocolIEs, ies_ranfunc); + + return true; + + +} + +bool subscription_delete_response:: get_fields(E2N_SuccessfulOutcome_t * success_msg, subscription_response_helper & dout) +{ + + if (success_msg == 0){ + error_string = "Invalid reference to success message inn get fields subscription delete response"; + return false; + } + + E2N_RICrequestID_t *requestid; + E2N_RANfunctionID_t * ranfunctionid; + + for(int edx = 0; edx < success_msg->value.choice.RICsubscriptionDeleteResponse.protocolIEs.list.count; edx++) { + E2N_RICsubscriptionDeleteResponse_IEs_t *memb_ptr = success_msg->value.choice.RICsubscriptionDeleteResponse.protocolIEs.list.array[edx]; + + switch(memb_ptr->id) + { + case (E2N_ProtocolIE_ID_id_RICrequestID): + requestid = &memb_ptr->value.choice.RICrequestID; + dout.set_request(requestid->ricRequestorID, requestid->ricRequestSequenceNumber); + break; + + case (E2N_ProtocolIE_ID_id_RANfunctionID): + ranfunctionid = &memb_ptr->value.choice.RANfunctionID; + dout.set_function_id(*ranfunctionid); + break; + } + + } + + return true; + //asn_fprint(stdout, &asn_DEF_E2AP_PDU, e2pdu); +} + + +bool subscription_delete_response::set_fields(E2N_UnsuccessfulOutcome_t *unsuccess, subscription_response_helper &helper){ + + if (unsuccess == 0){ + error_string = "Invalid reference to unsuccess message in set fields subscription delete response"; + return false; + } + + unsigned int ie_index; + + unsuccess->procedureCode = E2N_ProcedureCode_id_ricSubscriptionDelete; + unsuccess->criticality = E2N_Criticality_reject; + unsuccess->value.present = E2N_UnsuccessfulOutcome__value_PR_RICsubscriptionDeleteFailure; + + E2N_RICsubscriptionDeleteFailure_t * ric_subscription_failure = &(unsuccess->value.choice.RICsubscriptionDeleteFailure); + ric_subscription_failure->protocolIEs.list.count = 0; + + ie_index = 0; + E2N_RICsubscriptionDeleteFailure_IEs_t *ies_ricreq = &IE_Failure_array[ie_index]; + + ies_ricreq->criticality = E2N_Criticality_reject; + ies_ricreq->id = E2N_ProtocolIE_ID_id_RICrequestID; + ies_ricreq->value.present = E2N_RICsubscriptionDeleteFailure_IEs__value_PR_RICrequestID; + E2N_RICrequestID_t *ricrequest_ie = &ies_ricreq->value.choice.RICrequestID; + ricrequest_ie->ricRequestorID = helper.get_request_id(); + ricrequest_ie->ricRequestSequenceNumber = helper.get_req_seq(); + ASN_SEQUENCE_ADD(&ric_subscription_failure->protocolIEs, ies_ricreq); + + ie_index = 1; + E2N_RICsubscriptionDeleteFailure_IEs_t *ies_ranfunc = &IE_Failure_array[ie_index]; + ies_ranfunc->criticality = E2N_Criticality_reject; + ies_ranfunc->id = E2N_ProtocolIE_ID_id_RANfunctionID; + ies_ranfunc->value.present = E2N_RICsubscriptionDeleteFailure_IEs__value_PR_RANfunctionID; + E2N_RANfunctionID_t *ranfunction_ie = &ies_ranfunc->value.choice.RANfunctionID; + *ranfunction_ie = helper.get_function_id(); + ASN_SEQUENCE_ADD(&ric_subscription_failure->protocolIEs, ies_ranfunc); + + + return true; + +} + +bool subscription_delete_response:: get_fields(E2N_UnsuccessfulOutcome_t * unsuccess_msg, subscription_response_helper & dout) +{ + + if (unsuccess_msg == 0){ + error_string = "Invalid reference to unsuccess message in get fields subscription delete response"; + return false; + } + + E2N_RICrequestID_t *requestid; + E2N_RANfunctionID_t * ranfunctionid; + + for(int edx = 0; edx < unsuccess_msg->value.choice.RICsubscriptionDeleteFailure.protocolIEs.list.count; edx++) { + E2N_RICsubscriptionDeleteFailure_IEs_t *memb_ptr = unsuccess_msg->value.choice.RICsubscriptionDeleteFailure.protocolIEs.list.array[edx]; + + switch(memb_ptr->id) + { + case (E2N_ProtocolIE_ID_id_RICrequestID): + requestid = &memb_ptr->value.choice.RICrequestID; + dout.set_request(requestid->ricRequestorID, requestid->ricRequestSequenceNumber); + break; + + case (E2N_ProtocolIE_ID_id_RANfunctionID): + ranfunctionid = &memb_ptr->value.choice.RANfunctionID; + dout.set_function_id(*ranfunctionid); + break; + + } + + } + + return true; + //asn_fprint(stdout, &asn_DEF_E2AP_PDU, e2pdu); +} + + + diff --git a/src/xapp-asn/e2ap/subscription_delete_response.hpp b/src/xapp-asn/e2ap/subscription_delete_response.hpp new file mode 100644 index 0000000..d9581e4 --- /dev/null +++ b/src/xapp-asn/e2ap/subscription_delete_response.hpp @@ -0,0 +1,79 @@ +/* +================================================================================== + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== +*/ + +#pragma once + +#ifndef S_DEL_RESPONSE_ +#define S_DEL_RESPONSE_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "response_helper.hpp" + +#define NUM_SUBSCRIPTION_DELETE_RESPONSE_IES 2 +#define NUM_SUBSCRIPTION_DELETE_FAILURE_IES 2 + +class subscription_delete_response { +public: + + subscription_delete_response(void); + ~subscription_delete_response(void); + + bool encode_e2ap_subscription_delete_response(unsigned char *, size_t *, subscription_response_helper &, bool); + bool set_fields(E2N_SuccessfulOutcome_t *, subscription_response_helper &); + bool get_fields(E2N_SuccessfulOutcome_t *, subscription_response_helper &); + + bool set_fields(E2N_UnsuccessfulOutcome_t *, subscription_response_helper &); + bool get_fields(E2N_UnsuccessfulOutcome_t *, subscription_response_helper &); + + std::string get_error_string(void) const { + return error_string; + } + +private: + + E2N_E2AP_PDU_t * e2ap_pdu_obj; + E2N_SuccessfulOutcome_t * successMsg; + E2N_UnsuccessfulOutcome_t * unsuccessMsg; + + + E2N_RICsubscriptionDeleteResponse_IEs_t *IE_array; + E2N_RICsubscriptionDeleteFailure_IEs_t *IE_Failure_array; + + + char errbuf[128]; + size_t errbuf_len = 128; + std::string error_string; + +}; + + + + +#endif diff --git a/src/xapp-asn/e2ap/subscription_helper.hpp b/src/xapp-asn/e2ap/subscription_helper.hpp new file mode 100644 index 0000000..a9e0417 --- /dev/null +++ b/src/xapp-asn/e2ap/subscription_helper.hpp @@ -0,0 +1,195 @@ +/* +================================================================================== + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== +*/ + + +#ifndef SUB_HELPER_ +#define SUB_HELPER_ + +/* + Simple structure to store action related information based on E2 v0.22 + Used for subscription request, response etc + + ricActionID RICactionID, + ricActionType RICactionType, + ricActionDefinition RICactionDefinition OPTIONAL, + ricSubsequentAction RICsubsequentAction OPTIONAL, + ricCause +*/ + +#include +#include +#include +#include "generic_helpers.hpp" + + +// Note : if no action definition specified, octet length of action definition is NULL +// If no subsequent action specified, default is subsequent_action = 0, time to wait is 0 +struct Action { + +public: + + Action(int id, int type): _is_def(false), _is_subs_act(false), _id(id), _type(type), _next_action(0), _wait(0){}; + Action(int id, int type, const void *def, size_t def_size, int next, int wait): _is_def(false), _is_subs_act(false), _id(id), _type(type){ + + if (def_size > 0){ + _is_def = true; + _action_definition.set_ref(def); + _action_definition.set_size(def_size); + } + + if(next >= 0 && wait >= 0){ + _is_subs_act = true; + _next_action = next; + _wait = wait; + } + }; + + + int get_id() const{ + return _id; + } + + int get_type() const { + return _type; + } + + + const void * get_definition(void ) { + return _action_definition.get_ref(); + } + + int get_definition_size(void) const { + return _action_definition.get_size(); + }; + + + int get_subsequent_action() const { + return _next_action; + }; + + int get_wait() const { + return _wait; + } + + bool is_definition() const{ + + return _is_def; + } + + bool is_subsequent_action() const{ + return _is_subs_act; + } + +private: + + bool _is_def; + bool _is_subs_act; + int _id, _type, _next_action, _wait, _cause, _sub_cause; + bool _is_admit; + octet_helper _action_definition; + +}; + + +/* + Helper class that stores subscription data +*/ + + +struct subscription_helper { + +public: + + using action_t = std::vector; + + subscription_helper(){ + _action_ref = std::make_unique(); + curr_index = 0; + }; + + action_t * get_list() const {return _action_ref.get();}; + + void clear(void){ + _action_ref.get()->clear(); + } + + void set_request(int id, int seq_no){ + _req_id = id; + _req_seq_no = seq_no; + + }; + + void set_function_id(int id){ + _func_id = id; + }; + + void set_event_def(const void *ref, size_t size){ + _event_def.set_ref(ref); + _event_def.set_size(size); + }; + + + void add_action(int id, int type){ + Action a(id, type) ; + _action_ref.get()->push_back(a); + }; + + void add_action(int id, int type, std::string action_def, int next_action, int wait_time){ + Action a (id, type, action_def.c_str(), action_def.length(), next_action, wait_time); + _action_ref.get()->push_back(a); + }; + + + int get_request_id(void) const{ + return _req_id; + } + + int get_req_seq(void) const { + return _req_seq_no; + } + + int get_function_id(void) const{ + return _func_id; + } + + const void * get_event_def(void) { + return _event_def.get_ref(); + } + + int get_event_def_size(void) const { + return _event_def.get_size(); + } + + void print_sub_info(void){ + std::cout <<"Request ID = " << _req_id << std::endl; + std::cout <<"Request Sequence Number = " << _req_seq_no << std::endl; + std::cout <<"RAN Function ID = " << _func_id << std::endl; + for(auto const & e: *(_action_ref.get())){ + std::cout <<"Action ID = " << e.get_id() << " Action Type = " << e.get_type() << std::endl; + } + }; + +private: + + std::unique_ptr _action_ref; + int curr_index; + int _req_id, _req_seq_no, _func_id; + octet_helper _event_def; +}; + +#endif diff --git a/src/xapp-asn/e2ap/subscription_request.cc b/src/xapp-asn/e2ap/subscription_request.cc new file mode 100644 index 0000000..9b2f897 --- /dev/null +++ b/src/xapp-asn/e2ap/subscription_request.cc @@ -0,0 +1,308 @@ + + +/* +================================================================================== + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== +*/ + + +#include "subscription_request.hpp" + + +// Set up memory allocations for each IE for encoding +// We are responsible for memory management for each IE for encoding +// Hence destructor should clear out memory +// When decoding, we rely on asn1c macro (ASN_STRUCT_FREE to be called +// for releasing memory by external calling function) +subscription_request::subscription_request(void){ + + _name = "default"; + + e2ap_pdu_obj = 0; + e2ap_pdu_obj = (E2N_E2AP_PDU_t * )calloc(1, sizeof(E2N_E2AP_PDU_t)); + assert(e2ap_pdu_obj != 0); + + initMsg = 0; + initMsg = (E2N_InitiatingMessage_t * )calloc(1, sizeof(E2N_InitiatingMessage_t)); + assert(initMsg != 0); + + IE_array = 0; + IE_array = (E2N_RICsubscriptionRequest_IEs_t *)calloc(NUM_SUBSCRIPTION_REQUEST_IES, sizeof(E2N_RICsubscriptionRequest_IEs_t)); + assert(IE_array != 0); + + action_array = 0; + action_array = (E2N_RICaction_ToBeSetup_ItemIEs_t *)calloc(INITIAL_REQUEST_LIST_SIZE, sizeof(E2N_RICaction_ToBeSetup_ItemIEs_t)); + assert(action_array != 0); + action_array_size = INITIAL_REQUEST_LIST_SIZE; + // also need to add subsequent action and time to wait .. + for (unsigned int i = 0; i < action_array_size; i++){ + action_array[i].value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction = (struct E2N_RICsubsequentAction *)calloc(1, sizeof(struct E2N_RICsubsequentAction)); + assert(action_array[i].value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction != 0); + } + + e2ap_pdu_obj->choice.initiatingMessage = initMsg; + e2ap_pdu_obj->present = E2N_E2AP_PDU_PR_initiatingMessage; + + + +}; + + + +// Clear assigned protocolIE list from RIC indication IE container +subscription_request::~subscription_request(void){ + + mdclog_write(MDCLOG_DEBUG, "Freeing subscription request memory for");; + + // Sequence of actions to be admitted causes special heart-ache. Free ric subscription element manually and reset the ie pointer + E2N_RICsubscription_t * ricsubscription_ie = &(IE_array[2].value.choice.RICsubscription); + + for(int i = 0; i < ricsubscription_ie->ricAction_ToBeSetup_List.list.size; i++){ + ricsubscription_ie->ricAction_ToBeSetup_List.list.array[i] = 0; + } + + if (ricsubscription_ie->ricAction_ToBeSetup_List.list.size > 0){ + free(ricsubscription_ie->ricAction_ToBeSetup_List.list.array); + ricsubscription_ie->ricAction_ToBeSetup_List.list.size = 0; + ricsubscription_ie->ricAction_ToBeSetup_List.list.count = 0; + ricsubscription_ie->ricAction_ToBeSetup_List.list.array = 0; + } + + // clear subsequent action array + for (unsigned int i = 0; i < action_array_size; i++){ + free(action_array[i].value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction ); + } + + free(action_array); + E2N_RICsubscriptionRequest_t * subscription_request = &(initMsg->value.choice.RICsubscriptionRequest); + + for(int i = 0; i < subscription_request->protocolIEs.list.size; i++){ + subscription_request->protocolIEs.list.array[i] = 0; + } + + if( subscription_request->protocolIEs.list.size > 0){ + free( subscription_request->protocolIEs.list.array); + subscription_request->protocolIEs.list.array = 0; + subscription_request->protocolIEs.list.size = 0; + subscription_request->protocolIEs.list.count = 0; + } + + free(IE_array); + free(initMsg); + e2ap_pdu_obj->choice.initiatingMessage = 0; + + ASN_STRUCT_FREE(asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj); + mdclog_write(MDCLOG_DEBUG, "Freed subscription request memory "); +}; + + +bool subscription_request::encode_e2ap_subscription(unsigned char *buf, size_t *size, subscription_helper &dinput){ + + bool res; + + initMsg->procedureCode = E2N_ProcedureCode_id_ricSubscription; + initMsg->criticality = E2N_Criticality_ignore; + initMsg->value.present = E2N_InitiatingMessage__value_PR_RICsubscriptionRequest; + + res = set_fields(initMsg, dinput); + if (!res){ + return false; + } + + int ret_constr = asn_check_constraints(&asn_DEF_E2N_E2AP_PDU, (void *) e2ap_pdu_obj, errbuf, &errbuf_len); + if(ret_constr){ + error_string.assign(errbuf, errbuf_len); + error_string = "Constraints failed for encoding subscription request. Reason = " + error_string; + return false; + } + + //xer_fprint(stdout, &asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj); + + asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj, buf, *size); + + if(retval.encoded == -1){ + error_string.assign(strerror(errno)); + error_string = "Error encoding Subscription Request. Reason = " + error_string; + return false; + } + else { + if(*size < retval.encoded){ + std::stringstream ss; + ss <<"Error encoding Subscription Request . Reason = encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl; + error_string = ss.str(); + retval.encoded = -1; + return false; + } + } + + *size = retval.encoded; + return true; + +} + + +bool subscription_request::set_fields( E2N_InitiatingMessage_t * init_msg, subscription_helper &helper){ + + + int ie_index; + int result = 0; + + if (init_msg == 0){ + error_string = "Error. Invalid reference when getting fields from subscription request"; + return false; + } + + E2N_RICsubscriptionRequest_t * ric_subscription = &(init_msg->value.choice.RICsubscriptionRequest); + ric_subscription->protocolIEs.list.count = 0; + + ie_index = 0; + E2N_RICsubscriptionRequest_IEs_t *ies_ricreq = &IE_array[ie_index]; + ies_ricreq->criticality = E2N_Criticality_reject; + ies_ricreq->id = E2N_ProtocolIE_ID_id_RICrequestID; + ies_ricreq->value.present = E2N_RICsubscriptionRequest_IEs__value_PR_RICrequestID; + E2N_RICrequestID_t *ricrequest_ie = &ies_ricreq->value.choice.RICrequestID; + ricrequest_ie->ricRequestorID = helper.get_request_id(); + ricrequest_ie->ricRequestSequenceNumber = helper.get_req_seq(); + result = ASN_SEQUENCE_ADD(&(ric_subscription->protocolIEs), &IE_array[ie_index]); + assert(result == 0); + + ie_index = 1; + E2N_RICsubscriptionRequest_IEs_t *ies_ranfunc = &IE_array[ie_index]; + ies_ranfunc->criticality = E2N_Criticality_reject; + ies_ranfunc->id = E2N_ProtocolIE_ID_id_RANfunctionID; + ies_ranfunc->value.present = E2N_RICsubscriptionRequest_IEs__value_PR_RANfunctionID; + E2N_RANfunctionID_t *ranfunction_ie = &ies_ranfunc->value.choice.RANfunctionID; + *ranfunction_ie = helper.get_function_id(); + result = ASN_SEQUENCE_ADD(&(ric_subscription->protocolIEs), &IE_array[ie_index]); + assert(result == 0); + + + ie_index = 2; + E2N_RICsubscriptionRequest_IEs_t *ies_actid = &IE_array[ie_index]; + ies_actid->criticality = E2N_Criticality_reject; + ies_actid->id = E2N_ProtocolIE_ID_id_RICsubscription; + ies_actid->value.present = E2N_RICsubscriptionRequest_IEs__value_PR_RICsubscription; + E2N_RICsubscription_t *ricsubscription_ie = &ies_actid->value.choice.RICsubscription; + + ricsubscription_ie->ricEventTriggerDefinition.buf = (uint8_t *) helper.get_event_def(); + ricsubscription_ie->ricEventTriggerDefinition.size = helper.get_event_def_size(); + + std::vector * ref_action_array = helper.get_list(); + // do we need to resize ? + // we don't care about contents, so just do a free/calloc + if(action_array_size < ref_action_array->size()){ + std::cout <<"re-allocating action array from " << action_array_size << " to " << 2 * ref_action_array->size() << std::endl; + // free subsequent allocation + for (unsigned int i = 0; i < action_array_size; i++){ + free(action_array[i].value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction ); + } + + action_array_size = 2 * ref_action_array->size(); + free(action_array); + action_array = (E2N_RICaction_ToBeSetup_ItemIEs_t *)calloc(action_array_size, sizeof(E2N_RICaction_ToBeSetup_ItemIEs_t)); + assert(action_array != 0); + + // also need to add subsequent action and time to wait .. + for (unsigned int i = 0; i < action_array_size; i++){ + action_array[i].value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction = (struct E2N_RICsubsequentAction *)calloc(1, sizeof(struct E2N_RICsubsequentAction)); + assert(action_array[i].value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction != 0); + } + + } + + // reset the list count on ricAction_ToBeSetup_List; + ricsubscription_ie->ricAction_ToBeSetup_List.list.count = 0; + + for(unsigned int i = 0; i < ref_action_array->size(); i ++){ + action_array[i].criticality = E2N_Criticality_ignore; + action_array[i].id = E2N_ProtocolIE_ID_id_RICaction_ToBeSetup_Item ; + action_array[i].value.present = E2N_RICaction_ToBeSetup_ItemIEs__value_PR_RICaction_ToBeSetup_Item; + action_array[i].value.choice.RICaction_ToBeSetup_Item.ricActionID = (*ref_action_array)[i].get_id(); + action_array[i].value.choice.RICaction_ToBeSetup_Item.ricActionType = (*ref_action_array)[i].get_type(); + action_array[i].value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction->ricSubsequentActionType = (*ref_action_array)[i].get_subsequent_action(); + action_array[i].value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction->ricTimeToWait = (*ref_action_array)[i].get_wait(); + + result = ASN_SEQUENCE_ADD(&ricsubscription_ie->ricAction_ToBeSetup_List, &(action_array[i])); + if (result == -1){ + error_string = "Erorr : Unable to assign memory to add Action item to set up list"; + return false; + } + + } + + result = ASN_SEQUENCE_ADD(&(ric_subscription->protocolIEs), &IE_array[ie_index]); + assert(result == 0); + + + + return true; +}; + + + +bool subscription_request:: get_fields(E2N_InitiatingMessage_t * init_msg, subscription_helper & dout) +{ + + if (init_msg == 0){ + error_string = "Error. Invalid reference when getting fields from subscription request"; + return false; + } + + E2N_RICrequestID_t *requestid; + E2N_RANfunctionID_t * ranfunctionid; + E2N_RICsubscription_t * ricsubscription; + + for(int edx = 0; edx < init_msg->value.choice.RICsubscriptionRequest.protocolIEs.list.count; edx++) { + E2N_RICsubscriptionRequest_IEs_t *memb_ptr = init_msg->value.choice.RICsubscriptionRequest.protocolIEs.list.array[edx]; + + switch(memb_ptr->id) + { + case (E2N_ProtocolIE_ID_id_RICrequestID): + requestid = &memb_ptr->value.choice.RICrequestID; + dout.set_request(requestid->ricRequestorID, requestid->ricRequestSequenceNumber); + break; + + case (E2N_ProtocolIE_ID_id_RANfunctionID): + ranfunctionid = &memb_ptr->value.choice.RANfunctionID; + dout.set_function_id(*ranfunctionid); + break; + + case (E2N_ProtocolIE_ID_id_RICsubscription): + ricsubscription = &memb_ptr->value.choice.RICsubscription; + dout.set_event_def(ricsubscription->ricEventTriggerDefinition.buf, ricsubscription->ricEventTriggerDefinition.size); + + for(int index = 0; index < ricsubscription->ricAction_ToBeSetup_List.list.count; index ++){ + E2N_RICaction_ToBeSetup_ItemIEs_t * item = (E2N_RICaction_ToBeSetup_ItemIEs_t *)ricsubscription->ricAction_ToBeSetup_List.list.array[index]; + if (item->value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction == NULL){ + dout.add_action(item->value.choice.RICaction_ToBeSetup_Item.ricActionID, item->value.choice.RICaction_ToBeSetup_Item.ricActionType); + } + else{ + std::string action_def = ""; // for now we are ignoring action definition + dout.add_action(item->value.choice.RICaction_ToBeSetup_Item.ricActionID, item->value.choice.RICaction_ToBeSetup_Item.ricActionType, action_def, item->value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction->ricSubsequentActionType, item->value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction->ricTimeToWait); + } + }; + + break; + } + + } + + //asn_fprint(stdout, &asn_DEF_E2N_E2AP_PDU, e2pdu); + return true; +}; + + + diff --git a/src/xapp-asn/e2ap/subscription_request.hpp b/src/xapp-asn/e2ap/subscription_request.hpp new file mode 100644 index 0000000..28f419a --- /dev/null +++ b/src/xapp-asn/e2ap/subscription_request.hpp @@ -0,0 +1,73 @@ +/* +================================================================================== + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== +*/ + +#pragma once + +#ifndef S_REQUEST_ +#define S_REQUEST_ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "subscription_helper.hpp" + +#define NUM_SUBSCRIPTION_REQUEST_IES 3 +#define INITIAL_REQUEST_LIST_SIZE 4 + +class subscription_request{ +public: + + subscription_request(std::string name); + subscription_request(void); + ~subscription_request(void); + + bool encode_e2ap_subscription(unsigned char *, size_t *, subscription_helper &); + bool set_fields(E2N_InitiatingMessage_t *, subscription_helper &); + bool get_fields(E2N_InitiatingMessage_t *, subscription_helper &); + + std::string get_error(void) const{ + return error_string; + } + +private: + + E2N_InitiatingMessage_t *initMsg; + E2N_E2AP_PDU_t * e2ap_pdu_obj; + + E2N_RICsubscriptionRequest_IEs_t * IE_array; + E2N_RICaction_ToBeSetup_ItemIEs_t * action_array; + unsigned int action_array_size; + char errbuf[128]; + size_t errbuf_len = 128; + std::string _name; + std::string error_string; +}; + + + +#endif diff --git a/src/xapp-asn/e2ap/subscription_response.cc b/src/xapp-asn/e2ap/subscription_response.cc new file mode 100644 index 0000000..5308e81 --- /dev/null +++ b/src/xapp-asn/e2ap/subscription_response.cc @@ -0,0 +1,583 @@ +/* +================================================================================== + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== +*/ + + +#include "subscription_response.hpp" + +/* The xAPP need only worry about the get_fields from a response, since it does +not generate a response. Generating response however is included to support testing. +*/ + + +// Primarly for generation +subscription_response::subscription_response(void){ + + e2ap_pdu_obj = 0; + e2ap_pdu_obj = (E2N_E2AP_PDU_t *)calloc(1, sizeof(E2N_E2AP_PDU_t)); + assert(e2ap_pdu_obj != 0); + + successMsg = 0; + successMsg = (E2N_SuccessfulOutcome_t *)calloc(1, sizeof(E2N_SuccessfulOutcome_t)); + assert(successMsg != 0); + + unsuccessMsg = 0; + unsuccessMsg = (E2N_UnsuccessfulOutcome_t *)calloc(1, sizeof(E2N_UnsuccessfulOutcome_t)); + assert(unsuccessMsg != 0); + + IE_array = 0; + IE_array = (E2N_RICsubscriptionResponse_IEs_t *)calloc(NUM_SUBSCRIPTION_RESPONSE_IES, sizeof(E2N_RICsubscriptionResponse_IEs_t)); + assert(IE_array != 0); + + IE_Failure_array = 0; + IE_Failure_array = (E2N_RICsubscriptionFailure_IEs_t *)calloc(NUM_SUBSCRIPTION_FAILURE_IES, sizeof(E2N_RICsubscriptionFailure_IEs_t)); + assert(IE_Failure_array != 0); + + ie_admitted_list = 0; + ie_admitted_list = (E2N_RICaction_Admitted_ItemIEs_t *)calloc(INITIAL_RESPONSE_LIST_SIZE, sizeof(E2N_RICaction_Admitted_ItemIEs_t)); + assert(ie_admitted_list != 0); + ie_admitted_list_size = INITIAL_RESPONSE_LIST_SIZE; + + ie_not_admitted_list = 0; + ie_not_admitted_list = (E2N_RICaction_NotAdmitted_ItemIEs_t *)calloc(INITIAL_RESPONSE_LIST_SIZE, sizeof(E2N_RICaction_NotAdmitted_ItemIEs_t)); + assert(ie_not_admitted_list != 0); + ie_not_admitted_list_size = INITIAL_RESPONSE_LIST_SIZE; + + + + + +}; + + + +// Clear assigned protocolIE list from RIC indication IE container +subscription_response::~subscription_response(void){ + + mdclog_write(MDCLOG_DEBUG, "Freeing subscription response memory"); + E2N_RICaction_Admitted_List_t * response_admitted_list = (E2N_RICaction_Admitted_List_t *) &(IE_array[2].value.choice.RICaction_Admitted_List); + + for(int i = 0; i < response_admitted_list->list.size; i++){ + response_admitted_list->list.array[i] = 0; + } + + + if (response_admitted_list->list.size > 0){ + free(response_admitted_list->list.array); + response_admitted_list->list.array = 0; + response_admitted_list->list.size = 0; + response_admitted_list->list.count = 0; + } + + + E2N_RICaction_NotAdmitted_List_t * response_not_admitted_list = &(IE_array[3].value.choice.RICaction_NotAdmitted_List); + for(int i = 0; i < response_not_admitted_list->list.size; i++){ + response_not_admitted_list->list.array[i] = 0; + } + + if (response_not_admitted_list->list.size > 0){ + free(response_not_admitted_list->list.array); + response_not_admitted_list->list.array = 0; + response_not_admitted_list->list.size = 0; + response_not_admitted_list->list.count = 0; + } + + E2N_RICsubscriptionResponse_t * ric_subscription_response = &(successMsg->value.choice.RICsubscriptionResponse); + for(int i = 0; i < ric_subscription_response->protocolIEs.list.size ; i++){ + ric_subscription_response->protocolIEs.list.array[i] = 0; + } + + if (ric_subscription_response->protocolIEs.list.size > 0){ + free(ric_subscription_response->protocolIEs.list.array); + ric_subscription_response->protocolIEs.list.array = 0; + ric_subscription_response->protocolIEs.list.size = 0; + ric_subscription_response->protocolIEs.list.count = 0; + } + + + E2N_RICaction_NotAdmitted_List_t * failure_not_admitted_list = &(IE_Failure_array[2].value.choice.RICaction_NotAdmitted_List); + for(int i = 0; i < failure_not_admitted_list->list.size; i++){ + failure_not_admitted_list->list.array[i] = 0; + } + + if ( failure_not_admitted_list->list.size > 0){ + free( failure_not_admitted_list->list.array); + failure_not_admitted_list->list.array = 0; + failure_not_admitted_list->list.size = 0; + failure_not_admitted_list->list.count = 0; + } + + + E2N_RICsubscriptionFailure_t * ric_subscription_failure = &(unsuccessMsg->value.choice.RICsubscriptionFailure); + for(int i = 0; i < ric_subscription_failure->protocolIEs.list.size; i++){ + ric_subscription_failure->protocolIEs.list.array[i] = 0; + } + + if ( ric_subscription_failure->protocolIEs.list.size > 0){ + free(ric_subscription_failure->protocolIEs.list.array); + ric_subscription_failure->protocolIEs.list.array = 0; + ric_subscription_failure->protocolIEs.list.size = 0; + ric_subscription_failure->protocolIEs.list.count = 0; + } + + + free(ie_admitted_list); + free(ie_not_admitted_list); + free(IE_Failure_array); + free(IE_array); + + + ASN_STRUCT_FREE(asn_DEF_E2N_SuccessfulOutcome, successMsg); + ASN_STRUCT_FREE(asn_DEF_E2N_UnsuccessfulOutcome, unsuccessMsg); + + + e2ap_pdu_obj->choice.initiatingMessage = NULL; + e2ap_pdu_obj->present = E2N_E2AP_PDU_PR_NOTHING; + ASN_STRUCT_FREE(asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj); + + mdclog_write(MDCLOG_DEBUG, "Freed subscription response memory "); + + +}; + + +bool subscription_response::encode_e2ap_subscription_response(unsigned char *buf, size_t *size, subscription_response_helper &dinput, bool is_success){ + + + if(is_success){ + set_fields_success(dinput); + e2ap_pdu_obj->present = E2N_E2AP_PDU_PR_successfulOutcome; + e2ap_pdu_obj->choice.successfulOutcome = successMsg; + + successMsg->procedureCode = E2N_ProcedureCode_id_ricSubscription; + successMsg->criticality = E2N_Criticality_reject; + successMsg->value.present = E2N_SuccessfulOutcome__value_PR_RICsubscriptionResponse; + + } + else{ + set_fields_unsuccess(dinput); + e2ap_pdu_obj->present = E2N_E2AP_PDU_PR_unsuccessfulOutcome; + e2ap_pdu_obj->choice.unsuccessfulOutcome = unsuccessMsg; + + unsuccessMsg->procedureCode = E2N_ProcedureCode_id_ricSubscription; + unsuccessMsg->criticality = E2N_Criticality_reject; + unsuccessMsg->value.present = E2N_UnsuccessfulOutcome__value_PR_RICsubscriptionFailure; + + } + + //xer_fprint(stdout, &asn_DEF_E2AP_PDU, e2ap_pdu_obj); + + int ret_constr = asn_check_constraints(&asn_DEF_E2N_E2AP_PDU, (void *) e2ap_pdu_obj, errbuf, &errbuf_len); + if(ret_constr){ + error_string.assign(errbuf, errbuf_len); + error_string = "Constraints failed for encoding subscription response. Reason = " + error_string; + return false; + } + + asn_enc_rval_t res = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2AP_PDU, e2ap_pdu_obj, buf, *size); + + if(res.encoded == -1){ + std::cout <<"Error encoding PDU. Reason =" << strerror(errno) << std::endl; + return false; + } + else { + if(*size < res.encoded){ + fprintf(stderr, "Buffer assigned too small to encode: %s",(char *)(asn_DEF_E2N_E2AP_PDU.name)); + res.encoded = -1; + return false; + } + } + + *size = res.encoded; + return true; + +} + +void subscription_response::set_fields_success(subscription_response_helper &helper){ + + int ie_index; + + E2N_RICsubscriptionResponse_t * subscription_response = &(successMsg->value.choice.RICsubscriptionResponse); + //reset list count .. + subscription_response->protocolIEs.list.count = 0; + + ie_index = 0; + E2N_RICsubscriptionResponse_IEs_t *ies_ricreq = &IE_array[ie_index]; + + ies_ricreq->criticality = E2N_Criticality_reject; + ies_ricreq->id = E2N_ProtocolIE_ID_id_RICrequestID; + ies_ricreq->value.present = E2N_RICsubscriptionResponse_IEs__value_PR_RICrequestID; + E2N_RICrequestID_t *ricrequest_ie = &ies_ricreq->value.choice.RICrequestID; + ricrequest_ie->ricRequestorID = helper.get_request_id(); + ricrequest_ie->ricRequestSequenceNumber = helper.get_req_seq(); + ASN_SEQUENCE_ADD(&subscription_response->protocolIEs, &(IE_array[ie_index])); + + + ie_index = 1; + E2N_RICsubscriptionResponse_IEs_t *ies_ranfunc = &IE_array[ie_index]; + ies_ranfunc->criticality = E2N_Criticality_reject; + ies_ranfunc->id = E2N_ProtocolIE_ID_id_RANfunctionID; + ies_ranfunc->value.present = E2N_RICsubscriptionResponse_IEs__value_PR_RANfunctionID; + E2N_RANfunctionID_t *ranfunction_ie = &ies_ranfunc->value.choice.RANfunctionID; + *ranfunction_ie = helper.get_function_id(); + ASN_SEQUENCE_ADD(&subscription_response->protocolIEs, &(IE_array[ie_index])); + + + ie_index = 2; + E2N_RICsubscriptionResponse_IEs_t *ies_admitted_actid = &IE_array[ie_index]; + ies_admitted_actid->criticality = E2N_Criticality_reject; + ies_admitted_actid->id = E2N_ProtocolIE_ID_id_RICactions_Admitted; + E2N_RICaction_Admitted_List_t *ric_admitted_actions_ie = &ies_admitted_actid->value.choice.RICaction_Admitted_List; + ric_admitted_actions_ie->list.count = 0; + std::vector * ref_admitted_action_array = helper.get_admitted_list(); + + if(ref_admitted_action_array->size() == 0){ + ies_admitted_actid->value.present = E2N_RICsubscriptionResponse_IEs__value_PR_NOTHING; + } + else{ + ies_admitted_actid->value.present = E2N_RICsubscriptionResponse_IEs__value_PR_RICaction_Admitted_List; + + // resize memory ? + if (ref_admitted_action_array->size() >= ie_admitted_list_size){ + ie_admitted_list_size = 2 * ref_admitted_action_array->size(); + free(ie_admitted_list); + ie_admitted_list = (E2N_RICaction_Admitted_ItemIEs_t *)calloc(ie_admitted_list_size, sizeof(E2N_RICaction_Admitted_ItemIEs_t)); + assert(ie_admitted_list != 0); + }; + + + for(unsigned int i = 0; i < ref_admitted_action_array->size(); i ++){ + ie_admitted_list[i].criticality = E2N_Criticality_ignore; + ie_admitted_list[i].id = E2N_ProtocolIE_ID_id_RICaction_Admitted_Item ; + ie_admitted_list[i].value.present = E2N_RICaction_Admitted_ItemIEs__value_PR_RICaction_Admitted_Item; + ie_admitted_list[i].value.choice.RICaction_Admitted_Item.ricActionID = (*ref_admitted_action_array)[i].get_id(); + ASN_SEQUENCE_ADD(ric_admitted_actions_ie, &(ie_admitted_list[i])); + } + } + ASN_SEQUENCE_ADD(&subscription_response->protocolIEs, &(IE_array[ie_index])); + + // optional IE : add only if non-zero list + ie_index = 3; + std::vector * ref_notadmitted_action_array = helper.get_not_admitted_list(); + if (ref_notadmitted_action_array->size() > 0){ + + E2N_RICsubscriptionResponse_IEs_t *ies_notadmitted_actid = &IE_array[ie_index]; + ies_notadmitted_actid->criticality = E2N_Criticality_reject; + ies_notadmitted_actid->id = E2N_ProtocolIE_ID_id_RICactions_NotAdmitted; + + E2N_RICaction_NotAdmitted_List_t *ric_not_admitted_actions_ie = &ies_notadmitted_actid->value.choice.RICaction_NotAdmitted_List; + ric_not_admitted_actions_ie->list.count = 0; + + + ies_notadmitted_actid->value.present = E2N_RICsubscriptionResponse_IEs__value_PR_RICaction_NotAdmitted_List; + + // resize memory ? + if (ref_notadmitted_action_array->size() >= ie_not_admitted_list_size){ + ie_not_admitted_list_size = 2 * ref_notadmitted_action_array->size(); + free(ie_not_admitted_list); + ie_not_admitted_list = (E2N_RICaction_NotAdmitted_ItemIEs_t *)calloc(ie_not_admitted_list_size, sizeof(E2N_RICaction_NotAdmitted_ItemIEs_t)); + assert(ie_not_admitted_list != 0); + + }; + + + for(unsigned int i = 0; i < ref_notadmitted_action_array->size(); i ++){ + ie_not_admitted_list[i].criticality = E2N_Criticality_ignore; + ie_not_admitted_list[i].id = E2N_ProtocolIE_ID_id_RICaction_NotAdmitted_Item ; + ie_not_admitted_list[i].value.present = E2N_RICaction_NotAdmitted_ItemIEs__value_PR_RICaction_NotAdmitted_Item;; + ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.ricActionID = (*ref_notadmitted_action_array)[i].get_id(); + + int cause = (*ref_notadmitted_action_array)[i].get_cause(); + switch(cause){ + case E2N_RICcause_PR_radioNetwork: + ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.ricCause.choice.radioNetwork = (*ref_notadmitted_action_array)[i].get_sub_cause(); + break; + case E2N_RICcause_PR_transport: + ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.ricCause.choice.transport = (*ref_notadmitted_action_array)[i].get_sub_cause(); + break; + case E2N_RICcause_PR_protocol: + ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.ricCause.choice.protocol= (*ref_notadmitted_action_array)[i].get_sub_cause(); + break; + case E2N_RICcause_PR_misc: + ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.ricCause.choice.misc = (*ref_notadmitted_action_array)[i].get_sub_cause(); + break; + case E2N_RICcause_PR_ric: + ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.ricCause.choice.ric = (*ref_notadmitted_action_array)[i].get_sub_cause(); + break; + default: + mdclog_write(MDCLOG_ERR, "Error :: %s, %d : Unknown RIC cause %d\n", __FILE__, __LINE__, cause); + return; + } + + ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.ricCause.present = (E2N_RICcause_PR)cause; + ASN_SEQUENCE_ADD(ric_not_admitted_actions_ie, &(ie_not_admitted_list[i])); + } + + ASN_SEQUENCE_ADD(&subscription_response->protocolIEs, &(IE_array[ie_index])); + } + +} + +void subscription_response:: get_fields(E2N_SuccessfulOutcome_t * success_msg, subscription_response_helper & dout) +{ + + assert(success_msg != NULL); + + E2N_RICrequestID_t *requestid; + E2N_RANfunctionID_t * ranfunctionid; + E2N_RICaction_Admitted_List_t * ric_admitted_action_list; + E2N_RICaction_NotAdmitted_List_t * ric_not_admitted_action_list; + + for(int edx = 0; edx < success_msg->value.choice.RICsubscriptionResponse.protocolIEs.list.count; edx++) { + E2N_RICsubscriptionResponse_IEs_t *memb_ptr = success_msg->value.choice.RICsubscriptionResponse.protocolIEs.list.array[edx]; + + switch(memb_ptr->id) + { + case (E2N_ProtocolIE_ID_id_RICrequestID): + requestid = &memb_ptr->value.choice.RICrequestID; + dout.set_request(requestid->ricRequestorID, requestid->ricRequestSequenceNumber); + break; + + case (E2N_ProtocolIE_ID_id_RANfunctionID): + ranfunctionid = &memb_ptr->value.choice.RANfunctionID; + dout.set_function_id(*ranfunctionid); + break; + + case (E2N_ProtocolIE_ID_id_RICactions_Admitted): + ric_admitted_action_list = &memb_ptr->value.choice.RICaction_Admitted_List; + + // admitted actions + for(int index = 0; index < ric_admitted_action_list->list.count; index ++){ + E2N_RICaction_Admitted_ItemIEs_t * item = (E2N_RICaction_Admitted_ItemIEs_t *)ric_admitted_action_list->list.array[index]; + long int id = item->value.choice.RICaction_Admitted_Item.ricActionID; + dout.get_admitted_list()->push_back(ActionResponse(id)); + }; + + break; + + case (E2N_ProtocolIE_ID_id_RICactions_NotAdmitted): + ric_not_admitted_action_list = &memb_ptr->value.choice.RICaction_NotAdmitted_List; + + for(int index = 0; index < ric_not_admitted_action_list->list.count; index ++){ + E2N_RICaction_NotAdmitted_ItemIEs_t * item = (E2N_RICaction_NotAdmitted_ItemIEs_t *)ric_not_admitted_action_list->list.array[index]; + long int id = item->value.choice.RICaction_NotAdmitted_Item.ricActionID; + int cause = item->value.choice.RICaction_NotAdmitted_Item.ricCause.present; + int sub_cause; + switch(cause){ + + case E2N_RICcause_PR_radioNetwork : + sub_cause = item->value.choice.RICaction_NotAdmitted_Item.ricCause.choice.radioNetwork; + break; + + case E2N_RICcause_PR_transport : + sub_cause = item->value.choice.RICaction_NotAdmitted_Item.ricCause.choice.transport; + break; + + case E2N_RICcause_PR_protocol : + sub_cause = item->value.choice.RICaction_NotAdmitted_Item.ricCause.choice.protocol; + break; + + case E2N_RICcause_PR_misc : + sub_cause = item->value.choice.RICaction_NotAdmitted_Item.ricCause.choice.misc; + break; + + case E2N_RICcause_PR_ric : + sub_cause = item->value.choice.RICaction_NotAdmitted_Item.ricCause.choice.ric; + break; + + default: + std::cout <<"Error ! Illegal cause enum" << cause << std::endl; + return; + } + dout.get_not_admitted_list()->push_back(ActionResponse(id, cause, sub_cause)); + } + break; + } + + } + + //asn_fprint(stdout, &asn_DEF_E2AP_PDU, e2pdu); +} + + +void subscription_response::set_fields_unsuccess( subscription_response_helper &helper){ + + int ie_index; + E2N_RICsubscriptionFailure_t * ric_subscription_failure = &(unsuccessMsg->value.choice.RICsubscriptionFailure); + // reset list count + ric_subscription_failure->protocolIEs.list.count = 0; + + ie_index = 0; + E2N_RICsubscriptionFailure_IEs_t *ies_ricreq = &IE_Failure_array[ie_index]; + ies_ricreq->criticality = E2N_Criticality_reject; + ies_ricreq->id = E2N_ProtocolIE_ID_id_RICrequestID; + ies_ricreq->value.present = E2N_RICsubscriptionFailure_IEs__value_PR_RICrequestID; + E2N_RICrequestID_t *ricrequest_ie = &ies_ricreq->value.choice.RICrequestID; + ricrequest_ie->ricRequestorID = helper.get_request_id(); + ricrequest_ie->ricRequestSequenceNumber = helper.get_req_seq(); + ASN_SEQUENCE_ADD(&ric_subscription_failure->protocolIEs, &(IE_Failure_array[ie_index])); + + ie_index = 1; + E2N_RICsubscriptionFailure_IEs_t *ies_ranfunc = &IE_Failure_array[ie_index]; + ies_ranfunc->criticality = E2N_Criticality_reject; + ies_ranfunc->id = E2N_ProtocolIE_ID_id_RANfunctionID; + ies_ranfunc->value.present = E2N_RICsubscriptionFailure_IEs__value_PR_RANfunctionID; + E2N_RANfunctionID_t *ranfunction_ie = &ies_ranfunc->value.choice.RANfunctionID; + *ranfunction_ie = helper.get_function_id(); + ASN_SEQUENCE_ADD(&ric_subscription_failure->protocolIEs, &(IE_Failure_array[ie_index])); + + ie_index = 2; + E2N_RICsubscriptionFailure_IEs_t *ies_notadmitted_actid = &IE_Failure_array[ie_index]; + ies_notadmitted_actid->criticality = E2N_Criticality_reject; + ies_notadmitted_actid->id = E2N_ProtocolIE_ID_id_RICactions_NotAdmitted; + E2N_RICaction_NotAdmitted_List_t *ric_not_admitted_actions_ie = &ies_notadmitted_actid->value.choice.RICaction_NotAdmitted_List; + ric_not_admitted_actions_ie->list.count = 0; + std::vector * ref_notadmitted_action_array = helper.get_not_admitted_list(); + if(ref_notadmitted_action_array->size() == 0){ + ies_notadmitted_actid->value.present = E2N_RICsubscriptionFailure_IEs__value_PR_NOTHING; + } + else{ + ies_notadmitted_actid->value.present = E2N_RICsubscriptionFailure_IEs__value_PR_RICaction_NotAdmitted_List; + + // resize memory ? + if (ref_notadmitted_action_array->size() >= ie_not_admitted_list_size){ + ie_not_admitted_list_size = 2 * ref_notadmitted_action_array->size(); + free(ie_not_admitted_list); + ie_not_admitted_list = (E2N_RICaction_NotAdmitted_ItemIEs_t *)calloc(ie_not_admitted_list_size, sizeof(E2N_RICaction_NotAdmitted_ItemIEs_t)); + assert(ie_not_admitted_list != 0); + }; + + + // reset the list count on ricAction_ToBeSetup_List; + for(unsigned int i = 0; i < ref_notadmitted_action_array->size(); i ++){ + ie_not_admitted_list[i].criticality = E2N_Criticality_ignore; + ie_not_admitted_list[i].id = E2N_ProtocolIE_ID_id_RICaction_NotAdmitted_Item ; + ie_not_admitted_list[i].value.present = E2N_RICaction_NotAdmitted_ItemIEs__value_PR_RICaction_NotAdmitted_Item;; + ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.ricActionID = (*ref_notadmitted_action_array)[i].get_id(); + + int cause = (*ref_notadmitted_action_array)[i].get_cause(); + switch(cause){ + case E2N_RICcause_PR_radioNetwork: + ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.ricCause.choice.radioNetwork = (*ref_notadmitted_action_array)[i].get_sub_cause(); + break; + case E2N_RICcause_PR_transport: + ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.ricCause.choice.transport = (*ref_notadmitted_action_array)[i].get_sub_cause(); + break; + case E2N_RICcause_PR_protocol: + ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.ricCause.choice.protocol= (*ref_notadmitted_action_array)[i].get_sub_cause(); + break; + case E2N_RICcause_PR_misc: + ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.ricCause.choice.misc = (*ref_notadmitted_action_array)[i].get_sub_cause(); + break; + case E2N_RICcause_PR_ric: + ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.ricCause.choice.ric = (*ref_notadmitted_action_array)[i].get_sub_cause(); + break; + default: + mdclog_write(MDCLOG_ERR, "Error :: %s, %d : Unknown RIC cause %d\n", __FILE__, __LINE__, cause); + return ; + } + + ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.ricCause.present = (E2N_RICcause_PR)cause; + + ASN_SEQUENCE_ADD(ric_not_admitted_actions_ie, &(ie_not_admitted_list[i])); + } + + } + ASN_SEQUENCE_ADD(&ric_subscription_failure->protocolIEs, &(IE_Failure_array[ie_index])); + + + // // criticality diagnostics is not generated/parsed currently since optional + // i = 3; + // E2N_RICsubscriptionFailure_IEs_t *ies_criticality_diagnostics= &IE_Failure_array[i]; + // ies_criticality_diagnostics->criticality = E2N_Criticality_ignore; + // ies_criticality_diagnostics->id = E2N_ProtocolIE_ID_id_CriticalityDiagnostics ; + // ies_criticality_diagnostics->value.present = E2N_RICsubscriptionFailure_IEs__value_PR_NOTHING; + + +} + +void subscription_response:: get_fields(E2N_UnsuccessfulOutcome_t * unsuccess_msg, subscription_response_helper & dout) +{ + + assert(unsuccess_msg != NULL); + + E2N_RICrequestID_t *requestid; + E2N_RANfunctionID_t * ranfunctionid; + E2N_RICaction_NotAdmitted_List_t * ric_not_admitted_action_list; + + for(int edx = 0; edx < unsuccess_msg->value.choice.RICsubscriptionFailure.protocolIEs.list.count; edx++) { + E2N_RICsubscriptionFailure_IEs_t *memb_ptr = unsuccess_msg->value.choice.RICsubscriptionFailure.protocolIEs.list.array[edx]; + + switch(memb_ptr->id) + { + case (E2N_ProtocolIE_ID_id_RICrequestID): + requestid = &memb_ptr->value.choice.RICrequestID; + dout.set_request(requestid->ricRequestorID, requestid->ricRequestSequenceNumber); + break; + + case (E2N_ProtocolIE_ID_id_RANfunctionID): + ranfunctionid = &memb_ptr->value.choice.RANfunctionID; + dout.set_function_id(*ranfunctionid); + break; + + + case (E2N_ProtocolIE_ID_id_RICactions_NotAdmitted): + ric_not_admitted_action_list = &memb_ptr->value.choice.RICaction_NotAdmitted_List; + + for(int index = 0; index < ric_not_admitted_action_list->list.count; index ++){ + E2N_RICaction_NotAdmitted_ItemIEs_t * item = (E2N_RICaction_NotAdmitted_ItemIEs_t *)ric_not_admitted_action_list->list.array[index]; + long int id = item->value.choice.RICaction_NotAdmitted_Item.ricActionID; + int cause = item->value.choice.RICaction_NotAdmitted_Item.ricCause.present; + int sub_cause; + switch(cause){ + + case E2N_RICcause_PR_radioNetwork : + sub_cause = item->value.choice.RICaction_NotAdmitted_Item.ricCause.choice.radioNetwork; + break; + + case E2N_RICcause_PR_transport : + sub_cause = item->value.choice.RICaction_NotAdmitted_Item.ricCause.choice.transport; + break; + + case E2N_RICcause_PR_protocol : + sub_cause = item->value.choice.RICaction_NotAdmitted_Item.ricCause.choice.protocol; + break; + + case E2N_RICcause_PR_misc : + sub_cause = item->value.choice.RICaction_NotAdmitted_Item.ricCause.choice.misc; + break; + + case E2N_RICcause_PR_ric : + sub_cause = item->value.choice.RICaction_NotAdmitted_Item.ricCause.choice.ric; + break; + + default: + mdclog_write(MDCLOG_ERR, "Error :: %s, %d : Unknown RIC cause %d\n", __FILE__, __LINE__, cause); + return; + } + dout.get_not_admitted_list()->push_back(ActionResponse(id, cause, sub_cause)); + } + break; + } + + } + + //asn_fprint(stdout, &asn_DEF_E2AP_PDU, e2pdu); +} + + + diff --git a/src/xapp-asn/e2ap/subscription_response.hpp b/src/xapp-asn/e2ap/subscription_response.hpp new file mode 100644 index 0000000..28fad4e --- /dev/null +++ b/src/xapp-asn/e2ap/subscription_response.hpp @@ -0,0 +1,81 @@ +/* +================================================================================== + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== +*/ + +#pragma once + +#ifndef S_RESPONSE_ +#define S_RESPONSE_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "response_helper.hpp" + +#define NUM_SUBSCRIPTION_RESPONSE_IES 4 +#define NUM_SUBSCRIPTION_FAILURE_IES 3 +#define INITIAL_RESPONSE_LIST_SIZE 4 + +class subscription_response{ +public: + + subscription_response(void); + ~subscription_response(void); + + bool encode_e2ap_subscription_response(unsigned char *, size_t *, subscription_response_helper &, bool); + void get_fields(E2N_SuccessfulOutcome_t *, subscription_response_helper &); + void get_fields(E2N_UnsuccessfulOutcome_t *, subscription_response_helper &); + + std::string get_error(void) const{ + return error_string; + } + +private: + + void set_fields_success( subscription_response_helper &); + void set_fields_unsuccess( subscription_response_helper &); + + E2N_E2AP_PDU_t * e2ap_pdu_obj; + E2N_SuccessfulOutcome_t * successMsg; + E2N_UnsuccessfulOutcome_t * unsuccessMsg; + + + E2N_RICsubscriptionResponse_IEs_t *IE_array; + E2N_RICsubscriptionFailure_IEs_t *IE_Failure_array; + + + E2N_RICaction_Admitted_ItemIEs_t * ie_admitted_list; + E2N_RICaction_NotAdmitted_ItemIEs_t * ie_not_admitted_list; + unsigned int ie_admitted_list_size, ie_not_admitted_list_size; + + char errbuf[128]; + size_t errbuf_len = 128; + std::string error_string; +}; + + + + +#endif diff --git a/src/xapp-asn/e2sm/e2sm.cc b/src/xapp-asn/e2sm/e2sm.cc new file mode 100644 index 0000000..c476c83 --- /dev/null +++ b/src/xapp-asn/e2sm/e2sm.cc @@ -0,0 +1,660 @@ +/* + ================================================================================== + + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, softwares + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ================================================================================== +*/ + +/* Classes to handle E2 service model based on e2sm-gNB-X2-release-1-v040.asn */ + +#include "e2sm.hpp" + + + + //initialize + e2sm_event_trigger::e2sm_event_trigger(void){ + + memset(&gNodeB_ID, 0, sizeof(E2N_GlobalGNB_ID_t)); + + event_trigger = 0; + event_trigger = ( E2N_E2SM_gNB_X2_eventTriggerDefinition_t *)calloc(1, sizeof( E2N_E2SM_gNB_X2_eventTriggerDefinition_t)); + assert(event_trigger != 0); + + // allocate space for gNodeB id (used for encoding) + gNodeB_ID.gNB_ID.choice.gNB_ID.buf = 0; + gNodeB_ID.gNB_ID.choice.gNB_ID.buf = (uint8_t *)calloc(4, sizeof(uint8_t)); + assert(gNodeB_ID.gNB_ID.choice.gNB_ID.buf != 0); + + // allocate space for plmn identity (used for encoding) + gNodeB_ID.pLMN_Identity.buf = 0; + gNodeB_ID.pLMN_Identity.buf = (uint8_t *) calloc(4, sizeof(uint8_t)); + assert(gNodeB_ID.pLMN_Identity.buf != 0); + + ie_list = 0; + ie_list = ( struct E2N_InterfaceProtocolIE_Item *) calloc(INITIAL_LIST_SIZE, sizeof( struct E2N_InterfaceProtocolIE_Item)); + assert(ie_list != 0); + ie_list_size = INITIAL_LIST_SIZE; + + condition_list = 0; + condition_list = (E2N_E2SM_gNB_X2_eventTriggerDefinition::E2N_E2SM_gNB_X2_eventTriggerDefinition__interfaceProtocolIE_List *) calloc(1, sizeof(E2N_E2SM_gNB_X2_eventTriggerDefinition::E2N_E2SM_gNB_X2_eventTriggerDefinition__interfaceProtocolIE_List )); + assert(condition_list != 0); + + + + }; + +e2sm_event_trigger::~e2sm_event_trigger(void){ + + mdclog_write(MDCLOG_DEBUG, "Freeing event trigger object memory"); + for(int i = 0; i < condition_list->list.size; i++){ + condition_list->list.array[i] = 0; + } + + if (condition_list->list.size > 0){ + free(condition_list->list.array); + condition_list->list.array = 0; + condition_list->list.size = 0; + condition_list->list.count = 0; + } + + free(condition_list); + condition_list = 0; + + free(gNodeB_ID.gNB_ID.choice.gNB_ID.buf); + gNodeB_ID.gNB_ID.choice.gNB_ID.buf = 0; + + free(gNodeB_ID.pLMN_Identity.buf); + gNodeB_ID.pLMN_Identity.buf = 0; + + free(ie_list); + ie_list = 0; + + event_trigger->interface_ID.choice.global_gNB_ID = 0; + event_trigger->interfaceProtocolIE_List = 0; + + ASN_STRUCT_FREE(asn_DEF_E2N_E2SM_gNB_X2_eventTriggerDefinition, event_trigger); + mdclog_write(MDCLOG_DEBUG, "Freed event trigger object memory"); + + +}; + +bool e2sm_event_trigger::encode_event_trigger(unsigned char *buf, size_t *size, e2sm_event_trigger_helper &helper){ + + bool res; + res = set_fields(event_trigger, helper); + if (!res){ + return false; + } + + int ret_constr = asn_check_constraints(&asn_DEF_E2N_E2SM_gNB_X2_eventTriggerDefinition, event_trigger, errbuf, &errbuf_len); + if(ret_constr){ + error_string.assign(&errbuf[0], errbuf_len); + return false; + } + + //xer_fprint(stdout, &asn_DEF_E2N_E2SM_gNB_X2_eventTriggerDefinition, event_trigger); + + asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2SM_gNB_X2_eventTriggerDefinition, event_trigger, buf, *size); + + if(retval.encoded == -1){ + error_string.assign(strerror(errno)); + return false; + } + else if (retval.encoded > *size){ + std::stringstream ss; + ss <<"Error encoding event trigger definition. Reason = encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl; + error_string = ss.str(); + return false; + } + else{ + *size = retval.encoded; + } + + return true; +} + + +bool e2sm_event_trigger::set_fields(E2N_E2SM_gNB_X2_eventTriggerDefinition_t * ref_event_trigger, e2sm_event_trigger_helper & helper){ + if(ref_event_trigger == 0){ + error_string = "Invalid reference for Event Trigger Definition set fields"; + return false; + } + + // set the message type + ref_event_trigger->interfaceMessageType.procedureCode = helper.procedure_code; + ref_event_trigger->interfaceMessageType.typeOfMessage = helper.message_type; + + ref_event_trigger->interfaceDirection = helper.interface_direction; + ref_event_trigger->interface_ID.present = E2N_Interface_ID_PR_global_gNB_ID; + + ref_event_trigger->interface_ID.choice.global_gNB_ID = &gNodeB_ID; + + // to do : need to put correct code here for upding plmn id and gNodeB + // for now just place holders : + //================================================================ + memcpy(gNodeB_ID.pLMN_Identity.buf, helper.plmn_id.c_str(), 3); + gNodeB_ID.pLMN_Identity.size = 3; + + memcpy(gNodeB_ID.gNB_ID.choice.gNB_ID.buf, helper.egNB_id.c_str(), 3); + gNodeB_ID.gNB_ID.choice.gNB_ID.size = 3; + + // we only do global gNodeB id for now, not eNodeB + gNodeB_ID.gNB_ID.present = E2N_GNB_ID_PR_gNB_ID; + //================================================================ + + + // Add in any requested IE items + std::vector * ref_ie_array = helper.get_list(); + + if (ref_ie_array->size() == 0){ + ref_event_trigger->interfaceProtocolIE_List = 0; + + } + else{ + ref_event_trigger->interfaceProtocolIE_List = condition_list; + + //resize memory ? + if(ref_ie_array->size() > ie_list_size){ + ie_list_size = 2 * ref_ie_array->size(); + free(ie_list); + ie_list = (struct E2N_InterfaceProtocolIE_Item *)calloc(ie_list_size, sizeof(struct E2N_InterfaceProtocolIE_Item)); + assert(ie_list != 0); + } + + // reset the count so that adds start from the beginning + ref_event_trigger->interfaceProtocolIE_List->list.count = 0; + + for(unsigned int i = 0; i < ref_ie_array->size(); i++){ + + ie_list[i].interfaceProtocolIE_ID = (*ref_ie_array)[i].interface_id; + ie_list[i].interfaceProtocolIE_Test = (*ref_ie_array)[i].test; + + //switch(ie_list[i].interfaceProtocolIE_Value.present){ + switch((*ref_ie_array)[i].val_type){ + + case (E2N_InterfaceProtocolIE_Value_PR_valueInt): + ie_list[i].interfaceProtocolIE_Value.present = E2N_InterfaceProtocolIE_Value_PR_valueInt; + ie_list[i].interfaceProtocolIE_Value.choice.valueInt = (*ref_ie_array)[i].value_n; + break; + + case (E2N_InterfaceProtocolIE_Value_PR_valueEnum): + ie_list[i].interfaceProtocolIE_Value.present = E2N_InterfaceProtocolIE_Value_PR_valueEnum; + ie_list[i].interfaceProtocolIE_Value.choice.valueEnum = (*ref_ie_array)[i].value_n; + break; + + case (E2N_InterfaceProtocolIE_Value_PR_valueBool): + ie_list[i].interfaceProtocolIE_Value.present = E2N_InterfaceProtocolIE_Value_PR_valueBool; + ie_list[i].interfaceProtocolIE_Value.choice.valueBool = (*ref_ie_array)[i].value_n; + break; + + case (E2N_InterfaceProtocolIE_Value_PR_valueBitS): + ie_list[i].interfaceProtocolIE_Value.present = E2N_InterfaceProtocolIE_Value_PR_valueBitS; + ie_list[i].interfaceProtocolIE_Value.choice.valueBitS.buf = (uint8_t *)(*ref_ie_array)[i].value_s.c_str(); + ie_list[i].interfaceProtocolIE_Value.choice.valueBitS.size = (*ref_ie_array)[i].value_s.length(); + break; + + case (E2N_InterfaceProtocolIE_Value_PR_valueOctS): + ie_list[i].interfaceProtocolIE_Value.present = E2N_InterfaceProtocolIE_Value_PR_valueOctS; + ie_list[i].interfaceProtocolIE_Value.choice.valueOctS.buf = (uint8_t *)(*ref_ie_array)[i].value_s.c_str(); + ie_list[i].interfaceProtocolIE_Value.choice.valueOctS.size = (*ref_ie_array)[i].value_s.length(); + break; + + default: + { + std::stringstream ss; + ss <<"Error ! " << __FILE__ << "," << __LINE__ << " illegal enum " << (*ref_ie_array)[i].val_type << " for interface Protocol IE value" << std::endl; + std::string error_string = ss.str(); + return false; + } + } + + ASN_SEQUENCE_ADD(ref_event_trigger->interfaceProtocolIE_List, &ie_list[i]); + } + } + + return true; +}; + + +bool e2sm_event_trigger::get_fields(E2N_E2SM_gNB_X2_eventTriggerDefinition_t * ref_event_trigger, e2sm_event_trigger_helper & helper){ + + if (ref_event_trigger == 0){ + error_string = "Invalid reference for Event Trigger definition get fields"; + return false; + } + + helper.procedure_code = ref_event_trigger->interfaceMessageType.procedureCode; + helper.message_type = ref_event_trigger->interfaceMessageType.typeOfMessage; + helper.interface_direction = ref_event_trigger->interfaceDirection; + + 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); + 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); + for(int i = 0; i < ref_event_trigger->interfaceProtocolIE_List->list.count; i++){ + struct E2N_InterfaceProtocolIE_Item * ie_item = ref_event_trigger->interfaceProtocolIE_List->list.array[i]; + switch(ie_item->interfaceProtocolIE_Value.present){ + case (E2N_InterfaceProtocolIE_Value_PR_valueInt): + helper.add_protocol_ie_item(ie_item->interfaceProtocolIE_ID, ie_item->interfaceProtocolIE_Test, ie_item->interfaceProtocolIE_Value.present, ie_item->interfaceProtocolIE_Value.choice.valueInt); + break; + case (E2N_InterfaceProtocolIE_Value_PR_valueEnum): + helper.add_protocol_ie_item(ie_item->interfaceProtocolIE_ID, ie_item->interfaceProtocolIE_Test, ie_item->interfaceProtocolIE_Value.present, ie_item->interfaceProtocolIE_Value.choice.valueEnum); + break; + case (E2N_InterfaceProtocolIE_Value_PR_valueBool): + helper.add_protocol_ie_item(ie_item->interfaceProtocolIE_ID, ie_item->interfaceProtocolIE_Test, ie_item->interfaceProtocolIE_Value.present, ie_item->interfaceProtocolIE_Value.choice.valueBool); + break; + case (E2N_InterfaceProtocolIE_Value_PR_valueBitS): + helper.add_protocol_ie_item(ie_item->interfaceProtocolIE_ID, ie_item->interfaceProtocolIE_Test, ie_item->interfaceProtocolIE_Value.present, std::string((const char *)ie_item->interfaceProtocolIE_Value.choice.valueBitS.buf,ie_item->interfaceProtocolIE_Value.choice.valueBitS.size) ); + break; + case (E2N_InterfaceProtocolIE_Value_PR_valueOctS): + helper.add_protocol_ie_item(ie_item->interfaceProtocolIE_ID, ie_item->interfaceProtocolIE_Test, ie_item->interfaceProtocolIE_Value.present, std::string((const char *)ie_item->interfaceProtocolIE_Value.choice.valueOctS.buf,ie_item->interfaceProtocolIE_Value.choice.valueOctS.size) ); + break; + default: + mdclog_write(MDCLOG_ERR, "Error : %s, %d: Unkown interface protocol IE type %d in event trigger definition\n", __FILE__, __LINE__, ie_item->interfaceProtocolIE_Value.present); + return false; + } + } + + return true; +}; + + + + +// initialize +e2sm_indication::e2sm_indication(void) { + + memset(&gNodeB_ID, 0, sizeof(E2N_GlobalGNB_ID_t)); + + // allocate space for gNodeB id (used for encoding) + gNodeB_ID.gNB_ID.choice.gNB_ID.buf = (uint8_t *)calloc(4, sizeof(uint8_t)); + assert(gNodeB_ID.gNB_ID.choice.gNB_ID.buf != 0); + + // allocate space for plmn identity (used for encoding) + gNodeB_ID.pLMN_Identity.buf = (uint8_t *) calloc(4, sizeof(uint8_t)); + assert(gNodeB_ID.pLMN_Identity.buf != 0); + + header = 0; + header = (E2N_E2SM_gNB_X2_indicationHeader_t *)calloc(1, sizeof(E2N_E2SM_gNB_X2_indicationHeader_t)); + assert(header != 0); + + message = 0; + message = (E2N_E2SM_gNB_X2_indicationMessage_t *)calloc(1, sizeof(E2N_E2SM_gNB_X2_indicationMessage_t)); + assert(message != 0); +} + +e2sm_indication::~e2sm_indication(void){ + mdclog_write(MDCLOG_DEBUG, "Freeing E2N_E2SM Indication object memory"); + + free(gNodeB_ID.gNB_ID.choice.gNB_ID.buf); + free(gNodeB_ID.pLMN_Identity.buf); + + header->interface_ID.choice.global_gNB_ID = 0; + + ASN_STRUCT_FREE(asn_DEF_E2N_E2SM_gNB_X2_indicationHeader, header); + + message->interfaceMessage.buf = 0; + message->interfaceMessage.size = 0; + + ASN_STRUCT_FREE(asn_DEF_E2N_E2SM_gNB_X2_indicationMessage, message); + mdclog_write(MDCLOG_DEBUG, "Freed E2SM Indication object memory"); + +} + + + +bool e2sm_indication::encode_indication_header(unsigned char *buf, size_t *size, e2sm_header_helper &helper){ + + bool res; + res = set_header_fields(header, helper); + if (!res){ + return false; + } + + int ret_constr = asn_check_constraints(&asn_DEF_E2N_E2SM_gNB_X2_indicationHeader, header, errbuf, &errbuf_len); + if(ret_constr){ + error_string.assign(&errbuf[0], errbuf_len); + error_string = "E2SM Indication Header Constraint failed : " + error_string; + + return false; + } + + asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2SM_gNB_X2_indicationHeader, header, buf, *size); + + if(retval.encoded == -1){ + error_string.assign(strerror(errno)); + error_string = "Error encoding E2N_E2SM Indication Header. Reason = " + error_string; + return false; + } + else if (retval.encoded > *size){ + std::stringstream ss; + ss <<"Error encoding E2SM Indication Header . Reason = encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl; + error_string = ss.str(); + return false; + } + else{ + *size = retval.encoded; + } + + return true; +} + + +bool e2sm_indication::encode_indication_message(unsigned char *buf, size_t *size, e2sm_message_helper &helper){ + + set_message_fields(message, helper); + + int ret_constr = asn_check_constraints(&asn_DEF_E2N_E2SM_gNB_X2_indicationMessage, message, errbuf, &errbuf_len); + if(ret_constr){ + error_string.assign(&errbuf[0], errbuf_len); + error_string = "E2SM Indication Message Constraint failed : " + error_string; + return false; + } + + asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2SM_gNB_X2_indicationMessage, message, buf, *size); + if(retval.encoded == -1){ + error_string.assign(strerror(errno)); + error_string = "Error encoding E2SM Indication Header. Reason = " + error_string; + return false; + } + else if (retval.encoded > *size){ + std::stringstream ss; + ss <<"Error encoding E2N_E2SM Indication Message . Reason = encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl; + error_string = ss.str(); + + return false; + } + else{ + *size = retval.encoded; + } + + return true; +} + + + +// Used when generating an indication header +bool e2sm_indication::set_header_fields(E2N_E2SM_gNB_X2_indicationHeader_t *header, e2sm_header_helper &helper){ + + if (header == 0){ + error_string = "Invalid reference for E2SM Indication Header set fields"; + return false; + } + + + header->interfaceDirection = helper.interface_direction; + header->interface_ID.present = E2N_Interface_ID_PR_global_gNB_ID; + header->interface_ID.choice.global_gNB_ID = &gNodeB_ID; + + + // to do : need to put correct code here for upding plmn id and gNodeB + // for now just place holders : + memcpy(gNodeB_ID.pLMN_Identity.buf, helper.plmn_id.c_str(), 3); + gNodeB_ID.pLMN_Identity.size = 3; + + memcpy(gNodeB_ID.gNB_ID.choice.gNB_ID.buf, helper.egNB_id.c_str(), 3); + gNodeB_ID.gNB_ID.choice.gNB_ID.size = 3; + + // we only do global gNodeB id for now, not eNodeB + gNodeB_ID.gNB_ID.present = E2N_GNB_ID_PR_gNB_ID; + + return true; + +}; + + +// used when decoding an indication header +bool e2sm_indication::get_header_fields(E2N_E2SM_gNB_X2_indicationHeader_t *header, e2sm_header_helper &helper){ + + if (header == 0){ + error_string = "Invalid reference for E2SM Indication header get fields"; + return false; + } + + helper.interface_direction = header->interfaceDirection; + 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); + 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); + + // to do : add code to decipher plmn and global gnodeb from ints (since that is likely the convention for packing) + + return true; +} + + + +// Used when generating an indication message +bool e2sm_indication::set_message_fields(E2N_E2SM_gNB_X2_indicationMessage_t *interface_message, e2sm_message_helper &helper){ + + if(interface_message == 0){ + error_string = "Invalid reference for E2SM Indication Message set fields"; + return false; + } + + // interface-message is an octet string. just point it to the buffer + interface_message->interfaceMessage.buf = &(helper.x2ap_pdu[0]); + interface_message->interfaceMessage.size = helper.x2ap_pdu_size; + + return true; + +}; + +// used when decoding an indication message +bool e2sm_indication::get_message_fields( E2N_E2SM_gNB_X2_indicationMessage_t *interface_message, e2sm_message_helper &helper){ + + + if(interface_message == 0){ + error_string = "Invalid reference for E2SM Indication Message get fields"; + return false; + } + + // interface message is an octet string + helper.x2ap_pdu = interface_message->interfaceMessage.buf;; + helper.x2ap_pdu_size = interface_message->interfaceMessage.size; + + return true; + +} + + + +// initialize +e2sm_control::e2sm_control(void) { + + memset(&gNodeB_ID, 0, sizeof(E2N_GlobalGNB_ID_t)); + + // allocate space for gNodeB id (used for encoding) + gNodeB_ID.gNB_ID.choice.gNB_ID.buf = (uint8_t *)calloc(4, sizeof(uint8_t)); + assert(gNodeB_ID.gNB_ID.choice.gNB_ID.buf != 0); + + // allocate space for plmn identity (used for encoding) + gNodeB_ID.pLMN_Identity.buf = (uint8_t *) calloc(4, sizeof(uint8_t)); + assert(gNodeB_ID.pLMN_Identity.buf != 0); + + header = 0; + header = (E2N_E2SM_gNB_X2_controlHeader_t *)calloc(1, sizeof(E2N_E2SM_gNB_X2_controlHeader_t)); + assert(header != 0); + + message = 0; + message = (E2N_E2SM_gNB_X2_controlMessage_t *)calloc(1, sizeof(E2N_E2SM_gNB_X2_controlMessage_t)); + assert(message != 0); +} + +e2sm_control::~e2sm_control(void){ + mdclog_write(MDCLOG_DEBUG, "Freeing E2SM Control object memory"); + + free(gNodeB_ID.gNB_ID.choice.gNB_ID.buf); + free(gNodeB_ID.pLMN_Identity.buf); + header->interface_ID.choice.global_gNB_ID = 0; + ASN_STRUCT_FREE(asn_DEF_E2N_E2SM_gNB_X2_controlHeader, header); + + message->interfaceMessage.buf = 0; + ASN_STRUCT_FREE(asn_DEF_E2N_E2SM_gNB_X2_controlMessage, message); + + mdclog_write(MDCLOG_DEBUG, "Freed E2SM Control object memory"); + +} + + + +bool e2sm_control::encode_control_header(unsigned char *buf, size_t *size, e2sm_header_helper &helper){ + + bool res; + res = set_header_fields(header, helper); + if (!res){ + return false; + } + + int ret_constr = asn_check_constraints(&asn_DEF_E2N_E2SM_gNB_X2_controlHeader, header, errbuf, &errbuf_len); + if(ret_constr){ + error_string.assign(&errbuf[0], errbuf_len); + error_string = "E2SM Control Header Constraint failed : " + error_string; + + return false; + } + + asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2SM_gNB_X2_controlHeader, header, buf, *size); + + if(retval.encoded == -1){ + error_string.assign(strerror(errno)); + error_string = "Error encoding E2SM Control Header. Reason = " + error_string; + return false; + } + else if (retval.encoded > *size){ + std::stringstream ss; + ss <<"Error encoding E2N_E2SM Control Header . Reason = encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl; + error_string = ss.str(); + return false; + } + else{ + *size = retval.encoded; + } + + return true; +} + + +bool e2sm_control::encode_control_message(unsigned char *buf, size_t *size, e2sm_message_helper &helper){ + + set_message_fields(message, helper); + + int ret_constr = asn_check_constraints(&asn_DEF_E2N_E2SM_gNB_X2_controlMessage, message, errbuf, &errbuf_len); + if(ret_constr){ + error_string.assign(&errbuf[0], errbuf_len); + error_string = "E2SM Control Message Constraint failed : " + error_string; + return false; + } + + asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2SM_gNB_X2_controlMessage, message, buf, *size); + if(retval.encoded == -1){ + error_string.assign(strerror(errno)); + error_string = "Error encoding E2SM Control Message. Reason = " + error_string; + return false; + } + else if (retval.encoded > *size){ + std::stringstream ss; + ss <<"Error encoding E2SM Control Message . Reason = encoded pdu size " << retval.encoded << " exceeds buffer size " << *size << std::endl; + error_string = ss.str(); + + return false; + } + else{ + *size = retval.encoded; + } + + return true; +} + + + +// Used when generating an indication header +bool e2sm_control::set_header_fields(E2N_E2SM_gNB_X2_controlHeader_t *header, e2sm_header_helper &helper){ + + if (header == 0){ + error_string = "Invalid reference for E2SM Control Header set fields"; + return false; + } + + + header->interfaceDirection = helper.interface_direction; + header->interface_ID.present = E2N_Interface_ID_PR_global_gNB_ID; + header->interface_ID.choice.global_gNB_ID = &gNodeB_ID; + + + // to do : need to put correct code here for upding plmn id and gNodeB + // for now just place holders : + memcpy(gNodeB_ID.pLMN_Identity.buf, helper.plmn_id.c_str(), 3); + gNodeB_ID.pLMN_Identity.size = 3; + + memcpy(gNodeB_ID.gNB_ID.choice.gNB_ID.buf, helper.egNB_id.c_str(), 3); + gNodeB_ID.gNB_ID.choice.gNB_ID.size = 3; + + // we only do global gNodeB id for now, not eNodeB + gNodeB_ID.gNB_ID.present = E2N_GNB_ID_PR_gNB_ID; + + return true; + +}; + + +// used when decoding an indication header +bool e2sm_control::get_header_fields(E2N_E2SM_gNB_X2_controlHeader_t *header, e2sm_header_helper &helper){ + + if (header == 0){ + error_string = "Invalid reference for E2SM Control header get fields"; + return false; + } + + helper.interface_direction = header->interfaceDirection; + 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); + 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); + + // to do : add code to decipher plmn and global gnodeb from ints (since that is likely the convention for packing) + + return true; +} + + + +// Used when generating an indication message +bool e2sm_control::set_message_fields(E2N_E2SM_gNB_X2_controlMessage_t *interface_message, e2sm_message_helper &helper){ + + if(interface_message == 0){ + error_string = "Invalid reference for E2SM Control Message set fields"; + return false; + } + + // interface-message is an octet string. just point it to the buffer + interface_message->interfaceMessage.buf = &(helper.x2ap_pdu[0]); + interface_message->interfaceMessage.size = helper.x2ap_pdu_size; + + return true; + +}; + +// used when decoding an indication message +bool e2sm_control::get_message_fields( E2N_E2SM_gNB_X2_controlMessage_t *interface_message, e2sm_message_helper &helper){ + + + if(interface_message == 0){ + error_string = "Invalid reference for E2SM Control Message get fields"; + return false; + } + + // interface message is an octet string + helper.x2ap_pdu = interface_message->interfaceMessage.buf;; + helper.x2ap_pdu_size = interface_message->interfaceMessage.size; + + return true; + +} + diff --git a/src/xapp-asn/e2sm/e2sm.hpp b/src/xapp-asn/e2sm/e2sm.hpp new file mode 100644 index 0000000..c0877b4 --- /dev/null +++ b/src/xapp-asn/e2sm/e2sm.hpp @@ -0,0 +1,145 @@ +/* +================================================================================== + + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== +*/ + +/* Classes to handle E2 service model based on e2sm-gNB-X2-release-1-v040.asn */ + +#ifndef E2SM_ +#define E2SM_ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#define INITIAL_LIST_SIZE 4 + + + + +/* builder class for E2SM event trigger definition */ + +class e2sm_event_trigger { +public: + e2sm_event_trigger(void); + ~e2sm_event_trigger(void); + + bool set_fields(E2N_E2SM_gNB_X2_eventTriggerDefinition_t *, e2sm_event_trigger_helper &); + bool get_fields(E2N_E2SM_gNB_X2_eventTriggerDefinition_t *, e2sm_event_trigger_helper &); + bool encode_event_trigger(unsigned char *, size_t *, e2sm_event_trigger_helper &); + + std::string get_error (void) const {return error_string ;}; + +private: + + E2N_E2SM_gNB_X2_eventTriggerDefinition_t * event_trigger; // used for encoding + E2N_GlobalGNB_ID_t gNodeB_ID; + struct E2N_InterfaceProtocolIE_Item * ie_list; + unsigned int ie_list_size; + + //std::vector ie_list; + E2N_E2SM_gNB_X2_eventTriggerDefinition::E2N_E2SM_gNB_X2_eventTriggerDefinition__interfaceProtocolIE_List *condition_list; + + char errbuf[128]; + size_t errbuf_len; + std::string error_string; +}; + + +/* builder class for E2SM indication using ASN1c */ + +class e2sm_indication { +public: + + e2sm_indication(void); + ~e2sm_indication(void); + + E2N_E2SM_gNB_X2_indicationHeader_t * get_header(void); + E2N_E2SM_gNB_X2_indicationMessage_t * get_message(void); + + bool set_header_fields(E2N_E2SM_gNB_X2_indicationHeader_t *, e2sm_header_helper &); + bool get_header_fields(E2N_E2SM_gNB_X2_indicationHeader_t *, e2sm_header_helper &); + + bool set_message_fields(E2N_E2SM_gNB_X2_indicationMessage_t *, e2sm_message_helper &); + bool get_message_fields(E2N_E2SM_gNB_X2_indicationMessage_t *, e2sm_message_helper &); + + bool encode_indication_header(unsigned char * , size_t * , e2sm_header_helper &); + bool encode_indication_message(unsigned char *, size_t *, e2sm_message_helper &); + std::string get_error (void) const {return error_string ; }; + +private: + + E2N_E2SM_gNB_X2_indicationHeader_t *header; // used for encoding + E2N_E2SM_gNB_X2_indicationMessage_t *message; // used for encoding + + char errbuf[128]; + size_t errbuf_len; + E2N_GlobalGNB_ID_t gNodeB_ID; + std::string error_string; + + +}; + +/* builder class for E2SM control using ASN1c */ + +class e2sm_control { +public: + + e2sm_control(void); + ~e2sm_control(void); + + E2N_E2SM_gNB_X2_controlHeader_t * get_header(void); + E2N_E2SM_gNB_X2_controlMessage_t * get_message(void); + + bool set_header_fields(E2N_E2SM_gNB_X2_controlHeader_t *, e2sm_header_helper &); + bool get_header_fields(E2N_E2SM_gNB_X2_controlHeader_t *, e2sm_header_helper &); + + bool set_message_fields(E2N_E2SM_gNB_X2_controlMessage_t *, e2sm_message_helper &); + bool get_message_fields(E2N_E2SM_gNB_X2_controlMessage_t *, e2sm_message_helper &); + + bool encode_control_header(unsigned char * , size_t * , e2sm_header_helper &); + bool encode_control_message(unsigned char *, size_t *, e2sm_message_helper &); + std::string get_error (void) const {return error_string ; }; + +private: + + E2N_E2SM_gNB_X2_controlHeader_t *header; // used for encoding + E2N_E2SM_gNB_X2_controlMessage_t *message; // used for encoding + + char errbuf[128]; + size_t errbuf_len; + E2N_GlobalGNB_ID_t gNodeB_ID; + std::string error_string; + + +}; + +#endif diff --git a/src/xapp-asn/e2sm/e2sm_helpers.hpp b/src/xapp-asn/e2sm/e2sm_helpers.hpp new file mode 100644 index 0000000..ae7a481 --- /dev/null +++ b/src/xapp-asn/e2sm/e2sm_helpers.hpp @@ -0,0 +1,113 @@ +/* +================================================================================== + + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== + */ + +#ifndef E2SM_HELPER_ +#define E2SM_HELPER_ + +#include +#include +#include +#include + + /* information holder for E2SM indication header */ +typedef struct e2sm_header_helper e2sm_header_helper; +struct e2sm_header_helper { + int egNB_id_type; + + std::string egNB_id; + std::string plmn_id; + + long int interface_direction; + unsigned char* timestamp; +}; + +/* information holder for E2SM indication message */ +typedef struct e2sm_message_helper e2sm_message_helper; +struct e2sm_message_helper { + unsigned char * x2ap_pdu; + size_t x2ap_pdu_size; +}; + + +/* information holder for E2SM Action Trigger Definition */ +struct Item +{ + Item(long int id, long int test, long int val_type, int value):interface_id(id), test(test), val_type(val_type), value_n(value){}; + Item(long int id, long int test, long int val_type, std::string value):interface_id(id), test(test), val_type(val_type), value_s(value){}; + + long int interface_id; + long int test; + long int val_type; + long int value_n; + std::string value_s; + +}; + +typedef struct e2sm_event_trigger_helper e2sm_event_trigger_helper; +struct e2sm_event_trigger_helper { + + int egNB_id_type; + std::string egNB_id; + std::string plmn_id; + + long int interface_direction; + long int procedure_code; + + long int message_type; + + + std::vector * get_list(void){ return &protocol_ie_list; }; + void add_protocol_ie_item(long int id, long int test , unsigned int val_type, long int value ){ + // into list + protocol_ie_list.emplace_back(id, test, val_type, value); + }; + + void add_protocol_ie_item(long int id, long int test, unsigned int val_type, std::string value){ + // into list + protocol_ie_list.emplace_back(id, test, val_type, value); + }; + + void clear(void){ + protocol_ie_list.clear(); + } + + std::string get_string(void) const { + std::stringstream ss; + ss << "egNB_ID_type = " << egNB_id_type << std::endl; + ss << "PLMN Id = " << plmn_id << std::endl; + ss << "Procedure Code = " << procedure_code << std::endl; + ss << "Message Type = " << message_type << std::endl; + + std::string info; + info = ss.str(); + return info; + } + + + +private: + + std::vector protocol_ie_list; + +}; + + + + +#endif diff --git a/src/xapp-mgmt/msgs_proc.cc b/src/xapp-mgmt/msgs_proc.cc new file mode 100644 index 0000000..d20ef76 --- /dev/null +++ b/src/xapp-mgmt/msgs_proc.cc @@ -0,0 +1,282 @@ +/* +================================================================================== + + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== +*/ +/* + * msgs_proc.cc + * Created on: 2019 + * Author: Ashwin Shridharan, Shraboni Jana + */ + + +#include "msgs_proc.hpp" + +//sending messages are encoded. +bool XappMsgHandler::encode_subscription_request(unsigned char* buffer, size_t *buf_len) +{ + int request_id = 2; // will be over-written by subscription handler + int req_seq = 1; + int function_id = 0; + int action_id = 1; + int action_type = 0; + int subsequent_action = 0; // continue + int time_to_wait = 4; // 10ms + + int message_type = 1; + int procedure_code = 27; + std::string egnb_id = "Testgnb"; + std::string plmn_id = "Testplmn"; + + unsigned char event_buf[128]; + size_t event_buf_len = 128; + bool res; + + + e2sm_event_trigger_helper trigger_data; + e2sm_event_trigger event_trigger; + + trigger_data.egNB_id = egnb_id; + trigger_data.plmn_id = plmn_id; + trigger_data.egNB_id_type = 2; + trigger_data.interface_direction = 1; + trigger_data.procedure_code = procedure_code; + trigger_data.message_type = message_type; + //====================================================== + + // Encode the event trigger definition + res = event_trigger.encode_event_trigger(&event_buf[0], &event_buf_len, trigger_data); + if (!res){ + mdclog_write(MDCLOG_ERR, "Error : %s, %d: Could not encode subscription Request. Reason = %s\n", __FILE__, __LINE__, event_trigger.get_error().c_str()); + return false; + } + mdclog_write(MDCLOG_INFO, "Encoded event trigger definition into PDU of size %lu bytes\n", event_buf_len); + + + // create the subscription + subscription_helper subscr_req; + subscription_request e2ap_sub_req; + + subscr_req.clear(); + subscr_req.set_request(request_id, req_seq); + subscr_req.set_function_id(function_id); + subscr_req.add_action(action_id, action_type, "", subsequent_action, time_to_wait); + + subscr_req.set_event_def(&event_buf[0], event_buf_len); + // generate the request pdu + res = e2ap_sub_req.encode_e2ap_subscription(&buffer[0], buf_len, subscr_req); + if(! res){ + mdclog_write(MDCLOG_ERR, "%s, %d: Error encoding subscription pdu. Reason = ", __FILE__, __LINE__); + return false; + } + return true; +} +bool XappMsgHandler::encode_subscription_delete_request(unsigned char* buffer, size_t *buf_len){ + + subscription_helper sub_helper; + sub_helper.set_request(0, 0); // requirement of subscription manager ... ? + sub_helper.set_function_id(0); + + subscription_delete e2ap_sub_req_del; + + // generate the delete request pdu + + bool res = e2ap_sub_req_del.encode_e2ap_subscription(&buffer[0], buf_len, sub_helper); + if(! res){ + mdclog_write(MDCLOG_ERR, "%s, %d: Error encoding subscription delete request pdu. Reason = %s", __FILE__, __LINE__, e2ap_sub_req_del.get_error().c_str()); + return false; + } + + return true; + +} + +bool XappMsgHandler::decode_subscription_response(unsigned char* data_buf, size_t data_size){ + + bool res = true; + E2N_E2AP_PDU_t *e2pdu = 0; + + asn_dec_rval_t rval; + + ASN_STRUCT_RESET(asn_DEF_E2N_E2AP_PDU, e2pdu); + + rval = asn_decode(0,ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2AP_PDU, (void**)&e2pdu, data_buf, data_size); + switch(rval.code) + { + case RC_OK: + //Put in Subscription Response Object. + asn_fprint(stdout, &asn_DEF_E2N_E2AP_PDU, e2pdu); + + break; + case RC_WMORE: + mdclog_write(MDCLOG_ERR, "RC_WMORE"); + res = false; + break; + case RC_FAIL: + mdclog_write(MDCLOG_ERR, "RC_FAIL"); + res = false; + break; + default: + break; + } + ASN_STRUCT_FREE(asn_DEF_E2N_E2AP_PDU, e2pdu); + return res; + +} +bool XappMsgHandler::decode_subscription_delete_response(unsigned char* data_buf, size_t data_size){ + + bool res = true; + E2N_E2AP_PDU_t *e2pdu = 0; + + asn_dec_rval_t rval; + + ASN_STRUCT_RESET(asn_DEF_E2N_E2AP_PDU, e2pdu); + + rval = asn_decode(0,ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2AP_PDU, (void**)&e2pdu, data_buf, data_size); + switch(rval.code) + { + case RC_OK: + //Put in Subscription Delete Response Object. + asn_fprint(stdout, &asn_DEF_E2N_E2AP_PDU, e2pdu); + break; + case RC_WMORE: + mdclog_write(MDCLOG_ERR, "RC_WMORE"); + res = false; + break; + case RC_FAIL: + mdclog_write(MDCLOG_ERR, "RC_FAIL"); + res = false; + break; + default: + break; + } + ASN_STRUCT_FREE(asn_DEF_E2N_E2AP_PDU, e2pdu); + return res; + +} +bool XappMsgHandler::decode_subscription_response_failure(unsigned char* data_buf, size_t data_size){ + + bool res = true; + E2N_E2AP_PDU_t *e2pdu = 0; + + asn_dec_rval_t rval; + + ASN_STRUCT_RESET(asn_DEF_E2N_E2AP_PDU, e2pdu); + + rval = asn_decode(0,ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2AP_PDU, (void**)&e2pdu, data_buf, data_size); + switch(rval.code) + { + case RC_OK: + //Extract Subscription Response Failure. + asn_fprint(stdout, &asn_DEF_E2N_E2AP_PDU, e2pdu); + break; + case RC_WMORE: + mdclog_write(MDCLOG_ERR, "RC_WMORE"); + res = false; + break; + case RC_FAIL: + mdclog_write(MDCLOG_ERR, "RC_FAIL"); + res = false; + break; + default: + break; + } + ASN_STRUCT_FREE(asn_DEF_E2N_E2AP_PDU, e2pdu); + return res; + +} + +bool XappMsgHandler::decode_subscription_delete_response_failure(unsigned char* data_buf, size_t data_size){ + + bool res = true; + E2N_E2AP_PDU_t *e2pdu = 0; + + asn_dec_rval_t rval; + + ASN_STRUCT_RESET(asn_DEF_E2N_E2AP_PDU, e2pdu); + + rval = asn_decode(0,ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2AP_PDU, (void**)&e2pdu, data_buf, data_size); + switch(rval.code) + { + case RC_OK: + //Extract Subscription Delete Response Failure. + asn_fprint(stdout, &asn_DEF_E2N_E2AP_PDU, e2pdu); + break; + case RC_WMORE: + mdclog_write(MDCLOG_ERR, "RC_WMORE"); + res = false; + break; + case RC_FAIL: + mdclog_write(MDCLOG_ERR, "RC_FAIL"); + res = false; + break; + default: + break; + } + ASN_STRUCT_FREE(asn_DEF_E2N_E2AP_PDU, e2pdu); + return res; + +} + +//For processing received messages. +rmr_mbuf_t * XappMsgHandler::operator()(rmr_mbuf_t *message){ + + if (message->len > MAX_RMR_RECV_SIZE){ + mdclog_write(MDCLOG_ERR, "Error : %s, %d, RMR message larger than %d. Ignoring ...", __FILE__, __LINE__, MAX_RMR_RECV_SIZE); + return message; + } + + switch(message->mtype){ + //need to fix the health check. + case (RIC_HEALTH_CHECK_REQ): + message->mtype = RIC_HEALTH_CHECK_RESP; // if we're here we are running and all is ok + message->sub_id = -1; + break; + + case (RIC_SUB_RESP): + //Received Subscription Response Message + decode_subscription_response(message->payload,message->len); + message = NULL; + break; + + case (RIC_SUB_DEL_RESP): + decode_subscription_delete_response(message->payload,message->len); + message = NULL; + break; + + case (RIC_SUB_FAILURE): + decode_subscription_response_failure(message->payload, message->len); + message = NULL; + break; + + case (RIC_SUB_DEL_FAILURE): + decode_subscription_delete_response_failure(message->payload,message->len); + message = NULL; + break; + // case A1_POLICY_REQ: + // break; + + + default: + mdclog_write(MDCLOG_ERR, "Error :: Unknown message type %d received from RMR", message->mtype); + + } + + return message; + +}; + + diff --git a/src/xapp-mgmt/msgs_proc.hpp b/src/xapp-mgmt/msgs_proc.hpp new file mode 100644 index 0000000..ec15933 --- /dev/null +++ b/src/xapp-mgmt/msgs_proc.hpp @@ -0,0 +1,68 @@ +/* +================================================================================== + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== +*/ +/* + * msgs_proc.hpp + * Created on: 2019 + * Author: Ashwin Shridharan, Shraboni Jana + */ +#pragma once + +#ifndef XAPP_MSG_XAPP_MSG_HPP_ +#define XAPP_MSG_XAPP_MSG_HPP_ + +#include +#include +#include +#include + + +#include +#include +#include +#include +#include "subscription_request.hpp" +#include "subscription_helper.hpp" +#include "e2sm.hpp" +#include +#include +#include + +#define MAX_RMR_RECV_SIZE 2<<15 + +class XappMsgHandler{ + +private: + unsigned char* message_buffer; + size_t* message_length; + +public: + rmr_mbuf_t * operator() (rmr_mbuf_t *); + + bool encode_subscription_request(unsigned char*, size_t* ); + bool encode_subscription_delete_request(unsigned char*, size_t* ); + + bool decode_subscription_response(unsigned char*, size_t ); + bool decode_subscription_delete_response(unsigned char*, size_t ); + bool decode_subscription_response_failure(unsigned char*, size_t ); + bool decode_subscription_delete_response_failure(unsigned char*, size_t ); + + +}; + + +#endif /* XAPP_MSG_XAPP_MSG_HPP_ */ diff --git a/src/xapp-mgmt/subs_mgmt.cc b/src/xapp-mgmt/subs_mgmt.cc new file mode 100644 index 0000000..af53220 --- /dev/null +++ b/src/xapp-mgmt/subs_mgmt.cc @@ -0,0 +1,358 @@ +/* +================================================================================== + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== +*/ +/* + * subs_mgmt.cc + * Created on: 2019 + * Author: Ashwin Shridharan, Shraboni Jana + */ +#include "subs_mgmt.hpp" + +#include + + +SubscriptionHandler::SubscriptionHandler(unsigned int timeout_seconds, unsigned int num_tries):_time_out(std::chrono::seconds(timeout_seconds)), _num_retries(num_tries){ + init(); +}; + +void SubscriptionHandler::init(void){ + + _data_lock = std::make_unique(); + _cv = std::make_unique(); + +} + +void SubscriptionHandler::clear(void){ + { + std::lock_guard lock(*(_data_lock).get()); + requests_table.clear(); + subscription_responses.clear(); + } + +}; + +size_t SubscriptionHandler::num_pending(void) const { + return requests_table.size(); +} + +size_t SubscriptionHandler::num_complete(void) const { + return subscription_responses.size(); +} + + +void SubscriptionHandler::set_timeout(unsigned int timeout_seconds){ + _time_out = std::chrono::seconds(timeout_seconds); +} + +void SubscriptionHandler::set_num_retries(unsigned int num_tries){ + _num_retries = num_tries; +}; + + + +bool SubscriptionHandler::add_request_entry(subscription_identifier id, int status){ + + // add entry in hash table if it does not exist + auto search = requests_table.find(id); + if(search != requests_table.end()){ + return false; + } + + requests_table[id] = status; + return true; + +}; + +bool SubscriptionHandler::set_request_status(subscription_identifier id, int status){ + + // change status of a request only if it exists. + auto search = requests_table.find(id); + if(search != requests_table.end()){ + requests_table[id] = status; + return true; + } + + return false; + +}; + + +bool SubscriptionHandler::delete_request_entry(subscription_identifier id){ + + auto search = requests_table.find(id); + if (search != requests_table.end()){ + requests_table.erase(search); + return true; + } + + return false; +}; + +bool SubscriptionHandler::add_subscription_entry(subscription_identifier id, subscription_response_helper &he){ + + auto search = subscription_responses.find(id); + if (search == subscription_responses.end()){ + subscription_responses[id] = he; + return true; + } + + return false; +} + + +bool SubscriptionHandler::delete_subscription_entry(subscription_identifier id){ + + auto search = subscription_responses.find(id); + if(search == subscription_responses.end()){ + return false; + } + else{ + subscription_responses.erase(search); + return true; + } + +} + +subscription_response_helper * const SubscriptionHandler::get_subscription(subscription_identifier id){ + auto search = subscription_responses.find(id); + if(search == subscription_responses.end()){ + return NULL; + } + else{ + return &(subscription_responses[id]); + } +}; + + +// Handles responses from RMR +void SubscriptionHandler::Response(int message_type, unsigned char *payload, int payload_length, const char * node_id){ + + bool res; + std::string node(node_id); + int type; + int procedureCode; + bool valid_response =false; + + E2N_E2AP_PDU_t * e2ap_recv; + asn_dec_rval_t retval; + + subscription_response sub_resp; + subscription_delete_response sub_del_resp; + + subscription_response_helper he_response; + + + e2ap_recv = 0; + retval = asn_decode(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2N_E2AP_PDU, (void**)&(e2ap_recv), payload, payload_length); + + if(retval.code != RC_OK){ + mdclog_write(MDCLOG_ERR, "%s, %d: Error decoding E2AP PDU of RMR type %d. Bytes decoded = %lu out of %d\n", __FILE__, __LINE__, message_type, retval.consumed, payload_length); + ASN_STRUCT_FREE(asn_DEF_E2N_E2AP_PDU, e2ap_recv); + return ; + } + + type = e2ap_recv->present; + mdclog_write(MDCLOG_INFO, "Received RMR message of type = %d", type); + + if(type == E2N_E2AP_PDU_PR_successfulOutcome){ + + procedureCode = e2ap_recv->choice.successfulOutcome->procedureCode; + mdclog_write(MDCLOG_INFO, "Received E2N_E2AP PDU successful outcome message with procedureCode = %d", procedureCode); + + if( procedureCode == E2N_ProcedureCode_id_ricSubscription){ + // subscription response + // decode the message + sub_resp.get_fields(e2ap_recv->choice.successfulOutcome, he_response); + { + std::lock_guard lock(*(_data_lock.get())); + // get the id + subscription_identifier id = std::make_tuple (node, he_response.get_request_id()); + + // get status of id + int req_status = get_request_status(id); + if (req_status == request_pending ){ + res = add_subscription_entry(id, he_response); + if(res) + set_request_status(id, request_success); + + else{ + set_request_status(id, request_duplicate); + mdclog_write(MDCLOG_ERR, "Error:: %s, %d: Request %s, %d seems to be a duplicate. Subscription already present in subscription table\n", __FILE__, __LINE__, std::get<0>(id).c_str(), std::get<1>(id)); + } + + valid_response = true; + } + else if (req_status > 0){ + // we don't change status of response since it was not in pending + // we simply fail + mdclog_write(MDCLOG_ERR, "Error:: %s, %d: Request %s,%d is not in request_pending state, is in State = %d\n", __FILE__, __LINE__, std::get<0>(id).c_str(), std::get<1>(id), req_status); + + } + else{ + mdclog_write(MDCLOG_ERR, "%s, %d: Could not find id %s, %d in request queue for subscription", __FILE__, __LINE__, std::get<0>(id).c_str(), std::get<1>(id)); + } + + } + + } + + else if( procedureCode == E2N_ProcedureCode_id_ricSubscriptionDelete){ + + res = sub_del_resp.get_fields(e2ap_recv->choice.successfulOutcome, he_response); + { + std::lock_guard lock(*(_data_lock.get())); + + // get the id + subscription_identifier id = std::make_tuple (node, he_response.get_request_id()); + + int req_status = get_request_status(id); + if (req_status == delete_request_pending ){ + // Remove the subscription from the table + res = delete_subscription_entry(id); + if(res){ + set_request_status(id, delete_request_success); + valid_response = true; + } + else{ + set_request_status(id, delete_request_failed); + mdclog_write(MDCLOG_ERR, "%s, %d: Error deleting subscription entry for %s, %d", __FILE__, __LINE__, std::get<0>(id).c_str(), std::get<1>(id)); + valid_response = true; + } + } + else if (req_status > 0){ + // we don't change status since it was not in pending + // we simply fail + mdclog_write(MDCLOG_ERR, "Error:: %s, %d: Request %s, %d for deletion is not in delete_pending state, is in State = %d\n", __FILE__, __LINE__, id, std::get<0>(id).c_str(), std::get<1>(id)); + } + else{ + mdclog_write(MDCLOG_ERR, "%s, %d: Could not find request id %s, %d in request queue for deletion ", __FILE__, __LINE__, std::get<0>(id).c_str(), std::get<1>(id)); + } + + } + } + + else{ + mdclog_write(MDCLOG_ERR, "%s, %d: Subscription Handler Response received E2AP PDU success response with an non-subscription response related type %d", __FILE__, __LINE__, procedureCode); + } + + } + + else if(type == E2N_E2AP_PDU_PR_unsuccessfulOutcome){ + + procedureCode = e2ap_recv->choice.unsuccessfulOutcome->procedureCode; + mdclog_write(MDCLOG_INFO, "Received E2AP PDU unsuccessful outcome message with procedureCode = %d", procedureCode); + + if(procedureCode == E2N_ProcedureCode_id_ricSubscription){ + + sub_resp.get_fields(e2ap_recv->choice.unsuccessfulOutcome, he_response); + { + std::lock_guard lock(*(_data_lock.get())); + + // get the id + subscription_identifier id = std::make_tuple (node, he_response.get_request_id()); + + int req_status = get_request_status(id); + if(req_status == request_pending){ + set_request_status(id, request_failed); + valid_response = true; + mdclog_write(MDCLOG_ERR, "Subscription request %d failed", id); + } + else if (req_status > 0){ + // we don't changet status since it was not in pending + // we simply fail + mdclog_write(MDCLOG_ERR, "Error:: %s, %d: Request %s, %d is not in request_pending state, is in State = %d\n", __FILE__, __LINE__, std::get<0>(id).c_str(), std::get<1>(id), req_status); + } + else{ + mdclog_write(MDCLOG_ERR, "%s, %d: Could not find id %s, %d in request queue for subscription ", __FILE__, __LINE__, std::get<0>(id).c_str(), std::get<1>(id)); + } + } + } + + else if(procedureCode == E2N_ProcedureCode_id_ricSubscriptionDelete){ + + res = sub_del_resp.get_fields(e2ap_recv->choice.unsuccessfulOutcome, he_response); + { + std::lock_guard lock(*(_data_lock.get())); + // get the id + subscription_identifier id = std::make_tuple (node, he_response.get_request_id()); + + int req_status = get_request_status(id); + if(req_status == delete_request_pending){ + set_request_status(id, delete_request_failed); + mdclog_write(MDCLOG_INFO, "Subscription delete request %s,%d failed", std::get<0>(id).c_str(), std::get<1>(id)); + valid_response = true; + } + else if (req_status > 0){ + mdclog_write(MDCLOG_ERR, "Error:: %s, %d: Request %s,%d for deletion is not in delete_pending state, is in State = %d\n", __FILE__, __LINE__, std::get<0>(id).c_str(), std::get<1>(id), req_status); + } + else{ + mdclog_write(MDCLOG_ERR, "%s, %d: Could not find id %s,%d in request queue for deletion ", __FILE__, __LINE__, std::get<0>(id).c_str(), std::get<1>(id)); + } + + } + } + else{ + mdclog_write(MDCLOG_ERR, "%s, %d: Susbcription Handler Response received E2AP PDU failure response with a non-subscription response related type %d", __FILE__, __LINE__, procedureCode); + + } + } + else{ + mdclog_write(MDCLOG_ERR, "%s, %d: Susbcription Handler Response received E2AP PDU with non response type %d", __FILE__, __LINE__, type); + } + + + ASN_STRUCT_FREE(asn_DEF_E2N_E2AP_PDU, e2ap_recv); + + // wake up all waiting users ... + if(valid_response){ + _cv.get()->notify_all(); + } + +} + + +int const SubscriptionHandler::get_request_status(subscription_identifier id){ + auto search = requests_table.find(id); + if (search == requests_table.end()){ + return -1; + } + + return search->second; +} + + bool SubscriptionHandler::is_subscription_entry(subscription_identifier id){ + auto search = subscription_responses.find(id); + if (search != subscription_responses.end()) + return true; + else + return false; +} + +bool SubscriptionHandler::is_request_entry(subscription_identifier id){ + auto search = requests_table.find(id); + if (search != requests_table.end()) + return true; + else + return false; +} + + +void SubscriptionHandler::get_subscription_keys(std::vector & key_list){ + for(auto & e: subscription_responses){ + key_list.push_back(e.first); + } +} diff --git a/src/xapp-mgmt/subs_mgmt.hpp b/src/xapp-mgmt/subs_mgmt.hpp new file mode 100644 index 0000000..77458d3 --- /dev/null +++ b/src/xapp-mgmt/subs_mgmt.hpp @@ -0,0 +1,334 @@ +/* +================================================================================== + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== +*/ +/* + * subs_mgmt.hpp + * Created on: 2019 + * Author: Ashwin Shridharan, Shraboni Jana + */ + +#pragma once + +#ifndef SUBSCRIPTION_HANDLER +#define SUBSCRIPTION_HANDLER + +#include +#include +#include +#include +#include +#include +#include + +#include "subscription_delete_request.hpp" +#include "subscription_delete_response.hpp" +#include "subscription_request.hpp" +#include "subscription_response.hpp" + +#define SUBSCR_SUCCESS 0 +#define SUBSCR_ERR_TX 1 +#define SUBSCR_ERR_TIMEOUT 2 +#define SUBSCR_ERR_FAIL 3 +#define SUBSCR_ERR_UNKNOWN 4 +#define SUBSCR_ERR_DUPLICATE 5 +#define SUBSCR_ERR_ENCODE 6 +#define SUBSCR_ERR_MISSING 7 + +using namespace std; + +typedef enum { + request_pending = 1, + request_success, + request_failed, + delete_request_pending, + delete_request_success, + delete_request_failed, + request_duplicate +}Subscription_Status_Types; + +using subscription_identifier = std::tuple; + +struct subscription_hasher { + size_t operator()(const subscription_identifier & key) const { + return std::hash{}(std::get<0>(key) + std::to_string(std::get<1>(key))); + } +}; + +class SubscriptionHandler { + +public: + + SubscriptionHandler(unsigned int timeout_seconds = 5, unsigned int num_retries = 2); + + void init(void); + + template + int request_subscription(std::string, int , Transmitter &&); + + template + int request_subscription_delete(subscription_helper &, subscription_response_helper &, std::string, int , Transmitter &&); + + void Response(int, unsigned char *, int, const char *); + int const get_request_status(subscription_identifier); + subscription_response_helper * const get_subscription(subscription_identifier); + + unsigned int get_next_id(void); + void set_timeout(unsigned int); + void set_num_retries(unsigned int); + + bool is_subscription_entry(subscription_identifier); + bool is_request_entry(subscription_identifier); + void get_subscription_keys(std::vector &); + void clear(void); + size_t num_pending(void) const; + size_t num_complete(void) const ; + + + +private: + + + bool add_request_entry(subscription_identifier, int); + bool set_request_status(subscription_identifier, int); + bool delete_request_entry(subscription_identifier); + + bool get_subscription_entry(subscription_identifier); + bool add_subscription_entry(subscription_identifier, subscription_response_helper &he); + bool delete_subscription_entry(subscription_identifier); + + std::unordered_map requests_table; + std::unordered_map subscription_responses; // stores list of successful subscriptions + + std::unique_ptr _data_lock; + std::unique_ptr _cv; + + std::chrono::seconds _time_out; + unsigned int _num_retries = 2; + unsigned int unique_request_id = 0; + +}; + +template +int SubscriptionHandler::request_subscription(std::string node_id, int msgcode, Transmitter && tx){ + + // generate subscription identifier + subscription_identifier sub_id = std::make_tuple (node_id, 0); //0 is the function id which is hardcoded, which should come from rnib + + + bool res; + // put entry in request table + { + std::lock_guard lock(*(_data_lock.get())); + res = add_request_entry(sub_id, request_pending); + if(! res){ + mdclog_write(MDCLOG_ERR, "%s, %d : Error adding new subscription request %s, %d to queue because request with identical key already present", __FILE__, __LINE__, std::get<0>(sub_id).c_str(), std::get<1>(sub_id)); + return SUBSCR_ERR_DUPLICATE; + } + } + + // acquire lock ... + std::unique_lock _local_lock(*(_data_lock.get())); + + + // Send the message + res = tx(); + + if (!res){ + // clear state + delete_request_entry(sub_id); + mdclog_write(MDCLOG_ERR, "%s, %d :: Error transmitting subscription request %s, %d", __FILE__, __LINE__, std::get<0>(sub_id).c_str(), std::get<1>(sub_id) ); + return SUBSCR_ERR_TX; + }; + + + // record time stamp .. + auto start = std::chrono::system_clock::now(); + res = SUBSCR_ERR_UNKNOWN; + + while(1){ + // release lock and wait to be woken up + _cv.get()->wait_for(_local_lock, _time_out); + + // we have woken and acquired data_lock + // check status and return appropriate object + + int status = get_request_status(sub_id); + + if (status == request_success){ + // retreive & store the subscription response (why?) + // response = subscription_responses[sub_id]; + mdclog_write(MDCLOG_INFO, "Successfully subscribed for request %s, %d", std::get<0>(sub_id).c_str(), std::get<1>(sub_id)); + res = SUBSCR_SUCCESS; + break; + } + + if (status == request_pending){ + // woken up spuriously or timed out + auto end = std::chrono::system_clock::now(); + std::chrono::duration f = end - start; + + if ( f > _num_retries * _time_out){ + mdclog_write(MDCLOG_ERR, "%s, %d:: Subscription request %s, %d timed out waiting for response ", __FILE__, __LINE__, std::get<0>(sub_id).c_str(), std::get<1>(sub_id)); + res = SUBSCR_ERR_TIMEOUT; + break; + } + else{ + mdclog_write(MDCLOG_INFO, "Subscription request %s, %d Waiting for response ....", std::get<0>(sub_id).c_str(), std::get<1>(sub_id)); + continue; + } + } + + if(status == request_failed){ + mdclog_write(MDCLOG_ERR, "Error :: %s, %d : Subscription Request %s, %d got failure response .. \n", __FILE__, __LINE__, std::get<0>(sub_id).c_str(), std::get<1>(sub_id)); + res = SUBSCR_ERR_FAIL; + break; + } + + if (status == request_duplicate){ + mdclog_write(MDCLOG_ERR, "Error :: %s, %d : Subscription Request %s, %d is duplicate : subscription already present in table .. \n", __FILE__, __LINE__, std::get<0>(sub_id).c_str(), std::get<1>(sub_id)); + res = SUBSCR_ERR_DUPLICATE; + break; + + } + + // if we are here, some spurious + // status obtained or request failed . we return appropriate error code + mdclog_write(MDCLOG_ERR, "Error :: %s, %d : Spurious time out caused by invalid state of request %s, %d -- state = %d. Deleting request entry and failing .. \n", __FILE__, __LINE__, std::get<0>(sub_id).c_str(), std::get<1>(sub_id), status); + res = SUBSCR_ERR_UNKNOWN; + break; + }; + + delete_request_entry(sub_id); + + // release data lock + _local_lock.unlock(); + std::cout <<"Returning res = " << res << " for request = " << std::get<0>(sub_id).c_str() << "," << std::get<1>(sub_id) << std::endl; + return res; +}; + + +/*template +int SubscriptionHandler::request_subscription_delete(subscription_helper &he, subscription_response_helper &response, std::string node_id, int TxCode, Transmitter && tx){ + + int res; + // generate subscription identifier + subscription_identifier sub_id = std::make_tuple (node_id, he.get_function_id()); + + // First check if we have this subscription + if(! is_subscription_entry(sub_id)){ + mdclog_write(MDCLOG_ERR, "subscription with id %s, %d does not exist. Cannot be deleted",std::get<0>(sub_id).c_str(), std::get<1>(sub_id)); + return SUBSCR_ERR_MISSING; + } + + // Also check if such a request is queued + if (is_request_entry(sub_id)){ + mdclog_write(MDCLOG_ERR, "Subscription delete request with id %s, %d already in queue",std::get<0>(sub_id).c_str(), std::get<1>(sub_id)); + return SUBSCR_ERR_DUPLICATE; + } + + subscription_delete e2ap_sub_req_del; + + // generate the delete request pdu + unsigned char buffer[128]; + size_t buf_len = 128; + + res = e2ap_sub_req_del.encode_e2ap_subscription(&buffer[0], &buf_len, he); + if(! res){ + mdclog_write(MDCLOG_ERR, "%s, %d: Error encoding subscription delete request pdu. Reason = %s", __FILE__, __LINE__, e2ap_sub_req_del.get_error().c_str()); + return SUBSCR_ERR_ENCODE; + } + + // put entry in request table + { + std::lock_guard lock(*(_data_lock.get())); + res = add_request_entry(sub_id, delete_request_pending); + if(!res){ + mdclog_write(MDCLOG_ERR, "%s, %d: Duplicate subscription delete request = %s, %d", __FILE__, __LINE__, std::get<0>(sub_id).c_str(), std::get<1>(sub_id) ); + return SUBSCR_ERR_DUPLICATE; + } + } + + std::unique_lock _local_lock(*(_data_lock.get())); + + // Send the message + res = tx(TxCode, buf_len, buffer); + + if (!res){ + delete_request_entry(sub_id); + mdclog_write(MDCLOG_ERR, "Error transmitting delete subscription request %s, %d", std::get<0>(sub_id).c_str(), std::get<1>(sub_id)); + return SUBSCR_ERR_TX; + }; + + + // record time stamp .. + auto start = std::chrono::system_clock::now(); + + res = SUBSCR_ERR_UNKNOWN; + while(1){ + + // wait to be woken up + _cv.get()->wait_for(_local_lock, _time_out); + + // check status and return appropriate object + int status = get_request_status(sub_id); + if (status == delete_request_success){ + mdclog_write(MDCLOG_INFO, "Successfully deleted subscription id %s, %d", std::get<0>(sub_id).c_str(), std::get<1>(sub_id)); + res = SUBSCR_SUCCESS; + break; + } + + if (status == delete_request_pending){ + // woken up spuriously or timed out + auto end = std::chrono::system_clock::now(); + std::chrono::duration f = end - start; + + if (f > _num_retries * _time_out){ + mdclog_write(MDCLOG_ERR, "Subscription delete request %s, %d timed out waiting for response ", std::get<0>(sub_id).c_str(), std::get<1>(sub_id)); + res = SUBSCR_ERR_TIMEOUT; + break; + } + else{ + mdclog_write(MDCLOG_INFO, "Subscription delete request %s, %d Waiting for response ....", std::get<0>(sub_id).c_str(), std::get<1>(sub_id)); + } + + continue; + } + + if(status == delete_request_failed){ + mdclog_write(MDCLOG_ERR, "Error :: %s, %d : Subscription Delete Request %s, %d got failure response .. \n", __FILE__, __LINE__, std::get<0>(sub_id).c_str(), std::get<1>(sub_id)); + res = SUBSCR_ERR_FAIL; + break; + } + + // if we are here, some spurious + // status obtained. we return false + + mdclog_write(MDCLOG_ERR, "Error :: %s, %d : Spurious time out caused by invalid state of delete request %s, %d -- state = %d. Deleting request entry and failing .. \n", __FILE__, __LINE__,std::get<0>(sub_id).c_str(), std::get<1>(sub_id), status); + res = SUBSCR_ERR_UNKNOWN; + break; + + }; + + delete_request_entry(sub_id); + + // release data lock + _local_lock.unlock(); + std::cout <<"Returning res = " << res << " for " << std::get<0>(sub_id) << "," << std::get<1>(sub_id) << std::endl; + return res; +};*/ + +#endif diff --git a/src/xapp-utils/xapp_config.cc b/src/xapp-utils/xapp_config.cc new file mode 100644 index 0000000..f9a4640 --- /dev/null +++ b/src/xapp-utils/xapp_config.cc @@ -0,0 +1,226 @@ +/* +================================================================================== + + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== + */ +/* + * xapp_config.cc + * Created on: 2019 + * Author: Ashwin Shridharan, Shraboni Jana + */ + +#include "xapp_config.hpp" + +string& XappSettings::operator[](const SettingName& theName){ + return theSettings[theName]; +} + +void XappSettings::loadCmdlineSettings(int argc, char **argv){ + + // Parse command line options to over ride + static struct option long_options[] = + { + {"xappname", required_argument, 0, 'n'}, + {"xappid", required_argument, 0, 'x'}, + {"port", required_argument, 0, 'p'}, + {"threads", required_argument, 0, 't'}, + {"a1-schema", required_argument, 0, 'a'}, + {"ves-schema", required_argument, 0, 'v'}, + {"ves-url", required_argument, 0, 'u'}, + {"ves-interval", required_argument, 0, 'i'}, + {"gNodeB", required_argument, 0, 'g'}, + {"opmode", required_argument, 0, 'c'} + + }; + + + while(1) { + + int option_index = 0; + char c = getopt_long(argc, argv, "n:p:t:s:g:a:v:u:i:c:x:", long_options, &option_index); + + if(c == -1){ + break; + } + + switch(c) + { + + case 'n': + theSettings[XAPP_NAME].assign(optarg); + break; + + case 'p': + theSettings[HW_PORTS].assign(optarg); + break; + + case 't': + theSettings[THREADS].assign(optarg); + mdclog_write(MDCLOG_INFO, "Number of threads set to %s from command line e\n", theSettings[THREADS].c_str()); + break; + + case 'a': + theSettings[A1_SCHEMA_FILE].assign(optarg); + mdclog_write(MDCLOG_INFO, "Schema file set to %s from command line ", theSettings[A1_SCHEMA_FILE].c_str()); + break; + + case 'v': + theSettings[VES_SCHEMA_FILE].assign(optarg); + mdclog_write(MDCLOG_INFO, "VES Schema file set to %s from command line ", theSettings[VES_SCHEMA_FILE].c_str()); + break; + + case 'c': + theSettings[OPERATING_MODE].assign(optarg); + mdclog_write(MDCLOG_INFO, "Operating mode set from command line to %s\n", theSettings[OPERATING_MODE].c_str()); + break; + + case 'u': + theSettings[VES_COLLECTOR_URL].assign(optarg); + mdclog_write(MDCLOG_INFO, "VES collector url set to %s from command line ", theSettings[VES_COLLECTOR_URL].c_str()); + break; + + case 'x': + theSettings[XAPP_ID].assign(optarg); + mdclog_write(MDCLOG_INFO, "XAPP ID set to %s from command line ", theSettings[XAPP_ID].c_str()); + break; + + case 'i': + theSettings[VES_MEASUREMENT_INTERVAL].assign(optarg); + mdclog_write(MDCLOG_INFO, "Measurement interval set to %s from command line\n", theSettings[VES_MEASUREMENT_INTERVAL].c_str()); + break; + + case 'g': + theSettings[GNODEB].assign(optarg); + mdclog_write(MDCLOG_INFO, "gNodeB List set to %s from command line ", theSettings[GNODEB].c_str()); + break; + + case 'h': + usage(argv[0]); + exit(0); + + default: + usage(argv[0]); + exit(1); + } + }; + +} + +void XappSettings::loadDefaultSettings(){ + + + if(theSettings[XAPP_NAME].empty()){ + theSettings[XAPP_NAME] = DEFAULT_PORT; + } + + if(theSettings[XAPP_ID].empty()){ + theSettings[XAPP_ID] = DEFAULT_PORT; + } + if(theSettings[LOG_LEVEL].empty()){ + theSettings[LOG_LEVEL] = DEFAULT_LOG_LEVEL; + } + if(theSettings[HW_PORTS].empty()){ + theSettings[HW_PORTS] = DEFAULT_PORT; + } + if(theSettings[MSG_MAX_BUFFER].empty()){ + theSettings[MSG_MAX_BUFFER] = DEFAULT_BUFFER; + } + + if(theSettings[A1_SCHEMA_FILE].empty()){ + theSettings[A1_SCHEMA_FILE] = DEFAULT_A1_SCHEMA_FILE; + } + + if(theSettings[VES_SCHEMA_FILE].empty()){ + theSettings[VES_SCHEMA_FILE] = DEFAULT_VES_SCHEMA_FILE; + } + + if(theSettings[VES_COLLECTOR_URL].empty()){ + theSettings[VES_COLLECTOR_URL] = DEFAULT_VES_COLLECTOR_URL; + } + + if(theSettings[VES_MEASUREMENT_INTERVAL].empty()){ + theSettings[VES_MEASUREMENT_INTERVAL] = DEFAULT_VES_MEASUREMENT_INTERVAL; + } + + if(theSettings[GNODEB].empty()){ + theSettings[GNODEB] = DEFAULT_GNODEB; + } + + if(theSettings[OPERATING_MODE].empty()){ + theSettings[OPERATING_MODE] = DEFAULT_OPERATING_MODE; + } + +} + +void XappSettings::loadEnvVarSettings(){ + + if (const char *env_xname = std::getenv("XAPP_NAME")){ + theSettings[XAPP_NAME].assign(env_xname); + mdclog_write(MDCLOG_INFO,"Xapp Name set to %s from environment variable", theSettings[XAPP_NAME].c_str()); + } + if (const char *env_xid = std::getenv("XAPP_ID")){ + theSettings[XAPP_ID].assign(env_xid); + mdclog_write(MDCLOG_INFO,"Xapp ID set to %s from environment variable", theSettings[XAPP_ID].c_str()); + } + + if (const char *env_ports = std::getenv("HW_PORTS")){ + theSettings[HW_PORTS].assign(env_ports); + mdclog_write(MDCLOG_INFO,"Ports set to %s from environment variable", theSettings[HW_PORTS].c_str()); + } + if (const char *env_ports = std::getenv("MSG_MAX_BUFFER")){ + theSettings[MSG_MAX_BUFFER].assign(env_ports); + mdclog_write(MDCLOG_INFO,"Ports set to %s from environment variable", theSettings[MSG_MAX_BUFFER].c_str()); + } + + if (const char *env_schema = std::getenv("A1_SCHEMA_FILE")){ + theSettings[A1_SCHEMA_FILE].assign(env_schema); + mdclog_write(MDCLOG_INFO, "A1 Schema file set to %s from environment variable", theSettings[A1_SCHEMA_FILE].c_str()); + } + if (const char *env_schema = std::getenv("VES_SCHEMA_FILE")){ + theSettings[VES_SCHEMA_FILE].assign(env_schema); + mdclog_write(MDCLOG_INFO, "VES Schema file set to %s from environment variable", theSettings[VES_SCHEMA_FILE].c_str()); + } + if (const char *env_schema = std::getenv("VES_COLLECTOR_URL")){ + theSettings[VES_COLLECTOR_URL].assign(env_schema); + mdclog_write(MDCLOG_INFO, "VES Collector url set to %s from environment variable", theSettings[VES_COLLECTOR_URL].c_str()); + + } + if (const char *env_schema = std::getenv("VES_MEASUREMENT_INTERVAL")){ + theSettings[VES_MEASUREMENT_INTERVAL].assign(env_schema); + mdclog_write(MDCLOG_INFO, "VES Measurement Interval set to %s from environment variable", theSettings[VES_MEASUREMENT_INTERVAL].c_str()); + } + + if (char *env_gnodeb = std::getenv("GNODEB")){ + theSettings[GNODEB].assign(env_gnodeb); + mdclog_write(MDCLOG_INFO, "GNODEB file set to %s from environment variable", theSettings[GNODEB].c_str()); + } + + +} + +void XappSettings::usage(char *command){ + std::cout <<"Usage : " << command << " " << std::endl; + std::cout <<" --name[-n] xapp_instance_name "<< std::endl; + std::cout <<" --port[-p] port to listen on e.g tcp:4561 "<< std::endl; + std::cout << "--threads[-t] number of listener threads "<< std::endl ; + std::cout << "--a1-schema[-a] a1 schema file location" << std::endl; + std::cout << "--ves-schema[-v] ves schema file location" << std::endl; + std::cout << "--samples [-s] samples file location with samples for all jsons" << std::endl; + std::cout << "--ves-url [-u] ves collector url" << std::endl; + std::cout << "--gNodeB[][-g] gNodeB" << std::endl; + std::cout << "--interval[-i] measurement interval to send to ves collector (in seconds)" << std::endl; + std::cout << "--opmode [-c] type of operatoring mode : either REPORT or CONTROL. In REPORT, does not send a control message back to gNodeB" << std::endl; +} diff --git a/src/xapp-utils/xapp_config.hpp b/src/xapp-utils/xapp_config.hpp new file mode 100644 index 0000000..389703e --- /dev/null +++ b/src/xapp-utils/xapp_config.hpp @@ -0,0 +1,86 @@ +/* +================================================================================== + + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== + */ +/* + * xapp_config.hpp + * Created on: 2019 + * Author: Ashwin Shridharan, Shraboni Jana + */ + +#ifndef SRC_XAPP_CONFIG_XAPP_CONFIG_HPP_ +#define SRC_XAPP_CONFIG_XAPP_CONFIG_HPP_ + +#include +#include +#include +#include +#include + +#define MAX_SLEEP 86400 + +#define DEFAULT_A1_SCHEMA_FILE "/etc/xapp/a1-schema.json" +#define DEFAULT_XAPP_ID "hw-xapp-123" +#define DEFAULT_VES_SCHEMA_FILE "/etc/xapp/ves-schema.json" +#define DEFAULT_VES_COLLECTOR_URL "127.0.0.1:6350" +#define DEFAULT_VES_MEASUREMENT_INTERVAL 10 +#define DEFAULT_PORT "4560" +#define DEFAULT_BUFFER "1024" +#define DEFAULT_GNODEB "GNB123" +#define DEFAULT_OPERATING_MODE "report" +#define DEFAULT_LOG_LEVEL MDCLOG_WARN + +#define ASN_BUFF_MAX_SIZE 512 +#define MAX_SUBSCRIPTION_ATTEMPTS 10 +#define HELLOWORLD_POLICY_ID 00000 +#define DEFAULT_THREADS 1 + +using namespace std; + +struct XappSettings{ + +public: + typedef enum{ + XAPP_ID, + XAPP_NAME, + HW_PORTS, + MSG_MAX_BUFFER, + GNODEB, + THREADS, + A1_SCHEMA_FILE, + VES_SCHEMA_FILE, + SAMPLE_FILE, + VES_COLLECTOR_URL, + VES_MEASUREMENT_INTERVAL, + LOG_LEVEL, + OPERATING_MODE + }SettingName; + + void loadDefaultSettings(); + void loadCmdlineSettings(int, char **); + void loadEnvVarSettings(); + void usage(char*); + string& operator[](const SettingName& theName); +private: + typedef map SettingCollection; + SettingCollection theSettings; + +}; + + + +#endif /* SRC_XAPP_CONFIG_XAPP_CONFIG_HPP_ */ diff --git a/src/xapp-utils/xapp_rmr.cc b/src/xapp-utils/xapp_rmr.cc new file mode 100755 index 0000000..f757667 --- /dev/null +++ b/src/xapp-utils/xapp_rmr.cc @@ -0,0 +1,121 @@ +/* +================================================================================== + + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== + */ + + +#include "xapp_rmr.hpp" + +XappRmr::XappRmr(std::string xname, std::string port, int rmrattempts){ + + _proto_port = port; + _xapp_name = xname; + _nattempts = rmrattempts; + _xapp_rmr_ctx = NULL; + _xapp_received_buff = NULL; + _xapp_send_buff =NULL; + _rmr_is_ready = false; + +}; + +XappRmr::~XappRmr(void){ + + // free memory + if(_xapp_received_buff) + rmr_free_msg(_xapp_received_buff); + + if(_xapp_send_buff) + rmr_free_msg(_xapp_send_buff); + + if (_xapp_rmr_ctx){ + rmr_close(_xapp_rmr_ctx); + } +}; + +//Get RMR Context. +void XappRmr::xapp_rmr_init(){ + + // Initialize the RMR context + _xapp_rmr_ctx = rmr_init(const_cast(_proto_port.c_str()), RMR_MAX_RCV_BYTES, RMRFL_NONE); + + if ( _xapp_rmr_ctx == NULL){ + mdclog_write(MDCLOG_ERR,"Error Initializing RMR, file= %s, line=%d",__FILE__,__LINE__); + } + while( ! rmr_ready(_xapp_rmr_ctx) ) { + mdclog_write(MDCLOG_INFO,">>> waiting for RMR, file= %s, line=%d",__FILE__,__LINE__); + sleep(1); + } + _rmr_is_ready = true; + mdclog_write(MDCLOG_INFO,"RMR Context is Ready, file= %s, line=%d",__FILE__,__LINE__); + + return; + +} + +bool XappRmr::xapp_rmr_rts() +{ + _xapp_send_buff = rmr_realloc_payload( _xapp_send_buff, 128, false, false ); // ensure payload is large enough + strncpy( (char*)_xapp_send_buff->payload, "OK\n", rmr_payload_size( _xapp_send_buff) ); + rmr_rts_msg(_xapp_rmr_ctx, _xapp_send_buff ); + _xapp_send_buff = NULL; + return true; +} + +//RMR Send with payload and header. +bool XappRmr::xapp_rmr_send(xapp_rmr_header *hdr, void *payload){ + + if( _xapp_send_buff == NULL ) { + _xapp_send_buff = rmr_alloc_msg(_xapp_rmr_ctx, RMR_DEF_SIZE); + } + + + _xapp_send_buff->mtype = hdr->message_type; + + memcpy(_xapp_send_buff->payload, payload, hdr->payload_length); + + _xapp_send_buff->len = hdr->payload_length; + if(!_rmr_is_ready) { + mdclog_write(MDCLOG_ERR,"RMR Context is Not Ready in SENDER, file= %s, line=%d",__FILE__,__LINE__); + return false; + } + if( _xapp_send_buff == NULL ) { + return false; + } + + + while(_nattempts > 0){ + _xapp_send_buff = rmr_send_msg(_xapp_rmr_ctx,_xapp_send_buff); + + if(!_xapp_send_buff) { + mdclog_write(MDCLOG_ERR,"Error In Sending Message , file= %s, line=%d",__FILE__,__LINE__); + _nattempts--; + } + else if (_xapp_send_buff->state == RMR_OK){ + mdclog_write(MDCLOG_INFO,"The okay message is %d, file= %s, line=%d", RMR_OK, __FILE__,__LINE__); + _nattempts = 0; + return true; + } + else + { + mdclog_write(MDCLOG_INFO,"Need to retry RMR MSG NUM %d, file= %s, line=%d",_xapp_send_buff->state, __FILE__,__LINE__); + _nattempts--; + } + sleep(1); + } + return false; +} + diff --git a/src/xapp-utils/xapp_rmr.hpp b/src/xapp-utils/xapp_rmr.hpp new file mode 100755 index 0000000..2ba6fb1 --- /dev/null +++ b/src/xapp-utils/xapp_rmr.hpp @@ -0,0 +1,117 @@ +/* +================================================================================== + + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== +*/ + +#ifndef XAPP_RMR_XAPP_RMR_H_ +#define XAPP_RMR_XAPP_RMR_H_ + + +#ifdef __GNUC__ +#define likely(x) __builtin_expect((x), 1) +#define unlikely(x) __builtin_expect((x), 0) +#else +#define likely(x) (x) +#define unlikely(x) (x) +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct{ + struct timespec ts; + int32_t message_type; + int32_t state; + int32_t payload_length; + unsigned char xid[RMR_MAX_XID]; //space for user transaction id. + unsigned char sid[RMR_MAX_SID]; //sender ID for return to sender needs.(ACKS required) + unsigned char src[RMR_MAX_SRC]; //name of the sender (source) +} xapp_rmr_header; + + +class XappRmr{ +private: + std::string _xapp_name; + std::string _proto_port; + int _nattempts; + bool _rmr_is_ready; + void* _xapp_rmr_ctx; + rmr_mbuf_t* _xapp_send_buff; // send buffer + rmr_mbuf_t* _xapp_received_buff; // received buffer + + +public: + + XappRmr(std::string, std::string, int rmrattempts=10); + ~XappRmr(void); + void xapp_rmr_init(void); + + template + void xapp_rmr_receive(MessageProcessor&&, XappRmr *parent); + bool xapp_rmr_send(xapp_rmr_header*, void*); + bool xapp_rmr_rts(); + +}; + +//RMR receive +template +void XappRmr::xapp_rmr_receive(MessageProcessor&& msgproc, XappRmr *parent){ + char* listen_port; + + if( (listen_port = getenv( "RMR_RCV_PORT" )) == NULL ) { + mdclog_write(MDCLOG_ERR,"No Listening port assigned, file= %s, line=%d",__FILE__,__LINE__); + } + + if(!_rmr_is_ready){ + mdclog_write( MDCLOG_ERR, "RMR Shows Not Ready in RECEIVER, file= %s, line=%d ",__FILE__,__LINE__); + return; + } + + while( 1 ) { + parent->_xapp_received_buff = rmr_rcv_msg( parent->_xapp_rmr_ctx, parent->_xapp_received_buff ); // block until one arrives + if( parent->_xapp_received_buff->mtype < 0 || parent->_xapp_received_buff->state != RMR_OK ) { + mdclog_write(MDCLOG_ERR, "bad msg: state=%d errno=%d, file= %s, line=%d", parent->_xapp_received_buff->state, errno, __FILE__,__LINE__ ); + return; + } else { + std::cout << "The Message Received is:" << (char*)parent->_xapp_received_buff->payload <mtype <set(ns, dmap); +} + + diff --git a/src/xapp-utils/xapp_sdl.hpp b/src/xapp-utils/xapp_sdl.hpp new file mode 100644 index 0000000..6472352 --- /dev/null +++ b/src/xapp-utils/xapp_sdl.hpp @@ -0,0 +1,61 @@ +/* +================================================================================== + + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== + */ + +/* + * xapp_sdl.hpp + * + * Created on: Mar, 2020 + * Author: Shraboni Jana + */ +#pragma once + +#ifndef SRC_XAPP_UTILS_XAPP_SDL_HPP_ +#define SRC_XAPP_UTILS_XAPP_SDL_HPP_ + +#include +#include +#include +#include +#include +#include +#include + + +using namespace std; +using Namespace = std::string; +using Key = std::string; +using Data = std::vector; +using DataMap = std::map; +using Keys = std::set; + +class XappSDL{ +private: + std::unique_ptr sdl; + Namespace ns; +public: + + XappSDL(std::string s) { + Namespace temp(s); + ns = temp; + sdl = (shareddatalayer::SyncStorage::create()); + }; + void insert_data(); +}; + +#endif /* SRC_XAPP_UTILS_XAPP_SDL_HPP_ */ diff --git a/src/xapp.cc b/src/xapp.cc new file mode 100644 index 0000000..ca737e6 --- /dev/null +++ b/src/xapp.cc @@ -0,0 +1,156 @@ +/* +================================================================================== + + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== + */ +/* + * xapp.cc + * + * Created on: Mar, 2020 + * Author: Shraboni Jana + */ + +#include "xapp.hpp" + +Xapp::Xapp(XappSettings &config, XappRmr &rmr){ + rmr_ref = &rmr; + config_ref = &config; + xapp_mutex = NULL; + return; +} + + +Xapp::Xapp(XappSettings &config, XappRmr &rmr, XappSDL &sdl){ + rmr_ref = &rmr; + config_ref = &config; + sdl_ref = &sdl; + //sdl_ref.insert_data(); + xapp_mutex = NULL; + + return; +} +Xapp::~Xapp(void){ + + //Joining the threads + int threadcnt = xapp_rcv_thread.size(); + for(int i=0; i> message_procs; + mdclog_write(MDCLOG_INFO,"Receiver Thread file= %s, line=%d",__FILE__,__LINE__); + std::unique_ptr mp_handler = std::make_unique(); + std::lock_guard guard(*xapp_mutex); + std::thread th_recv([&](){ rmr_ref->xapp_rmr_receive(std::move(*mp_handler.get()), rmr_ref);}); + xapp_rcv_thread.push_back(std::move(th_recv)); + + + return; + + + +} +void Xapp::shutdown(){ + + return; + +} + + +void Xapp::startup_subscribe_requests(void ){ + size_t data_size = ASN_BUFF_MAX_SIZE; + unsigned char data[data_size]; + + std::vector gNodeBs; + gNodeBs.push_back("GNB1001"); //this line should come from RNIB + + + for(auto &it: gNodeBs){ + int attempt = 0; + XappMsgHandler msg; + + /* bool res_encode = msg.encode_subscription_request(data, &data_size); + if(!res_encode) exit(0);*/ + char *strMsg = "HelloWorld\0"; + strncpy((char *)data,strMsg,strlen(strMsg)); + data_size = sizeof(data); + + xapp_rmr_header rmr_header; + rmr_header.message_type = RIC_SUB_RESP; + rmr_header.payload_length = data_size; + while(1){ + + auto transmitter = std::bind(&XappRmr::xapp_rmr_send,rmr_ref, &rmr_header, (void*)data); + transmitter(); //this will go to subscription manager. + break; + } + } +} + +void Xapp::startup_get_policies(void){ + + int policy_id = HELLOWORLD_POLICY_ID; + + std::string policy_query = "{\"policy_id\":" + std::to_string(policy_id) + "}"; + unsigned char * message = (unsigned char *)calloc(policy_query.length(), sizeof(unsigned char)); + memcpy(message, policy_query.c_str(), policy_query.length()); + xapp_rmr_header header; + header.payload_length = policy_query.length(); + header.message_type = A1_POLICY_QUERY; + mdclog_write(MDCLOG_INFO, "Sending request for policy id %d\n", policy_id); + rmr_ref->xapp_rmr_send(&header, (void *)message); + free(message); + +} +void Xapp::sdl_data(void) { + sdl_ref->insert_data(); +} +/*void Xapp::rnib_data(void) { + + printf("Using rnibreader lib from C:\n"); + open(); + void *result = getListGnbIds(); + if(result == NULL){ + + printf("ERROR: no data from getListGnbIds\n"); + return; + } + printf("getListGnbIds response: %s\n", (char *)result); + close(); + free(result); + return; + +}*/ + + + + + + diff --git a/src/xapp.hpp b/src/xapp.hpp new file mode 100644 index 0000000..bcfff5b --- /dev/null +++ b/src/xapp.hpp @@ -0,0 +1,78 @@ +/* +================================================================================== + + Copyright (c) 2018-2019 AT&T Intellectual Property. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +================================================================================== + *//* + * xapp.hpp + * + * Modified: Mar, 2020 (Shraboni Jana) + * + */ + +#pragma once + +#ifndef SRC_XAPP_HPP_ +#define SRC_XAPP_HPP_ + +#include +#include +#include +#include +#include +#include "xapp_rmr.hpp" +#include "xapp_sdl.hpp" +#include "rapidjson/writer.h" + +#include "msgs_proc.hpp" +#include "subs_mgmt.hpp" +#include "xapp_config.hpp" +//#include "rnib/rnibreader.h" + + +using namespace std; +using namespace std::placeholders; + +class Xapp{ +public: + + Xapp(XappSettings &, XappRmr &); + Xapp(XappSettings &, XappRmr &, XappSDL &); + ~Xapp(void); + + void startup(); + void shutdown(void); + + void start_xapp_receiver(); + + Xapp(Xapp const &)=delete; + Xapp& operator=(Xapp const &) = delete; + +private: + void startup_subscribe_requests(void ); + void shutdown_subscribe_deletes(void); + void startup_get_policies(void ); + void sdl_data(void); + void rnib_data(void); + + XappRmr * rmr_ref; + XappSettings * config_ref; + XappSDL *sdl_ref = NULL; + std::mutex *xapp_mutex; + std::vector xapp_rcv_thread; +}; + + +#endif /* SRC_XAPP_HPP_ */ -- 2.16.6