Newer
Older
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/

gauthier
committed
/*
play_scenario_fsm.c
-------------------
AUTHOR : Lionel GAUTHIER
COMPANY : EURECOM
EMAIL : Lionel.Gauthier@eurecom.fr
*/
#include <stdio.h>

gauthier
committed
#include "intertask_interface.h"
#include "platform_types.h"
#include "assertions.h"
#include "play_scenario.h"
#include "s1ap_ies_defs.h"
#include "play_scenario_s1ap_eNB_defs.h"

gauthier
committed
//------------------------------------------------------------------------------
extern int g_max_speed;
//------------------------------------------------------------------------------
et_scenario_t *g_scenario = NULL;
pthread_mutex_t g_fsm_lock = PTHREAD_MUTEX_INITIALIZER;
et_fsm_state_t g_fsm_state = ET_FSM_STATE_NULL;
uint32_t g_constraints = ET_BIT_MASK_MATCH_SCTP_STREAM | ET_BIT_MASK_MATCH_SCTP_SSN;

gauthier
committed
//------------------------------------------------------------------------------
// it is assumed that if a time is negative tv_sec and tv_usec are both negative
void timeval_add (struct timeval * const result, const struct timeval * const a, const struct timeval * const b)
AssertFatal(((a->tv_sec <= 0) && (a->tv_usec <= 0)) || ((a->tv_sec >= 0) && (a->tv_usec >= 0)), " Bad time format arg a\n");
AssertFatal(((b->tv_sec <= 0) && (b->tv_usec <= 0)) || ((b->tv_sec >= 0) && (b->tv_usec >= 0)), " Bad time format arg b\n");
// may happen overflows but were are not dealing with very large timings
long long int r = a->tv_usec + b->tv_usec + (a->tv_sec + b->tv_sec) * 1000000;
result->tv_sec = r / (long long int)1000000;
result->tv_usec = r % (long long int)1000000;
if ((result != a) && (result != b)) {
LOG_D(ENB_APP, "timeval_add(%ld.%06d, %ld.%06d)=%ld.%06d\n", a->tv_sec, a->tv_usec, b->tv_sec, b->tv_usec, result->tv_sec, result->tv_usec);
//------------------------------------------------------------------------------
// it is assumed that if a time is negative tv_sec and tv_usec are both negative
// return true if result is positive
int timeval_subtract (struct timeval * const result, struct timeval * const a, struct timeval * const b)
{
AssertFatal(((a->tv_sec <= 0) && (a->tv_usec <= 0)) || ((a->tv_sec >= 0) && (a->tv_usec >= 0)), " Bad time format arg a\n");
AssertFatal(((b->tv_sec <= 0) && (b->tv_usec <= 0)) || ((b->tv_sec >= 0) && (b->tv_usec >= 0)), " Bad time format arg b\n");
// may happen overflows but were are not dealing with very large timings
long long int r = a->tv_usec - b->tv_usec + (a->tv_sec - b->tv_sec) * 1000000;
result->tv_sec = r / (long long int)1000000;
result->tv_usec = r % (long long int)1000000;
if ((result != a) && (result != b)) {
LOG_D(ENB_APP, "timeval_subtract(%ld.%06d, %ld.%06d)=%ld.%06d\n", a->tv_sec, a->tv_usec, b->tv_sec, b->tv_usec, result->tv_sec, result->tv_usec);
}
return (result->tv_sec >= 0) && (result->tv_usec >= 0);
//------------------------------------------------------------------------------
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,
packet, &packet->timer_id) < 0) {
AssertFatal(0, " Can not start waiting RX event timer\n");
}
g_scenario->timer_count++;
LOG_D(ENB_APP, "Waiting RX packet num %d original frame number %u\n", packet->packet_number, packet->original_frame_number);
}
//------------------------------------------------------------------------------
void et_scenario_schedule_tx_packet(et_packet_t * packet)
{
s1ap_eNB_instance_t *s1ap_eNB_instance = NULL;
struct timeval now = { .tv_sec = 0, .tv_usec = 0 };
struct timeval offset_last_tx_packet = { .tv_sec = 0, .tv_usec = 0 };
struct timeval offset_last_rx_packet = { .tv_sec = 0, .tv_usec = 0 };
struct timeval offset_tx_rx = { .tv_sec = 0, .tv_usec = 0 };
struct timeval offset = { .tv_sec = 0, .tv_usec = 0 };
int last_packet_was_rx = 0;
int we_are_too_late = 0;
int original_frame_number = -1;
AssertFatal(NULL != packet, "packet argument is NULL");
s1ap_eNB_instance = et_s1ap_eNB_get_instance(packet->enb_instance);
AssertFatal(NULL != s1ap_eNB_instance, "Cannot get s1ap_eNB_instance_t for eNB instance %d", packet->enb_instance);
LOG_D(ENB_APP, "%s\n", __FUNCTION__);
g_fsm_state = ET_FSM_STATE_WAITING_TX_EVENT;
switch (packet->sctp_hdr.chunk_type) {
case SCTP_CID_DATA:
// check if we can send it now
// TODO: BUG we have to discard in scenario all packets that cannot be processed (SACK, COOKIEs, etc)
AssertFatal(gettimeofday(&now, NULL) == 0, "gettimeofday failed");
timeval_subtract(&offset_last_tx_packet,&now,&g_scenario->time_last_tx_packet);
timeval_subtract(&offset_last_rx_packet,&now,&g_scenario->time_last_rx_packet);
LOG_D(ENB_APP, "offset_last_tx_packet=%ld.%06d\n", offset_last_tx_packet.tv_sec, offset_last_tx_packet.tv_usec);
LOG_D(ENB_APP, "offset_last_rx_packet=%ld.%06d\n", offset_last_rx_packet.tv_sec, offset_last_rx_packet.tv_usec);
last_packet_was_rx = timeval_subtract(&offset_tx_rx,&offset_last_tx_packet,&offset_last_rx_packet);
if (last_packet_was_rx) {
LOG_D(ENB_APP, "last_packet_was_rx\n");
we_are_too_late = timeval_subtract(&offset,&offset_last_rx_packet,&packet->time_relative_to_last_received_packet);
LOG_D(ENB_APP, "we_are_too_late=%d, offset=%ld.%06d\n", we_are_too_late, offset.tv_sec, offset.tv_usec);
} else {
LOG_D(ENB_APP, "last_packet_was_tx\n");
we_are_too_late = timeval_subtract(&offset,&offset_last_tx_packet,&packet->time_relative_to_last_sent_packet);
LOG_D(ENB_APP, "we_are_too_late=%d, offset=%ld.%06d\n", we_are_too_late, offset.tv_sec, offset.tv_usec);
if ((0 == we_are_too_late) && (0 == g_max_speed)){
if ((offset.tv_sec <= 0) || (offset.tv_usec <= 0)){
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,packet, &packet->timer_id) < 0) {
AssertFatal(0, " Can not start TX event timer\n");
}
g_scenario->timer_count++;
// Done g_fsm_state = ET_FSM_STATE_WAITING_TX_EVENT;
} else {
// send immediately
AssertFatal(0 == gettimeofday(&packet->timestamp_packet, NULL), "gettimeofday() Failed");
original_frame_number = packet->original_frame_number;
do {
g_scenario->time_last_tx_packet.tv_sec = packet->timestamp_packet.tv_sec;
g_scenario->time_last_tx_packet.tv_usec = packet->timestamp_packet.tv_usec;
LOG_D(ENB_APP, "Sending packet num %d original frame number %u immediately\n",packet->packet_number, packet->original_frame_number);
et_s1ap_eNB_itti_send_sctp_data_req(
packet->enb_instance,
packet->sctp_hdr.u.data_hdr.assoc_id,
packet->sctp_hdr.u.data_hdr.payload.binary_stream,
packet->sctp_hdr.u.data_hdr.payload.binary_stream_allocated_size,
packet->sctp_hdr.u.data_hdr.stream);
packet->status = ET_PACKET_STATUS_SENT;
g_scenario->next_packet = g_scenario->next_packet->next;
packet = packet->next;
} while ((NULL != packet) && (packet->original_frame_number == original_frame_number));
g_fsm_state = ET_FSM_STATE_RUNNING;
}
break;
case SCTP_CID_INIT:
case SCTP_CID_INIT_ACK:
AssertFatal(0, "Invalid case TX packet SCTP_CID_INIT or SCTP_CID_INIT_ACK");
break;
default:
AssertFatal(0, "Invalid case TX packet SCTP_CID %d", packet->sctp_hdr.chunk_type);
}
}
//------------------------------------------------------------------------------
et_fsm_state_t et_scenario_fsm_notify_event_state_running(et_event_t event)

gauthier
committed
{
case ET_EVENT_TICK:
while (NULL != g_scenario->next_packet) {
LOG_D(ENB_APP, "EVENT_TICK: Considering packet num %d original frame number %u\n", g_scenario->next_packet->packet_number, g_scenario->next_packet->original_frame_number);
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
switch (g_scenario->next_packet->sctp_hdr.chunk_type) {
case SCTP_CID_DATA :
// no init in this scenario, may be sub-scenario
if (g_scenario->next_packet->action == ET_PACKET_ACTION_S1C_SEND) {
if (g_scenario->next_packet->status == ET_PACKET_STATUS_NONE) {
et_scenario_schedule_tx_packet(g_scenario->next_packet);
pthread_mutex_unlock(&g_fsm_lock);
et_event_t continue_event;
continue_event.code = ET_EVENT_TICK;
et_scenario_fsm_notify_event(continue_event);
return g_fsm_state;
} else if (g_scenario->next_packet->status != ET_PACKET_STATUS_SCHEDULED_FOR_SENDING) {
AssertFatal(0, "Invalid packet status %d", g_scenario->next_packet->status);
}
} else if (g_scenario->next_packet->action == ET_PACKET_ACTION_S1C_RECEIVE) {
if (g_scenario->next_packet->status == ET_PACKET_STATUS_RECEIVED) {
g_scenario->next_packet = g_scenario->next_packet->next;
} else if (g_scenario->next_packet->status == ET_PACKET_STATUS_NONE) {
et_scenario_wait_rx_packet(g_scenario->next_packet);
pthread_mutex_unlock(&g_fsm_lock);
return g_fsm_state;
} else {
AssertFatal(0, "Invalid packet status %d", g_scenario->next_packet->status);
}
} else {
AssertFatal(0, "Invalid packet action %d", g_scenario->next_packet->action);
}
break;
case SCTP_CID_INIT:
case SCTP_CID_INIT_ACK:
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:
LOG_D(ENB_APP, "EVENT_TICK: Ignoring packet num %d SCTP CID %s\n",
g_scenario->next_packet->packet_number,
et_chunk_type_cid2str(g_scenario->next_packet->sctp_hdr.chunk_type));
g_scenario->next_packet->status = ET_PACKET_STATUS_NOT_TAKEN_IN_ACCOUNT;
g_scenario->next_packet = g_scenario->next_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(g_scenario->next_packet->sctp_hdr.chunk_type));
break;
default:
LOG_D(ENB_APP, "EVENT_TICK: Ignoring packet num %d SCTP CID %s\n",
g_scenario->next_packet->packet_number,
et_chunk_type_cid2str(g_scenario->next_packet->sctp_hdr.chunk_type));
g_scenario->next_packet->status = ET_PACKET_STATUS_NOT_TAKEN_IN_ACCOUNT;
g_scenario->next_packet = g_scenario->next_packet->next;
}
}
fprintf(stderr, "No Packet found in this scenario: %s\n", g_scenario->name);
g_fsm_state = ET_FSM_STATE_NULL;
pthread_mutex_unlock(&g_fsm_lock);
if (0 == g_scenario->timer_count) {
fprintf(stderr, "End of scenario: %s\n", g_scenario->name);
fflush(stderr);
fflush(stdout);
}
fprintf(stderr, "Remaining timers running: %d\n", g_scenario->timer_count);
break;
case ET_EVENT_RX_PACKET_TIME_OUT:
AssertFatal(0, "Event ET_EVENT_RX_PACKET_TIME_OUT not handled in FSM state ET_FSM_STATE_RUNNING");
break;
case ET_EVENT_TX_TIMED_PACKET:
AssertFatal(0, "Event ET_EVENT_TX_TIMED_PACKET not handled in FSM state ET_FSM_STATE_RUNNING");
break;
case ET_EVENT_RX_S1AP:
et_s1ap_process_rx_packet(&event.u.s1ap_data_ind);
break;
default:
AssertFatal(0, "Case event %d not handled in ET_FSM_STATE_RUNNING", event.code);
}
pthread_mutex_unlock(&g_fsm_lock);
return 0;
}
//------------------------------------------------------------------------------
et_fsm_state_t et_scenario_fsm_notify_event_state_waiting_tx(et_event_t event)
int rv = 0;
int original_frame_number = -1;
et_packet_t *packet = NULL;
case ET_EVENT_TICK:
fprintf(stdout, "EVENT_TICK: waiting for tx event\n");
rv = et_s1ap_process_rx_packet(&event.u.s1ap_data_ind);
case ET_EVENT_TX_TIMED_PACKET:
// send immediately
packet = event.u.tx_timed_packet;
AssertFatal(0 == gettimeofday(&packet->timestamp_packet, NULL), "gettimeofday() Failed");
original_frame_number = packet->original_frame_number;
do {
g_scenario->time_last_tx_packet.tv_sec = packet->timestamp_packet.tv_sec;
g_scenario->time_last_tx_packet.tv_usec = packet->timestamp_packet.tv_usec;
LOG_D(ENB_APP, "Sending packet num %d original frame number %u immediately\n",packet->packet_number, packet->original_frame_number);
et_s1ap_eNB_itti_send_sctp_data_req(
packet->enb_instance,
packet->sctp_hdr.u.data_hdr.assoc_id,
packet->sctp_hdr.u.data_hdr.payload.binary_stream,
packet->sctp_hdr.u.data_hdr.payload.binary_stream_allocated_size,
packet->sctp_hdr.u.data_hdr.stream);
packet->status = ET_PACKET_STATUS_SENT;
packet = packet->next;
g_scenario->next_packet = packet;
} while ( (NULL != packet) && (packet->original_frame_number == original_frame_number));
g_fsm_state = ET_FSM_STATE_RUNNING;
case ET_EVENT_RX_PACKET_TIME_OUT:
default:
AssertFatal(0, "Case event %d not handled in ET_FSM_STATE_WAITING_TX", event.code);
}
pthread_mutex_unlock(&g_fsm_lock);
return 0;
}
//------------------------------------------------------------------------------
et_fsm_state_t et_scenario_fsm_notify_event_state_waiting_rx(et_event_t event)
{
int rv = 0;
switch (event.code){
case ET_EVENT_TICK:
fprintf(stdout, "EVENT_TICK: waiting for rx event\n");
break;
case ET_EVENT_RX_PACKET_TIME_OUT:
fprintf(stderr, "Error The following packet is not received:\n");
AssertFatal(0, "Waited packet not received");
break;
case ET_EVENT_RX_S1AP:
rv = et_s1ap_process_rx_packet(&event.u.s1ap_data_ind);
// waited packet
if (rv == 0) {
g_fsm_state = ET_FSM_STATE_RUNNING;
}
break;
case ET_EVENT_TX_TIMED_PACKET:
AssertFatal(0, "Case event %d not handled in ET_FSM_STATE_WAITING_RX", event.code);
pthread_mutex_unlock(&g_fsm_lock);
return 0;
}
//------------------------------------------------------------------------------
et_fsm_state_t et_scenario_fsm_notify_event_state_connecting_s1c(et_event_t event)
{
switch (event.code){
case ET_EVENT_TICK:
break;
case ET_EVENT_S1C_CONNECTED:
// hack simulate we have been able to get the right timing values for STCP connect
AssertFatal(gettimeofday(&g_scenario->time_last_rx_packet, NULL) == 0, "gettimeofday failed");
while (NULL != g_scenario->next_packet) {
switch (g_scenario->next_packet->sctp_hdr.chunk_type) {
case SCTP_CID_DATA :
// no init in this scenario, may be sub-scenario
if (g_scenario->next_packet->action == ET_PACKET_ACTION_S1C_SEND) {
et_scenario_schedule_tx_packet(g_scenario->next_packet);
pthread_mutex_unlock(&g_fsm_lock);
et_event_t continue_event;
continue_event.code = ET_EVENT_TICK;
et_scenario_fsm_notify_event(continue_event);
} else if (g_scenario->next_packet->action == ET_PACKET_ACTION_S1C_RECEIVE) {
if (g_scenario->next_packet->status == ET_PACKET_STATUS_RECEIVED) {
g_scenario->last_rx_packet = g_scenario->next_packet;
g_scenario->time_last_rx_packet = g_scenario->last_rx_packet->timestamp_packet;
g_scenario->next_packet = g_scenario->next_packet->next;
} else if (g_scenario->next_packet->status == ET_PACKET_STATUS_NONE) {
et_scenario_wait_rx_packet(g_scenario->next_packet);
pthread_mutex_unlock(&g_fsm_lock);
return g_fsm_state;
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
} else {
AssertFatal(0, "Invalid packet status %d", g_scenario->next_packet->status);
}
} else {
AssertFatal(0, "Invalid packet action %d", g_scenario->next_packet->action);
}
break;
case SCTP_CID_INIT:
case SCTP_CID_INIT_ACK:
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:
g_scenario->next_packet->status = ET_PACKET_STATUS_NOT_TAKEN_IN_ACCOUNT;
g_scenario->next_packet = g_scenario->next_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(g_scenario->next_packet->sctp_hdr.chunk_type));
break;
default:
g_scenario->next_packet->status = ET_PACKET_STATUS_NOT_TAKEN_IN_ACCOUNT;
g_scenario->next_packet = g_scenario->next_packet->next;
}
}
fprintf(stderr, "No Packet found in this scenario: %s\n", g_scenario->name);
g_fsm_state = ET_FSM_STATE_NULL;
pthread_mutex_unlock(&g_fsm_lock);
if (0 == g_scenario->timer_count) {
fprintf(stderr, "End of scenario: %s\n", g_scenario->name);
fflush(stderr);
fflush(stdout);
exit(0);
}
fprintf(stderr, "Remaining timers running: %d\n", g_scenario->timer_count);
break;
default:
AssertFatal(0, "Case event %d not handled in ET_FSM_STATE_CONNECTING_S1C", event.code);
}
pthread_mutex_unlock(&g_fsm_lock);
return 0;
}
//------------------------------------------------------------------------------
et_fsm_state_t et_scenario_fsm_notify_event_state_null(et_event_t event)
{

gauthier
committed
switch (event.code){
case ET_EVENT_TICK:
break;

gauthier
committed
case ET_EVENT_INIT:
AssertFatal(NULL == g_scenario, "Current scenario not ended");
g_scenario = event.u.init.scenario;
g_scenario->next_packet = g_scenario->list_packet;
g_scenario->last_rx_packet = NULL;
g_scenario->last_tx_packet = NULL;
while (NULL != g_scenario->next_packet) {
switch (g_scenario->next_packet->sctp_hdr.chunk_type) {

gauthier
committed
case SCTP_CID_DATA :
// no init in this scenario, may be sub-scenario, ...
if (g_scenario->next_packet->action == ET_PACKET_ACTION_S1C_SEND) {
et_scenario_schedule_tx_packet(g_scenario->next_packet);
pthread_mutex_unlock(&g_fsm_lock);
et_event_t continue_event;
continue_event.code = ET_EVENT_TICK;
et_scenario_fsm_notify_event(continue_event);
} else if (g_scenario->next_packet->action == ET_PACKET_ACTION_S1C_RECEIVE) {
if (g_scenario->next_packet->status == ET_PACKET_STATUS_RECEIVED) {
g_scenario->last_rx_packet = g_scenario->next_packet;
g_scenario->time_last_rx_packet = g_scenario->last_rx_packet->timestamp_packet;
g_scenario->next_packet = g_scenario->next_packet->next;
} else if (g_scenario->next_packet->status == ET_PACKET_STATUS_NONE) {
et_scenario_wait_rx_packet(g_scenario->next_packet);
pthread_mutex_unlock(&g_fsm_lock);
return g_fsm_state;
} else {
AssertFatal(0, "Invalid packet status %d", g_scenario->next_packet->status);
}

gauthier
committed
} else {
AssertFatal(0, "Invalid packet action %d", g_scenario->next_packet->action);

gauthier
committed
}
break;

gauthier
committed
case SCTP_CID_INIT:
case SCTP_CID_INIT_ACK:
g_scenario->enb_properties = (Enb_properties_array_t *)et_enb_config_get();
g_scenario->hash_old_ue_mme_id2ue_mme_id = hashtable_create (256,NULL,NULL);
g_scenario->hash_mme2association_id = hashtable_create (256,NULL,NULL);
// Try to register each eNB
g_scenario->registered_enb = 0;
g_fsm_state = ET_FSM_STATE_CONNECTING_S1C;
AssertFatal(gettimeofday(&g_scenario->time_last_tx_packet, NULL) == 0, "gettimeofday failed");
et_eNB_app_register (g_scenario->enb_properties);
pthread_mutex_unlock(&g_fsm_lock);
return g_fsm_state;

gauthier
committed
break;

gauthier
committed
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:
g_scenario->next_packet->status = ET_PACKET_STATUS_NOT_TAKEN_IN_ACCOUNT;
g_scenario->next_packet = g_scenario->next_packet->next;

gauthier
committed
break;

gauthier
committed
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(g_scenario->next_packet->sctp_hdr.chunk_type));

gauthier
committed
break;
default:
g_scenario->next_packet->status = ET_PACKET_STATUS_NOT_TAKEN_IN_ACCOUNT;
g_scenario->next_packet = g_scenario->next_packet->next;

gauthier
committed
}
}
fprintf(stderr, "No Useful packet found in this scenario: %s\n", g_scenario->name);
g_fsm_state = ET_FSM_STATE_NULL;
pthread_mutex_unlock(&g_fsm_lock);
return g_fsm_state;

gauthier
committed
break;
default:
AssertFatal(0, "Case event %d not handled in ET_FSM_STATE_NULL", event.code);
}
return 0;
}
//------------------------------------------------------------------------------
et_fsm_state_t et_scenario_fsm_notify_event(et_event_t event)

gauthier
committed
{
AssertFatal((event.code >= ET_EVENT_START) && (event.code < ET_EVENT_END), "Unknown et_event_t.code %d", event.code);
pthread_mutex_lock(&g_fsm_lock);
switch (g_fsm_state){

gauthier
committed
case ET_FSM_STATE_NULL: return et_scenario_fsm_notify_event_state_null(event); break;
case ET_FSM_STATE_CONNECTING_S1C: return et_scenario_fsm_notify_event_state_connecting_s1c(event); break;
case ET_FSM_STATE_WAITING_TX_EVENT: return et_scenario_fsm_notify_event_state_waiting_tx(event); break;
case ET_FSM_STATE_WAITING_RX_EVENT: return et_scenario_fsm_notify_event_state_waiting_rx(event); break;
case ET_FSM_STATE_RUNNING: return et_scenario_fsm_notify_event_state_running(event); break;

gauthier
committed
default:
AssertFatal(0, "Case fsm_state %d not handled", g_fsm_state);

gauthier
committed
}
pthread_mutex_unlock(&g_fsm_lock);
return g_fsm_state;