• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2016, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  * @brief
32  *   This file includes the platform-specific initializers.
33  */
34 
35 #include "platform-simulation.h"
36 
37 #if OPENTHREAD_SIMULATION_VIRTUAL_TIME == 0
38 
39 #include <arpa/inet.h>
40 #include <assert.h>
41 #include <errno.h>
42 #include <getopt.h>
43 #include <libgen.h>
44 #include <stddef.h>
45 #include <stdint.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <sys/types.h>
50 
51 #include <openthread/tasklet.h>
52 #include <openthread/platform/alarm-milli.h>
53 #include <openthread/platform/radio.h>
54 
55 #include "simul_utils.h"
56 
57 uint32_t gNodeId = 1;
58 
59 extern bool        gPlatformPseudoResetWasRequested;
60 extern otRadioCaps gRadioCaps;
61 
62 static volatile bool gTerminate = false;
63 
handleSignal(int aSignal)64 static void handleSignal(int aSignal)
65 {
66     OT_UNUSED_VARIABLE(aSignal);
67 
68     gTerminate = true;
69 }
70 
71 /**
72  * Defines the argument return values.
73  */
74 enum
75 {
76     OT_SIM_OPT_HELP               = 'h',
77     OT_SIM_OPT_ENABLE_ENERGY_SCAN = 'E',
78     OT_SIM_OPT_LOCAL_INTERFACE    = 'L',
79     OT_SIM_OPT_SLEEP_TO_TX        = 't',
80     OT_SIM_OPT_TIME_SPEED         = 's',
81     OT_SIM_OPT_LOG_FILE           = 'l',
82     OT_SIM_OPT_UNKNOWN            = '?',
83 };
84 
PrintUsage(const char * aProgramName,int aExitCode)85 static void PrintUsage(const char *aProgramName, int aExitCode)
86 {
87     fprintf(stderr,
88             "Syntax:\n"
89             "    %s [Options] NodeId\n"
90             "Options:\n"
91             "    -h --help                  Display this usage information.\n"
92             "    -L --local-interface=val   The address or name of the netif to simulate Thread radio.\n"
93             "    -E --enable-energy-scan    Enable energy scan capability.\n"
94             "    -t --sleep-to-tx           Let radio support direct transition from sleep to TX with CSMA.\n"
95             "    -s --time-speed=val        Speed up the time in simulation.\n"
96 #if (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED)
97             "    -l --log-file=name         File name to write logs.\n"
98 #endif
99             ,
100             aProgramName);
101 
102     exit(aExitCode);
103 }
104 
otSysInit(int aArgCount,char * aArgVector[])105 void otSysInit(int aArgCount, char *aArgVector[])
106 {
107     char    *endptr;
108     uint32_t speedUpFactor = 1;
109 
110     static const struct option long_options[] = {
111         {"help", no_argument, 0, OT_SIM_OPT_HELP},
112         {"enable-energy-scan", no_argument, 0, OT_SIM_OPT_ENABLE_ENERGY_SCAN},
113         {"sleep-to-tx", no_argument, 0, OT_SIM_OPT_SLEEP_TO_TX},
114         {"time-speed", required_argument, 0, OT_SIM_OPT_TIME_SPEED},
115         {"local-interface", required_argument, 0, OT_SIM_OPT_LOCAL_INTERFACE},
116 #if (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED)
117         {"log-file", required_argument, 0, OT_SIM_OPT_LOG_FILE},
118 #endif
119         {0, 0, 0, 0},
120     };
121 
122 #if (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED)
123     static const char options[] = "Ehts:L:l:";
124 #else
125     static const char options[] = "Ehts:L:";
126 #endif
127 
128     if (gPlatformPseudoResetWasRequested)
129     {
130         gPlatformPseudoResetWasRequested = false;
131         return;
132     }
133 
134     optind = 1;
135 
136     while (true)
137     {
138         int c = getopt_long(aArgCount, aArgVector, options, long_options, NULL);
139 
140         if (c == -1)
141         {
142             break;
143         }
144 
145         switch (c)
146         {
147         case OT_SIM_OPT_UNKNOWN:
148             PrintUsage(aArgVector[0], EXIT_FAILURE);
149             break;
150         case OT_SIM_OPT_HELP:
151             PrintUsage(aArgVector[0], EXIT_SUCCESS);
152             break;
153         case OT_SIM_OPT_ENABLE_ENERGY_SCAN:
154             gRadioCaps |= OT_RADIO_CAPS_ENERGY_SCAN;
155             break;
156         case OT_SIM_OPT_SLEEP_TO_TX:
157             gRadioCaps |= OT_RADIO_CAPS_SLEEP_TO_TX;
158             break;
159         case OT_SIM_OPT_LOCAL_INTERFACE:
160             gLocalInterface = optarg;
161             break;
162         case OT_SIM_OPT_TIME_SPEED:
163             speedUpFactor = (uint32_t)strtol(optarg, &endptr, 10);
164             if (*endptr != '\0' || speedUpFactor == 0)
165             {
166                 fprintf(stderr, "Invalid value for TimerSpeedUpFactor: %s\n", optarg);
167                 exit(EXIT_FAILURE);
168             }
169             break;
170 #if OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED
171         case OT_SIM_OPT_LOG_FILE:
172             platformLoggingSetFileName(optarg);
173             break;
174 #endif
175         default:
176             break;
177         }
178     }
179 
180     if (optind != aArgCount - 1)
181     {
182         PrintUsage(aArgVector[0], EXIT_FAILURE);
183     }
184 
185     gNodeId = (uint32_t)strtol(aArgVector[optind], &endptr, 0);
186 
187     if (*endptr != '\0' || gNodeId < 1 || gNodeId > MAX_NETWORK_SIZE)
188     {
189         fprintf(stderr, "Invalid NodeId: %s\n", aArgVector[optind]);
190         exit(EXIT_FAILURE);
191     }
192 
193     signal(SIGTERM, &handleSignal);
194     signal(SIGHUP, &handleSignal);
195 
196     platformLoggingInit(basename(aArgVector[0]));
197     platformAlarmInit(speedUpFactor);
198     platformRadioInit();
199 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
200     platformTrelInit(speedUpFactor);
201 #endif
202 #if OPENTHREAD_SIMULATION_IMPLEMENT_INFRA_IF && OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
203     platformInfraIfInit();
204 #endif
205     platformRandomInit();
206 }
207 
otSysPseudoResetWasRequested(void)208 bool otSysPseudoResetWasRequested(void) { return gPlatformPseudoResetWasRequested; }
209 
otSysDeinit(void)210 void otSysDeinit(void)
211 {
212     platformRadioDeinit();
213 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
214     platformTrelDeinit();
215 #endif
216 #if OPENTHREAD_SIMULATION_IMPLEMENT_INFRA_IF && OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
217     platformInfraIfDeinit();
218 #endif
219     platformLoggingDeinit();
220 }
221 
otSysProcessDrivers(otInstance * aInstance)222 void otSysProcessDrivers(otInstance *aInstance)
223 {
224     fd_set         read_fds;
225     fd_set         write_fds;
226     fd_set         error_fds;
227     int            max_fd = -1;
228     struct timeval timeout;
229     int            rval;
230 
231     FD_ZERO(&read_fds);
232     FD_ZERO(&write_fds);
233     FD_ZERO(&error_fds);
234 
235     platformUartUpdateFdSet(&read_fds, &write_fds, &error_fds, &max_fd);
236     platformAlarmUpdateTimeout(&timeout);
237     platformRadioUpdateFdSet(&read_fds, &write_fds, &timeout, &max_fd);
238 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
239     platformTrelUpdateFdSet(&read_fds, &write_fds, &timeout, &max_fd);
240 #endif
241 #if OPENTHREAD_SIMULATION_IMPLEMENT_INFRA_IF && OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
242     platformInfraIfUpdateFdSet(&read_fds, &write_fds, &max_fd);
243 #endif
244 #if OPENTHREAD_CONFIG_MULTICAST_DNS_ENABLE && OPENTHREAD_SIMULATION_MDNS_SOCKET_IMPLEMENT_POSIX
245     platformMdnsSocketUpdateFdSet(&read_fds, &max_fd);
246 #endif
247 
248 #if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
249     platformBleUpdateFdSet(&read_fds, &write_fds, &timeout, &max_fd);
250 #endif
251 
252     if (otTaskletsArePending(aInstance))
253     {
254         timeout.tv_sec  = 0;
255         timeout.tv_usec = 0;
256     }
257 
258     rval = select(max_fd + 1, &read_fds, &write_fds, &error_fds, &timeout);
259 
260     if (rval >= 0)
261     {
262         platformUartProcess();
263         platformRadioProcess(aInstance, &read_fds, &write_fds);
264 #if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
265         platformBleProcess(aInstance, &read_fds, &write_fds);
266 #endif
267     }
268     else if (errno != EINTR)
269     {
270         perror("select");
271         exit(EXIT_FAILURE);
272     }
273 
274     platformAlarmProcess(aInstance);
275 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
276     platformTrelProcess(aInstance, &read_fds, &write_fds);
277 #endif
278 #if OPENTHREAD_SIMULATION_IMPLEMENT_INFRA_IF && OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
279     platformInfraIfProcess(aInstance, &read_fds, &write_fds);
280 #endif
281 #if OPENTHREAD_CONFIG_MULTICAST_DNS_ENABLE && OPENTHREAD_SIMULATION_MDNS_SOCKET_IMPLEMENT_POSIX
282     platformMdnsSocketProcess(aInstance, &read_fds);
283 #endif
284 
285     if (gTerminate)
286     {
287         exit(0);
288     }
289 }
290 
291 #endif // OPENTHREAD_SIMULATION_VIRTUAL_TIME == 0
292