#include "viavi_connector.hpp"
#include "errno.h"
#include "e2sim_defs.h"
+#include <cstdlib>
+
using json = nlohmann::json;
using namespace std;
class E2Sim;
-
+int gFuncId;
E2Sim e2sim;
ranfunc_ostr->buf = (uint8_t*)calloc(1,er.encoded);
ranfunc_ostr->size = er.encoded;
memcpy(ranfunc_ostr->buf,e2smbuffer,er.encoded);
-
- e2sim.register_e2sm(0,ranfunc_ostr);
- e2sim.register_subscription_callback(0,&callback_kpm_subscription_request);
+ const char* func_id_str = std::getenv("RAN_FUNC_ID");
+ ::gFuncId = func_id_str == nullptr ? 0 : std::stoi(func_id_str);
+
+ e2sim.register_e2sm(gFuncId, ranfunc_ostr);
+ e2sim.register_subscription_callback(gFuncId, &callback_kpm_subscription_request);
e2sim.run_loop(argc, argv);
}
LOG_I("Buffer of size %zu is too small for %s, need %zu\n", e2sm_message_buf_size_cucp_ue, asn_DEF_E2SM_KPM_IndicationMessage.name, er_message_cucp_ue.encoded);
exit(1);
} else {
- LOG_I("Encoded UE indication message succesfully, size in bytes: %d", er_message_cucp_ue.encoded)
+ LOG_I("Encoded UE indication message succesfully, size in bytes: %zu", er_message_cucp_ue.encoded)
}
ASN_STRUCT_FREE(asn_DEF_E2SM_KPM_IndicationMessage, ind_msg_cucp_ue);
LOG_I("Buffer of size %zu is too small for %s, need %zu\n", e2sm_header_buf_size_cucp_ue, asn_DEF_E2SM_KPM_IndicationHeader.name, er_header_cucp_ue.encoded);
exit(1);
} else {
- LOG_I("Encoded UE indication header succesfully, size in bytes: %d", er_header_cucp_ue.encoded);
+ LOG_I("Encoded UE indication header succesfully, size in bytes: %zu", er_header_cucp_ue.encoded);
for(int i = 0; i < er_header_cucp_ue.encoded; i ++) {
printf("%x ", e2sm_header_buf_cucp_ue[i]);
}
er_message_cucp_ue.encoded);
e2sim.encode_and_send_sctp_data(pdu_cucp_ue);
- LOG_I("Measurement report for UE %d has been sent\n", i);
+ LOG_I("Measurement report for UE %d has been sent", i);
seqNum++;
std::this_thread::sleep_for (std::chrono::milliseconds(50));
}
e2sm_message_buf_style1, e2sm_message_buf_size_style1);
if(er_message_style1.encoded == -1) {
- LOG_I("Failed to serialize data. Detail: %s.\n", asn_DEF_E2SM_KPM_IndicationMessage.name);
+ LOG_I("Failed to serialize data. Detail: %s.", asn_DEF_E2SM_KPM_IndicationMessage.name);
exit(1);
} else if(er_message_style1.encoded > e2sm_message_buf_size_style1) {
LOG_I("Buffer of size %zu is too small for %s, need %zu\n", e2sm_message_buf_size_style1, asn_DEF_E2SM_KPM_IndicationMessage.name, er_message_style1.encoded);
exit(1);
} else {
- LOG_I("Encoded Cell indication message succesfully, size in bytes: %d", er_message_style1.encoded)
+ LOG_I("Encoded Cell indication message succesfully, size in bytes: %ld", er_message_style1.encoded)
}
ASN_STRUCT_FREE(asn_DEF_E2SM_KPM_IndicationMessage, ind_message_style1);
void callback_kpm_subscription_request(E2AP_PDU_t *sub_req_pdu) {
- fprintf(stderr, "[%s:%d]Calling callback_kpm_subscription_request");
-
//Record RIC Request ID
//Go through RIC action to be Setup List
//Find first entry with REPORT action Type
RICsubscriptionRequest_IEs_t *next_ie = ies[i];
pres = next_ie->value.present;
- LOG_I("The next present value %d\n", pres);
+ LOG_I("The next present value %d", pres);
switch(pres) {
- case RICsubscriptionRequest_IEs__value_PR_RICrequestID:
- {
- LOG_I("in case request id");
- RICrequestID_t reqId = next_ie->value.choice.RICrequestID;
- long requestorId = reqId.ricRequestorID;
- long instanceId = reqId.ricInstanceID;
- LOG_I("requestorId %d\n", requestorId);
- LOG_I("instanceId %d\n", instanceId);
- reqRequestorId = requestorId;
- reqInstanceId = instanceId;
-
- break;
- }
- case RICsubscriptionRequest_IEs__value_PR_RANfunctionID:
- {
- LOG_I("in case ran func id");
- break;
- }
- case RICsubscriptionRequest_IEs__value_PR_RICsubscriptionDetails:
- {
- RICsubscriptionDetails_t subDetails = next_ie->value.choice.RICsubscriptionDetails;
- RICeventTriggerDefinition_t triggerDef = subDetails.ricEventTriggerDefinition;
- RICactions_ToBeSetup_List_t actionList = subDetails.ricAction_ToBeSetup_List;
- //We are ignoring the trigger definition
-
- //We identify the first action whose type is REPORT
- //That is the only one accepted; all others are rejected
-
- int actionCount = actionList.list.count;
- LOG_I("Action count%d\n", actionCount);
+ case RICsubscriptionRequest_IEs__value_PR_RICrequestID: {
+ LOG_I("in case request id");
+ RICrequestID_t reqId = next_ie->value.choice.RICrequestID;
+ long requestorId = reqId.ricRequestorID;
+ long instanceId = reqId.ricInstanceID;
- auto **item_array = actionList.list.array;
+ LOG_I("requestorId: %ld, InstanceID: %ld", requestorId, instanceId);
- bool foundAction = false;
+ reqRequestorId = requestorId;
+ reqInstanceId = instanceId;
- for (int i=0; i < actionCount; i++) {
+ break;
+ }
+ case RICsubscriptionRequest_IEs__value_PR_RANfunctionID: {
+ LOG_I("in case ran func id");
+ break;
+ }
+ case RICsubscriptionRequest_IEs__value_PR_RICsubscriptionDetails: {
+ RICsubscriptionDetails_t subDetails = next_ie->value.choice.RICsubscriptionDetails;
+ RICeventTriggerDefinition_t triggerDef = subDetails.ricEventTriggerDefinition;
+ RICactions_ToBeSetup_List_t actionList = subDetails.ricAction_ToBeSetup_List;
+ //We are ignoring the trigger definition
- auto *next_item = item_array[i];
- RICactionID_t actionId = ((RICaction_ToBeSetup_ItemIEs*)next_item)->value.choice.RICaction_ToBeSetup_Item.ricActionID;
- RICactionType_t actionType = ((RICaction_ToBeSetup_ItemIEs*)next_item)->value.choice.RICaction_ToBeSetup_Item.ricActionType;
+ //We identify the first action whose type is REPORT
+ //That is the only one accepted; all others are rejected
- if (!foundAction && actionType == RICactionType_report) {
- reqActionId = actionId;
- actionIdsAccept.push_back(reqActionId);
- foundAction = true;
- } else {
- reqActionId = actionId;
- actionIdsReject.push_back(reqActionId);
- }
- }
-
- break;
- }
- default:
- {
- break;
- }
+ int actionCount = actionList.list.count;
+ LOG_I("Action count%d", actionCount);
+
+ auto **item_array = actionList.list.array;
+
+ bool foundAction = false;
+
+ for (int i=0; i < actionCount; i++) {
+ auto *next_item = item_array[i];
+ RICactionID_t actionId = ((RICaction_ToBeSetup_ItemIEs*)next_item)->value.choice.RICaction_ToBeSetup_Item.ricActionID;
+ RICactionType_t actionType = ((RICaction_ToBeSetup_ItemIEs*)next_item)->value.choice.RICaction_ToBeSetup_Item.ricActionType;
+
+ if (!foundAction && actionType == RICactionType_report) {
+ reqActionId = actionId;
+ actionIdsAccept.push_back(reqActionId);
+ foundAction = true;
+ } else {
+ reqActionId = actionId;
+ actionIdsReject.push_back(reqActionId);
+ }
+ }
+
+ break;
+ }
+ default: {
+ break;
+ }
}
}
LOG_I("After Processing Subscription Request");
- LOG_I("requestorId %d\n", reqRequestorId);
- LOG_I("instanceId %d\n", reqInstanceId);
-
-
for (int i=0; i < actionIdsAccept.size(); i++) {
- LOG_I("Action ID %d %ld\n", i, actionIdsAccept.at(i));
-
+ LOG_D("Action ID %d %ld\n", i, actionIdsAccept.at(i));
}
E2AP_PDU *e2ap_pdu = (E2AP_PDU*)calloc(1,sizeof(E2AP_PDU));
LOG_I("Encode and sending E2AP subscription success response via SCTP");
e2sim.encode_and_send_sctp_data(e2ap_pdu);
- long funcId = 0;
-
- run_report_loop(reqRequestorId, reqInstanceId, funcId, reqActionId);
+ LOG_I("Now generating data for subscription request");
+ run_report_loop(reqRequestorId, reqInstanceId, gFuncId, reqActionId);
}
else { \
fileName = file; \
} \
- printf("[%s:%d] ", fileName, __LINE__); \
- printf(format, ##__VA_ARGS__); \
- printf("\n"); \
+ fprintf(stderr, "[%s:%d] [INFO] ", fileName, __LINE__); \
+ fprintf(stderr, format, ##__VA_ARGS__); \
+ fprintf(stderr, "\n"); \
+ } while (0);
+
+#define LOG_D(format, ...) \
+ do { \
+ const char *file = __FILE__; \
+ const char *fileName = strrchr(file, '/'); \
+ if (fileName != NULL) { \
+ fileName++; \
+ } \
+ else { \
+ fileName = file; \
+ } \
+ fprintf(stderr, "[%s:%d] [DEBUG] ", fileName, __LINE__); \
+ fprintf(stderr, format, ##__VA_ARGS__); \
+ fprintf(stderr, "\n"); \
+ } while (0);
+
+#define LOG_E(format, ...) \
+ do { \
+ const char *file = __FILE__; \
+ const char *fileName = strrchr(file, '/'); \
+ if (fileName != NULL) { \
+ fileName++; \
+ } \
+ else { \
+ fileName = file; \
+ } \
+ fprintf(stderr, "[%s:%d] [ERROR] ", fileName, __LINE__); \
+ fprintf(stderr, format, ##__VA_ARGS__); \
+ fprintf(stderr, "\n"); \
} while (0);
-#define LOG_E(...) {printf(__VA_ARGS__); printf("\n");}
-#define LOG_D(...) {printf(__VA_ARGS__); printf("\n");}
typedef struct SCTP_DATA {
unsigned char *data;
}
void E2Sim::register_subscription_callback(long func_id, SubscriptionCallback cb) {
- LOG_I("About to register callback for subscription for func_id %d", func_id);
+ LOG_I("About to register callback for subscription for RAN function with ID %d", func_id);
subscription_callbacks[func_id] = cb;
}
//Error conditions:
//If we already have an entry for func_id
- LOG_I("About to register e2sm func desc for %d", func_id);
+ LOG_I("About to register E2SM RAN function description with ID %d", func_id);
ran_functions_registered[func_id] = ostr;
}
int E2Sim::run_loop(int argc, char* argv[]){
- printf("Start E2 Agent (E2 Simulator\n");
+ LOG_I("Start E2 Agent (E2 Simulator)");
ifstream simfile;
string line;
options_t ops = read_input_options(argc, argv);
- printf("After reading input options\n");
+ LOG_I("After reading input options");
//E2 Agent will automatically restart upon sctp disconnection
// int server_fd = sctp_start_server(ops.server_ip, ops.server_port);
client_fd = sctp_start_client(ops.server_ip, ops.server_port);
E2AP_PDU_t* pdu_setup = (E2AP_PDU_t*)calloc(1,sizeof(E2AP_PDU));
- printf("After starting client\n");
- printf("client_fd value is %d\n", client_fd);
+ LOG_I("SCTP client has been started");
std::vector<encoding::ran_func_info> all_funcs;
RANfunctionOID_t *ranFunctionOIDe = (RANfunctionOID_t*)calloc(1,sizeof(RANfunctionOID_t));
ranFunctionOIDe->size = strlen((char*)buf);
//Loop through RAN function definitions that are registered
-
+ LOG_I("Constructing a list of RAN functions based on registered information");
for (std::pair<long, OCTET_STRING_t*> elem : ran_functions_registered) {
- printf("looping through ran func\n");
+ char* ran_desc = (char*) calloc(1, elem.second->size+1);
+ ran_desc = (char*)elem.second->buf;
+ ran_desc[elem.second->size] = '\0';
+
+ LOG_I("Adding RAN function ID %ld, description: %s to the list", elem.first, ran_desc);
+
encoding::ran_func_info next_func;
next_func.ranFunctionId = elem.first;
all_funcs.push_back(next_func);
}
- printf("about to call setup request encode\n");
+ LOG_I("Generate E2AP v1 setup request for all registered RAN functions");
generate_e2apv1_setup_request_parameterized(pdu_setup, all_funcs);
- printf("After generating e2setup req\n");
-
xer_fprint(stderr, &asn_DEF_E2AP_PDU, pdu_setup);
- printf("After XER Encoding\n");
-
auto buffer_size = MAX_SCTP_BUFFER;
unsigned char buffer[MAX_SCTP_BUFFER];
size_t errlen = 0;
asn_check_constraints(&asn_DEF_E2AP_PDU, pdu_setup, error_buf, &errlen);
- printf("error length %d\n", errlen);
- printf("error buf %s\n", error_buf);
+ LOG_I("Error length %d, error buf %s", errlen, error_buf);
auto er = asn_encode_to_buffer(nullptr, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2AP_PDU, pdu_setup, buffer, buffer_size);
data.len = er.encoded;
- fprintf(stderr, "er encded is %d\n", er.encoded);
+ LOG_I("Error encoded %d", er.encoded);
memcpy(data.buffer, buffer, er.encoded);
if(sctp_send_data(client_fd, data) > 0) {
- LOG_I("[SCTP] Sent E2-SETUP-REQUEST");
+ LOG_I("Sent E2-SETUP-REQUEST as E2AP message");
} else {
- LOG_E("[SCTP] Unable to send E2-SETUP-REQUEST to peer");
+ LOG_E("Fail to send E2-SETUP-REQUEST to peer");
}
buffer_size = MAX_SCTP_BUFFER;
memset(buffer, '\0', sizeof(buffer));
- E2AP_PDU_t* pdu = (E2AP_PDU_t*)calloc(1,sizeof(E2AP_PDU));
-
- LOG_D("about to call E2ResetRequest encode\n");
-
- encoding::generate_e2apv2_reset_request(pdu);
-
- LOG_D("[E2AP] Created E2ResetRequest");
-
- e2ap_asn1c_print_pdu(pdu);
-
- sctp_buffer_t resetdata;
-
- error_buf[300] = {0, };
- errlen = 0;
-
- asn_check_constraints(&asn_DEF_E2AP_PDU, pdu, error_buf, &errlen);
- printf("error length %d\n", errlen);
- printf("error buf %s\n", error_buf);
- er = asn_encode_to_buffer(nullptr, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2AP_PDU, pdu, buffer, buffer_size);
-
- resetdata.len = er.encoded;
- fprintf(stderr, "er encoded is %d\n", er.encoded);
-
- memcpy(resetdata.buffer, buffer, er.encoded);
-
- LOG_I("Test to delete ReSet code");
sctp_buffer_t recv_buf;
- LOG_I("[SCTP] Waiting for SCTP data");
+ LOG_I("Waiting for SCTP data");
while(1) //constantly looking for data on SCTP interface
{
if(sctp_receive_data(client_fd, recv_buf) <= 0)
break;
- LOG_I("[SCTP] Received new data of size %d", recv_buf.len);
+ LOG_I("Received new data of size %d", recv_buf.len);
e2ap_handle_sctp_data(client_fd, recv_buf, xmlenc, this);
if (xmlenc) xmlenc = false;
}
+ close(client_fd);
+
return 0;
}
void e2ap_asn1c_print_pdu(const E2AP_PDU_t* pdu)
{
- printf("before\n");
// xer_fprint(stdout, &asn_DEF_E2AP_PDU, (void *)pdu);
xer_fprint(stdout, &asn_DEF_E2AP_PDU, pdu);
- printf("after\n");
- printf("\n");
}
void asn1c_xer_print(asn_TYPE_descriptor_t *typeDescriptor, void *data)
{
xer_fprint(stdout, typeDescriptor, (void *)data);
- printf("\n");
}
switch(pdu->present)
{
case E2AP_PDU_PR_initiatingMessage:
- fprintf(stderr,"initiating message\n");
+ LOG_I("Initiating E2AP PDU PR message");
procedureCode = pdu->choice.initiatingMessage->procedureCode;
break;
break;\r
}\r
\r
- int procedureCode = e2ap_asn1c_get_procedureCode(pdu);\r
- int index = (int)pdu->present;\r
-\r
- LOG_D("Unpacked E2AP-PDU: index = %d, procedureCode = %d\n", index, procedureCode);\r
-\r
- switch (procedureCode) {\r
- case ProcedureCode_id_E2setup:\r
+ int procedureCode = e2ap_asn1c_get_procedureCode(pdu);
+ int index = (int)pdu->present;
+
+ LOG_D("Unpacked E2AP-PDU: index = %d, procedureCode = %d", index, procedureCode);
+
+ switch (procedureCode) {
+ case ProcedureCode_id_E2setup:
LOG_I("Received a message of E2 setup procedure");\r
switch (index) {\r
case E2AP_PDU_PR_initiatingMessage:\r
break;\r
\r
case ProcedureCode_id_RICsubscription: // RIC SUBSCRIPTION = 201\r
- LOG_I("Received a message of RIC subscription procedure");\r
- switch (index) {\r
- case E2AP_PDU_PR_initiatingMessage: { // initiatingMessage\r
- LOG_I("Received RIC-SUBSCRIPTION-REQUEST");\r
- // e2ap_handle_RICSubscriptionRequest(pdu, socket_fd);\r
- long func_id = encoding::get_function_id_from_subscription(pdu);\r
- fprintf(stderr, "Function Id of message is %d\n", func_id);\r
- SubscriptionCallback cb;\r
-\r
- bool func_exists = true;\r
-\r
- try {\r
- cb = e2sim->get_subscription_callback(func_id);\r
- } catch (const std::out_of_range& e) {\r
- func_exists = false;\r
- }\r
-\r
- if (func_exists) {\r
- fprintf(stderr, "Calling callback function\n");\r
- cb(pdu);\r
- } else {\r
- fprintf(stderr, "Error: No RAN Function with this ID exists\n");\r
- }\r
- // callback_kpm_subscription_request(pdu, socket_fd);\r
-\r
- } break;\r
-\r
- case E2AP_PDU_PR_successfulOutcome:\r
- LOG_I("Received RIC-SUBSCRIPTION-RESPONSE");\r
+ LOG_I("Received a message of RIC subscription procedure");
+ switch (index) {
+ case E2AP_PDU_PR_initiatingMessage: { // initiatingMessage
+ long func_id = encoding::get_function_id_from_subscription(pdu);
+ LOG_I("Received RIC subscription request for function with ID %d", func_id);
+
+ try {
+ SubscriptionCallback cb;
+ cb = e2sim->get_subscription_callback(func_id);
+ LOG_I("Calling callback subscription function to handle subscription request to function with ID %d", func_id);
+ cb(pdu);
+ } catch (const std::out_of_range& e) {
+ LOG_E("No RAN Function with this ID exists\n");
+ }
+
+ break;
+ }
+
+ case E2AP_PDU_PR_successfulOutcome:
+ LOG_I("Received RIC-SUBSCRIPTION-RESPONSE");
break;\r
\r
case E2AP_PDU_PR_unsuccessfulOutcome:\r