/******************************************************************************* 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.h ------------------- AUTHOR : Lionel GAUTHIER COMPANY : EURECOM EMAIL : Lionel.Gauthier@eurecom.fr */ #ifndef PLAY_SCENARIO_H_ #define PLAY_SCENARIO_H_ # include <time.h> # include <stdint.h> # include <libxml/tree.h> # include <libxml/xpath.h> # include <netinet/in.h> #include "S1AP-PDU.h" #include "s1ap_ies_defs.h" #include "play_scenario_s1ap_eNB_defs.h" #include "hashtable.h" #include "asn_compare.h" #define ET_XPATH_EXPRESSION_MAX_LENGTH 400 // powers of 2 #define ET_BIT_MASK_MATCH_SCTP_STREAM 1 #define ET_BIT_MASK_MATCH_SCTP_SSN 2 //#define ET_BIT_MASK_MATCH_S1AP_ 2 #define MAX_ENB 16 #define ENB_CONFIG_STRING_ACTIVE_ENBS "Active_eNBs" #define ENB_CONFIG_STRING_ENB_LIST "eNBs" #define ENB_CONFIG_STRING_ENB_ID "eNB_ID" #define ENB_CONFIG_STRING_CELL_TYPE "cell_type" #define ENB_CONFIG_STRING_ENB_NAME "eNB_name" #define ENB_CONFIG_STRING_TRACKING_AREA_CODE "tracking_area_code" #define ENB_CONFIG_STRING_MOBILE_COUNTRY_CODE "mobile_country_code" #define ENB_CONFIG_STRING_MOBILE_NETWORK_CODE "mobile_network_code" #define ENB_CONFIG_STRING_MME_IP_ADDRESS "mme_ip_address" #define ENB_CONFIG_STRING_MME_IPV4_ADDRESS "ipv4" #define ENB_CONFIG_STRING_MME_IPV6_ADDRESS "ipv6" #define ENB_CONFIG_STRING_MME_IP_ADDRESS_ACTIVE "active" #define ENB_CONFIG_STRING_MME_IP_ADDRESS_PREFERENCE "preference" #define ENB_CONFIG_STRING_SCTP_CONFIG "SCTP" #define ENB_CONFIG_STRING_SCTP_INSTREAMS "SCTP_INSTREAMS" #define ENB_CONFIG_STRING_SCTP_OUTSTREAMS "SCTP_OUTSTREAMS" #define ENB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG "NETWORK_INTERFACES" #define ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_S1_MME "ENB_INTERFACE_NAME_FOR_S1_MME" #define ENB_CONFIG_STRING_ENB_IPV4_ADDRESS_FOR_S1_MME "ENB_IPV4_ADDRESS_FOR_S1_MME" #define ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_S1U "ENB_INTERFACE_NAME_FOR_S1U" #define ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_S1U "ENB_IPV4_ADDRESS_FOR_S1U" #define ENB_CONFIG_STRING_ENB_PORT_FOR_S1U "ENB_PORT_FOR_S1U" typedef struct shift_packet_s { unsigned int frame_number; // original frame number int shift_seconds; int shift_microseconds; int single; // shift timing only for this packet (not also following packets) struct shift_packet_s *next; } shift_packet_t; typedef struct mme_ip_address_s { unsigned ipv4:1; unsigned ipv6:1; unsigned active:1; char *ipv4_address; char *ipv6_address; } mme_ip_address_t; #define IPV4_STR_ADDR_TO_INT_NWBO(AdDr_StR,NwBo,MeSsAgE ) do {\ struct in_addr inp;\ if ( inet_aton(AdDr_StR, &inp ) < 0 ) {\ AssertFatal (0, MeSsAgE);\ } else {\ NwBo = inp.s_addr;\ }\ } while (0); typedef struct Enb_properties_s { /* Unique eNB_id to identify the eNB within EPC. * For macro eNB ids this field should be 20 bits long. * For home eNB ids this field should be 28 bits long. */ uint32_t eNB_id; /* The type of the cell */ enum cell_type_e cell_type; /* Optional name for the cell * NOTE: the name can be NULL (i.e no name) and will be cropped to 150 * characters. */ char *eNB_name; /* Tracking area code */ uint16_t tac; /* Mobile Country Code * Mobile Network Code */ uint16_t mcc; uint16_t mnc; uint8_t mnc_digit_length; /* Physical parameters */ int16_t Nid_cell[1+MAX_NUM_CCs];// for testing, change later /* Nb of MME to connect to */ uint8_t nb_mme; /* List of MME to connect to */ mme_ip_address_t mme_ip_address[S1AP_MAX_NB_MME_IP_ADDRESS]; int sctp_in_streams; int sctp_out_streams; char *enb_interface_name_for_S1U; in_addr_t enb_ipv4_address_for_S1U; tcp_udp_port_t enb_port_for_S1U; char *enb_interface_name_for_S1_MME; in_addr_t enb_ipv4_address_for_S1_MME; } Enb_properties_t; typedef struct Enb_properties_array_s { int number; Enb_properties_t *properties[MAX_ENB]; } Enb_properties_array_t; # define ET_ENB_REGISTER_RETRY_DELAY 3 # define ET_FSM_STATE_WAITING_RX_EVENT_DELAY_SEC 15 typedef enum { 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_SCHEDULED_FOR_RECEIVING, ET_PACKET_STATUS_RECEIVED, 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_S1C, ET_FSM_STATE_WAITING_RX_EVENT, ET_FSM_STATE_WAITING_TX_EVENT, ET_FSM_STATE_RUNNING, ET_FSM_STATE_END } et_fsm_state_t; enum COMPARE_ERR_CODE_e; typedef enum { ET_ERROR_MATCH_START = COMPARE_ERR_CODE_END, ET_ERROR_MATCH_PACKET_SCTP_CHUNK_TYPE = ET_ERROR_MATCH_START, ET_ERROR_MATCH_PACKET_SCTP_PPID, ET_ERROR_MATCH_PACKET_SCTP_ASSOC_ID, ET_ERROR_MATCH_PACKET_SCTP_STREAM_ID, ET_ERROR_MATCH_PACKET_SCTP_SSN, ET_ERROR_MATCH_PACKET_S1AP_PRESENT, ET_ERROR_MATCH_PACKET_S1AP_PROCEDURE_CODE, ET_ERROR_MATCH_PACKET_S1AP_CRITICALITY, ET_ERROR_MATCH_END } et_error_match_code_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 { SCTP_CID_DATA = 0, SCTP_CID_INIT = 1, SCTP_CID_INIT_ACK = 2, SCTP_CID_SACK = 3, SCTP_CID_HEARTBEAT = 4, SCTP_CID_HEARTBEAT_ACK = 5, SCTP_CID_ABORT = 6, SCTP_CID_SHUTDOWN = 7, SCTP_CID_SHUTDOWN_ACK = 8, SCTP_CID_ERROR = 9, SCTP_CID_COOKIE_ECHO = 10, SCTP_CID_COOKIE_ACK = 11, SCTP_CID_ECN_ECNE = 12, SCTP_CID_ECN_CWR = 13, SCTP_CID_SHUTDOWN_COMPLETE = 14, /* AUTH Extension Section 4.1 */ SCTP_CID_AUTH = 0x0F, /* PR-SCTP Sec 3.2 */ SCTP_CID_FWD_TSN = 0xC0, /* Use hex, as defined in ADDIP sec. 3.1 */ SCTP_CID_ASCONF = 0xC1, SCTP_CID_ASCONF_ACK = 0x80, } sctp_cid_t; /* enum */ typedef enum { TEST_S1AP_PDU_TYPE_START = 0, TEST_S1AP_PDU_TYPE_UNKNOWN = TEST_S1AP_PDU_TYPE_START, TEST_S1AP_PDU_TYPE_INITIATING, TEST_S1AP_PDU_TYPE_SUCCESSFUL_OUTCOME, TEST_S1AP_PDU_TYPE_UNSUCCESSFUL_OUTCOME, TEST_S1AP_PDU_TYPE_END } et_s1ap_pdu_type_t; 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 xml_stream_pos_offset; uint16_t binary_stream_pos; uint16_t binary_stream_allocated_size; uint8_t *binary_stream; s1ap_message message; // decoded message: information elements xmlDocPtr doc; // XML representation of the S1AP PDU } et_s1ap_t; // from kernel source file 3.19/include/linux/sctp.h, Big Endians typedef struct sctp_datahdr_s { uint32_t tsn; uint16_t stream; uint16_t ssn; uint32_t ppid; uint32_t assoc_id; // filled when running scenario et_s1ap_t payload; } sctp_datahdr_t; // from kernel source file 3.19/include/linux/sctp.h, Big Endians typedef struct sctp_inithdr { uint32_t init_tag; uint32_t a_rwnd; uint16_t num_outbound_streams; uint16_t num_inbound_streams; uint32_t initial_tsn; uint8_t params[0]; } sctp_inithdr_t; typedef sctp_inithdr_t sctp_initackhdr_t; typedef struct et_sctp_hdr_s { unsigned int src_port; unsigned int dst_port; sctp_cid_t chunk_type; union { sctp_datahdr_t data_hdr; sctp_inithdr_t init_hdr; sctp_initackhdr_t init_ack_hdr; } u; } et_sctp_hdr_t; typedef struct et_ip_s { unsigned int address_family; // AF_INET, AF_INET6 union { struct in6_addr ipv6; in_addr_t ipv4; }address; char str[INET6_ADDRSTRLEN+1]; }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; instance_t enb_instance; 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; long timer_id; // ITTI timer id for waiting rx packets struct timeval timestamp_packet; // timestamp when rx or tx packet }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; et_packet_t *list_packet; //-------------------------- // playing scenario //-------------------------- Enb_properties_array_t *enb_properties; uint32_t register_enb_pending; uint32_t registered_enb; long enb_register_retry_timer_id; hash_table_t *hash_mme2association_id; hash_table_t *hash_old_ue_mme_id2ue_mme_id; struct timeval time_last_tx_packet; // Time last sent packet struct timeval time_last_rx_packet; // Time last packet received with all previous scenario RX packet received. et_packet_t *last_rx_packet; // Last packet received with all previous scenario RX packet received. et_packet_t *last_tx_packet; // Last sent packet et_packet_t *next_packet; // Next packet to be handled in the scenario (RX or TX packet) int timer_count; } et_scenario_t; typedef enum { ET_EVENT_START = 0, ET_EVENT_INIT = ET_EVENT_START, ET_EVENT_S1C_CONNECTED, ET_EVENT_RX_SCTP_EVENT, ET_EVENT_RX_S1AP, ET_EVENT_RX_PACKET_TIME_OUT, ET_EVENT_TX_TIMED_PACKET, ET_EVENT_TICK, 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_packet_t *tx_timed_packet; et_packet_t *rx_packet_time_out; } 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); //------------------------- int et_s1ap_eNB_compare_assoc_id( struct s1ap_eNB_mme_data_s *p1, struct s1ap_eNB_mme_data_s *p2); uint32_t et_s1ap_generate_eNB_id(void); uint16_t et_s1ap_eNB_fetch_add_global_cnx_id(void); void et_s1ap_eNB_prepare_internal_data(void); void et_s1ap_eNB_insert_new_instance(s1ap_eNB_instance_t *new_instance_p); struct s1ap_eNB_mme_data_s *et_s1ap_eNB_get_MME(s1ap_eNB_instance_t *instance_p,int32_t assoc_id, uint16_t cnx_id); s1ap_eNB_instance_t *et_s1ap_eNB_get_instance(instance_t instance); void et_s1ap_eNB_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uint8_t *buffer,uint32_t buffer_length, uint16_t stream); int et_handle_s1ap_mismatch_mme_ue_s1ap_id(et_packet_t * const spacket, et_packet_t * const rx_packet); asn_comp_rval_t* et_s1ap_is_matching(et_s1ap_t * const s1ap1, et_s1ap_t * const s1ap2, const uint32_t constraints); et_packet_t* et_build_packet_from_s1ap_data_ind(et_event_s1ap_data_ind_t * const s1ap_data_ind); int et_scenario_set_packet_received(et_packet_t * const packet); int et_s1ap_process_rx_packet(et_event_s1ap_data_ind_t * const sctp_data_ind); void et_s1ap_eNB_handle_sctp_data_ind(sctp_data_ind_t * const sctp_data_ind); void et_s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p, net_ip_address_t *mme_ip_address, net_ip_address_t *local_ip_addr, uint16_t in_streams, uint16_t out_streams); void et_s1ap_handle_s1_setup_message(s1ap_eNB_mme_data_t *mme_desc_p, int sctp_shutdown); void et_s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *s1ap_register_eNB); void et_s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp); 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); //------------------------- void timeval_add (struct timeval * const result, const struct timeval * const a, const struct timeval * const b); int timeval_subtract (struct timeval * const result, struct timeval * const a, struct timeval * const b); void et_scenario_wait_rx_packet(et_packet_t * const packet); void et_scenario_schedule_tx_packet(et_packet_t * packet); et_fsm_state_t et_scenario_fsm_notify_event_state_running(et_event_t event); et_fsm_state_t et_scenario_fsm_notify_event_state_waiting_tx(et_event_t event); et_fsm_state_t et_scenario_fsm_notify_event_state_waiting_rx(et_event_t event); et_fsm_state_t et_scenario_fsm_notify_event_state_connecting_s1c(et_event_t event); et_fsm_state_t et_scenario_fsm_notify_event_state_null(et_event_t event); et_fsm_state_t 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); //------------------------- asn_comp_rval_t * et_s1ap_ies_is_matching(const S1AP_PDU_PR present, s1ap_message * const m1, s1ap_message * const m2, const uint32_t constraints); void update_xpath_node_mme_ue_s1ap_id(et_s1ap_t * const s1ap, xmlNode *node, const S1ap_MME_UE_S1AP_ID_t new_id); void update_xpath_nodes_mme_ue_s1ap_id(et_s1ap_t * const s1ap_payload, xmlNodeSetPtr nodes, const S1ap_MME_UE_S1AP_ID_t new_id); int et_s1ap_update_mme_ue_s1ap_id(et_packet_t * const packet, const S1ap_MME_UE_S1AP_ID_t old_id, const S1ap_MME_UE_S1AP_ID_t new_id); //------------------------- asn_comp_rval_t * et_sctp_data_is_matching(sctp_datahdr_t * const sctp1, sctp_datahdr_t * const sctp2, const uint32_t constraints); asn_comp_rval_t * et_sctp_is_matching(et_sctp_hdr_t * const sctp1, et_sctp_hdr_t * const sctp2, const uint32_t constraints); //------------------------------------------------------------------------------ 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); void et_get_shift_arg( char * line_argument, shift_packet_t * const shift); 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_compare_et_ip_to_net_ip_address(const et_ip_t * const ip, const net_ip_address_t * const net_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); const char * const et_error_match2str(const int err); 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); void et_enb_config_init(const char const * lib_config_file_name_pP); const Enb_properties_array_t *et_enb_config_get(void); void 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, const struct shift_packet_s *shifts); #endif /* PLAY_SCENARIO_H_ */