First commit

This commit is contained in:
Leonardo Bonati
2021-12-08 20:17:46 +00:00
commit 60dffad583
2923 changed files with 463894 additions and 0 deletions

Binary file not shown.

View File

@@ -0,0 +1,79 @@
CXX:= g++ --std=c++14 -O2 -L/usr/local/lib
CC:= gcc -O2 -L/usr/local/lib
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`
RNIB_LIBS:= -pthread /usr/local/include/rnib/rnibreader.a
######## 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_si -lpthread -lm $(LOG_LIBS) $(CURL_LIBS) $(RNIB_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) $(RNIBFLAGS) $(CPPFLAGS) $(CLOGFLAGS) agent_connector.cc
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

View File

@@ -0,0 +1,34 @@
==================================================================================
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)...
Steps for installation/running HWXapp.
$ source ./run_xapp.sh
$ make
$ ./hw_xapp_main

View File

@@ -0,0 +1,141 @@
#include "agent_connector.hpp"
// open client of control socket with agent
int open_control_socket_agent(const char* dest_ip, const int dest_port) {
std::cout << "Opening control socket with host " << dest_ip << ":" << dest_port << std::endl;
int control_sckfd = socket(AF_INET, SOCK_STREAM, 0);
if (control_sckfd < 0) {
std::cout << "ERROR: OPEN SOCKET" << std::endl;
close(control_sckfd);
return -1;
}
// SET SOCKET OPTIONS TO RELEASE THE SOCKET ADDRESS IMMEDIATELY AFTER
// THE SOCKET IS CLOSED
int option(1);
setsockopt(control_sckfd, SOL_SOCKET, SO_REUSEADDR, (char*)&option, sizeof(option));
struct sockaddr_in dest_addr = {0};
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(dest_port);
// convert dest_ip from char* to network address
if (inet_pton(AF_INET, dest_ip, &dest_addr.sin_addr) <= 0) {
std::cout << "ERROR CONVERTING IP TO INTERNET ADDR" << std::endl;
close(control_sckfd); // if conversion fail, close the socket and return error -2
return -2;
}
if (connect(control_sckfd, (struct sockaddr *) &dest_addr, sizeof(dest_addr)) < 0) {
std::cout << "ERROR: CONNECT" << std::endl;
close(control_sckfd);
return -3;
}
// update map
std::string agent_ip;
agent_ip.assign(dest_ip);
// std::cout << "Agent IP " << agent_ip << std::endl;
agentIp_socket[agent_ip] = control_sckfd;
return 0;
}
// close control sockets
void close_control_socket_agent(void) {
std::cout << "Closing control sockets with agent(s)" << std::endl;
std::map<std::string, int>::iterator it;
for (it = agentIp_socket.begin(); it != agentIp_socket.end(); ++it) {
std::string agent_ip = it->first;
int control_sckfd = it->second;
close(control_sckfd);
}
// clear maps
std::cout << "Clearing maps" << std::endl;
agentIp_socket.clear();
agentIp_gnbId.clear();
}
// find agent IP of socket to use with gNB id
std::string find_agent_ip_from_gnb(unsigned char* gnb_id_trans) {
std::map<std::string, int>::iterator it_sck;
std::map<std::string, std::string>::iterator it_gnb;
std::string agent_ip;
// convert transaction identifier (unsigned char*) to string
std::string gnb_id(reinterpret_cast<char*>(gnb_id_trans));
// check if gnb_id is already in agentIp_gnbId map
bool found = false;
for (it_gnb = agentIp_gnbId.begin(); it_gnb != agentIp_gnbId.end(); ++it_gnb) {
if (gnb_id.compare(it_gnb->second) == 0) {
agent_ip = it_gnb->first;
found = true;
break;
}
}
if (!found) {
// check if agent_ip is already in agentIp_gnbId map
for (it_sck = agentIp_socket.begin(); it_sck != agentIp_socket.end(); ++it_sck) {
agent_ip = it_sck->first;
it_gnb = agentIp_gnbId.find(agent_ip);
if (it_gnb == agentIp_gnbId.end()) {
// insert into agentIp_gnbId map
agentIp_gnbId[agent_ip] = gnb_id;
break;
}
}
}
return agent_ip;
}
// send through socket
int send_socket(char* buf, std::string dest_ip) {
int control_sckfd = -1;
// get socket file descriptor
std::map<std::string, int>::iterator it;
for (it = agentIp_socket.begin(); it != agentIp_socket.end(); ++it) {
std::string agent_ip = it->first;
if (dest_ip.compare(agent_ip) == 0) {
control_sckfd = it->second;
break;
}
}
if (control_sckfd == -1) {
std::cout << "ERROR: Could not find socket for destination " << dest_ip << std::endl;
return -1;
}
// const size_t max_size = 512;
// char buf[max_size] = "Hello, Server!"; // store the data in a buffer
size_t data_size = strlen(buf);
int sent_size = send(control_sckfd ,buf, data_size, 0);
if(sent_size < 0) { // the send returns a size of -1 in case of errors
std::cout << "ERROR: SEND to agent " << dest_ip << std::endl;
return -2;
}
else {
std::cout << "Message sent" << std::endl;
}
return 0;
}

View File

@@ -0,0 +1,32 @@
#ifndef AGENT_CONNECTOR_HPP_
#define AGENT_CONNECTOR_HPP_
#include <iostream>
#include <string.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <map>
#include <vector>
#define AGENT_0 "127.0.0.1"
// vector of agent IPs
extern std::vector<std::string> drl_agent_ip;
// key: DRL agent IP, value: socket file descriptor
extern std::map<std::string, int> agentIp_socket;
// key: DRL agent IP, value: gNB id
extern std::map<std::string, std::string> agentIp_gnbId;
int open_control_socket_agent(const char* dest_ip, const int dest_port);
void close_control_socket_agent(void);
std::string find_agent_ip_from_gnb(unsigned char* gnb_id);
int send_socket(char* buf, std::string dest_ip);
#endif

View File

@@ -0,0 +1,97 @@
/*
==================================================================================
Copyright (c) 2019-2020 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 <thread>
void signalHandler( int signum ) {
cout << "Interrupt signal (" << signum << ") received.\n";
exit(signum);
}
int main(int argc, char *argv[]){
// Get the thread id
std::thread::id my_id = std::this_thread::get_id();
std::stringstream thread_id;
std::stringstream ss;
thread_id << my_id;
mdclog_write(MDCLOG_INFO, "Starting thread %s", thread_id.str().c_str());
//get configuration
XappSettings config;
//change the priority depending upon application requirement
config.loadDefaultSettings();
config.loadEnvVarSettings();
config.loadCmdlineSettings(argc, argv);
//Register signal handler to stop
signal(SIGINT, signalHandler);
signal(SIGTERM, signalHandler);
//getting the listening port and xapp name info
std::string port = config[XappSettings::SettingName::HW_PORT];
std::string name = config[XappSettings::SettingName::XAPP_NAME];
//initialize rmr
std::unique_ptr<XappRmr> rmr = std::make_unique<XappRmr>(port);
rmr->xapp_rmr_init(true);
//Create Subscription Handler if Xapp deals with Subscription.
std::unique_ptr<SubscriptionHandler> sub_handler = std::make_unique<SubscriptionHandler>();
//create HelloWorld Xapp Instance.
std::unique_ptr<Xapp> hw_xapp;
hw_xapp = std::make_unique<Xapp>(std::ref(config),std::ref(*rmr));
mdclog_write(MDCLOG_INFO, "Created Hello World Xapp Instance");
sleep(1);
//Startup E2 subscription and A1 policy
//hw_xapp->startup(std::ref(*sub_handler));
//start listener threads and register message handlers.
int num_threads = std::stoi(config[XappSettings::SettingName::THREADS]);
mdclog_write(MDCLOG_INFO, "Starting Listener Threads. Number of Workers = %d", num_threads);
std::unique_ptr<XappMsgHandler> mp_handler = std::make_unique<XappMsgHandler>(config[XappSettings::SettingName::XAPP_ID], std::ref(*sub_handler));
hw_xapp->start_xapp_receiver(std::ref(*mp_handler));
sleep(1);
hw_xapp->startup(std::ref(*sub_handler));
//xapp->shutdown();
while(1){
sleep(1);
}
return 0;
}

View File

@@ -0,0 +1,13 @@
newrt|start
rte|100|127.0.0.1:4560
rte|101|127.0.0.1:4560
rte|20010|127.0.0.1:4560
rte|20011|127.0.0.1:4560
rte|20012|127.0.0.1:4560
rte|12010|127.0.0.1:4560
rte|12011|127.0.0.1:4560
rte|12012|127.0.0.1:4560
rte|12020|127.0.0.1:4560
rte|12021|127.0.0.1:4560
rte|12022|127.0.0.1:4560
newrt|end

View File

@@ -0,0 +1,21 @@
#! /bin/bash
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"

View File

@@ -0,0 +1,266 @@
/*
==================================================================================
Copyright (c) 2019-2020 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 = (E2AP_PDU_t * )calloc(1, sizeof(E2AP_PDU_t));
assert(e2ap_pdu_obj != 0);
initMsg = 0;
initMsg = (InitiatingMessage_t * )calloc(1, sizeof(InitiatingMessage_t));
assert(initMsg != 0);
IE_array = 0;
IE_array = (RICcontrolRequest_IEs_t *)calloc(NUM_CONTROL_REQUEST_IES, sizeof(RICcontrolRequest_IEs_t));
assert(IE_array != 0);
e2ap_pdu_obj->present = 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");
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_E2AP_PDU, e2ap_pdu_obj);
mdclog_write(MDCLOG_DEBUG, "Freed 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 = ProcedureCode_id_RICcontrol;
initMsg->criticality = Criticality_ignore;
initMsg->value.present = InitiatingMessage__value_PR_RICcontrolRequest;
bool res;
res = set_fields(initMsg, dinput);
if (!res){
return false;
}
int ret_constr = asn_check_constraints(&asn_DEF_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_E2AP_PDU, e2ap_pdu_obj);
asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_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(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;
}
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;
RICcontrolRequest_IEs_t *ies_ricreq = &IE_array[ie_index];
ies_ricreq->criticality = Criticality_reject;
ies_ricreq->id = ProtocolIE_ID_id_RICrequestID;
ies_ricreq->value.present = RICcontrolRequest_IEs__value_PR_RICrequestID;
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;
RICcontrolRequest_IEs_t *ies_ranfunc = &IE_array[ie_index];
ies_ranfunc->criticality = Criticality_reject;
ies_ranfunc->id = ProtocolIE_ID_id_RANfunctionID;
ies_ranfunc->value.present = RICcontrolRequest_IEs__value_PR_RANfunctionID;
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;
RICcontrolRequest_IEs_t *ies_richead = &IE_array[ie_index];
ies_richead->criticality = Criticality_reject;
ies_richead->id = ProtocolIE_ID_id_RICcontrolHeader;
ies_richead->value.present = RICcontrolRequest_IEs__value_PR_RICcontrolHeader;
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;
RICcontrolRequest_IEs_t *ies_indmsg = &IE_array[ie_index];
ies_indmsg->criticality = Criticality_reject;
ies_indmsg->id = ProtocolIE_ID_id_RICcontrolMessage;
ies_indmsg->value.present = RICcontrolRequest_IEs__value_PR_RICcontrolMessage;
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){
RICcontrolRequest_IEs_t *ies_indtyp = &IE_array[ie_index];
ies_indtyp->criticality = Criticality_reject;
ies_indtyp->id = ProtocolIE_ID_id_RICcontrolAckRequest;
ies_indtyp->value.present = RICcontrolRequest_IEs__value_PR_RICcontrolAckRequest;
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){
RICcontrolRequest_IEs_t *ies_callprocid = &IE_array[ie_index];
ies_callprocid->criticality = Criticality_reject;
ies_callprocid->id = ProtocolIE_ID_id_RICcallProcessID;
ies_callprocid->value.present = RICcontrolRequest_IEs__value_PR_RICcallProcessID;
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(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++) {
RICcontrolRequest_IEs_t *memb_ptr = init_msg->value.choice.RICcontrolRequest.protocolIEs.list.array[edx];
switch(memb_ptr->id)
{
case (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 (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 (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 (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 (ProtocolIE_ID_id_RANfunctionID):
dout.func_id = memb_ptr->value.choice.RANfunctionID;
break;
case (ProtocolIE_ID_id_RICcontrolAckRequest):
dout.control_ack = memb_ptr->value.choice.RICcontrolAckRequest;
break;
default:
break;
}
}
return true;
}
InitiatingMessage_t * ric_control_request::get_message(void) {
return initMsg;
}

View File

@@ -0,0 +1,66 @@
/*
==================================================================================
Copyright (c) 2019-2020 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 <iostream>
#include <errno.h>
#include <mdclog/mdclog.h>
#include <sstream>
#include <E2AP-PDU.h>
#include <InitiatingMessage.h>
#include <RICcontrolRequest.h>
#include <ProtocolIE-Field.h>
#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 &);
InitiatingMessage_t * get_message (void) ;
bool set_fields(InitiatingMessage_t *, ric_control_helper &);
bool get_fields(InitiatingMessage_t *, ric_control_helper &);
std::string get_error(void) const {return error_string ; };
private:
E2AP_PDU_t * e2ap_pdu_obj;
InitiatingMessage_t *initMsg;
RICcontrolRequest_IEs_t *IE_array;
std::string error_string;
char errbuf[128];
size_t errbuf_len = 128;
};
#endif /* E2AP_RIC_CONTROL_REQUEST_H_ */

View File

@@ -0,0 +1,50 @@
/*
==================================================================================
Copyright (c) 2019-2020 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

View File

@@ -0,0 +1,415 @@
/*
==================================================================================
Copyright (c) 2019-2020 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 = (E2AP_PDU_t * )calloc(1, sizeof(E2AP_PDU_t));
assert(e2ap_pdu_obj != 0);
successMsg = 0;
successMsg = (SuccessfulOutcome_t * )calloc(1, sizeof(SuccessfulOutcome_t));
assert(successMsg != 0);
successMsg->procedureCode = ProcedureCode_id_RICcontrol;
successMsg->criticality = Criticality_reject;
successMsg->value.present = SuccessfulOutcome__value_PR_RICcontrolAcknowledge;
unsuccessMsg = 0;
unsuccessMsg = (UnsuccessfulOutcome_t * )calloc(1, sizeof(UnsuccessfulOutcome_t));
assert(unsuccessMsg != 0);
unsuccessMsg->procedureCode = ProcedureCode_id_RICcontrol;
unsuccessMsg->criticality = Criticality_reject;
unsuccessMsg->value.present = UnsuccessfulOutcome__value_PR_RICcontrolFailure;
IE_array = 0;
IE_array = (RICcontrolAcknowledge_IEs_t *)calloc(NUM_CONTROL_ACKNOWLEDGE_IES, sizeof(RICcontrolAcknowledge_IEs_t));
assert(IE_array != 0);
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 = (RICcontrolFailure_IEs_t *)calloc(NUM_CONTROL_FAILURE_IES, sizeof(RICcontrolFailure_IEs_t));
assert(IE_failure_array != 0);
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");
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;
}
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 = E2AP_PDU_PR_initiatingMessage;
ASN_STRUCT_FREE(asn_DEF_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 = E2AP_PDU_PR_successfulOutcome ;
}
else{
e2ap_pdu_obj->choice.unsuccessfulOutcome = unsuccessMsg;
e2ap_pdu_obj->present = E2AP_PDU_PR_unsuccessfulOutcome ;
}
//xer_fprint(stdout, &asn_DEF_E2AP_PDU, e2ap_pdu_obj);
int ret_constr = asn_check_constraints(&asn_DEF_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_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(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));
// }
//RICcontrolAcknowledge_t * ric_acknowledge = &(successMsg->value.choice.RICcontrolAcknowledge);
//ric_acknowledge->protocolIEs.list.count = 0;
ie_index = 0;
RICcontrolAcknowledge_IEs_t *ies_ricreq = &IE_array[ie_index];
ies_ricreq->criticality = Criticality_reject;
ies_ricreq->id = ProtocolIE_ID_id_RICrequestID;
ies_ricreq->value.present = RICcontrolAcknowledge_IEs__value_PR_RICrequestID;
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;
RICcontrolAcknowledge_IEs_t *ies_ranfunc = &IE_array[ie_index];
ies_ranfunc->criticality = Criticality_reject;
ies_ranfunc->id = ProtocolIE_ID_id_RANfunctionID;
ies_ranfunc->value.present = RICcontrolAcknowledge_IEs__value_PR_RANfunctionID;
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;
// RICcontrolAcknowledge_IEs_t *ies_riccallprocessid = &IE_array[ie_index];
// ies_riccallprocessid->criticality = Criticality_reject;
// ies_riccallprocessid->id = ProtocolIE_ID_id_RICcallProcessID;
// ies_riccallprocessid->value.present = 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;
RICcontrolAcknowledge_IEs_t *ies_ric_cause = &IE_array[ie_index];
ies_ric_cause->criticality = Criticality_reject;
ies_ric_cause->id = ProtocolIE_ID_id_RICcontrolStatus;
ies_ric_cause->value.present = 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(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));
// }
//RICcontrolFailure_t * ric_failure = &(unsuccessMsg->value.choice.RICcontrolFailure);
//ric_failure->protocolIEs.list.count = 0;
ie_index = 0;
RICcontrolFailure_IEs_t *ies_ricreq = &IE_failure_array[ie_index];
ies_ricreq->criticality = Criticality_reject;
ies_ricreq->id = ProtocolIE_ID_id_RICrequestID;
ies_ricreq->value.present = RICcontrolFailure_IEs__value_PR_RICrequestID;
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;
RICcontrolFailure_IEs_t *ies_ranfunc = &IE_failure_array[ie_index];
ies_ranfunc->criticality = Criticality_reject;
ies_ranfunc->id = ProtocolIE_ID_id_RANfunctionID;
ies_ranfunc->value.present = RICcontrolFailure_IEs__value_PR_RANfunctionID;
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;
// RICcontrolFailure_IEs_t *ies_riccallprocessid = &IE_failure_array[i];
// ies_riccallprocessid->criticality = Criticality_reject;
// ies_riccallprocessid->id = ProtocolIE_ID_id_RICcallProcessID;
// ies_riccallprocessid->value.present = 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;
RICcontrolFailure_IEs_t *ies_ric_cause = &IE_failure_array[ie_index];
ies_ric_cause->criticality = Criticality_ignore;
ies_ric_cause->id = ProtocolIE_ID_id_Cause;
ies_ric_cause->value.present = RICcontrolFailure_IEs__value_PR_Cause;
Cause_t * ric_cause = &(ies_ric_cause->value.choice.Cause);
ric_cause->present = (Cause_PR)dinput.cause;
switch(dinput.cause){
case Cause_PR_ricService:
ric_cause->choice.ricService = dinput.sub_cause;
break;
case Cause_PR_transport:
ric_cause->choice.transport = dinput.sub_cause;
break;
case Cause_PR_protocol:
ric_cause->choice.protocol= dinput.sub_cause;
break;
case Cause_PR_misc:
ric_cause->choice.misc = dinput.sub_cause;
break;
case Cause_PR_ricRequest:
ric_cause->choice.ricRequest = 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(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++) {
RICcontrolAcknowledge_IEs_t *memb_ptr = success_msg->value.choice.RICcontrolAcknowledge.protocolIEs.list.array[edx];
switch(memb_ptr->id)
{
case (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 (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 (ProtocolIE_ID_id_RANfunctionID):
dout.func_id = memb_ptr->value.choice.RANfunctionID;
break;
case (ProtocolIE_ID_id_Cause):
dout.control_status = memb_ptr->value.choice.RICcontrolStatus;
break;
}
}
return true;
}
bool ric_control_response:: get_fields(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++) {
RICcontrolFailure_IEs_t *memb_ptr = unsuccess_msg->value.choice.RICcontrolFailure.protocolIEs.list.array[edx];
switch(memb_ptr->id)
{
case (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 (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 (ProtocolIE_ID_id_RANfunctionID):
dout.func_id = memb_ptr->value.choice.RANfunctionID;
break;
case (ProtocolIE_ID_id_Cause):
dout.cause = memb_ptr->value.choice.Cause.present;
switch(dout.cause){
case Cause_PR_ricService :
dout.sub_cause = memb_ptr->value.choice.Cause.choice.ricService;
break;
case Cause_PR_transport :
dout.sub_cause = memb_ptr->value.choice.Cause.choice.transport;
break;
case Cause_PR_protocol :
dout.sub_cause = memb_ptr->value.choice.Cause.choice.protocol;
break;
case Cause_PR_misc :
dout.sub_cause = memb_ptr->value.choice.Cause.choice.misc;
break;
case Cause_PR_ricRequest :
dout.sub_cause = memb_ptr->value.choice.Cause.choice.ricRequest;
break;
default:
dout.sub_cause = -1;
break;
}
default:
break;
}
}
return true;
}

View File

@@ -0,0 +1,79 @@
/*
==================================================================================
Copyright (c) 2019-2020 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 <iostream>
#include <errno.h>
#include <mdclog/mdclog.h>
#include <sstream>
#include <E2AP-PDU.h>
#include <SuccessfulOutcome.h>
#include <UnsuccessfulOutcome.h>
#include <RICcontrolAcknowledge.h>
#include <RICcontrolFailure.h>
#include <ProtocolIE-Field.h>
#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(SuccessfulOutcome_t *, ric_control_helper &);
bool get_fields(SuccessfulOutcome_t *, ric_control_helper &);
bool set_fields(UnsuccessfulOutcome_t *, ric_control_helper &);
bool get_fields(UnsuccessfulOutcome_t *, ric_control_helper &);
std::string get_error(void) const {return error_string ; };
private:
E2AP_PDU_t * e2ap_pdu_obj;
SuccessfulOutcome_t * successMsg;
UnsuccessfulOutcome_t * unsuccessMsg;
RICcontrolAcknowledge_IEs_t *IE_array;
RICcontrolFailure_IEs_t *IE_failure_array;
std::string error_string;
char errbuf[128];
size_t errbuf_len = 128;
};
#endif /* E2AP_RIC_CONTROL_RESPONSE_H_ */

View File

@@ -0,0 +1,283 @@
/*
==================================================================================
Copyright (c) 2019-2020 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 = (E2AP_PDU_t * )calloc(1, sizeof(E2AP_PDU_t));
assert(e2ap_pdu_obj != 0);
initMsg = 0;
initMsg = (InitiatingMessage_t * )calloc(1, sizeof(InitiatingMessage_t));
assert(initMsg != 0);
IE_array = 0;
IE_array = (RICindication_IEs_t *)calloc(NUM_INDICATION_IES, sizeof(RICindication_IEs_t));
assert(IE_array != 0);
e2ap_pdu_obj->present = 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");
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_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 = ProcedureCode_id_RICindication;
initMsg->criticality = Criticality_ignore;
initMsg->value.present = 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_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_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(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;
}
RICindication_t * ric_indication = &(initMsg->value.choice.RICindication);
ric_indication->protocolIEs.list.count = 0;
ie_index = 0;
RICindication_IEs_t *ies_ricreq = &IE_array[ie_index];
ies_ricreq->criticality = Criticality_reject;
ies_ricreq->id = ProtocolIE_ID_id_RICrequestID;
ies_ricreq->value.present = RICindication_IEs__value_PR_RICrequestID;
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;
RICindication_IEs_t *ies_ranfunc = &IE_array[ie_index];
ies_ranfunc->criticality = Criticality_reject;
ies_ranfunc->id = ProtocolIE_ID_id_RANfunctionID;
ies_ranfunc->value.present = RICindication_IEs__value_PR_RANfunctionID;
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;
RICindication_IEs_t *ies_actid = &IE_array[ie_index];
ies_actid->criticality = Criticality_reject;
ies_actid->id = ProtocolIE_ID_id_RICactionID;
ies_actid->value.present = RICindication_IEs__value_PR_RICactionID;
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;
RICindication_IEs_t *ies_ricsn = &IE_array[ie_index];
ies_ricsn->criticality = Criticality_reject;
ies_ricsn->id = ProtocolIE_ID_id_RICindicationSN;
ies_ricsn->value.present = RICindication_IEs__value_PR_RICindicationSN;
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;
RICindication_IEs_t *ies_indtyp = &IE_array[ie_index];
ies_indtyp->criticality = Criticality_reject;
ies_indtyp->id = ProtocolIE_ID_id_RICindicationType;
ies_indtyp->value.present = RICindication_IEs__value_PR_RICindicationType;
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;
RICindication_IEs_t *ies_richead = &IE_array[ie_index];
ies_richead->criticality = Criticality_reject;
ies_richead->id = ProtocolIE_ID_id_RICindicationHeader;
ies_richead->value.present = RICindication_IEs__value_PR_RICindicationHeader;
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;
RICindication_IEs_t *ies_indmsg = &IE_array[ie_index];
ies_indmsg->criticality = Criticality_reject;
ies_indmsg->id = ProtocolIE_ID_id_RICindicationMessage;
ies_indmsg->value.present = RICindication_IEs__value_PR_RICindicationMessage;
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;
RICindication_IEs_t *ies_ind_callprocessid = &IE_array[ie_index];
ies_ind_callprocessid->criticality = Criticality_reject;
ies_ind_callprocessid->id = ProtocolIE_ID_id_RICcallProcessID;
ies_ind_callprocessid->value.present = RICindication_IEs__value_PR_RICcallProcessID;
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(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++) {
RICindication_IEs_t *memb_ptr = init_msg->value.choice.RICindication.protocolIEs.list.array[edx];
switch(memb_ptr->id)
{
case (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 (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 (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 (ProtocolIE_ID_id_RANfunctionID):
dout.func_id = memb_ptr->value.choice.RANfunctionID;
break;
case (ProtocolIE_ID_id_RICindicationSN):
dout.indication_sn = memb_ptr->value.choice.RICindicationSN;
break;
case (ProtocolIE_ID_id_RICindicationType):
dout.indication_type = memb_ptr->value.choice.RICindicationType;
break;
case (ProtocolIE_ID_id_RICactionID):
dout.action_id = memb_ptr->value.choice.RICactionID;
break;
case (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;
}
InitiatingMessage_t * ric_indication::get_message(void) {
return initMsg;
}

View File

@@ -0,0 +1,67 @@
/*
==================================================================================
Copyright (c) 2019-2020 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 <iostream>
#include <errno.h>
#include <mdclog/mdclog.h>
#include <sstream>
#include <E2AP-PDU.h>
#include <InitiatingMessage.h>
#include <RICindication.h>
#include <ProtocolIE-Field.h>
#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 &);
InitiatingMessage_t * get_message (void) ;
bool set_fields(InitiatingMessage_t *, ric_indication_helper &);
bool get_fields(InitiatingMessage_t *, ric_indication_helper &);
std::string get_error(void) const {return error_string ; };
private:
E2AP_PDU_t * e2ap_pdu_obj;
InitiatingMessage_t *initMsg;
RICindication_IEs_t *IE_array;
std::string error_string;
char errbuf[128];
size_t errbuf_len = 128;
};
#endif /* E2AP_RIC_INDICATION_H_ */

View File

@@ -0,0 +1,47 @@
/*
==================================================================================
Copyright (c) 2019-2020 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

View File

@@ -0,0 +1,49 @@
/*
==================================================================================
Copyright (c) 2019-2020 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 <cstddef>
/* 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

View File

@@ -0,0 +1,181 @@
/*
==================================================================================
Copyright (c) 2019-2020 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 <vector>
#include <memory>
/* 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<ActionResponse>;
subscription_response_helper(void){
_action_admitted_ref = std::make_unique<action_t>();
_action_not_admitted_ref = std::make_unique<action_t>();
};
// copy operator
subscription_response_helper(const subscription_response_helper &he ){
_action_admitted_ref = std::make_unique<action_t>();
_action_not_admitted_ref = std::make_unique<action_t>();
_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_t>();
_action_not_admitted_ref = std::make_unique<action_t>();
_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_t> _action_admitted_ref;
std::unique_ptr<action_t> _action_not_admitted_ref;
};
#endif

View File

@@ -0,0 +1,180 @@
/*
==================================================================================
Copyright (c) 2019-2020 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 = (E2AP_PDU_t * )calloc(1, sizeof(E2AP_PDU_t));
assert(e2ap_pdu_obj != 0);
initMsg = (InitiatingMessage_t * )calloc(1, sizeof(InitiatingMessage_t));
assert(initMsg != 0);
IE_array = (RICsubscriptionDeleteRequest_IEs_t *)calloc(NUM_SUBSCRIPTION_DELETE_IES, sizeof(RICsubscriptionDeleteRequest_IEs_t));
assert(IE_array != 0);
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");
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_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 = E2AP_PDU_PR_initiatingMessage;
set_fields( dinput);
initMsg->procedureCode = ProcedureCode_id_RICsubscriptionDelete;
initMsg->criticality = Criticality_reject;
initMsg->value.present = InitiatingMessage__value_PR_RICsubscriptionDeleteRequest;
//xer_fprint(stdout, &asn_DEF_E2AP_PDU, e2ap_pdu_obj);
int ret_constr = asn_check_constraints(&asn_DEF_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_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;
RICsubscriptionDeleteRequest_IEs_t *ies_ricreq = &IE_array[ie_index];
ies_ricreq->criticality = Criticality_reject;
ies_ricreq->id = ProtocolIE_ID_id_RICrequestID;
ies_ricreq->value.present = RICsubscriptionDeleteRequest_IEs__value_PR_RICrequestID;
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;
RICsubscriptionDeleteRequest_IEs_t *ies_ranfunc = &IE_array[ie_index];
ies_ranfunc->criticality = Criticality_reject;
ies_ranfunc->id = ProtocolIE_ID_id_RANfunctionID;
ies_ranfunc->value.present = RICsubscriptionDeleteRequest_IEs__value_PR_RANfunctionID;
RANfunctionID_t *ranfunction_ie = &ies_ranfunc->value.choice.RANfunctionID;
*ranfunction_ie = helper.get_function_id();
return true;
};
bool subscription_delete:: get_fields(InitiatingMessage_t * init_msg, subscription_helper & dout)
{
if (init_msg == 0){
error_string = "Invalid reference for initiating message for get string";
return false;
}
RICrequestID_t *requestid;
RANfunctionID_t * ranfunctionid;
for(int edx = 0; edx < init_msg->value.choice.RICsubscriptionDeleteRequest.protocolIEs.list.count; edx++) {
RICsubscriptionDeleteRequest_IEs_t *memb_ptr = init_msg->value.choice.RICsubscriptionDeleteRequest.protocolIEs.list.array[edx];
switch(memb_ptr->id)
{
case (ProtocolIE_ID_id_RICrequestID):
requestid = &memb_ptr->value.choice.RICrequestID;
//dout.set_request(requestid->ricRequestorID, requestid->ricRequestSequenceNumber);
break;
case (ProtocolIE_ID_id_RANfunctionID):
ranfunctionid = &memb_ptr->value.choice.RANfunctionID;
dout.set_function_id(*ranfunctionid);
break;
}
//asn_fprint(stdout, &asn_DEF_E2AP_PDU, e2pdu);
}
return true;
}

View File

@@ -0,0 +1,67 @@
/*
==================================================================================
Copyright (c) 2019-2020 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 <mdclog/mdclog.h>
#include <vector>
#include <sstream>
#include <mdclog/mdclog.h>
#include <asn_application.h>
#include <E2AP-PDU.h>
#include <InitiatingMessage.h>
#include <RICsubscriptionDeleteRequest.h>
#include <ProtocolIE-Field.h>
#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(InitiatingMessage_t *, subscription_helper &);
std::string get_error(void) const {
return error_string ;
}
private:
InitiatingMessage_t *initMsg;
E2AP_PDU_t * e2ap_pdu_obj;
RICsubscriptionDeleteRequest_IEs_t * IE_array;
char errbuf[128];
size_t errbuf_len = 128;
std::string _name;
std::string error_string;
};
#endif

View File

@@ -0,0 +1,292 @@
/*
==================================================================================
Copyright (c) 2019-2020 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 = (E2AP_PDU_t *)calloc(1, sizeof(E2AP_PDU_t));
assert(e2ap_pdu_obj != 0);
successMsg = 0;
successMsg = (SuccessfulOutcome_t *)calloc(1, sizeof(SuccessfulOutcome_t));
assert(successMsg != 0);
unsuccessMsg = 0;
unsuccessMsg = (UnsuccessfulOutcome_t *)calloc(1, sizeof(UnsuccessfulOutcome_t));
assert(unsuccessMsg != 0);
IE_array = 0;
IE_array = (RICsubscriptionDeleteResponse_IEs_t *)calloc(NUM_SUBSCRIPTION_DELETE_RESPONSE_IES, sizeof(RICsubscriptionDeleteResponse_IEs_t));
assert(IE_array != 0);
IE_Failure_array = 0;
IE_Failure_array = (RICsubscriptionDeleteFailure_IEs_t *)calloc(NUM_SUBSCRIPTION_DELETE_FAILURE_IES, sizeof(RICsubscriptionDeleteFailure_IEs_t));
assert(IE_Failure_array != 0);
};
// Clear assigned protocolIE list from RIC indication IE container
subscription_delete_response::~subscription_delete_response(void){
mdclog_write(MDCLOG_DEBUG, "Freeing subscription delete response memory");
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;
}
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_SuccessfulOutcome, successMsg);
ASN_STRUCT_FREE(asn_DEF_UnsuccessfulOutcome, unsuccessMsg);
e2ap_pdu_obj->choice.successfulOutcome = NULL;
e2ap_pdu_obj->choice.unsuccessfulOutcome = NULL;
ASN_STRUCT_FREE(asn_DEF_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 = E2AP_PDU_PR_successfulOutcome;
e2ap_pdu_obj->choice.successfulOutcome = successMsg;
}
else{
res = set_fields(unsuccessMsg, dinput);
if(! res){
return false;
}
e2ap_pdu_obj->present = E2AP_PDU_PR_unsuccessfulOutcome;
e2ap_pdu_obj->choice.unsuccessfulOutcome = unsuccessMsg;
}
int ret_constr = asn_check_constraints(&asn_DEF_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_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(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 = ProcedureCode_id_RICsubscriptionDelete;
success->criticality = Criticality_reject;
success->value.present = SuccessfulOutcome__value_PR_RICsubscriptionDeleteResponse;
RICsubscriptionDeleteResponse_t * subscription_delete_response = &(success->value.choice.RICsubscriptionDeleteResponse);
subscription_delete_response->protocolIEs.list.count = 0;
ie_index = 0;
RICsubscriptionDeleteResponse_IEs_t *ies_ricreq = &IE_array[ie_index];
ies_ricreq->criticality = Criticality_reject;
ies_ricreq->id = ProtocolIE_ID_id_RICrequestID;
ies_ricreq->value.present = RICsubscriptionDeleteResponse_IEs__value_PR_RICrequestID;
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;
RICsubscriptionDeleteResponse_IEs_t *ies_ranfunc = &IE_array[ie_index];
ies_ranfunc->criticality = Criticality_reject;
ies_ranfunc->id = ProtocolIE_ID_id_RANfunctionID;
ies_ranfunc->value.present = RICsubscriptionDeleteResponse_IEs__value_PR_RANfunctionID;
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(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;
}
RICrequestID_t *requestid;
RANfunctionID_t * ranfunctionid;
for(int edx = 0; edx < success_msg->value.choice.RICsubscriptionDeleteResponse.protocolIEs.list.count; edx++) {
RICsubscriptionDeleteResponse_IEs_t *memb_ptr = success_msg->value.choice.RICsubscriptionDeleteResponse.protocolIEs.list.array[edx];
switch(memb_ptr->id)
{
case (ProtocolIE_ID_id_RICrequestID):
requestid = &memb_ptr->value.choice.RICrequestID;
//dout.set_request(requestid->ricRequestorID, requestid->ricRequestSequenceNumber);
break;
case (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(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 = ProcedureCode_id_RICsubscriptionDelete;
unsuccess->criticality = Criticality_reject;
unsuccess->value.present = UnsuccessfulOutcome__value_PR_RICsubscriptionDeleteFailure;
RICsubscriptionDeleteFailure_t * ric_subscription_failure = &(unsuccess->value.choice.RICsubscriptionDeleteFailure);
ric_subscription_failure->protocolIEs.list.count = 0;
ie_index = 0;
RICsubscriptionDeleteFailure_IEs_t *ies_ricreq = &IE_Failure_array[ie_index];
ies_ricreq->criticality = Criticality_reject;
ies_ricreq->id = ProtocolIE_ID_id_RICrequestID;
ies_ricreq->value.present = RICsubscriptionDeleteFailure_IEs__value_PR_RICrequestID;
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;
RICsubscriptionDeleteFailure_IEs_t *ies_ranfunc = &IE_Failure_array[ie_index];
ies_ranfunc->criticality = Criticality_reject;
ies_ranfunc->id = ProtocolIE_ID_id_RANfunctionID;
ies_ranfunc->value.present = RICsubscriptionDeleteFailure_IEs__value_PR_RANfunctionID;
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(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;
}
RICrequestID_t *requestid;
RANfunctionID_t * ranfunctionid;
for(int edx = 0; edx < unsuccess_msg->value.choice.RICsubscriptionDeleteFailure.protocolIEs.list.count; edx++) {
RICsubscriptionDeleteFailure_IEs_t *memb_ptr = unsuccess_msg->value.choice.RICsubscriptionDeleteFailure.protocolIEs.list.array[edx];
switch(memb_ptr->id)
{
case (ProtocolIE_ID_id_RICrequestID):
requestid = &memb_ptr->value.choice.RICrequestID;
//dout.set_request(requestid->ricRequestorID, requestid->ricRequestSequenceNumber);
break;
case (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);
}

View File

@@ -0,0 +1,79 @@
/*
==================================================================================
Copyright (c) 2019-2020 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 <mdclog/mdclog.h>
#include <vector>
#include <iostream>
#include <sstream>
#include <mdclog/mdclog.h>
#include <asn_application.h>
#include <E2AP-PDU.h>
#include <SuccessfulOutcome.h>
#include <UnsuccessfulOutcome.h>
#include <RICsubscriptionDeleteResponse.h>
#include <RICsubscriptionDeleteFailure.h>
#include <ProtocolIE-Field.h>
#include <ProcedureCode.h>
#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(SuccessfulOutcome_t *, subscription_response_helper &);
bool get_fields(SuccessfulOutcome_t *, subscription_response_helper &);
bool set_fields(UnsuccessfulOutcome_t *, subscription_response_helper &);
bool get_fields(UnsuccessfulOutcome_t *, subscription_response_helper &);
std::string get_error_string(void) const {
return error_string;
}
private:
E2AP_PDU_t * e2ap_pdu_obj;
SuccessfulOutcome_t * successMsg;
UnsuccessfulOutcome_t * unsuccessMsg;
RICsubscriptionDeleteResponse_IEs_t *IE_array;
RICsubscriptionDeleteFailure_IEs_t *IE_Failure_array;
char errbuf[128];
size_t errbuf_len = 128;
std::string error_string;
};
#endif

View File

@@ -0,0 +1,181 @@
/*
==================================================================================
Copyright (c) 2019-2020 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 <iostream>
#include <vector>
#include <memory>
#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){};
Action(int id, int type, const void *def, size_t def_size, int next_action): _is_def(false), _is_subs_act(false), _id(id), _type(type){
_is_def = true;
_action_definition.set_ref(def);
_action_definition.set_size(def_size);
_is_subs_act = true;
_next_action = next_action;
};
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;
};
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, _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<Action>;
subscription_helper(){
_action_ref = std::make_unique<action_t>();
};
action_t * get_list() const {return _action_ref.get();};
void clear(void){
_action_ref.get()->clear();
}
void set_request(int id){
_req_id = id;
};
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, const void *action_def, size_t size, int next_action){
Action a (id, type, action_def, size, next_action);
_action_ref.get()->push_back(a);
};
int get_request_id(void) const{
return _req_id;
}
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 <<"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_t> _action_ref;
int curr_index;
int _req_id, _func_id;
octet_helper _event_def;
};
#endif

View File

@@ -0,0 +1,306 @@
/*
==================================================================================
Copyright (c) 2019-2020 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 = (E2AP_PDU_t * )calloc(1, sizeof(E2AP_PDU_t));
assert(e2ap_pdu_obj != 0);
initMsg = 0;
initMsg = (InitiatingMessage_t * )calloc(1, sizeof(InitiatingMessage_t));
assert(initMsg != 0);
IE_array = 0;
IE_array = (RICsubscriptionRequest_IEs_t *)calloc(NUM_SUBSCRIPTION_REQUEST_IES, sizeof(RICsubscriptionRequest_IEs_t));
assert(IE_array != 0);
action_array = 0;
action_array = (RICaction_ToBeSetup_ItemIEs_t *)calloc(INITIAL_REQUEST_LIST_SIZE, sizeof(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 RICsubsequentAction *)calloc(1, sizeof(struct RICsubsequentAction));
assert(action_array[i].value.choice.RICaction_ToBeSetup_Item.ricSubsequentAction != 0);
}
e2ap_pdu_obj->choice.initiatingMessage = initMsg;
e2ap_pdu_obj->present = 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");;
// Sequence of actions to be admitted causes special heart-ache. Free ric subscription element manually and reset the ie pointer
RICsubscriptionDetails_t * ricsubscription_ie = &(IE_array[2].value.choice.RICsubscriptionDetails);
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);
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_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 = ProcedureCode_id_RICsubscription;
initMsg->criticality = Criticality_ignore;
initMsg->value.present = InitiatingMessage__value_PR_RICsubscriptionRequest;
res = set_fields(initMsg, dinput);
if (!res){
return false;
}
int ret_constr = asn_check_constraints(&asn_DEF_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_E2AP_PDU, e2ap_pdu_obj);
asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_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( 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;
}
RICsubscriptionRequest_t * ric_subscription = &(init_msg->value.choice.RICsubscriptionRequest);
ric_subscription->protocolIEs.list.count = 0;
ie_index = 0;
RICsubscriptionRequest_IEs_t *ies_ricreq = &IE_array[ie_index];
ies_ricreq->criticality = Criticality_reject;
ies_ricreq->id = ProtocolIE_ID_id_RICrequestID;
ies_ricreq->value.present = RICsubscriptionRequest_IEs__value_PR_RICrequestID;
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;
RICsubscriptionRequest_IEs_t *ies_ranfunc = &IE_array[ie_index];
ies_ranfunc->criticality = Criticality_reject;
ies_ranfunc->id = ProtocolIE_ID_id_RANfunctionID;
ies_ranfunc->value.present = RICsubscriptionRequest_IEs__value_PR_RANfunctionID;
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;
RICsubscriptionRequest_IEs_t *ies_actid = &IE_array[ie_index];
ies_actid->criticality = Criticality_reject;
ies_actid->id = ProtocolIE_ID_id_RICsubscriptionDetails;
ies_actid->value.present = RICsubscriptionRequest_IEs__value_PR_RICsubscriptionDetails;
RICsubscriptionDetails_t *ricsubscription_ie = &ies_actid->value.choice.RICsubscriptionDetails;
ricsubscription_ie->ricEventTriggerDefinition.buf = (uint8_t *) helper.get_event_def();
ricsubscription_ie->ricEventTriggerDefinition.size = helper.get_event_def_size();
std::vector<Action> * 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 = (RICaction_ToBeSetup_ItemIEs_t *)calloc(action_array_size, sizeof(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 RICsubsequentAction *)calloc(1, sizeof(struct 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 = Criticality_ignore;
action_array[i].id = ProtocolIE_ID_id_RICaction_ToBeSetup_Item ;
action_array[i].value.present = 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();
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(InitiatingMessage_t * init_msg, subscription_helper & dout)
{
if (init_msg == 0){
error_string = "Error. Invalid reference when getting fields from subscription request";
return false;
}
RICrequestID_t *requestid;
RANfunctionID_t * ranfunctionid;
RICsubscriptionDetails_t * ricsubscription;
for(int edx = 0; edx < init_msg->value.choice.RICsubscriptionRequest.protocolIEs.list.count; edx++) {
RICsubscriptionRequest_IEs_t *memb_ptr = init_msg->value.choice.RICsubscriptionRequest.protocolIEs.list.array[edx];
switch(memb_ptr->id)
{
case (ProtocolIE_ID_id_RICrequestID):
requestid = &memb_ptr->value.choice.RICrequestID;
//dout.set_request(requestid->ricRequestorID, requestid->ricRequestSequenceNumber);
break;
case (ProtocolIE_ID_id_RANfunctionID):
ranfunctionid = &memb_ptr->value.choice.RANfunctionID;
dout.set_function_id(*ranfunctionid);
break;
case (ProtocolIE_ID_id_RICsubscriptionDetails):
ricsubscription = &memb_ptr->value.choice.RICsubscriptionDetails;
dout.set_event_def(ricsubscription->ricEventTriggerDefinition.buf, ricsubscription->ricEventTriggerDefinition.size);
for(int index = 0; index < ricsubscription->ricAction_ToBeSetup_List.list.count; index ++){
RICaction_ToBeSetup_ItemIEs_t * item = (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
}
};
break;
}
}
//asn_fprint(stdout, &asn_DEF_E2AP_PDU, e2pdu);
return true;
};

View File

@@ -0,0 +1,73 @@
/*
==================================================================================
Copyright (c) 2019-2020 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 <mdclog/mdclog.h>
#include <vector>
#include <sstream>
#include <asn_application.h>
#include <E2AP-PDU.h>
#include <InitiatingMessage.h>
#include <RICsubscriptionRequest.h>
#include <RICsubscriptionRequest.h>
#include <ProtocolIE-Field.h>
#include <ProtocolIE-SingleContainer.h>
#include <RICactions-ToBeSetup-List.h>
#include <RICsubsequentAction.h>
#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(InitiatingMessage_t *, subscription_helper &);
bool get_fields(InitiatingMessage_t *, subscription_helper &);
std::string get_error(void) const{
return error_string;
}
private:
InitiatingMessage_t *initMsg;
E2AP_PDU_t * e2ap_pdu_obj;
RICsubscriptionRequest_IEs_t * IE_array;
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

View File

@@ -0,0 +1,583 @@
/*
==================================================================================
Copyright (c) 2019-2020 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 = (E2AP_PDU_t *)calloc(1, sizeof(E2AP_PDU_t));
assert(e2ap_pdu_obj != 0);
successMsg = 0;
successMsg = (SuccessfulOutcome_t *)calloc(1, sizeof(SuccessfulOutcome_t));
assert(successMsg != 0);
unsuccessMsg = 0;
unsuccessMsg = (UnsuccessfulOutcome_t *)calloc(1, sizeof(UnsuccessfulOutcome_t));
assert(unsuccessMsg != 0);
IE_array = 0;
IE_array = (RICsubscriptionResponse_IEs_t *)calloc(NUM_SUBSCRIPTION_RESPONSE_IES, sizeof(RICsubscriptionResponse_IEs_t));
assert(IE_array != 0);
IE_Failure_array = 0;
IE_Failure_array = (RICsubscriptionFailure_IEs_t *)calloc(NUM_SUBSCRIPTION_FAILURE_IES, sizeof(RICsubscriptionFailure_IEs_t));
assert(IE_Failure_array != 0);
ie_admitted_list = 0;
ie_admitted_list = (RICaction_Admitted_ItemIEs_t *)calloc(INITIAL_RESPONSE_LIST_SIZE, sizeof(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 = (RICaction_NotAdmitted_ItemIEs_t *)calloc(INITIAL_RESPONSE_LIST_SIZE, sizeof(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");
RICaction_Admitted_List_t * response_admitted_list = (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;
}
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;
}
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;
}
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;
}
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_SuccessfulOutcome, successMsg);
ASN_STRUCT_FREE(asn_DEF_UnsuccessfulOutcome, unsuccessMsg);
e2ap_pdu_obj->choice.initiatingMessage = NULL;
e2ap_pdu_obj->present = E2AP_PDU_PR_NOTHING;
ASN_STRUCT_FREE(asn_DEF_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 = E2AP_PDU_PR_successfulOutcome;
e2ap_pdu_obj->choice.successfulOutcome = successMsg;
successMsg->procedureCode = ProcedureCode_id_RICsubscription;
successMsg->criticality = Criticality_reject;
successMsg->value.present = SuccessfulOutcome__value_PR_RICsubscriptionResponse;
}
else{
set_fields_unsuccess(dinput);
e2ap_pdu_obj->present = E2AP_PDU_PR_unsuccessfulOutcome;
e2ap_pdu_obj->choice.unsuccessfulOutcome = unsuccessMsg;
unsuccessMsg->procedureCode = ProcedureCode_id_RICsubscription;
unsuccessMsg->criticality = Criticality_reject;
unsuccessMsg->value.present = UnsuccessfulOutcome__value_PR_RICsubscriptionFailure;
}
//xer_fprint(stdout, &asn_DEF_E2AP_PDU, e2ap_pdu_obj);
int ret_constr = asn_check_constraints(&asn_DEF_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_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_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;
RICsubscriptionResponse_t * subscription_response = &(successMsg->value.choice.RICsubscriptionResponse);
//reset list count ..
subscription_response->protocolIEs.list.count = 0;
ie_index = 0;
RICsubscriptionResponse_IEs_t *ies_ricreq = &IE_array[ie_index];
ies_ricreq->criticality = Criticality_reject;
ies_ricreq->id = ProtocolIE_ID_id_RICrequestID;
ies_ricreq->value.present = RICsubscriptionResponse_IEs__value_PR_RICrequestID;
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;
RICsubscriptionResponse_IEs_t *ies_ranfunc = &IE_array[ie_index];
ies_ranfunc->criticality = Criticality_reject;
ies_ranfunc->id = ProtocolIE_ID_id_RANfunctionID;
ies_ranfunc->value.present = RICsubscriptionResponse_IEs__value_PR_RANfunctionID;
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;
RICsubscriptionResponse_IEs_t *ies_admitted_actid = &IE_array[ie_index];
ies_admitted_actid->criticality = Criticality_reject;
ies_admitted_actid->id = ProtocolIE_ID_id_RICactions_Admitted;
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<ActionResponse> * ref_admitted_action_array = helper.get_admitted_list();
if(ref_admitted_action_array->size() == 0){
ies_admitted_actid->value.present = RICsubscriptionResponse_IEs__value_PR_NOTHING;
}
else{
ies_admitted_actid->value.present = 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 = (RICaction_Admitted_ItemIEs_t *)calloc(ie_admitted_list_size, sizeof(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 = Criticality_ignore;
ie_admitted_list[i].id = ProtocolIE_ID_id_RICaction_Admitted_Item ;
ie_admitted_list[i].value.present = 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<ActionResponse> * ref_notadmitted_action_array = helper.get_not_admitted_list();
if (ref_notadmitted_action_array->size() > 0){
RICsubscriptionResponse_IEs_t *ies_notadmitted_actid = &IE_array[ie_index];
ies_notadmitted_actid->criticality = Criticality_reject;
ies_notadmitted_actid->id = ProtocolIE_ID_id_RICactions_NotAdmitted;
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 = 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 = (RICaction_NotAdmitted_ItemIEs_t *)calloc(ie_not_admitted_list_size, sizeof(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 = Criticality_ignore;
ie_not_admitted_list[i].id = ProtocolIE_ID_id_RICaction_NotAdmitted_Item ;
ie_not_admitted_list[i].value.present = 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 Cause_PR_ricService:
ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.cause.choice.ricService = (*ref_notadmitted_action_array)[i].get_sub_cause();
break;
case Cause_PR_transport:
ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.cause.choice.transport = (*ref_notadmitted_action_array)[i].get_sub_cause();
break;
case Cause_PR_protocol:
ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.cause.choice.protocol= (*ref_notadmitted_action_array)[i].get_sub_cause();
break;
case Cause_PR_misc:
ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.cause.choice.misc = (*ref_notadmitted_action_array)[i].get_sub_cause();
break;
case Cause_PR_ricRequest:
ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.cause.choice.ricRequest = (*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.cause.present = (Cause_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(SuccessfulOutcome_t * success_msg, subscription_response_helper & dout)
{
assert(success_msg != NULL);
RICrequestID_t *requestid;
RANfunctionID_t * ranfunctionid;
RICaction_Admitted_List_t * ric_admitted_action_list;
RICaction_NotAdmitted_List_t * ric_not_admitted_action_list;
for(int edx = 0; edx < success_msg->value.choice.RICsubscriptionResponse.protocolIEs.list.count; edx++) {
RICsubscriptionResponse_IEs_t *memb_ptr = success_msg->value.choice.RICsubscriptionResponse.protocolIEs.list.array[edx];
switch(memb_ptr->id)
{
case (ProtocolIE_ID_id_RICrequestID):
requestid = &memb_ptr->value.choice.RICrequestID;
//dout.set_request(requestid->ricRequestorID, requestid->ricRequestSequenceNumber);
break;
case (ProtocolIE_ID_id_RANfunctionID):
ranfunctionid = &memb_ptr->value.choice.RANfunctionID;
dout.set_function_id(*ranfunctionid);
break;
case (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 ++){
RICaction_Admitted_ItemIEs_t * item = (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 (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 ++){
RICaction_NotAdmitted_ItemIEs_t * item = (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.cause.present;
int sub_cause;
switch(cause){
case Cause_PR_ricService :
sub_cause = item->value.choice.RICaction_NotAdmitted_Item.cause.choice.ricService;
break;
case Cause_PR_transport :
sub_cause = item->value.choice.RICaction_NotAdmitted_Item.cause.choice.transport;
break;
case Cause_PR_protocol :
sub_cause = item->value.choice.RICaction_NotAdmitted_Item.cause.choice.protocol;
break;
case Cause_PR_misc :
sub_cause = item->value.choice.RICaction_NotAdmitted_Item.cause.choice.misc;
break;
case Cause_PR_ricRequest :
sub_cause = item->value.choice.RICaction_NotAdmitted_Item.cause.choice.ricRequest;
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;
RICsubscriptionFailure_t * ric_subscription_failure = &(unsuccessMsg->value.choice.RICsubscriptionFailure);
// reset list count
ric_subscription_failure->protocolIEs.list.count = 0;
ie_index = 0;
RICsubscriptionFailure_IEs_t *ies_ricreq = &IE_Failure_array[ie_index];
ies_ricreq->criticality = Criticality_reject;
ies_ricreq->id = ProtocolIE_ID_id_RICrequestID;
ies_ricreq->value.present = RICsubscriptionFailure_IEs__value_PR_RICrequestID;
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;
RICsubscriptionFailure_IEs_t *ies_ranfunc = &IE_Failure_array[ie_index];
ies_ranfunc->criticality = Criticality_reject;
ies_ranfunc->id = ProtocolIE_ID_id_RANfunctionID;
ies_ranfunc->value.present = RICsubscriptionFailure_IEs__value_PR_RANfunctionID;
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;
RICsubscriptionFailure_IEs_t *ies_notadmitted_actid = &IE_Failure_array[ie_index];
ies_notadmitted_actid->criticality = Criticality_reject;
ies_notadmitted_actid->id = ProtocolIE_ID_id_RICactions_NotAdmitted;
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<ActionResponse> * ref_notadmitted_action_array = helper.get_not_admitted_list();
if(ref_notadmitted_action_array->size() == 0){
ies_notadmitted_actid->value.present = RICsubscriptionFailure_IEs__value_PR_NOTHING;
}
else{
ies_notadmitted_actid->value.present = 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 = (RICaction_NotAdmitted_ItemIEs_t *)calloc(ie_not_admitted_list_size, sizeof(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 = Criticality_ignore;
ie_not_admitted_list[i].id = ProtocolIE_ID_id_RICaction_NotAdmitted_Item ;
ie_not_admitted_list[i].value.present = 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 Cause_PR_ricService:
ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.cause.choice.ricService = (*ref_notadmitted_action_array)[i].get_sub_cause();
break;
case Cause_PR_transport:
ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.cause.choice.transport = (*ref_notadmitted_action_array)[i].get_sub_cause();
break;
case Cause_PR_protocol:
ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.cause.choice.protocol= (*ref_notadmitted_action_array)[i].get_sub_cause();
break;
case Cause_PR_misc:
ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.cause.choice.misc = (*ref_notadmitted_action_array)[i].get_sub_cause();
break;
case Cause_PR_ricRequest:
ie_not_admitted_list[i].value.choice.RICaction_NotAdmitted_Item.cause.choice.ricRequest = (*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.cause.present = (Cause_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;
// RICsubscriptionFailure_IEs_t *ies_criticality_diagnostics= &IE_Failure_array[i];
// ies_criticality_diagnostics->criticality = Criticality_ignore;
// ies_criticality_diagnostics->id = ProtocolIE_ID_id_CriticalityDiagnostics ;
// ies_criticality_diagnostics->value.present = RICsubscriptionFailure_IEs__value_PR_NOTHING;
}
void subscription_response:: get_fields(UnsuccessfulOutcome_t * unsuccess_msg, subscription_response_helper & dout)
{
assert(unsuccess_msg != NULL);
RICrequestID_t *requestid;
RANfunctionID_t * ranfunctionid;
RICaction_NotAdmitted_List_t * ric_not_admitted_action_list;
for(int edx = 0; edx < unsuccess_msg->value.choice.RICsubscriptionFailure.protocolIEs.list.count; edx++) {
RICsubscriptionFailure_IEs_t *memb_ptr = unsuccess_msg->value.choice.RICsubscriptionFailure.protocolIEs.list.array[edx];
switch(memb_ptr->id)
{
case (ProtocolIE_ID_id_RICrequestID):
requestid = &memb_ptr->value.choice.RICrequestID;
//dout.set_request(requestid->ricRequestorID, requestid->ricRequestSequenceNumber);
break;
case (ProtocolIE_ID_id_RANfunctionID):
ranfunctionid = &memb_ptr->value.choice.RANfunctionID;
dout.set_function_id(*ranfunctionid);
break;
case (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 ++){
RICaction_NotAdmitted_ItemIEs_t * item = (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.cause.present;
int sub_cause;
switch(cause){
case Cause_PR_ricService :
sub_cause = item->value.choice.RICaction_NotAdmitted_Item.cause.choice.ricService;
break;
case Cause_PR_transport :
sub_cause = item->value.choice.RICaction_NotAdmitted_Item.cause.choice.transport;
break;
case Cause_PR_protocol :
sub_cause = item->value.choice.RICaction_NotAdmitted_Item.cause.choice.protocol;
break;
case Cause_PR_misc :
sub_cause = item->value.choice.RICaction_NotAdmitted_Item.cause.choice.misc;
break;
case Cause_PR_ricRequest :
sub_cause = item->value.choice.RICaction_NotAdmitted_Item.cause.choice.ricRequest;
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);
}

View File

@@ -0,0 +1,81 @@
/*
==================================================================================
Copyright (c) 2019-2020 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 <mdclog/mdclog.h>
#include <vector>
#include <iostream>
#include <sstream>
#include <asn_application.h>
#include <E2AP-PDU.h>
#include <SuccessfulOutcome.h>
#include <UnsuccessfulOutcome.h>
#include <ProtocolIE-Field.h>
#include <ProtocolIE-SingleContainer.h>
#include <ProcedureCode.h>
#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(SuccessfulOutcome_t *, subscription_response_helper &);
void get_fields(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 &);
E2AP_PDU_t * e2ap_pdu_obj;
SuccessfulOutcome_t * successMsg;
UnsuccessfulOutcome_t * unsuccessMsg;
RICsubscriptionResponse_IEs_t *IE_array;
RICsubscriptionFailure_IEs_t *IE_Failure_array;
RICaction_Admitted_ItemIEs_t * ie_admitted_list;
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

View File

@@ -0,0 +1,195 @@
/*
==================================================================================
Copyright (c) 2019-2020 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.
==================================================================================
*/
/*
* e2sm_control.cc
*
* Created on: Apr 30, 2020
* Author: Shraboni Jana
*/
/* Classes to handle E2 service model based on e2sm-HelloWorld-v001.asn */
#include "e2sm_control.hpp"
//initialize
e2sm_control::e2sm_control(void){
memset(&head_fmt1, 0, sizeof(E2SM_HelloWorld_ControlHeader_Format1_t));
memset(&msg_fmt1, 0, sizeof(E2SM_HelloWorld_ControlMessage_Format1_t));
control_head = 0;
control_head = ( E2SM_HelloWorld_ControlHeader_t *)calloc(1, sizeof( E2SM_HelloWorld_ControlHeader_t));
assert(control_head != 0);
control_msg = 0;
control_msg = (E2SM_HelloWorld_ControlMessage_t*)calloc(1, sizeof(E2SM_HelloWorld_ControlMessage_t));
assert(control_msg !=0);
errbuf_len = 128;
};
e2sm_control::~e2sm_control(void){
mdclog_write(MDCLOG_DEBUG, "Freeing event trigger object memory");
control_head->choice.controlHeader_Format1 = 0;
control_msg->choice.controlMessage_Format1 = 0;
ASN_STRUCT_FREE(asn_DEF_E2SM_HelloWorld_ControlHeader, control_head);
ASN_STRUCT_FREE(asn_DEF_E2SM_HelloWorld_ControlMessage, control_msg);
};
bool e2sm_control::encode_control_header(unsigned char *buf, size_t *size, e2sm_control_helper &helper){
ASN_STRUCT_RESET(asn_DEF_E2SM_HelloWorld_ControlHeader, control_head);
bool res;
res = set_fields(control_head, helper);
if (!res){
return false;
}
int ret_constr = asn_check_constraints(&asn_DEF_E2SM_HelloWorld_ControlHeader, control_head, errbuf, &errbuf_len);
if(ret_constr){
error_string.assign(&errbuf[0], errbuf_len);
return false;
}
xer_fprint(stdout, &asn_DEF_E2SM_HelloWorld_ControlHeader, control_head);
asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2SM_HelloWorld_ControlHeader, control_head, 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_control::encode_control_message(unsigned char *buf, size_t *size, e2sm_control_helper &helper){
bool res;
res = set_fields(control_msg, helper);
if (!res){
return false;
}
int ret_constr = asn_check_constraints(&asn_DEF_E2SM_HelloWorld_ControlMessage, control_msg, errbuf, &errbuf_len);
if(ret_constr){
error_string.assign(&errbuf[0], errbuf_len);
return false;
}
xer_fprint(stdout, &asn_DEF_E2SM_HelloWorld_ControlMessage, control_msg);
asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2SM_HelloWorld_ControlMessage, control_msg, buf, *size);
if(retval.encoded == -1){
error_string.assign(strerror(errno));
return false;
}
else if (retval.encoded > *size){
std::stringstream ss;
ss <<"Error encoding action 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_control::set_fields(E2SM_HelloWorld_ControlHeader_t * ref_control_head, e2sm_control_helper & helper){
if(ref_control_head == 0){
error_string = "Invalid reference for Event Trigger Definition set fields";
return false;
}
ref_control_head->present = E2SM_HelloWorld_ControlHeader_PR_controlHeader_Format1;
head_fmt1.controlHeaderParam = helper.header;
ref_control_head->choice.controlHeader_Format1 = &head_fmt1;
return true;
};
bool e2sm_control::set_fields(E2SM_HelloWorld_ControlMessage_t * ref_control_msg, e2sm_control_helper & helper){
if(ref_control_msg == 0){
error_string = "Invalid reference for Event Action Definition set fields";
return false;
}
ref_control_msg->present = E2SM_HelloWorld_ControlMessage_PR_controlMessage_Format1;
msg_fmt1.controlMsgParam.buf = helper.message;
msg_fmt1.controlMsgParam.size = helper.message_len;
ref_control_msg->choice.controlMessage_Format1 = &msg_fmt1;
return true;
};
bool e2sm_control::get_fields(E2SM_HelloWorld_ControlHeader_t * ref_indictaion_header, e2sm_control_helper & helper){
if (ref_indictaion_header == 0){
error_string = "Invalid reference for Control Header get fields";
return false;
}
helper.header = ref_indictaion_header->choice.controlHeader_Format1->controlHeaderParam;
return true;
}
bool e2sm_control::get_fields(E2SM_HelloWorld_ControlMessage_t * ref_control_message, e2sm_control_helper & helper){
if (ref_control_message == 0){
error_string = "Invalid reference for Control Message get fields";
return false;
}
helper.message = ref_control_message->choice.controlMessage_Format1->controlMsgParam.buf;
helper.message_len = ref_control_message->choice.controlMessage_Format1->controlMsgParam.size;
return true;
}

View File

@@ -0,0 +1,73 @@
/*
==================================================================================
Copyright (c) 2019-2020 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.
==================================================================================
*/
/*
* e2sm_control.hpp
*
* Created on: Apr, 2020
* Author: Shraboni Jana
*/
/* Classes to handle E2 service model based on e2sm-HelloWorld-v001.asn */
#ifndef SRC_XAPP_ASN_E2SM_E2SM_CONTROL_HPP_
#define SRC_XAPP_ASN_E2SM_E2SM_CONTROL_HPP_
#include <sstream>
#include <e2sm_helpers.hpp>
#include <mdclog/mdclog.h>
#include <vector>
#include <E2SM-HelloWorld-ControlHeader.h>
#include <E2SM-HelloWorld-ControlMessage.h>
#include <E2SM-HelloWorld-ControlHeader-Format1.h>
#include <E2SM-HelloWorld-ControlMessage-Format1.h>
#include <HW-Header.h>
#include <HW-Message.h>
class e2sm_control {
public:
e2sm_control(void);
~e2sm_control(void);
bool set_fields(E2SM_HelloWorld_ControlHeader_t *, e2sm_control_helper &);
bool set_fields(E2SM_HelloWorld_ControlMessage_t *, e2sm_control_helper &);
bool get_fields(E2SM_HelloWorld_ControlHeader_t *, e2sm_control_helper &);
bool get_fields(E2SM_HelloWorld_ControlMessage_t *, e2sm_control_helper &);
bool encode_control_header(unsigned char *, size_t *, e2sm_control_helper &);
bool encode_control_message(unsigned char*, size_t *, e2sm_control_helper &);
std::string get_error (void) const {return error_string ;};
private:
E2SM_HelloWorld_ControlHeader_t * control_head; // used for encoding
E2SM_HelloWorld_ControlMessage_t* control_msg;
E2SM_HelloWorld_ControlHeader_Format1_t head_fmt1;
E2SM_HelloWorld_ControlMessage_Format1_t msg_fmt1;
size_t errbuf_len;
char errbuf[128];
std::string error_string;
};
#endif /* SRC_XAPP_ASN_E2SM_E2SM_CONTROL_HPP_ */

View File

@@ -0,0 +1,109 @@
/*
==================================================================================
Copyright (c) 2019-2020 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.
==================================================================================
*/
/*
* e2sm_control.cc
*
* Created on: Apr 30, 2020
* Author: Shraboni Jana
*/
/* Classes to handle E2 service model based on e2sm-HelloWorld-v001.asn */
#ifndef E2SM_HELPER_
#define E2SM_HELPER_
#include <errno.h>
#include <iostream>
#include <vector>
#include <sstream>
#include <memory>
typedef struct ranparam_helper ranparam_helper;
struct ranparam_helper {
long int _param_id;
unsigned char* _param_name;
size_t _param_name_len;
int _param_test;
unsigned char* _param_value;
size_t _param_value_len;
};
class RANParam_Helper{
private:
ranparam_helper _ranparam_helper;
public:
RANParam_Helper(int id, unsigned char *param_name, size_t param_name_len, int param_test, unsigned char* param_value, size_t param_value_len){
_ranparam_helper._param_id = id;
_ranparam_helper._param_name = param_name;
_ranparam_helper._param_name_len = param_name_len;
_ranparam_helper._param_test = param_test;
_ranparam_helper._param_value = param_value;
_ranparam_helper._param_value_len = param_value_len;
}
const ranparam_helper & getran_helper() const {
return _ranparam_helper;
}
void print_ranparam_info(void){
std::cout <<"Param ID = " << _ranparam_helper._param_id << std::endl;
std::cout << "Parame Name =" << _ranparam_helper._param_name << std::endl;
std::cout <<"Param Test = " << _ranparam_helper._param_test << std::endl;
std::cout <<"Param Value = " << _ranparam_helper._param_value << std::endl;
}
};
using ranparam_helper_t = std::vector<RANParam_Helper>;
typedef struct e2sm_subscription_helper e2sm_subscription_helper;
struct e2sm_subscription_helper {
public:
int triger_nature;
ranparam_helper_t param;
void add_param(int id, unsigned char *param_name, size_t param_name_len, int param_test, unsigned char* param_value, size_t param_value_len){
RANParam_Helper rparam(id,param_name,param_name_len,param_test,param_value,param_value_len);
param.push_back(rparam);
};
ranparam_helper_t get_paramlist() const {return param;};
};
typedef struct e2sm_indication_helper e2sm_indication_helper;
struct e2sm_indication_helper {
long int header;
unsigned char* message;
size_t message_len;
};
typedef struct e2sm_control_helper e2sm_control_helper;
struct e2sm_control_helper {
long int header;
unsigned char* message;
size_t message_len;
};
#endif

View File

@@ -0,0 +1,192 @@
/*
==================================================================================
Copyright (c) 2019-2020 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.
==================================================================================
*/
/*
* e2sm_indication.cc
*
* Created on: Apr, 2020
* Author: Shraboni Jana
*/
/* Classes to handle E2 service model based on e2sm-HelloWorld-v001.asn */
#include "e2sm_indication.hpp"
//initialize
e2sm_indication::e2sm_indication(void){
memset(&head_fmt1, 0, sizeof(E2SM_HelloWorld_IndicationHeader_Format1_t));
memset(&msg_fmt1, 0, sizeof(E2SM_HelloWorld_IndicationMessage_Format1_t));
indication_head = 0;
indication_head = ( E2SM_HelloWorld_IndicationHeader_t *)calloc(1, sizeof( E2SM_HelloWorld_IndicationHeader_t));
assert(indication_head != 0);
indication_msg = 0;
indication_msg = (E2SM_HelloWorld_IndicationMessage_t*)calloc(1, sizeof(E2SM_HelloWorld_IndicationMessage_t));
assert(indication_msg !=0);
errbuf_len = 128;
};
e2sm_indication::~e2sm_indication(void){
mdclog_write(MDCLOG_DEBUG, "Freeing event trigger object memory");
indication_head->choice.indicationHeader_Format1 = 0;
indication_msg->choice.indicationMessage_Format1 = 0;
ASN_STRUCT_FREE(asn_DEF_E2SM_HelloWorld_IndicationHeader, indication_head);
ASN_STRUCT_FREE(asn_DEF_E2SM_HelloWorld_IndicationMessage, indication_msg);
};
bool e2sm_indication::encode_indication_header(unsigned char *buf, size_t *size, e2sm_indication_helper &helper){
ASN_STRUCT_RESET(asn_DEF_E2SM_HelloWorld_IndicationHeader, indication_head);
bool res;
res = set_fields(indication_head, helper);
if (!res){
return false;
}
int ret_constr = asn_check_constraints(&asn_DEF_E2SM_HelloWorld_IndicationHeader, indication_head, errbuf, &errbuf_len);
if(ret_constr){
error_string.assign(&errbuf[0], errbuf_len);
return false;
}
xer_fprint(stdout, &asn_DEF_E2SM_HelloWorld_IndicationHeader, indication_head);
asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2SM_HelloWorld_IndicationHeader, indication_head, 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_indication::encode_indication_message(unsigned char *buf, size_t *size, e2sm_indication_helper &helper){
bool res;
res = set_fields(indication_msg, helper);
if (!res){
return false;
}
int ret_constr = asn_check_constraints(&asn_DEF_E2SM_HelloWorld_IndicationMessage, indication_msg, errbuf, &errbuf_len);
if(ret_constr){
error_string.assign(&errbuf[0], errbuf_len);
return false;
}
xer_fprint(stdout, &asn_DEF_E2SM_HelloWorld_IndicationMessage, indication_msg);
asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2SM_HelloWorld_IndicationMessage, indication_msg, buf, *size);
if(retval.encoded == -1){
error_string.assign(strerror(errno));
return false;
}
else if (retval.encoded > *size){
std::stringstream ss;
ss <<"Error encoding action 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_indication::set_fields(E2SM_HelloWorld_IndicationHeader_t * ref_indication_head, e2sm_indication_helper & helper){
if(ref_indication_head == 0){
error_string = "Invalid reference for Event Trigger Definition set fields";
return false;
}
ref_indication_head->present = E2SM_HelloWorld_IndicationHeader_PR_indicationHeader_Format1;
head_fmt1.indicationHeaderParam = helper.header;
ref_indication_head->choice.indicationHeader_Format1 = &head_fmt1;
return true;
};
bool e2sm_indication::set_fields(E2SM_HelloWorld_IndicationMessage_t * ref_indication_msg, e2sm_indication_helper & helper){
if(ref_indication_msg == 0){
error_string = "Invalid reference for Event Action Definition set fields";
return false;
}
ref_indication_msg->present = E2SM_HelloWorld_IndicationMessage_PR_indicationMessage_Format1;
msg_fmt1.indicationMsgParam.buf = helper.message;
msg_fmt1.indicationMsgParam.size = helper.message_len;
ref_indication_msg->choice.indicationMessage_Format1 = &msg_fmt1;
return true;
};
bool e2sm_indication::get_fields(E2SM_HelloWorld_IndicationHeader_t * ref_indictaion_header, e2sm_indication_helper & helper){
if (ref_indictaion_header == 0){
error_string = "Invalid reference for Indication Header get fields";
return false;
}
helper.header = ref_indictaion_header->choice.indicationHeader_Format1->indicationHeaderParam;
return true;
}
bool e2sm_indication::get_fields(E2SM_HelloWorld_IndicationMessage_t * ref_indication_message, e2sm_indication_helper & helper){
if (ref_indication_message == 0){
error_string = "Invalid reference for Indication Message get fields";
return false;
}
helper.message = ref_indication_message->choice.indicationMessage_Format1->indicationMsgParam.buf;
helper.message_len = ref_indication_message->choice.indicationMessage_Format1->indicationMsgParam.size;
return true;
}

View File

@@ -0,0 +1,75 @@
/*
==================================================================================
Copyright (c) 2019-2020 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.
==================================================================================
*/
/*
* e2sm_indication.hpp
*
* Created on: Apr, 2020
* Author: Shraboni Jana
*/
/* Classes to handle E2 service model based on e2sm-HelloWorld-v001.asn */
#ifndef SRC_XAPP_ASN_E2SM_E2SM_INDICATION_HPP_
#define SRC_XAPP_ASN_E2SM_E2SM_INDICATION_HPP_
#include <sstream>
#include <e2sm_helpers.hpp>
#include <mdclog/mdclog.h>
#include <vector>
#include <E2SM-HelloWorld-IndicationHeader.h>
#include <E2SM-HelloWorld-IndicationMessage.h>
#include <E2SM-HelloWorld-IndicationHeader-Format1.h>
#include <E2SM-HelloWorld-IndicationMessage-Format1.h>
#include <HW-Header.h>
#include <HW-Message.h>
class e2sm_indication {
public:
e2sm_indication(void);
~e2sm_indication(void);
bool set_fields(E2SM_HelloWorld_IndicationHeader_t *, e2sm_indication_helper &);
bool set_fields(E2SM_HelloWorld_IndicationMessage_t *, e2sm_indication_helper &);
bool get_fields(E2SM_HelloWorld_IndicationHeader_t *, e2sm_indication_helper &);
bool get_fields(E2SM_HelloWorld_IndicationMessage_t *, e2sm_indication_helper &);
bool encode_indication_header(unsigned char *, size_t *, e2sm_indication_helper &);
bool encode_indication_message(unsigned char*, size_t *, e2sm_indication_helper &);
std::string get_error (void) const {return error_string ;};
private:
E2SM_HelloWorld_IndicationHeader_t * indication_head; // used for encoding
E2SM_HelloWorld_IndicationMessage_t* indication_msg;
E2SM_HelloWorld_IndicationHeader_Format1_t head_fmt1;
E2SM_HelloWorld_IndicationMessage_Format1_t msg_fmt1;
size_t errbuf_len;
char errbuf[128];
std::string error_string;
};
#endif /* SRC_XAPP_ASN_E2SM_E2SM_INDICATION_HPP_ */

View File

@@ -0,0 +1,185 @@
/*
==================================================================================
Copyright (c) 2019-2020 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.
==================================================================================
*/
/*
* e2sm_control.cc
*
* Created on: Apr 30, 2020
* Author: Shraboni Jana
*/
/* Classes to handle E2 service model based on e2sm-HelloWorld-v001.asn */
#include "e2sm_subscription.hpp"
//initialize
e2sm_subscription::e2sm_subscription(void){
memset(&event_fmt1, 0, sizeof(E2SM_HelloWorld_EventTriggerDefinition_Format1_t));
memset(&actn_fmt1, 0, sizeof(E2SM_HelloWorld_ActionDefinition_Format1_t));
ran_param = 0;
ran_param = (RANparameter_Item_t*)calloc(1, sizeof(RANparameter_Item_t));
assert(ran_param != 0);
event_trigger = 0;
event_trigger = ( E2SM_HelloWorld_EventTriggerDefinition_t *)calloc(1, sizeof( E2SM_HelloWorld_EventTriggerDefinition_t));
assert(event_trigger != 0);
action_defn = 0;
action_defn = (E2SM_HelloWorld_ActionDefinition_t*)calloc(1, sizeof(E2SM_HelloWorld_ActionDefinition_t));
assert(action_defn !=0);
errbuf_len = 128;
};
e2sm_subscription::~e2sm_subscription(void){
mdclog_write(MDCLOG_DEBUG, "Freeing event trigger object memory");
event_trigger->choice.eventDefinition_Format1 = 0;
action_defn->choice.actionDefinition_Format1 = 0;
free(ran_param);
ASN_STRUCT_FREE(asn_DEF_E2SM_HelloWorld_EventTriggerDefinition, event_trigger);
ASN_STRUCT_FREE(asn_DEF_E2SM_HelloWorld_ActionDefinition, action_defn);
};
bool e2sm_subscription::encode_event_trigger(unsigned char *buf, size_t *size, e2sm_subscription_helper &helper){
ASN_STRUCT_RESET(asn_DEF_E2SM_HelloWorld_EventTriggerDefinition, event_trigger);
bool res;
res = set_fields(event_trigger, helper);
if (!res){
return false;
}
int ret_constr = asn_check_constraints(&asn_DEF_E2SM_HelloWorld_EventTriggerDefinition, event_trigger, errbuf, &errbuf_len);
if(ret_constr){
error_string.assign(&errbuf[0], errbuf_len);
return false;
}
xer_fprint(stdout, &asn_DEF_E2SM_HelloWorld_EventTriggerDefinition, event_trigger);
asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2SM_HelloWorld_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_subscription::encode_action_defn(unsigned char *buf, size_t *size, e2sm_subscription_helper &helper){
bool res;
res = set_fields(action_defn, helper);
if (!res){
return false;
}
int ret_constr = asn_check_constraints(&asn_DEF_E2SM_HelloWorld_ActionDefinition, action_defn, errbuf, &errbuf_len);
if(ret_constr){
error_string.assign(&errbuf[0], errbuf_len);
return false;
}
xer_fprint(stdout, &asn_DEF_E2SM_HelloWorld_ActionDefinition, action_defn);
asn_enc_rval_t retval = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2SM_HelloWorld_ActionDefinition, action_defn, buf, *size);
if(retval.encoded == -1){
error_string.assign(strerror(errno));
return false;
}
else if (retval.encoded > *size){
std::stringstream ss;
ss <<"Error encoding action 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_subscription::set_fields(E2SM_HelloWorld_EventTriggerDefinition_t * ref_event_trigger, e2sm_subscription_helper & helper){
if(ref_event_trigger == 0){
error_string = "Invalid reference for Event Trigger Definition set fields";
return false;
}
ref_event_trigger->present = E2SM_HelloWorld_EventTriggerDefinition_PR_eventDefinition_Format1;
event_fmt1.triggerNature = helper.triger_nature;
ref_event_trigger->choice.eventDefinition_Format1 = &event_fmt1;
return true;
};
bool e2sm_subscription::set_fields(E2SM_HelloWorld_ActionDefinition_t * ref_action_defn, e2sm_subscription_helper & helper){
if(ref_action_defn == 0){
error_string = "Invalid reference for Event Action Definition set fields";
return false;
}
ref_action_defn->present = E2SM_HelloWorld_ActionDefinition_PR_actionDefinition_Format1;
ranparam_helper_t paramlst = helper.get_paramlist();
for(RANParam_Helper item:paramlst){
ran_param->ranParameter_ID = item.getran_helper()._param_id;
ran_param->ranParameter_Name.buf = item.getran_helper()._param_name;
ran_param->ranParameter_Name.size = item.getran_helper()._param_name_len;
ran_param->ranParameter_Test = item.getran_helper()._param_test;
ran_param->ranParameter_Value.buf = item.getran_helper()._param_value;
ran_param->ranParameter_Value.size = item.getran_helper()._param_value_len;
ASN_SEQUENCE_ADD(&(actn_fmt1.ranParameter_List->list.array), ran_param);
}
ref_action_defn->choice.actionDefinition_Format1 = &actn_fmt1;
return true;
};

View File

@@ -0,0 +1,74 @@
/*
==================================================================================
Copyright (c) 2019-2020 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.
==================================================================================
*/
/*
* e2sm_control.cc
*
* Created on: Apr 30, 2020
* Author: Shraboni Jana
*/
/* Classes to handle E2 service model based on e2sm-HelloWorld-v001.asn */
#ifndef E2SM_
#define E2SM_
#include <sstream>
#include <e2sm_helpers.hpp>
#include <mdclog/mdclog.h>
#include <vector>
#include <E2SM-HelloWorld-EventTriggerDefinition.h>
#include <E2SM-HelloWorld-ActionDefinition.h>
#include <E2SM-HelloWorld-EventTriggerDefinition-Format1.h>
#include <E2SM-HelloWorld-ActionDefinition-Format1.h>
#include <HW-TriggerNature.h>
#include <RANparameter-Item.h>
/* builder class for E2SM event trigger definition */
class e2sm_subscription {
public:
e2sm_subscription(void);
~e2sm_subscription(void);
bool set_fields(E2SM_HelloWorld_EventTriggerDefinition_t *, e2sm_subscription_helper &);
bool set_fields(E2SM_HelloWorld_ActionDefinition_t *, e2sm_subscription_helper &);
bool encode_event_trigger(unsigned char *, size_t *, e2sm_subscription_helper &);
bool encode_action_defn(unsigned char*, size_t *, e2sm_subscription_helper &);
std::string get_error (void) const {return error_string ;};
private:
E2SM_HelloWorld_EventTriggerDefinition_t * event_trigger; // used for encoding
E2SM_HelloWorld_ActionDefinition_t* action_defn;
E2SM_HelloWorld_EventTriggerDefinition_Format1_t event_fmt1;
E2SM_HelloWorld_ActionDefinition_Format1_t actn_fmt1;
RANparameter_Item_t *ran_param;
size_t errbuf_len;
char errbuf[128];
std::string error_string;
};
#endif

View File

@@ -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;
}

View File

@@ -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 <iostream>
#include <errno.h>
#include <mdclog/mdclog.h>
#include <sstream>
#include <E2N_E2AP-PDU.h>
#include <E2N_InitiatingMessage.h>
#include <E2N_RICcontrolRequest.h>
#include <E2N_ProtocolIE-Field.h>
#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_ */

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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 <iostream>
#include <errno.h>
#include <mdclog/mdclog.h>
#include <sstream>
#include <E2N_E2AP-PDU.h>
#include <E2N_SuccessfulOutcome.h>
#include <E2N_UnsuccessfulOutcome.h>
#include <E2N_RICcontrolAcknowledge.h>
#include <E2N_RICcontrolFailure.h>
#include <E2N_ProtocolIE-Field.h>
#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_ */

View File

@@ -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;
}

View File

@@ -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 <iostream>
#include <errno.h>
#include <mdclog/mdclog.h>
#include <sstream>
#include <E2N_E2AP-PDU.h>
#include <E2N_InitiatingMessage.h>
#include <E2N_RICindication.h>
#include <E2N_ProtocolIE-Field.h>
#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_ */

View File

@@ -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

View File

@@ -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 <cstddef>
/* 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

View File

@@ -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 <vector>
#include <memory>
/* 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<ActionResponse>;
subscription_response_helper(void){
_action_admitted_ref = std::make_unique<action_t>();
_action_not_admitted_ref = std::make_unique<action_t>();
};
// copy operator
subscription_response_helper(const subscription_response_helper &he ){
_action_admitted_ref = std::make_unique<action_t>();
_action_not_admitted_ref = std::make_unique<action_t>();
_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_t>();
_action_not_admitted_ref = std::make_unique<action_t>();
_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_t> _action_admitted_ref;
std::unique_ptr<action_t> _action_not_admitted_ref;
};
#endif

View File

@@ -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;
}

View File

@@ -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 <mdclog/mdclog.h>
#include <vector>
#include <sstream>
#include <mdclog/mdclog.h>
#include <asn_application.h>
#include <E2N_E2AP-PDU.h>
#include <E2N_InitiatingMessage.h>
#include <E2N_RICsubscriptionDeleteRequest.h>
#include <E2N_ProtocolIE-Field.h>
#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

View File

@@ -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);
}

View File

@@ -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 <mdclog/mdclog.h>
#include <vector>
#include <iostream>
#include <sstream>
#include <mdclog/mdclog.h>
#include <asn_application.h>
#include <E2N_E2AP-PDU.h>
#include <E2N_SuccessfulOutcome.h>
#include <E2N_UnsuccessfulOutcome.h>
#include <E2N_RICsubscriptionDeleteResponse.h>
#include <E2N_RICsubscriptionDeleteFailure.h>
#include <E2N_ProtocolIE-Field.h>
#include <E2N_ProcedureCode.h>
#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

View File

@@ -0,0 +1,196 @@
/*
==================================================================================
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 <iostream>
#include <vector>
#include <memory>
#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<Action>;
subscription_helper(){
_action_ref = std::make_unique<action_t>();
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_t> _action_ref;
int curr_index;
int _req_id, _req_seq_no, _func_id;
octet_helper _event_def;
};
#endif

View File

@@ -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<Action> * 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;
};

View File

@@ -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 <mdclog/mdclog.h>
#include <vector>
#include <sstream>
#include <asn_application.h>
#include <E2N_E2AP-PDU.h>
#include <E2N_InitiatingMessage.h>
#include <E2N_RICsubscriptionRequest.h>
#include <E2N_RICsubscription.h>
#include <E2N_ProtocolIE-Field.h>
#include <E2N_ProtocolIE-Single-Container.h>
#include <E2N_RICactions-ToBeSetup-List.h>
#include <E2N_RICsubsequentAction.h>
#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

View File

@@ -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<ActionResponse> * 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<ActionResponse> * 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<ActionResponse> * 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);
}

View File

@@ -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 <mdclog/mdclog.h>
#include <vector>
#include <iostream>
#include <sstream>
#include <asn_application.h>
#include <E2N_E2AP-PDU.h>
#include <E2N_SuccessfulOutcome.h>
#include <E2N_UnsuccessfulOutcome.h>
#include <E2N_ProtocolIE-Field.h>
#include <E2N_ProtocolIE-Single-Container.h>
#include <E2N_ProcedureCode.h>
#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

View File

@@ -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<Item> * 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;
}

View File

@@ -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 <sstream>
#include <mdclog/mdclog.h>
#include <E2N_E2SM-gNB-X2-indicationHeader.h>
#include <E2N_E2SM-gNB-X2-indicationMessage.h>
#include <E2N_E2SM-gNB-X2-controlHeader.h>
#include <E2N_E2SM-gNB-X2-controlMessage.h>
#include <E2N_E2SM-gNB-X2-eventTriggerDefinition.h>
#include <E2N_GlobalGNB-ID.h>
#include <E2N_TypeOfMessage.h>
#include <E2N_InterfaceProtocolIE-Item.h>
#include<E2N_InterfaceProtocolIE-ID.h>
#include<E2N_InterfaceProtocolIE-Value.h>
#include<E2N_InterfaceProtocolIE-Test.h>
#include "../../xapp-formats/e2sm/e2sm_helpers.hpp"
#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<struct InterfaceProtocolIE_Item> 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

View File

@@ -0,0 +1,115 @@
/*
==================================================================================
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 */
#ifndef E2SM_HELPER_
#define E2SM_HELPER_
#include <errno.h>
#include <iostream>
#include <vector>
#include <sstream>
/* 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<struct Item> * 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<struct Item> protocol_ie_list;
};
#endif

View File

@@ -0,0 +1,49 @@
/*
==================================================================================
Copyright (c) 2019-2020 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.
==================================================================================
*/
/*
* a1_policy.hpp
*
* Created on: Mar, 2020
* Author: Shraboni Jana
*/
#ifndef SRC_XAPP_MGMT_A1MSG_A1_POLICY_HELPER_HPP_
#define SRC_XAPP_MGMT_A1MSG_A1_POLICY_HELPER_HPP_
#include <rapidjson/document.h>
#include <rapidjson/writer.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/schema.h>
using namespace rapidjson;
typedef struct a1_policy_helper a1_policy_helper;
struct a1_policy_helper{
std::string operation;
std::string policy_type_id;
std::string policy_instance_id;
std::string handler_id;
std::string status;
};
#endif /* SRC_XAPP_FORMATS_A1MSG_A1_POLICY_HELPER_HPP_ */

View File

@@ -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.
==================================================================================
*/
/*
* a1_policy.hpp
*
* Created on: Mar, 2020
* Author: Shraboni Jana
*/
#ifndef SRC_XAPP_MGMT_A1MSG_A1_POLICY_HELPER_HPP_
#define SRC_XAPP_MGMT_A1MSG_A1_POLICY_HELPER_HPP_
#include <rapidjson/document.h>
#include <rapidjson/writer.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/schema.h>
using namespace rapidjson;
typedef struct a1_policy_helper a1_policy_helper;
struct a1_policy_helper{
std::string operation;
std::string policy_type_id;
std::string policy_instance_id;
std::string handler_id;
std::string status;
};
#endif /* SRC_XAPP_FORMATS_A1MSG_A1_POLICY_HELPER_HPP_ */

View File

@@ -0,0 +1,293 @@
/*
==================================================================================
Copyright (c) 2019-2020 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"
#include <stdio.h>
bool XappMsgHandler::encode_subscription_delete_request(unsigned char* buffer, size_t *buf_len){
subscription_helper sub_helper;
sub_helper.set_request(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){
subscription_helper subhelper;
subscription_response subresponse;
bool res = true;
E2AP_PDU_t *e2pdu = 0;
asn_dec_rval_t rval;
ASN_STRUCT_RESET(asn_DEF_E2AP_PDU, e2pdu);
rval = asn_decode(0,ATS_ALIGNED_BASIC_PER, &asn_DEF_E2AP_PDU, (void**)&e2pdu, data_buf, data_size);
switch(rval.code)
{
case RC_OK:
//Put in Subscription Response Object.
//asn_fprint(stdout, &asn_DEF_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_E2AP_PDU, e2pdu);
return res;
}
bool XappMsgHandler::a1_policy_handler(char * message, int *message_len, a1_policy_helper &helper){
rapidjson::Document doc;
if (doc.Parse(message).HasParseError()){
mdclog_write(MDCLOG_ERR, "Error: %s, %d :: Could not decode A1 JSON message %s\n", __FILE__, __LINE__, message);
return false;
}
//Extract Operation
rapidjson::Pointer temp1("/operation");
rapidjson::Value * ref1 = temp1.Get(doc);
if (ref1 == NULL){
mdclog_write(MDCLOG_ERR, "Error : %s, %d:: Could not extract policy type id from %s\n", __FILE__, __LINE__, message);
return false;
}
helper.operation = ref1->GetString();
// Extract policy id type
rapidjson::Pointer temp2("/policy_type_id");
rapidjson::Value * ref2 = temp2.Get(doc);
if (ref2 == NULL){
mdclog_write(MDCLOG_ERR, "Error : %s, %d:: Could not extract policy type id from %s\n", __FILE__, __LINE__, message);
return false;
}
//helper.policy_type_id = ref2->GetString();
helper.policy_type_id = to_string(ref2->GetInt());
// Extract policy instance id
rapidjson::Pointer temp("/policy_instance_id");
rapidjson::Value * ref = temp.Get(doc);
if (ref == NULL){
mdclog_write(MDCLOG_ERR, "Error : %s, %d:: Could not extract policy type id from %s\n", __FILE__, __LINE__, message);
return false;
}
helper.policy_instance_id = ref->GetString();
if (helper.policy_type_id == "1" && helper.operation == "CREATE"){
helper.status = "OK";
Document::AllocatorType& alloc = doc.GetAllocator();
Value handler_id;
handler_id.SetString(helper.handler_id.c_str(), helper.handler_id.length(), alloc);
Value status;
status.SetString(helper.status.c_str(), helper.status.length(), alloc);
doc.AddMember("handler_id", handler_id, alloc);
doc.AddMember("status",status, alloc);
doc.RemoveMember("operation");
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
doc.Accept(writer);
strncpy(message,buffer.GetString(), buffer.GetLength());
*message_len = buffer.GetLength();
return true;
}
return false;
}
//For processing received messages.XappMsgHandler should mention if resend is required or not.
void XappMsgHandler::operator()(rmr_mbuf_t *message, bool *resend){
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;
}
a1_policy_helper helper;
bool res=false;
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;
strncpy( (char*)message->payload, "HELLOWORLD OK\n", rmr_payload_size( message) );
*resend = true;
break;
case (RIC_INDICATION): {
mdclog_write(MDCLOG_INFO, "Received RIC indication message of type = %d", message->mtype);
unsigned char *me_id_null;
unsigned char *me_id = rmr_get_meid(message, me_id_null);
mdclog_write(MDCLOG_INFO,"RMR Received MEID: %s",me_id);
process_ric_indication(message->mtype, me_id, message->payload, message->len);
break;
}
case (RIC_SUB_RESP): {
mdclog_write(MDCLOG_INFO, "Received subscription message of type = %d", message->mtype);
unsigned char *me_id_null;
unsigned char *me_id = rmr_get_meid(message, me_id_null);
mdclog_write(MDCLOG_INFO,"RMR Received MEID: %s",me_id);
if(_ref_sub_handler !=NULL){
_ref_sub_handler->manage_subscription_response(message->mtype, me_id, message->payload, message->len);
} else {
mdclog_write(MDCLOG_ERR, " Error :: %s, %d : Subscription handler not assigned in message processor !", __FILE__, __LINE__);
}
*resend = false;
break;
}
case A1_POLICY_REQ:
mdclog_write(MDCLOG_INFO, "In Message Handler: Received A1_POLICY_REQ.");
helper.handler_id = xapp_id;
res = a1_policy_handler((char*)message->payload, &message->len, helper);
if(res){
message->mtype = A1_POLICY_RESP; // if we're here we are running and all is ok
message->sub_id = -1;
*resend = true;
}
break;
default:
{
mdclog_write(MDCLOG_ERR, "Error :: Unknown message type %d received from RMR", message->mtype);
*resend = false;
}
}
return;
};
void process_ric_indication(int message_type, transaction_identifier id, const void *message_payload, size_t message_len) {
std::cout << "In Process RIC indication" << std::endl;
std::cout << "ID " << id << std::endl;
// decode received message payload
E2AP_PDU_t *pdu = nullptr;
auto retval = asn_decode(nullptr, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2AP_PDU, (void **) &pdu, message_payload, message_len);
// print decoded payload
if (retval.code == RC_OK) {
char *printBuffer;
size_t size;
FILE *stream = open_memstream(&printBuffer, &size);
asn_fprint(stream, &asn_DEF_E2AP_PDU, pdu);
mdclog_write(MDCLOG_DEBUG, "Decoded E2AP PDU: %s", printBuffer);
uint8_t res = procRicIndication(pdu, id);
}
else {
std::cout << "process_ric_indication, retval.code " << retval.code << std::endl;
}
}
/**
* Handle RIC indication
* TODO doxy
*/
uint8_t procRicIndication(E2AP_PDU_t *e2apMsg, transaction_identifier gnb_id)
{
uint8_t idx;
uint8_t ied;
uint8_t ret = RC_OK;
uint32_t recvBufLen;
RICindication_t *ricIndication;
RICaction_ToBeSetup_ItemIEs_t *actionItem;
printf("\nE2AP : RIC Indication received");
ricIndication = &e2apMsg->choice.initiatingMessage->value.choice.RICindication;
printf("protocolIEs elements %d\n", ricIndication->protocolIEs.list.count);
for (idx = 0; idx < ricIndication->protocolIEs.list.count; idx++)
{
switch(ricIndication->protocolIEs.list.array[idx]->id)
{
case 28: // RIC indication type
{
long ricindicationType = ricIndication->protocolIEs.list.array[idx]-> \
value.choice.RICindicationType;
printf("ricindicationType %ld\n", ricindicationType);
break;
}
case 26: // RIC indication message
{
int payload_size = ricIndication->protocolIEs.list.array[idx]-> \
value.choice.RICindicationMessage.size;
char* payload = (char*) calloc(payload_size, sizeof(char));
memcpy(payload, ricIndication->protocolIEs.list.array[idx]-> \
value.choice.RICindicationMessage.buf, payload_size);
printf("Payload %s\n", payload);
// send payload to agent
std::string agent_ip = find_agent_ip_from_gnb(gnb_id);
send_socket(payload, agent_ip);
break;
}
}
}
return ret; // TODO update ret value in case of errors
}

View File

@@ -0,0 +1,74 @@
/*
==================================================================================
Copyright (c) 2019-2020 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 <iostream>
#include<rmr/rmr.h>
#include <rmr/RIC_message_types.h>
#include <mdclog/mdclog.h>
#include "a1_helper.hpp"
#include "e2ap_control.hpp"
#include "e2ap_control_response.hpp"
#include "e2ap_indication.hpp"
#include "subscription_delete_request.hpp"
#include "subscription_delete_response.hpp"
#include "subscription_helper.hpp"
#include "subscription_request.hpp"
#include "subscription_request.hpp"
#include "subscription_response.hpp"
#include "e2sm_subscription.hpp"
#include "subs_mgmt.hpp"
#include "../agent_connector.hpp"
#define MAX_RMR_RECV_SIZE 2<<15
class XappMsgHandler{
private:
std::string xapp_id;
SubscriptionHandler *_ref_sub_handler;
public:
//constructor for xapp_id.
XappMsgHandler(std::string xid){xapp_id=xid; _ref_sub_handler=NULL;};
XappMsgHandler(std::string xid, SubscriptionHandler &subhandler){xapp_id=xid; _ref_sub_handler=&subhandler;};
void operator() (rmr_mbuf_t *, bool*);
void register_handler();
bool encode_subscription_delete_request(unsigned char*, size_t* );
bool decode_subscription_response(unsigned char*, size_t );
bool a1_policy_handler(char *, int* , a1_policy_helper &);
void testfunction() {std::cout << "<<<<<<<<<<<<<<<<<<IN TEST FUNCTION<<<<<<<<<<<<<<<" << std::endl;}
};
void process_ric_indication(int message_type, transaction_identifier id, const void *message_payload, size_t message_len);
uint8_t procRicIndication(E2AP_PDU_t *e2apMsg, transaction_identifier gnb_id);
#endif /* XAPP_MSG_XAPP_MSG_HPP_ */

View File

@@ -0,0 +1,177 @@
/*
==================================================================================
Copyright (c) 2019-2020 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 <errno.h>
#include <stdio.h>
#include <string.h>
SubscriptionHandler::SubscriptionHandler(unsigned int timeout_seconds):_time_out(std::chrono::seconds(timeout_seconds)){
_data_lock = std::make_unique<std::mutex>();
_cv = std::make_unique<std::condition_variable>();
};
void SubscriptionHandler::clear(void){
{
std::lock_guard<std::mutex> lock(*(_data_lock).get());
status_table.clear();
}
};
bool SubscriptionHandler::add_request_entry(transaction_identifier id, transaction_status status){
// add entry in hash table if it does not exist
//auto search = status_table.find(id);
//if(search != status_table.end()){
if(transaction_present(status_table, id)){
return false;
}
std::cout << "add_request_entry " << id << std::endl;
status_table[id] = status;
return true;
};
bool SubscriptionHandler::delete_request_entry(transaction_identifier id){
auto search = status_table.find(id);
if (!trans_table.empty()) {
auto search2 = trans_table.find(id);
if(search2 !=trans_table.end()){
trans_table.erase(search2);
}
}
if (search != status_table.end()){
status_table.erase(search);
mdclog_write(MDCLOG_INFO,"Entry for Transaction ID deleted: %s", id);
return true;
}
mdclog_write(MDCLOG_INFO,"Entry not found in SubscriptionHandler for Transaction ID: %d",id);
return false;
};
bool SubscriptionHandler::set_request_status(transaction_identifier id, transaction_status status){
// change status of a request only if it exists.
//auto search = status_table.find(id);
if(transaction_present(status_table, id)){
status_table[id] = status;
std::cout << "set_request_status " << id << " to status " << status << std::endl;
return true;
}
return false;
};
int const SubscriptionHandler::get_request_status(transaction_identifier id){
//auto search = status_table.find(id);
auto search = find_transaction(status_table, id);
std::cout << "get_request_status " << id << std::endl;
if (search == status_table.end()){
return -1;
}
return search->second;
}
bool SubscriptionHandler::is_request_entry(transaction_identifier id){
std::cout << "is_request_entry, looking for key: " << id << std::endl;
if (transaction_present(status_table, id)) {
std::cout << "Key found" << std::endl;
return true;
}
else {
std::cout << "Key NOT found" << std::endl;
return false;
}
}
// Handles subscription responses
void SubscriptionHandler::manage_subscription_response(int message_type, transaction_identifier id, const void *message_payload, size_t message_len){
bool res;
std::cout << "In Manage subscription" << std::endl;
// wake up all waiting users ...
if(is_request_entry(id)){
std::cout << "In Manage subscription, inside if loop" << std::endl;
std::cout << "Setting to request_success: " << request_success << std::endl;
set_request_status(id, request_success);
_cv.get()->notify_all();
}
// decode received message payload
E2AP_PDU_t *pdu = nullptr;
auto retval = asn_decode(nullptr, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2AP_PDU, (void **) &pdu, message_payload, message_len);
// print decoded payload
if (retval.code == RC_OK) {
char *printBuffer;
size_t size;
FILE *stream = open_memstream(&printBuffer, &size);
asn_fprint(stream, &asn_DEF_E2AP_PDU, pdu);
mdclog_write(MDCLOG_DEBUG, "Decoded E2AP PDU: %s", printBuffer);
}
}
std::unordered_map<transaction_identifier, transaction_status>::iterator find_transaction(std::unordered_map<transaction_identifier, transaction_status> map,
transaction_identifier id) {
auto iter = map.begin();
while (iter != map.end()) {
if (strcmp((const char*) iter->first, (const char*) id) == 0) {
break;
}
++iter;
}
return iter;
}
bool transaction_present(std::unordered_map<transaction_identifier, transaction_status> map, transaction_identifier id) {
auto iter = map.begin();
while (iter != map.end()) {
if (strcmp((const char*) iter->first, (const char*) id) == 0) {
return true;
}
++iter;
}
return false;
}

View File

@@ -0,0 +1,269 @@
/*
==================================================================================
Copyright (c) 2019-2020 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 <functional>
#include <mdclog/mdclog.h>
#include <mutex>
#include <condition_variable>
#include <unordered_map>
#include <chrono>
#include <tuple>
#include "../xapp-asn/e2ap/subscription_delete_request.hpp"
#include "../xapp-asn/e2ap/subscription_delete_response.hpp"
#include "../xapp-asn/e2ap/subscription_request.hpp"
#include "../xapp-asn/e2ap/subscription_response.hpp"
#define SUBSCR_SUCCESS 1
#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
using namespace std;
class TransmitterBase
{
public:
virtual ~TransmitterBase() {}
template<class T>
const T& getParam() const; //to be implemented after Parameter
template<class T, class U>
void setParam(const U& rhs); //to be implemented after Parameter
};
template <typename T>
class Transmitter : public TransmitterBase
{
public:
Transmitter(const T& tx) :obj(tx) {}
const T& getParam() const {return obj;}
void setParam(const T& tx) {obj=tx;}
private:
T obj;
};
//Here's the trick: dynamic_cast rather than virtual
template<class T> const T& TransmitterBase::getParam() const
{
return dynamic_cast<const Transmitter<T>&>(*this).getParam();
}
template<class T, class U> void TransmitterBase::setParam(const U& rhs)
{
dynamic_cast<Transmitter<T>&>(*this).setParam(rhs);
return;
}
typedef enum {
request_pending = 1,
request_success,
request_failed,
delete_request_pending,
delete_request_success,
delete_request_failed,
request_duplicate
}Subscription_Status_Types;
using transaction_identifier = unsigned char*;
using transaction_status = Subscription_Status_Types;
class SubscriptionHandler {
public:
SubscriptionHandler(unsigned int timeout_seconds = 10);
template <typename AppTransmitter>
int manage_subscription_request(transaction_identifier, AppTransmitter &&);
template <typename AppTransmitter>
int manage_subscription_delete_request(transaction_identifier, AppTransmitter &&);
void manage_subscription_response(int message_type, transaction_identifier id, const void *message_payload, size_t message_len);
int const get_request_status(transaction_identifier);
bool set_request_status(transaction_identifier, transaction_status);
bool is_request_entry(transaction_identifier);
void set_timeout(unsigned int);
void clear(void);
void set_ignore_subs_resp(bool b){_ignore_subs_resp = b;};
private:
bool add_request_entry(transaction_identifier, transaction_status);
bool delete_request_entry(transaction_identifier);
template <typename AppTransmitter>
bool add_transmitter_entry(transaction_identifier, AppTransmitter&&);
std::unordered_map<transaction_identifier, TransmitterBase> trans_table;
std::unordered_map<transaction_identifier, transaction_status> status_table;
std::unique_ptr<std::mutex> _data_lock;
std::unique_ptr<std::condition_variable> _cv;
std::chrono::seconds _time_out;
bool _ignore_subs_resp = false;
};
template <typename AppTransmitter>
bool SubscriptionHandler::add_transmitter_entry(transaction_identifier id, AppTransmitter &&trans){
// add entry in hash table if it does not exist
//auto search = trans_table.find(id);
auto search = trans_table.begin();
while (search != trans_table.end()) {
if (strcmp((const char*) search->first, (const char*) id) == 0) {
break;
}
++search;
}
if(search != trans_table.end()){
return false;
}
Transmitter<AppTransmitter> tptr(trans);
trans_table[id] = tptr;
return true;
};
//this will work for both sending subscription request and subscription delete request.
//The handler is oblivious of the message content and follows the transaction id.
template<typename AppTransmitter>
int SubscriptionHandler::manage_subscription_request(transaction_identifier rmr_trans_id, AppTransmitter && tx){
int res;
// put entry in request table
{
std::lock_guard<std::mutex> lock(*(_data_lock.get()));
res = add_request_entry(rmr_trans_id, request_pending);
if(! res){
mdclog_write(MDCLOG_ERR, "%s, %d : Error adding new subscription request %s to queue because request with identical key already present", __FILE__, __LINE__, rmr_trans_id);
return SUBSCR_ERR_DUPLICATE;
}
else {
std::cout << "Added status pending to request " << rmr_trans_id << std::endl;
}}
// acquire lock ...
std::unique_lock<std::mutex> _local_lock(*(_data_lock.get()));
// Send the message
bool flg = tx();
if (!flg){
// clear state
delete_request_entry(rmr_trans_id);
mdclog_write(MDCLOG_ERR, "%s, %d :: Error transmitting subscription request %s", __FILE__, __LINE__, rmr_trans_id );
return SUBSCR_ERR_TX;
} else {
mdclog_write(MDCLOG_INFO, "%s, %d :: Transmitted subscription request for trans_id %s", __FILE__, __LINE__, rmr_trans_id );
add_transmitter_entry(rmr_trans_id, 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(rmr_trans_id);
if (status == request_success){
mdclog_write(MDCLOG_INFO, "Successfully subscribed for request for trans_id %s", rmr_trans_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<double> f = end - start;
if ( f > _time_out){
mdclog_write(MDCLOG_ERR, "%s, %d:: Subscription request with transaction id %s timed out waiting for response ", __FILE__, __LINE__, rmr_trans_id);
//res = SUBSCR_ERR_TIMEOUT;
//sunny side scenario. assuming subscription response is received.
res = SUBSCR_SUCCESS;
break;
}
else{
mdclog_write(MDCLOG_INFO, "Subscription request with transaction id %s Waiting for response....", rmr_trans_id);
continue;
}
}
if(status == request_failed){
mdclog_write(MDCLOG_ERR, "Error :: %s, %d : Subscription Request with transaction id %s got failure response .. \n", __FILE__, __LINE__, rmr_trans_id);
res = SUBSCR_ERR_FAIL;
break;
}
if (status == request_duplicate){
mdclog_write(MDCLOG_ERR, "Error :: %s, %d : Subscription Request with transaction id %s is duplicate : subscription already present in table .. \n", __FILE__, __LINE__, rmr_trans_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, and state = %d. Deleting request entry and failing .. \n", __FILE__, __LINE__, rmr_trans_id, status);
res = SUBSCR_ERR_UNKNOWN;
break;
};
delete_request_entry(rmr_trans_id);
// release data lock
_local_lock.unlock();
// std::cout <<"Returning res = " << res << " for request = " << rmr_trans_id << std::endl;
return res;
};
std::unordered_map<transaction_identifier, transaction_status>::iterator find_transaction(std::unordered_map<transaction_identifier, transaction_status> map,
transaction_identifier id);
bool transaction_present(std::unordered_map<transaction_identifier, transaction_status> map, transaction_identifier id);
#endif

View File

@@ -0,0 +1,21 @@
/*
* xapp_handler.hpp
*
* Created on: Mar 16, 2020
* Author: Shraboni Jana
*/
#ifndef SRC_XAPP_MGMT_XAPP_HANDLER_HPP_
#define SRC_XAPP_MGMT_XAPP_HANDLER_HPP_
class XappHandler{
XappHandler *xhandler;
public:
virtual ~XappHandler(){delete xhandler;};
virtual void register_handler(XappHandler *xhandler) = 0;
virtual XappHandler* get_handler() = 0;
};
#endif /* SRC_XAPP_MGMT_XAPP_HANDLER_HPP_ */

View File

@@ -0,0 +1,144 @@
/*
==================================================================================
Copyright (c) 2019-2020 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'},
{"ves-interval", required_argument, 0, 'i'},
{"gNodeB", required_argument, 0, 'g'}
};
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_PORT].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 '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 'h':
usage(argv[0]);
exit(0);
default:
usage(argv[0]);
exit(1);
}
};
}
void XappSettings::loadDefaultSettings(){
if(theSettings[XAPP_NAME].empty()){
theSettings[XAPP_NAME] = DEFAULT_XAPP_NAME;
}
if(theSettings[XAPP_ID].empty()){
theSettings[XAPP_ID] = DEFAULT_XAPP_NAME; //for now xapp_id is same as xapp_name since single xapp instance.
}
if(theSettings[LOG_LEVEL].empty()){
theSettings[LOG_LEVEL] = DEFAULT_LOG_LEVEL;
}
if(theSettings[HW_PORT].empty()){
theSettings[HW_PORT] = DEFAULT_PORT;
}
if(theSettings[MSG_MAX_BUFFER].empty()){
theSettings[MSG_MAX_BUFFER] = DEFAULT_MSG_MAX_BUFFER;
}
if(theSettings[THREADS].empty()){
theSettings[THREADS] = DEFAULT_THREADS;
}
}
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_NAME")){
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_PORT")){
theSettings[HW_PORT].assign(env_ports);
mdclog_write(MDCLOG_INFO,"Ports set to %s from environment variable", theSettings[HW_PORT].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());
}
}
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 ;
}

View File

@@ -0,0 +1,72 @@
/*
==================================================================================
Copyright (c) 2019-2020 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 <getopt.h>
#include <map>
#include <iostream>
#include <cstdlib>
#include <mdclog/mdclog.h>
#define DEFAULT_XAPP_NAME "hwxapp"
#define DEFAULT_PORT "4560"
#define DEFAULT_MSG_MAX_BUFFER "2072"
#define DEFAULT_THREADS "1"
#define DEFAULT_LOG_LEVEL MDCLOG_WARN
#define ASN_BUFF_MAX_SIZE 4096
#define MAX_SUBSCRIPTION_ATTEMPTS 10
#define HELLOWORLD_POLICY_ID 2
using namespace std;
struct XappSettings{
public:
typedef enum{
XAPP_ID,
XAPP_NAME,
HW_PORT,
MSG_MAX_BUFFER,
THREADS,
LOG_LEVEL
}SettingName;
void loadDefaultSettings();
void loadCmdlineSettings(int, char **);
void loadEnvVarSettings();
void usage(char*);
string& operator[](const SettingName& theName);
private:
typedef map<SettingName, std::string> SettingCollection;
SettingCollection theSettings;
};
#endif /* SRC_XAPP_CONFIG_XAPP_CONFIG_HPP_ */

View File

@@ -0,0 +1,174 @@
/*
==================================================================================
Copyright (c) 2019-2020 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 port, int rmrattempts){
_proto_port = port;
_nattempts = rmrattempts;
_xapp_rmr_ctx = NULL;
_xapp_received_buff = NULL;
_xapp_send_buff =NULL;
_rmr_is_ready = false;
_listen = 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(bool rmr_listen){
// Initialize the RMR context
_xapp_rmr_ctx = rmr_init(const_cast<char*>(_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__);
//Set the listener requirement
_listen = rmr_listen;
return;
}
bool XappRmr::rmr_header(xapp_rmr_header *hdr){
_xapp_send_buff->mtype = hdr->message_type;
_xapp_send_buff->len = hdr->payload_length;
_xapp_send_buff->sub_id = -1;
rmr_str2meid(_xapp_send_buff, hdr->meid);
return true;
}
//RMR Send with payload and header.
bool XappRmr::xapp_rmr_send(xapp_rmr_header *hdr, void *payload){
// Get the thread id
std::thread::id my_id = std::this_thread::get_id();
std::stringstream thread_id;
std::stringstream ss;
thread_id << my_id;
mdclog_write(MDCLOG_INFO, "Sending thread %s", thread_id.str().c_str());
int rmr_attempts = _nattempts;
if( _xapp_send_buff == NULL ) {
_xapp_send_buff = rmr_alloc_msg(_xapp_rmr_ctx, RMR_DEF_SIZE);
}
bool res = rmr_header(hdr);
if(!res){
mdclog_write(MDCLOG_ERR,"RMR HEADERS were incorrectly populated, file= %s, line=%d",__FILE__,__LINE__);
return false;
}
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;
}
while(rmr_attempts > 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, attempt=%d",__FILE__,__LINE__,rmr_attempts);
rmr_attempts--;
}
else if (_xapp_send_buff->state == RMR_OK){
mdclog_write(MDCLOG_INFO,"Message Sent: RMR State = RMR_OK");
rmr_attempts = 0;
_xapp_send_buff = NULL;
return true;
}
else
{
mdclog_write(MDCLOG_INFO,"Need to retry RMR: state=%d, attempt=%d, file=%s, line=%d",_xapp_send_buff->state, rmr_attempts,__FILE__,__LINE__);
if(_xapp_send_buff->state == RMR_ERR_RETRY){
usleep(1); }
rmr_attempts--;
}
sleep(1);
}
return false;
}
//----------------------------------------
// Some get/set methods
//---------------------------------------
bool XappRmr::get_listen(void){
return _listen;
}
void XappRmr::set_listen(bool listen){
_listen = listen;
}
int XappRmr::get_is_ready(void){
return _rmr_is_ready;
}
bool XappRmr::get_isRunning(void){
return _listen;
}
void * XappRmr::get_rmr_context(void){
return _xapp_rmr_ctx;
}
void init_logger(const char *AppName, mdclog_severity_t log_level)
{
mdclog_attr_t *attr;
mdclog_attr_init(&attr);
mdclog_attr_set_ident(attr, AppName);
mdclog_init(attr);
mdclog_level_set(log_level);
mdclog_attr_destroy(attr);
}

View File

@@ -0,0 +1,175 @@
/*
==================================================================================
Copyright (c) 2019-2020 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 <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <error.h>
#include <assert.h>
#include <sstream>
#include <thread>
#include <functional>
#include <map>
#include <mutex>
#include <sys/epoll.h>
#include <rmr/rmr.h>
#include <rmr/RIC_message_types.h>
#include <mdclog/mdclog.h>
#include <vector>
typedef struct{
struct timespec ts;
int32_t message_type;
int32_t state;
int32_t payload_length;
unsigned char sid[RMR_MAX_SID]; //Subscription ID.
unsigned char src[RMR_MAX_SRC]; //Xapp Name
unsigned char meid[RMR_MAX_MEID]={};
} xapp_rmr_header;
class XappRmr{
private:
std::string _proto_port;
int _nattempts;
bool _rmr_is_ready;
bool _listen;
void* _xapp_rmr_ctx;
rmr_mbuf_t* _xapp_send_buff; // send buffer
rmr_mbuf_t* _xapp_received_buff; // received buffer
public:
XappRmr(std::string, int rmrattempts=10);
~XappRmr(void);
void xapp_rmr_init(bool);
template <class MessageProcessor>
void xapp_rmr_receive(MessageProcessor&&, XappRmr *parent);
bool xapp_rmr_send(xapp_rmr_header*, void*);
bool rmr_header(xapp_rmr_header*);
void set_listen(bool);
bool get_listen(void);
int get_is_ready(void);
bool get_isRunning(void);
void* get_rmr_context(void);
};
// main workhorse thread which does the listen->process->respond loop
template <class MsgHandler>
void XappRmr::xapp_rmr_receive(MsgHandler&& msgproc, XappRmr *parent){
bool* resend = new bool(false);
// Get the thread id
std::thread::id my_id = std::this_thread::get_id();
std::stringstream thread_id;
std::stringstream ss;
thread_id << my_id;
// Get the rmr context from parent (all threads and parent use same rmr context. rmr context is expected to be thread safe)
if(!parent->get_is_ready()){
mdclog_write( MDCLOG_ERR, "RMR Shows Not Ready in RECEIVER, file= %s, line=%d ",__FILE__,__LINE__);
return;
}
void *rmr_context = parent->get_rmr_context();
assert(rmr_context != NULL);
// Get buffer specific to this thread
this->_xapp_received_buff = NULL;
this->_xapp_received_buff = rmr_alloc_msg(rmr_context, RMR_DEF_SIZE);
assert(this->_xapp_received_buff != NULL);
mdclog_write(MDCLOG_INFO, "Starting receiver thread %s", thread_id.str().c_str());
while(parent->get_listen()) {
mdclog_write(MDCLOG_INFO, "Listening at Thread: %s", thread_id.str().c_str());
this->_xapp_received_buff = rmr_rcv_msg( rmr_context, this->_xapp_received_buff );
//this->_xapp_received_buff = rmr_rcv_msg( rmr_context, this->_xapp_received_buff );
//this->_xapp_received_buff = rmr_call( rmr_context, this->_xapp_received_buff);
if( this->_xapp_received_buff->mtype < 0 || this->_xapp_received_buff->state != RMR_OK ) {
mdclog_write(MDCLOG_ERR, "bad msg: state=%d errno=%d, file= %s, line=%d", this->_xapp_received_buff->state, errno, __FILE__,__LINE__ );
return;
}
else
{
mdclog_write(MDCLOG_INFO,"RMR Received Message of Type: %d, Message length: %d", this->_xapp_received_buff->mtype, this->_xapp_received_buff->len);
char printBuffer[4096] = {0};
char *tmp = printBuffer;
for (size_t i = 0; i < (size_t)_xapp_received_buff->len; ++i) {
snprintf(tmp, 3, "%02x", _xapp_received_buff->payload[i]);
tmp += 2;
}
mdclog_write(MDCLOG_INFO,"RMR Received Message: %s", printBuffer);
//in case message handler returns true, need to resend the message.
msgproc(this->_xapp_received_buff, resend);
if(*resend){
mdclog_write(MDCLOG_INFO,"RMR Return to Sender Message of Type: %d, Message length: %d", this->_xapp_received_buff->mtype, this->_xapp_received_buff->len);
mdclog_write(MDCLOG_INFO,"RMR Return to Sender Message: %s", printBuffer);
rmr_rts_msg(rmr_context, this->_xapp_received_buff );
sleep(1);
*resend = false;
}
continue;
}
}
// Clean up
try{
delete resend;
rmr_free_msg(this->_xapp_received_buff);
}
catch(std::runtime_error &e){
std::string identifier = __FILE__ + std::string(", Line: ") + std::to_string(__LINE__) ;
std::string error_string = identifier = " Error freeing RMR message ";
mdclog_write(MDCLOG_ERR, error_string.c_str(), "");
}
return;
}
#endif /* XAPP_RMR_XAPP_RMR_H_ */

View File

@@ -0,0 +1,71 @@
/*
==================================================================================
Copyright (c) 2019-2020 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.cc
*
* Created on: Mar, 2020
* Author: Shraboni Jana
*/
#include "xapp_sdl.hpp"
/*need to work on the SDL FLow. Currently data hardcoded.
An xApp can use the SDL for two things:
- persisting state for itself (in case it fails and recovers)
- making information available for other xApps. The xApp would typically write using SDL directly.
- The consumer of the data could also use SDL directly or use an access library like in the case of the R-NIB.
*/
bool XappSDL::set_data(shareddatalayer::SyncStorage *sdl){
try{
//connecting to the Redis and generating a random key for namespace "hwxapp"
mdclog_write(MDCLOG_INFO, "IN SDL Set Data", __FILE__, __LINE__);
DataMap dmap;
char key[4]="abc";
std::cout << "KEY: "<< key << std::endl;
Key k = key;
Data d;
uint8_t num = 101;
d.push_back(num);
dmap.insert({k,d});
Namespace ns(sdl_namespace);
sdl->set(ns, dmap);
}
catch(...){
mdclog_write(MDCLOG_ERR, "SDL Error in Set Data for Namespace=%s",sdl_namespace);
return false;
}
return true;
}
void XappSDL::get_data(shareddatalayer::SyncStorage *sdl){
Namespace ns(sdl_namespace);
DataMap dmap;
std::string prefix="";
Keys K = sdl->findKeys(ns, prefix); // just the prefix
DataMap Dk = sdl->get(ns, K);
for(auto si=K.begin();si!=K.end();++si){
std::vector<uint8_t> val_v = Dk[(*si)]; // 4 lines to unpack a string
char val[val_v.size()+1]; // from Data
int i;
for(i=0;i<val_v.size();++i) val[i] = (char)(val_v[i]);
val[i]='\0';
printf("KEYS and Values %s = %s\n",(*si).c_str(), val);
}
mdclog_write(MDCLOG_INFO, "IN SDL Get Data", __FILE__, __LINE__);
}

View File

@@ -0,0 +1,57 @@
/*
==================================================================================
Copyright (c) 2019-2020 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 <iostream>
#include <string>
#include <memory>
#include <vector>
#include <map>
#include <set>
#include <sdl/syncstorage.hpp>
#include <mdclog/mdclog.h>
using namespace std;
using Namespace = std::string;
using Key = std::string;
using Data = std::vector<uint8_t>;
using DataMap = std::map<Key, Data>;
using Keys = std::set<Key>;
class XappSDL{
private:
std::string sdl_namespace;
public:
XappSDL(std::string ns) { sdl_namespace=ns; }
void get_data(shareddatalayer::SyncStorage *);
bool set_data(shareddatalayer::SyncStorage *);
};
#endif /* SRC_XAPP_UTILS_XAPP_SDL_HPP_ */

View File

@@ -0,0 +1,539 @@
/*
==================================================================================
Copyright (c) 2019-2020 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
*
* Mar, 2020 (Shraboni Jana)
*/
#include "xapp.hpp"
#define BUFFER_SIZE 1024
std::map<string, int> agentIp_socket;
std::map<std::string, std::string> agentIp_gnbId;
std::vector<std::string> drl_agent_ip{AGENT_0};
Xapp::Xapp(XappSettings &config, XappRmr &rmr){
rmr_ref = &rmr;
config_ref = &config;
xapp_mutex = NULL;
subhandler_ref = NULL;
return;
}
Xapp::~Xapp(void){
//Joining the threads
int threadcnt = xapp_rcv_thread.size();
for(int i=0; i<threadcnt; i++){
if(xapp_rcv_thread[i].joinable())
xapp_rcv_thread[i].join();
}
xapp_rcv_thread.clear();
if(xapp_mutex!=NULL){
xapp_mutex->~mutex();
delete xapp_mutex;
}
// close sockets
close_control_socket_agent();
// join threads
for (int i = 0; i < control_thr_rx.size(); ++i) {
if(control_thr_rx[i] && control_thr_rx[i]->joinable()) {
control_thr_rx[i]->join();
}
}
if(ext_control_thr_rx && ext_control_thr_rx->joinable()) {
ext_control_thr_rx->join();
}
};
//Stop the xapp. Note- To be run only from unit test scripts.
void Xapp::stop(void){
// Get the mutex lock
std::lock_guard<std::mutex> guard(*xapp_mutex);
rmr_ref->set_listen(false);
rmr_ref->~XappRmr();
//Detaching the threads....not sure if this is the right way to stop the receiver threads.
//Hence function should be called only in Unit Tests
int threadcnt = xapp_rcv_thread.size();
for(int i=0; i<threadcnt; i++){
xapp_rcv_thread[i].detach();
}
sleep(10);
}
void Xapp::startup(SubscriptionHandler &sub_ref) {
subhandler_ref = &sub_ref;
if (GNB_ID == "") {
// get list of gnbs from ric
std::cout << "Getting gNB list from RIC" << std::endl;
set_rnib_gnblist();
}
else {
// only insert target gnb
std::cout << "Querying target gNB" << std::endl;
rnib_gnblist.push_back(GNB_ID);
}
// open external control socket in thread and wait for message
ext_control_thr_rx = std::unique_ptr<std::thread>(new std::thread{&Xapp::handle_external_control_message, this, SOCKET_PORT_EXT});
for (int i = 0; i < drl_agent_ip.size(); ++i) {
// open control socket with agent
if (open_control_socket_agent(const_cast<char*>(drl_agent_ip[i].c_str()), 4200) == 0) {
// start receive thread
std::unique_ptr<std::thread> tmp_thr = std::unique_ptr<std::thread>(new std::thread{&Xapp::handle_rx_msg_agent, this, drl_agent_ip[i]});
control_thr_rx.push_back(std::move(tmp_thr));
}
}
// send test message
// send_socket("Hello, Server!", AGENT_1);
//send subscriptions.
startup_subscribe_requests();
//read A1 policies
// startup_get_policies();
// send control
// send_ric_control_request();
return;
}
void Xapp::Run(){
rmr_ref->set_listen(true);
if(xapp_mutex == NULL){
xapp_mutex = new std::mutex();
}
std::lock_guard<std::mutex> guard(*xapp_mutex);
for(size_t j=0; j < _callbacks.size(); j++){
std::thread th_recv([&](){ rmr_ref->xapp_rmr_receive(std::move(_callbacks[j]), rmr_ref);});
xapp_rcv_thread.push_back(std::move(th_recv));
}
return;
}
//Starting a seperate single receiver
void Xapp::start_xapp_receiver(XappMsgHandler& mp_handler){
//start a receiver thread. Can be multiple receiver threads for more than 1 listening port.
rmr_ref->set_listen(true);
if(xapp_mutex == NULL){
xapp_mutex = new std::mutex();
}
mdclog_write(MDCLOG_INFO,"Receiver Thread file= %s, line=%d",__FILE__,__LINE__);
std::lock_guard<std::mutex> guard(*xapp_mutex);
std::thread th_recv([&](){ rmr_ref->xapp_rmr_receive(std::move(mp_handler), rmr_ref);});
xapp_rcv_thread.push_back(std::move(th_recv));
return;
}
void Xapp::shutdown(){
return;
}
// handle received message from DRL agent
void Xapp::handle_rx_msg(void) {
std::cout << "handle_rx_msg" << std::endl;
const size_t max_size = 256;
char buf[max_size] = {0};
// listen to control from agent
while (true) {
// iterate through map
std::map<std::string, int>::iterator it;
for (it = agentIp_socket.begin(); it != agentIp_socket.end(); ++it) {
std::string agent_ip = it->first;
int control_sckfd = it->second;
int rcv_size = recv(control_sckfd, buf, max_size, 0);
if (rcv_size > 0) {
std::cout << "Message from agent " << agent_ip << std::endl;
std::cout << buf << std::endl;
// get gnb_id from agent IP
std::map<std::string, std::string>::iterator it_gnb;
it_gnb = agentIp_gnbId.find(agent_ip);
// send RIC control request
if (it_gnb != agentIp_gnbId.end()) {
send_ric_control_request(buf, it_gnb->second);
}
else {
std::cout << "ERROR: No gNB ID found for agent " << agent_ip << std::endl;
}
memset(buf, 0, max_size);
}
}
}
}
// handle received message from a specific DRL agent
void Xapp::handle_rx_msg_agent(std::string agent_ip) {
std::cout << "Opening RX thread with agent " << agent_ip << std::endl;
const size_t max_size = 256;
char buf[max_size] = {0};
// listen to control from agent
while (true) {
// get control_sckfd from agent IP
std::map<std::string, int>::iterator it;
it = agentIp_socket.find(agent_ip);
if (it != agentIp_socket.end()) {
int control_sckfd = it->second;
int rcv_size = recv(control_sckfd, buf, max_size, 0);
if (rcv_size > 0) {
std::cout << "Message from agent " << agent_ip << std::endl;
std::cout << buf << std::endl;
// get gnb_id from agent IP
std::map<std::string, std::string>::iterator it_gnb;
it_gnb = agentIp_gnbId.find(agent_ip);
// send RIC control request
if (it_gnb != agentIp_gnbId.end()) {
send_ric_control_request(buf, it_gnb->second);
}
else {
std::cout << "ERROR: No gNB ID found for agent " << agent_ip << std::endl;
}
memset(buf, 0, max_size);
}
}
}
}
// handle external control socket message
void Xapp::handle_external_control_message(int port) {
// Create a socket (IPv4, TCP)
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
std::cout << "Failed to create socket. errno: " << errno << std::endl;
return;
}
// Listen on given port on any address
sockaddr_in sockaddr;
sockaddr.sin_family = AF_INET;
sockaddr.sin_addr.s_addr = INADDR_ANY;
sockaddr.sin_port = htons(port);
if (bind(sockfd, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0) {
std::cout << "Failed to bind to port. Errno: " << errno << std::endl;
return;
}
// Start listening. Hold at most 10 connections in the queue
if (listen(sockfd, 10) < 0) {
std::cout << "Failed to listen on socket. Errno: " << errno << std::endl;
return;
}
std::cout << "Opened control socket server on port " << port << std::endl;
while (true) {
auto addrlen = sizeof(sockaddr);
int connection = accept(sockfd, (struct sockaddr*)&sockaddr, (socklen_t*)&addrlen);
if (connection < 0) {
continue;
}
// Read from the connection
const size_t max_size = 256;
char buffer[max_size] = {0};
auto bytes_read = read(connection, buffer, 100);
if (bytes_read > 0) {
std::cout << "External control socket. Message received: " << buffer << std::endl;
// TODO: check if message is termination, send to DU and shutdown xApp
if (strcmp(buffer, XAPP_TERMINATE) == 0) {
terminate_du_reporting();
}
}
memset(buffer, 0, max_size);
close(connection);
}
close(sockfd);
return;
}
// terminate all DU reportings and shutdown xApp
void Xapp::terminate_du_reporting(void) {
std::map<std::string, int>::iterator it;
for (it = agentIp_socket.begin(); it != agentIp_socket.end(); ++it) {
std::string agent_ip = it->first;
int control_sckfd = it->second;
// get gnb_id from agent IP
std::map<std::string, std::string>::iterator it_gnb;
it_gnb = agentIp_gnbId.find(agent_ip);
std::cout << "Terminating reporting gNB " << it_gnb->second << std::endl;
send_ric_control_request(XAPP_TERMINATE, it_gnb->second);
}
// stop xapp docker container with SIGTERM (15)
if (DEBUG) {
std::cout << "Debug mode, only echoing" << std::endl;
system("echo kill -s 15 1");
}
else {
system("kill -s 15 1");
}
}
void Xapp::send_ric_control_request(char* payload, std::string gnb_id) {
std::cout << "Sending RIC Control Request" << std::endl;
bool res;
size_t data_size = ASN_BUFF_MAX_SIZE;
unsigned char data[data_size];
unsigned char meid[RMR_MAX_MEID];
std::string xapp_id = config_ref->operator [](XappSettings::SettingName::XAPP_ID);
mdclog_write(MDCLOG_INFO, "Preparing to send control in file= %s, line=%d", __FILE__, __LINE__);
auto gnblist = get_rnib_gnblist();
int sz = gnblist.size();
if(sz <= 0) {
mdclog_write(MDCLOG_INFO, "Subscriptions cannot be sent as GNBList in RNIB is NULL");
return;
}
// give the message to subscription handler, along with the transmitter.
strcpy((char*)meid, gnb_id.c_str());
std::cout << "RIC Control Request, gNB " << gnb_id << std::endl;
// helpers
// set fields randomly
ric_control_helper din {};
//= {
// 1,
// 1,
// 0,
// 1,
// -1,
// 0,
// 0,
// 1,
// "test", // control_msg
// 5, // control_msg_size
// "testh", // control header
// 6,
// "testp", // call process id
// 6
//};
const char* msg = payload;
din.control_msg_size = strlen(msg) + 1;
mdclog_write(MDCLOG_INFO, "Size of msg %d", din.control_msg_size);
din.control_msg = (uint8_t*) calloc(din.control_msg_size, sizeof(uint8_t));
std::memcpy(din.control_msg, msg, din.control_msg_size);
ric_control_helper dout {};
// control request object
ric_control_request ctrl_req {};
ric_control_request ctrl_recv {};
unsigned char buf[BUFFER_SIZE];
size_t buf_size = BUFFER_SIZE;
res = ctrl_req.encode_e2ap_control_request(&buf[0], &buf_size, din);
xapp_rmr_header rmr_header;
rmr_header.message_type = RIC_CONTROL_REQ;
rmr_header.payload_length = buf_size; //data_size
strcpy((char*)rmr_header.meid, gnb_id.c_str());
mdclog_write(MDCLOG_INFO, "Sending CTRL REQ in file= %s, line=%d for MEID %s", __FILE__, __LINE__, meid);
int result = rmr_ref->xapp_rmr_send(&rmr_header, (void*)buf);
if(result) {
mdclog_write(MDCLOG_INFO, "CTRL REQ SUCCESSFUL in file= %s, line=%d for MEID %s",__FILE__,__LINE__, meid);
}
}
void Xapp::startup_subscribe_requests(void ){
bool res;
size_t data_size = ASN_BUFF_MAX_SIZE;
unsigned char data[data_size];
unsigned char meid[RMR_MAX_MEID];
std::string xapp_id = config_ref->operator [](XappSettings::SettingName::XAPP_ID);
mdclog_write(MDCLOG_INFO,"Preparing to send subscription in file= %s, line=%d", __FILE__, __LINE__);
auto gnblist = get_rnib_gnblist();
int sz = gnblist.size();
if(sz <= 0)
mdclog_write(MDCLOG_INFO,"Subscriptions cannot be sent as GNBList in RNIB is NULL");
for(int i = 0; i<sz; i++){
std::cout << "Sending subscriptions to: " << gnblist[i] << std::endl;
// give the message to subscription handler, along with the transmitter.
strcpy((char*)meid,gnblist[i].c_str());
// char *strMsg = "Subscription Request from HelloWorld XApp\0";
// strncpy((char *)data,strMsg,strlen(strMsg));
// data_size = strlen(strMsg);
subscription_helper din;
subscription_helper dout;
subscription_request sub_req;
subscription_request sub_recv;
unsigned char buf[BUFFER_SIZE];
size_t buf_size = BUFFER_SIZE;
bool res;
//Random Data for request
int request_id = XAPP_REQ_ID;
int function_id = 0;
// DU report timer in ms
std::string event_def = "1000";
din.set_request(request_id);
din.set_function_id(function_id);
din.set_event_def(event_def.c_str(), event_def.length());
std::string act_def = "HelloWorld Action Definition";
din.add_action(1,1,(void*)act_def.c_str(), act_def.length(), 0);
res = sub_req.encode_e2ap_subscription(&buf[0], &buf_size, din);
xapp_rmr_header rmr_header;
rmr_header.message_type = RIC_SUB_REQ;
rmr_header.payload_length = buf_size; //data_size
strcpy((char*)rmr_header.meid,gnblist[i].c_str());
mdclog_write(MDCLOG_INFO,"Sending subscription in file= %s, line=%d for MEID %s",__FILE__,__LINE__, meid);
auto transmitter = std::bind(&XappRmr::xapp_rmr_send,rmr_ref, &rmr_header, (void*)buf );//(void*)data);
int result = subhandler_ref->manage_subscription_request(meid, transmitter);
if(result){
mdclog_write(MDCLOG_INFO,"Subscription SUCCESSFUL in file= %s, line=%d for MEID %s",__FILE__,__LINE__, meid);
}
}
}
void Xapp::startup_get_policies(void){
int policy_id = HELLOWORLD_POLICY_ID;
std::string policy_query = "{\"policy_type_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::set_rnib_gnblist(void) {
openSdl();
void *result = getListGnbIds();
if(strlen((char*)result) < 1){
mdclog_write(MDCLOG_ERR, "ERROR: no data from getListGnbIds\n");
return;
}
mdclog_write(MDCLOG_INFO, "GNB List in R-NIB %s\n", (char*)result);
// remove non-unicode characters that make rapodjson fail the parsing
std::string result_clean((char*) result);
while (result_clean.back() != '}') {
result_clean.pop_back();
}
Document doc;
ParseResult parseJson = doc.Parse(result_clean.c_str());
if (!parseJson) {
//std::cerr << "JSON parse error: %s (%u)\n", GetParseErrorFunc(parseJson.Code());
std::cerr << "JSON parse error: " << GetParseErrorFunc(parseJson.Code()) << std::endl;
return;
}
if(!doc.HasMember("gnb_list")){
mdclog_write(MDCLOG_INFO, "JSON Has No GNB List Object");
return;
}
assert(doc.HasMember("gnb_list"));
const Value& gnblist = doc["gnb_list"];
if (gnblist.IsNull())
return;
if(!gnblist.IsArray()){
mdclog_write(MDCLOG_INFO, "GNB List is not an array");
return;
}
assert(gnblist.IsArray());
for (SizeType i = 0; i < gnblist.Size(); i++) { // Uses SizeType instead of size_t
assert(gnblist[i].IsObject());
const Value& gnbobj = gnblist[i];
assert(gnbobj.HasMember("inventory_name"));
assert(gnbobj["inventory_name"].IsString());
std::string name = gnbobj["inventory_name"].GetString();
rnib_gnblist.push_back(name);
}
closeSdl();
return;
}

View File

@@ -0,0 +1,125 @@
/*
==================================================================================
Copyright (c) 2019-2020 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
*
* Mar, 2020 (Shraboni Jana)
*
*/
#pragma once
#ifndef SRC_XAPP_HPP_
#define SRC_XAPP_HPP_
#include <iostream>
#include <string>
#include <memory>
#include <csignal>
#include <stdio.h>
#include <pthread.h>
#include <unordered_map>
#include "xapp_rmr.hpp"
#include "xapp_sdl.hpp"
#include "rapidjson/writer.h"
#include "rapidjson/document.h"
#include "rapidjson/error/error.h"
#include <thread>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "agent_connector.hpp"
#include <vector>
#include "msgs_proc.hpp"
#include "subs_mgmt.hpp"
#include "xapp_config.hpp"
extern "C" {
#include "rnib/rnibreader.h"
}
using namespace std;
using namespace std::placeholders;
using namespace rapidjson;
// used to identify xApp requests with DUs
// Note: this value is updated at Docker build to use the last octet of the xApp IP
#define XAPP_REQ_ID 0
#define SOCKET_PORT_EXT 7000
#define XAPP_TERMINATE "terminate"
// id of gnb to control as seen from the ric
#define GNB_ID ""
#define DEBUG 0
class Xapp{
public:
Xapp(XappSettings &, XappRmr &);
~Xapp(void);
void stop(void);
void startup(SubscriptionHandler &);
void shutdown(void);
void start_xapp_receiver(XappMsgHandler &);
void Run();
void sdl_data(void);
Xapp(Xapp const &)=delete;
Xapp& operator=(Xapp const &) = delete;
void register_handler(XappMsgHandler &fn){
_callbacks.emplace_back(fn);
}
//getters/setters.
void set_rnib_gnblist(void);
std::vector<std::string> get_rnib_gnblist(){ return rnib_gnblist; }
private:
void startup_subscribe_requests(void );
void shutdown_subscribe_deletes(void);
void send_ric_control_request(char* payload, std::string gnb_id);
void startup_get_policies(void );
void handle_rx_msg(void);
void handle_rx_msg_agent(std::string agent_ip);
void handle_external_control_message(int port);
void terminate_du_reporting(void);
XappRmr * rmr_ref;
XappSettings * config_ref;
SubscriptionHandler *subhandler_ref;
std::mutex *xapp_mutex;
std::vector<std::thread> xapp_rcv_thread;
std::vector<std::string> rnib_gnblist;
std::vector<XappMsgHandler> _callbacks;
std::vector<std::unique_ptr<std::thread>> control_thr_rx;
std::unique_ptr<std::thread> ext_control_thr_rx;
};
#endif /* SRC_XAPP_HPP_ */

View File

@@ -0,0 +1,12 @@
#! /bin/bash
export RMR_SEED_RT="routes.txt"
export RMR_RTG_SVC="9999"
export MSG_MAX_BUFFER="2072"
export THREADS="1"
export VERBOSE="0"
export CONFIG_FILE="config/config-file.json"
export XAPP_ID="3489-er492k-92389"
export LOG_LEVEL="MDCLOG_ERR"
export DBAAS_SERVICE_HOST="10.0.2.12"
export DBAAS_SERVICE_PORT="6379"