diff --git a/openair3/TEST/EPC_TEST/play_scenario.c b/openair3/TEST/EPC_TEST/play_scenario.c
index 21aca820c280ddd7f9a1ce93f8769cdda280a720..d85faf4c2cec17fcfa24d16f17acd562b7aa37ec 100644
--- a/openair3/TEST/EPC_TEST/play_scenario.c
+++ b/openair3/TEST/EPC_TEST/play_scenario.c
@@ -130,6 +130,54 @@ int et_strip_extension(char *in_filename)
 }
 //------------------------------------------------------------------------------
 // return number of splitted items
+void et_get_shift_arg( char * line_argument, shift_packet_t * const shift)
+{
+  int  len       = strlen(line_argument);
+  int  i         = 0;
+  int  j         = 0;
+  int  num_milli = 0;
+  char my_num[64];
+  int  negative  = 0;
+
+
+  while ((line_argument[i] != ':') && (i < len)) {
+    my_num[i] = line_argument[i];
+    i += 1;
+  }
+  my_num[i++] = '\0';
+  shift->frame_number = atoi(my_num);
+  AssertFatal(i<len, "Shift argument %s bad format", line_argument);
+
+  if (line_argument[i] == '-') {
+    negative = 1;
+    i += 1;
+  } else if (line_argument[i] == '+') {
+    i += 1;
+  }
+  AssertFatal(i<len, "Shift argument %s bad format", line_argument);
+  while ((line_argument[i] != '.') && (i < len)) {
+    my_num[j++] = line_argument[i++];
+  }
+  my_num[j] = '\0';
+  j = 0;
+  i += 1;
+  shift->shift_seconds = atoi(my_num);
+  // may omit .mmm, accept .m or .mm or .mmm or ...
+  while ((i < len) && (num_milli++ < 3)){
+    my_num[j++] = line_argument[i++];
+  }
+  while (num_milli++ < 6){
+    my_num[j++] = '0';
+  }
+  my_num[j] = '\0';
+  shift->shift_microseconds = atoi(my_num);
+  if (negative == 1) {
+    shift->shift_seconds      = - shift->shift_seconds;
+    shift->shift_microseconds = - shift->shift_microseconds;
+  }
+}
+//------------------------------------------------------------------------------
+// return number of splitted items
 int split_path( char * pathP, char *** resP)
 {
   char *  saveptr1;
@@ -764,9 +812,168 @@ void *et_eNB_app_task(void *args_p)
 }
 
 //------------------------------------------------------------------------------
-int et_play_scenario(et_scenario_t* const scenario)
+int et_play_scenario(et_scenario_t* const scenario, const struct shift_packet_s *shifts)
 {
-  et_event_t        event;
+  et_event_t             event;
+  struct shift_packet_s *shift                 = shifts;
+  et_packet_t           *packet                = NULL;
+  et_packet_t           *next_packet           = NULL;
+  struct timeval         shift_all_packets     = { .tv_sec = 0, .tv_usec = 0 };
+  struct timeval         relative_last_sent_packet     = { .tv_sec = 0, .tv_usec = 0 };
+  struct timeval         relative_last_received_packet = { .tv_sec = 0, .tv_usec = 0 };
+  struct timeval         initial_time          = { .tv_sec = 0, .tv_usec = 0 };
+  char                   first_packet          = 1;
+  char                   first_sent_packet     = 1;
+  char                   first_received_packet = 1;
+
+  // first apply timing shifts if requested
+  while (shift) {
+    packet = scenario->list_packet;
+    while (packet) {
+      fprintf(stdout, "*shift: %p\n", shift);
+      fprintf(stdout, "\tframe_number:       %p\n", shift->frame_number);
+      fprintf(stdout, "\tshift_seconds:      %ld\n", shift->shift_seconds);
+      fprintf(stdout, "\tshift_microseconds: %ld\n", shift->shift_microseconds);
+      fprintf(stdout, "\tsingle:             %d\n\n", shift->single);
+      fprintf(stdout, "\tshift_all_packets_seconds:      %ld\n", shift_all_packets.tv_sec);
+      fprintf(stdout, "\tshift_all_packets_microseconds: %ld\n", shift_all_packets.tv_usec);
+
+      AssertFatal((packet->time_relative_to_first_packet.tv_sec >= 0) && (packet->time_relative_to_first_packet.tv_usec >= 0),
+          "Bad timing result time_relative_to_first_packet=%d.%d packet num %u, original frame number %u",
+          packet->time_relative_to_first_packet.tv_sec,
+          packet->time_relative_to_first_packet.tv_usec,
+          packet->packet_number,
+          packet->original_frame_number);
+      AssertFatal((packet->time_relative_to_last_received_packet.tv_sec >= 0) && (packet->time_relative_to_last_received_packet.tv_usec >= 0),
+          "Bad timing result time_relative_to_last_received_packet=%d.%d packet num %u, original frame number %u",
+          packet->time_relative_to_last_received_packet.tv_sec,
+          packet->time_relative_to_last_received_packet.tv_usec,
+          packet->packet_number,
+          packet->original_frame_number);
+      AssertFatal((packet->time_relative_to_last_sent_packet.tv_sec >= 0) && (packet->time_relative_to_last_sent_packet.tv_usec >= 0),
+          "Bad timing result time_relative_to_last_sent_packet=%d.%d packet num %u, original frame number %u",
+          packet->time_relative_to_last_sent_packet.tv_sec,
+          packet->time_relative_to_last_sent_packet.tv_usec,
+          packet->packet_number,
+          packet->original_frame_number);
+      fprintf(stdout, "\tpacket num %u, original frame number %u time_relative_to_first_packet=%d.%d\n",
+          packet->packet_number,
+          packet->original_frame_number,
+          packet->time_relative_to_first_packet.tv_sec,
+          packet->time_relative_to_first_packet.tv_usec);
+      fprintf(stdout, "\tpacket num %u, original frame number %u time_relative_to_last_received_packet=%d.%d\n",
+          packet->packet_number,
+          packet->original_frame_number,
+          packet->time_relative_to_last_received_packet.tv_sec,
+          packet->time_relative_to_last_received_packet.tv_usec);
+      fprintf(stdout, "\tpacket num %u, original frame number %u time_relative_to_last_sent_packet=%d.%d\n",
+          packet->packet_number,
+          packet->original_frame_number,
+          packet->time_relative_to_last_sent_packet.tv_sec,
+          packet->time_relative_to_last_sent_packet.tv_usec);
+
+      if ((shift->single) && (shift->frame_number == packet->original_frame_number)) {
+        struct timeval t_offset     = { .tv_sec = shift->shift_seconds, .tv_usec = shift->shift_microseconds };
+        et_packet_shift_timing(packet, &t_offset);
+        next_packet = packet->next;
+        if (next_packet) {
+          t_offset.tv_sec  = -t_offset.tv_sec;
+          t_offset.tv_usec = -t_offset.tv_usec;
+
+          if (packet->action == ET_PACKET_ACTION_S1C_SEND) {
+            timeval_add(&next_packet->time_relative_to_last_sent_packet, &next_packet->time_relative_to_last_sent_packet, &t_offset);
+          } else if (packet->action == ET_PACKET_ACTION_S1C_RECEIVE) {
+            timeval_add(&next_packet->time_relative_to_last_received_packet, &next_packet->time_relative_to_last_received_packet, &t_offset);
+          }
+        }
+      }
+      if ((0 == shift->single) && (shift->frame_number == packet->original_frame_number)) {
+        shift_all_packets.tv_sec = shift->shift_seconds;
+        shift_all_packets.tv_usec = shift->shift_microseconds;
+        timeval_add(&packet->time_relative_to_first_packet, &packet->time_relative_to_first_packet, &shift_all_packets);
+        fprintf(stdout, "\tpacket num %u, now original frame number %u time_relative_to_first_packet=%d.%d\n",
+            packet->packet_number,
+            packet->original_frame_number,
+            packet->time_relative_to_first_packet.tv_sec,
+            packet->time_relative_to_first_packet.tv_usec);
+        AssertFatal((packet->time_relative_to_first_packet.tv_sec >= 0) && (packet->time_relative_to_first_packet.tv_usec >= 0),
+            "Bad timing result time_relative_to_first_packet=%d.%d packet num %u, original frame number %u",
+            packet->time_relative_to_first_packet.tv_sec,
+            packet->time_relative_to_first_packet.tv_usec,
+            packet->packet_number,
+            packet->original_frame_number);
+      } else if ((0 == shift->single)  && (shift->frame_number < packet->original_frame_number)) {
+        timeval_add(&packet->time_relative_to_first_packet, &packet->time_relative_to_first_packet, &shift_all_packets);
+        fprintf(stdout, "\tpacket num %u, now original frame number %u time_relative_to_first_packet=%d.%d\n",
+            packet->packet_number,
+            packet->original_frame_number,
+            packet->time_relative_to_first_packet.tv_sec,
+            packet->time_relative_to_first_packet.tv_usec);
+        AssertFatal((packet->time_relative_to_first_packet.tv_sec >= 0) && (packet->time_relative_to_first_packet.tv_usec >= 0),
+            "Bad timing result time_relative_to_first_packet=%d.%d packet num %u, original frame number %u",
+            packet->time_relative_to_first_packet.tv_sec,
+            packet->time_relative_to_first_packet.tv_usec,
+            packet->packet_number,
+            packet->original_frame_number);
+      }
+      packet = packet->next;
+    }
+    shift = shift->next;
+  }
+  // now recompute time_relative_to_last_received_packet, time_relative_to_last_sent_packet
+  if (shifts) {
+    packet = scenario->list_packet;
+    while (packet) {
+      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;
+        }
+        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;
+          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;
+        }
+        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);
+        }
+      }
+      packet = packet->next;
+    }
+  }
   et_display_scenario(scenario);
 
   // create SCTP ITTI task: same as eNB code
@@ -804,16 +1011,16 @@ static void et_usage (
   fprintf (stdout, "Please report any bug to: %s\n",PACKAGE_BUGREPORT);
   fprintf (stdout, "Usage: %s [options]\n\n", argv[0]);
   fprintf (stdout, "\n");
-  //fprintf (stdout, "Client options:\n");
-  //fprintf (stdout, "\t-S | --server         <server network @>  File name (with no path) of a test scenario that has to be replayed (TODO in future?)\n");
-  //fprintf (stdout, "Server options:\n");
-  fprintf (stdout, "\t-d | --test-dir       <dir>               Directory where a set of files related to a particular test are located\n");
-  fprintf (stdout, "\t-c | --enb-conf-file  <file>              Provide an eNB config file, valid for the testbed\n");
-  fprintf (stdout, "\t-s | --scenario       <file>              File name (with no path) of a test scenario that has to be replayed ()\n");
+  fprintf (stdout, "\t-d | --test-dir       <dir>                  Directory where a set of files related to a particular test are located\n");
+  fprintf (stdout, "\t-c | --enb-conf-file  <file>                 Provide an eNB config file, valid for the testbed\n");
+  fprintf (stdout, "\t-f | --shift-packet   <frame:[+|-]seconds[.usec]> Shift the timing of a packet'\n");
+  fprintf (stdout, "\t-F | --shift-packets  <frame:[+|-]seconds[.usec]> Shift the timing of packets starting at frame 'frame' included\n");
+  fprintf (stdout, "\t-m | --max-speed                             Play scenario as fast as possible without respecting frame timings\n");
+  fprintf (stdout, "\t-s | --scenario       <file>                 File name (with no path) of a test scenario that has to be replayed ()\n");
   fprintf (stdout, "\n");
   fprintf (stdout, "Other options:\n");
-  fprintf (stdout, "\t-h | --help                               Print this help and return\n");
-  fprintf (stdout, "\t-v | --version                            Print informations about the version of this executable\n");
+  fprintf (stdout, "\t-h | --help                                  Print this help and return\n");
+  fprintf (stdout, "\t-v | --version                               Print informations about the version of this executable\n");
   fprintf (stdout, "\n");
 }
 
@@ -824,11 +1031,13 @@ et_config_parse_opt_line (
   char *argv[],
   char **et_dir_name,
   char **scenario_file_name,
-  char **enb_config_file_name)
+  char **enb_config_file_name,
+  shift_packet_t **shifts)
 //------------------------------------------------------------------------------
 {
-  int                           option;
-  int                           rv                   = 0;
+  int                 option   = 0;
+  int                 rv       = 0;
+  shift_packet_t      *shift   = NULL;
 
   enum long_option_e {
     LONG_OPTION_START = 0x100, /* Start after regular single char options */
@@ -836,6 +1045,8 @@ et_config_parse_opt_line (
     LONG_OPTION_SCENARIO_FILE,
     LONG_OPTION_MAX_SPEED,
     LONG_OPTION_TEST_DIR,
+    LONG_OPTION_SHIFT_PACKET,
+    LONG_OPTION_SHIFT_PACKETS,
     LONG_OPTION_HELP,
     LONG_OPTION_VERSION
   };
@@ -845,6 +1056,8 @@ et_config_parse_opt_line (
     {"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},
+    {"shift-packet",   required_argument, 0, LONG_OPTION_SHIFT_PACKET},
+    {"shift-packets",  required_argument, 0, LONG_OPTION_SHIFT_PACKETS},
     {"help",           no_argument,       0, LONG_OPTION_HELP},
     {"version",        no_argument,       0, LONG_OPTION_VERSION},
      {NULL, 0, NULL, 0}
@@ -853,7 +1066,7 @@ et_config_parse_opt_line (
   /*
    * Parsing command line
    */
-  while ((option = getopt_long (argc, argv, "vhmc:s:d:", long_options, NULL)) != -1) {
+  while ((option = getopt_long (argc, argv, "vhmc:s:d:f:F", long_options, NULL)) != -1) {
     switch (option) {
       case LONG_OPTION_ENB_CONF_FILE:
       case 'c':
@@ -885,6 +1098,37 @@ et_config_parse_opt_line (
         }
         break;
 
+      case LONG_OPTION_SHIFT_PACKET:
+      case 'f':
+        if (optarg) {
+          if (NULL == *shifts) {
+            shift = calloc(1, sizeof (*shift));
+            *shifts = shift;
+          } else {
+            shift->next = calloc(1, sizeof (*shift));
+            shift = shift->next;
+          }
+          shift->single = 1;
+          et_get_shift_arg(optarg, shift);
+          printf("Arg Shift packet %s\n", optarg);
+        }
+        break;
+
+      case LONG_OPTION_SHIFT_PACKETS:
+      case 'F':
+        if (optarg) {
+          if (NULL == *shifts) {
+            shift = calloc(1, sizeof (*shift));
+            *shifts = shift;
+          } else {
+            shift->next = calloc(1, sizeof (*shift));
+            shift = shift->next;
+          }
+          et_get_shift_arg(optarg, shift);
+          printf("Arg Shift packets %s\n", optarg);
+        }
+        break;
+
       case LONG_OPTION_MAX_SPEED:
       case 'm':
         g_max_speed = 1;
@@ -938,6 +1182,7 @@ int main( int argc, char **argv )
   char            *et_dir_name          = NULL;
   char            *scenario_file_name   = NULL;
   char            *enb_config_file_name = NULL;
+  struct shift_packet_s *shifts         = NULL;
   int              ret                  = 0;
   et_scenario_t   *scenario             = NULL;
   char             play_scenario_filename[NAME_MAX];
@@ -957,11 +1202,11 @@ int main( int argc, char **argv )
   asn1_xer_print = 1;
 
   //parameters
-  actions = et_config_parse_opt_line (argc, argv, &et_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, &shifts); //Command-line options
   if  (actions & PLAY_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);
+        ret = et_play_scenario(scenario, shifts);
       } else {
         fprintf(stderr, "ERROR: Could not generate scenario from tsml file\n");
         ret = -1;
diff --git a/openair3/TEST/EPC_TEST/play_scenario.h b/openair3/TEST/EPC_TEST/play_scenario.h
index 0391ac5c472382a4a3ca6f1884a4011b2bd13b91..ca569e514180318ae7f4305b78ed12c3e46c46a0 100644
--- a/openair3/TEST/EPC_TEST/play_scenario.h
+++ b/openair3/TEST/EPC_TEST/play_scenario.h
@@ -89,6 +89,15 @@
 #define ENB_CONFIG_STRING_ENB_PORT_FOR_S1U              "ENB_PORT_FOR_S1U"
 
 
+typedef struct shift_packet_s {
+  unsigned int           frame_number;
+  int                    shift_seconds;
+  int                    shift_microseconds;
+  int                    single;            // only this packet
+  struct shift_packet_s *next;
+} shift_packet_t;
+
+
 typedef struct mme_ip_address_s {
   unsigned  ipv4:1;
   unsigned  ipv6:1;
@@ -445,6 +454,10 @@ int et_generate_xml_scenario(
     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 * const 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);
@@ -458,7 +471,7 @@ void et_parse_sctp_init_chunk(xmlDocPtr doc, const xmlNode const *sctp_node, sct
 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 );
+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);
@@ -471,6 +484,7 @@ asn_comp_rval_t * et_sctp_is_matching(et_sctp_hdr_t * const sctp1, et_sctp_hdr_t
 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);
@@ -486,6 +500,6 @@ 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);
+int et_play_scenario(et_scenario_t* const scenario, const struct shift_packet_s *shifts);
 
 #endif /* PLAY_SCENARIO_H_ */
diff --git a/openair3/TEST/EPC_TEST/play_scenario_fsm.c b/openair3/TEST/EPC_TEST/play_scenario_fsm.c
index a8f7e7331f1ba8a1d14f6db122623b688c967b19..dece907deee706a52055c0feac304a9ef33abfcb 100644
--- a/openair3/TEST/EPC_TEST/play_scenario_fsm.c
+++ b/openair3/TEST/EPC_TEST/play_scenario_fsm.c
@@ -54,36 +54,35 @@ 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;
 //------------------------------------------------------------------------------
-int timeval_subtract (struct timeval * const result, struct timeval * const a, struct timeval * const b)
+// 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)
 {
-  struct timeval  b2;
-  int nsec = 0;
-  b2.tv_sec   = b->tv_sec;
-  b2.tv_usec = b->tv_usec;
-
-
-  /* Perform the carry for the later subtraction by updating y. */
-  if (a->tv_usec < b2.tv_usec) {
-    nsec = (b2.tv_usec - a->tv_usec) / 1000000 + 1;
-    b2.tv_usec -= 1000000 * nsec;
-    b2.tv_sec += nsec;
+  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);
   }
-  if (a->tv_usec - b2.tv_usec > 1000000) {
-    nsec = (a->tv_usec - b2.tv_usec) / 1000000;
-    b2.tv_usec += 1000000 * nsec;
-    b2.tv_sec -= nsec;
-  }
-
-  /* Compute the time remaining to wait.
-     tv_usec is certainly positive. */
-  result->tv_sec = a->tv_sec - b2.tv_sec;
-  result->tv_usec = a->tv_usec - b2.tv_usec;
-
-  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 a->tv_sec < b2.tv_sec;
 }
 
+//------------------------------------------------------------------------------
+// it is assumed that if a time is negative tv_sec and tv_usec are both negative
+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;
+}
 
 //------------------------------------------------------------------------------
 void et_scenario_wait_rx_packet(et_packet_t * const packet)
@@ -137,10 +136,9 @@ void et_scenario_schedule_tx_packet(et_packet_t * const packet)
       }
       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;
+        if (offset.tv_sec < 0) {
+          offset.tv_sec = -offset.tv_sec;
+          offset.tv_usec = -offset.tv_usec;
         }
 
         LOG_D(ENB_APP, "Send packet num %u original frame number %u in %ld.%06d sec\n",
diff --git a/openair3/TEST/EPC_TEST/play_scenario_parse.c b/openair3/TEST/EPC_TEST/play_scenario_parse.c
index 4004dd507499e9ed3884010c45c481f2b9765cbc..11dac34f0a451f48c71e11638945c10d282e3d36 100644
--- a/openair3/TEST/EPC_TEST/play_scenario_parse.c
+++ b/openair3/TEST/EPC_TEST/play_scenario_parse.c
@@ -62,7 +62,7 @@ extern Enb_properties_array_t g_enb_properties;
 //------------------------------------------------------------------------------
 void et_parse_s1ap(xmlDocPtr doc, const xmlNode const *s1ap_node, et_s1ap_t * const s1ap)
 {
-  xmlNode              *cur_node  = NULL;
+  xmlNodePtr            cur_node  = NULL;
   xmlChar              *xml_char  = NULL;
   xmlChar              *xml_char2  = NULL;
   unsigned int          size = 0;
@@ -329,9 +329,38 @@ void et_parse_sctp(xmlDocPtr doc, const xmlNode const *sctp_node, et_sctp_hdr_t
   }
 }
 //------------------------------------------------------------------------------
-et_packet_t* et_parse_xml_packet(xmlDocPtr doc, xmlNodePtr node) {
+void et_packet_shift_timing(et_packet_t * const packet, const struct timeval * const shift)
+{
+  timeval_add(&packet->time_relative_to_first_packet, &packet->time_relative_to_first_packet, shift);
+  AssertFatal((packet->time_relative_to_first_packet.tv_sec >= 0) && (packet->time_relative_to_first_packet.tv_usec >= 0),
+      "Bad timing result time_relative_to_first_packet=%d.%d packet num %u, original frame number %u",
+      packet->time_relative_to_first_packet.tv_sec,
+      packet->time_relative_to_first_packet.tv_usec,
+      packet->packet_number,
+      packet->original_frame_number);
+
+  timeval_add(&packet->time_relative_to_last_received_packet, &packet->time_relative_to_last_received_packet, shift);
+  AssertFatal((packet->time_relative_to_last_received_packet.tv_sec >= 0) && (packet->time_relative_to_last_received_packet.tv_usec >= 0),
+      "Bad timing result time_relative_to_last_received_packet=%d.%d packet num %u, original frame number %u",
+      packet->time_relative_to_last_received_packet.tv_sec,
+      packet->time_relative_to_last_received_packet.tv_usec,
+      packet->packet_number,
+      packet->original_frame_number);
+
+  timeval_add(&packet->time_relative_to_last_sent_packet, &packet->time_relative_to_last_sent_packet, shift);
+  AssertFatal((packet->time_relative_to_last_sent_packet.tv_sec >= 0) && (packet->time_relative_to_last_sent_packet.tv_usec >= 0),
+      "Bad timing result time_relative_to_last_sent_packet=%d.%d packet num %u, original frame number %u",
+      packet->time_relative_to_last_sent_packet.tv_sec,
+      packet->time_relative_to_last_sent_packet.tv_usec,
+      packet->packet_number,
+      packet->original_frame_number);
+}
 
-  et_packet_t        *packet   = NULL;
+//------------------------------------------------------------------------------
+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;
@@ -343,6 +372,7 @@ et_packet_t* et_parse_xml_packet(xmlDocPtr doc, xmlNodePtr node) {
   static char           first_received_packet = 1;
   static unsigned int   packet_number = 1;
 
+
   if (NULL != node) {
     packet = calloc(1, sizeof(*packet));
 
@@ -441,15 +471,15 @@ et_packet_t* et_parse_xml_packet(xmlDocPtr doc, xmlNodePtr node) {
 }
 //------------------------------------------------------------------------------
 et_scenario_t* et_generate_scenario(
-    const char  * const tsml_out_scenario_filename )
+    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;
+  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) {
diff --git a/openair3/TEST/EPC_TEST/play_scenario_s1ap.c b/openair3/TEST/EPC_TEST/play_scenario_s1ap.c
index 6a39397f19acde6b321cfacccba483a7c07c97e5..285b883ded865e9a2181bb576506670109bab65b 100644
--- a/openair3/TEST/EPC_TEST/play_scenario_s1ap.c
+++ b/openair3/TEST/EPC_TEST/play_scenario_s1ap.c
@@ -68,7 +68,6 @@ int et_s1ap_eNB_compare_assoc_id(
     if (p1->cnx_id < p2->cnx_id) {
       return -1;
     }
-
     if (p1->cnx_id > p2->cnx_id) {
       return 1;
     }
@@ -76,7 +75,6 @@ int et_s1ap_eNB_compare_assoc_id(
     if (p1->assoc_id < p2->assoc_id) {
       return -1;
     }
-
     if (p1->assoc_id > p2->assoc_id) {
       return 1;
     }
diff --git a/openair3/TEST/EPC_TEST/play_scenario_s1ap_compare_ie.c b/openair3/TEST/EPC_TEST/play_scenario_s1ap_compare_ie.c
index 31d784b2bdc4c62fb536782350aed65cb8f17280..32b571f823d47f6fd65939feec813f8b451a6115 100644
--- a/openair3/TEST/EPC_TEST/play_scenario_s1ap_compare_ie.c
+++ b/openair3/TEST/EPC_TEST/play_scenario_s1ap_compare_ie.c
@@ -586,7 +586,6 @@ int et_s1ap_update_mme_ue_s1ap_id(et_packet_t * const packet, const S1ap_MME_UE_
 {
 
 
-  xmlNode              *cur_node = NULL;
   xmlChar              xpath_expression[ET_XPATH_EXPRESSION_MAX_LENGTH];
   int                  ret       = 0;
   xmlDocPtr            doc       = NULL;