Skip to content

Commit f88e65d

Browse files
committed
pkg/openthread: fix error handling and synchronization
Previously, there was zero error handling in the ot_command_t commands provided in pkg/openthread/contrib/platform_functions_wrapper.c - ignoring the return value even of functions that are marked with `OT_MUST_USE_RESULT`. In addition, `ot_call_command()` never synchronized with the thread executing the command before return the value. Given that there was no error handling anyways, this likely was never noticed. But now that the commands actually report an error, it is of utmost importance to actually wait for the command to complete before checking the commands return value.
1 parent 76bd03d commit f88e65d

File tree

3 files changed

+124
-99
lines changed

3 files changed

+124
-99
lines changed

pkg/openthread/contrib/netdev/openthread_netdev.c

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@ static void _event_cb(netdev_t *dev, netdev_event_t event) {
7777
}
7878
}
7979

80+
static void *_error_msg_and_return_null(const char *fn, otError err)
81+
{
82+
printf("Call to %s() failed with error code %d\n", fn, (int)err);
83+
return NULL;
84+
}
85+
8086
static void *_openthread_event_loop(void *arg)
8187
{
8288
_dev = arg;
@@ -98,12 +104,25 @@ static void *_openthread_event_loop(void *arg)
98104
/* Init default parameters */
99105
otPanId panid = OPENTHREAD_PANID;
100106
uint8_t channel = OPENTHREAD_CHANNEL;
101-
otLinkSetPanId(sInstance, panid);
102-
otLinkSetChannel(sInstance, channel);
107+
otError err;
108+
err = otLinkSetPanId(sInstance, panid);
109+
if (err != OT_ERROR_NONE) {
110+
return _error_msg_and_return_null("otLinkSetPanId", err);
111+
}
112+
err = otLinkSetChannel(sInstance, channel);
113+
if (err != OT_ERROR_NONE) {
114+
return _error_msg_and_return_null("otLinkSetChannel", err);
115+
}
103116
/* Bring up the IPv6 interface */
104-
otIp6SetEnabled(sInstance, true);
117+
err = otIp6SetEnabled(sInstance, true);
118+
if (err != OT_ERROR_NONE) {
119+
return _error_msg_and_return_null("otIp6SetEnabled", err);
120+
}
105121
/* Start Thread protocol operation */
106-
otThreadSetEnabled(sInstance, true);
122+
err = otThreadSetEnabled(sInstance, true);
123+
if (err != OT_ERROR_NONE) {
124+
return _error_msg_and_return_null("otThreadSetEnabled", err);
125+
}
107126
#else
108127
/* enable OpenThread UART */
109128
otPlatUartEnable();

pkg/openthread/contrib/platform_functions_wrapper.c

Lines changed: 99 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -29,26 +29,24 @@
2929
#define ENABLE_DEBUG 0
3030
#include "debug.h"
3131

32-
typedef uint8_t OT_COMMAND;
33-
34-
static OT_COMMAND ot_channel(otInstance *ot_instance, void *arg, void *answer);
35-
static OT_COMMAND ot_eui64(otInstance *ot_instance, void *arg, void *answer);
36-
static OT_COMMAND ot_extaddr(otInstance *ot_instance, void *arg, void *answer);
37-
static OT_COMMAND ot_ipaddr(otInstance *ot_instance, void *arg, void *answer);
38-
static OT_COMMAND ot_masterkey(otInstance *ot_instance, void *arg, void *answer);
39-
static OT_COMMAND ot_networkname(otInstance *ot_instance, void *arg, void *answer);
40-
static OT_COMMAND ot_mode(otInstance *ot_instance, void *arg, void *answer);
41-
static OT_COMMAND ot_panid(otInstance *ot_instance, void *arg, void *answer);
42-
static OT_COMMAND ot_parent(otInstance *ot_instance, void *arg, void *answer);
43-
static OT_COMMAND ot_state(otInstance *ot_instance, void *arg, void *answer);
44-
static OT_COMMAND ot_thread(otInstance *ot_instance, void *arg, void *answer);
32+
static otError ot_channel(otInstance *ot_instance, void *arg, void *answer);
33+
static otError ot_eui64(otInstance *ot_instance, void *arg, void *answer);
34+
static otError ot_extaddr(otInstance *ot_instance, void *arg, void *answer);
35+
static otError ot_ipaddr(otInstance *ot_instance, void *arg, void *answer);
36+
static otError ot_masterkey(otInstance *ot_instance, void *arg, void *answer);
37+
static otError ot_networkname(otInstance *ot_instance, void *arg, void *answer);
38+
static otError ot_mode(otInstance *ot_instance, void *arg, void *answer);
39+
static otError ot_panid(otInstance *ot_instance, void *arg, void *answer);
40+
static otError ot_parent(otInstance *ot_instance, void *arg, void *answer);
41+
static otError ot_state(otInstance *ot_instance, void *arg, void *answer);
42+
static otError ot_thread(otInstance *ot_instance, void *arg, void *answer);
4543

4644
/**
4745
* @brief Struct containing an OpenThread job command
4846
*/
4947
typedef struct {
5048
const char *name; /**< A pointer to the job name string. */
51-
OT_COMMAND (*function)(otInstance *, void *, void *); /**< function to be called */
49+
otError (*function)(otInstance *, void *, void *); /**< function to be called */
5250
} ot_command_t;
5351

5452
static const ot_command_t otCommands[] =
@@ -80,33 +78,34 @@ static const ot_command_t otCommands[] =
8078
static void _exec_cmd(event_t *event) {
8179
ot_job_t *job = container_of(event, ot_job_t, ev);
8280

83-
uint8_t res = 0xFF;
8481
/* Check running thread */
8582
for (uint8_t i = 0; i < ARRAY_SIZE(otCommands); i++) {
8683
if (strcmp(job->command, otCommands[i].name) == 0) {
87-
res = (*otCommands[i].function)(openthread_get_instance(), job->arg, job->answer);
88-
break;
84+
job->retval = (*otCommands[i].function)(openthread_get_instance(), job->arg, job->answer);
85+
return;
8986
}
9087
}
91-
if (res == 0xFF) {
92-
DEBUG_PUTS("Wrong ot_COMMAND name");
93-
res = 1;
94-
}
95-
job->status = res;
88+
89+
DEBUG_PUTS("Wrong ot_COMMAND name");
90+
job->retval = OT_ERROR_INVALID_COMMAND;
9691
}
9792

9893
uint8_t ot_call_command(char *command, void *arg, void *answer)
9994
{
10095
ot_job_t job = {
10196
.ev.handler = _exec_cmd,
97+
.mutex = MUTEX_INIT_LOCKED,
10298
};
10399

104100
job.command = command;
105101
job.arg = arg;
106102
job.answer = answer;
107103

108104
event_post(openthread_get_evq(), &job.ev);
109-
return job.status;
105+
/* wait for OT thread to complete the command */
106+
mutex_lock(&job.mutex);
107+
108+
return job.retval != OT_ERROR_NONE;
110109
}
111110

112111
static void output_bytes(const char *name, const uint8_t *aBytes, uint8_t aLength)
@@ -120,50 +119,49 @@ static void output_bytes(const char *name, const uint8_t *aBytes, uint8_t aLengt
120119
}
121120
}
122121

123-
static OT_COMMAND ot_channel(otInstance *ot_instance, void *arg, void *answer) {
122+
static otError ot_channel(otInstance *ot_instance, void *arg, void *answer) {
124123
if (answer != NULL) {
125124
*((uint8_t *) answer) = otLinkGetChannel(ot_instance);
126125
DEBUG("Channel: %04x\n", *((uint8_t *)answer));
127126
}
128127
else if (arg != NULL) {
129128
uint8_t channel = *((uint8_t *)arg);
130-
otLinkSetChannel(ot_instance, channel);
129+
return otLinkSetChannel(ot_instance, channel);
131130
}
132-
else {
133-
DEBUG_PUTS("ERROR: wrong argument");
134-
}
135-
return 0;
131+
132+
DEBUG_PUTS("ERROR: wrong argument");
133+
return OT_ERROR_INVALID_ARGS;
136134
}
137135

138-
static OT_COMMAND ot_eui64(otInstance *ot_instance, void *arg, void *answer) {
136+
static otError ot_eui64(otInstance *ot_instance, void *arg, void *answer) {
139137
(void)arg;
140138

141139
if (answer != NULL) {
142140
otExtAddress address;
143141
otLinkGetFactoryAssignedIeeeEui64(ot_instance, &address);
144142
output_bytes("eui64", address.m8, OT_EXT_ADDRESS_SIZE);
145143
*((otExtAddress *)answer) = address;
144+
return OT_ERROR_NONE;
146145
}
147-
else {
148-
DEBUG_PUTS("ERROR: wrong argument");
149-
}
150-
return 0;
146+
147+
DEBUG_PUTS("ERROR: wrong argument");
148+
return OT_ERROR_INVALID_ARGS;
151149
}
152150

153-
static OT_COMMAND ot_extaddr(otInstance *ot_instance, void *arg, void *answer) {
151+
static otError ot_extaddr(otInstance *ot_instance, void *arg, void *answer) {
154152
(void)arg;
155153

156154
if (answer != NULL) {
157155
answer = (void*)otLinkGetExtendedAddress(ot_instance);
158156
output_bytes("extaddr", (const uint8_t *)answer, OT_EXT_ADDRESS_SIZE);
157+
return OT_ERROR_NONE;
159158
}
160-
else {
161-
DEBUG_PUTS("ERROR: wrong argument");
162-
}
163-
return 0;
159+
160+
DEBUG_PUTS("ERROR: wrong argument");
161+
return OT_ERROR_INVALID_ARGS;
164162
}
165163

166-
static OT_COMMAND ot_ipaddr(otInstance *ot_instance, void *arg, void *answer) {
164+
static otError ot_ipaddr(otInstance *ot_instance, void *arg, void *answer) {
167165
uint8_t cnt = 0;
168166
for (const otNetifAddress *addr = otIp6GetUnicastAddresses(ot_instance); addr; addr = addr->mNext) {
169167
if (arg != NULL && answer != NULL && cnt == *((uint8_t *)arg)) {
@@ -174,29 +172,28 @@ static OT_COMMAND ot_ipaddr(otInstance *ot_instance, void *arg, void *answer) {
174172
}
175173
if (answer != NULL) {
176174
*((uint8_t *)answer) = cnt;
175+
return OT_ERROR_NONE;
177176
}
178-
else {
179-
DEBUG_PUTS("ERROR: wrong argument");
180-
}
181-
return 0;
177+
178+
DEBUG_PUTS("ERROR: wrong argument");
179+
return OT_ERROR_INVALID_ARGS;
182180
}
183181

184-
static OT_COMMAND ot_masterkey(otInstance *ot_instance, void *arg, void *answer) {
182+
static otError ot_masterkey(otInstance *ot_instance, void *arg, void *answer) {
185183
if (answer != NULL) {
186184
const otMasterKey* masterkey = otThreadGetMasterKey(ot_instance);
187185
*((otMasterKey *) answer) = *masterkey;
188186
output_bytes("masterkey", (const uint8_t *)answer, OT_MASTER_KEY_SIZE);
189187
}
190188
else if (arg != NULL) {
191-
otThreadSetMasterKey(ot_instance, (otMasterKey *)arg);
189+
return otThreadSetMasterKey(ot_instance, (otMasterKey *)arg);
192190
}
193-
else {
194-
DEBUG_PUTS("ERROR: wrong argument");
195-
}
196-
return 0;
191+
192+
DEBUG_PUTS("ERROR: wrong argument");
193+
return OT_ERROR_INVALID_ARGS;
197194
}
198195

199-
static OT_COMMAND ot_mode(otInstance *ot_instance, void *arg, void *answer) {
196+
static otError ot_mode(otInstance *ot_instance, void *arg, void *answer) {
200197
(void)answer;
201198

202199
if (arg != NULL) {
@@ -221,65 +218,74 @@ static OT_COMMAND ot_mode(otInstance *ot_instance, void *arg, void *answer) {
221218
break;
222219
}
223220
}
224-
otThreadSetLinkMode(ot_instance, link_mode);
225-
DEBUG("OT mode changed to %s\n", (char *)arg);
226-
}
227-
else {
228-
DEBUG_PUTS("ERROR: wrong argument");
221+
DEBUG("changing OT mode to %s\n", (char *)arg);
222+
return otThreadSetLinkMode(ot_instance, link_mode);
229223
}
230-
return 0;
224+
225+
DEBUG_PUTS("ERROR: wrong argument");
226+
return OT_ERROR_INVALID_ARGS;
231227
}
232228

233-
static OT_COMMAND ot_networkname(otInstance *ot_instance, void *arg, void *answer) {
229+
static otError ot_networkname(otInstance *ot_instance, void *arg, void *answer) {
234230
if (answer != NULL) {
231+
assert(arg == NULL);
235232
const char *networkName = otThreadGetNetworkName(ot_instance);
236-
strcpy((char*) answer, networkName);
233+
strcpy((char *)answer, networkName);
237234
DEBUG("networkname: %.*s\n", OT_NETWORK_NAME_MAX_SIZE, networkName);
235+
return OT_ERROR_NONE;
238236
}
239237
else if (arg != NULL) {
240-
otThreadSetNetworkName(ot_instance, (char *)arg);
241-
}
242-
else {
243-
DEBUG_PUTS("ERROR: wrong argument\n");
238+
return otThreadSetNetworkName(ot_instance, (char *)arg);
244239
}
245-
return 0;
240+
241+
DEBUG_PUTS("ERROR: wrong argument\n");
242+
return OT_ERROR_INVALID_ARGS;
246243
}
247244

248-
static OT_COMMAND ot_panid(otInstance *ot_instance, void *arg, void *answer) {
245+
static otError ot_panid(otInstance *ot_instance, void *arg, void *answer) {
249246
if (answer != NULL) {
247+
assert(arg == NULL);
250248
*((uint16_t *) answer) = otLinkGetPanId(ot_instance);
251-
DEBUG("PanID: %04x\n", *((uint16_t *) answer));
249+
DEBUG("PanID: %04x\n", *((uint16_t *)answer));
250+
return OT_ERROR_NONE;
252251
}
253252
else if (arg != NULL) {
253+
otError err;
254254
/* Thread operation needs to be stopped before setting panid */
255-
otThreadSetEnabled(ot_instance, false);
255+
err = otThreadSetEnabled(ot_instance, false);
256+
if (err != OT_ERROR_NONE) {
257+
return err;
258+
}
256259
uint16_t panid = *((uint16_t *)arg);
257-
otLinkSetPanId(ot_instance, panid);
258-
otThreadSetEnabled(ot_instance, true);
259-
}
260-
else {
261-
DEBUG_PUTS("ERROR: wrong argument");
260+
err = otLinkSetPanId(ot_instance, panid);
261+
if (err != OT_ERROR_NONE) {
262+
return err;
263+
}
264+
return otThreadSetEnabled(ot_instance, true);
262265
}
263-
return 0;
266+
267+
DEBUG_PUTS("ERROR: wrong argument");
268+
return OT_ERROR_INVALID_ARGS;
264269
}
265270

266-
static OT_COMMAND ot_parent(otInstance *ot_instance, void *arg, void *answer) {
271+
static otError ot_parent(otInstance *ot_instance, void *arg, void *answer) {
267272
(void)arg;
268273

269274
if (answer != NULL) {
275+
otError err;
270276
otRouterInfo parentInfo;
271-
otThreadGetParentInfo(ot_instance, &parentInfo);
277+
err = otThreadGetParentInfo(ot_instance, &parentInfo);
272278
output_bytes("parent", (const uint8_t *)parentInfo.mExtAddress.m8, sizeof(parentInfo.mExtAddress));
273279
DEBUG("Rloc: %x\n", parentInfo.mRloc16);
274280
*((otRouterInfo *)answer) = parentInfo;
281+
return err;
275282
}
276-
else {
277-
DEBUG_PUTS("ERROR: wrong argument");
278-
}
279-
return 0;
283+
284+
DEBUG_PUTS("ERROR: wrong argument");
285+
return OT_ERROR_INVALID_ARGS;
280286
}
281287

282-
static OT_COMMAND ot_state(otInstance *ot_instance, void *arg, void *answer) {
288+
static otError ot_state(otInstance *ot_instance, void *arg, void *answer) {
283289
(void)arg;
284290

285291
if (answer != NULL) {
@@ -304,33 +310,32 @@ static OT_COMMAND ot_state(otInstance *ot_instance, void *arg, void *answer) {
304310
break;
305311
default:
306312
puts("invalid state");
313+
return OT_ERROR_INVALID_STATE;
307314
break;
308315
}
316+
return OT_ERROR_NONE;
309317
}
310-
else {
311-
DEBUG_PUTS("ERROR: wrong argument");
312-
}
313-
return 0;
318+
319+
DEBUG_PUTS("ERROR: wrong argument");
320+
return OT_ERROR_INVALID_ARGS;
314321
}
315322

316-
static OT_COMMAND ot_thread(otInstance *ot_instance, void *arg, void *answer) {
323+
static otError ot_thread(otInstance *ot_instance, void *arg, void *answer) {
317324
(void)answer;
318325

319326
if (arg != NULL) {
320327
if (strcmp((char*)arg, "start") == 0) {
321-
otThreadSetEnabled(ot_instance, true);
322328
DEBUG_PUTS("Thread start");
329+
return otThreadSetEnabled(ot_instance, true);
323330
}
324331
else if (strcmp(arg, "stop") == 0) {
325-
otThreadSetEnabled(ot_instance, false);
326332
DEBUG_PUTS("Thread stop");
333+
return otThreadSetEnabled(ot_instance, false);
327334
}
328-
else {
329-
DEBUG_PUTS("ERROR: thread available args: start/stop");
330-
}
331-
}
332-
else {
333-
DEBUG_PUTS("ERROR: wrong argument");
335+
DEBUG_PUTS("ERROR: thread available args: start/stop");
336+
return OT_ERROR_INVALID_ARGS;
334337
}
335-
return 0;
338+
339+
DEBUG_PUTS("ERROR: wrong argument");
340+
return OT_ERROR_INVALID_ARGS;
336341
}

pkg/openthread/include/ot.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,11 @@ typedef struct {
109109
*/
110110
typedef struct {
111111
event_t ev; /**< Event associated to the OpenThread job */
112-
int status; /**< Status of the job */
112+
otError retval; /**< Return value of the job */
113113
const char *command; /**< A pointer to the job name string. */
114114
void *arg; /**< arg for the job **/
115115
void *answer; /**< answer from the job **/
116+
mutex_t mutex; /**< used to for synchronization with the event thread */
116117
} ot_job_t;
117118

118119
/**

0 commit comments

Comments
 (0)