diff --git a/openair3/TEST/EPC_TEST/generic_scenario.xsl b/openair3/TEST/EPC_TEST/generic_scenario.xsl
index e55bfffd69..b1cadbcdfa 100644
--- a/openair3/TEST/EPC_TEST/generic_scenario.xsl
+++ b/openair3/TEST/EPC_TEST/generic_scenario.xsl
@@ -146,7 +146,7 @@
-
+
@@ -160,14 +160,14 @@
-
+
-
+
@@ -181,13 +181,13 @@
-
+
-
+
@@ -201,13 +201,13 @@
-
+
-
+
@@ -218,10 +218,10 @@
-
+
-
+
@@ -232,11 +232,11 @@
-
+
-
+
@@ -247,7 +247,7 @@
-
+
diff --git a/openair3/TEST/EPC_TEST/play_scenario.c b/openair3/TEST/EPC_TEST/play_scenario.c
index b8252854e4..e73a41a683 100644
--- a/openair3/TEST/EPC_TEST/play_scenario.c
+++ b/openair3/TEST/EPC_TEST/play_scenario.c
@@ -49,7 +49,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -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 c6e1087a04..4916950783 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
+# include
+#include
/** @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 1a89128005..6b1c36cc3d 100644
--- a/openair3/TEST/EPC_TEST/play_scenario.xsl
+++ b/openair3/TEST/EPC_TEST/play_scenario.xsl
@@ -34,7 +34,7 @@
-
+
@@ -67,7 +67,7 @@
-
+