From d27641a443113d3af55e05df7f433b54fd0a6bc5 Mon Sep 17 00:00:00 2001 From: gauthier <lionel.gauthier@eurecom.fr> Date: Tue, 17 Nov 2015 16:56:24 +0100 Subject: [PATCH] Begin to begin sending packets (many things to do hash assoc id, mme_ue_id, nas security, etc) --- cmake_targets/CMakeLists.txt | 30 +- cmake_targets/epc_test/CMakeLists.template | 4 +- cmake_targets/tools/build_test_epc_tools | 2 +- openair3/S1AP/s1ap_eNB.c | 7 +- openair3/TEST/EPC_TEST/play_scenario.c | 1203 +++-------------- openair3/TEST/EPC_TEST/play_scenario.h | 221 ++- openair3/TEST/EPC_TEST/play_scenario_decode.c | 214 +++ .../TEST/EPC_TEST/play_scenario_display.c | 292 ++++ openair3/TEST/EPC_TEST/play_scenario_fsm.c | 127 ++ openair3/TEST/EPC_TEST/play_scenario_parse.c | 561 ++++++++ openair3/TEST/EPC_TEST/play_scenario_s1ap.c | 162 +++ openair3/TEST/EPC_TEST/play_scenario_sctp.c | 45 + openair3/UTILS/conversions.h | 1 - 13 files changed, 1811 insertions(+), 1058 deletions(-) create mode 100644 openair3/TEST/EPC_TEST/play_scenario_decode.c create mode 100644 openair3/TEST/EPC_TEST/play_scenario_display.c create mode 100644 openair3/TEST/EPC_TEST/play_scenario_fsm.c create mode 100644 openair3/TEST/EPC_TEST/play_scenario_parse.c create mode 100644 openair3/TEST/EPC_TEST/play_scenario_s1ap.c create mode 100644 openair3/TEST/EPC_TEST/play_scenario_sctp.c diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 5fb722ee9d7..148aae24195 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -216,18 +216,20 @@ add_definitions("-DPACKAGE_BUGREPORT=\"openair4g-devel@lists.eurecom.fr\"") # Debug related options ######################################### -add_boolean_option(MSG_PRINT False "print debug messages") -add_boolean_option(DISABLE_XER_PRINT False "print XER Format") -add_boolean_option(XER_PRINT False "print XER Format") -add_boolean_option(RRC_MSG_PRINT False "print RRC messages") -add_boolean_option(PDCP_MSG_PRINT False "print PDCP messages to /tmp/pdcp.log") -add_boolean_option(DEBUG_PDCP_PAYLOAD False "print PDCP PDU to stdout") # if true, make sure that global and PDCP log levels are trace +add_boolean_option(ASN_DEBUG False "ASN1 coder/decoder Debug") +add_boolean_option(EMIT_ASN_DEBUG False "ASN1 coder/decoder Debug") +add_boolean_option(MSG_PRINT False "print debug messages") +add_boolean_option(DISABLE_XER_PRINT False "print XER Format") +add_boolean_option(XER_PRINT False "print XER Format") +add_boolean_option(RRC_MSG_PRINT False "print RRC messages") +add_boolean_option(PDCP_MSG_PRINT False "print PDCP messages to /tmp/pdcp.log") +add_boolean_option(DEBUG_PDCP_PAYLOAD False "print PDCP PDU to stdout") # if true, make sure that global and PDCP log levels are trace add_boolean_option(DEBUG_MAC_INTERFACE False "print MAC-RLC PDU exchange to stdout") # if true, make sure that global and PDCP log levels are trace -add_boolean_option(TRACE_RLC_PAYLOAD False "print RLC PDU to stdout") # if true, make sure that global and PDCP log levels are trace -add_boolean_option(TEST_OMG False "???") -add_boolean_option(DEBUG_OMG False "???") -add_boolean_option(XFORMS False "This adds the possibility to see the signal oscilloscope") -add_boolean_option(PRINT_STATS False "This adds the possibility to see the status") +add_boolean_option(TRACE_RLC_PAYLOAD False "print RLC PDU to stdout") # if true, make sure that global and PDCP log levels are trace +add_boolean_option(TEST_OMG False "???") +add_boolean_option(DEBUG_OMG False "???") +add_boolean_option(XFORMS False "This adds the possibility to see the signal oscilloscope") +add_boolean_option(PRINT_STATS False "This adds the possibility to see the status") add_boolean_option(DEBUG_CONSOLE False "makes debugging easier, disables stdout/stderr buffering") @@ -1660,6 +1662,12 @@ target_link_libraries (test_epc_generate_scenario add_executable(test_epc_play_scenario ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario.c + ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_decode.c + ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_display.c + ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_fsm.c + ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_parse.c + ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_s1ap.c + ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_sctp.c ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario.h ${OPENAIR2_DIR}/ENB_APP/enb_config.h ${OPENAIR2_DIR}/COMMON/commonDef.h diff --git a/cmake_targets/epc_test/CMakeLists.template b/cmake_targets/epc_test/CMakeLists.template index 5789c3eb5c5..8a8223e4ae6 100644 --- a/cmake_targets/epc_test/CMakeLists.template +++ b/cmake_targets/epc_test/CMakeLists.template @@ -7,7 +7,7 @@ set ( DEBUG_OMG False ) set ( DISABLE_XER_PRINT False ) set ( DRIVER2013 True ) set ( EMOS False ) -set ( EMIT_ASN_DEBUG True ) +set ( EMIT_ASN_DEBUG False ) set ( ENABLE_FXP True ) set ( ENABLE_ITTI True ) set ( ENABLE_NAS_UE_LOGGING True ) @@ -76,4 +76,4 @@ set ( SMBV False ) set ( TEST_OMG False ) set ( USE_MME "R10" ) set ( USER_MODE True ) -set ( XER_PRINT False ) +set ( XER_PRINT True ) diff --git a/cmake_targets/tools/build_test_epc_tools b/cmake_targets/tools/build_test_epc_tools index 10dc4fd2564..db49fa017b6 100755 --- a/cmake_targets/tools/build_test_epc_tools +++ b/cmake_targets/tools/build_test_epc_tools @@ -22,7 +22,7 @@ # Contact Information # OpenAirInterface Admin: openair_admin@eurecom.fr # OpenAirInterface Tech : openair_tech@eurecom.fr -# OpenAirInterface Dev : openair4g-devel@eurecom.fr +# OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr # # Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE # diff --git a/openair3/S1AP/s1ap_eNB.c b/openair3/S1AP/s1ap_eNB.c index c880c3f3b4b..1b683d4aa34 100644 --- a/openair3/S1AP/s1ap_eNB.c +++ b/openair3/S1AP/s1ap_eNB.c @@ -72,9 +72,9 @@ s1ap_eNB_config_t s1ap_config; static int s1ap_eNB_generate_s1_setup_request( s1ap_eNB_instance_t *instance_p, s1ap_eNB_mme_data_t *s1ap_mme_data_p); -static + void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *s1ap_register_eNB); -static + void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp); uint32_t s1ap_generate_eNB_id(void) @@ -150,7 +150,7 @@ static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p, itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message_p); } -static + void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *s1ap_register_eNB) { s1ap_eNB_instance_t *new_instance; @@ -210,7 +210,6 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * } } -static void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp) { s1ap_eNB_instance_t *instance_p; diff --git a/openair3/TEST/EPC_TEST/play_scenario.c b/openair3/TEST/EPC_TEST/play_scenario.c index 982c1ffb402..fda38dbcb8b 100644 --- a/openair3/TEST/EPC_TEST/play_scenario.c +++ b/openair3/TEST/EPC_TEST/play_scenario.c @@ -48,133 +48,28 @@ #include <sys/stat.h> #include <sys/time.h> #include <unistd.h> -#include <libxml/xmlmemory.h> -#include <libxml/debugXML.h> -#include <libxml/xmlIO.h> -#include <libxml/DOCBparser.h> -#include <libxml/xinclude.h> -#include <libxml/catalog.h> -#include <libxml/xmlreader.h> -#include <libxslt/xslt.h> -#include <libxslt/xsltInternals.h> -#include <libxslt/transform.h> -#include <libxslt/xsltutils.h> + #include "intertask_interface_init.h" +#include "timer.h" #include "assertions.h" -#include "play_scenario.h" -//#include "s1ap_eNB.h" #include "s1ap_common.h" -#include "s1ap_ies_defs.h" -#include "s1ap_eNB_decoder.h" #include "intertask_interface.h" -#include "enb_config.h" +#include "play_scenario.h" +#include "sctp_eNB_task.h" #include "log.h" //------------------------------------------------------------------------------ -#define ENB_CONFIG_MAX_XSLT_PARAMS 32 #define PLAY_SCENARIO 1 #define GS_IS_FILE 1 #define GS_IS_DIR 2 //------------------------------------------------------------------------------ char *g_openair_dir = NULL; //------------------------------------------------------------------------------ -extern Enb_properties_array_t enb_properties; extern int xmlLoadExtDtdDefaultValue; extern int asn_debug; extern int asn1_xer_print; -//------------------------------------------------------------------------------ -void test_print_hex_octets(const unsigned char * const byte_stream, const unsigned long int num); -int is_file_exists ( const char const * file_nameP, const char const *file_roleP); -int strip_extension( char *in_filename); -int split_path ( char * pathP, char *** resP); -void display_node ( xmlNodePtr node, unsigned int indent); -void display_tree ( xmlNodePtr node, unsigned int indent); -//------------------------- -void free_packet(test_packet_t* packet); -void free_scenario(test_scenario_t* scenario); -//------------------------- -void display_packet_sctp_init(const sctp_inithdr_t * const sctp); -void display_packet_sctp_initack(const sctp_initackhdr_t * const sctp); -void display_packet_sctp_data(const sctp_datahdr_t * const sctp); -void display_packet_sctp(const test_sctp_hdr_t * const sctp); -void display_packet_ip(const test_ip_hdr_t * const ip); -void display_packet(const test_packet_t * const packet); -void display_scenario(const test_scenario_t * const scenario); -//------------------------- -char * test_ip2ip_str(const test_ip_t * const ip); -int hex2data(unsigned char * const data, const unsigned char * const hexstring, const unsigned int len); -sctp_cid_t chunk_type_str2cid(const xmlChar * const chunk_type_str); -const char * const chunk_type_cid2str(const sctp_cid_t chunk_type); -test_action_t action_str2test_action_t(const xmlChar * const action); -void ip_str2test_ip(const xmlChar * const ip_str, test_ip_t * const ip); -//------------------------- -int test_s1ap_decode_initiating_message(s1ap_message *message, S1ap_InitiatingMessage_t *initiating_p); -int test_s1ap_decode_successful_outcome(s1ap_message *message, S1ap_SuccessfulOutcome_t *successfullOutcome_p); -int test_s1ap_decode_unsuccessful_outcome(s1ap_message *message, S1ap_UnsuccessfulOutcome_t *unSuccessfullOutcome_p); -int test_s1ap_decode_pdu(s1ap_message *message, const uint8_t * const buffer,const uint32_t length); -void test_decode_s1ap(test_s1ap_t * const s1ap); -//------------------------- -void parse_s1ap(xmlDocPtr doc, const xmlNode const *s1ap_node, test_s1ap_t * const s1ap); -void parse_sctp_data_chunk(xmlDocPtr doc, const xmlNode const *sctp_node, sctp_datahdr_t * const sctp_hdr); -void parse_sctp_init_chunk(xmlDocPtr doc, const xmlNode const *sctp_node, sctp_inithdr_t * const sctp_hdr); -void parse_sctp_init_ack_chunk(xmlDocPtr doc, const xmlNode const *sctp_node, sctp_initackhdr_t * const sctp_hdr); -void parse_sctp(xmlDocPtr doc, const xmlNode const *sctp_node, test_sctp_hdr_t * const sctp_hdr); -test_packet_t* parse_xml_packet(xmlDocPtr doc, xmlNodePtr node); -//------------------------- -int play_scenario(test_scenario_t* scenario); -int generate_xml_scenario( - const char const * test_dir_name, - const char const * test_scenario_filename, - const char const * enb_config_filename, - char const * play_scenario_filename /* OUT PARAM*/); - -//----------------------------------------------------------------------------- -void test_print_hex_octets(const unsigned char * const byte_stream, const unsigned long int num) -//----------------------------------------------------------------------------- -{ - unsigned long octet_index = 0; - - if (byte_stream == NULL) { - return; - } - - - fprintf(stdout, "+-----+-------------------------------------------------+\n"); - fprintf(stdout, "| | 0 1 2 3 4 5 6 7 8 9 a b c d e f |\n"); - fprintf(stdout, "+-----+-------------------------------------------------+\n"); - - for (octet_index = 0; octet_index < num; octet_index++) { - if ((octet_index % 16) == 0) { - if (octet_index != 0) { - fprintf(stdout, " |\n"); - } - - fprintf(stdout, " %04ld |", octet_index); - } - - /* - * Print every single octet in hexadecimal form - */ - fprintf(stdout, " %02x", byte_stream[octet_index]); - /* - * Align newline and pipes according to the octets in groups of 2 - */ - } - - /* - * Append enough spaces and put final pipe - */ - unsigned char index; - - for (index = octet_index; index < 16; ++index) { - fprintf(stdout, " "); - } - - fprintf(stdout, " |\n"); -} - //------------------------------------------------------------------------------ // test if file exist in current directory int is_file_exists( const char const * file_nameP, const char const *file_roleP) @@ -202,7 +97,7 @@ int is_file_exists( const char const * file_nameP, const char const *file_roleP) //------------------------------------------------------------------------------ -int strip_extension(char *in_filename) +int et_strip_extension(char *in_filename) { static const uint8_t name_min_len = 1; static const uint8_t max_ext_len = 5; // .pdml ! @@ -237,193 +132,38 @@ int split_path( char * pathP, char *** resP) return n_spaces; } //------------------------------------------------------------------------------ -void display_node(xmlNodePtr node, unsigned int indent) -{ - int i = 0; - if (node->type == XML_ELEMENT_NODE) { - xmlChar *path = xmlGetNodePath(node); - for (i=0; i<indent; i++) { - printf(" "); - } - if (node->children != NULL && node->children->type == XML_TEXT_NODE) { - xmlChar *content = xmlNodeGetContent(node); - printf("%s -> %s\n", path, content); - xmlFree(content); - } else { - printf("%s\n", path); - } - xmlFree(path); - } -} -/** - * print_element_names: - * @node: the initial xml node to consider. - * @indent: indentation level. - * - * Prints the names of the all the xml elements - * that are siblings or children of a given xml node. - */ -//------------------------------------------------------------------------------ -void display_tree(xmlNodePtr node, unsigned int indent) -{ - xmlNode *cur_node = NULL; - - for (cur_node = node; cur_node; cur_node = cur_node->next) { - if (cur_node->type == XML_ELEMENT_NODE) { - display_node(cur_node, indent); - } - display_tree(cur_node->children, indent++); - } -} -//------------------------------------------------------------------------------ -void free_packet(test_packet_t* packet) +void et_free_packet(et_packet_t* packet) { if (packet) { switch (packet->sctp_hdr.chunk_type) { case SCTP_CID_DATA: - free_pointer(packet->sctp_hdr.u.data_hdr.payload.binary_stream); + et_free_pointer(packet->sctp_hdr.u.data_hdr.payload.binary_stream); break; default: ; } - free_pointer(packet); + et_free_pointer(packet); } } //------------------------------------------------------------------------------ -void free_scenario(test_scenario_t* scenario) +void et_free_scenario(et_scenario_t* scenario) { - test_packet_t *packet = NULL; - test_packet_t *next_packet = NULL; + et_packet_t *packet = NULL; + et_packet_t *next_packet = NULL; if (scenario) { packet = scenario->list_packet; while (packet) { next_packet = packet->next; - free_packet(packet); + et_free_packet(packet); packet = next_packet->next; } - free_pointer(scenario); - } -} - - -//------------------------------------------------------------------------------ -void display_packet_sctp_init(const sctp_inithdr_t * const sctp) -{ - - if (sctp) { - fprintf(stdout, "\t\tSCTP.init.init_tag : %u\n", sctp->init_tag); - fprintf(stdout, "\t\tSCTP.init.a_rwnd : %u\n", sctp->a_rwnd); - fprintf(stdout, "\t\tSCTP.init.num_inbound_streams : %u\n", sctp->num_inbound_streams); - fprintf(stdout, "\t\tSCTP.init.num_outbound_streams : %u\n", sctp->num_outbound_streams); - fprintf(stdout, "\t\tSCTP.init.initial_tsn : %u\n", sctp->initial_tsn); - } -} -//------------------------------------------------------------------------------ -void display_packet_sctp_initack(const sctp_initackhdr_t * const sctp) -{ - - if (sctp) { - fprintf(stdout, "\t\tSCTP.initack.init_tag : %u\n", sctp->init_tag); - fprintf(stdout, "\t\tSCTP.initack.a_rwnd : %u\n", sctp->a_rwnd); - fprintf(stdout, "\t\tSCTP.initack.num_inbound_streams : %u\n", sctp->num_inbound_streams); - fprintf(stdout, "\t\tSCTP.initack.num_outbound_streams : %u\n", sctp->num_outbound_streams); - fprintf(stdout, "\t\tSCTP.initack.initial_tsn : %u\n", sctp->initial_tsn); - } -} -//------------------------------------------------------------------------------ -void display_packet_sctp_data(const sctp_datahdr_t * const sctp) -{ - if (sctp) { - fprintf(stdout, "\t\tSCTP.data.tsn : %u\n", sctp->tsn); - fprintf(stdout, "\t\tSCTP.data.stream : %u\n", sctp->stream); - fprintf(stdout, "\t\tSCTP.data.ssn : %u\n", sctp->ssn); - fprintf(stdout, "\t\tSCTP.data.ppid : %u\n", sctp->ppid); - //fprintf(stdout, "\t\tSCTP.data.pdu_type : %u\n", sctp->payload.pdu_type); - //fprintf(stdout, "\t\tSCTP.data.procedure_code : %u\n", sctp->payload.procedure_code); - fprintf(stdout, "\t\tSCTP.data.binary_stream_allocated_size : %u\n", sctp->payload.binary_stream_allocated_size); - if (NULL != sctp->payload.binary_stream) { - fprintf(stdout, "\t\tSCTP.data.binary_stream :\n"); - test_print_hex_octets(sctp->payload.binary_stream, sctp->payload.binary_stream_allocated_size); - } else { - fprintf(stdout, "\t\tSCTP.data.binary_stream : NULL\n"); - } + et_free_pointer(scenario); } } //------------------------------------------------------------------------------ -void display_packet_sctp(const test_sctp_hdr_t * const sctp) -{ - if (sctp) { - fprintf(stdout, "\t\tSCTP.src_port : %u\n", sctp->src_port); - fprintf(stdout, "\t\tSCTP.dst_port : %u\n", sctp->dst_port); - fprintf(stdout, "\t\tSCTP.chunk_type : %s\n", chunk_type_cid2str(sctp->chunk_type)); - switch (sctp->chunk_type) { - case SCTP_CID_DATA: - display_packet_sctp_data(&sctp->u.data_hdr); - break; - case SCTP_CID_INIT: - display_packet_sctp_initack(&sctp->u.init_hdr); - break; - case SCTP_CID_INIT_ACK: - display_packet_sctp_initack(&sctp->u.init_ack_hdr); - break; - default: - ; - } - } -} -//------------------------------------------------------------------------------ -void display_packet_ip(const test_ip_hdr_t * const ip) -{ - if (ip) { - fprintf(stdout, "\t\tSource address : %s\n", test_ip2ip_str(&ip->src)); - fprintf(stdout, "\t\tDestination address : %s\n", test_ip2ip_str(&ip->dst)); - } -} - -//------------------------------------------------------------------------------ -void display_packet(const test_packet_t * const packet) -{ - if (packet) { - fprintf(stdout, "\tPacket:\tnum %u | original frame number %u \n", packet->packet_number, packet->original_frame_number); - fprintf(stdout, "\tPacket:\ttime relative to 1st packet %ld.%06lu\n", - packet->time_relative_to_first_packet.tv_sec, packet->time_relative_to_first_packet.tv_usec); - fprintf(stdout, "\tPacket:\ttime relative to last tx packet %ld.%06lu\n", - packet->time_relative_to_last_sent_packet.tv_sec, packet->time_relative_to_last_sent_packet.tv_usec); - fprintf(stdout, "\tPacket:\ttime relative to last_received packet %ld.%06lu\n", - packet->time_relative_to_last_received_packet.tv_sec, packet->time_relative_to_last_received_packet.tv_usec); - - switch(packet->action) { - case ACTION_S1C_SEND: - fprintf(stdout, "\tPacket:\tAction SEND\n"); - break; - case ACTION_S1C_RECEIVE: - fprintf(stdout, "\tPacket:\tAction RECEIVE\n"); - break; - default: - fprintf(stdout, "\tPacket:\tAction UNKNOWN\n"); - } - display_packet_ip(&packet->ip_hdr); - display_packet_sctp(&packet->sctp_hdr); - } -} -//------------------------------------------------------------------------------ -void display_scenario(const test_scenario_t * const scenario) -{ - test_packet_t *packet = NULL; - if (scenario) { - fprintf(stdout, "Scenario: %s\n", (scenario->name != NULL) ? (char*)scenario->name:"UNKNOWN NAME"); - packet = scenario->list_packet; - while (packet) { - display_packet(packet); - packet = packet->next; - } - } -} - -//------------------------------------------------------------------------------ -char * test_ip2ip_str(const test_ip_t * const ip) +char * et_ip2ip_str(const et_ip_t * const ip) { static char str[INET6_ADDRSTRLEN]; @@ -445,7 +185,7 @@ char * test_ip2ip_str(const test_ip_t * const ip) //returns 0 on success, negative on error //data is a buffer of at least len bytes //hexstring is upper or lower case hexadecimal, NOT prepended with "0x" -int hex2data(unsigned char * const data, const unsigned char * const hexstring, const unsigned int len) +int et_hex2data(unsigned char * const data, const unsigned char * const hexstring, const unsigned int len) { unsigned const char *pos = hexstring; char *endptr = NULL; @@ -477,7 +217,7 @@ int hex2data(unsigned char * const data, const unsigned char * const hexstring, return 0; } //------------------------------------------------------------------------------ -sctp_cid_t chunk_type_str2cid(const xmlChar * const chunk_type_str) +sctp_cid_t et_chunk_type_str2cid(const xmlChar * const chunk_type_str) { if ((!xmlStrcmp(chunk_type_str, (const xmlChar *)"DATA"))) { return SCTP_CID_DATA;} if ((!xmlStrcmp(chunk_type_str, (const xmlChar *)"INIT"))) { return SCTP_CID_INIT;} @@ -501,7 +241,7 @@ sctp_cid_t chunk_type_str2cid(const xmlChar * const chunk_type_str) AssertFatal (0, "ERROR: %s() cannot convert: %s\n", __FUNCTION__, chunk_type_str); } //------------------------------------------------------------------------------ -const char * const chunk_type_cid2str(const sctp_cid_t chunk_type) +const char * const et_chunk_type_cid2str(const sctp_cid_t chunk_type) { switch (chunk_type) { case SCTP_CID_DATA: return "DATA"; break; @@ -528,15 +268,15 @@ const char * const chunk_type_cid2str(const sctp_cid_t chunk_type) } } //------------------------------------------------------------------------------ -test_action_t action_str2test_action_t(const xmlChar * const action) +et_packet_action_t et_action_str2et_action_t(const xmlChar * const action) { - if ((!xmlStrcmp(action, (const xmlChar *)"SEND"))) { return ACTION_S1C_SEND;} - if ((!xmlStrcmp(action, (const xmlChar *)"RECEIVE"))) { return ACTION_S1C_RECEIVE;} + if ((!xmlStrcmp(action, (const xmlChar *)"SEND"))) { return ET_PACKET_ACTION_S1C_SEND;} + if ((!xmlStrcmp(action, (const xmlChar *)"RECEIVE"))) { return ET_PACKET_ACTION_S1C_RECEIVE;} AssertFatal (0, "ERROR: %s cannot convert: %s\n", __FUNCTION__, action); //if (NULL == action) {return ACTION_S1C_NULL;} } //------------------------------------------------------------------------------ -void ip_str2test_ip(const xmlChar * const ip_str, test_ip_t * const ip) +void et_ip_str2et_ip(const xmlChar * const ip_str, et_ip_t * const ip) { AssertFatal (NULL != ip_str, "ERROR %s() Cannot convert null string to ip address!\n", __FUNCTION__); AssertFatal (NULL != ip, "ERROR %s() out parameter pointer is NULL!\n", __FUNCTION__); @@ -550,732 +290,207 @@ void ip_str2test_ip(const xmlChar * const ip_str, test_ip_t * const ip) AssertFatal (0, "ERROR %s() Could not parse ip address %s!\n", __FUNCTION__, ip_str); } } -//------------------------------------------------------------------------------ -int test_s1ap_decode_initiating_message(s1ap_message *message, - S1ap_InitiatingMessage_t *initiating_p) -{ - char *message_string = NULL; - int ret = -1; - - DevAssert(initiating_p != NULL); - - message_string = calloc(20000, sizeof(char)); - AssertFatal (NULL != message_string, "ERROR malloc()failed!\n"); - message->procedureCode = initiating_p->procedureCode; - message->criticality = initiating_p->criticality; - - switch(initiating_p->procedureCode) { - case S1ap_ProcedureCode_id_downlinkNASTransport: - ret = s1ap_decode_s1ap_downlinknastransporties( - &message->msg.s1ap_DownlinkNASTransportIEs, - &initiating_p->value); - s1ap_xer_print_s1ap_downlinknastransport(s1ap_xer__print2sp, message_string, message); - break; - - case S1ap_ProcedureCode_id_InitialContextSetup: - ret = s1ap_decode_s1ap_initialcontextsetuprequesties( - &message->msg.s1ap_InitialContextSetupRequestIEs, &initiating_p->value); - s1ap_xer_print_s1ap_initialcontextsetuprequest(s1ap_xer__print2sp, message_string, message); - break; - - case S1ap_ProcedureCode_id_UEContextRelease: - ret = s1ap_decode_s1ap_uecontextreleasecommandies( - &message->msg.s1ap_UEContextReleaseCommandIEs, &initiating_p->value); - s1ap_xer_print_s1ap_uecontextreleasecommand(s1ap_xer__print2sp, message_string, message); - break; - - case S1ap_ProcedureCode_id_Paging: - ret = s1ap_decode_s1ap_pagingies( - &message->msg.s1ap_PagingIEs, &initiating_p->value); - s1ap_xer_print_s1ap_paging(s1ap_xer__print2sp, message_string, message); - break; - - case S1ap_ProcedureCode_id_uplinkNASTransport: - ret = s1ap_decode_s1ap_uplinknastransporties (&message->msg.s1ap_UplinkNASTransportIEs, &initiating_p->value); - s1ap_xer_print_s1ap_uplinknastransport(s1ap_xer__print2sp, message_string, message); - break; - - case S1ap_ProcedureCode_id_S1Setup: - ret = s1ap_decode_s1ap_s1setuprequesties (&message->msg.s1ap_S1SetupRequestIEs, &initiating_p->value); - s1ap_xer_print_s1ap_s1setuprequest(s1ap_xer__print2sp, message_string, message); - break; - - case S1ap_ProcedureCode_id_initialUEMessage: - ret = s1ap_decode_s1ap_initialuemessageies (&message->msg.s1ap_InitialUEMessageIEs, &initiating_p->value); - s1ap_xer_print_s1ap_initialuemessage(s1ap_xer__print2sp, message_string, message); - break; - - case S1ap_ProcedureCode_id_UEContextReleaseRequest: - ret = s1ap_decode_s1ap_uecontextreleaserequesties (&message->msg.s1ap_UEContextReleaseRequestIEs, &initiating_p->value); - s1ap_xer_print_s1ap_uecontextreleaserequest(s1ap_xer__print2sp, message_string, message); - break; - - case S1ap_ProcedureCode_id_UECapabilityInfoIndication: - ret = s1ap_decode_s1ap_uecapabilityinfoindicationies (&message->msg.s1ap_UECapabilityInfoIndicationIEs, &initiating_p->value); - //s1ap_xer_print_s1ap_uecapabilityinfoindication(s1ap_xer__print2sp, message_string, message); - break; - - case S1ap_ProcedureCode_id_NASNonDeliveryIndication: - ret = s1ap_decode_s1ap_nasnondeliveryindication_ies (&message->msg.s1ap_NASNonDeliveryIndication_IEs, &initiating_p->value); - s1ap_xer_print_s1ap_nasnondeliveryindication_(s1ap_xer__print2sp, message_string, message); - break; - - default: - free(message_string); - AssertFatal( 0 , "Unknown procedure ID (%d) for initiating message\n", - (int)initiating_p->procedureCode); - return -1; - } - fprintf(stdout, "s1ap_xer_print:\n%s\n", message_string); - free(message_string); - return ret; -} +/*------------------------------------------------------------------------------*/ +uint32_t et_eNB_app_register(const Enb_properties_array_t *enb_properties) +{ + uint32_t enb_id; + uint32_t mme_id; + MessageDef *msg_p; + uint32_t register_enb_pending = 0; + char *str = NULL; + struct in_addr addr; + + + for (enb_id = 0; (enb_id < enb_properties->number) ; enb_id++) { + { + s1ap_register_enb_req_t *s1ap_register_eNB; + + /* note: there is an implicit relationship between the data structure and the message name */ + msg_p = itti_alloc_new_message (TASK_ENB_APP, S1AP_REGISTER_ENB_REQ); + + s1ap_register_eNB = &S1AP_REGISTER_ENB_REQ(msg_p); + + /* Some default/random parameters */ + s1ap_register_eNB->eNB_id = enb_properties->properties[enb_id]->eNB_id; + s1ap_register_eNB->cell_type = enb_properties->properties[enb_id]->cell_type; + s1ap_register_eNB->eNB_name = enb_properties->properties[enb_id]->eNB_name; + s1ap_register_eNB->tac = enb_properties->properties[enb_id]->tac; + s1ap_register_eNB->mcc = enb_properties->properties[enb_id]->mcc; + s1ap_register_eNB->mnc = enb_properties->properties[enb_id]->mnc; + s1ap_register_eNB->mnc_digit_length = enb_properties->properties[enb_id]->mnc_digit_length; + s1ap_register_eNB->default_drx = enb_properties->properties[enb_id]->pcch_defaultPagingCycle[0]; + + s1ap_register_eNB->nb_mme = enb_properties->properties[enb_id]->nb_mme; + AssertFatal (s1ap_register_eNB->nb_mme <= S1AP_MAX_NB_MME_IP_ADDRESS, "Too many MME for eNB %d (%d/%d)!", enb_id, s1ap_register_eNB->nb_mme, + S1AP_MAX_NB_MME_IP_ADDRESS); + + for (mme_id = 0; mme_id < s1ap_register_eNB->nb_mme; mme_id++) { + s1ap_register_eNB->mme_ip_address[mme_id].ipv4 = enb_properties->properties[enb_id]->mme_ip_address[mme_id].ipv4; + s1ap_register_eNB->mme_ip_address[mme_id].ipv6 = enb_properties->properties[enb_id]->mme_ip_address[mme_id].ipv6; + strncpy (s1ap_register_eNB->mme_ip_address[mme_id].ipv4_address, + enb_properties->properties[enb_id]->mme_ip_address[mme_id].ipv4_address, + sizeof(s1ap_register_eNB->mme_ip_address[0].ipv4_address)); + strncpy (s1ap_register_eNB->mme_ip_address[mme_id].ipv6_address, + enb_properties->properties[enb_id]->mme_ip_address[mme_id].ipv6_address, + sizeof(s1ap_register_eNB->mme_ip_address[0].ipv6_address)); + } -//------------------------------------------------------------------------------ -int test_s1ap_decode_successful_outcome(s1ap_message *message, - S1ap_SuccessfulOutcome_t *successfullOutcome_p) -{ - char *message_string = NULL; - int ret = -1; - - DevAssert(successfullOutcome_p != NULL); - message_string = calloc(20000, sizeof(char)); - AssertFatal (NULL != message_string, "ERROR malloc()failed!\n"); - - message->procedureCode = successfullOutcome_p->procedureCode; - message->criticality = successfullOutcome_p->criticality; - - switch(successfullOutcome_p->procedureCode) { - case S1ap_ProcedureCode_id_S1Setup: - ret = s1ap_decode_s1ap_s1setupresponseies( - &message->msg.s1ap_S1SetupResponseIEs, &successfullOutcome_p->value); - s1ap_xer_print_s1ap_s1setupresponse(s1ap_xer__print2sp, message_string, message); - break; - - case S1ap_ProcedureCode_id_InitialContextSetup: - ret = s1ap_decode_s1ap_initialcontextsetupresponseies (&message->msg.s1ap_InitialContextSetupResponseIEs, &successfullOutcome_p->value); - s1ap_xer_print_s1ap_initialcontextsetupresponse(s1ap_xer__print2sp, message_string, message); - break; - - case S1ap_ProcedureCode_id_UEContextRelease: - ret = s1ap_decode_s1ap_uecontextreleasecompleteies (&message->msg.s1ap_UEContextReleaseCompleteIEs, &successfullOutcome_p->value); - s1ap_xer_print_s1ap_uecontextreleasecomplete(s1ap_xer__print2sp, message_string, message); - break; - - default: - free(message_string); - AssertFatal(0, "Unknown procedure ID (%d) for successfull outcome message\n", - (int)successfullOutcome_p->procedureCode); - return -1; - } - fprintf(stdout, "s1ap_xer_print:\n%s\n", message_string); - free(message_string); - return ret; -} + s1ap_register_eNB->sctp_in_streams = enb_properties->properties[enb_id]->sctp_in_streams; + s1ap_register_eNB->sctp_out_streams = enb_properties->properties[enb_id]->sctp_out_streams; -//------------------------------------------------------------------------------ -int test_s1ap_decode_unsuccessful_outcome(s1ap_message *message, - S1ap_UnsuccessfulOutcome_t *unSuccessfullOutcome_p) -{ - char *message_string = NULL; - int ret = -1; - - DevAssert(unSuccessfullOutcome_p != NULL); - message_string = calloc(20000, sizeof(char)); - AssertFatal (NULL != message_string, "ERROR malloc()failed!\n"); - - message->procedureCode = unSuccessfullOutcome_p->procedureCode; - message->criticality = unSuccessfullOutcome_p->criticality; - - switch(unSuccessfullOutcome_p->procedureCode) { - case S1ap_ProcedureCode_id_S1Setup: - ret = s1ap_decode_s1ap_s1setupfailureies( - &message->msg.s1ap_S1SetupFailureIEs, &unSuccessfullOutcome_p->value); - s1ap_xer_print_s1ap_s1setupfailure(s1ap_xer__print2sp, message_string, message); - break; - - case S1ap_ProcedureCode_id_InitialContextSetup: - ret = s1ap_decode_s1ap_initialcontextsetupfailureies (&message->msg.s1ap_InitialContextSetupFailureIEs, &unSuccessfullOutcome_p->value); - s1ap_xer_print_s1ap_initialcontextsetupfailure(s1ap_xer__print2sp, message_string, message); - break; - - - default: - free(message_string); - AssertFatal(0,"Unknown procedure ID (%d) for unsuccessfull outcome message\n", - (int)unSuccessfullOutcome_p->procedureCode); - break; + + s1ap_register_eNB->enb_ip_address.ipv6 = 0; + s1ap_register_eNB->enb_ip_address.ipv4 = 1; + addr.s_addr = enb_properties->properties[enb_id]->enb_ipv4_address_for_S1_MME; + str = inet_ntoa(addr); + strcpy(s1ap_register_eNB->enb_ip_address.ipv4_address, str); + + itti_send_msg_to_task (TASK_S1AP, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p); + + register_enb_pending++; + } } - fprintf(stdout, "s1ap_xer_print:\n%s\n", message_string); - free(message_string); - return ret; -} -//------------------------------------------------------------------------------ -int test_s1ap_decode_pdu(s1ap_message *message, const uint8_t * const buffer, - const uint32_t length) + return register_enb_pending; +} +/*------------------------------------------------------------------------------*/ +void *et_eNB_app_task(void *args_p) { - S1AP_PDU_t pdu; - S1AP_PDU_t *pdu_p = &pdu; - asn_dec_rval_t dec_ret; + const Enb_properties_array_t *enb_properties_p = NULL; + uint32_t register_enb_pending; + uint32_t registered_enb; + long enb_register_retry_timer_id; + uint32_t enb_id; + MessageDef *msg_p = NULL; + const char *msg_name = NULL; + instance_t instance; + int result; - DevAssert(buffer != NULL); + itti_mark_task_ready (TASK_ENB_APP); - memset((void *)pdu_p, 0, sizeof(S1AP_PDU_t)); - dec_ret = aper_decode(NULL, - &asn_DEF_S1AP_PDU, - (void **)&pdu_p, - buffer, - length, - 0, - 0); + enb_properties_p = enb_config_get(); - if (dec_ret.code != RC_OK) { - S1AP_ERROR("Failed to decode pdu\n"); - return -1; - } - message->direction = pdu_p->present; + /* Try to register each eNB */ + registered_enb = 0; + register_enb_pending = et_eNB_app_register (enb_properties_p); - switch(pdu_p->present) { - case S1AP_PDU_PR_initiatingMessage: - return test_s1ap_decode_initiating_message(message, - &pdu_p->choice.initiatingMessage); - case S1AP_PDU_PR_successfulOutcome: - return test_s1ap_decode_successful_outcome(message, - &pdu_p->choice.successfulOutcome); + do { + // Wait for a message + itti_receive_msg (TASK_ENB_APP, &msg_p); - case S1AP_PDU_PR_unsuccessfulOutcome: - return test_s1ap_decode_unsuccessful_outcome(message, - &pdu_p->choice.unsuccessfulOutcome); + msg_name = ITTI_MSG_NAME (msg_p); + instance = ITTI_MSG_INSTANCE (msg_p); - default: - AssertFatal(0, "Unknown presence (%d) or not implemented\n", (int)pdu_p->present); - break; - } - return -1; -} -//------------------------------------------------------------------------------ -void test_decode_s1ap(test_s1ap_t * const s1ap) -{ - if (NULL != s1ap) { - if (test_s1ap_decode_pdu(&s1ap->message, s1ap->binary_stream, s1ap->binary_stream_allocated_size) < 0) { - AssertFatal (0, "ERROR %s() Cannot decode S1AP message!\n", __FUNCTION__); - } - } -} -//------------------------------------------------------------------------------ -void parse_s1ap(xmlDocPtr doc, const xmlNode const *s1ap_node, test_s1ap_t * const s1ap) -{ - xmlNode *cur_node = NULL; - xmlChar *xml_char = NULL; - xmlChar *xml_char2 = NULL; - unsigned int size = 0; - int rc = 0; - unsigned int go_deeper_in_tree = 1; - - if ((NULL != s1ap_node) && (NULL != s1ap)) { - for (cur_node = (xmlNode *)s1ap_node; cur_node; cur_node = cur_node->next) { - go_deeper_in_tree = 1; - if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"field"))) { - // do not get hidden fields - xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"hide"); - if (NULL != xml_char) { - if ((!xmlStrcmp(xml_char, (const xmlChar *)"yes"))) { - go_deeper_in_tree = 0; - } - xmlFree(xml_char); - } - if (0 < go_deeper_in_tree) { - // first get size - xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"size"); - if (NULL != xml_char) { - size = strtoul((const char *)xml_char, NULL, 0); - xmlFree(xml_char); - // second: try to get value (always hex) - xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"value"); - if (NULL != xml_char) { - xml_char2 = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"name"); - fprintf(stdout, "s1ap %p field %s size %d value %s\n",s1ap, xml_char2, size, xml_char); - xmlFree(xml_char2); - // if success to get value, do not parse children - //AssertFatal ((xmlStrlen(xml_char) == size), "ERROR %s() mismatch in size %d and strlen %d\n", __FUNCTION__, size, xmlStrlen(xml_char)); - //if (xmlStrlen(xml_char) == size) { - AssertFatal ((s1ap->binary_stream_pos+xmlStrlen(xml_char)/2) <= s1ap->binary_stream_allocated_size, - "ERROR %s() in buffer size: binary_stream_pos %d xmlStrlen(xml_char)/2=%d\n", __FUNCTION__, s1ap->binary_stream_pos, xmlStrlen(xml_char)/2); - rc = hex2data( &s1ap->binary_stream[s1ap->binary_stream_pos], xml_char, xmlStrlen(xml_char)); - s1ap->binary_stream_pos += xmlStrlen(xml_char)/2; - display_node(cur_node, 0); - AssertFatal (rc >= 0, "ERROR %s() in converting hex string %s len %d size %d rc %d\n", __FUNCTION__, xml_char, xmlStrlen(xml_char), size, rc); - go_deeper_in_tree = 0; - //} - xmlFree(xml_char); - } - } - } - } - if (0 < go_deeper_in_tree) { - parse_s1ap(doc, cur_node->children, s1ap); - } - } - } -} + switch (ITTI_MSG_ID(msg_p)) { + case TERMINATE_MESSAGE: + itti_exit_task (); + break; -//------------------------------------------------------------------------------ -void parse_sctp_data_chunk(xmlDocPtr doc, const xmlNode const *sctp_node, sctp_datahdr_t * const sctp_hdr) -{ - xmlNode *cur_node = NULL; - xmlChar *xml_char = NULL; - xmlChar *xml_char2 = NULL; - - if ((NULL != sctp_node) && (NULL != sctp_hdr)) { - xml_char = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"name"); - if (NULL != xml_char) { - if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.data_payload_proto_id"))) { - xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show"); - if (NULL != xml_char2) { - sctp_hdr->ppid = strtoul((const char *)xml_char2, NULL, 0); - xmlFree(xml_char2); - } - } else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.data_sid"))) { - xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show"); - if (NULL != xml_char2) { - sctp_hdr->stream = strtoul((const char *)xml_char2, NULL, 16); - xmlFree(xml_char2); - } - } else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.data_tsn"))) { - xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show"); - if (NULL != xml_char2) { - sctp_hdr->tsn = strtoul((const char *)xml_char2, NULL, 0); - xmlFree(xml_char2); - } - } else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.data_ssn"))) { - xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show"); - if (NULL != xml_char2) { - sctp_hdr->ssn = strtoul((const char *)xml_char2, NULL, 0); - xmlFree(xml_char2); - } - } - xmlFree(xml_char); - } - for (cur_node = sctp_node->children; cur_node; cur_node = cur_node->next) { - parse_sctp_data_chunk(doc, cur_node, sctp_hdr); - } - } -} -//------------------------------------------------------------------------------ -void parse_sctp_init_chunk(xmlDocPtr doc, const xmlNode const *sctp_node, sctp_inithdr_t * const sctp_hdr) -{ - xmlNode *cur_node = NULL; - xmlChar *xml_char = NULL; - xmlChar *xml_char2 = NULL; - - if ((NULL != sctp_node) && (NULL != sctp_hdr)) { - xml_char = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"name"); - if (NULL != xml_char) { - if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.init_nr_out_streams"))) { - xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value"); - if (NULL != xml_char2) { - sctp_hdr->num_outbound_streams = strtoul((const char *)xml_char2, NULL, 0); - xmlFree(xml_char2); - } - } else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.init_nr_in_streams"))) { - xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value"); - if (NULL != xml_char2) { - sctp_hdr->num_inbound_streams = strtoul((const char *)xml_char2, NULL, 0); - xmlFree(xml_char2); - } - } else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.init_credit"))) { - xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value"); - if (NULL != xml_char2) { - sctp_hdr->a_rwnd = strtoul((const char *)xml_char2, NULL, 0); - xmlFree(xml_char2); - } - } else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.init_initial_tsn"))) { - xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show"); - if (NULL != xml_char2) { - sctp_hdr->initial_tsn = strtoul((const char *)xml_char2, NULL, 0); - xmlFree(xml_char2); - } - } else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.init_initiate_tag"))) { - xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show"); - if (NULL != xml_char2) { - sctp_hdr->init_tag = strtoul((const char *)xml_char2, NULL, 16); - xmlFree(xml_char2); - } - } - xmlFree(xml_char); - } - for (cur_node = sctp_node->children; cur_node; cur_node = cur_node->next) { - parse_sctp_init_chunk(doc, cur_node, sctp_hdr); - } - } -} -//------------------------------------------------------------------------------ -void parse_sctp_init_ack_chunk(xmlDocPtr doc, const xmlNode const *sctp_node, sctp_initackhdr_t * const sctp_hdr) -{ - xmlNode *cur_node = NULL; - xmlChar *xml_char = NULL; - xmlChar *xml_char2 = NULL; - - if ((NULL != sctp_node) && (NULL != sctp_hdr)) { - xml_char = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"name"); - if (NULL != xml_char) { - if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.initack_nr_out_streams"))) { - xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value"); - if (NULL != xml_char2) { - sctp_hdr->num_outbound_streams = strtoul((const char *)xml_char2, NULL, 0); - xmlFree(xml_char2); - } - } else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.initack_nr_in_streams"))) { - xml_char2 = xmlGetProp((xmlNode *)(xmlNode *)sctp_node, (const xmlChar *)"value"); - if (NULL != xml_char2) { - sctp_hdr->num_inbound_streams = strtoul((const char *)xml_char2, NULL, 0); - xmlFree(xml_char2); - } - } else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.initack_credit"))) { - xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value"); - if (NULL != xml_char2) { - sctp_hdr->a_rwnd = strtoul((const char *)xml_char2, NULL, 0); - xmlFree(xml_char2); - } - } else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.initack_initial_tsn"))) { - xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show"); - if (NULL != xml_char2) { - sctp_hdr->initial_tsn = strtoul((const char *)xml_char2, NULL, 0); - xmlFree(xml_char2); - } - } else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.initack_initiate_tag"))) { - xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show"); - if (NULL != xml_char2) { - sctp_hdr->init_tag = strtoul((const char *)xml_char2, NULL, 16); - xmlFree(xml_char2); - } - } - xmlFree(xml_char); - } - for (cur_node = sctp_node->children; cur_node; cur_node = cur_node->next) { - parse_sctp_init_ack_chunk(doc, cur_node, sctp_hdr); - } - } -} -//------------------------------------------------------------------------------ -void parse_sctp(xmlDocPtr doc, const xmlNode const *sctp_node, test_sctp_hdr_t * const sctp_hdr) -{ - xmlNode *cur_node = NULL; - xmlChar *xml_char = NULL; - xmlChar *xml_char2 = NULL; - - if ((NULL != sctp_node) && (NULL != sctp_hdr)) { - if ((!xmlStrcmp(sctp_node->name, (const xmlChar *)"proto"))) { - xml_char = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"name"); - if (NULL != xml_char) { - if ((!xmlStrcmp(xml_char, (const xmlChar *)"s1ap"))) { - xmlFree(xml_char); - xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"size"); - if (NULL != xml_char2) { - sctp_hdr->u.data_hdr.payload.binary_stream_allocated_size = strtoul((const char *)xml_char2, NULL, 0); - sctp_hdr->u.data_hdr.payload.binary_stream = calloc(1, sctp_hdr->u.data_hdr.payload.binary_stream_allocated_size); - xmlFree(xml_char2); - } - parse_s1ap(doc, sctp_node, &sctp_hdr->u.data_hdr.payload); - test_decode_s1ap(&sctp_hdr->u.data_hdr.payload); - return; - } - xmlFree(xml_char); + + case S1AP_REGISTER_ENB_CNF: + LOG_I(ENB_APP, "[eNB %d] Received %s: associated MME %d\n", instance, msg_name, + S1AP_REGISTER_ENB_CNF(msg_p).nb_mme); + + DevAssert(register_enb_pending > 0); + register_enb_pending--; + + /* Check if at least eNB is registered with one MME */ + if (S1AP_REGISTER_ENB_CNF(msg_p).nb_mme > 0) { + registered_enb++; } - } - //if ((cur_node->type == XML_ATTRIBUTE_NODE) || (cur_node->type == XML_ELEMENT_NODE)) { - xml_char = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"name"); - if (NULL != xml_char) { - if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.srcport"))) { - xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value"); - if (NULL != xml_char2) { - sctp_hdr->src_port = strtoul((const char *)xml_char2, NULL, 16); - xmlFree(xml_char2); - } - } else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.dstport"))) { - xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value"); - if (NULL != xml_char2) { - sctp_hdr->dst_port = strtoul((const char *)xml_char2, NULL, 16); - xmlFree(xml_char2); - } - } else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.chunk_type"))) { - xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value"); - if (NULL != xml_char2) { - sctp_hdr->chunk_type = strtoul((const char *)xml_char2, NULL, 0); - xmlFree(xml_char2); - switch (sctp_hdr->chunk_type) { - case SCTP_CID_DATA: - parse_sctp_data_chunk(doc, sctp_node->parent, &sctp_hdr->u.data_hdr); - break; - case SCTP_CID_INIT: - parse_sctp_init_chunk(doc, sctp_node->parent, &sctp_hdr->u.init_hdr); - break; - case SCTP_CID_INIT_ACK: - parse_sctp_init_ack_chunk(doc, sctp_node->parent, &sctp_hdr->u.init_ack_hdr); - break; - default: - ; + + /* Check if all register eNB requests have been processed */ + if (register_enb_pending == 0) { + if (registered_enb == enb_properties_p->number) { + /* If all eNB are registered, start scenario */ + + } else { + uint32_t not_associated = enb_properties_p->number - registered_enb; + + LOG_W(ENB_APP, " %d eNB %s not associated with a MME, retrying registration in %d seconds ...\n", + not_associated, not_associated > 1 ? "are" : "is", ET_ENB_REGISTER_RETRY_DELAY); + + /* Restart the eNB registration process in ENB_REGISTER_RETRY_DELAY seconds */ + if (timer_setup (ET_ENB_REGISTER_RETRY_DELAY, 0, TASK_ENB_APP, INSTANCE_DEFAULT, TIMER_ONE_SHOT, + NULL, &enb_register_retry_timer_id) < 0) { + LOG_E(ENB_APP, " Can not start eNB register retry timer, use \"sleep\" instead!\n"); + + sleep(ET_ENB_REGISTER_RETRY_DELAY); + /* Restart the registration process */ + registered_enb = 0; + register_enb_pending = et_eNB_app_register (enb_properties_p); } } } - } - for (cur_node = sctp_node->children; cur_node; cur_node = cur_node->next) { - parse_sctp(doc, cur_node, sctp_hdr); - } - } -} -//------------------------------------------------------------------------------ -test_packet_t* parse_xml_packet(xmlDocPtr doc, xmlNodePtr node) { - - test_packet_t *packet = NULL; - xmlNode *cur_node = NULL; - xmlChar *xml_char = NULL; - float afloat = (float)0.0; - static struct timeval initial_time = { .tv_sec = 0, .tv_usec = 0 }; - static struct timeval relative_last_sent_packet = { .tv_sec = 0, .tv_usec = 0 }; - static struct timeval relative_last_received_packet = { .tv_sec = 0, .tv_usec = 0 }; - static char first_packet = 1; - static char first_sent_packet = 1; - static char first_received_packet = 1; - static unsigned int packet_number = 1; - - if (NULL != node) { - packet = calloc(1, sizeof(*packet)); - - xml_char = xmlGetProp(node, (const xmlChar *)"action"); - packet->action = action_str2test_action_t(xml_char); - xmlFree(xml_char); - packet->packet_number = packet_number++; - - for (cur_node = node->children; cur_node; cur_node = cur_node->next) { - //if (cur_node->type == XML_ELEMENT_NODE) { - if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"frame.time_relative"))) { - xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"value"); - afloat = atof((const char*)xml_char); - xmlFree(xml_char); - packet->time_relative_to_first_packet.tv_sec = (int)afloat; - packet->time_relative_to_first_packet.tv_usec = (int)((afloat - packet->time_relative_to_first_packet.tv_sec)*1000000); - - if (first_packet > 0) { - initial_time = packet->time_relative_to_first_packet; - packet->time_relative_to_first_packet.tv_sec = 0; - packet->time_relative_to_first_packet.tv_usec = 0; - first_packet = 0; - } else { - timersub(&packet->time_relative_to_first_packet, &initial_time, - &packet->time_relative_to_first_packet); - } - if (packet->action == ACTION_S1C_SEND) { - if (first_sent_packet > 0) { - relative_last_sent_packet = packet->time_relative_to_first_packet; - packet->time_relative_to_last_sent_packet.tv_sec = 0; - packet->time_relative_to_last_sent_packet.tv_usec = 0; - first_sent_packet = 0; - } else { - timersub(&packet->time_relative_to_first_packet, &relative_last_sent_packet, - &packet->time_relative_to_last_sent_packet); - relative_last_sent_packet = packet->time_relative_to_first_packet; - } - } else if (packet->action == ACTION_S1C_RECEIVE) { - if (first_received_packet > 0) { - relative_last_received_packet.tv_sec = packet->time_relative_to_first_packet.tv_sec; - relative_last_received_packet.tv_usec = packet->time_relative_to_first_packet.tv_usec; - packet->time_relative_to_last_received_packet.tv_sec = 0; - packet->time_relative_to_last_received_packet.tv_usec = 0; - first_received_packet = 0; - } else { - timersub(&packet->time_relative_to_first_packet, &relative_last_received_packet, - &packet->time_relative_to_last_received_packet); - relative_last_received_packet = packet->time_relative_to_first_packet; - } - } - } else if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"frame.number"))) { - xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"value"); - packet->original_frame_number = strtoul((const char *)xml_char, NULL, 0); - xmlFree(xml_char); - } else if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"ip.src"))) { - xml_char = xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1); - ip_str2test_ip(xml_char, &packet->ip_hdr.src); - xmlFree(xml_char); - } else if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"ip.dst"))) { - xml_char = xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1); - ip_str2test_ip(xml_char, &packet->ip_hdr.dst); - xmlFree(xml_char); - } else if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"proto"))) { - xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"name"); - if (NULL != xml_char) { - if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp"))) { - parse_sctp(doc, cur_node, &packet->sctp_hdr); - } - xmlFree(xml_char); - } - } - //} - } - } - return packet; -} -//------------------------------------------------------------------------------ -int play_scenario(test_scenario_t* scenario) { - //TODO - display_scenario(scenario); - return 0; -} -//------------------------------------------------------------------------------ -test_scenario_t* generate_scenario( - const char * const play_scenario_filename ) -{ - xmlDocPtr doc = NULL; - xmlNodePtr root = NULL; - xmlNodePtr node = NULL; - xmlChar *xml_char = NULL; - test_scenario_t *scenario = NULL; - test_packet_t *packet = NULL; - test_packet_t **next_packet = NULL; - - doc = xmlParseFile(play_scenario_filename); - if (NULL == doc) { - AssertFatal (0, "Could not parse scenario xml file %s!\n", play_scenario_filename); - } else { - fprintf(stdout, "Test scenario file to play: %s\n", play_scenario_filename); - //xmlDebugDumpDocument(NULL, doc); - } + break; - // Get root - root = xmlDocGetRootElement(doc); - if (NULL != root) { - if ((!xmlStrcmp(root->name, (const xmlChar *)"scenario"))) { - xml_char = xmlGetProp(root, (const xmlChar *)"name"); - printf("scenario name: %s\n", xml_char); - scenario = calloc(1, sizeof(*scenario)); - scenario->name = xml_char; // nodup nofree - next_packet = &scenario->list_packet; - for (node = root->children; node != NULL; node = node->next) { - if ((!xmlStrcmp(node->name, (const xmlChar *)"packet"))) { - packet = parse_xml_packet(doc, node); - if (NULL != packet) { - *next_packet = packet; - next_packet = &packet->next; - } else { - fprintf(stdout, "WARNING omitted packet:\n"); - display_node(node, 0); - } - } + case S1AP_DEREGISTERED_ENB_IND: + LOG_W(ENB_APP, "[eNB %d] Received %s: associated MME %d\n", instance, msg_name, + S1AP_DEREGISTERED_ENB_IND(msg_p).nb_mme); + + /* TODO handle recovering of registration */ + break; + + case TIMER_HAS_EXPIRED: + LOG_I(ENB_APP, " Received %s: timer_id %d\n", msg_name, TIMER_HAS_EXPIRED(msg_p).timer_id); + + if (TIMER_HAS_EXPIRED (msg_p).timer_id == enb_register_retry_timer_id) { + /* Restart the registration process */ + registered_enb = 0; + register_enb_pending = et_eNB_app_register (enb_properties_p); } + break; + + default: + LOG_E(ENB_APP, "Received unexpected message %s\n", msg_name); + break; } - } else { - fprintf(stderr, "Empty xml document\n"); - } - xmlFreeDoc(doc); - xmlCleanupParser(); - return scenario; + + result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p); + AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); + } while (1); + return NULL; } //------------------------------------------------------------------------------ -int generate_xml_scenario( - const char const * test_dir_name, - const char const * test_scenario_filename, - const char const * enb_config_filename, - char const * play_scenario_filename /* OUT PARAM*/) -//------------------------------------------------------------------------------ +int et_play_scenario(et_scenario_t* const scenario) { - //int fd_pdml_in; - xsltStylesheetPtr cur = NULL; - xmlDocPtr doc, res; - FILE *play_scenario_file = NULL; - const char *params[2*ENB_CONFIG_MAX_XSLT_PARAMS]; - int nb_params = 0; - int i,j; - char astring[1024]; - struct in_addr addr; - int ret = 0; - - memset(astring, 0, sizeof(astring)); - if (getcwd(astring, sizeof(astring)) != NULL) { - fprintf(stdout, "working in %s directory\n", astring); - } else { - perror("getcwd() ERROR"); - exit(1); - } - - memset(astring, 0, sizeof(astring)); - strcat(astring, g_openair_dir); - strcat(astring, "/openair3/TEST/EPC_TEST/play_scenario.xsl"); + et_event_t event; + et_display_scenario(scenario); - xmlSubstituteEntitiesDefault(1); - xmlLoadExtDtdDefaultValue = 1; - cur = xsltParseStylesheetFile((const xmlChar *)astring); - if (NULL == cur) { - AssertFatal (0, "Could not parse stylesheet file %s (check OPENAIR_DIR env variable)!\n", astring); - } else { - fprintf(stdout, "XSLT style sheet: %s\n", astring); + // create SCTP ITTI task: same as eNB code + if (itti_create_task (TASK_SCTP, sctp_eNB_task, NULL) < 0) { + LOG_E(SCTP, "Create task for SCTP failed\n"); + return -1; } - doc = xmlParseFile(test_scenario_filename); - if (NULL == doc) { - AssertFatal (0, "Could not parse scenario xml file %s!\n", test_scenario_filename); - } else { - fprintf(stdout, "Test scenario file: %s\n", test_scenario_filename); + // create S1AP ITTI task: not as same as eNB code + if (itti_create_task (TASK_S1AP, et_s1ap_eNB_task, NULL) < 0) { + LOG_E(S1AP, "Create task for S1AP failed\n"); + return -1; } - for (i = 0; i < enb_properties.number; i++) { - // eNB S1-C IPv4 address - sprintf(astring, "enb_s1c%d", i); - params[nb_params++] = strdup(astring); - addr.s_addr = enb_properties.properties[i]->enb_ipv4_address_for_S1_MME; - sprintf(astring, "\"%s\"", inet_ntoa(addr)); - params[nb_params++] = strdup(astring); - - // MME S1-C IPv4 address - for (j = 0; j < enb_properties.properties[i]->nb_mme; j++) { - sprintf(astring, "mme_s1c%d_%d", i, j); - params[nb_params++] = strdup(astring); - AssertFatal (enb_properties.properties[i]->mme_ip_address[j].ipv4_address, - "Only support MME IPv4 address\n"); - sprintf(astring, "\"%s\"", enb_properties.properties[i]->mme_ip_address[j].ipv4_address); - params[nb_params++] = strdup(astring); - } - } - params[nb_params] = NULL; - res = xsltApplyStylesheet(cur, doc, params); - if (NULL != res) { - sprintf((char *)play_scenario_filename,"%s",test_scenario_filename); - if (strip_extension((char *)play_scenario_filename) > 0) { - strcat((char *)play_scenario_filename, ".tsml"); - play_scenario_file = fopen( play_scenario_filename, "w+"); - if (NULL != play_scenario_file) { - xsltSaveResultToFile(play_scenario_file, res, cur); - fclose(play_scenario_file); - fprintf(stdout, "Wrote test scenario to %s\n", play_scenario_filename); - } else { - fprintf(stderr, "ERROR in fopen(%s)\n", play_scenario_filename); - ret = -1; - } - } else { - fprintf(stderr, "ERROR in strip_extension()\n"); - ret = -1; - } - } else { - fprintf(stderr, "ERROR in xsltApplyStylesheet()\n"); - ret = -1; + // create ENB_APP ITTI task: not as same as eNB code + if (itti_create_task (TASK_ENB_APP, et_eNB_app_task, NULL) < 0) { + LOG_E(ENB_APP, "Create task for ENB_APP failed\n"); + return -1; } - xsltFreeStylesheet(cur); - xmlFreeDoc(doc); - xmlFreeDoc(res); - xsltCleanupGlobals(); - xmlCleanupParser(); - return ret; + event.code = ET_EVENT_INIT; + event.u.init.scenario = scenario; + et_scenario_fsm_notify_event(event); + + + return 0; } //------------------------------------------------------------------------------ -static void usage ( +static void et_usage ( int argc, char *argv[]) //------------------------------------------------------------------------------ @@ -1298,10 +513,10 @@ static void usage ( //------------------------------------------------------------------------------ int -config_parse_opt_line ( +et_config_parse_opt_line ( int argc, char *argv[], - char **test_dir_name, + char **et_dir_name, char **scenario_file_name, char **enb_config_file_name) //------------------------------------------------------------------------------ @@ -1354,12 +569,12 @@ config_parse_opt_line ( case LONG_OPTION_TEST_DIR: case 'd': if (optarg) { - *test_dir_name = strdup(optarg); - if (is_file_exists(*test_dir_name, "test dirname") != GS_IS_DIR) { - fprintf(stderr, "Please provide a valid test dirname, %s is not a valid directory name\n", *test_dir_name); + *et_dir_name = strdup(optarg); + if (is_file_exists(*et_dir_name, "test dirname") != GS_IS_DIR) { + fprintf(stderr, "Please provide a valid test dirname, %s is not a valid directory name\n", *et_dir_name); exit(1); } - printf("Test dir name is %s\n", *test_dir_name); + printf("Test dir name is %s\n", *et_dir_name); } break; @@ -1372,32 +587,32 @@ config_parse_opt_line ( case LONG_OPTION_HELP: case 'h': default: - usage (argc, argv); + et_usage (argc, argv); exit (0); } } - if (NULL == *test_dir_name) { + if (NULL == *et_dir_name) { fprintf(stderr, "Please provide a valid test dirname\n"); exit(1); } - if (chdir(*test_dir_name) != 0) { - fprintf(stderr, "ERROR: chdir %s returned %s\n", *test_dir_name, strerror(errno)); + if (chdir(*et_dir_name) != 0) { + fprintf(stderr, "ERROR: chdir %s returned %s\n", *et_dir_name, strerror(errno)); exit(1); } if (rv & PLAY_SCENARIO) { if (NULL == *enb_config_file_name) { - fprintf(stderr, "ERROR: please provide the original eNB config file name that should be in %s\n", *test_dir_name); + fprintf(stderr, "ERROR: please provide the original eNB config file name that should be in %s\n", *et_dir_name); } if (is_file_exists(*enb_config_file_name, "eNB config file") != GS_IS_FILE) { - fprintf(stderr, "ERROR: original eNB config file name %s is not found in dir %s\n", *enb_config_file_name, *test_dir_name); + fprintf(stderr, "ERROR: original eNB config file name %s is not found in dir %s\n", *enb_config_file_name, *et_dir_name); } enb_properties_p = enb_config_init(*enb_config_file_name); if (NULL == *scenario_file_name) { - fprintf(stderr, "ERROR: please provide the scenario file name that should be in %s\n", *test_dir_name); + fprintf(stderr, "ERROR: please provide the scenario file name that should be in %s\n", *et_dir_name); } if (is_file_exists(*scenario_file_name, "Scenario file") != GS_IS_FILE) { - fprintf(stderr, "ERROR: Scenario file name %s is not found in dir %s\n", *scenario_file_name, *test_dir_name); + fprintf(stderr, "ERROR: Scenario file name %s is not found in dir %s\n", *scenario_file_name, *et_dir_name); } } return rv; @@ -1408,12 +623,12 @@ int main( int argc, char **argv ) //------------------------------------------------------------------------------ { int actions = 0; - char *test_dir_name = NULL; + char *et_dir_name = NULL; char *scenario_file_name = NULL; char *enb_config_file_name = NULL; - char play_scenario_filename[NAME_MAX]; int ret = 0; - test_scenario_t *scenario = NULL; + et_scenario_t *scenario = NULL; + char play_scenario_filename[NAME_MAX]; memset(play_scenario_filename, 0, sizeof(play_scenario_filename)); g_openair_dir = getenv("OPENAIR_DIR"); @@ -1428,15 +643,15 @@ int main( int argc, char **argv ) set_comp_log(S1AP, LOG_TRACE, LOG_MED, 1); set_comp_log(SCTP, LOG_TRACE, LOG_MED, 1); - asn_debug = 1; + asn_debug = 0; asn1_xer_print = 1; //parameters - actions = config_parse_opt_line (argc, argv, &test_dir_name, &scenario_file_name, &enb_config_file_name); //Command-line options + actions = et_config_parse_opt_line (argc, argv, &et_dir_name, &scenario_file_name, &enb_config_file_name); //Command-line options if (actions & PLAY_SCENARIO) { - if (generate_xml_scenario(test_dir_name, scenario_file_name,enb_config_file_name, play_scenario_filename) == 0) { - if (NULL != (scenario = generate_scenario(play_scenario_filename))) { - ret = play_scenario(scenario); + if (et_generate_xml_scenario(et_dir_name, scenario_file_name,enb_config_file_name, play_scenario_filename) == 0) { + if (NULL != (scenario = et_generate_scenario(play_scenario_filename))) { + ret = et_play_scenario(scenario); } else { fprintf(stderr, "ERROR: Could not generate scenario from tsml file\n"); ret = -1; @@ -1445,9 +660,9 @@ int main( int argc, char **argv ) fprintf(stderr, "ERROR: Could not generate tsml scenario from xml file\n"); ret = -1; } - free_pointer(test_dir_name); - free_pointer(scenario_file_name); - free_pointer(enb_config_file_name); + et_free_pointer(et_dir_name); + et_free_pointer(scenario_file_name); + et_free_pointer(enb_config_file_name); } return ret; diff --git a/openair3/TEST/EPC_TEST/play_scenario.h b/openair3/TEST/EPC_TEST/play_scenario.h index 2bf6cc4ccfd..725b5abc0e9 100644 --- a/openair3/TEST/EPC_TEST/play_scenario.h +++ b/openair3/TEST/EPC_TEST/play_scenario.h @@ -28,7 +28,7 @@ *******************************************************************************/ /* - play_scenario.h + et_scenario.h ------------------- AUTHOR : Lionel GAUTHIER COMPANY : EURECOM @@ -42,21 +42,44 @@ # include <libxml/tree.h> # include <netinet/in.h> +#include "enb_config.h" #include "s1ap_ies_defs.h" +# define ET_ENB_REGISTER_RETRY_DELAY 3 -/** @defgroup _enb_app ENB APP - * @ingroup _oai2 - * @{ - */ typedef enum { - ACTION_S1C_START = 0, - ACTION_S1C_NULL = ACTION_S1C_START, - ACTION_S1C_SEND, - ACTION_S1C_RECEIVE, - ACTION_S1C_END -} test_action_t; + ET_PACKET_STATUS_START = 0, + ET_PACKET_STATUS_NONE = ET_PACKET_STATUS_START, + ET_PACKET_STATUS_NOT_TAKEN_IN_ACCOUNT, + ET_PACKET_STATUS_SCHEDULED_FOR_SENDING, + ET_PACKET_STATUS_SENT, + ET_PACKET_STATUS_SENT_WITH_ERRORS, + ET_PACKET_STATUS_SCHEDULED_FOR_RECEIVING, + ET_PACKET_STATUS_RECEIVED, + ET_PACKET_STATUS_RECEIVED_WITH_ERRORS, + ET_PACKET_STATUS_END +} et_packet_status_t; + +typedef enum { + ET_FSM_STATE_START = 0, + ET_FSM_STATE_NULL = ET_FSM_STATE_START, + ET_FSM_STATE_CONNECTING_SCTP, + ET_FSM_STATE_WAITING_TX_EVENT, + ET_FSM_STATE_WAITING_RX_EVENT, + ET_FSM_STATE_END +} et_fsm_state_t; + + + + +typedef enum { + ET_PACKET_ACTION_S1C_START = 0, + ET_PACKET_ACTION_S1C_NULL = ET_PACKET_ACTION_S1C_START, + ET_PACKET_ACTION_S1C_SEND, + ET_PACKET_ACTION_S1C_RECEIVE, + ET_PACKET_ACTION_S1C_END +} et_packet_action_t; // from kernel source file 3.19/include/linux/sctp.h typedef enum { @@ -94,16 +117,17 @@ typedef enum { TEST_S1AP_PDU_TYPE_SUCCESSFUL_OUTCOME, TEST_S1AP_PDU_TYPE_UNSUCCESSFUL_OUTCOME, TEST_S1AP_PDU_TYPE_END -} test_s1ap_pdu_type_t; +} et_s1ap_pdu_type_t; -typedef struct test_s1ap_s { - //test_s1ap_pdu_type_t pdu_type; +typedef struct et_s1ap_s { + //et_s1ap_pdu_type_t pdu_type; + S1AP_PDU_t pdu; // decoded ASN1 C type: choice of initiatingMessage, successfulOutcome, unsuccessfulOutcome uint16_t binary_stream_pos; uint16_t binary_stream_allocated_size; uint8_t *binary_stream; - s1ap_message message; -} test_s1ap_t; + s1ap_message message; // decoded message: information elements +} et_s1ap_t; // from kernel source file 3.19/include/linux/sctp.h, Big Endians @@ -112,7 +136,7 @@ typedef struct sctp_datahdr_s { uint16_t stream; uint16_t ssn; uint32_t ppid; - test_s1ap_t payload; + et_s1ap_t payload; } sctp_datahdr_t; // from kernel source file 3.19/include/linux/sctp.h, Big Endians @@ -127,7 +151,7 @@ typedef struct sctp_inithdr { typedef sctp_inithdr_t sctp_initackhdr_t; -typedef struct test_sctp_hdr_s { +typedef struct et_sctp_hdr_s { unsigned int src_port; unsigned int dst_port; sctp_cid_t chunk_type; @@ -136,38 +160,145 @@ typedef struct test_sctp_hdr_s { sctp_inithdr_t init_hdr; sctp_initackhdr_t init_ack_hdr; } u; -} test_sctp_hdr_t; +} et_sctp_hdr_t; -typedef struct test_ip_s { +typedef struct et_ip_s { unsigned int address_family; // AF_INET, AF_INET6 union { struct in6_addr ipv6; in_addr_t ipv4; }address; -}test_ip_t; - -typedef struct test_ip_hdr_s { - test_ip_t src; - test_ip_t dst; -} test_ip_hdr_t; - -typedef struct test_packet_s { - test_action_t action; - struct timeval time_relative_to_first_packet; - struct timeval time_relative_to_last_sent_packet; - struct timeval time_relative_to_last_received_packet; - unsigned int original_frame_number; - unsigned int packet_number; - test_ip_hdr_t ip_hdr; - test_sctp_hdr_t sctp_hdr; - struct test_packet_s *next; -}test_packet_t; - -typedef struct test_scenario_s { +}et_ip_t; + +typedef struct et_ip_hdr_s { + et_ip_t src; + et_ip_t dst; +} et_ip_hdr_t; + +typedef struct et_packet_s { + et_packet_action_t action; + struct timeval time_relative_to_first_packet; + struct timeval time_relative_to_last_sent_packet; + struct timeval time_relative_to_last_received_packet; + unsigned int original_frame_number; + unsigned int packet_number; + et_ip_hdr_t ip_hdr; + et_sctp_hdr_t sctp_hdr; + struct et_packet_s *next; + //scenario running vars + et_packet_status_t status; +}et_packet_t; + + +typedef struct sctp_epoll_s { + /* Array of events monitored by the task. + * By default only one fd is monitored (the one used to received messages + * from other tasks). + * More events can be suscribed later by the task itself. + */ + struct epoll_event *events; + + int epoll_nb_events; + +} thread_desc_t; + +typedef struct et_scenario_s { xmlChar *name; - test_packet_t *list_packet; -}test_scenario_t; + et_packet_t *list_packet; + + // playing scenario + et_packet_t *waited_packet; + et_packet_t *current_packet; +} et_scenario_t; + + +typedef enum { + ET_EVENT_START = 0, + ET_EVENT_INIT = ET_EVENT_START, + ET_EVENT_RX_SCTP_EVENT, + ET_EVENT_RX_S1AP, + ET_EVENT_RX_X2AP, + ET_EVENT_RX_PACKET_TIME_OUT, + ET_EVENT_TX_PACKET, + ET_EVENT_STOP, + ET_EVENT_END +} et_event_code_t; + +typedef struct et_event_init_s { + et_scenario_t *scenario; +} et_event_init_t; + +typedef struct et_event_s1ap_data_ind_s { + sctp_datahdr_t sctp_datahdr; +} et_event_s1ap_data_ind_t; + +typedef struct et_event_s1ap_data_req_s { + +} et_event_s1ap_data_req_t; + +typedef struct et_event_s { + et_event_code_t code; + union { + et_event_init_t init; + et_event_s1ap_data_ind_t s1ap_data_ind; + et_event_s1ap_data_req_t s1ap_data_req; + } u; +} et_event_t; + +inline void et_free_pointer(void *p) {if (NULL != p) {free(p); p=NULL;}}; + +//------------------------- +void et_free_packet(et_packet_t* packet); +void et_free_scenario(et_scenario_t* scenario); +//------------------------- +void et_display_packet_s1ap_data(const et_s1ap_t * const s1ap); +void et_display_packet_sctp_init(const sctp_inithdr_t * const sctp); +void et_display_packet_sctp_initack(const sctp_initackhdr_t * const sctp); +void et_display_packet_sctp_data(const sctp_datahdr_t * const sctp); +void et_display_packet_sctp(const et_sctp_hdr_t * const sctp); +void et_display_packet_ip(const et_ip_hdr_t * const ip); +void et_display_packet(const et_packet_t * const packet); +void et_display_scenario(const et_scenario_t * const scenario); +//------------------------- +int et_s1ap_decode_initiating_message(s1ap_message *message, S1ap_InitiatingMessage_t *initiating_p); +int et_s1ap_decode_successful_outcome(s1ap_message *message, S1ap_SuccessfulOutcome_t *successfullOutcome_p); +int et_s1ap_decode_unsuccessful_outcome(s1ap_message *message, S1ap_UnsuccessfulOutcome_t *unSuccessfullOutcome_p); +int et_s1ap_decode_pdu(S1AP_PDU_t * const pdu, s1ap_message * const message, const uint8_t * const buffer, const uint32_t length); +void et_decode_s1ap(et_s1ap_t * const s1ap); +//------------------------- +void et_s1ap_eNB_handle_sctp_data_ind(sctp_data_ind_t *sctp_data_ind); +void * et_s1ap_eNB_task(void *arg); +int et_generate_xml_scenario( + const char const * xml_in_dir_name, + const char const * xml_in_scenario_filename, + const char const * enb_config_filename, + char const * tsml_out_scenario_filename); +//------------------------- +int et_scenario_fsm_notify_event_state_null(et_event_t event); +int et_scenario_fsm_notify_event(et_event_t event); +//------------------------- +void et_parse_s1ap(xmlDocPtr doc, const xmlNode const *s1ap_node, et_s1ap_t * const s1ap); +void et_parse_sctp_data_chunk(xmlDocPtr doc, const xmlNode const *sctp_node, sctp_datahdr_t * const sctp_hdr); +void et_parse_sctp_init_chunk(xmlDocPtr doc, const xmlNode const *sctp_node, sctp_inithdr_t * const sctp_hdr); +void et_parse_sctp_init_ack_chunk(xmlDocPtr doc, const xmlNode const *sctp_node, sctp_initackhdr_t * const sctp_hdr); +void et_parse_sctp(xmlDocPtr doc, const xmlNode const *sctp_node, et_sctp_hdr_t * const sctp_hdr); +et_packet_t* et_parse_xml_packet(xmlDocPtr doc, xmlNodePtr node); +et_scenario_t* et_generate_scenario(const char * const et_scenario_filename ); +//------------------------- +void et_print_hex_octets(const unsigned char * const byte_stream, const unsigned long int num); +int et_is_file_exists ( const char const * file_nameP, const char const *file_roleP); +int et_strip_extension( char *in_filename); +int et_split_path ( char * pathP, char *** resP); +void et_display_node ( xmlNodePtr node, unsigned int indent); +void et_display_tree ( xmlNodePtr node, unsigned int indent); +char * et_ip2ip_str(const et_ip_t * const ip); +int et_hex2data(unsigned char * const data, const unsigned char * const hexstring, const unsigned int len); +sctp_cid_t et_chunk_type_str2cid(const xmlChar * const chunk_type_str); +const char * const et_chunk_type_cid2str(const sctp_cid_t chunk_type); +et_packet_action_t et_action_str2et_action_t(const xmlChar * const action); +void et_ip_str2et_ip(const xmlChar * const ip_str, et_ip_t * const ip); +uint32_t et_eNB_app_register(const Enb_properties_array_t *enb_properties); +void *et_eNB_app_task(void *args_p); +int et_play_scenario(et_scenario_t* const scenario); -inline void free_pointer(void *p) {if (NULL != p) {free(p); p=NULL;}}; -#endif /* ENB_CONFIG_H_ */ -/** @} */ +#endif /* PLAY_SCENARIO_H_ */ diff --git a/openair3/TEST/EPC_TEST/play_scenario_decode.c b/openair3/TEST/EPC_TEST/play_scenario_decode.c new file mode 100644 index 00000000000..aba1703eb3f --- /dev/null +++ b/openair3/TEST/EPC_TEST/play_scenario_decode.c @@ -0,0 +1,214 @@ +/******************************************************************************* + OpenAirInterface + Copyright(c) 1999 - 2014 Eurecom + + OpenAirInterface is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + + OpenAirInterface is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenAirInterface.The full GNU General Public License is + included in this distribution in the file called "COPYING". If not, + see <http://www.gnu.org/licenses/>. + + Contact Information + OpenAirInterface Admin: openair_admin@eurecom.fr + OpenAirInterface Tech : openair_tech@eurecom.fr + OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr + + Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE + + *******************************************************************************/ + +/* + play_scenario_decode.c + ------------------- + AUTHOR : Lionel GAUTHIER + COMPANY : EURECOM + EMAIL : Lionel.Gauthier@eurecom.fr + */ + +#include "intertask_interface.h" +#include "platform_types.h" +#include "s1ap_ies_defs.h" +#include "s1ap_eNB_decoder.h" +#include "assertions.h" +#include "play_scenario.h" + +//------------------------------------------------------------------------------ +int et_s1ap_decode_initiating_message(s1ap_message *message, S1ap_InitiatingMessage_t *initiating_p) +{ + int ret = -1; + + DevAssert(initiating_p != NULL); + + message->procedureCode = initiating_p->procedureCode; + message->criticality = initiating_p->criticality; + + switch(initiating_p->procedureCode) { + case S1ap_ProcedureCode_id_downlinkNASTransport: + ret = s1ap_decode_s1ap_downlinknastransporties(&message->msg.s1ap_DownlinkNASTransportIEs,&initiating_p->value); + break; + + case S1ap_ProcedureCode_id_InitialContextSetup: + ret = s1ap_decode_s1ap_initialcontextsetuprequesties(&message->msg.s1ap_InitialContextSetupRequestIEs, &initiating_p->value); + break; + + case S1ap_ProcedureCode_id_UEContextRelease: + ret = s1ap_decode_s1ap_uecontextreleasecommandies(&message->msg.s1ap_UEContextReleaseCommandIEs, &initiating_p->value); + break; + + case S1ap_ProcedureCode_id_Paging: + ret = s1ap_decode_s1ap_pagingies(&message->msg.s1ap_PagingIEs, &initiating_p->value); + break; + + case S1ap_ProcedureCode_id_uplinkNASTransport: + ret = s1ap_decode_s1ap_uplinknastransporties (&message->msg.s1ap_UplinkNASTransportIEs, &initiating_p->value); + break; + + case S1ap_ProcedureCode_id_S1Setup: + ret = s1ap_decode_s1ap_s1setuprequesties (&message->msg.s1ap_S1SetupRequestIEs, &initiating_p->value); + break; + + case S1ap_ProcedureCode_id_initialUEMessage: + ret = s1ap_decode_s1ap_initialuemessageies (&message->msg.s1ap_InitialUEMessageIEs, &initiating_p->value); + break; + + case S1ap_ProcedureCode_id_UEContextReleaseRequest: + ret = s1ap_decode_s1ap_uecontextreleaserequesties (&message->msg.s1ap_UEContextReleaseRequestIEs, &initiating_p->value); + break; + + case S1ap_ProcedureCode_id_UECapabilityInfoIndication: + ret = s1ap_decode_s1ap_uecapabilityinfoindicationies (&message->msg.s1ap_UECapabilityInfoIndicationIEs, &initiating_p->value); + break; + + case S1ap_ProcedureCode_id_NASNonDeliveryIndication: + ret = s1ap_decode_s1ap_nasnondeliveryindication_ies (&message->msg.s1ap_NASNonDeliveryIndication_IEs, &initiating_p->value); + break; + + default: + AssertFatal( 0 , "Unknown procedure ID (%d) for initiating message\n", + (int)initiating_p->procedureCode); + return -1; + } + return ret; +} + +//------------------------------------------------------------------------------ +int et_s1ap_decode_successful_outcome(s1ap_message *message, S1ap_SuccessfulOutcome_t *successfullOutcome_p) +{ + int ret = -1; + + DevAssert(successfullOutcome_p != NULL); + + message->procedureCode = successfullOutcome_p->procedureCode; + message->criticality = successfullOutcome_p->criticality; + + switch(successfullOutcome_p->procedureCode) { + case S1ap_ProcedureCode_id_S1Setup: + ret = s1ap_decode_s1ap_s1setupresponseies( + &message->msg.s1ap_S1SetupResponseIEs, &successfullOutcome_p->value); + break; + + case S1ap_ProcedureCode_id_InitialContextSetup: + ret = s1ap_decode_s1ap_initialcontextsetupresponseies (&message->msg.s1ap_InitialContextSetupResponseIEs, &successfullOutcome_p->value); + break; + + case S1ap_ProcedureCode_id_UEContextRelease: + ret = s1ap_decode_s1ap_uecontextreleasecompleteies (&message->msg.s1ap_UEContextReleaseCompleteIEs, &successfullOutcome_p->value); + break; + + default: + AssertFatal(0, "Unknown procedure ID (%d) for successfull outcome message\n", + (int)successfullOutcome_p->procedureCode); + return -1; + } + return ret; +} + +//------------------------------------------------------------------------------ +int et_s1ap_decode_unsuccessful_outcome(s1ap_message *message, S1ap_UnsuccessfulOutcome_t *unSuccessfullOutcome_p) +{ + int ret = -1; + + DevAssert(unSuccessfullOutcome_p != NULL); + + message->procedureCode = unSuccessfullOutcome_p->procedureCode; + message->criticality = unSuccessfullOutcome_p->criticality; + + switch(unSuccessfullOutcome_p->procedureCode) { + case S1ap_ProcedureCode_id_S1Setup: + ret = s1ap_decode_s1ap_s1setupfailureies(&message->msg.s1ap_S1SetupFailureIEs, &unSuccessfullOutcome_p->value); + break; + + case S1ap_ProcedureCode_id_InitialContextSetup: + ret = s1ap_decode_s1ap_initialcontextsetupfailureies (&message->msg.s1ap_InitialContextSetupFailureIEs, &unSuccessfullOutcome_p->value); + break; + + default: + AssertFatal(0,"Unknown procedure ID (%d) for unsuccessfull outcome message\n", + (int)unSuccessfullOutcome_p->procedureCode); + break; + } + return ret; +} + +//------------------------------------------------------------------------------ +int et_s1ap_decode_pdu(S1AP_PDU_t * const pdu, s1ap_message * const message, const uint8_t * const buffer, const uint32_t length) +{ + asn_dec_rval_t dec_ret; + + DevAssert(buffer != NULL); + + memset((void *)pdu, 0, sizeof(S1AP_PDU_t)); + + dec_ret = aper_decode(NULL, + &asn_DEF_S1AP_PDU, + (void **)&pdu, + buffer, + length, + 0, + 0); + + if (dec_ret.code != RC_OK) { + S1AP_ERROR("Failed to decode pdu\n"); + return -1; + } + + message->direction = pdu->present; + + switch(pdu->present) { + case S1AP_PDU_PR_initiatingMessage: + return et_s1ap_decode_initiating_message(message, + &pdu->choice.initiatingMessage); + + case S1AP_PDU_PR_successfulOutcome: + return et_s1ap_decode_successful_outcome(message, + &pdu->choice.successfulOutcome); + + case S1AP_PDU_PR_unsuccessfulOutcome: + return et_s1ap_decode_unsuccessful_outcome(message, + &pdu->choice.unsuccessfulOutcome); + + default: + AssertFatal(0, "Unknown presence (%d) or not implemented\n", (int)pdu->present); + break; + } + return -1; +} +//------------------------------------------------------------------------------ +void et_decode_s1ap(et_s1ap_t * const s1ap) +{ + if (NULL != s1ap) { + if (et_s1ap_decode_pdu(&s1ap->pdu, &s1ap->message, s1ap->binary_stream, s1ap->binary_stream_allocated_size) < 0) { + AssertFatal (0, "ERROR %s() Cannot decode S1AP message!\n", __FUNCTION__); + } + } +} diff --git a/openair3/TEST/EPC_TEST/play_scenario_display.c b/openair3/TEST/EPC_TEST/play_scenario_display.c new file mode 100644 index 00000000000..406c69c8587 --- /dev/null +++ b/openair3/TEST/EPC_TEST/play_scenario_display.c @@ -0,0 +1,292 @@ +/******************************************************************************* + OpenAirInterface + Copyright(c) 1999 - 2014 Eurecom + + OpenAirInterface is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + + OpenAirInterface is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenAirInterface.The full GNU General Public License is + included in this distribution in the file called "COPYING". If not, + see <http://www.gnu.org/licenses/>. + + Contact Information + OpenAirInterface Admin: openair_admin@eurecom.fr + OpenAirInterface Tech : openair_tech@eurecom.fr + OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr + + Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE + + *******************************************************************************/ + +/* + play_scenario_display.c + ------------------- + AUTHOR : Lionel GAUTHIER + COMPANY : EURECOM + EMAIL : Lionel.Gauthier@eurecom.fr + */ +#include <string.h> +#include <stdio.h> + +#include "intertask_interface.h" +#include "platform_types.h" +#include "assertions.h" +#include "s1ap_ies_defs.h" +#include "s1ap_eNB_decoder.h" +#include "play_scenario.h" +//----------------------------------------------------------------------------- +void et_print_hex_octets(const unsigned char * const byte_stream, const unsigned long int num) +{ + unsigned long octet_index = 0; + + if (byte_stream == NULL) { + return; + } + + fprintf(stdout, "+-----+-------------------------------------------------+\n"); + fprintf(stdout, "| | 0 1 2 3 4 5 6 7 8 9 a b c d e f |\n"); + fprintf(stdout, "+-----+-------------------------------------------------+\n"); + + for (octet_index = 0; octet_index < num; octet_index++) { + if ((octet_index % 16) == 0) { + if (octet_index != 0) { + fprintf(stdout, " |\n"); + } + + fprintf(stdout, " %04ld |", octet_index); + } + + /* + * Print every single octet in hexadecimal form + */ + fprintf(stdout, " %02x", byte_stream[octet_index]); + /* + * Align newline and pipes according to the octets in groups of 2 + */ + } + + /* + * Append enough spaces and put final pipe + */ + unsigned char index; + + for (index = octet_index; index < 16; ++index) { + fprintf(stdout, " "); + } + + fprintf(stdout, " |\n"); +} + +//------------------------------------------------------------------------------ +void et_display_node(xmlNodePtr node, unsigned int indent) +{ + int i = 0; + if (node->type == XML_ELEMENT_NODE) { + xmlChar *path = xmlGetNodePath(node); + for (i=0; i<indent; i++) { + printf(" "); + } + if (node->children != NULL && node->children->type == XML_TEXT_NODE) { + xmlChar *content = xmlNodeGetContent(node); + printf("%s -> %s\n", path, content); + xmlFree(content); + } else { + printf("%s\n", path); + } + xmlFree(path); + } +} +//------------------------------------------------------------------------------ +void et_display_tree(xmlNodePtr node, unsigned int indent) +{ + xmlNode *cur_node = NULL; + + for (cur_node = node; cur_node; cur_node = cur_node->next) { + if (cur_node->type == XML_ELEMENT_NODE) { + et_display_node(cur_node, indent); + } + et_display_tree(cur_node->children, indent++); + } +} +//------------------------------------------------------------------------------ +void et_display_packet_s1ap_data(const et_s1ap_t * const s1ap) +{ + char *message_string = NULL; + + if (s1ap) { + message_string = calloc(20000, sizeof(char)); + AssertFatal (NULL != message_string, "ERROR malloc()failed!\n"); + s1ap_string_total_size = 0; + switch(s1ap->pdu.present) { + case S1AP_PDU_PR_initiatingMessage: + switch(s1ap->pdu.choice.initiatingMessage.procedureCode) { + case S1ap_ProcedureCode_id_downlinkNASTransport: s1ap_xer_print_s1ap_downlinknastransport(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break; + case S1ap_ProcedureCode_id_InitialContextSetup: s1ap_xer_print_s1ap_initialcontextsetuprequest(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break; + case S1ap_ProcedureCode_id_UEContextRelease: s1ap_xer_print_s1ap_uecontextreleasecommand(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break; + case S1ap_ProcedureCode_id_Paging: s1ap_xer_print_s1ap_paging(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break; + case S1ap_ProcedureCode_id_uplinkNASTransport: s1ap_xer_print_s1ap_uplinknastransport(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break; + case S1ap_ProcedureCode_id_S1Setup: s1ap_xer_print_s1ap_s1setuprequest(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break; + case S1ap_ProcedureCode_id_initialUEMessage: s1ap_xer_print_s1ap_initialuemessage(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break; + case S1ap_ProcedureCode_id_UEContextReleaseRequest: s1ap_xer_print_s1ap_uecontextreleaserequest(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break; + case S1ap_ProcedureCode_id_UECapabilityInfoIndication:s1ap_xer_print_s1ap_uecapabilityinfoindication(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break; + case S1ap_ProcedureCode_id_NASNonDeliveryIndication: s1ap_xer_print_s1ap_nasnondeliveryindication_(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break; + default: + AssertFatal( 0 , "Unknown procedure ID (%d) for initiating message\n", + (int)s1ap->pdu.choice.initiatingMessage.procedureCode); + } + break; + case S1AP_PDU_PR_successfulOutcome: + switch(s1ap->pdu.choice.successfulOutcome.procedureCode) { + case S1ap_ProcedureCode_id_S1Setup: s1ap_xer_print_s1ap_s1setupresponse(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break; + case S1ap_ProcedureCode_id_InitialContextSetup: s1ap_xer_print_s1ap_initialcontextsetupresponse(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break; + case S1ap_ProcedureCode_id_UEContextRelease: s1ap_xer_print_s1ap_uecontextreleasecomplete(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break; + default: + AssertFatal(0, "Unknown procedure ID (%d) for successfull outcome message\n", + (int)s1ap->pdu.choice.successfulOutcome.procedureCode); + } + break; + + case S1AP_PDU_PR_unsuccessfulOutcome: + switch(s1ap->pdu.choice.unsuccessfulOutcome.procedureCode) { + case S1ap_ProcedureCode_id_S1Setup: s1ap_xer_print_s1ap_s1setupfailure(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break; + case S1ap_ProcedureCode_id_InitialContextSetup: s1ap_xer_print_s1ap_initialcontextsetupfailure(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break; + default: + et_free_pointer(message_string); + AssertFatal(0,"Unknown procedure ID (%d) for unsuccessfull outcome message\n", + (int)s1ap->pdu.choice.unsuccessfulOutcome.procedureCode); + break; + } + break; + default: + AssertFatal(0, "Unknown presence (%d) or not implemented\n", (int)s1ap->pdu.present); + break; + } + fprintf(stdout, "\t\tSCTP.data XML dump:\n%s\n", message_string); + et_free_pointer(message_string); + } +} +//------------------------------------------------------------------------------ +void et_display_packet_sctp_init(const sctp_inithdr_t * const sctp) +{ + + if (sctp) { + fprintf(stdout, "\t\tSCTP.init.init_tag : %u\n", sctp->init_tag); + fprintf(stdout, "\t\tSCTP.init.a_rwnd : %u\n", sctp->a_rwnd); + fprintf(stdout, "\t\tSCTP.init.num_inbound_streams : %u\n", sctp->num_inbound_streams); + fprintf(stdout, "\t\tSCTP.init.num_outbound_streams : %u\n", sctp->num_outbound_streams); + fprintf(stdout, "\t\tSCTP.init.initial_tsn : %u\n", sctp->initial_tsn); + } +} +//------------------------------------------------------------------------------ +void et_display_packet_sctp_initack(const sctp_initackhdr_t * const sctp) +{ + + if (sctp) { + fprintf(stdout, "\t\tSCTP.initack.init_tag : %u\n", sctp->init_tag); + fprintf(stdout, "\t\tSCTP.initack.a_rwnd : %u\n", sctp->a_rwnd); + fprintf(stdout, "\t\tSCTP.initack.num_inbound_streams : %u\n", sctp->num_inbound_streams); + fprintf(stdout, "\t\tSCTP.initack.num_outbound_streams : %u\n", sctp->num_outbound_streams); + fprintf(stdout, "\t\tSCTP.initack.initial_tsn : %u\n", sctp->initial_tsn); + } +} +//------------------------------------------------------------------------------ +void et_display_packet_sctp_data(const sctp_datahdr_t * const sctp) +{ + if (sctp) { + fprintf(stdout, "\t\tSCTP.data.tsn : %u\n", sctp->tsn); + fprintf(stdout, "\t\tSCTP.data.stream : %u\n", sctp->stream); + fprintf(stdout, "\t\tSCTP.data.ssn : %u\n", sctp->ssn); + fprintf(stdout, "\t\tSCTP.data.ppid : %u\n", sctp->ppid); + if (sctp->ppid == 18) { + et_display_packet_s1ap_data(&sctp->payload); + } + fprintf(stdout, "\t\tSCTP.data.binary_stream_allocated_size : %u\n", sctp->payload.binary_stream_allocated_size); + if (NULL != sctp->payload.binary_stream) { + fprintf(stdout, "\t\tSCTP.data.binary_stream :\n"); + et_print_hex_octets(sctp->payload.binary_stream, sctp->payload.binary_stream_allocated_size); + } else { + fprintf(stdout, "\t\tSCTP.data.binary_stream : NULL\n"); + } + } +} + +//------------------------------------------------------------------------------ +void et_display_packet_sctp(const et_sctp_hdr_t * const sctp) +{ + if (sctp) { + fprintf(stdout, "\t\tSCTP.src_port : %u\n", sctp->src_port); + fprintf(stdout, "\t\tSCTP.dst_port : %u\n", sctp->dst_port); + fprintf(stdout, "\t\tSCTP.chunk_type : %s\n", et_chunk_type_cid2str(sctp->chunk_type)); + switch (sctp->chunk_type) { + case SCTP_CID_DATA: + et_display_packet_sctp_data(&sctp->u.data_hdr); + break; + case SCTP_CID_INIT: + et_display_packet_sctp_initack(&sctp->u.init_hdr); + break; + case SCTP_CID_INIT_ACK: + et_display_packet_sctp_initack(&sctp->u.init_ack_hdr); + break; + default: + ; + } + } +} +//------------------------------------------------------------------------------ +void et_display_packet_ip(const et_ip_hdr_t * const ip) +{ + if (ip) { + fprintf(stdout, "\t\tSource address : %s\n", et_ip2ip_str(&ip->src)); + fprintf(stdout, "\t\tDestination address : %s\n", et_ip2ip_str(&ip->dst)); + } +} + +//------------------------------------------------------------------------------ +void et_display_packet(const et_packet_t * const packet) +{ + if (packet) { + fprintf(stdout, "-------------------------------------------------------------------------------\n"); + fprintf(stdout, "\tPacket:\tnum %u | original frame number %u \n", packet->packet_number, packet->original_frame_number); + fprintf(stdout, "\tPacket:\ttime relative to 1st packet %ld.%06lu\n", + packet->time_relative_to_first_packet.tv_sec, packet->time_relative_to_first_packet.tv_usec); + fprintf(stdout, "\tPacket:\ttime relative to last tx packet %ld.%06lu\n", + packet->time_relative_to_last_sent_packet.tv_sec, packet->time_relative_to_last_sent_packet.tv_usec); + fprintf(stdout, "\tPacket:\ttime relative to last_received packet %ld.%06lu\n", + packet->time_relative_to_last_received_packet.tv_sec, packet->time_relative_to_last_received_packet.tv_usec); + + switch(packet->action) { + case ET_PACKET_ACTION_S1C_SEND: + fprintf(stdout, "\tPacket:\tAction SEND\n"); + break; + case ET_PACKET_ACTION_S1C_RECEIVE: + fprintf(stdout, "\tPacket:\tAction RECEIVE\n"); + break; + default: + fprintf(stdout, "\tPacket:\tAction UNKNOWN\n"); + } + et_display_packet_ip(&packet->ip_hdr); + et_display_packet_sctp(&packet->sctp_hdr); + } +} +//------------------------------------------------------------------------------ +void et_display_scenario(const et_scenario_t * const scenario) +{ + et_packet_t *packet = NULL; + if (scenario) { + fprintf(stdout, "Scenario: %s\n", (scenario->name != NULL) ? (char*)scenario->name:"UNKNOWN NAME"); + packet = scenario->list_packet; + while (packet) { + et_display_packet(packet); + packet = packet->next; + } + } +} diff --git a/openair3/TEST/EPC_TEST/play_scenario_fsm.c b/openair3/TEST/EPC_TEST/play_scenario_fsm.c new file mode 100644 index 00000000000..6c73793f4df --- /dev/null +++ b/openair3/TEST/EPC_TEST/play_scenario_fsm.c @@ -0,0 +1,127 @@ +/******************************************************************************* + OpenAirInterface + Copyright(c) 1999 - 2014 Eurecom + + OpenAirInterface is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + + OpenAirInterface is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenAirInterface.The full GNU General Public License is + included in this distribution in the file called "COPYING". If not, + see <http://www.gnu.org/licenses/>. + + Contact Information + OpenAirInterface Admin: openair_admin@eurecom.fr + OpenAirInterface Tech : openair_tech@eurecom.fr + OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr + + Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE + + *******************************************************************************/ + +/* + play_scenario_fsm.c + ------------------- + AUTHOR : Lionel GAUTHIER + COMPANY : EURECOM + EMAIL : Lionel.Gauthier@eurecom.fr + */ +#include <stdio.h> + +#include "intertask_interface.h" +#include "platform_types.h" +#include "assertions.h" +#include "play_scenario.h" + + +et_scenario_t *g_scenario = NULL; +et_fsm_state_t g_fsm_state = ET_FSM_STATE_NULL; +//------------------------------------------------------------------------------ +int et_scenario_fsm_notify_event_state_null(et_event_t event) +{ + et_packet_t *packet = NULL; + const Enb_properties_array_t *enb_properties_p = NULL; + uint32_t register_enb_pending; + + switch (event.code){ + case ET_EVENT_INIT: + AssertFatal(NULL == g_scenario, "Current scenario not ended"); + g_scenario = event.u.init.scenario; + packet = g_scenario->list_packet; + while (NULL != packet) { + switch (packet->sctp_hdr.chunk_type) { + + case SCTP_CID_DATA : + // no init in this scenario, may be sub-scenario + if (packet->action == ET_PACKET_ACTION_S1C_SEND) { + } else if (packet->action == ET_PACKET_ACTION_S1C_RECEIVE) { + g_scenario->waited_packet = packet; + } else { + packet->status = ET_PACKET_STATUS_NOT_TAKEN_IN_ACCOUNT; + packet = packet->next; + } + break; + case SCTP_CID_INIT: + case SCTP_CID_INIT_ACK: + enb_properties_p = enb_config_get(); + /* Try to register each eNB */ + g_fsm_state = ET_FSM_STATE_CONNECTING_SCTP; + register_enb_pending = et_eNB_app_register (enb_properties_p); + break; + case SCTP_CID_HEARTBEAT: + case SCTP_CID_HEARTBEAT_ACK: + case SCTP_CID_COOKIE_ECHO: + case SCTP_CID_COOKIE_ACK: + case SCTP_CID_ECN_ECNE: + case SCTP_CID_ECN_CWR: + packet->status = ET_PACKET_STATUS_NOT_TAKEN_IN_ACCOUNT; + packet = packet->next; + break; + case SCTP_CID_ABORT: + case SCTP_CID_SHUTDOWN: + case SCTP_CID_SHUTDOWN_ACK: + case SCTP_CID_ERROR: + case SCTP_CID_SHUTDOWN_COMPLETE: + AssertFatal(0, "The scenario should be cleaned (packet %s cannot be processed at this time)", et_chunk_type_cid2str(packet->sctp_hdr.chunk_type)); + break; + + default: + packet->status = ET_PACKET_STATUS_NOT_TAKEN_IN_ACCOUNT; + packet = packet->next; + } + } + fprintf(stderr, "No Packet found in this scenario: %s\n", g_scenario->name); + return -1; + break; + + case ET_EVENT_STOP: + break; + + default: + AssertFatal(0, "Case event %d not handled in ET_FSM_STATE_NULL", event.code); + } + return 0; +} + +//------------------------------------------------------------------------------ +int et_scenario_fsm_notify_event(et_event_t event) +{ + AssertFatal((event.code >= ET_EVENT_START) && (event.code < ET_EVENT_END), "Unknown et_event_t.code %d", event.code); + + switch (g_fsm_state){ + case ET_FSM_STATE_NULL: return et_scenario_fsm_notify_event_state_null(event); break; + case ET_FSM_STATE_CONNECTING_SCTP: return et_scenario_fsm_notify_event_state_null(event); break; + case ET_FSM_STATE_WAITING_TX_EVENT: return et_scenario_fsm_notify_event_state_null(event); break; + case ET_FSM_STATE_WAITING_RX_EVENT: return et_scenario_fsm_notify_event_state_null(event); break; + default: + return -1; + } +} diff --git a/openair3/TEST/EPC_TEST/play_scenario_parse.c b/openair3/TEST/EPC_TEST/play_scenario_parse.c new file mode 100644 index 00000000000..236c17963ab --- /dev/null +++ b/openair3/TEST/EPC_TEST/play_scenario_parse.c @@ -0,0 +1,561 @@ +/******************************************************************************* + OpenAirInterface + Copyright(c) 1999 - 2014 Eurecom + + OpenAirInterface is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + + OpenAirInterface is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenAirInterface.The full GNU General Public License is + included in this distribution in the file called "COPYING". If not, + see <http://www.gnu.org/licenses/>. + + Contact Information + OpenAirInterface Admin: openair_admin@eurecom.fr + OpenAirInterface Tech : openair_tech@eurecom.fr + OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr + + Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE + + *******************************************************************************/ + +/* + play_scenario_parse.c + ------------------- + AUTHOR : Lionel GAUTHIER + COMPANY : EURECOM + EMAIL : Lionel.Gauthier@eurecom.fr + */ + +#include <libxml/xmlmemory.h> +#include <libxml/debugXML.h> +#include <libxml/xmlIO.h> +#include <libxml/DOCBparser.h> +#include <libxml/xinclude.h> +#include <libxml/catalog.h> +#include <libxml/xmlreader.h> +#include <libxslt/xslt.h> +#include <libxslt/xsltInternals.h> +#include <libxslt/transform.h> +#include <libxslt/xsltutils.h> +#include <sys/time.h> + +#include "intertask_interface.h" +#include "platform_types.h" +#include "enb_config.h" +#include "assertions.h" +#include "play_scenario.h" +//------------------------------------------------------------------------------ +#define ENB_CONFIG_MAX_XSLT_PARAMS 32 +//------------------------------------------------------------------------------ +extern char *g_openair_dir; +extern Enb_properties_array_t enb_properties; +//------------------------------------------------------------------------------ +void et_parse_s1ap(xmlDocPtr doc, const xmlNode const *s1ap_node, et_s1ap_t * const s1ap) +{ + xmlNode *cur_node = NULL; + xmlChar *xml_char = NULL; + xmlChar *xml_char2 = NULL; + unsigned int size = 0; + int rc = 0; + unsigned int go_deeper_in_tree = 1; + + if ((NULL != s1ap_node) && (NULL != s1ap)) { + for (cur_node = (xmlNode *)s1ap_node; cur_node; cur_node = cur_node->next) { + go_deeper_in_tree = 1; + if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"field"))) { + // do not get hidden fields + xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"hide"); + if (NULL != xml_char) { + if ((!xmlStrcmp(xml_char, (const xmlChar *)"yes"))) { + go_deeper_in_tree = 0; + } + xmlFree(xml_char); + } + if (0 < go_deeper_in_tree) { + // first get size + xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"size"); + if (NULL != xml_char) { + size = strtoul((const char *)xml_char, NULL, 0); + xmlFree(xml_char); + // second: try to get value (always hex) + xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"value"); + if (NULL != xml_char) { + xml_char2 = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"name"); + fprintf(stdout, "s1ap %p field %s size %d value %s\n",s1ap, xml_char2, size, xml_char); + xmlFree(xml_char2); + // if success to get value, do not parse children + //AssertFatal ((xmlStrlen(xml_char) == size), "ERROR %s() mismatch in size %d and strlen %d\n", __FUNCTION__, size, xmlStrlen(xml_char)); + //if (xmlStrlen(xml_char) == size) { + AssertFatal ((s1ap->binary_stream_pos+xmlStrlen(xml_char)/2) <= s1ap->binary_stream_allocated_size, + "ERROR %s() in buffer size: binary_stream_pos %d xmlStrlen(xml_char)/2=%d\n", __FUNCTION__, s1ap->binary_stream_pos, xmlStrlen(xml_char)/2); + rc = et_hex2data( &s1ap->binary_stream[s1ap->binary_stream_pos], xml_char, xmlStrlen(xml_char)); + s1ap->binary_stream_pos += xmlStrlen(xml_char)/2; + et_display_node(cur_node, 0); + AssertFatal (rc >= 0, "ERROR %s() in converting hex string %s len %d size %d rc %d\n", __FUNCTION__, xml_char, xmlStrlen(xml_char), size, rc); + go_deeper_in_tree = 0; + //} + xmlFree(xml_char); + } + } + } + } + if (0 < go_deeper_in_tree) { + et_parse_s1ap(doc, cur_node->children, s1ap); + } + } + } +} + +//------------------------------------------------------------------------------ +void et_parse_sctp_data_chunk(xmlDocPtr doc, const xmlNode const *sctp_node, sctp_datahdr_t * const sctp_hdr) +{ + xmlNode *cur_node = NULL; + xmlChar *xml_char = NULL; + xmlChar *xml_char2 = NULL; + + if ((NULL != sctp_node) && (NULL != sctp_hdr)) { + xml_char = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"name"); + if (NULL != xml_char) { + if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.data_payload_proto_id"))) { + xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show"); + if (NULL != xml_char2) { + sctp_hdr->ppid = strtoul((const char *)xml_char2, NULL, 0); + xmlFree(xml_char2); + } + } else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.data_sid"))) { + xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show"); + if (NULL != xml_char2) { + sctp_hdr->stream = strtoul((const char *)xml_char2, NULL, 16); + xmlFree(xml_char2); + } + } else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.data_tsn"))) { + xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show"); + if (NULL != xml_char2) { + sctp_hdr->tsn = strtoul((const char *)xml_char2, NULL, 0); + xmlFree(xml_char2); + } + } else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.data_ssn"))) { + xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show"); + if (NULL != xml_char2) { + sctp_hdr->ssn = strtoul((const char *)xml_char2, NULL, 0); + xmlFree(xml_char2); + } + } + xmlFree(xml_char); + } + for (cur_node = sctp_node->children; cur_node; cur_node = cur_node->next) { + et_parse_sctp_data_chunk(doc, cur_node, sctp_hdr); + } + } + +} +//------------------------------------------------------------------------------ +void et_parse_sctp_init_chunk(xmlDocPtr doc, const xmlNode const *sctp_node, sctp_inithdr_t * const sctp_hdr) +{ + xmlNode *cur_node = NULL; + xmlChar *xml_char = NULL; + xmlChar *xml_char2 = NULL; + + if ((NULL != sctp_node) && (NULL != sctp_hdr)) { + xml_char = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"name"); + if (NULL != xml_char) { + if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.init_nr_out_streams"))) { + xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value"); + if (NULL != xml_char2) { + sctp_hdr->num_outbound_streams = strtoul((const char *)xml_char2, NULL, 0); + xmlFree(xml_char2); + } + } else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.init_nr_in_streams"))) { + xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value"); + if (NULL != xml_char2) { + sctp_hdr->num_inbound_streams = strtoul((const char *)xml_char2, NULL, 0); + xmlFree(xml_char2); + } + } else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.init_credit"))) { + xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value"); + if (NULL != xml_char2) { + sctp_hdr->a_rwnd = strtoul((const char *)xml_char2, NULL, 0); + xmlFree(xml_char2); + } + } else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.init_initial_tsn"))) { + xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show"); + if (NULL != xml_char2) { + sctp_hdr->initial_tsn = strtoul((const char *)xml_char2, NULL, 0); + xmlFree(xml_char2); + } + } else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.init_initiate_tag"))) { + xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show"); + if (NULL != xml_char2) { + sctp_hdr->init_tag = strtoul((const char *)xml_char2, NULL, 16); + xmlFree(xml_char2); + } + } + xmlFree(xml_char); + } + for (cur_node = sctp_node->children; cur_node; cur_node = cur_node->next) { + et_parse_sctp_init_chunk(doc, cur_node, sctp_hdr); + } + } +} +//------------------------------------------------------------------------------ +void et_parse_sctp_init_ack_chunk(xmlDocPtr doc, const xmlNode const *sctp_node, sctp_initackhdr_t * const sctp_hdr) +{ + xmlNode *cur_node = NULL; + xmlChar *xml_char = NULL; + xmlChar *xml_char2 = NULL; + + if ((NULL != sctp_node) && (NULL != sctp_hdr)) { + xml_char = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"name"); + if (NULL != xml_char) { + if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.initack_nr_out_streams"))) { + xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value"); + if (NULL != xml_char2) { + sctp_hdr->num_outbound_streams = strtoul((const char *)xml_char2, NULL, 0); + xmlFree(xml_char2); + } + } else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.initack_nr_in_streams"))) { + xml_char2 = xmlGetProp((xmlNode *)(xmlNode *)sctp_node, (const xmlChar *)"value"); + if (NULL != xml_char2) { + sctp_hdr->num_inbound_streams = strtoul((const char *)xml_char2, NULL, 0); + xmlFree(xml_char2); + } + } else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.initack_credit"))) { + xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value"); + if (NULL != xml_char2) { + sctp_hdr->a_rwnd = strtoul((const char *)xml_char2, NULL, 0); + xmlFree(xml_char2); + } + } else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.initack_initial_tsn"))) { + xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show"); + if (NULL != xml_char2) { + sctp_hdr->initial_tsn = strtoul((const char *)xml_char2, NULL, 0); + xmlFree(xml_char2); + } + } else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.initack_initiate_tag"))) { + xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show"); + if (NULL != xml_char2) { + sctp_hdr->init_tag = strtoul((const char *)xml_char2, NULL, 16); + xmlFree(xml_char2); + } + } + xmlFree(xml_char); + } + for (cur_node = sctp_node->children; cur_node; cur_node = cur_node->next) { + et_parse_sctp_init_ack_chunk(doc, cur_node, sctp_hdr); + } + } +} +//------------------------------------------------------------------------------ +void et_parse_sctp(xmlDocPtr doc, const xmlNode const *sctp_node, et_sctp_hdr_t * const sctp_hdr) +{ + xmlNode *cur_node = NULL; + xmlChar *xml_char = NULL; + xmlChar *xml_char2 = NULL; + + if ((NULL != sctp_node) && (NULL != sctp_hdr)) { + if ((!xmlStrcmp(sctp_node->name, (const xmlChar *)"proto"))) { + xml_char = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"name"); + if (NULL != xml_char) { + if ((!xmlStrcmp(xml_char, (const xmlChar *)"s1ap"))) { + xmlFree(xml_char); + xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"size"); + if (NULL != xml_char2) { + sctp_hdr->u.data_hdr.payload.binary_stream_allocated_size = strtoul((const char *)xml_char2, NULL, 0); + sctp_hdr->u.data_hdr.payload.binary_stream = calloc(1, sctp_hdr->u.data_hdr.payload.binary_stream_allocated_size); + xmlFree(xml_char2); + } + et_parse_s1ap(doc, sctp_node, &sctp_hdr->u.data_hdr.payload); + et_decode_s1ap(&sctp_hdr->u.data_hdr.payload); + return; + } + xmlFree(xml_char); + } + } + //if ((cur_node->type == XML_ATTRIBUTE_NODE) || (cur_node->type == XML_ELEMENT_NODE)) { + xml_char = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"name"); + if (NULL != xml_char) { + if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.srcport"))) { + xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value"); + if (NULL != xml_char2) { + sctp_hdr->src_port = strtoul((const char *)xml_char2, NULL, 16); + xmlFree(xml_char2); + } + } else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.dstport"))) { + xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value"); + if (NULL != xml_char2) { + sctp_hdr->dst_port = strtoul((const char *)xml_char2, NULL, 16); + xmlFree(xml_char2); + } + } else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.chunk_type"))) { + xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value"); + if (NULL != xml_char2) { + sctp_hdr->chunk_type = strtoul((const char *)xml_char2, NULL, 0); + xmlFree(xml_char2); + switch (sctp_hdr->chunk_type) { + case SCTP_CID_DATA: + et_parse_sctp_data_chunk(doc, sctp_node->parent, &sctp_hdr->u.data_hdr); + break; + case SCTP_CID_INIT: + et_parse_sctp_init_chunk(doc, sctp_node->parent, &sctp_hdr->u.init_hdr); + break; + case SCTP_CID_INIT_ACK: + et_parse_sctp_init_ack_chunk(doc, sctp_node->parent, &sctp_hdr->u.init_ack_hdr); + break; + default: + ; + } + } + } + } + for (cur_node = sctp_node->children; cur_node; cur_node = cur_node->next) { + et_parse_sctp(doc, cur_node, sctp_hdr); + } + } +} +//------------------------------------------------------------------------------ +et_packet_t* et_parse_xml_packet(xmlDocPtr doc, xmlNodePtr node) { + + et_packet_t *packet = NULL; + xmlNode *cur_node = NULL; + xmlChar *xml_char = NULL; + float afloat = (float)0.0; + static struct timeval initial_time = { .tv_sec = 0, .tv_usec = 0 }; + static struct timeval relative_last_sent_packet = { .tv_sec = 0, .tv_usec = 0 }; + static struct timeval relative_last_received_packet = { .tv_sec = 0, .tv_usec = 0 }; + static char first_packet = 1; + static char first_sent_packet = 1; + static char first_received_packet = 1; + static unsigned int packet_number = 1; + + if (NULL != node) { + packet = calloc(1, sizeof(*packet)); + + xml_char = xmlGetProp(node, (const xmlChar *)"action"); + packet->action = et_action_str2et_action_t(xml_char); + xmlFree(xml_char); + packet->packet_number = packet_number++; + + for (cur_node = node->children; cur_node; cur_node = cur_node->next) { + //if (cur_node->type == XML_ELEMENT_NODE) { + if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"frame.time_relative"))) { + xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"value"); + afloat = atof((const char*)xml_char); + xmlFree(xml_char); + packet->time_relative_to_first_packet.tv_sec = (int)afloat; + packet->time_relative_to_first_packet.tv_usec = (int)((afloat - packet->time_relative_to_first_packet.tv_sec)*1000000); + + if (first_packet > 0) { + initial_time = packet->time_relative_to_first_packet; + packet->time_relative_to_first_packet.tv_sec = 0; + packet->time_relative_to_first_packet.tv_usec = 0; + first_packet = 0; + } else { + timersub(&packet->time_relative_to_first_packet, &initial_time, + &packet->time_relative_to_first_packet); + } + if (packet->action == ET_PACKET_ACTION_S1C_SEND) { + if (first_sent_packet > 0) { + relative_last_sent_packet = packet->time_relative_to_first_packet; + packet->time_relative_to_last_sent_packet.tv_sec = 0; + packet->time_relative_to_last_sent_packet.tv_usec = 0; + first_sent_packet = 0; + } else { + timersub(&packet->time_relative_to_first_packet, &relative_last_sent_packet, + &packet->time_relative_to_last_sent_packet); + relative_last_sent_packet = packet->time_relative_to_first_packet; + } + } else if (packet->action == ET_PACKET_ACTION_S1C_RECEIVE) { + if (first_received_packet > 0) { + relative_last_received_packet.tv_sec = packet->time_relative_to_first_packet.tv_sec; + relative_last_received_packet.tv_usec = packet->time_relative_to_first_packet.tv_usec; + packet->time_relative_to_last_received_packet.tv_sec = 0; + packet->time_relative_to_last_received_packet.tv_usec = 0; + first_received_packet = 0; + } else { + timersub(&packet->time_relative_to_first_packet, &relative_last_received_packet, + &packet->time_relative_to_last_received_packet); + relative_last_received_packet = packet->time_relative_to_first_packet; + } + } + + } else if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"frame.number"))) { + xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"value"); + packet->original_frame_number = strtoul((const char *)xml_char, NULL, 0); + xmlFree(xml_char); + } else if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"ip.src"))) { + xml_char = xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1); + et_ip_str2et_ip(xml_char, &packet->ip_hdr.src); + xmlFree(xml_char); + } else if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"ip.dst"))) { + xml_char = xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1); + et_ip_str2et_ip(xml_char, &packet->ip_hdr.dst); + xmlFree(xml_char); + } else if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"proto"))) { + xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"name"); + if (NULL != xml_char) { + if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp"))) { + et_parse_sctp(doc, cur_node, &packet->sctp_hdr); + } + xmlFree(xml_char); + } + } + //} + } + } + return packet; +} +//------------------------------------------------------------------------------ +et_scenario_t* et_generate_scenario( + const char * const tsml_out_scenario_filename ) +{ + xmlDocPtr doc = NULL; + xmlNodePtr root = NULL; + xmlNodePtr node = NULL; + xmlChar *xml_char = NULL; + et_scenario_t *scenario = NULL; + et_packet_t *packet = NULL; + et_packet_t **next_packet = NULL; + + doc = xmlParseFile(tsml_out_scenario_filename); + if (NULL == doc) { + AssertFatal (0, "Could not parse scenario xml file %s!\n", tsml_out_scenario_filename); + } else { + fprintf(stdout, "Test scenario file to play: %s\n", tsml_out_scenario_filename); + //xmlDebugDumpDocument(NULL, doc); + } + + // Get root + root = xmlDocGetRootElement(doc); + if (NULL != root) { + if ((!xmlStrcmp(root->name, (const xmlChar *)"scenario"))) { + xml_char = xmlGetProp(root, (const xmlChar *)"name"); + printf("scenario name: %s\n", xml_char); + scenario = calloc(1, sizeof(*scenario)); + scenario->name = xml_char; // nodup nofree + next_packet = &scenario->list_packet; + for (node = root->children; node != NULL; node = node->next) { + if ((!xmlStrcmp(node->name, (const xmlChar *)"packet"))) { + packet = et_parse_xml_packet(doc, node); + if (NULL != packet) { + *next_packet = packet; + next_packet = &packet->next; + } else { + fprintf(stdout, "WARNING omitted packet:\n"); + et_display_node(node, 0); + } + } + } + } + } else { + fprintf(stderr, "Empty xml document\n"); + } + xmlFreeDoc(doc); + xmlCleanupParser(); + return scenario; +} +//------------------------------------------------------------------------------ +int et_generate_xml_scenario( + const char const * xml_in_dir_name, + const char const * xml_in_scenario_filename, + const char const * enb_config_filename, + char const * tsml_out_scenario_filename) +//------------------------------------------------------------------------------ +{ + //int fd_pdml_in; + xsltStylesheetPtr cur = NULL; + xmlDocPtr doc, res; + FILE *play_scenario_file = NULL; + const char *params[2*ENB_CONFIG_MAX_XSLT_PARAMS]; + int nb_params = 0; + int i,j; + char astring[1024]; + struct in_addr addr; + int ret = 0; + + memset(astring, 0, sizeof(astring)); + if (getcwd(astring, sizeof(astring)) != NULL) { + fprintf(stdout, "working in %s directory\n", astring); + } else { + perror("getcwd() ERROR"); + exit(1); + } + + memset(astring, 0, sizeof(astring)); + strcat(astring, g_openair_dir); + strcat(astring, "/openair3/TEST/EPC_TEST/play_scenario.xsl"); + + xmlSubstituteEntitiesDefault(1); + xmlLoadExtDtdDefaultValue = 1; + cur = xsltParseStylesheetFile((const xmlChar *)astring); + if (NULL == cur) { + AssertFatal (0, "Could not parse stylesheet file %s (check OPENAIR_DIR env variable)!\n", astring); + } else { + fprintf(stdout, "XSLT style sheet: %s\n", astring); + } + + doc = xmlParseFile(xml_in_scenario_filename); + if (NULL == doc) { + AssertFatal (0, "Could not parse scenario xml file %s!\n", xml_in_scenario_filename); + } else { + fprintf(stdout, "Test scenario file: %s\n", xml_in_scenario_filename); + } + + for (i = 0; i < enb_properties.number; i++) { + // eNB S1-C IPv4 address + sprintf(astring, "enb_s1c%d", i); + params[nb_params++] = strdup(astring); + addr.s_addr = enb_properties.properties[i]->enb_ipv4_address_for_S1_MME; + sprintf(astring, "\"%s\"", inet_ntoa(addr)); + params[nb_params++] = strdup(astring); + + // MME S1-C IPv4 address + for (j = 0; j < enb_properties.properties[i]->nb_mme; j++) { + sprintf(astring, "mme_s1c%d_%d", i, j); + params[nb_params++] = strdup(astring); + AssertFatal (enb_properties.properties[i]->mme_ip_address[j].ipv4_address, + "Only support MME IPv4 address\n"); + sprintf(astring, "\"%s\"", enb_properties.properties[i]->mme_ip_address[j].ipv4_address); + params[nb_params++] = strdup(astring); + } + } + params[nb_params] = NULL; + res = xsltApplyStylesheet(cur, doc, params); + if (NULL != res) { + sprintf((char *)tsml_out_scenario_filename,"%s",xml_in_scenario_filename); + if (et_strip_extension((char *)tsml_out_scenario_filename) > 0) { + strcat((char *)tsml_out_scenario_filename, ".tsml"); + play_scenario_file = fopen( tsml_out_scenario_filename, "w+"); + if (NULL != play_scenario_file) { + xsltSaveResultToFile(play_scenario_file, res, cur); + fclose(play_scenario_file); + fprintf(stdout, "Wrote test scenario to %s\n", tsml_out_scenario_filename); + } else { + fprintf(stderr, "ERROR in fopen(%s)\n", tsml_out_scenario_filename); + ret = -1; + } + } else { + fprintf(stderr, "ERROR in strip_extension()\n"); + ret = -1; + } + } else { + fprintf(stderr, "ERROR in xsltApplyStylesheet()\n"); + ret = -1; + } + xsltFreeStylesheet(cur); + xmlFreeDoc(doc); + xmlFreeDoc(res); + + xsltCleanupGlobals(); + xmlCleanupParser(); + return ret; +} + diff --git a/openair3/TEST/EPC_TEST/play_scenario_s1ap.c b/openair3/TEST/EPC_TEST/play_scenario_s1ap.c new file mode 100644 index 00000000000..cb5571c28b6 --- /dev/null +++ b/openair3/TEST/EPC_TEST/play_scenario_s1ap.c @@ -0,0 +1,162 @@ +/******************************************************************************* + OpenAirInterface + Copyright(c) 1999 - 2014 Eurecom + + OpenAirInterface is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + + OpenAirInterface is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenAirInterface.The full GNU General Public License is + included in this distribution in the file called "COPYING". If not, + see <http://www.gnu.org/licenses/>. + + Contact Information + OpenAirInterface Admin: openair_admin@eurecom.fr + OpenAirInterface Tech : openair_tech@eurecom.fr + OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr + + Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE + + *******************************************************************************/ + +/* + play_scenario_s1ap.c + ------------------- + AUTHOR : Lionel GAUTHIER + COMPANY : EURECOM + EMAIL : Lionel.Gauthier@eurecom.fr + */ +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include "tree.h" +#include "queue.h" + + +#include "intertask_interface.h" +#include "messages_types.h" +#include "platform_types.h" +#include "s1ap_common.h" +#include "s1ap_eNB_defs.h" +#include "s1ap_eNB_default_values.h" +#include "s1ap_eNB_management_procedures.h" +#include "s1ap_eNB.h" +#include "play_scenario.h" +#include "msc.h" +#include "assertions.h" +#include "conversions.h" + + +//------------------------------------------------------------------------------ +extern void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp); +extern void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *s1ap_register_eNB); +//------------------------------------------------------------------------------ +void et_s1ap_eNB_handle_sctp_data_ind(sctp_data_ind_t *sctp_data_ind) +{ + int result = 0; + et_event_t event; + + DevAssert(sctp_data_ind != NULL); + + memset((void*)&event, 0, sizeof(event)); + + event.code = ET_EVENT_RX_S1AP; + event.u.s1ap_data_ind.sctp_datahdr.tsn = 0; + event.u.s1ap_data_ind.sctp_datahdr.stream = sctp_data_ind->stream; + event.u.s1ap_data_ind.sctp_datahdr.ssn = 0; + event.u.s1ap_data_ind.sctp_datahdr.ppid = 18; // find constant + + event.u.s1ap_data_ind.sctp_datahdr.payload.binary_stream_pos = 0; + event.u.s1ap_data_ind.sctp_datahdr.payload.binary_stream_allocated_size = sctp_data_ind->buffer_length; + event.u.s1ap_data_ind.sctp_datahdr.payload.binary_stream = NULL; + if ((sctp_data_ind->buffer_length > 0) && (NULL != sctp_data_ind->buffer)) { + event.u.s1ap_data_ind.sctp_datahdr.payload.binary_stream = calloc(1, sctp_data_ind->buffer_length); + memcpy(event.u.s1ap_data_ind.sctp_datahdr.payload.binary_stream, + sctp_data_ind->buffer, + sctp_data_ind->buffer_length); + + if (et_s1ap_decode_pdu( + &event.u.s1ap_data_ind.sctp_datahdr.payload.pdu, + &event.u.s1ap_data_ind.sctp_datahdr.payload.message, + event.u.s1ap_data_ind.sctp_datahdr.payload.binary_stream, + event.u.s1ap_data_ind.sctp_datahdr.payload.binary_stream_allocated_size) < 0) { + AssertFatal (0, "ERROR %s() Cannot decode RX S1AP message!\n", __FUNCTION__); + } + + } + + result = itti_free(TASK_UNKNOWN, sctp_data_ind->buffer); + AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); + + et_scenario_fsm_notify_event(event); + +} +//------------------------------------------------------------------------------ +void *et_s1ap_eNB_task(void *arg) +{ + MessageDef *received_msg = NULL; + int result; + + S1AP_DEBUG("Starting S1AP layer\n"); + + s1ap_eNB_prepare_internal_data(); + + itti_mark_task_ready(TASK_S1AP); + MSC_START_USE(); + + while (1) { + itti_receive_msg(TASK_S1AP, &received_msg); + + switch (ITTI_MSG_ID(received_msg)) { + case TERMINATE_MESSAGE: + itti_exit_task(); + break; + + case S1AP_REGISTER_ENB_REQ: { + /* Register a new eNB. + * in Virtual mode eNBs will be distinguished using the mod_id/ + * Each eNB has to send an S1AP_REGISTER_ENB message with its + * own parameters. + */ + s1ap_eNB_handle_register_eNB(ITTI_MESSAGE_GET_INSTANCE(received_msg), + &S1AP_REGISTER_ENB_REQ(received_msg)); + } + break; + + case SCTP_NEW_ASSOCIATION_RESP: { + s1ap_eNB_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg), + &received_msg->ittiMsg.sctp_new_association_resp); + } + break; + + case SCTP_DATA_IND: { + et_s1ap_eNB_handle_sctp_data_ind(&received_msg->ittiMsg.sctp_data_ind); + } + break; + + + default: + S1AP_ERROR("Received unhandled message: %d:%s\n", + ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg)); + break; + } + + result = itti_free (ITTI_MSG_ORIGIN_ID(received_msg), received_msg); + AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); + + received_msg = NULL; + } + + return NULL; +} + + diff --git a/openair3/TEST/EPC_TEST/play_scenario_sctp.c b/openair3/TEST/EPC_TEST/play_scenario_sctp.c new file mode 100644 index 00000000000..6856cb29336 --- /dev/null +++ b/openair3/TEST/EPC_TEST/play_scenario_sctp.c @@ -0,0 +1,45 @@ +/******************************************************************************* + OpenAirInterface + Copyright(c) 1999 - 2014 Eurecom + + OpenAirInterface is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + + OpenAirInterface is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenAirInterface.The full GNU General Public License is + included in this distribution in the file called "COPYING". If not, + see <http://www.gnu.org/licenses/>. + + Contact Information + OpenAirInterface Admin: openair_admin@eurecom.fr + OpenAirInterface Tech : openair_tech@eurecom.fr + OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr + + Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE + + *******************************************************************************/ + +/* + play_scenario_sctp.c + ------------------- + AUTHOR : Lionel GAUTHIER + COMPANY : EURECOM + EMAIL : Lionel.Gauthier@eurecom.fr + */ + + +#include <errno.h> + +#include "intertask_interface.h" +#include "platform_types.h" +#include "assertions.h" +#include "play_scenario.h" + diff --git a/openair3/UTILS/conversions.h b/openair3/UTILS/conversions.h index aaa2b9714f1..47912f0d92e 100644 --- a/openair3/UTILS/conversions.h +++ b/openair3/UTILS/conversions.h @@ -275,7 +275,6 @@ do { \ (bITsTRING)->size = 3; \ (bITsTRING)->bits_unused = 4; \ } while(0) -/* /* TS 36.413 v10.9.0 section 9.2.1.38: * E-UTRAN CGI/Cell Identity * The leftmost bits of the Cell -- GitLab