Skip to content

Commit 966864b

Browse files
Damian-Nordicanangl
authored andcommitted
net: openthread: rpc: allocate minimal buffer for read
otMessageRead() accepts the len argument, which can be specified to a larger number than the actual size. In such a case, OT RPC server would allocate needlessly large buffer before calling otMessageRead(). Optimize the heap usage by checking otMessageGetLength() before otMessageRead() and allocating only necessary space. Also, make a few other enhancements for message APIs: 1. Significantly increase unit test coverage. 2. Make sure message table is always checked or modified with OT RPC mutex locked. 3. Use nrf_rpc_rsp_send_xxx() helpers. Rework otMessageRead() implementation in OT RPC server to Signed-off-by: Damian Krolik <[email protected]>
1 parent e3f8e7b commit 966864b

File tree

8 files changed

+328
-105
lines changed

8 files changed

+328
-105
lines changed

subsys/net/openthread/rpc/server/ot_rpc_message.c

Lines changed: 38 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -24,33 +24,32 @@ OT_RPC_RESOURCE_TABLE_REGISTER(msg, otMessage, CONFIG_OPENTHREAD_RPC_MESSAGE_POO
2424
static void ot_rpc_msg_free(const struct nrf_rpc_group *group, struct nrf_rpc_cbor_ctx *ctx,
2525
void *handler_data)
2626
{
27-
ot_rpc_res_tab_key key = 0;
27+
ot_rpc_res_tab_key key;
2828
otMessage *message;
2929

3030
key = nrf_rpc_decode_uint(ctx);
31+
3132
if (!nrf_rpc_decoding_done_and_check(group, ctx)) {
3233
ot_rpc_report_cmd_decoding_error(OT_RPC_CMD_MESSAGE_FREE);
3334
return;
3435
}
3536

37+
ot_rpc_mutex_lock();
3638
message = ot_res_tab_msg_get(key);
3739

3840
if (message != NULL) {
39-
ot_rpc_mutex_lock();
4041
otMessageFree(message);
41-
ot_rpc_mutex_unlock();
42+
ot_res_tab_msg_free(key);
4243
}
4344

44-
ot_res_tab_msg_free(key);
45-
45+
ot_rpc_mutex_unlock();
4646
nrf_rpc_rsp_send_void(group);
4747
}
4848

4949
static void ot_rpc_msg_append(const struct nrf_rpc_group *group, struct nrf_rpc_cbor_ctx *ctx,
5050
void *handler_data)
5151
{
5252
otError error = OT_ERROR_INVALID_ARGS;
53-
struct nrf_rpc_cbor_ctx rsp_ctx;
5453
uint32_t key;
5554
const void *data;
5655
size_t size = 0;
@@ -59,31 +58,29 @@ static void ot_rpc_msg_append(const struct nrf_rpc_group *group, struct nrf_rpc_
5958
key = nrf_rpc_decode_uint(ctx);
6059
data = nrf_rpc_decode_buffer_ptr_and_size(ctx, &size);
6160

62-
if (data && size && nrf_rpc_decode_valid(ctx)) {
61+
if (data) {
62+
ot_rpc_mutex_lock();
6363
message = ot_res_tab_msg_get(key);
6464

6565
if (message != NULL) {
66-
ot_rpc_mutex_lock();
6766
error = otMessageAppend(message, data, size);
68-
ot_rpc_mutex_unlock();
6967
}
68+
69+
ot_rpc_mutex_unlock();
7070
}
7171

7272
if (!nrf_rpc_decoding_done_and_check(group, ctx)) {
7373
ot_rpc_report_cmd_decoding_error(OT_RPC_CMD_MESSAGE_APPEND);
7474
return;
7575
}
7676

77-
NRF_RPC_CBOR_ALLOC(group, rsp_ctx, sizeof(otError) + 1);
78-
nrf_rpc_encode_uint(&rsp_ctx, error);
79-
nrf_rpc_cbor_rsp_no_err(group, &rsp_ctx);
77+
nrf_rpc_rsp_send_uint(group, error);
8078
}
8179

8280
static void ot_rpc_msg_udp_new(const struct nrf_rpc_group *group, struct nrf_rpc_cbor_ctx *ctx,
8381
void *handler_data)
8482
{
8583
ot_rpc_res_tab_key key;
86-
struct nrf_rpc_cbor_ctx rsp_ctx;
8784
otMessageSettings settings;
8885
otMessageSettings *p_settings = &settings;
8986

@@ -96,122 +93,114 @@ static void ot_rpc_msg_udp_new(const struct nrf_rpc_group *group, struct nrf_rpc
9693

9794
ot_rpc_mutex_lock();
9895
key = ot_res_tab_msg_alloc(otUdpNewMessage(openthread_get_default_instance(), p_settings));
99-
ot_rpc_mutex_unlock();
10096

10197
if (ot_res_tab_msg_get(key) == NULL) {
10298
key = 0;
10399
}
104100

105-
NRF_RPC_CBOR_ALLOC(group, rsp_ctx, sizeof(key) + 1);
106-
nrf_rpc_encode_uint(&rsp_ctx, key);
107-
nrf_rpc_cbor_rsp_no_err(group, &rsp_ctx);
101+
ot_rpc_mutex_unlock();
102+
nrf_rpc_rsp_send_uint(group, key);
108103
}
109104

110105
static void ot_rpc_msg_length(const struct nrf_rpc_group *group, struct nrf_rpc_cbor_ctx *ctx,
111106
void *handler_data)
112107
{
113108
ot_rpc_res_tab_key key;
114-
struct nrf_rpc_cbor_ctx rsp_ctx;
115109
uint16_t length = 0;
116110
otMessage *message;
117111

118112
key = nrf_rpc_decode_uint(ctx);
113+
119114
if (!nrf_rpc_decoding_done_and_check(group, ctx)) {
120115
ot_rpc_report_cmd_decoding_error(OT_RPC_CMD_MESSAGE_GET_LENGTH);
121116
return;
122117
}
123118

119+
ot_rpc_mutex_lock();
124120
message = ot_res_tab_msg_get(key);
125121

126122
if (message != NULL) {
127-
ot_rpc_mutex_lock();
128123
length = otMessageGetLength(message);
129-
ot_rpc_mutex_unlock();
130124
}
131125

132-
NRF_RPC_CBOR_ALLOC(group, rsp_ctx, sizeof(length) + 1);
133-
nrf_rpc_encode_uint(&rsp_ctx, length);
134-
nrf_rpc_cbor_rsp_no_err(group, &rsp_ctx);
126+
ot_rpc_mutex_unlock();
127+
nrf_rpc_rsp_send_uint(group, length);
135128
}
136129

137130
static void ot_rpc_get_offset(const struct nrf_rpc_group *group, struct nrf_rpc_cbor_ctx *ctx,
138131
void *handler_data)
139132
{
140133
ot_rpc_res_tab_key key;
141-
struct nrf_rpc_cbor_ctx rsp_ctx;
142134
uint16_t offset = 0;
143135
otMessage *message;
144136

145137
key = nrf_rpc_decode_uint(ctx);
138+
146139
if (!nrf_rpc_decoding_done_and_check(group, ctx)) {
147140
ot_rpc_report_cmd_decoding_error(OT_RPC_CMD_MESSAGE_GET_OFFSET);
148141
return;
149142
}
150143

144+
ot_rpc_mutex_lock();
151145
message = ot_res_tab_msg_get(key);
152146

153147
if (message != NULL) {
154-
ot_rpc_mutex_lock();
155148
offset = otMessageGetOffset(message);
156-
ot_rpc_mutex_unlock();
157149
}
158150

159-
NRF_RPC_CBOR_ALLOC(group, rsp_ctx, sizeof(offset) + 1);
160-
nrf_rpc_encode_uint(&rsp_ctx, offset);
161-
nrf_rpc_cbor_rsp_no_err(group, &rsp_ctx);
151+
ot_rpc_mutex_unlock();
152+
nrf_rpc_rsp_send_uint(group, offset);
162153
}
163154

164155
static void ot_rpc_msg_read(const struct nrf_rpc_group *group, struct nrf_rpc_cbor_ctx *ctx,
165156
void *handler_data)
166157
{
158+
ot_rpc_res_tab_key key;
167159
uint16_t offset;
168160
uint16_t length;
169-
ot_rpc_res_tab_key key;
161+
otMessage *message;
170162
struct nrf_rpc_cbor_ctx rsp_ctx;
171-
const uint16_t chunk_size = 64;
172-
uint8_t buf[chunk_size];
163+
uint16_t message_length;
173164
uint16_t read = 0;
174-
otMessage *message;
175165

176166
key = nrf_rpc_decode_uint(ctx);
177167
offset = nrf_rpc_decode_uint(ctx);
178168
length = nrf_rpc_decode_uint(ctx);
169+
179170
if (!nrf_rpc_decoding_done_and_check(group, ctx)) {
180171
ot_rpc_report_cmd_decoding_error(OT_RPC_CMD_MESSAGE_READ);
181172
return;
182173
}
183174

184-
NRF_RPC_CBOR_ALLOC(group, rsp_ctx, length + 2);
185-
175+
ot_rpc_mutex_lock();
186176
message = ot_res_tab_msg_get(key);
187177

188178
if (message == NULL) {
179+
NRF_RPC_CBOR_ALLOC(group, rsp_ctx, 1);
189180
nrf_rpc_encode_null(&rsp_ctx);
190181
goto exit;
191182
}
192183

184+
/* Get the actual message size before reading to allocate as small buffer as necessary. */
185+
message_length = otMessageGetLength(message);
186+
offset = MIN(offset, message_length);
187+
length = MIN(length, message_length - offset);
188+
189+
NRF_RPC_CBOR_ALLOC(group, rsp_ctx, length + 3);
190+
193191
if (!zcbor_bstr_start_encode(rsp_ctx.zs)) {
194192
goto exit;
195193
}
196194

197-
ot_rpc_mutex_lock();
198-
199-
do {
200-
read = otMessageRead(message, offset, buf,
201-
(chunk_size < length) ? chunk_size : length);
202-
memcpy(rsp_ctx.zs[0].payload_mut, buf, read);
203-
rsp_ctx.zs->payload_mut += read;
204-
length -= read;
205-
offset += read;
206-
} while (read > 0 && length > 0);
207-
208-
ot_rpc_mutex_unlock();
195+
read = otMessageRead(message, offset, rsp_ctx.zs->payload_mut, length);
196+
rsp_ctx.zs->payload_mut += read;
209197

210198
if (!zcbor_bstr_end_encode(rsp_ctx.zs, NULL)) {
211199
goto exit;
212200
}
213201

214202
exit:
203+
ot_rpc_mutex_unlock();
215204
nrf_rpc_cbor_rsp_no_err(group, &rsp_ctx);
216205
}
217206

@@ -232,14 +221,15 @@ static void ot_rpc_msg_get_thread_link_info(const struct nrf_rpc_group *group,
232221
return;
233222
}
234223

224+
ot_rpc_mutex_lock();
235225
message = ot_res_tab_msg_get(key);
236226

237227
if (!message) {
228+
ot_rpc_mutex_unlock();
238229
ot_rpc_report_cmd_decoding_error(OT_RPC_CMD_MESSAGE_GET_THREAD_LINK_INFO);
239230
return;
240231
}
241232

242-
ot_rpc_mutex_lock();
243233
error = otMessageGetThreadLinkInfo(message, &link_info);
244234
ot_rpc_mutex_unlock();
245235

tests/subsys/net/openthread/rpc/common/test_rpc_env.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,17 @@
2020
/* for value bigger than 0x17 */
2121
#define CBOR_UINT8(value) 0x18, (value)
2222

23-
#define CBOR_LIST(...) 0x9F, __VA_ARGS__, 0xFF
24-
#define CBOR_EMPTY_BYTES 0x40
25-
#define CBOR_EMPTY_STRING 0x60
23+
#define CBOR_INT64(value) 0x3B, BT_BYTES_LIST_LE64(BSWAP_64(-1 - value))
24+
#define CBOR_INT32(value) 0x3A, BT_BYTES_LIST_LE32(BSWAP_32(-1 - value))
25+
#define CBOR_INT16(value) 0x39, BT_BYTES_LIST_LE16(BSWAP_16(-1 - value))
26+
/* for value smaller than -0x17 */
27+
#define CBOR_INT8(value) 0x38, (-1 - value)
28+
29+
#define CBOR_LIST(...) 0x9F __VA_OPT__(,) __VA_ARGS__, 0xFF
30+
#define CBOR_BSTR16(len, ...) (0x40 | 25), BT_BYTES_LIST_BE16(len) __VA_OPT__(,) __VA_ARGS__
31+
#define CBOR_BSTR8(len, ...) (0x40 | 24), len __VA_OPT__(,) __VA_ARGS__
32+
#define CBOR_BSTR(len, ...) (0x40 | len) __VA_OPT__(,) __VA_ARGS__
33+
#define CBOR_EMPTY_STRING 0x60
2634

2735
/* Macros for constructing nRF RPC packets for the OpenThread command group. */
2836

tests/subsys/net/openthread/rpc/server/src/coap_suite.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,6 @@ FAKE_VALUE_FUNC(otError, otCoapSendResponseWithParameters, otInstance *, otMessa
5353
const otMessageInfo *, const otCoapTxParameters *);
5454

5555
#define FOREACH_FAKE(f) \
56-
f(otMessageGetLength); \
57-
f(otMessageGetOffset); \
58-
f(otMessageRead); \
59-
f(otMessageFree); \
60-
f(otMessageAppend); \
6156
f(otCoapNewMessage); \
6257
f(otCoapMessageInit); \
6358
f(otCoapMessageInitResponse); \
@@ -89,8 +84,11 @@ static void tc_setup(void *f)
8984

9085
FOREACH_FAKE(RESET_FAKE);
9186
FFF_RESET_HISTORY();
87+
}
9288

93-
/* Unit tests take up to two message slots. */
89+
static void tc_cleanup(void *f)
90+
{
91+
/* This suite uses two messages at most. */
9492
ot_res_tab_msg_free(1);
9593
ot_res_tab_msg_free(2);
9694
}
@@ -576,4 +574,4 @@ ZTEST(ot_rpc_coap, test_otCoapSendResponse_failed)
576574
zassert_not_null(ot_res_tab_msg_get(message_rep));
577575
}
578576

579-
ZTEST_SUITE(ot_rpc_coap, NULL, NULL, tc_setup, NULL, NULL);
577+
ZTEST_SUITE(ot_rpc_coap, NULL, NULL, tc_setup, tc_cleanup, NULL);

tests/subsys/net/openthread/rpc/server/src/common_fakes.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,5 @@ DEFINE_FAKE_VOID_FUNC(otMessageFree, otMessage *);
1414
DEFINE_FAKE_VALUE_FUNC(otError, otMessageAppend, otMessage *, const void *, uint16_t);
1515
DEFINE_FAKE_VALUE_FUNC(otMessage *, otUdpNewMessage, otInstance *, const otMessageSettings *);
1616
DEFINE_FAKE_VALUE_FUNC(void *, nrf_rpc_cbkproxy_out_get, int, void *);
17+
DEFINE_FAKE_VOID_FUNC(otCliInit, otInstance *, otCliOutputCallback, void *);
18+
DEFINE_FAKE_VOID_FUNC(otCliInputLine, char *);

tests/subsys/net/openthread/rpc/server/src/common_fakes.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66

77
#ifndef __COMMON_FAKES_H__
88
#define __COMMON_FAKES_H__
9+
910
#include <zephyr/fff.h>
11+
#include <openthread/cli.h>
1012
#include <openthread/message.h>
1113

1214
DECLARE_FAKE_VALUE_FUNC(otMessage *, otUdpNewMessage, otInstance *, const otMessageSettings *);
@@ -17,5 +19,7 @@ DECLARE_FAKE_VALUE_FUNC(uint16_t, otMessageRead, const otMessage *, uint16_t, vo
1719
DECLARE_FAKE_VOID_FUNC(otMessageFree, otMessage *);
1820
DECLARE_FAKE_VALUE_FUNC(otError, otMessageAppend, otMessage *, const void *, uint16_t);
1921
DECLARE_FAKE_VALUE_FUNC(void *, nrf_rpc_cbkproxy_out_get, int, void *);
22+
DECLARE_FAKE_VOID_FUNC(otCliInit, otInstance *, otCliOutputCallback, void *);
23+
DECLARE_FAKE_VOID_FUNC(otCliInputLine, char *);
2024

2125
#endif

tests/subsys/net/openthread/rpc/server/src/ip6_suite.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020
/* Fake functions */
2121

2222
DEFINE_FFF_GLOBALS;
23-
FAKE_VOID_FUNC(otCliInit, otInstance *, otCliOutputCallback, void *);
24-
FAKE_VOID_FUNC(otCliInputLine, char *);
2523
FAKE_VALUE_FUNC(const otNetifAddress *, otIp6GetUnicastAddresses, otInstance *);
2624
FAKE_VALUE_FUNC(const otNetifMulticastAddress *, otIp6GetMulticastAddresses, otInstance *);
2725
FAKE_VALUE_FUNC(otError, otIp6SubscribeMulticastAddress, otInstance *, const otIp6Address *);
@@ -30,8 +28,6 @@ FAKE_VALUE_FUNC(otError, otIp6SetEnabled, otInstance *, bool);
3028
FAKE_VALUE_FUNC(bool, otIp6IsEnabled, otInstance *);
3129

3230
#define FOREACH_FAKE(f) \
33-
f(otCliInit); \
34-
f(otCliInputLine); \
3531
f(otIp6GetUnicastAddresses); \
3632
f(otIp6GetMulticastAddresses); \
3733
f(otIp6SubscribeMulticastAddress); \
@@ -233,6 +229,9 @@ ZTEST(ot_rpc_ip6, test_otIp6UnsubscribeMulticastAddress_failed)
233229

234230
/*
235231
* Test reception of otIp6GetUnicastAddresses() command.
232+
* Test serialization of the result:
233+
* - fe80:aabb:aabb:aabb:aabb:aabb:aabb:aa01
234+
* - fe80:aabb:aabb:aabb:aabb:aabb:aabb:aa02
236235
*/
237236
ZTEST(ot_rpc_ip6, test_otIp6GetUnicastAddresses)
238237
{
@@ -278,6 +277,9 @@ ZTEST(ot_rpc_ip6, test_otIp6GetUnicastAddresses)
278277

279278
/*
280279
* Test reception of otIp6GetMulticastAddresses() command.
280+
* Test serialization of the result:
281+
* - fe02::1
282+
* - fe02::2
281283
*/
282284
ZTEST(ot_rpc_ip6, test_otIp6GetMulticastAddresses)
283285
{

0 commit comments

Comments
 (0)