From 7512e23b59dd2544af743dd4b087ee4d9e921577 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Mon, 16 Apr 2018 13:17:00 -0700 Subject: [PATCH] [posix] enable time speed up feature (#2624) This commit adds a new feature under posix platform to emulate time (platform Alarm APIs) with a given speed up factor (i.e., as if time runs `x` times faster). The speed up factor can be given when running the NCP app as an input argument (default is 1). --- examples/platforms/posix/alarm.c | 32 ++++++++++++++------- examples/platforms/posix/platform-posix.h | 2 +- examples/platforms/posix/platform.c | 31 ++++++++++++++------ examples/platforms/posix/sim/alarm-sim.c | 3 +- examples/platforms/posix/sim/platform-sim.c | 2 +- tests/toranj/wpan.py | 14 +++++++-- 6 files changed, 60 insertions(+), 24 deletions(-) diff --git a/examples/platforms/posix/alarm.c b/examples/platforms/posix/alarm.c index 65a28d37e..9288cfdec 100644 --- a/examples/platforms/posix/alarm.c +++ b/examples/platforms/posix/alarm.c @@ -50,10 +50,13 @@ static uint32_t sMsAlarm = 0; static bool sIsUsRunning = false; static uint32_t sUsAlarm = 0; +static uint32_t sSpeedUpFactor = 1; + static struct timeval sStart; -void platformAlarmInit(void) +void platformAlarmInit(uint32_t aSpeedUpFactor) { + sSpeedUpFactor = aSpeedUpFactor; gettimeofday(&sStart, NULL); } @@ -64,7 +67,7 @@ uint32_t otPlatAlarmMilliGetNow(void) gettimeofday(&tv, NULL); timersub(&tv, &sStart, &tv); - return (uint32_t)((tv.tv_sec * MS_PER_S) + (tv.tv_usec / US_PER_MS)); + return (uint32_t)((tv.tv_sec * sSpeedUpFactor * MS_PER_S) + (tv.tv_usec * sSpeedUpFactor / US_PER_MS)); } void otPlatAlarmMilliStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt) @@ -87,7 +90,7 @@ uint32_t otPlatAlarmMicroGetNow(void) gettimeofday(&tv, NULL); timersub(&tv, &sStart, &tv); - return (uint32_t)(tv.tv_sec * US_PER_S + tv.tv_usec); + return (uint32_t)(tv.tv_sec * US_PER_S + tv.tv_usec) * sSpeedUpFactor; } void otPlatAlarmMicroStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt) @@ -128,15 +131,24 @@ void platformAlarmUpdateTimeout(struct timeval *aTimeout) aTimeout->tv_sec = 0; aTimeout->tv_usec = 0; } - else if (msRemaining * US_PER_MS < usRemaining) - { - aTimeout->tv_sec = msRemaining / MS_PER_S; - aTimeout->tv_usec = (msRemaining % MS_PER_S) * US_PER_MS; - } else { - aTimeout->tv_sec = usRemaining / US_PER_S; - aTimeout->tv_usec = usRemaining % US_PER_S; + int64_t remaining = ((int64_t)msRemaining) * US_PER_MS; + + if (usRemaining < remaining) + { + remaining = usRemaining; + } + + remaining /= sSpeedUpFactor; + + if (remaining == 0) + { + remaining = 1; + } + + aTimeout->tv_sec = remaining / US_PER_S; + aTimeout->tv_usec = remaining % US_PER_S; } } diff --git a/examples/platforms/posix/platform-posix.h b/examples/platforms/posix/platform-posix.h index 9753a334e..de7684e7c 100644 --- a/examples/platforms/posix/platform-posix.h +++ b/examples/platforms/posix/platform-posix.h @@ -114,7 +114,7 @@ extern uint32_t WELLKNOWN_NODE_ID; * This function initializes the alarm service used by OpenThread. * */ -void platformAlarmInit(void); +void platformAlarmInit(uint32_t aSpeedUpFactor); /** * This function retrieves the time remaining until the alarm fires. diff --git a/examples/platforms/posix/platform.c b/examples/platforms/posix/platform.c index b34e06abd..c75caee67 100644 --- a/examples/platforms/posix/platform.c +++ b/examples/platforms/posix/platform.c @@ -62,9 +62,10 @@ int gArgumentsCount = 0; char **gArguments = NULL; #endif -void PlatformInit(int argc, char *argv[]) +void PlatformInit(int aArgCount, char *aArgVector[]) { - char *endptr; + char * endptr; + uint32_t speedUpFactor = 1; if (gPlatformPseudoResetWasRequested) { @@ -72,28 +73,40 @@ void PlatformInit(int argc, char *argv[]) return; } - if (argc != 2) + if (aArgCount < 2) { + fprintf(stderr, "Syntax:\n %s NodeId [TimeSpeedUpFactor]\n", aArgVector[0]); exit(EXIT_FAILURE); } #ifndef _WIN32 - openlog(basename(argv[0]), LOG_PID, LOG_USER); + openlog(basename(aArgVector[0]), LOG_PID, LOG_USER); setlogmask(setlogmask(0) & LOG_UPTO(LOG_NOTICE)); - gArgumentsCount = argc; - gArguments = argv; + gArgumentsCount = aArgCount; + gArguments = aArgVector; #endif - NODE_ID = (uint32_t)strtol(argv[1], &endptr, 0); + NODE_ID = (uint32_t)strtol(aArgVector[1], &endptr, 0); if (*endptr != '\0' || NODE_ID < 1 || NODE_ID >= WELLKNOWN_NODE_ID) { - fprintf(stderr, "Invalid NODE_ID: %s\n", argv[1]); + fprintf(stderr, "Invalid NodeId: %s\n", aArgVector[1]); exit(EXIT_FAILURE); } - platformAlarmInit(); + if (aArgCount > 2) + { + speedUpFactor = (uint32_t)strtol(aArgVector[2], &endptr, 0); + + if (*endptr != '\0' || speedUpFactor == 0) + { + fprintf(stderr, "Invalid value for TimerSpeedUpFactor: %s\n", aArgVector[2]); + exit(EXIT_FAILURE); + } + } + + platformAlarmInit(speedUpFactor); platformRadioInit(); platformRandomInit(); } diff --git a/examples/platforms/posix/sim/alarm-sim.c b/examples/platforms/posix/sim/alarm-sim.c index 415826f07..19c07bb75 100644 --- a/examples/platforms/posix/sim/alarm-sim.c +++ b/examples/platforms/posix/sim/alarm-sim.c @@ -48,8 +48,9 @@ static uint32_t sMsAlarm = 0; static bool sIsUsRunning = false; static uint32_t sUsAlarm = 0; -void platformAlarmInit(void) +void platformAlarmInit(uint32_t aSpeedUpFactor) { + (void)aSpeedUpFactor; sNow = 0; } diff --git a/examples/platforms/posix/sim/platform-sim.c b/examples/platforms/posix/sim/platform-sim.c index 99337ed01..a5c389430 100644 --- a/examples/platforms/posix/sim/platform-sim.c +++ b/examples/platforms/posix/sim/platform-sim.c @@ -199,7 +199,7 @@ void PlatformInit(int argc, char *argv[]) socket_init(); - platformAlarmInit(); + platformAlarmInit(1); platformRadioInit(); platformRandomInit(); } diff --git a/tests/toranj/wpan.py b/tests/toranj/wpan.py index 5a7e48c76..2881ce8b0 100644 --- a/tests/toranj/wpan.py +++ b/tests/toranj/wpan.py @@ -173,7 +173,8 @@ def _log(text, new_line=True, flush=True): class Node(object): """ A wpantund OT NCP instance """ - _VERBOSE = False # defines the default verbosity setting (can be changed per `Node`) + _VERBOSE = False # defines the default verbosity setting (can be changed per `Node`) + _SPEED_UP_FACTOR = 1 # defines the default time speed up factor # path to `wpantund`, `wpanctl` and `ot-ncp-ftd` code _WPANTUND = '/usr/local/sbin/wpantund' @@ -200,8 +201,10 @@ class Node(object): self._interface_name = self._INTFC_NAME_PREFIX + str(index) self._verbose = verbose + ncp_socket_path = 'system:{} {} {}'.format(self._OT_NCP_FTD, index, self._SPEED_UP_FACTOR) + cmd = self._WPANTUND + \ - ' -o Config:NCP:SocketPath \"system:{} {}\"'.format(self._OT_NCP_FTD, index) + \ + ' -o Config:NCP:SocketPath \"{}\"'.format(ncp_socket_path) + \ ' -o Config:TUN:InterfaceName {}'.format(self._interface_name) + \ ' -o Config:NCP:DriverName spinel' + \ ' -o Daemon:SyslogMask \"all -debug\"' @@ -424,6 +427,13 @@ class Node(object): break time.sleep(0.4) + @classmethod + def set_time_speedup_factor(cls, factor): + """Sets up the time speed up factor - should be set before creating any `Node` objects""" + if len(Node._all_nodes) != 0: + raise Node._NodeError('set_time_speedup_factor() cannot be called after creating a `Node`') + Node._SPEED_UP_FACTOR = factor + #------------------------------------------------------------------------------------------------------------------ # IPv6 message Sender and Receiver class