From d03f78a4031bf62d4ea1b43b0a83e899027ec84c Mon Sep 17 00:00:00 2001 From: gauthier <lionel.gauthier@eurecom.fr> Date: Fri, 6 Nov 2015 10:03:26 +0100 Subject: [PATCH] Cleaned xml output, now a S1C test scenario is generated, ready to be parsed. --- cmake_targets/CMakeLists.txt | 66 ++- cmake_targets/tools/build_test_epc_tools | 4 + openair2/ENB_APP/enb_config.c | 2 +- openair2/ENB_APP/enb_config.h | 1 + openair3/TEST/EPC_TEST/generate_scenario.c | 103 ++--- openair3/TEST/EPC_TEST/generate_scenario.h | 0 openair3/TEST/EPC_TEST/generic_scenario.xsl | 421 ++++++++++---------- openair3/TEST/EPC_TEST/play_scenario.c | 405 +++++++++++++++++++ openair3/TEST/EPC_TEST/play_scenario.h | 49 +++ openair3/TEST/EPC_TEST/play_scenario.xsl | 113 ++++++ 10 files changed, 901 insertions(+), 263 deletions(-) mode change 100755 => 100644 openair3/TEST/EPC_TEST/generate_scenario.h create mode 100644 openair3/TEST/EPC_TEST/play_scenario.c create mode 100644 openair3/TEST/EPC_TEST/play_scenario.h create mode 100644 openair3/TEST/EPC_TEST/play_scenario.xsl diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 6b9dae6b044..42e381dd68c 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -162,24 +162,47 @@ add_definitions(-DCMAKER) set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -g -DMALLOC_CHECK_=3") set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS} -g -DMALLOC_CHECK_=3 -O2") -# Below has been put in comment because does not work with -# SVN authentication. -# -#find_package(Subversion) -#if(SUBVERSION_FOUND) -# Subversion_WC_INFO(${OPENAIR_DIR} openair) -# set (FIRMWARE_VERSION "${openair_WC_REVISION} - ${openair_WC_LAST_CHANGED_DATE}") -# Subversion_WC_LOG(${OPENAIR_DIR} Project) -#else() -# set (FIRMWARE_VERSION "No svn information") -#endif() -#add_definitions("-DFIRMWARE_VERSION=\"${FIRMWARE_VERSION}\"") + + +set(GIT_BRANCH "UNKNOWN") +set(GIT_COMMIT_HASH "UNKNOWN") +set(GIT_COMMIT_DATE "UNKNOWN") + + +find_package(Git) +if(GIT_FOUND) + message("git found: ${GIT_EXECUTABLE}") + # Get the current working branch + execute_process( + COMMAND git rev-parse --abbrev-ref HEAD + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE GIT_BRANCH + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + # Get the latest abbreviated commit hash of the working branch + execute_process( + COMMAND git log -1 --format=%h + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE GIT_COMMIT_HASH + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + # Get the latest commit date of the working branch + execute_process( + COMMAND git log -1 --format=%cd + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE GIT_COMMIT_DATE + OUTPUT_STRIP_TRAILING_WHITESPACE + ) +endif() + # Below is a hard-coded info set (FIRMWARE_VERSION "No svn information") add_definitions("-DFIRMWARE_VERSION=\"${FIRMWARE_VERSION}\"") -add_definitions("-DPACKAGE_VERSION=\"${FIRMWARE_VERSION}\"") -add_definitions("-DPACKAGE_BUGREPORT=\"OpenAirInterface web site\"") +add_definitions("-DPACKAGE_VERSION=\"Branch: ${GIT_BRANCH} Abrev. Hash: ${GIT_COMMIT_HASH} Date: ${GIT_COMMIT_DATE}\"") +add_definitions("-DPACKAGE_BUGREPORT=\"openair4g-devel@lists.eurecom.fr\"") @@ -1615,6 +1638,7 @@ endforeach(myExe) add_executable(test_epc_generate_scenario ${OPENAIR3_DIR}/TEST/EPC_TEST/generate_scenario.c + ${OPENAIR3_DIR}/TEST/EPC_TEST/generate_scenario.h ${OPENAIR2_DIR}/ENB_APP/enb_config.h ${OPENAIR2_DIR}/COMMON/commonDef.h ${OPENAIR2_DIR}/COMMON/messages_def.h @@ -1626,6 +1650,20 @@ target_link_libraries (test_epc_generate_scenario -Wl,--start-group RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS ${ITTI_LIB} ${MSC_LIB} L2 -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES} ) +add_executable(test_epc_play_scenario + ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario.c + ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario.h + ${OPENAIR2_DIR}/ENB_APP/enb_config.h + ${OPENAIR2_DIR}/COMMON/commonDef.h + ${OPENAIR2_DIR}/COMMON/messages_def.h + ${OPENAIR2_DIR}/COMMON/messages_types.h + ${OPENAIR3_DIR}/S1AP/s1ap_eNB_defs.h + ${OPENAIR_BIN_DIR}/messages_xml.h + ) +target_link_libraries (test_epc_play_scenario + -Wl,--start-group RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS ${ITTI_LIB} ${MSC_LIB} L2 -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES} + ) + #unitary tests for Core NEtwork pieces ################################# diff --git a/cmake_targets/tools/build_test_epc_tools b/cmake_targets/tools/build_test_epc_tools index aff2a26fc09..10dc4fd2564 100755 --- a/cmake_targets/tools/build_test_epc_tools +++ b/cmake_targets/tools/build_test_epc_tools @@ -121,6 +121,7 @@ function main() echo "Cleaning TEST_EPC" fi rm -f $OPENAIR_DIR/targets/bin/test_epc_generate_scenario + rm -f $OPENAIR_DIR/targets/bin/test_epc_play_scenario rm -Rf build 2>&1 mkdir -m 777 -p -v build fi @@ -140,6 +141,9 @@ function main() compilations \ epc_test test_epc_generate_scenario \ test_epc_generate_scenario $dbin/test_epc_generate_scenario + compilations \ + epc_test test_epc_play_scenario \ + test_epc_play_scenario $dbin/test_epc_play_scenario } diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 07e0ffa6406..ad4dde7faa4 100755 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -253,7 +253,7 @@ static const eutra_band_t eutra_bands[] = { Enb_properties_array_t enb_properties; -static void enb_config_display(void) +void enb_config_display(void) { int i,j; diff --git a/openair2/ENB_APP/enb_config.h b/openair2/ENB_APP/enb_config.h index 113681dafe6..de837303ea6 100755 --- a/openair2/ENB_APP/enb_config.h +++ b/openair2/ENB_APP/enb_config.h @@ -239,6 +239,7 @@ typedef struct Enb_properties_array_s { Enb_properties_t *properties[MAX_ENB]; } Enb_properties_array_t; +void enb_config_display(void); const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP); const Enb_properties_array_t *enb_config_get(void); diff --git a/openair3/TEST/EPC_TEST/generate_scenario.c b/openair3/TEST/EPC_TEST/generate_scenario.c index 4cb21f9604f..8f39b9873e7 100644 --- a/openair3/TEST/EPC_TEST/generate_scenario.c +++ b/openair3/TEST/EPC_TEST/generate_scenario.c @@ -100,11 +100,10 @@ Enb_properties_array_t g_enb_properties; char *g_openair_dir = NULL; char *g_test_dir = NULL; char *g_pdml_in_origin = NULL; -char *g_generic_scenario = NULL; extern int xmlLoadExtDtdDefaultValue; #define GENERATE_PDML_FILE 1 -#define GENERATE_GENERIC_SCENARIO 2 +#define GENERATE_SCENARIO 2 #define GS_IS_FILE 1 #define GS_IS_DIR 2 @@ -172,14 +171,14 @@ int split_path( char * pathP, char *** resP) } //------------------------------------------------------------------------------ -int generate_generic_scenario(const char const * test_nameP, const char const * pdml_in_basenameP) +int generate_test_scenario(const char const * test_nameP, const char const * pdml_in_basenameP) //------------------------------------------------------------------------------ { //int fd_pdml_in; xsltStylesheetPtr cur = NULL; xmlDocPtr doc, res; - FILE *generic_scenario_file = NULL; - const char generic_scenario_filename[NAME_MAX]; + FILE *test_scenario_file = NULL; + const char test_scenario_filename[NAME_MAX]; const char *params[2*ENB_CONFIG_MAX_XSLT_PARAMS]; int nb_params = 0; int i,j; @@ -187,7 +186,7 @@ int generate_generic_scenario(const char const * test_nameP, const char const * char *astring2 = NULL; struct in_addr addr; - memset(generic_scenario_filename, 0, sizeof(generic_scenario_filename)); + memset(test_scenario_filename, 0, sizeof(test_scenario_filename)); memset(astring, 0, sizeof(astring)); if (getcwd(astring, sizeof(astring)) != NULL) { fprintf(stdout, "working in %s directory\n", astring); @@ -249,16 +248,16 @@ int generate_generic_scenario(const char const * test_nameP, const char const * 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(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); + sprintf(test_scenario_filename,"%s",pdml_in_basenameP); + if (strip_extension(test_scenario_filename) > 0) { + strcat(test_scenario_filename, ".xml"); + test_scenario_file = fopen( test_scenario_filename, "w+"); + if (NULL != test_scenario_file) { + xsltSaveResultToFile(test_scenario_file, res, cur); + fclose(test_scenario_file); + fprintf(stdout, "Wrote test scenario to %s\n", test_scenario_filename); } else { - fprintf(stderr, "Error in fopen(%s)\n", generic_scenario_filename); + fprintf(stderr, "Error in fopen(%s)\n", test_scenario_filename); } } else { fprintf(stderr, "Error in strip_extension()\n"); @@ -537,17 +536,17 @@ static void usage ( char *argv[]) //------------------------------------------------------------------------------ { - fprintf (stdout, "Please report any bug to: openair4g-devel@lists.eurecom.fr\n\n"); + fprintf (stdout, "Please report any bug to: %s\n",PACKAGE_BUGREPORT); fprintf (stdout, "Usage: %s [options]\n\n", argv[0]); + fprintf (stdout, "\n"); fprintf (stdout, "Mandatory options:\n"); - fprintf (stdout, "\t-t | --test-dir <dir> Directory where a set of files related to a particular test are located\n"); + fprintf (stdout, "\t-c | --enb-conf-file <file> Provide the old eNB config file for generating a copy of the original test\n"); + fprintf (stdout, "\t-d | --test-dir <dir> Directory where a set of files related to a particular test are located\n"); + fprintf (stdout, "\t-p | --pdml <file> File name (with no path) in 'test-dir' directory of an original scenario that has to be reworked (IP addresses) with new testbed\n"); fprintf (stdout, "\n"); - fprintf (stdout, "Available options:\n"); + fprintf (stdout, "Other options:\n"); fprintf (stdout, "\t-h | --help Print this help and return\n"); - 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, "\n"); + fprintf (stdout, "\t-v | --version Print informations about the version of this executable\n"); fprintf (stdout, "\n"); fprintf (stdout, "Example of generate_scenario use case: \n"); fprintf (stdout, "\n"); @@ -558,16 +557,16 @@ static void usage ( fprintf (stdout, " |\n"); fprintf (stdout, " mme_test_s1_pcap2pdml --pcap_file <`captured pcap-ng file`>\n"); fprintf (stdout, " |\n"); - fprintf (stdout, " +--------V----------+ +------------------------+\n"); - fprintf (stdout, " |'pdml-in-orig' file| |'old-enb-conf-file' file|\n"); - fprintf (stdout, " +--------+----------+ +------------+-----------+\n"); + fprintf (stdout, " +--------V----------+ +--------------------+\n"); + fprintf (stdout, " |'pdml-in-orig' file| |'enb-conf-file' file|\n"); + fprintf (stdout, " +--------+----------+ +--------------------+\n"); fprintf (stdout, " | |\n"); fprintf (stdout, " +----------------------------+\n"); fprintf (stdout, " |\n"); - fprintf (stdout, " generate_scenario -t <dir> -p <'pdml-in-orig' file> -o <'old-enb-conf-file' file> \n"); + fprintf (stdout, " generate_scenario -d <dir> -p <'pdml-in-orig' file> -c <'enb-conf-file' file> \n"); fprintf (stdout, " |\n"); fprintf (stdout, " +------------V--------------+\n"); - fprintf (stdout, " +'xml-scenario-generic' file|\n"); + fprintf (stdout, " +'xml-test-scenario' file |\n"); fprintf (stdout, " +---------------------------+\n"); fprintf (stdout, "\n"); } @@ -581,37 +580,39 @@ config_parse_opt_line ( { int option; int rv = 0; - char *old_enb_config_file_name = NULL; + char *enb_config_file_name = NULL; char *pdml_in_file_name = NULL; char *test_dir_name = NULL; enum long_option_e { LONG_OPTION_START = 0x100, /* Start after regular single char options */ - LONG_OPTION_OLD_ENB_CONF_FILE, + LONG_OPTION_ENB_CONF_FILE, LONG_OPTION_PDML, LONG_OPTION_TEST_DIR, LONG_OPTION_HELP, + LONG_OPTION_VERSION, }; static struct option long_options[] = { - {"old-enb-conf-file", required_argument, 0, LONG_OPTION_OLD_ENB_CONF_FILE}, - {"pdml ", required_argument, 0, LONG_OPTION_PDML}, - {"test-dir", required_argument, 0, LONG_OPTION_TEST_DIR}, - {"help", required_argument, 0, LONG_OPTION_HELP}, + {"enb-conf-file", required_argument, 0, LONG_OPTION_ENB_CONF_FILE}, + {"pdml ", required_argument, 0, LONG_OPTION_PDML}, + {"test-dir", required_argument, 0, LONG_OPTION_TEST_DIR}, + {"help", no_argument, 0, LONG_OPTION_HELP}, + {"version", no_argument, 0, LONG_OPTION_VERSION}, {NULL, 0, NULL, 0} }; /* * Parsing command line */ - while ((option = getopt_long (argc, argv, "hp:n:o:s:t:", long_options, NULL)) != -1) { + while ((option = getopt_long (argc, argv, "vhp:n:c:s:d:", long_options, NULL)) != -1) { switch (option) { - case LONG_OPTION_OLD_ENB_CONF_FILE: - case 'o': + case LONG_OPTION_ENB_CONF_FILE: + case 'c': if (optarg) { - old_enb_config_file_name = optarg; - printf("Old eNB config file name is %s\n", old_enb_config_file_name); - rv |= GENERATE_GENERIC_SCENARIO; + enb_config_file_name = optarg; + printf("eNB config file name is %s\n", enb_config_file_name); + rv |= GENERATE_SCENARIO; } break; @@ -620,12 +621,12 @@ config_parse_opt_line ( if (optarg) { pdml_in_file_name = strdup(optarg); printf("PDML input file name is %s\n", pdml_in_file_name); - rv |= GENERATE_GENERIC_SCENARIO; + rv |= GENERATE_SCENARIO; } break; case LONG_OPTION_TEST_DIR: - case 't': + case 'd': if (optarg) { test_dir_name = strdup(optarg); if (is_file_exists(test_dir_name, "test dirname") != GS_IS_DIR) { @@ -636,6 +637,12 @@ config_parse_opt_line ( } break; + case LONG_OPTION_VERSION: + case 'v': + printf("Version %s\n", PACKAGE_VERSION); + exit (0); + break; + case LONG_OPTION_HELP: case 'h': default: @@ -652,14 +659,14 @@ config_parse_opt_line ( fprintf(stderr, "Error: chdir %s returned %s\n", g_test_dir, strerror(errno)); exit(1); } - if (rv & GENERATE_GENERIC_SCENARIO) { - if (NULL == old_enb_config_file_name) { + if (rv & GENERATE_SCENARIO) { + if (NULL == enb_config_file_name) { fprintf(stderr, "Error: please provide the original eNB config file name that should be in %s\n", g_test_dir); } - 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); + if (is_file_exists(enb_config_file_name, "ENB config file") != GS_IS_FILE) { + fprintf(stderr, "Error: eNB config file name %s is not found in dir %s\n", enb_config_file_name, g_test_dir); } - enb_config_init(old_enb_config_file_name); + enb_config_init(enb_config_file_name); enb_config_display(); if (NULL == pdml_in_file_name) { @@ -688,8 +695,8 @@ int main( int argc, char **argv ) memset((char*) &g_enb_properties, 0 , sizeof(g_enb_properties)); actions = config_parse_opt_line (argc, argv); //Command-line options - if (actions & GENERATE_GENERIC_SCENARIO) { - generate_generic_scenario(g_test_dir, g_pdml_in_origin); + if (actions & GENERATE_SCENARIO) { + generate_test_scenario(g_test_dir, g_pdml_in_origin); } return 0; diff --git a/openair3/TEST/EPC_TEST/generate_scenario.h b/openair3/TEST/EPC_TEST/generate_scenario.h old mode 100755 new mode 100644 diff --git a/openair3/TEST/EPC_TEST/generic_scenario.xsl b/openair3/TEST/EPC_TEST/generic_scenario.xsl index ab0e7f1123a..e55bfffd690 100644 --- a/openair3/TEST/EPC_TEST/generic_scenario.xsl +++ b/openair3/TEST/EPC_TEST/generic_scenario.xsl @@ -1,240 +1,261 @@ <xsl:stylesheet version="1.0" - xmlns:xsl="http://www.w3.org/1999/XSL/Transform" - xmlns="http://www.w3.org/TR/xhtml1/strict"> + xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> -<xsl:output - method="xml" - indent="yes" - encoding="iso-8859-1" -/> + <xsl:output + method="xml" + indent="yes" + encoding="iso-8859-1" + /> -<!-- 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'"/> + <!-- 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'"/> -<xsl:template name="reverse_ip"> - <xsl:param name="ip_address"/> - <xsl:choose> + <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=$enb_s1c6">enb_s1c6</xsl:when> + <xsl:when test="$ip_address=$enb_s1c7">enb_s1c7</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_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:when test="$ip_address=$mme_s1c2_0">mme_s1c2_0</xsl:when> + <xsl:when test="$ip_address=$mme_s1c2_1">mme_s1c2_1</xsl:when> + <xsl:when test="$ip_address=$mme_s1c2_2">mme_s1c2_2</xsl:when> + <xsl:when test="$ip_address=$mme_s1c2_3">mme_s1c2_3</xsl:when> + <xsl:when test="$ip_address=$mme_s1c3_0">mme_s1c3_0</xsl:when> + <xsl:when test="$ip_address=$mme_s1c3_1">mme_s1c3_1</xsl:when> + <xsl:when test="$ip_address=$mme_s1c3_2">mme_s1c3_2</xsl:when> + <xsl:when test="$ip_address=$mme_s1c3_3">mme_s1c3_3</xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes">ERROR: Cannot reverse resolv IP <xsl:value-of select="."/> ! + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:template> -<xsl:template name="chunktype2str"> - <xsl:param name="chunk_type"/> + <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: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> + <xsl:message terminate="yes">ERROR: UNKNOWN CHUNK TYPE <xsl:value-of select="."/> ! + </xsl:message> + </xsl:otherwise> </xsl:choose> -</xsl:template> - + </xsl:template> + <xsl:strip-space elements="pdml packet proto field"/> -<xsl:strip-space elements="pdml packet proto field"/> - -<xsl:template match="/"> + <xsl:template match="/"> <scenario name="{$test_name}"> - <xsl:apply-templates/> + <xsl:apply-templates/> </scenario> -</xsl:template> + </xsl:template> -<xsl:template match="proto[@name='frame']"> + <xsl:template match="proto[@name='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"> - <xsl:call-template name="reverse_ip"> - <xsl:with-param name="ip_address" select="$ip/field[@name='ip.src']/@show"/> - </xsl:call-template> + <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 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:variable name="action"> + <xsl:choose> + <xsl:when test="starts-with($ip_src,'enb_s1')">SEND</xsl:when> + <xsl:when test="starts-with($ip_src,'mme_s1c')">RECEIVE</xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes">ERROR: UNKNOWN ACTION <xsl:value-of select="."/> ! + </xsl:message> + </xsl:otherwise> + </xsl:choose> </xsl:variable> - <xsl:for-each select="$ip/proto[@name='sctp']"> - <xsl:variable name="sctp.data_sid" select="./field[@name='sctp.data_sid']/@show"/> - <xsl:variable name="sctp.srcport" select="./field[@name='sctp.srcport']/@show"/> - <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:variable name="sctp_data_sid" select="./field/field[@name='sctp.data_sid']/@show"/> + <!-- TODO resolv problem of 2 SCTP packets in 1 IP packet: src and dst ports are not in the 2nd SCTP packet --> + <xsl:variable name="sctp_srcport" select="./field[@name='sctp.srcport']/@show"/> + <xsl:variable name="sctp_dstport" select="./field[@name='sctp.dstport']/@show"/> + <xsl:variable name="sctp_data_ssn" select="./field/field[@name='sctp.data_ssn']/@show"/> + <xsl:variable name="sctp_data_payload_proto_id" select="./field/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']"> + <xsl:choose> + <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}"> - <frame.time_relative value="{$time_relative}"/> + <payload 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="{$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()"/> + <!-- 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> + </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}"> + <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}" 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}"/> + <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}" 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}"/> + <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}" 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}"/> + <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}" 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}"/> + <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> -</xsl:template> + </xsl:template> </xsl:stylesheet> diff --git a/openair3/TEST/EPC_TEST/play_scenario.c b/openair3/TEST/EPC_TEST/play_scenario.c new file mode 100644 index 00000000000..b8252854e40 --- /dev/null +++ b/openair3/TEST/EPC_TEST/play_scenario.c @@ -0,0 +1,405 @@ +/******************************************************************************* + 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.c + ------------------- + AUTHOR : Lionel GAUTHIER + COMPANY : EURECOM + EMAIL : Lionel.Gauthier@eurecom.fr + */ + +#include <string.h> +#include <limits.h> +#include <libconfig.h> +#include <inttypes.h> +#include <getopt.h> +#include <libgen.h> +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#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> +#include <libxml/catalog.h> +#include <libxslt/xslt.h> +#include <libxslt/xsltInternals.h> +#include <libxslt/transform.h> +#include <libxslt/xsltutils.h> + +#include "assertions.h" +#include "play_scenario.h" +#include "s1ap_eNB.h" +#include "intertask_interface.h" +#include "enb_config.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; + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// test if file exist in current directory +int is_file_exists( const char const * file_nameP, const char const *file_roleP) +{ + struct stat s; + int err = stat(file_nameP, &s); + if(-1 == err) { + if(ENOENT == errno) { + fprintf(stderr, "Please provide a valid %s, %s does not exist\n", file_roleP, file_nameP); + } else { + perror("stat"); + exit(1); + } + } else { + if(S_ISREG(s.st_mode)) { + return GS_IS_FILE; + } else if(S_ISDIR(s.st_mode)) { + return GS_IS_DIR; + } else { + fprintf(stderr, "Please provide a valid test %s, %s exists but is not found valid\n", file_roleP, file_nameP); + } + } + 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) +{ + char * saveptr1; + char * p = strtok_r (pathP, "/", &saveptr1); + int n_spaces = 0; + + /// split string and append tokens to 'res' + while (p) { + *resP = realloc (*resP, sizeof (char*) * ++n_spaces); + AssertFatal (*resP, "realloc failed"); + (*resP)[n_spaces-1] = p; + p = strtok_r (NULL, "/", &saveptr1); + } + return n_spaces; +} + +//------------------------------------------------------------------------------ +void play_scenario( + const char const * play_scenario_filename ) +{ + +} + +//------------------------------------------------------------------------------ +int generate_play_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 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]; + char *astring2 = NULL; + 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(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(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); + } + + 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) { + // 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"); + 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; + } + xsltFreeStylesheet(cur); + xmlFreeDoc(res); + xmlFreeDoc(doc); + + xsltCleanupGlobals(); + xmlCleanupParser(); + return ret; +} + +//------------------------------------------------------------------------------ +static void usage ( + int argc, + char *argv[]) +//------------------------------------------------------------------------------ +{ + fprintf (stdout, "Please report any bug to: %s\n",PACKAGE_BUGREPORT); + fprintf (stdout, "Usage: %s [options]\n\n", argv[0]); + fprintf (stdout, "\n"); + fprintf (stdout, "Client options:\n"); + fprintf (stdout, "\t-S | --server <server network @> File name (with no path) of a test scenario that has to be replayed (TODO in future?)\n"); + fprintf (stdout, "Server options:\n"); + fprintf (stdout, "\t-d | --test-dir <dir> Directory where a set of files related to a particular test are located\n"); + fprintf (stdout, "\t-c | --enb-conf-file <file> Provide an eNB config file, valid for the testbed\n"); + fprintf (stdout, "\t-s | --scenario <file> File name (with no path) of a test scenario that has to be replayed ()\n"); + fprintf (stdout, "\n"); + fprintf (stdout, "Other options:\n"); + fprintf (stdout, "\t-h | --help Print this help and return\n"); + fprintf (stdout, "\t-v | --version Print informations about the version of this executable\n"); + fprintf (stdout, "\n"); +} + +//------------------------------------------------------------------------------ +int +config_parse_opt_line ( + int argc, + char *argv[], + char **test_dir_name, + char **scenario_file_name, + char **enb_config_file_name) +//------------------------------------------------------------------------------ +{ + int option; + int rv = 0; + const Enb_properties_array_t *enb_properties_p = NULL; + + enum long_option_e { + LONG_OPTION_START = 0x100, /* Start after regular single char options */ + LONG_OPTION_ENB_CONF_FILE, + LONG_OPTION_SCENARIO_FILE, + LONG_OPTION_TEST_DIR, + LONG_OPTION_HELP, + LONG_OPTION_VERSION + }; + + static struct option long_options[] = { + {"enb-conf-file", required_argument, 0, LONG_OPTION_ENB_CONF_FILE}, + {"scenario ", required_argument, 0, LONG_OPTION_SCENARIO_FILE}, + {"test-dir", required_argument, 0, LONG_OPTION_TEST_DIR}, + {"help", no_argument, 0, LONG_OPTION_HELP}, + {"version", no_argument, 0, LONG_OPTION_VERSION}, + {NULL, 0, NULL, 0} + }; + + /* + * Parsing command line + */ + while ((option = getopt_long (argc, argv, "vhc:s:d:", long_options, NULL)) != -1) { + switch (option) { + case LONG_OPTION_ENB_CONF_FILE: + case 'c': + if (optarg) { + *enb_config_file_name = strdup(optarg); + printf("eNB config file name is %s\n", *enb_config_file_name); + rv |= PLAY_SCENARIO; + } + break; + + case LONG_OPTION_SCENARIO_FILE: + case 's': + if (optarg) { + *scenario_file_name = strdup(optarg); + printf("Scenario file name is %s\n", *scenario_file_name); + rv |= PLAY_SCENARIO; + } + break; + + 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); + exit(1); + } + printf("Test dir name is %s\n", *test_dir_name); + } + break; + + case LONG_OPTION_VERSION: + case 'v': + printf("Version %s\n", PACKAGE_VERSION); + exit (0); + break; + + case LONG_OPTION_HELP: + case 'h': + default: + usage (argc, argv); + exit (0); + } + } + if (NULL == *test_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)); + 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); + } + 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); + } + 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); + } + 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); + } + } + return rv; +} + +//------------------------------------------------------------------------------ +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]; + + memset(play_scenario_filename, 0, sizeof(play_scenario_filename)); + g_openair_dir = getenv("OPENAIR_DIR"); + if (NULL == g_openair_dir) { + fprintf(stderr, "Error: Could not get OPENAIR_DIR environment variable\n"); + exit(1); + } + + 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); + } + free_pointer(test_dir_name); + free_pointer(scenario_file_name); + free_pointer(enb_config_file_name); + } + + return 0; +} diff --git a/openair3/TEST/EPC_TEST/play_scenario.h b/openair3/TEST/EPC_TEST/play_scenario.h new file mode 100644 index 00000000000..c6e1087a04d --- /dev/null +++ b/openair3/TEST/EPC_TEST/play_scenario.h @@ -0,0 +1,49 @@ +/******************************************************************************* + 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 + +*******************************************************************************/ + +/* + generate_scenario.h + ------------------- + AUTHOR : Lionel GAUTHIER + COMPANY : EURECOM + EMAIL : Lionel.Gauthier@eurecom.fr +*/ + +#ifndef GENERATE_SCENARIO_H_ +#define GENERATE_SCENARIO_H_ + +/** @defgroup _enb_app ENB APP + * @ingroup _oai2 + * @{ + */ + + +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 new file mode 100644 index 00000000000..1a89128005c --- /dev/null +++ b/openair3/TEST/EPC_TEST/play_scenario.xsl @@ -0,0 +1,113 @@ +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns="http://www.w3.org/TR/xhtml1/strict"> + + <xsl:output + method="xml" + indent="yes" + encoding="iso-8859-1" + /> + + <!-- 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:template match="ip.src[parent::payload]/@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> + <xsl:when test=".='enb_s1c2'"><xsl:value-of select="$enb_s1c2"/></xsl:when> + <xsl:when test=".='enb_s1c3'"><xsl:value-of select="$enb_s1c3"/></xsl:when> + <xsl:when test=".='enb_s1c4'"><xsl:value-of select="$enb_s1c4"/></xsl:when> + <xsl:when test=".='enb_s1c5'"><xsl:value-of select="$enb_s1c5"/></xsl:when> + <xsl:when test=".='enb_s1c6'"><xsl:value-of select="$enb_s1c6"/></xsl:when> + <xsl:when test=".='enb_s1c7'"><xsl:value-of select="$enb_s1c7"/></xsl:when> + <xsl:when test=".='mme_s1c0_0'"><xsl:value-of select="$mme_s1c0_0"/></xsl:when> + <xsl:when test=".='mme_s1c0_1'"><xsl:value-of select="$mme_s1c0_1"/></xsl:when> + <xsl:when test=".='mme_s1c0_2'"><xsl:value-of select="$mme_s1c0_2"/></xsl:when> + <xsl:when test=".='mme_s1c0_3'"><xsl:value-of select="$mme_s1c0_3"/></xsl:when> + <xsl:when test=".='mme_s1c1_0'"><xsl:value-of select="$mme_s1c1_0"/></xsl:when> + <xsl:when test=".='mme_s1c1_1'"><xsl:value-of select="$mme_s1c1_1"/></xsl:when> + <xsl:when test=".='mme_s1c1_2'"><xsl:value-of select="$mme_s1c1_2"/></xsl:when> + <xsl:when test=".='mme_s1c1_3'"><xsl:value-of select="$mme_s1c1_3"/></xsl:when> + <xsl:when test=".='mme_s1c2_0'"><xsl:value-of select="$mme_s1c2_0"/></xsl:when> + <xsl:when test=".='mme_s1c2_1'"><xsl:value-of select="$mme_s1c2_1"/></xsl:when> + <xsl:when test=".='mme_s1c2_2'"><xsl:value-of select="$mme_s1c2_2"/></xsl:when> + <xsl:when test=".='mme_s1c2_3'"><xsl:value-of select="$mme_s1c2_3"/></xsl:when> + <xsl:when test=".='mme_s1c3_0'"><xsl:value-of select="$mme_s1c3_0"/></xsl:when> + <xsl:when test=".='mme_s1c3_1'"><xsl:value-of select="$mme_s1c3_1"/></xsl:when> + <xsl:when test=".='mme_s1c3_2'"><xsl:value-of select="$mme_s1c3_2"/></xsl:when> + <xsl:when test=".='mme_s1c3_3'"><xsl:value-of select="$mme_s1c3_3"/></xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes">ERROR: Cannot resolv IP <xsl:value-of select="."/> ! + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template match="ip.dst[parent::payload]/@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> + <xsl:when test=".='enb_s1c2'"><xsl:value-of select="$enb_s1c2"/></xsl:when> + <xsl:when test=".='enb_s1c3'"><xsl:value-of select="$enb_s1c3"/></xsl:when> + <xsl:when test=".='enb_s1c4'"><xsl:value-of select="$enb_s1c4"/></xsl:when> + <xsl:when test=".='enb_s1c5'"><xsl:value-of select="$enb_s1c5"/></xsl:when> + <xsl:when test=".='enb_s1c6'"><xsl:value-of select="$enb_s1c6"/></xsl:when> + <xsl:when test=".='enb_s1c7'"><xsl:value-of select="$enb_s1c7"/></xsl:when> + <xsl:when test=".='mme_s1c0_0'"><xsl:value-of select="$mme_s1c0_0"/></xsl:when> + <xsl:when test=".='mme_s1c0_1'"><xsl:value-of select="$mme_s1c0_1"/></xsl:when> + <xsl:when test=".='mme_s1c0_2'"><xsl:value-of select="$mme_s1c0_2"/></xsl:when> + <xsl:when test=".='mme_s1c0_3'"><xsl:value-of select="$mme_s1c0_3"/></xsl:when> + <xsl:when test=".='mme_s1c1_0'"><xsl:value-of select="$mme_s1c1_0"/></xsl:when> + <xsl:when test=".='mme_s1c1_1'"><xsl:value-of select="$mme_s1c1_1"/></xsl:when> + <xsl:when test=".='mme_s1c1_2'"><xsl:value-of select="$mme_s1c1_2"/></xsl:when> + <xsl:when test=".='mme_s1c1_3'"><xsl:value-of select="$mme_s1c1_3"/></xsl:when> + <xsl:when test=".='mme_s1c2_0'"><xsl:value-of select="$mme_s1c2_0"/></xsl:when> + <xsl:when test=".='mme_s1c2_1'"><xsl:value-of select="$mme_s1c2_1"/></xsl:when> + <xsl:when test=".='mme_s1c2_2'"><xsl:value-of select="$mme_s1c2_2"/></xsl:when> + <xsl:when test=".='mme_s1c2_3'"><xsl:value-of select="$mme_s1c2_3"/></xsl:when> + <xsl:when test=".='mme_s1c3_0'"><xsl:value-of select="$mme_s1c3_0"/></xsl:when> + <xsl:when test=".='mme_s1c3_1'"><xsl:value-of select="$mme_s1c3_1"/></xsl:when> + <xsl:when test=".='mme_s1c3_2'"><xsl:value-of select="$mme_s1c3_2"/></xsl:when> + <xsl:when test=".='mme_s1c3_3'"><xsl:value-of select="$mme_s1c3_3"/></xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes">ERROR: Cannot resolv IP <xsl:value-of select="."/> ! + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template match="node()|@*"> + <xsl:copy> + <xsl:apply-templates select="node()|@*"/> + </xsl:copy> + </xsl:template> + + <xsl:template match="/"> + <xsl:apply-templates/> + </xsl:template> + +</xsl:stylesheet> -- GitLab