Commit d27641a4 authored by gauthier's avatar gauthier

Begin to begin sending packets (many things to do hash assoc id, mme_ue_id, nas security, etc)

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