Commit ed268454 authored by gauthier's avatar gauthier

TODO transport layer address, play scenario max speed

parent cc4286f2
......@@ -301,184 +301,6 @@ install_nas_tools() {
fi
}
#################################################
# 3. Network interfaces utilities
################################################
cidr2mask(){
local i mask=""
local full_octets=$(($1/8))
local partial_octet=$(($1%8))
for ((i=0;i<4;i+=1)); do
if [ $i -lt $full_octets ]; then
mask+=255
elif [ $i -eq $full_octets ]; then
mask+=$((256 - 2**(8-$partial_octet)))
else
mask+=0
fi
test $i -lt 3 && mask+=.
done
echo $mask
}
# example: netcalc 192.168.12.100 255.255.255.0
netcalc(){
local IFS='.' ip i
local -a oct msk
read -ra oct <<<"$1"
read -ra msk <<<"$2"
for i in ${!oct[@]}; do
ip+=( "$(( oct[i] & msk[i] ))" )
done
echo "${ip[*]}"
}
# example:
bcastcalc(){
local IFS='.' ip i
local -a oct msk
read -ra oct <<<"$1"
read -ra msk <<<"$2"
for i in ${!oct[@]}; do
ip+=( "$(( oct[i] + ( 255 - ( oct[i] | msk[i] ) ) ))" )
done
echo "${ip[*]}"
}
is_real_interface(){
my_bool=1
for var in "$@"
do
if [ "a$var" == "a" ]; then
return 0
fi
if [ "a$var" == "anone" ]; then
return 0
fi
IF=`cat /etc/udev/rules.d/70-persistent-net.rules | grep $var | sed 's/^.*NAME=//' | tr -d '"'`
if [ "$IF" == "$var" ]; then
if [ "a${var:0:3}" != "aeth" ]; then
if [ "a${var:0:4}" != "awlan" ]; then
if [ "a${var:0:4}" != "awifi" ]; then
my_bool=0;
fi
fi
fi
fi
done
return $my_bool
}
is_virtual_interface(){
my_bool=1
for var in "$@"
do
if [ "a$var" == "a" ]; then
return 0
fi
if [ "a$var" == "anone" ]; then
return 0
fi
num=`expr index "$var" :`
if [ $num -eq 0 ]; then
my_bool=0;
fi
done
return $my_bool
}
# arg1 = interface name
# arg2 = ipv4 addr cidr
set_interface_up(){
interface=$1
address=${2%/*} #part before '/'
cidr_netmask=${2#*/} # part after '/'
if [ "a${interface:0:4}" == "anone" ]; then
return;
fi
echo "ifconfig $interface up"
$SUDO ifconfig $interface up
sync
netmask=`cidr2mask $cidr_netmask`
broadcast=`bcastcalc $address $netmask`
echo "ip -4 addr add $address/$cidr_netmask broadcast $broadcast dev $interface"
$SUDO ip -4 addr add $address/$cidr_netmask broadcast $broadcast dev $interface
sync
}
# arg1 = interface name
# arg2 = ipv4 addr cidr
set_virtual_interface_up(){
interface=$1
address=${2%/*} #part before '/'
cidr_netmask=${2#*/} # part after '/'
if [ "a${interface:0:4}" == "anone" ]; then
return;
fi
$SUDO ifconfig $interface down > /dev/null 2>&1
sync
echo "ifconfig $interface $address up"
$SUDO ifconfig $interface $address up
sync
}
#arg1 is interface name
#arg2 is IP address (CIDR)
set_network_interface(){
local interface_name=$1
local ip_cidr=$2
is_virtual_interface $interface_name
if [ $? -eq 1 ]; then
echo "$interface_name is virtual interface"
set_virtual_interface_up $interface_name $ip_cidr
else
is_real_interface $interface_name
if [ $? -eq 1 ]; then
echo "$interface_name is real interface"
set_interface_up $interface_name $ip_cidr
else
echo_warning "$interface_name not handled, not configuring it"
return
fi
fi
}
# arg1 is a 'libconfig-like' config file
set_epc_network_interfaces(){
value="`cat $1 | cut -d "#" -f1 | grep 'ADDRESS\|INTERFACE' | tr -d " " | grep "="`"
eval $value
# check all var names are correct
list_var_name="\
ENB_INTERFACE_NAME_FOR_S1_MME ENB_IPV4_ADDRESS_FOR_S1_MME \
ENB_INTERFACE_NAME_FOR_S1U ENB_IPV4_ADDRESS_FOR_S1U "
for var_name in $list_var_name
do
if [ -n "$${var_name}" ]; then
echo_success "Found ${var_name} = ${!var_name}"
else
echo_fatal "${var_name} does does not exist in your config file $1"
fi
done
# configure interfaces
set_network_interface $ENB_INTERFACE_NAME_FOR_S1_MME $ENB_IPV4_ADDRESS_FOR_S1_MME
set_network_interface $ENB_INTERFACE_NAME_FOR_S1U $ENB_IPV4_ADDRESS_FOR_S1U
}
################################
......
......@@ -142,7 +142,7 @@ int strip_extension(char *in_filename)
if (NULL != in_filename) {
/* Check chars starting at end of string to find last '.' */
for (ssize_t i = strlen(in_filename); i > (name_min_len + max_ext_len); i--) {
for (ssize_t i = strlen(in_filename); i >= name_min_len; i--) {
if (in_filename[i] == '.') {
in_filename[i] = '\0';
return i;
......@@ -662,7 +662,7 @@ config_parse_opt_line (
fprintf(stderr, "Error: eNB config file name %s is not found in dir %s\n", enb_config_file_name, g_test_dir);
}
enb_config_init(enb_config_file_name);
enb_config_display();
//enb_config_display();
if (NULL == pdml_in_file_name) {
fprintf(stderr, "Error: please provide the PDML file name that should be in %s\n", g_test_dir);
......
......@@ -69,6 +69,7 @@
#define GS_IS_DIR 2
//------------------------------------------------------------------------------
Enb_properties_array_t g_enb_properties;
int g_max_speed = 0;
//------------------------------------------------------------------------------
extern et_scenario_t *g_scenario;
extern int xmlLoadExtDtdDefaultValue;
......@@ -118,7 +119,7 @@ int et_strip_extension(char *in_filename)
if (NULL != in_filename) {
/* Check chars starting at end of string to find last '.' */
for (ssize_t i = strlen(in_filename); i > (name_min_len + max_ext_len); i--) {
for (ssize_t i = strlen(in_filename); i > name_min_len; i--) {
if (in_filename[i] == '.') {
in_filename[i] = '\0';
return i;
......@@ -833,6 +834,7 @@ et_config_parse_opt_line (
LONG_OPTION_START = 0x100, /* Start after regular single char options */
LONG_OPTION_ENB_CONF_FILE,
LONG_OPTION_SCENARIO_FILE,
LONG_OPTION_MAX_SPEED,
LONG_OPTION_TEST_DIR,
LONG_OPTION_HELP,
LONG_OPTION_VERSION
......@@ -841,6 +843,7 @@ et_config_parse_opt_line (
static struct option long_options[] = {
{"enb-conf-file", required_argument, 0, LONG_OPTION_ENB_CONF_FILE},
{"scenario ", required_argument, 0, LONG_OPTION_SCENARIO_FILE},
{"max-speed ", no_argument, 0, LONG_OPTION_MAX_SPEED},
{"test-dir", required_argument, 0, LONG_OPTION_TEST_DIR},
{"help", no_argument, 0, LONG_OPTION_HELP},
{"version", no_argument, 0, LONG_OPTION_VERSION},
......@@ -850,7 +853,7 @@ et_config_parse_opt_line (
/*
* Parsing command line
*/
while ((option = getopt_long (argc, argv, "vhc:s:d:", long_options, NULL)) != -1) {
while ((option = getopt_long (argc, argv, "vhmc:s:d:", long_options, NULL)) != -1) {
switch (option) {
case LONG_OPTION_ENB_CONF_FILE:
case 'c':
......@@ -882,6 +885,11 @@ et_config_parse_opt_line (
}
break;
case LONG_OPTION_MAX_SPEED:
case 'm':
g_max_speed = 1;
break;
case LONG_OPTION_VERSION:
case 'v':
printf("Version %s\n", PACKAGE_VERSION);
......
......@@ -40,6 +40,7 @@
# include <time.h>
# include <stdint.h>
# include <libxml/tree.h>
# include <libxml/xpath.h>
# include <netinet/in.h>
#include "S1AP-PDU.h"
......@@ -460,6 +461,9 @@ 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);
......
......@@ -46,6 +46,8 @@
#include "play_scenario_s1ap_eNB_defs.h"
#include "timer.h"
//------------------------------------------------------------------------------
extern int g_max_speed;
//------------------------------------------------------------------------------
et_scenario_t *g_scenario = NULL;
pthread_mutex_t g_fsm_lock = PTHREAD_MUTEX_INITIALIZER;
......@@ -86,13 +88,13 @@ int timeval_subtract (struct timeval * const result, struct timeval * const a, s
//------------------------------------------------------------------------------
void et_scenario_wait_rx_packet(et_packet_t * const packet)
{
packet->status = ET_PACKET_STATUS_SCHEDULED_FOR_RECEIVING;
g_fsm_state = ET_FSM_STATE_WAITING_RX_EVENT;
if (timer_setup (ET_FSM_STATE_WAITING_RX_EVENT_DELAY_SEC, 0, TASK_S1AP, INSTANCE_DEFAULT, TIMER_ONE_SHOT,
NULL, &packet->timer_id) < 0) {
packet, &packet->timer_id) < 0) {
AssertFatal(0, " Can not start waiting RX event timer\n");
}
LOG_D(ENB_APP, "Waiting RX packet num %d\n", packet->packet_number);
g_fsm_state = ET_FSM_STATE_WAITING_RX_EVENT;
packet->status = ET_PACKET_STATUS_SCHEDULED_FOR_RECEIVING;
}
//------------------------------------------------------------------------------
void et_scenario_schedule_tx_packet(et_packet_t * const packet)
......@@ -133,14 +135,19 @@ void et_scenario_schedule_tx_packet(et_packet_t * const packet)
we_are_too_early = timeval_subtract(&offset,&offset_last_rx_packet,&packet->time_relative_to_last_received_packet);
LOG_D(ENB_APP, "we_are_too_early=%d, offset=%ld.%06d\n", we_are_too_early, offset.tv_sec, offset.tv_usec);
}
if (we_are_too_early > 0) {
if ((0 < we_are_too_early) && (0 == g_max_speed)){
// set timer
if (offset.tv_sec < 0) offset.tv_sec = -offset.tv_sec;
if (offset.tv_usec < 0) {
offset.tv_usec = offset.tv_usec + 1000000;
offset.tv_sec -= 1;
}
LOG_D(ENB_APP, "Send packet num %u original frame number %u in %ld.%06d sec\n",
packet->packet_number, packet->original_frame_number, offset.tv_sec, offset.tv_usec);
packet->status = ET_PACKET_STATUS_SCHEDULED_FOR_SENDING;
if (timer_setup (offset.tv_sec, offset.tv_usec, TASK_S1AP, INSTANCE_DEFAULT, TIMER_ONE_SHOT,
NULL, &packet->timer_id) < 0) {
if (timer_setup (offset.tv_sec, offset.tv_usec, TASK_S1AP, INSTANCE_DEFAULT, TIMER_ONE_SHOT,packet, &packet->timer_id) < 0) {
AssertFatal(0, " Can not start TX event timer\n");
}
// Done g_fsm_state = ET_FSM_STATE_WAITING_TX_EVENT;
......
......@@ -359,7 +359,7 @@ et_packet_t* et_parse_xml_packet(xmlDocPtr doc, xmlNodePtr node) {
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);
packet->time_relative_to_first_packet.tv_usec = (int)((afloat - packet->time_relative_to_first_packet.tv_sec)*1000000.0);
if (first_packet > 0) {
initial_time = packet->time_relative_to_first_packet;
......@@ -381,6 +381,13 @@ et_packet_t* et_parse_xml_packet(xmlDocPtr doc, xmlNodePtr node) {
&packet->time_relative_to_last_sent_packet);
relative_last_sent_packet = packet->time_relative_to_first_packet;
}
if (first_received_packet > 0) {
packet->time_relative_to_last_received_packet.tv_sec = 0;
packet->time_relative_to_last_received_packet.tv_usec = 0;
} else {
timersub(&packet->time_relative_to_first_packet, &relative_last_received_packet,
&packet->time_relative_to_last_received_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;
......@@ -393,6 +400,13 @@ et_packet_t* et_parse_xml_packet(xmlDocPtr doc, xmlNodePtr node) {
&packet->time_relative_to_last_received_packet);
relative_last_received_packet = packet->time_relative_to_first_packet;
}
if (first_sent_packet > 0) {
packet->time_relative_to_last_sent_packet.tv_sec = 0;
packet->time_relative_to_last_sent_packet.tv_usec = 0;
} else {
timersub(&packet->time_relative_to_first_packet, &relative_last_sent_packet,
&packet->time_relative_to_last_sent_packet);
}
}
} else if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"frame.number"))) {
......
......@@ -682,6 +682,11 @@ int et_s1ap_process_rx_packet(et_event_s1ap_data_ind_t * const s1ap_data_ind)
packet->timestamp_packet.tv_usec = rx_packet->timestamp_packet.tv_usec;
return et_scenario_set_packet_received(packet);
}
} else if (strcmp(comp_results->name, "S1ap-TransportLayerAddress") == 0) {
S1AP_WARN("Some work needed there for %s, TODO in generic_scenario.xsl, add epc conf file in the process\n",comp_results->name);
packet->timestamp_packet.tv_sec = rx_packet->timestamp_packet.tv_sec;
packet->timestamp_packet.tv_usec = rx_packet->timestamp_packet.tv_usec;
return et_scenario_set_packet_received(packet);
} else {
AssertFatal(0,"Some work needed there");
}
......@@ -1109,6 +1114,7 @@ void *et_s1ap_eNB_task(void *arg)
{
et_packet_t * packet = (et_packet_t*)TIMER_HAS_EXPIRED (received_msg).arg;
et_event_t event;
if (NULL != packet) {
if (packet->status == ET_PACKET_STATUS_SCHEDULED_FOR_RECEIVING) {
memset((void*)&event, 0, sizeof(event));
event.code = ET_EVENT_RX_PACKET_TIME_OUT;
......@@ -1122,6 +1128,9 @@ void *et_s1ap_eNB_task(void *arg)
} else if ((packet->status != ET_PACKET_STATUS_SENT) && ((packet->status != ET_PACKET_STATUS_RECEIVED))) {
AssertFatal (0, "Bad status %d of packet timed out!\n", packet->status);
}
} else {
LOG_W(S1AP, " Received TIMER_HAS_EXPIRED: timer_id %d, no packet attached to timer\n", TIMER_HAS_EXPIRED(received_msg).timer_id);
}
}
if (TIMER_HAS_EXPIRED (received_msg).timer_id == g_scenario->enb_register_retry_timer_id) {
/* Restart the registration process */
......
......@@ -38,8 +38,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <unistd.h>
#include <crypt.h>
#include <errno.h>
#include <libxml/tree.h>
#include <libxml/parser.h>
#include <libxml/xpath.h>
......@@ -457,7 +459,7 @@ asn_comp_rval_t * et_s1ap_ies_is_matching(const S1AP_PDU_PR present, s1ap_messag
}
static void update_xpath_node_mme_ue_s1ap_id(et_s1ap_t * const s1ap, xmlNode *node, xmlChar *new_id_hex, xmlChar *new_id_dec, xmlChar *showname)
void update_xpath_node_mme_ue_s1ap_id(et_s1ap_t * const s1ap, xmlNode *node, const S1ap_MME_UE_S1AP_ID_t new_id)
{
xmlNode *cur_node = NULL;
xmlAttrPtr attr = NULL;
......@@ -485,19 +487,47 @@ static void update_xpath_node_mme_ue_s1ap_id(et_s1ap_t * const s1ap, xmlNode *no
xmlFree(xml_char);
xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"size");
if (NULL != xml_char) {
const xmlChar value_d[32];
const xmlChar value_h[20];
const xmlChar showname[64];
int ret = 0;
int pos2 = 0;
char val = NULL;
char hex[3] = {0,0,0};;
size = strtoul((const char *)xml_char, NULL, 0);
xmlFree(xml_char);
// second: try to set value (always hex)
attr = xmlSetProp((xmlNode *)cur_node, (const xmlChar *)"value", new_id_hex);
attr = xmlSetProp((xmlNode *)cur_node, (const xmlChar *)"show", new_id_dec);
ret = snprintf((char *)value_d, 32, "%ld", new_id);
AssertFatal((ret < 0) || (ret > 32), "Could not convert int to dec str");
ret = snprintf((char *)value_h, 20, "C0%08X", new_id);
AssertFatal((ret < 0) || (ret > 20), "Could not convert int to hex str");
ret = snprintf((char *)showname, 64, "MME-UE-S1AP-ID: %d", new_id);
AssertFatal((ret < 0) || (ret > 64), "Could not convert int to dec str");
attr = xmlSetProp((xmlNode *)cur_node, (const xmlChar *)"value", value_h);
attr = xmlSetProp((xmlNode *)cur_node, (const xmlChar *)"show", value_d);
attr = xmlSetProp((xmlNode *)cur_node, (const xmlChar *)"showname", showname);
//TODO update s1ap->binary_stream @pos with new_id_hex, size
AssertFatal((pos+size) < s1ap->binary_stream_allocated_size, "Rewrite of mme_ue_s1ap_id out of bounds of binary_stream");
//avoid endianess issues
do {
hex[0] = value_h[pos2++];
hex[1] = value_h[pos2++];
hex[2] = 0;
val = (unsigned char)strtoul(hex, NULL, 16);
AssertFatal(errno != 0, "Conversion of hexstring %s failed", hex);
s1ap->binary_stream[pos++] = val;
} while (pos2 < (2*5));
// update ASN1
et_decode_s1ap(s1ap);
S1AP_DEBUG("Updated ASN1 for %s\n", showname);
}
}
}
}
if (0 < go_deeper_in_tree) {
update_xpath_node_mme_ue_s1ap_id(s1ap, cur_node->children, new_id_hex, new_id_dec, showname);
update_xpath_node_mme_ue_s1ap_id(s1ap, cur_node->children, new_id);
}
}
}
......@@ -510,24 +540,14 @@ static void update_xpath_node_mme_ue_s1ap_id(et_s1ap_t * const s1ap, xmlNode *no
* Prints the @nodes content to @output.
* From http://www.xmlsoft.org/examples/#xpath2.c
*/
static 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)
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 size = 0;
int i = 0;
int ret = 0;
const xmlChar value_d[32];
const xmlChar value_h[20];
const xmlChar showname[64];
xmlNode *s1ap_node = NULL;
size = (nodes) ? nodes->nodeNr : 0;
ret = snprintf((char *)value_d, 32, "%ld", new_id);
AssertFatal((ret < 0) || (ret > 32), "Could not convert int to dec str");
ret = snprintf((char *)value_h, 20, "C0%X", new_id);
AssertFatal((ret < 0) || (ret > 20), "Could not convert int to hex str");
ret = snprintf((char *)showname, 64, "MME-UE-S1AP-ID: %d", new_id);
AssertFatal((ret < 0) || (ret > 64), "Could not convert int to dec str");
/*
* NOTE: the nodes are processed in reverse order, i.e. reverse document
* order because xmlNodeSetContent can actually free up descendant
......@@ -539,7 +559,7 @@ static void update_xpath_nodes_mme_ue_s1ap_id(et_s1ap_t * const s1ap_payload, xm
for(i = size - 1; i >= 0; i--) {
s1ap_node = nodes->nodeTab[i];
AssertFatal(NULL != s1ap_node, "One element of resultset of XPATH expression is NULL\n");
update_xpath_node_mme_ue_s1ap_id(s1ap_payload, s1ap_node, value_d, value_h, showname);
update_xpath_node_mme_ue_s1ap_id(s1ap_payload, s1ap_node, new_id);
/*
* All the elements returned by an XPath query are pointers to
* elements from the tree *except* namespace nodes where the XPath
......@@ -574,7 +594,7 @@ int et_s1ap_update_mme_ue_s1ap_id(et_packet_t * const packet, const S1ap_MME_UE_
xmlXPathObjectPtr xpath_obj = NULL;
ret = snprintf(xpath_expression, ET_XPATH_EXPRESSION_MAX_LENGTH, "//field[@name=\"s1ap.MME_UE_S1AP_ID\"][@show=\"%d\"]", old_id);
AssertFatal((ret < 0) || (ret > ET_XPATH_EXPRESSION_MAX_LENGTH), "Could not build XPATH expression");
AssertFatal((ret > 0) && (ret < ET_XPATH_EXPRESSION_MAX_LENGTH), "Could not build XPATH expression err=%d", ret);
doc = packet->sctp_hdr.u.data_hdr.payload.doc;
......
......@@ -69,15 +69,16 @@ asn_comp_rval_t * et_sctp_data_is_matching(sctp_datahdr_t * const sctp1, sctp_da
S1AP_WARN("No Matching SCTP stream %u %u\n", sctp1->stream, sctp2->stream);
}
}
if (sctp1->ssn != sctp2->ssn) {
if (constraints & ET_BIT_MASK_MATCH_SCTP_SSN) {
rv = calloc(1, sizeof(asn_comp_rval_t));
rv->err_code = ET_ERROR_MATCH_PACKET_SCTP_SSN;
return rv;
} else {
S1AP_WARN("No Matching SCTP STREAM SN %u %u\n", sctp1->ssn, sctp2->ssn);
}
}
// We do not have SSN from lower layers
// if (sctp1->ssn != sctp2->ssn) {
// if (constraints & ET_BIT_MASK_MATCH_SCTP_SSN) {
// rv = calloc(1, sizeof(asn_comp_rval_t));
// rv->err_code = ET_ERROR_MATCH_PACKET_SCTP_SSN;
// return rv;
// } else {
// S1AP_WARN("No Matching SCTP STREAM SN %u %u\n", sctp1->ssn, sctp2->ssn);
// }
// }
return et_s1ap_is_matching(&sctp1->payload, &sctp2->payload, constraints);
}
......
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