diff --git a/openair3/TEST/EPC_TEST/generic_scenario.xsl b/openair3/TEST/EPC_TEST/generic_scenario.xsl index e55bfffd69038e567dba9ad1b90c541cdb955084..b1cadbcdfa21a8c42a88705a7d786c6eea2d335b 100644 --- a/openair3/TEST/EPC_TEST/generic_scenario.xsl +++ b/openair3/TEST/EPC_TEST/generic_scenario.xsl @@ -146,7 +146,7 @@ <xsl:when test="$sctp_chunk_type_str='DATA'"> <xsl:for-each select="./proto[@name='s1ap']"> <xsl:variable name="s1ap_pos_offset" select="./@pos"/> - <payload name="{$sctp_chunk_type_str}" action="{$action}"> + <packet name="{$sctp_chunk_type_str}" action="{$action}"> <frame.time_relative value="{$time_relative}"/> <!-- TODO: pos_offset(substract it from all pos_offsets in s1ap, may depend on which test scenario protocol target S1AP/NAS or NAS only...)--> @@ -160,14 +160,14 @@ <sctp.data_payload_proto_id value="{$sctp_data_payload_proto_id}"/> <sctp.chunk_type_str value="{$sctp_chunk_type_str}"/> <xsl:copy-of select="node()"/> - </payload> + </packet> </xsl:for-each> </xsl:when> <xsl:when test="$sctp_chunk_type_str='INIT'"> <xsl:variable name="sctp_init_nr_out_streams" select="./field/field[@name='sctp.init_nr_out_streams']/@show"/> <xsl:variable name="sctp_init_nr_in_streams" select="./field/field[@name='sctp.init_nr_in_streams']/@show"/> <xsl:variable name="sctp_init_initial_tsn" select="./field/field[@name='sctp.init_initial_tsn']/@show"/> - <payload name="{$sctp_chunk_type_str}" action="{$action}"> + <packet name="{$sctp_chunk_type_str}" action="{$action}"> <frame.time_relative value="{$time_relative}"/> <!-- TODO: pos_offset(substract it from all pos_offsets in s1ap, may depend on which test scenario protocol target S1AP/NAS or NAS only...)--> <pos_offset value="{$sctp_pos_offset}"/> @@ -181,13 +181,13 @@ <sctp.init_initial_tsn value="{$sctp_init_initial_tsn}"/> <sctp.chunk_type_str value="{$sctp_chunk_type_str}"/> <!--xsl:copy-of select="node()"/--> - </payload> + </packet> </xsl:when> <xsl:when test="$sctp_chunk_type_str='INIT_ACK'"> <xsl:variable name="sctp_initack_nr_out_streams" select="./field/field[@name='sctp.initack_nr_out_streams']/@show"/> <xsl:variable name="sctp_initack_nr_in_streams" select="./field/field[@name='sctp.initack_nr_in_streams']/@show"/> <xsl:variable name="sctp_initack_initial_tsn" select="./field/field[@name='sctp.initack_initial_tsn']/@show"/> - <payload name="{$sctp_chunk_type_str}" action="{$action}"> + <packet name="{$sctp_chunk_type_str}" action="{$action}"> <frame.time_relative value="{$time_relative}"/> <!-- TODO: pos_offset(substract it from all pos_offsets in s1ap, may depend on which test scenario protocol target S1AP/NAS or NAS only...)--> <pos_offset value="{$sctp_pos_offset}"/> @@ -201,13 +201,13 @@ <sctp.initack_initial_tsn value="{$sctp_initack_initial_tsn}"/> <sctp.chunk_type_str value="{$sctp_chunk_type_str}"/> <!--xsl:copy-of select="node()"/--> - </payload> + </packet> </xsl:when> <!--xsl:when test="$sctp_chunk_type_str='SACK'"> </xsl:when--> <!--xsl:when test="$sctp_chunk_type_str='HEARTBEAT'"></xsl:when--> <!--xsl:when test="$sctp_chunk_type_str='HEARTBEAT_ACK'"></xsl:when--> <xsl:when test="$sctp_chunk_type_str='ABORT'"> - <payload name="{$sctp_chunk_type_str}" action="{$action}"> + <packet name="{$sctp_chunk_type_str}" action="{$action}"> <frame.time_relative value="{$time_relative}"/> <!-- TODO: pos_offset(substract it from all pos_offsets in s1ap, may depend on which test scenario protocol target S1AP/NAS or NAS only...)--> <pos_offset value="{$sctp_pos_offset}"/> @@ -218,10 +218,10 @@ <sctp.dstport value="{$sctp_dstport}"/> <sctp.chunk_type_str value="{$sctp_chunk_type_str}"/> <xsl:copy-of select="node()"/> - </payload> + </packet> </xsl:when> <xsl:when test="$sctp_chunk_type_str='SHUTDOWN'"> - <payload name="{$sctp_chunk_type_str}" action="{$action}"> + <packet name="{$sctp_chunk_type_str}" action="{$action}"> <frame.time_relative value="{$time_relative}"/> <!-- TODO: pos_offset(substract it from all pos_offsets in s1ap, may depend on which test scenario protocol target S1AP/NAS or NAS only...)--> <pos_offset value="{$sctp_pos_offset}"/> @@ -232,11 +232,11 @@ <sctp.dstport value="{$sctp_dstport}"/> <sctp.chunk_type_str value="{$sctp_chunk_type_str}"/> <xsl:copy-of select="node()"/> - </payload> + </packet> </xsl:when> <!--xsl:when test="$sctp_chunk_type_str='SHUTDOWN_ACK'"></xsl:when--> <xsl:when test="$sctp_chunk_type_str='ERROR'"> - <payload name="{$sctp_chunk_type_str}" action="{$action}"> + <packet name="{$sctp_chunk_type_str}" action="{$action}"> <frame.time_relative value="{$time_relative}"/> <!-- TODO: pos_offset(substract it from all pos_offsets in s1ap, may depend on which test scenario protocol target S1AP/NAS or NAS only...)--> <pos_offset value="{$sctp_pos_offset}"/> @@ -247,7 +247,7 @@ <sctp.dstport value="{$sctp_dstport}"/> <sctp.chunk_type_str value="{$sctp_chunk_type_str}"/> <xsl:copy-of select="node()"/> - </payload> + </packet> </xsl:when> <!--xsl:when test="$sctp_chunk_type_str='COOKIE_ECHO'"> </xsl:when--> <!--xsl:when test="$sctp_chunk_type_str='COOKIE_ACK'"> </xsl:when--> diff --git a/openair3/TEST/EPC_TEST/play_scenario.c b/openair3/TEST/EPC_TEST/play_scenario.c index b8252854e408f56126c979b40014208a3d9d950d..e73a41a68372a207f0da37bfd8b5782ec3c40e48 100644 --- a/openair3/TEST/EPC_TEST/play_scenario.c +++ b/openair3/TEST/EPC_TEST/play_scenario.c @@ -49,7 +49,6 @@ #include <unistd.h> #include <libxml/xmlmemory.h> #include <libxml/debugXML.h> -#include <libxml/HTMLtree.h> #include <libxml/xmlIO.h> #include <libxml/DOCBparser.h> #include <libxml/xinclude.h> @@ -138,16 +137,132 @@ int split_path( char * pathP, char *** resP) } return n_spaces; } - //------------------------------------------------------------------------------ -void play_scenario( +void display_node(xmlNodePtr node) { + if (node->type == XML_ELEMENT_NODE) { + xmlChar *path = xmlGetNodePath(node); + 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 free_scenario(test_scenario_t* scenario) +{ + //TODO +} +//------------------------------------------------------------------------------ +sctp_cid_t chunk_type_str2cid(xmlChar *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;} + if ((!xmlStrcmp(chunk_type_str, (const xmlChar *)"INIT_ACK"))) { return SCTP_CID_INIT_ACK;} + if ((!xmlStrcmp(chunk_type_str, (const xmlChar *)"SACK"))) { return SCTP_CID_SACK;} + if ((!xmlStrcmp(chunk_type_str, (const xmlChar *)"HEARTBEAT"))) { return SCTP_CID_HEARTBEAT;} + if ((!xmlStrcmp(chunk_type_str, (const xmlChar *)"HEARTBEAT_ACK"))) { return SCTP_CID_HEARTBEAT_ACK;} + if ((!xmlStrcmp(chunk_type_str, (const xmlChar *)"ABORT"))) { return SCTP_CID_ABORT;} + if ((!xmlStrcmp(chunk_type_str, (const xmlChar *)"SHUTDOWN"))) { return SCTP_CID_SHUTDOWN;} + if ((!xmlStrcmp(chunk_type_str, (const xmlChar *)"SHUTDOWN_ACK"))) { return SCTP_CID_SHUTDOWN_ACK;} + if ((!xmlStrcmp(chunk_type_str, (const xmlChar *)"ERROR"))) { return SCTP_CID_ERROR;} + if ((!xmlStrcmp(chunk_type_str, (const xmlChar *)"COOKIE_ECHO"))) { return SCTP_CID_COOKIE_ECHO;} + if ((!xmlStrcmp(chunk_type_str, (const xmlChar *)"COOKIE_ACK"))) { return SCTP_CID_COOKIE_ACK;} + if ((!xmlStrcmp(chunk_type_str, (const xmlChar *)"ECN_ECNE"))) { return SCTP_CID_ECN_ECNE;} + if ((!xmlStrcmp(chunk_type_str, (const xmlChar *)"ECN_CWR"))) { return SCTP_CID_ECN_CWR;} + if ((!xmlStrcmp(chunk_type_str, (const xmlChar *)"SHUTDOWN_COMPLETE"))) { return SCTP_CID_SHUTDOWN_COMPLETE;} + if ((!xmlStrcmp(chunk_type_str, (const xmlChar *)"AUTH"))) { return SCTP_CID_AUTH;} + if ((!xmlStrcmp(chunk_type_str, (const xmlChar *)"FWD_TSN"))) { return SCTP_CID_FWD_TSN;} + if ((!xmlStrcmp(chunk_type_str, (const xmlChar *)"ASCONF"))) { return SCTP_CID_ASCONF;} + if ((!xmlStrcmp(chunk_type_str, (const xmlChar *)"ASCONF_ACK"))) { return SCTP_CID_ASCONF_ACK;} + fprintf(stderr, "ERROR: Could not convert: %s\n", chunk_type_str); + exit(-1); +} +//------------------------------------------------------------------------------ +test_packet_t* parse_xml_packet(xmlNodePtr node) { + + test_packet_t *packet = NULL; + xmlNode *cur_node = NULL; + xmlChar *xml_char = NULL; + + if (NULL != node) { + packet = calloc(1, sizeof(*packet)); + + for (cur_node = node->children; cur_node; cur_node = cur_node->next) { + if (cur_node->type == XML_ELEMENT_NODE) { + printf("node type: Element, name: %s\n", cur_node->name); + if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"frame.time_relative"))) { + } else if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"ip.src"))) { + } else if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"ip.dst"))) { + } else if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"sctp.chunk_type_str"))) { + xml_char = xmlGetProp(cur_node, (const xmlChar *)"value"); + packet->sctp_hdr.chunk_type = chunk_type_str2cid(xml_char); + fprintf(stdout, "chunk_type_str2cid: %s\n", xml_char); + } + } + } + } + return packet; +} +//------------------------------------------------------------------------------ +int play_scenario(test_scenario_t* scenario) { + //TODO + 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); + } + // 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(node); + if (NULL != packet) { + *next_packet = packet; + next_packet = &packet->next; + } else { + fprintf(stdout, "WARNING omitted packet:\n"); + display_node(node); + } + } + } + } + } else { + fprintf(stderr, "Empty xml document\n"); + } + xmlFreeDoc(doc); + xmlCleanupParser(); + return scenario; } //------------------------------------------------------------------------------ -int generate_play_scenario( +int generate_xml_scenario( const char const * test_dir_name, const char const * test_scenario_filename, const char const * enb_config_filename, @@ -180,7 +295,7 @@ int generate_play_scenario( xmlSubstituteEntitiesDefault(1); xmlLoadExtDtdDefaultValue = 1; - cur = xsltParseStylesheetFile(astring); + cur = xsltParseStylesheetFile((const xmlChar *)astring); if (NULL == cur) { AssertFatal (0, "Could not parse stylesheet file %s (check OPENAIR_DIR env variable)!\n", astring); } else { @@ -215,7 +330,6 @@ int generate_play_scenario( params[nb_params] = NULL; res = xsltApplyStylesheet(cur, doc, params); if (NULL != res) { - // since pdml filename is not relative (no path), just filename in current directory we can safely remove sprintf(play_scenario_filename,"%s",test_scenario_filename); if (strip_extension(play_scenario_filename) > 0) { strcat(play_scenario_filename, ".tsml"); @@ -237,8 +351,8 @@ int generate_play_scenario( ret = -1; } xsltFreeStylesheet(cur); - xmlFreeDoc(res); xmlFreeDoc(doc); + xmlFreeDoc(res); xsltCleanupGlobals(); xmlCleanupParser(); @@ -378,11 +492,13 @@ config_parse_opt_line ( int main( int argc, char **argv ) //------------------------------------------------------------------------------ { - int actions = 0; - char *test_dir_name = NULL; - char *scenario_file_name = NULL; - char *enb_config_file_name = NULL; - char play_scenario_filename[NAME_MAX]; + int actions = 0; + char *test_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; memset(play_scenario_filename, 0, sizeof(play_scenario_filename)); g_openair_dir = getenv("OPENAIR_DIR"); @@ -393,13 +509,21 @@ int main( int argc, char **argv ) actions = config_parse_opt_line (argc, argv, &test_dir_name, &scenario_file_name, &enb_config_file_name); //Command-line options if (actions & PLAY_SCENARIO) { - if (generate_play_scenario(test_dir_name, scenario_file_name,enb_config_file_name, play_scenario_filename) == 0) { - play_scenario(play_scenario_filename); + 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); + } else { + fprintf(stderr, "Error: Could not generate scenario from tsml file\n"); + ret = -1; + } + } else { + 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); } - return 0; + return ret; } diff --git a/openair3/TEST/EPC_TEST/play_scenario.h b/openair3/TEST/EPC_TEST/play_scenario.h index c6e1087a04d60da25e8dcb66eda22804cb82fe83..4916950783d3f3effb853ab0a2bc956cd2dcdece 100644 --- a/openair3/TEST/EPC_TEST/play_scenario.h +++ b/openair3/TEST/EPC_TEST/play_scenario.h @@ -37,12 +37,100 @@ #ifndef GENERATE_SCENARIO_H_ #define GENERATE_SCENARIO_H_ +# include <time.h> +# include <stdint.h> +#include <libxml/tree.h> /** @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; + +// from kernel source file 3.19/include/linux/sctp.h +typedef enum { + SCTP_CID_DATA = 0, + SCTP_CID_INIT = 1, + SCTP_CID_INIT_ACK = 2, + SCTP_CID_SACK = 3, + SCTP_CID_HEARTBEAT = 4, + SCTP_CID_HEARTBEAT_ACK = 5, + SCTP_CID_ABORT = 6, + SCTP_CID_SHUTDOWN = 7, + SCTP_CID_SHUTDOWN_ACK = 8, + SCTP_CID_ERROR = 9, + SCTP_CID_COOKIE_ECHO = 10, + SCTP_CID_COOKIE_ACK = 11, + SCTP_CID_ECN_ECNE = 12, + SCTP_CID_ECN_CWR = 13, + SCTP_CID_SHUTDOWN_COMPLETE = 14, + + /* AUTH Extension Section 4.1 */ + SCTP_CID_AUTH = 0x0F, + + /* PR-SCTP Sec 3.2 */ + SCTP_CID_FWD_TSN = 0xC0, + + /* Use hex, as defined in ADDIP sec. 3.1 */ + SCTP_CID_ASCONF = 0xC1, + SCTP_CID_ASCONF_ACK = 0x80, +} sctp_cid_t; /* enum */ + +// from kernel source file 3.19/include/linux/sctp.h, Big Endians +typedef struct sctp_datahdr_s { + uint32_t tsn; + uint16_t stream; + uint16_t ssn; + uint32_t ppid; + uint8_t payload[0]; +} sctp_datahdr_t; + +// from kernel source file 3.19/include/linux/sctp.h, Big Endians +typedef struct sctp_inithdr { + uint32_t init_tag; + uint32_t a_rwnd; + uint16_t num_outbound_streams; + uint16_t num_inbound_streams; + uint32_t initial_tsn; + uint8_t params[0]; +} sctp_inithdr_t; + +typedef sctp_inithdr_t sctp_initackhdr_t; + +typedef struct test_sctp_hdr_s { + unsigned int src_port; + unsigned int dst_port; + sctp_cid_t chunk_type; + union { + sctp_datahdr_t data_hdr; + sctp_inithdr_t init_hdr; + sctp_initackhdr_t init_ack_hdr; + } u; +} test_sctp_hdr_t; + +typedef struct test_packet_s { + test_action_t action; + struct timeval time_relative_to_first_packet; + struct timeval time_relative_to_last_packet; + test_sctp_hdr_t sctp_hdr; + uint16_t s1ap_byte_stream_count; + uint8_t *s1ap_byte_stream; + xmlNodePtr *s1ap_node; + + struct test_packet_s *next; +}test_packet_t; + +typedef struct test_scenario_s { + xmlChar *name; + test_packet_t *list_packet; +}test_scenario_t; inline void free_pointer(void *p) {if (NULL != p) {free(p); p=NULL;}}; #endif /* ENB_CONFIG_H_ */ diff --git a/openair3/TEST/EPC_TEST/play_scenario.xsl b/openair3/TEST/EPC_TEST/play_scenario.xsl index 1a89128005cee64062714823ab88c3486f9f523f..6b1c36cc3d98bcd8001cc8a7d16ccc9e72ba6dd0 100644 --- a/openair3/TEST/EPC_TEST/play_scenario.xsl +++ b/openair3/TEST/EPC_TEST/play_scenario.xsl @@ -34,7 +34,7 @@ <xsl:param name="mme_s1c3_2" select="'0.0.0.0'"/> <xsl:param name="mme_s1c3_3" select="'0.0.0.0'"/> - <xsl:template match="ip.src[parent::payload]/@value"> + <xsl:template match="ip.src[parent::packet]/@value"> <xsl:choose> <xsl:when test=".='enb_s1c0'"><xsl:value-of select="$enb_s1c0"/></xsl:when> <xsl:when test=".='enb_s1c1'"><xsl:value-of select="$enb_s1c1"/></xsl:when> @@ -67,7 +67,7 @@ </xsl:choose> </xsl:template> - <xsl:template match="ip.dst[parent::payload]/@value"> + <xsl:template match="ip.dst[parent::packet]/@value"> <xsl:choose> <xsl:when test=".='enb_s1c0'"><xsl:value-of select="$enb_s1c0"/></xsl:when> <xsl:when test=".='enb_s1c1'"><xsl:value-of select="$enb_s1c1"/></xsl:when>