From e8c40e78efc35ad3c284c494a718b42cffb68b9f Mon Sep 17 00:00:00 2001 From: gauthier <lionel.gauthier@eurecom.fr> Date: Wed, 4 Nov 2015 10:57:03 +0100 Subject: [PATCH] generated an initial 'generic' scenario. --- openair3/TEST/EPC_TEST/generate_scenario.c | 69 ++++++- openair3/TEST/EPC_TEST/generic_scenario.xsl | 214 +++++++++++++++++++- 2 files changed, 264 insertions(+), 19 deletions(-) diff --git a/openair3/TEST/EPC_TEST/generate_scenario.c b/openair3/TEST/EPC_TEST/generate_scenario.c index eff91ea56fc..c5289142b5a 100644 --- a/openair3/TEST/EPC_TEST/generate_scenario.c +++ b/openair3/TEST/EPC_TEST/generate_scenario.c @@ -36,6 +36,7 @@ */ #include <string.h> +#include <limits.h> #include <libconfig.h> #include <inttypes.h> #include <getopt.h> @@ -95,7 +96,7 @@ #define ENB_CONFIG_PROPERTIES_INDEX_OLD 0 #define ENB_CONFIG_PROPERTIES_INDEX_NEW 1 -#define ENB_CONFIG_MAX_XSLT_PARAMS 64 +#define ENB_CONFIG_MAX_XSLT_PARAMS 32 Enb_properties_array_t g_enb_properties[2]; char *g_openair_dir = NULL; @@ -136,6 +137,25 @@ int is_file_exists( const char const * file_nameP, const char const *file_roleP) return 0; } + +//------------------------------------------------------------------------------ +int strip_extension(char *in_filename) +{ + static const uint8_t name_min_len = 1; + static const uint8_t max_ext_len = 5; // .pdml ! + fprintf(stdout, "strip_extension %s\n", in_filename); + + if (NULL != in_filename) { + /* Check chars starting at end of string to find last '.' */ + for (ssize_t i = strlen(in_filename); i > (name_min_len + max_ext_len); i--) { + if (in_filename[i] == '.') { + in_filename[i] = '\0'; + return i; + } + } + } + return -1; +} //------------------------------------------------------------------------------ // return number of splitted items int split_path( char * pathP, char *** resP) @@ -155,18 +175,21 @@ int split_path( char * pathP, char *** resP) } //------------------------------------------------------------------------------ -void generate_generic_scenario(const char const * test_nameP, const char const * pdml_in_basenameP) +int generate_generic_scenario(const char const * test_nameP, const char const * pdml_in_basenameP) //------------------------------------------------------------------------------ { //int fd_pdml_in; xsltStylesheetPtr cur = NULL; xmlDocPtr doc, res; - const char *params[ENB_CONFIG_MAX_XSLT_PARAMS]; + FILE *generic_scenario_file = NULL; + const char generic_scenario_filename[NAME_MAX]; + const char *params[2*ENB_CONFIG_MAX_XSLT_PARAMS]; int nb_params = 0; int i,j; char astring[1024]; struct in_addr addr; + memset(generic_scenario_filename, 0, sizeof(generic_scenario_filename)); memset(astring, 0, sizeof(astring)); if (getcwd(astring, sizeof(astring)) != NULL) { fprintf(stdout, "working in %s directory\n", astring); @@ -182,7 +205,18 @@ void generate_generic_scenario(const char const * test_nameP, const char const * xmlSubstituteEntitiesDefault(1); xmlLoadExtDtdDefaultValue = 1; cur = xsltParseStylesheetFile(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(pdml_in_basenameP); + if (NULL == doc) { + AssertFatal (0, "Could not parse pdml file %s!\n", pdml_in_basenameP); + } else { + fprintf(stdout, "pdml file: %s\n", pdml_in_basenameP); + } params[nb_params++] = "test_name"; sprintf(astring, "\"%s\"", test_nameP); params[nb_params++] = strdup(astring); @@ -207,8 +241,25 @@ void generate_generic_scenario(const char const * test_nameP, const char const * } params[nb_params] = NULL; res = xsltApplyStylesheet(cur, doc, params); - xsltSaveResultToFile(stdout, res, cur); - + if (NULL != res) { + // since pdml filename is not relative (no path), just filename in current directory we can safely remove + sprintf(generic_scenario_filename,"%s",pdml_in_basenameP); + if (strip_extension(generic_scenario_filename) > 0) { + strcat(generic_scenario_filename, "_generic_scenario.xml"); + generic_scenario_file = fopen( generic_scenario_filename, "w+"); + if (NULL != generic_scenario_file) { + xsltSaveResultToFile(generic_scenario_file, res, cur); + fclose(generic_scenario_file); + fprintf(stdout, "Wrote generic scenario to %s\n", generic_scenario_filename); + } else { + fprintf(stderr, "Error in fopen(%s)\n", generic_scenario_filename); + } + } else { + fprintf(stderr, "Error in strip_extension()\n"); + } + } else { + fprintf(stderr, "Error in xsltApplyStylesheet()\n"); + } xsltFreeStylesheet(cur); xmlFreeDoc(res); xmlFreeDoc(doc); @@ -494,7 +545,7 @@ static void usage ( fprintf (stdout, "\t-o | --old-enb-conf-file <file> Provide the old eNB config file for generating a copy of the original test\n"); fprintf (stdout, " This option is set as many times as there are some eNB config files in the original test\n"); fprintf (stdout, "\t-p | --pdml <file> File name (with no path) of an original scenario that has to be reworked (IP addresses) with new testbed\n"); - fprintf (stdout, "\t-s | --scenario-generic <file> File name (with no path) of a scenario that has to be customized (IP addresses) with new testbed\n"); + fprintf (stdout, "\t-s | --scenario-generic <file> File name (with no path) of a scenario that has to be customized (IP addresses) with new testbed\n"); fprintf (stdout, "\n"); fprintf (stdout, "\n"); fprintf (stdout, "Example of generate_scenario use cases: \n"); @@ -596,7 +647,7 @@ config_parse_opt_line ( /* * Parsing command line */ - while ((option = getopt_long (argc, argv, "hp:n:o:s:t", long_options, NULL)) != -1) { + while ((option = getopt_long (argc, argv, "hp:n:o:s:t:", long_options, NULL)) != -1) { switch (option) { case LONG_OPTION_OLD_ENB_CONF_FILE: case 'o': @@ -669,8 +720,8 @@ config_parse_opt_line ( if (is_file_exists(old_enb_config_file_name, "Old eNB config file") != GS_IS_FILE) { fprintf(stderr, "Error: original eNB config file name %s is not found in dir %s\n", old_enb_config_file_name, g_test_dir); } - enb_config_display(ENB_CONFIG_PROPERTIES_INDEX_OLD); enb_config_init(old_enb_config_file_name, ENB_CONFIG_PROPERTIES_INDEX_OLD); + enb_config_display(ENB_CONFIG_PROPERTIES_INDEX_OLD); if (NULL == pdml_in_file_name) { fprintf(stderr, "Error: please provide the PDML file name that should be in %s\n", g_test_dir); @@ -688,8 +739,8 @@ config_parse_opt_line ( if (is_file_exists(new_enb_config_file_name, "New eNB config file") != GS_IS_FILE) { fprintf(stderr, "Error: New eNB config file name %s is not found in dir %s\n", new_enb_config_file_name, g_test_dir); } - enb_config_display(ENB_CONFIG_PROPERTIES_INDEX_NEW); enb_config_init(new_enb_config_file_name, ENB_CONFIG_PROPERTIES_INDEX_NEW); + enb_config_display(ENB_CONFIG_PROPERTIES_INDEX_NEW); if (NULL == generic_scenario_file_name) { fprintf(stderr, "Error: please provide the Generic scenario file name that should be in %s\n", g_test_dir); diff --git a/openair3/TEST/EPC_TEST/generic_scenario.xsl b/openair3/TEST/EPC_TEST/generic_scenario.xsl index 99672a28f02..ab0e7f1123a 100644 --- a/openair3/TEST/EPC_TEST/generic_scenario.xsl +++ b/openair3/TEST/EPC_TEST/generic_scenario.xsl @@ -8,16 +8,103 @@ encoding="iso-8859-1" /> -<xsl:strip-space elements="proto field"/> +<!-- Ugly but no time to find a better way in XSLT 1.0 (map/list)--> + <xsl:param name="enb_s1c0" select="'0.0.0.0'"/> + <xsl:param name="enb_s1c1" select="'0.0.0.0'"/> + <xsl:param name="enb_s1c2" select="'0.0.0.0'"/> + <xsl:param name="enb_s1c3" select="'0.0.0.0'"/> + <xsl:param name="enb_s1c4" select="'0.0.0.0'"/> + <xsl:param name="enb_s1c5" select="'0.0.0.0'"/> + <xsl:param name="enb_s1c6" select="'0.0.0.0'"/> + <xsl:param name="enb_s1c7" select="'0.0.0.0'"/> + <xsl:param name="mme_s1c0_0" select="'0.0.0.0'"/> + <xsl:param name="mme_s1c0_1" select="'0.0.0.0'"/> + <xsl:param name="mme_s1c0_2" select="'0.0.0.0'"/> + <xsl:param name="mme_s1c0_3" select="'0.0.0.0'"/> + <xsl:param name="mme_s1c1_0" select="'0.0.0.0'"/> + <xsl:param name="mme_s1c1_1" select="'0.0.0.0'"/> + <xsl:param name="mme_s1c1_2" select="'0.0.0.0'"/> + <xsl:param name="mme_s1c1_3" select="'0.0.0.0'"/> + <xsl:param name="mme_s1c2_0" select="'0.0.0.0'"/> + <xsl:param name="mme_s1c2_1" select="'0.0.0.0'"/> + <xsl:param name="mme_s1c2_2" select="'0.0.0.0'"/> + <xsl:param name="mme_s1c2_3" select="'0.0.0.0'"/> + <xsl:param name="mme_s1c3_0" select="'0.0.0.0'"/> + <xsl:param name="mme_s1c3_1" select="'0.0.0.0'"/> + <xsl:param name="mme_s1c3_2" select="'0.0.0.0'"/> + <xsl:param name="mme_s1c3_3" select="'0.0.0.0'"/> + <xsl:param name="ip_address" select="'0.0.0.0'"/> -<scenario name="{$test_name}"> + + +<xsl:template name="reverse_ip"> + <xsl:param name="ip_address"/> + <xsl:choose> + <xsl:when test="$ip_address=$enb_s1c0">enb_s1c0</xsl:when> + <xsl:when test="$ip_address=$enb_s1c1">enb_s1c1</xsl:when> + <xsl:when test="$ip_address=$enb_s1c2">enb_s1c2</xsl:when> + <xsl:when test="$ip_address=$enb_s1c3">enb_s1c3</xsl:when> + <xsl:when test="$ip_address=$enb_s1c4">enb_s1c4</xsl:when> + <xsl:when test="$ip_address=$enb_s1c5">enb_s1c5</xsl:when> + <xsl:when test="$ip_address=$mme_s1c0_0">mme_s1c0_0</xsl:when> + <xsl:when test="$ip_address=$mme_s1c0_1">mme_s1c0_1</xsl:when> + <xsl:when test="$ip_address=$mme_s1c0_2">mme_s1c0_2</xsl:when> + <xsl:when test="$ip_address=$mme_s1c0_3">mme_s1c0_3</xsl:when> + <xsl:when test="$ip_address=$mme_s1c1_0">mme_s1c1_0</xsl:when> + <xsl:when test="$ip_address=$mme_s1c1_1">mme_s1c1_1</xsl:when> + <xsl:when test="$ip_address=$mme_s1c1_2">mme_s1c1_2"</xsl:when> + <xsl:when test="$ip_address=$mme_s1c1_3">mme_s1c1_3</xsl:when> + <xsl:otherwise>reverse_ip_yourself</xsl:otherwise> + </xsl:choose> +</xsl:template> + +<xsl:template name="chunktype2str"> + <xsl:param name="chunk_type"/> + <xsl:choose> + <xsl:when test="$chunk_type='00'">DATA</xsl:when> + <xsl:when test="$chunk_type='01'">INIT</xsl:when> + <xsl:when test="$chunk_type='02'">INIT_ACK</xsl:when> + <xsl:when test="$chunk_type='03'">SACK</xsl:when> + <xsl:when test="$chunk_type='04'">HEARTBEAT</xsl:when> + <xsl:when test="$chunk_type='05'">HEARTBEAT_ACK</xsl:when> + <xsl:when test="$chunk_type='06'">ABORT</xsl:when> + <xsl:when test="$chunk_type='07'">SHUTDOWN</xsl:when> + <xsl:when test="$chunk_type='08'">SHUTDOWN_ACK</xsl:when> + <xsl:when test="$chunk_type='09'">ERROR</xsl:when> + <xsl:when test="$chunk_type='0a'">COOKIE_ECHO</xsl:when> + <xsl:when test="$chunk_type='0b'">COOKIE_ACK</xsl:when> + <xsl:when test="$chunk_type='0c'">ECNE</xsl:when> + <xsl:when test="$chunk_type='0d'">CWR</xsl:when> + <xsl:when test="$chunk_type='0e'">SHUTDOWN_COMPLETE</xsl:when> + <xsl:otherwise>UNKNOWN_CHUNK_TYPE</xsl:otherwise> + </xsl:choose> +</xsl:template> + + + + +<xsl:strip-space elements="pdml packet proto field"/> + +<xsl:template match="/"> + <scenario name="{$test_name}"> + <xsl:apply-templates/> + </scenario> +</xsl:template> <xsl:template match="proto[@name='frame']"> - <DEBUG_FRAME> <xsl:variable name="time_relative" select="field[@name='frame.time_relative']/@show"/> <xsl:variable name="ip" select="proto[@name='ip']"/> - <xsl:variable name="ip.src" select="$ip/field[@name='ip.src']/@show"/> - <xsl:variable name="ip.dst" select="$ip/field[@name='ip.dst']/@show"/> + <xsl:variable name="ip.src"> + <xsl:call-template name="reverse_ip"> + <xsl:with-param name="ip_address" select="$ip/field[@name='ip.src']/@show"/> + </xsl:call-template> + </xsl:variable> + <xsl:variable name="ip.dst"> + <xsl:call-template name="reverse_ip"> + <xsl:with-param name="ip_address" select="$ip/field[@name='ip.dst']/@show"/> + </xsl:call-template> + </xsl:variable> + <xsl:for-each select="$ip/proto[@name='sctp']"> <xsl:variable name="sctp.data_sid" select="./field[@name='sctp.data_sid']/@show"/> @@ -25,22 +112,129 @@ <xsl:variable name="sctp.dstport" select="./field[@name='sctp.dstport']/@show"/> <xsl:variable name="sctp.data_ssn" select="./field[@name='sctp.data_ssn']/@show"/> <xsl:variable name="sctp.data_payload_proto_id" select="./field[@name='sctp.data_payload_proto_id']/@show"/> - + <xsl:variable name="sctp.chunk_type_str"> + <xsl:call-template name="chunktype2str"> + <xsl:with-param name="chunk_type" select="./field/field[@name='sctp.chunk_type']/@value"/> + </xsl:call-template> + </xsl:variable> + <xsl:variable name="sctp_pos_offset" select="./@pos"/> + + <xsl:choose> + <xsl:when test="$sctp.chunk_type_str='DATA'"> <xsl:for-each select="./proto[@name='s1ap']"> - <payload name="{ip_dst}"> + <xsl:variable name="s1ap_pos_offset" select="./@pos"/> + <payload name="{$sctp.chunk_type_str}"> <frame.time_relative value="{$time_relative}"/> - <ip.dst value="{$ip.dst}"/> + + <!-- 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="{$s1ap_pos_offset}"/> <ip.src value="{$ip.src}"/> + <ip.dst value="{$ip.dst}"/> <sctp.data_sid value="{$sctp.data_sid}"/> <sctp.srcport value="{$sctp.srcport}"/> <sctp.dstport value="{$sctp.dstport}"/> <sctp.data_ssn value="{$sctp.data_ssn}"/> <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> </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}"> + <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}"/> + <ip.src value="{$ip.src}"/> + <ip.dst value="{$ip.dst}"/> + <sctp.data_sid value="{$sctp.data_sid}"/> + <sctp.srcport value="{$sctp.srcport}"/> + <sctp.dstport value="{$sctp.dstport}"/> + <sctp.init_nr_in_streams value="{$sctp.init_nr_in_streams}"/> + <sctp.init_nr_out_streams value="{$sctp.init_nr_out_streams}"/> + <sctp.init_initial_tsn value="{$sctp.init_initial_tsn}"/> + <sctp.chunk_type_str value="{$sctp.chunk_type_str}"/> + <!--xsl:copy-of select="node()"/--> + </payload> + </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}"> + <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}"/> + <ip.src value="{$ip.src}"/> + <ip.dst value="{$ip.dst}"/> + <sctp.data_sid value="{$sctp.data_sid}"/> + <sctp.srcport value="{$sctp.srcport}"/> + <sctp.dstport value="{$sctp.dstport}"/> + <sctp.initack_nr_in_streams value="{$sctp.initack_nr_in_streams}"/> + <sctp.initack_nr_out_streams value="{$sctp.initack_nr_out_streams}"/> + <sctp.initack_initial_tsn value="{$sctp.initack_initial_tsn}"/> + <sctp.chunk_type_str value="{$sctp.chunk_type_str}"/> + <!--xsl:copy-of select="node()"/--> + </payload> + </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}"> + <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}"/> + <ip.src value="{$ip.src}"/> + <ip.dst value="{$ip.dst}"/> + <sctp.data_sid value="{$sctp.data_sid}"/> + <sctp.srcport value="{$sctp.srcport}"/> + <sctp.dstport value="{$sctp.dstport}"/> + <sctp.chunk_type_str value="{$sctp.chunk_type_str}"/> + <xsl:copy-of select="node()"/> + </payload> + </xsl:when> + <xsl:when test="$sctp.chunk_type_str='SHUTDOWN'"> + <payload name="{$sctp.chunk_type_str}"> + <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}"/> + <ip.src value="{$ip.src}"/> + <ip.dst value="{$ip.dst}"/> + <sctp.data_sid value="{$sctp.data_sid}"/> + <sctp.srcport value="{$sctp.srcport}"/> + <sctp.dstport value="{$sctp.dstport}"/> + <sctp.chunk_type_str value="{$sctp.chunk_type_str}"/> + <xsl:copy-of select="node()"/> + </payload> + </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}"> + <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}"/> + <ip.src value="{$ip.src}"/> + <ip.dst value="{$ip.dst}"/> + <sctp.data_sid value="{$sctp.data_sid}"/> + <sctp.srcport value="{$sctp.srcport}"/> + <sctp.dstport value="{$sctp.dstport}"/> + <sctp.chunk_type_str value="{$sctp.chunk_type_str}"/> + <xsl:copy-of select="node()"/> + </payload> + </xsl:when> + <!--xsl:when test="$sctp.chunk_type_str='COOKIE_ECHO'"> </xsl:when--> + <!--xsl:when test="$sctp.chunk_type_str='COOKIE_ACK'"> </xsl:when--> + <!--xsl:when test="$sctp.chunk_type_str='ECNE'"> </xsl:when--> + <!--xsl:when test="$sctp.chunk_type_str='CWR'"> </xsl:when--> + <!--xsl:when test="$sctp.chunk_type_str='SHUTDOWN_COMPLETE'"> </xsl:when--> + <xsl:otherwise></xsl:otherwise> + </xsl:choose> + + </xsl:for-each> - </DEBUG_FRAME> </xsl:template> -</scenario> </xsl:stylesheet> -- GitLab