blob: 25f6d51469147ae02946f9255aba171ac18682b3 [file] [log] [blame]
Buke Po818998e2017-08-04 01:19:07 +08001/*
2 * Copyright (c) 2016-2017, 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" AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28/**
29 * @file
30 * This file implements minimal thread device required Spinel interface to the OpenThread stack.
31 */
32
Jonathan Hui512d2332019-07-12 14:57:15 -070033#include "openthread-core-config.h"
Yakun Xu96ed7cc2018-04-17 00:28:00 +080034
Buke Po818998e2017-08-04 01:19:07 +080035#include "ncp_base.hpp"
36
Jonathan Huif1849732019-07-16 12:31:11 -070037#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
Buke Po818998e2017-08-04 01:19:07 +080038#include <openthread/border_router.h>
39#endif
Jonathan Hui01ebc182019-07-12 15:21:49 -070040#if OPENTHREAD_CONFIG_CHANNEL_MONITOR_ENABLE
Abtin Keshavarzianba5317a2018-01-13 13:37:04 -080041#include <openthread/channel_monitor.h>
42#endif
Jonathan Huiaa823912019-07-15 12:03:36 -070043#if OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE
Abtin Keshavarzian1ca81fb2018-08-02 15:21:11 -070044#include <openthread/child_supervision.h>
45#endif
Buke Po818998e2017-08-04 01:19:07 +080046#include <openthread/diag.h>
47#include <openthread/icmp6.h>
Jonathan Hui02da2062019-07-16 12:18:34 -070048#if OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE
Buke Po818998e2017-08-04 01:19:07 +080049#include <openthread/jam_detection.h>
50#endif
51#include <openthread/ncp.h>
Jonathan Hui926b9e82019-07-15 21:16:37 -070052#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
Shu Chene69019f2018-06-27 02:46:32 +080053#include <openthread/network_time.h>
54#endif
Buke Po818998e2017-08-04 01:19:07 +080055#include <openthread/platform/misc.h>
56#include <openthread/platform/radio.h>
57#if OPENTHREAD_FTD
58#include <openthread/thread_ftd.h>
59#endif
Jonathan Hui149640d2019-07-16 11:06:03 -070060#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
Joseph Newmanecad7172019-03-29 05:29:25 +000061#include <openthread/server.h>
62#endif
Buke Po818998e2017-08-04 01:19:07 +080063
Buke Po818998e2017-08-04 01:19:07 +080064#include "common/code_utils.hpp"
65#include "common/debug.hpp"
Abtin Keshavarzian02c876e2017-11-13 08:27:57 -080066#include "common/instance.hpp"
Buke Po818998e2017-08-04 01:19:07 +080067#include "net/ip6.hpp"
68
69#if OPENTHREAD_MTD || OPENTHREAD_FTD
70
71namespace ot {
72namespace Ncp {
73
Buke Po818998e2017-08-04 01:19:07 +080074static uint8_t BorderRouterConfigToFlagByte(const otBorderRouterConfig &aConfig)
75{
76 uint8_t flags(0);
77
78 if (aConfig.mPreferred)
79 {
80 flags |= SPINEL_NET_FLAG_PREFERRED;
81 }
82
83 if (aConfig.mSlaac)
84 {
85 flags |= SPINEL_NET_FLAG_SLAAC;
86 }
87
88 if (aConfig.mDhcp)
89 {
90 flags |= SPINEL_NET_FLAG_DHCP;
91 }
92
93 if (aConfig.mDefaultRoute)
94 {
95 flags |= SPINEL_NET_FLAG_DEFAULT_ROUTE;
96 }
97
98 if (aConfig.mConfigure)
99 {
100 flags |= SPINEL_NET_FLAG_CONFIGURE;
101 }
102
103 if (aConfig.mOnMesh)
104 {
105 flags |= SPINEL_NET_FLAG_ON_MESH;
106 }
107
Jonathan Hui70cb48f2019-01-28 08:39:02 -0800108 flags |= (static_cast<uint8_t>(aConfig.mPreference) << SPINEL_NET_FLAG_PREFERENCE_OFFSET);
Buke Po818998e2017-08-04 01:19:07 +0800109
110 return flags;
111}
112
113static uint8_t ExternalRoutePreferenceToFlagByte(int aPreference)
114{
115 uint8_t flags;
116
117 switch (aPreference)
118 {
119 case OT_ROUTE_PREFERENCE_LOW:
120 flags = SPINEL_ROUTE_PREFERENCE_LOW;
121 break;
122
Buke Po818998e2017-08-04 01:19:07 +0800123 case OT_ROUTE_PREFERENCE_HIGH:
124 flags = SPINEL_ROUTE_PREFERENCE_HIGH;
125 break;
126
Yakun Xu26694be2020-01-23 02:18:54 +0800127 case OT_ROUTE_PREFERENCE_MED:
128 // fall through
129
Buke Po818998e2017-08-04 01:19:07 +0800130 default:
131 flags = SPINEL_ROUTE_PREFERENCE_MEDIUM;
132 break;
133 }
134
135 return flags;
136}
137
138uint8_t NcpBase::LinkFlagsToFlagByte(bool aRxOnWhenIdle, bool aSecureDataRequests, bool aDeviceType, bool aNetworkData)
139{
140 uint8_t flags(0);
141
142 if (aRxOnWhenIdle)
143 {
144 flags |= SPINEL_THREAD_MODE_RX_ON_WHEN_IDLE;
145 }
146
147 if (aSecureDataRequests)
148 {
149 flags |= SPINEL_THREAD_MODE_SECURE_DATA_REQUEST;
150 }
151
152 if (aDeviceType)
153 {
Jonathan Hui5a489832018-09-27 09:33:03 -0700154 flags |= SPINEL_THREAD_MODE_FULL_THREAD_DEV;
Buke Po818998e2017-08-04 01:19:07 +0800155 }
156
157 if (aNetworkData)
158 {
159 flags |= SPINEL_THREAD_MODE_FULL_NETWORK_DATA;
160 }
161
162 return flags;
163}
164
Abtin Keshavarziana1b2d352019-05-19 00:05:21 -0700165otError NcpBase::EncodeNeighborInfo(const otNeighborInfo &aNeighborInfo)
166{
167 otError error;
168 uint8_t modeFlags;
169
170 modeFlags = LinkFlagsToFlagByte(aNeighborInfo.mRxOnWhenIdle, aNeighborInfo.mSecureDataRequest,
171 aNeighborInfo.mFullThreadDevice, aNeighborInfo.mFullNetworkData);
172
173 SuccessOrExit(error = mEncoder.OpenStruct());
174
175 SuccessOrExit(error = mEncoder.WriteEui64(aNeighborInfo.mExtAddress));
176 SuccessOrExit(error = mEncoder.WriteUint16(aNeighborInfo.mRloc16));
177 SuccessOrExit(error = mEncoder.WriteUint32(aNeighborInfo.mAge));
178 SuccessOrExit(error = mEncoder.WriteUint8(aNeighborInfo.mLinkQualityIn));
179 SuccessOrExit(error = mEncoder.WriteInt8(aNeighborInfo.mAverageRssi));
180 SuccessOrExit(error = mEncoder.WriteUint8(modeFlags));
181 SuccessOrExit(error = mEncoder.WriteBool(aNeighborInfo.mIsChild));
182 SuccessOrExit(error = mEncoder.WriteUint32(aNeighborInfo.mLinkFrameCounter));
183 SuccessOrExit(error = mEncoder.WriteUint32(aNeighborInfo.mMleFrameCounter));
184 SuccessOrExit(error = mEncoder.WriteInt8(aNeighborInfo.mLastRssi));
185
186 SuccessOrExit(error = mEncoder.CloseStruct());
187
188exit:
189 return error;
190}
191
Yakun Xu8ccf1382018-06-29 00:26:31 +0800192template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_DATA_POLL_PERIOD>(void)
Buke Po818998e2017-08-04 01:19:07 +0800193{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700194 return mEncoder.WriteUint32(otLinkGetPollPeriod(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800195}
196
Yakun Xu8ccf1382018-06-29 00:26:31 +0800197template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_DATA_POLL_PERIOD>(void)
Buke Po818998e2017-08-04 01:19:07 +0800198{
199 uint32_t pollPeriod;
Yakun Xub8333732018-06-21 04:15:13 +0800200 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800201
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700202 SuccessOrExit(error = mDecoder.ReadUint32(pollPeriod));
Buke Po818998e2017-08-04 01:19:07 +0800203
rongli32823982018-12-28 14:35:57 +0800204 error = otLinkSetPollPeriod(mInstance, pollPeriod);
Buke Po818998e2017-08-04 01:19:07 +0800205
206exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700207 return error;
Buke Po818998e2017-08-04 01:19:07 +0800208}
209
Yakun Xu8ccf1382018-06-29 00:26:31 +0800210template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_EXTENDED_ADDR>(void)
Buke Po818998e2017-08-04 01:19:07 +0800211{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700212 return mEncoder.WriteEui64(*otLinkGetExtendedAddress(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800213}
214
Rafał Kuźnia5a7e1902019-10-29 17:04:26 +0100215template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_MAX_RETRY_NUMBER_DIRECT>(void)
216{
217 return mEncoder.WriteUint8(otLinkGetMaxFrameRetriesDirect(mInstance));
218}
219
220template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_MAX_RETRY_NUMBER_DIRECT>(void)
221{
222 uint8_t maxFrameRetriesDirect;
223 otError error = OT_ERROR_NONE;
224
225 SuccessOrExit(error = mDecoder.ReadUint8(maxFrameRetriesDirect));
226 otLinkSetMaxFrameRetriesDirect(mInstance, maxFrameRetriesDirect);
227
228exit:
229 return error;
230}
231
Abtin Keshavarzian31698ec2018-07-02 08:43:45 -0700232template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_PHY_CHAN_SUPPORTED>(void)
233{
234 uint32_t newMask = 0;
235 otError error = OT_ERROR_NONE;
236
237 SuccessOrExit(error = DecodeChannelMask(newMask));
238 error = otLinkSetSupportedChannelMask(mInstance, newMask);
239
240exit:
241 return error;
Buke Po818998e2017-08-04 01:19:07 +0800242}
243
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700244otError NcpBase::CommandHandler_NET_CLEAR(uint8_t aHeader)
Buke Po818998e2017-08-04 01:19:07 +0800245{
Abtin Keshavarzian9ce57b22017-12-05 18:33:53 -0800246 return PrepareLastStatusResponse(aHeader, ThreadErrorToSpinelStatus(otInstanceErasePersistentInfo(mInstance)));
Buke Po818998e2017-08-04 01:19:07 +0800247}
248
Yakun Xu8ccf1382018-06-29 00:26:31 +0800249template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NET_SAVED>(void)
Buke Po818998e2017-08-04 01:19:07 +0800250{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700251 return mEncoder.WriteBool(otDatasetIsCommissioned(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800252}
253
Yakun Xu8ccf1382018-06-29 00:26:31 +0800254template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NET_IF_UP>(void)
Buke Po818998e2017-08-04 01:19:07 +0800255{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700256 return mEncoder.WriteBool(otIp6IsEnabled(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800257}
258
Yakun Xu8ccf1382018-06-29 00:26:31 +0800259template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_NET_IF_UP>(void)
Buke Po818998e2017-08-04 01:19:07 +0800260{
Yakun Xub8333732018-06-21 04:15:13 +0800261 bool enabled = false;
262 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800263
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700264 SuccessOrExit(error = mDecoder.ReadBool(enabled));
Buke Po818998e2017-08-04 01:19:07 +0800265
266 error = otIp6SetEnabled(mInstance, enabled);
267
268exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700269 return error;
Buke Po818998e2017-08-04 01:19:07 +0800270}
271
Yakun Xu8ccf1382018-06-29 00:26:31 +0800272template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NET_STACK_UP>(void)
Buke Po818998e2017-08-04 01:19:07 +0800273{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700274 return mEncoder.WriteBool(otThreadGetDeviceRole(mInstance) != OT_DEVICE_ROLE_DISABLED);
Buke Po818998e2017-08-04 01:19:07 +0800275}
276
Yakun Xu8ccf1382018-06-29 00:26:31 +0800277template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_NET_STACK_UP>(void)
Buke Po818998e2017-08-04 01:19:07 +0800278{
Yakun Xub8333732018-06-21 04:15:13 +0800279 bool enabled = false;
280 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800281
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700282 SuccessOrExit(error = mDecoder.ReadBool(enabled));
Buke Po818998e2017-08-04 01:19:07 +0800283
284 // If the value has changed...
285 if ((enabled != false) != (otThreadGetDeviceRole(mInstance) != OT_DEVICE_ROLE_DISABLED))
286 {
287 if (enabled != false)
288 {
289 error = otThreadSetEnabled(mInstance, true);
Abtin Keshavarzianecd28452018-04-05 10:20:47 -0700290 StartLegacy();
Buke Po818998e2017-08-04 01:19:07 +0800291 }
292 else
293 {
294 error = otThreadSetEnabled(mInstance, false);
Abtin Keshavarzianecd28452018-04-05 10:20:47 -0700295 StopLegacy();
Buke Po818998e2017-08-04 01:19:07 +0800296 }
297 }
298
299exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700300 return error;
Buke Po818998e2017-08-04 01:19:07 +0800301}
302
Yakun Xu8ccf1382018-06-29 00:26:31 +0800303template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NET_ROLE>(void)
Buke Po818998e2017-08-04 01:19:07 +0800304{
305 spinel_net_role_t role(SPINEL_NET_ROLE_DETACHED);
306
307 switch (otThreadGetDeviceRole(mInstance))
308 {
309 case OT_DEVICE_ROLE_DISABLED:
310 case OT_DEVICE_ROLE_DETACHED:
311 role = SPINEL_NET_ROLE_DETACHED;
312 break;
313
314 case OT_DEVICE_ROLE_CHILD:
315 role = SPINEL_NET_ROLE_CHILD;
316 break;
317
318 case OT_DEVICE_ROLE_ROUTER:
319 role = SPINEL_NET_ROLE_ROUTER;
320 break;
321
322 case OT_DEVICE_ROLE_LEADER:
323 role = SPINEL_NET_ROLE_LEADER;
324 break;
325 }
326
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700327 return mEncoder.WriteUint8(role);
Buke Po818998e2017-08-04 01:19:07 +0800328}
329
Yakun Xu8ccf1382018-06-29 00:26:31 +0800330template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_NET_ROLE>(void)
Buke Po818998e2017-08-04 01:19:07 +0800331{
Yakun Xub8333732018-06-21 04:15:13 +0800332 unsigned int role = 0;
333 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800334
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700335 SuccessOrExit(error = mDecoder.ReadUintPacked(role));
Buke Po818998e2017-08-04 01:19:07 +0800336
337 switch (role)
338 {
339 case SPINEL_NET_ROLE_DETACHED:
340 error = otThreadBecomeDetached(mInstance);
341 break;
342
343#if OPENTHREAD_FTD
344 case SPINEL_NET_ROLE_ROUTER:
345 error = otThreadBecomeRouter(mInstance);
346 break;
347
348 case SPINEL_NET_ROLE_LEADER:
349 error = otThreadBecomeLeader(mInstance);
350 break;
Yakun Xub8333732018-06-21 04:15:13 +0800351#endif // OPENTHREAD_FTD
Buke Po818998e2017-08-04 01:19:07 +0800352
353 case SPINEL_NET_ROLE_CHILD:
354 error = otThreadBecomeChild(mInstance);
355 break;
356 }
357
358exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700359 return error;
Buke Po818998e2017-08-04 01:19:07 +0800360}
361
Yakun Xu8ccf1382018-06-29 00:26:31 +0800362template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NET_NETWORK_NAME>(void)
Buke Po818998e2017-08-04 01:19:07 +0800363{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700364 return mEncoder.WriteUtf8(otThreadGetNetworkName(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800365}
366
Yakun Xu8ccf1382018-06-29 00:26:31 +0800367template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_NET_NETWORK_NAME>(void)
Buke Po818998e2017-08-04 01:19:07 +0800368{
Jonathan Hui1326d642020-06-17 22:44:54 -0700369 const char *string = nullptr;
Yakun Xub8333732018-06-21 04:15:13 +0800370 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800371
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700372 SuccessOrExit(mDecoder.ReadUtf8(string));
Buke Po818998e2017-08-04 01:19:07 +0800373
374 error = otThreadSetNetworkName(mInstance, string);
375
376exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700377 return error;
Buke Po818998e2017-08-04 01:19:07 +0800378}
379
Yakun Xu8ccf1382018-06-29 00:26:31 +0800380template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NET_XPANID>(void)
Buke Po818998e2017-08-04 01:19:07 +0800381{
Jonathan Hui92019732018-08-15 10:12:49 -0700382 return mEncoder.WriteData(otThreadGetExtendedPanId(mInstance)->m8, sizeof(spinel_net_xpanid_t));
Buke Po818998e2017-08-04 01:19:07 +0800383}
384
Yakun Xu8ccf1382018-06-29 00:26:31 +0800385template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_NET_XPANID>(void)
Buke Po818998e2017-08-04 01:19:07 +0800386{
Jonathan Hui1326d642020-06-17 22:44:54 -0700387 const uint8_t *ptr = nullptr;
Yakun Xub8333732018-06-21 04:15:13 +0800388 uint16_t len;
389 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800390
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700391 SuccessOrExit(error = mDecoder.ReadData(ptr, len));
Buke Po818998e2017-08-04 01:19:07 +0800392
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700393 VerifyOrExit(len == sizeof(spinel_net_xpanid_t), error = OT_ERROR_PARSE);
Buke Po818998e2017-08-04 01:19:07 +0800394
Jonathan Hui92019732018-08-15 10:12:49 -0700395 error = otThreadSetExtendedPanId(mInstance, reinterpret_cast<const otExtendedPanId *>(ptr));
Buke Po818998e2017-08-04 01:19:07 +0800396
397exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700398 return error;
Buke Po818998e2017-08-04 01:19:07 +0800399}
400
Yakun Xu8ccf1382018-06-29 00:26:31 +0800401template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NET_MASTER_KEY>(void)
Buke Po818998e2017-08-04 01:19:07 +0800402{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700403 return mEncoder.WriteData(otThreadGetMasterKey(mInstance)->m8, OT_MASTER_KEY_SIZE);
Buke Po818998e2017-08-04 01:19:07 +0800404}
405
Yakun Xu8ccf1382018-06-29 00:26:31 +0800406template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_NET_MASTER_KEY>(void)
Buke Po818998e2017-08-04 01:19:07 +0800407{
Jonathan Hui1326d642020-06-17 22:44:54 -0700408 const uint8_t *ptr = nullptr;
Yakun Xub8333732018-06-21 04:15:13 +0800409 uint16_t len;
410 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800411
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700412 SuccessOrExit(error = mDecoder.ReadData(ptr, len));
Buke Po818998e2017-08-04 01:19:07 +0800413
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700414 VerifyOrExit(len == OT_MASTER_KEY_SIZE, error = OT_ERROR_PARSE);
Buke Po818998e2017-08-04 01:19:07 +0800415
416 error = otThreadSetMasterKey(mInstance, reinterpret_cast<const otMasterKey *>(ptr));
417
418exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700419 return error;
Buke Po818998e2017-08-04 01:19:07 +0800420}
421
Yakun Xu8ccf1382018-06-29 00:26:31 +0800422template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER>(void)
Buke Po818998e2017-08-04 01:19:07 +0800423{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700424 return mEncoder.WriteUint32(otThreadGetKeySequenceCounter(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800425}
426
Yakun Xu8ccf1382018-06-29 00:26:31 +0800427template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER>(void)
Buke Po818998e2017-08-04 01:19:07 +0800428{
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700429 uint32_t keySeqCounter;
Yakun Xub8333732018-06-21 04:15:13 +0800430 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800431
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700432 SuccessOrExit(error = mDecoder.ReadUint32(keySeqCounter));
Buke Po818998e2017-08-04 01:19:07 +0800433
434 otThreadSetKeySequenceCounter(mInstance, keySeqCounter);
435
436exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700437 return error;
Buke Po818998e2017-08-04 01:19:07 +0800438}
439
Yakun Xu8ccf1382018-06-29 00:26:31 +0800440template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NET_PARTITION_ID>(void)
Buke Po818998e2017-08-04 01:19:07 +0800441{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700442 return mEncoder.WriteUint32(otThreadGetPartitionId(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800443}
444
Yakun Xu8ccf1382018-06-29 00:26:31 +0800445template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NET_KEY_SWITCH_GUARDTIME>(void)
Buke Po818998e2017-08-04 01:19:07 +0800446{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700447 return mEncoder.WriteUint32(otThreadGetKeySwitchGuardTime(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800448}
449
Yakun Xu8ccf1382018-06-29 00:26:31 +0800450template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_NET_KEY_SWITCH_GUARDTIME>(void)
Buke Po818998e2017-08-04 01:19:07 +0800451{
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700452 uint32_t keyGuardTime;
Yakun Xub8333732018-06-21 04:15:13 +0800453 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800454
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700455 SuccessOrExit(error = mDecoder.ReadUint32(keyGuardTime));
Buke Po818998e2017-08-04 01:19:07 +0800456
457 otThreadSetKeySwitchGuardTime(mInstance, keyGuardTime);
458
459exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700460 return error;
Buke Po818998e2017-08-04 01:19:07 +0800461}
462
Yakun Xu8ccf1382018-06-29 00:26:31 +0800463template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_NETWORK_DATA_VERSION>(void)
Buke Po818998e2017-08-04 01:19:07 +0800464{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700465 return mEncoder.WriteUint8(otNetDataGetVersion(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800466}
467
Yakun Xu8ccf1382018-06-29 00:26:31 +0800468template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_STABLE_NETWORK_DATA_VERSION>(void)
Buke Po818998e2017-08-04 01:19:07 +0800469{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700470 return mEncoder.WriteUint8(otNetDataGetStableVersion(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800471}
472
Jonathan Huif1849732019-07-16 12:31:11 -0700473#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
Yakun Xu8ccf1382018-06-29 00:26:31 +0800474template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_NETWORK_DATA>(void)
Buke Po818998e2017-08-04 01:19:07 +0800475{
Buke Po818998e2017-08-04 01:19:07 +0800476 uint8_t networkData[255];
477 uint8_t networkDataLen = 255;
478
kangping49f36f82020-05-07 02:17:58 +0800479 IgnoreError(otBorderRouterGetNetData(mInstance,
480 false, // Stable?
481 networkData, &networkDataLen));
Buke Po818998e2017-08-04 01:19:07 +0800482
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700483 return mEncoder.WriteData(networkData, networkDataLen);
Buke Po818998e2017-08-04 01:19:07 +0800484}
485
Yakun Xu8ccf1382018-06-29 00:26:31 +0800486template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_STABLE_NETWORK_DATA>(void)
Buke Po818998e2017-08-04 01:19:07 +0800487{
Buke Po818998e2017-08-04 01:19:07 +0800488 uint8_t networkData[255];
489 uint8_t networkDataLen = 255;
490
kangping49f36f82020-05-07 02:17:58 +0800491 IgnoreError(otBorderRouterGetNetData(mInstance,
492 true, // Stable?
493 networkData, &networkDataLen));
Buke Po818998e2017-08-04 01:19:07 +0800494
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700495 return mEncoder.WriteData(networkData, networkDataLen);
Buke Po818998e2017-08-04 01:19:07 +0800496}
Jonathan Huif1849732019-07-16 12:31:11 -0700497#endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
Buke Po818998e2017-08-04 01:19:07 +0800498
Yakun Xu8ccf1382018-06-29 00:26:31 +0800499template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_LEADER_NETWORK_DATA>(void)
Buke Po818998e2017-08-04 01:19:07 +0800500{
Buke Po818998e2017-08-04 01:19:07 +0800501 uint8_t networkData[255];
502 uint8_t networkDataLen = 255;
503
kangping49f36f82020-05-07 02:17:58 +0800504 IgnoreError(otNetDataGet(mInstance,
505 false, // Stable?
506 networkData, &networkDataLen));
Buke Po818998e2017-08-04 01:19:07 +0800507
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700508 return mEncoder.WriteData(networkData, networkDataLen);
Buke Po818998e2017-08-04 01:19:07 +0800509}
510
Yakun Xu8ccf1382018-06-29 00:26:31 +0800511template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_STABLE_LEADER_NETWORK_DATA>(void)
Buke Po818998e2017-08-04 01:19:07 +0800512{
Buke Po818998e2017-08-04 01:19:07 +0800513 uint8_t networkData[255];
514 uint8_t networkDataLen = 255;
515
kangping49f36f82020-05-07 02:17:58 +0800516 IgnoreError(otNetDataGet(mInstance,
517 true, // Stable?
518 networkData, &networkDataLen));
Buke Po818998e2017-08-04 01:19:07 +0800519
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700520 return mEncoder.WriteData(networkData, networkDataLen);
Buke Po818998e2017-08-04 01:19:07 +0800521}
522
Yakun Xu8ccf1382018-06-29 00:26:31 +0800523template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_LEADER_RID>(void)
Buke Po818998e2017-08-04 01:19:07 +0800524{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700525 return mEncoder.WriteUint8(otThreadGetLeaderRouterId(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800526}
527
Yakun Xu8ccf1382018-06-29 00:26:31 +0800528template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_LEADER_ADDR>(void)
Buke Po818998e2017-08-04 01:19:07 +0800529{
Yakun Xub8333732018-06-21 04:15:13 +0800530 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800531 otIp6Address address;
532
533 error = otThreadGetLeaderRloc(mInstance, &address);
534
535 if (error == OT_ERROR_NONE)
536 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700537 error = mEncoder.WriteIp6Address(address);
Buke Po818998e2017-08-04 01:19:07 +0800538 }
539 else
540 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700541 error = mEncoder.OverwriteWithLastStatusError(ThreadErrorToSpinelStatus(error));
Buke Po818998e2017-08-04 01:19:07 +0800542 }
543
544 return error;
545}
546
Yakun Xu8ccf1382018-06-29 00:26:31 +0800547template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_PARENT>(void)
Buke Po818998e2017-08-04 01:19:07 +0800548{
549 otError error = OT_ERROR_NONE;
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700550
Buke Po818998e2017-08-04 01:19:07 +0800551 otRouterInfo parentInfo;
552
553 error = otThreadGetParentInfo(mInstance, &parentInfo);
554
555 if (error == OT_ERROR_NONE)
556 {
Abtin Keshavarzian52354e72018-07-04 13:40:40 -0700557 if (parentInfo.mLinkEstablished)
558 {
559 int8_t averageRssi;
560 int8_t lastRssi;
561
kangping49f36f82020-05-07 02:17:58 +0800562 IgnoreError(otThreadGetParentAverageRssi(mInstance, &averageRssi));
563 IgnoreError(otThreadGetParentLastRssi(mInstance, &lastRssi));
Abtin Keshavarzian52354e72018-07-04 13:40:40 -0700564
565 SuccessOrExit(error = mEncoder.WriteEui64(parentInfo.mExtAddress));
566 SuccessOrExit(error = mEncoder.WriteUint16(parentInfo.mRloc16));
567 SuccessOrExit(error = mEncoder.WriteUint32(parentInfo.mAge));
568 SuccessOrExit(error = mEncoder.WriteInt8(averageRssi));
569 SuccessOrExit(error = mEncoder.WriteInt8(lastRssi));
570 SuccessOrExit(error = mEncoder.WriteUint8(parentInfo.mLinkQualityIn));
571 SuccessOrExit(error = mEncoder.WriteUint8(parentInfo.mLinkQualityOut));
572 }
573 else
574 {
575 SuccessOrExit(error = mEncoder.OverwriteWithLastStatusError(SPINEL_STATUS_ITEM_NOT_FOUND));
576 }
Buke Po818998e2017-08-04 01:19:07 +0800577 }
578 else
579 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700580 error = mEncoder.OverwriteWithLastStatusError(ThreadErrorToSpinelStatus(error));
Buke Po818998e2017-08-04 01:19:07 +0800581 }
582
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700583exit:
Buke Po818998e2017-08-04 01:19:07 +0800584 return error;
585}
586
Yakun Xu8ccf1382018-06-29 00:26:31 +0800587template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_NEIGHBOR_TABLE>(void)
Buke Po818998e2017-08-04 01:19:07 +0800588{
Yakun Xub8333732018-06-21 04:15:13 +0800589 otError error = OT_ERROR_NONE;
590 otNeighborInfoIterator iter = OT_NEIGHBOR_INFO_ITERATOR_INIT;
591 otNeighborInfo neighInfo;
Buke Po818998e2017-08-04 01:19:07 +0800592
Buke Po818998e2017-08-04 01:19:07 +0800593 while (otThreadGetNextNeighborInfo(mInstance, &iter, &neighInfo) == OT_ERROR_NONE)
594 {
Abtin Keshavarziana1b2d352019-05-19 00:05:21 -0700595 SuccessOrExit(error = EncodeNeighborInfo(neighInfo));
Buke Po818998e2017-08-04 01:19:07 +0800596 }
597
Buke Po818998e2017-08-04 01:19:07 +0800598exit:
Buke Po818998e2017-08-04 01:19:07 +0800599 return error;
600}
601
Yakun Xu8ccf1382018-06-29 00:26:31 +0800602template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_NEIGHBOR_TABLE_ERROR_RATES>(void)
Abtin Keshavarzian10f6c4f2018-02-02 10:29:52 -0800603{
Yakun Xub8333732018-06-21 04:15:13 +0800604 otError error = OT_ERROR_NONE;
605 otNeighborInfoIterator iter = OT_NEIGHBOR_INFO_ITERATOR_INIT;
606 otNeighborInfo neighInfo;
Abtin Keshavarzian10f6c4f2018-02-02 10:29:52 -0800607
608 while (otThreadGetNextNeighborInfo(mInstance, &iter, &neighInfo) == OT_ERROR_NONE)
609 {
610 SuccessOrExit(error = mEncoder.OpenStruct());
611
612 SuccessOrExit(error = mEncoder.WriteEui64(neighInfo.mExtAddress));
613 SuccessOrExit(error = mEncoder.WriteUint16(neighInfo.mRloc16));
614 SuccessOrExit(error = mEncoder.WriteUint16(neighInfo.mFrameErrorRate));
615 SuccessOrExit(error = mEncoder.WriteUint16(neighInfo.mMessageErrorRate));
616 SuccessOrExit(error = mEncoder.WriteInt8(neighInfo.mAverageRssi));
617 SuccessOrExit(error = mEncoder.WriteInt8(neighInfo.mLastRssi));
618
619 SuccessOrExit(error = mEncoder.CloseStruct());
620 }
621
622exit:
623 return error;
624}
625
Yakun Xu8ccf1382018-06-29 00:26:31 +0800626template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_ASSISTING_PORTS>(void)
Buke Po818998e2017-08-04 01:19:07 +0800627{
Yakun Xub8333732018-06-21 04:15:13 +0800628 otError error = OT_ERROR_NONE;
629 uint8_t numEntries = 0;
630 const uint16_t *ports = otIp6GetUnsecurePorts(mInstance, &numEntries);
Buke Po818998e2017-08-04 01:19:07 +0800631
Buke Po818998e2017-08-04 01:19:07 +0800632 for (; numEntries != 0; ports++, numEntries--)
633 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700634 SuccessOrExit(error = mEncoder.WriteUint16(*ports));
Buke Po818998e2017-08-04 01:19:07 +0800635 }
636
Buke Po818998e2017-08-04 01:19:07 +0800637exit:
638 return error;
639}
640
Yakun Xu8ccf1382018-06-29 00:26:31 +0800641template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_ASSISTING_PORTS>(void)
Buke Po818998e2017-08-04 01:19:07 +0800642{
Zhanglong Xiac573daf2018-09-11 08:39:06 +0800643 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800644
645 // First, we need to remove all of the current assisting ports.
Zhanglong Xiac573daf2018-09-11 08:39:06 +0800646 otIp6RemoveAllUnsecurePorts(mInstance);
Buke Po818998e2017-08-04 01:19:07 +0800647
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700648 while (mDecoder.GetRemainingLengthInStruct() >= sizeof(uint16_t))
Buke Po818998e2017-08-04 01:19:07 +0800649 {
650 uint16_t port;
651
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700652 SuccessOrExit(mDecoder.ReadUint16(port));
Buke Po818998e2017-08-04 01:19:07 +0800653
654 SuccessOrExit(error = otIp6AddUnsecurePort(mInstance, port));
Buke Po818998e2017-08-04 01:19:07 +0800655 }
656
Buke Po818998e2017-08-04 01:19:07 +0800657exit:
Buke Po818998e2017-08-04 01:19:07 +0800658
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700659 if (error != OT_ERROR_NONE)
Buke Po818998e2017-08-04 01:19:07 +0800660 {
661 // We had an error, but we've actually changed
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700662 // the state of these ports, so we need to report
Buke Po818998e2017-08-04 01:19:07 +0800663 // those incomplete changes via an asynchronous
664 // change event.
kangping49f36f82020-05-07 02:17:58 +0800665 IgnoreError(
666 WritePropertyValueIsFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_PROP_THREAD_ASSISTING_PORTS));
Buke Po818998e2017-08-04 01:19:07 +0800667 }
668
669 return error;
670}
671
Yakun Xu8ccf1382018-06-29 00:26:31 +0800672template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE>(void)
Buke Po818998e2017-08-04 01:19:07 +0800673{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700674 return mEncoder.WriteBool(mAllowLocalNetworkDataChange);
Buke Po818998e2017-08-04 01:19:07 +0800675}
676
Jonathan Huif1849732019-07-16 12:31:11 -0700677#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
Yakun Xu8ccf1382018-06-29 00:26:31 +0800678template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE>(void)
Buke Po818998e2017-08-04 01:19:07 +0800679{
Yakun Xub8333732018-06-21 04:15:13 +0800680 bool value = false;
681 otError error = OT_ERROR_NONE;
682 bool shouldRegisterWithLeader = false;
Buke Po818998e2017-08-04 01:19:07 +0800683
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700684 SuccessOrExit(error = mDecoder.ReadBool(value));
Buke Po818998e2017-08-04 01:19:07 +0800685
686 // Register any net data changes on transition from `true` to `false`.
687 shouldRegisterWithLeader = (mAllowLocalNetworkDataChange == true) && (value == false);
688
689 mAllowLocalNetworkDataChange = value;
690
691exit:
Buke Po818998e2017-08-04 01:19:07 +0800692
693 if (shouldRegisterWithLeader)
694 {
kangping49f36f82020-05-07 02:17:58 +0800695 IgnoreError(otBorderRouterRegister(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800696 }
697
698 return error;
699}
Jonathan Huif1849732019-07-16 12:31:11 -0700700#endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
Buke Po818998e2017-08-04 01:19:07 +0800701
Yakun Xu8ccf1382018-06-29 00:26:31 +0800702template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_ON_MESH_NETS>(void)
Buke Po818998e2017-08-04 01:19:07 +0800703{
Yakun Xub8333732018-06-21 04:15:13 +0800704 otError error = OT_ERROR_NONE;
705 otBorderRouterConfig borderRouterConfig;
Abtin Keshavarzian2c8f50b2017-09-01 21:27:58 -0700706 otNetworkDataIterator iter = OT_NETWORK_DATA_ITERATOR_INIT;
Buke Po818998e2017-08-04 01:19:07 +0800707
708 // Fill from non-local network data first
Abtin Keshavarzian2c8f50b2017-09-01 21:27:58 -0700709 while (otNetDataGetNextOnMeshPrefix(mInstance, &iter, &borderRouterConfig) == OT_ERROR_NONE)
Buke Po818998e2017-08-04 01:19:07 +0800710 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700711 SuccessOrExit(error = mEncoder.OpenStruct());
Buke Po818998e2017-08-04 01:19:07 +0800712
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700713 SuccessOrExit(error = mEncoder.WriteIp6Address(borderRouterConfig.mPrefix.mPrefix));
714 SuccessOrExit(error = mEncoder.WriteUint8(borderRouterConfig.mPrefix.mLength));
715 SuccessOrExit(error = mEncoder.WriteBool(borderRouterConfig.mStable));
716 SuccessOrExit(error = mEncoder.WriteUint8(BorderRouterConfigToFlagByte(borderRouterConfig)));
Yakun Xub8333732018-06-21 04:15:13 +0800717 SuccessOrExit(error = mEncoder.WriteBool(false)); // isLocal
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700718 SuccessOrExit(error = mEncoder.WriteUint16(borderRouterConfig.mRloc16));
719
720 SuccessOrExit(error = mEncoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +0800721 }
722
Jonathan Huif1849732019-07-16 12:31:11 -0700723#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
Abtin Keshavarzian2c8f50b2017-09-01 21:27:58 -0700724
725 iter = OT_NETWORK_DATA_ITERATOR_INIT;
726
Buke Po818998e2017-08-04 01:19:07 +0800727 // Fill from local network data last
Abtin Keshavarzian2c8f50b2017-09-01 21:27:58 -0700728 while (otBorderRouterGetNextOnMeshPrefix(mInstance, &iter, &borderRouterConfig) == OT_ERROR_NONE)
Buke Po818998e2017-08-04 01:19:07 +0800729 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700730 SuccessOrExit(error = mEncoder.OpenStruct());
Buke Po818998e2017-08-04 01:19:07 +0800731
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700732 SuccessOrExit(error = mEncoder.WriteIp6Address(borderRouterConfig.mPrefix.mPrefix));
733 SuccessOrExit(error = mEncoder.WriteUint8(borderRouterConfig.mPrefix.mLength));
734 SuccessOrExit(error = mEncoder.WriteBool(borderRouterConfig.mStable));
735 SuccessOrExit(error = mEncoder.WriteUint8(BorderRouterConfigToFlagByte(borderRouterConfig)));
Yakun Xub8333732018-06-21 04:15:13 +0800736 SuccessOrExit(error = mEncoder.WriteBool(true)); // isLocal
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700737 SuccessOrExit(error = mEncoder.WriteUint16(borderRouterConfig.mRloc16));
738
739 SuccessOrExit(error = mEncoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +0800740 }
Jonathan Huif1849732019-07-16 12:31:11 -0700741#endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
Buke Po818998e2017-08-04 01:19:07 +0800742
Buke Po818998e2017-08-04 01:19:07 +0800743exit:
Buke Po818998e2017-08-04 01:19:07 +0800744 return error;
745}
746
Jonathan Huif1849732019-07-16 12:31:11 -0700747#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
Yakun Xu8ccf1382018-06-29 00:26:31 +0800748template <> otError NcpBase::HandlePropertyInsert<SPINEL_PROP_THREAD_ON_MESH_NETS>(void)
Buke Po818998e2017-08-04 01:19:07 +0800749{
Yakun Xub8333732018-06-21 04:15:13 +0800750 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800751 otBorderRouterConfig borderRouterConfig;
Yakun Xub8333732018-06-21 04:15:13 +0800752 bool stable = false;
753 uint8_t flags = 0;
754 uint8_t prefixLength;
Buke Po818998e2017-08-04 01:19:07 +0800755
756 memset(&borderRouterConfig, 0, sizeof(otBorderRouterConfig));
757
Abtin Keshavarzian31ce3d42019-08-01 10:30:08 -0700758 VerifyOrExit(mAllowLocalNetworkDataChange, error = OT_ERROR_INVALID_STATE);
Buke Po818998e2017-08-04 01:19:07 +0800759
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700760 SuccessOrExit(error = mDecoder.ReadIp6Address(borderRouterConfig.mPrefix.mPrefix));
Łukasz Duda7b084ec2017-10-25 17:54:17 +0200761 SuccessOrExit(error = mDecoder.ReadUint8(prefixLength));
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700762 SuccessOrExit(error = mDecoder.ReadBool(stable));
763 SuccessOrExit(error = mDecoder.ReadUint8(flags));
Buke Po818998e2017-08-04 01:19:07 +0800764
Łukasz Duda7b084ec2017-10-25 17:54:17 +0200765 borderRouterConfig.mPrefix.mLength = prefixLength;
Yakun Xub8333732018-06-21 04:15:13 +0800766 borderRouterConfig.mStable = stable;
767 borderRouterConfig.mPreference = ((flags & SPINEL_NET_FLAG_PREFERENCE_MASK) >> SPINEL_NET_FLAG_PREFERENCE_OFFSET);
768 borderRouterConfig.mPreferred = ((flags & SPINEL_NET_FLAG_PREFERRED) != 0);
769 borderRouterConfig.mSlaac = ((flags & SPINEL_NET_FLAG_SLAAC) != 0);
770 borderRouterConfig.mDhcp = ((flags & SPINEL_NET_FLAG_DHCP) != 0);
771 borderRouterConfig.mConfigure = ((flags & SPINEL_NET_FLAG_CONFIGURE) != 0);
Buke Po818998e2017-08-04 01:19:07 +0800772 borderRouterConfig.mDefaultRoute = ((flags & SPINEL_NET_FLAG_DEFAULT_ROUTE) != 0);
Yakun Xub8333732018-06-21 04:15:13 +0800773 borderRouterConfig.mOnMesh = ((flags & SPINEL_NET_FLAG_ON_MESH) != 0);
Buke Po818998e2017-08-04 01:19:07 +0800774
775 error = otBorderRouterAddOnMeshPrefix(mInstance, &borderRouterConfig);
Buke Po818998e2017-08-04 01:19:07 +0800776
777exit:
Buke Po818998e2017-08-04 01:19:07 +0800778 return error;
779}
780
Yakun Xu8ccf1382018-06-29 00:26:31 +0800781template <> otError NcpBase::HandlePropertyRemove<SPINEL_PROP_THREAD_ON_MESH_NETS>(void)
Buke Po818998e2017-08-04 01:19:07 +0800782{
Yakun Xub8333732018-06-21 04:15:13 +0800783 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800784 otIp6Prefix ip6Prefix;
Yakun Xub8333732018-06-21 04:15:13 +0800785 uint8_t prefixLength;
Buke Po818998e2017-08-04 01:19:07 +0800786
787 memset(&ip6Prefix, 0, sizeof(otIp6Prefix));
788
Abtin Keshavarzian31ce3d42019-08-01 10:30:08 -0700789 VerifyOrExit(mAllowLocalNetworkDataChange, error = OT_ERROR_INVALID_STATE);
Buke Po818998e2017-08-04 01:19:07 +0800790
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700791 SuccessOrExit(error = mDecoder.ReadIp6Address(ip6Prefix.mPrefix));
Łukasz Duda7b084ec2017-10-25 17:54:17 +0200792 SuccessOrExit(error = mDecoder.ReadUint8(prefixLength));
793
794 ip6Prefix.mLength = prefixLength;
Buke Po818998e2017-08-04 01:19:07 +0800795
796 error = otBorderRouterRemoveOnMeshPrefix(mInstance, &ip6Prefix);
797
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700798 // If prefix was not on the list, "remove" command can be considred
799 // successful.
Abtin Keshavarzian02bdc692017-08-15 09:11:19 -0700800
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700801 if (error == OT_ERROR_NOT_FOUND)
Buke Po818998e2017-08-04 01:19:07 +0800802 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700803 error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800804 }
805
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700806exit:
Buke Po818998e2017-08-04 01:19:07 +0800807 return error;
808}
Jonathan Huif1849732019-07-16 12:31:11 -0700809#endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
Buke Po818998e2017-08-04 01:19:07 +0800810
Jonathan Hui149640d2019-07-16 11:06:03 -0700811#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
Joseph Newmanecad7172019-03-29 05:29:25 +0000812
813template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_SERVER_ALLOW_LOCAL_DATA_CHANGE>(void)
814{
815 return mEncoder.WriteBool(mAllowLocalServerDataChange);
816}
817
818template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_SERVER_ALLOW_LOCAL_DATA_CHANGE>(void)
819{
820 bool value = false;
821 otError error = OT_ERROR_NONE;
822 bool shouldRegisterWithLeader = false;
823
824 SuccessOrExit(error = mDecoder.ReadBool(value));
825
826 // Register any server data changes on transition from `true` to `false`.
827 shouldRegisterWithLeader = (mAllowLocalServerDataChange == true) && (value == false);
828
829 mAllowLocalServerDataChange = value;
830
831exit:
832
833 if (shouldRegisterWithLeader)
834 {
kangping49f36f82020-05-07 02:17:58 +0800835 IgnoreError(otServerRegister(mInstance));
Joseph Newmanecad7172019-03-29 05:29:25 +0000836 }
837
838 return error;
839}
840
841template <> otError NcpBase::HandlePropertyInsert<SPINEL_PROP_SERVER_SERVICES>(void)
842{
843 otError error = OT_ERROR_NONE;
844 otServiceConfig cfg;
845 bool stable;
846 const uint8_t * data;
847 uint16_t dataLen;
848
Abtin Keshavarzian31ce3d42019-08-01 10:30:08 -0700849 VerifyOrExit(mAllowLocalServerDataChange, error = OT_ERROR_INVALID_STATE);
Joseph Newmanecad7172019-03-29 05:29:25 +0000850
851 SuccessOrExit(error = mDecoder.ReadUint32(cfg.mEnterpriseNumber));
852 SuccessOrExit(error = mDecoder.ReadDataWithLen(data, dataLen));
853
854 VerifyOrExit((dataLen <= sizeof(cfg.mServiceData)), error = OT_ERROR_INVALID_ARGS);
855 memcpy(cfg.mServiceData, data, dataLen);
856
Abtin Keshavarzian53d23b52020-06-20 18:09:14 -0700857 static_assert((sizeof(cfg.mServiceData) <= UINT8_MAX), "Cannot handle full range of buffer length");
Joseph Newmanecad7172019-03-29 05:29:25 +0000858 cfg.mServiceDataLength = static_cast<uint8_t>(dataLen);
859
860 SuccessOrExit(error = mDecoder.ReadBool(stable));
861 cfg.mServerConfig.mStable = stable;
862 SuccessOrExit(error = mDecoder.ReadDataWithLen(data, dataLen));
863
864 VerifyOrExit((dataLen <= sizeof(cfg.mServerConfig.mServerData)), error = OT_ERROR_INVALID_ARGS);
865 memcpy(cfg.mServerConfig.mServerData, data, dataLen);
866
Abtin Keshavarzian53d23b52020-06-20 18:09:14 -0700867 static_assert((sizeof(cfg.mServerConfig.mServerData) <= UINT8_MAX), "Cannot handle full range of buffer length");
Joseph Newmanecad7172019-03-29 05:29:25 +0000868 cfg.mServerConfig.mServerDataLength = static_cast<uint8_t>(dataLen);
869
870 SuccessOrExit(error = otServerAddService(mInstance, &cfg));
871exit:
872 return error;
873}
874
875template <> otError NcpBase::HandlePropertyRemove<SPINEL_PROP_SERVER_SERVICES>(void)
876{
877 otError error = OT_ERROR_NONE;
878
879 uint32_t enterpriseNumber;
880 const uint8_t *serviceData;
881 uint16_t serviceDataLength;
882
Abtin Keshavarzian31ce3d42019-08-01 10:30:08 -0700883 VerifyOrExit(mAllowLocalServerDataChange, error = OT_ERROR_INVALID_STATE);
Joseph Newmanecad7172019-03-29 05:29:25 +0000884
885 SuccessOrExit(error = mDecoder.ReadUint32(enterpriseNumber));
886 SuccessOrExit(error = mDecoder.ReadDataWithLen(serviceData, serviceDataLength));
887
888 VerifyOrExit(serviceDataLength <= UINT8_MAX, error = OT_ERROR_INVALID_ARGS);
889
890 SuccessOrExit(error = otServerRemoveService(mInstance, enterpriseNumber, serviceData,
891 static_cast<uint8_t>(serviceDataLength)));
892exit:
893 return error;
894}
895
896template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_SERVER_SERVICES>(void)
897{
898 otError error = OT_ERROR_NONE;
899 otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
900 otServiceConfig cfg;
901
902 while (otServerGetNextService(mInstance, &iterator, &cfg) == OT_ERROR_NONE)
903 {
904 SuccessOrExit(error = mEncoder.OpenStruct());
905
906 SuccessOrExit(error = mEncoder.WriteUint32(cfg.mEnterpriseNumber));
907 SuccessOrExit(error = mEncoder.WriteDataWithLen(cfg.mServiceData, cfg.mServiceDataLength));
908 SuccessOrExit(error = mEncoder.WriteBool(cfg.mServerConfig.mStable));
909 SuccessOrExit(
910 error = mEncoder.WriteDataWithLen(cfg.mServerConfig.mServerData, cfg.mServerConfig.mServerDataLength));
911 SuccessOrExit(error = mEncoder.WriteUint16(cfg.mServerConfig.mRloc16));
912
913 SuccessOrExit(error = mEncoder.CloseStruct());
914 }
915exit:
916 return error;
917}
Rongli Sune8600092019-12-03 00:42:46 +0800918#endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
Joseph Newmanecad7172019-03-29 05:29:25 +0000919
920template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_SERVER_LEADER_SERVICES>(void)
921{
922 otError error = OT_ERROR_NONE;
923 otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
924 otServiceConfig cfg;
925
Rongli Sune8600092019-12-03 00:42:46 +0800926 while (otNetDataGetNextService(mInstance, &iterator, &cfg) == OT_ERROR_NONE)
Joseph Newmanecad7172019-03-29 05:29:25 +0000927 {
928 SuccessOrExit(error = mEncoder.OpenStruct());
929
Rongli Sun315a27b2020-03-26 23:54:23 +0800930 SuccessOrExit(error = mEncoder.WriteUint8(cfg.mServiceId));
Joseph Newmanecad7172019-03-29 05:29:25 +0000931 SuccessOrExit(error = mEncoder.WriteUint32(cfg.mEnterpriseNumber));
932 SuccessOrExit(error = mEncoder.WriteDataWithLen(cfg.mServiceData, cfg.mServiceDataLength));
933 SuccessOrExit(error = mEncoder.WriteBool(cfg.mServerConfig.mStable));
934 SuccessOrExit(
935 error = mEncoder.WriteDataWithLen(cfg.mServerConfig.mServerData, cfg.mServerConfig.mServerDataLength));
936 SuccessOrExit(error = mEncoder.WriteUint16(cfg.mServerConfig.mRloc16));
937
938 SuccessOrExit(error = mEncoder.CloseStruct());
939 }
940exit:
941 return error;
942}
943
Yakun Xu8ccf1382018-06-29 00:26:31 +0800944template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_DISCOVERY_SCAN_JOINER_FLAG>(void)
Buke Po818998e2017-08-04 01:19:07 +0800945{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700946 return mEncoder.WriteBool(mDiscoveryScanJoinerFlag);
Buke Po818998e2017-08-04 01:19:07 +0800947}
948
Yakun Xu8ccf1382018-06-29 00:26:31 +0800949template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_DISCOVERY_SCAN_JOINER_FLAG>(void)
Buke Po818998e2017-08-04 01:19:07 +0800950{
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700951 return mDecoder.ReadBool(mDiscoveryScanJoinerFlag);
Buke Po818998e2017-08-04 01:19:07 +0800952}
953
Yakun Xu8ccf1382018-06-29 00:26:31 +0800954template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_DISCOVERY_SCAN_ENABLE_FILTERING>(void)
Buke Po818998e2017-08-04 01:19:07 +0800955{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700956 return mEncoder.WriteBool(mDiscoveryScanEnableFiltering);
Buke Po818998e2017-08-04 01:19:07 +0800957}
958
Yakun Xu8ccf1382018-06-29 00:26:31 +0800959template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_DISCOVERY_SCAN_ENABLE_FILTERING>(void)
Buke Po818998e2017-08-04 01:19:07 +0800960{
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700961 return mDecoder.ReadBool(mDiscoveryScanEnableFiltering);
Buke Po818998e2017-08-04 01:19:07 +0800962}
963
Yakun Xu8ccf1382018-06-29 00:26:31 +0800964template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_DISCOVERY_SCAN_PANID>(void)
Buke Po818998e2017-08-04 01:19:07 +0800965{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700966 return mEncoder.WriteUint16(mDiscoveryScanPanId);
Buke Po818998e2017-08-04 01:19:07 +0800967}
968
Yakun Xu8ccf1382018-06-29 00:26:31 +0800969template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_DISCOVERY_SCAN_PANID>(void)
Buke Po818998e2017-08-04 01:19:07 +0800970{
Yakun Xub8333732018-06-21 04:15:13 +0800971 return mDecoder.ReadUint16(mDiscoveryScanPanId);
Buke Po818998e2017-08-04 01:19:07 +0800972}
973
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -0800974otError NcpBase::EncodeOperationalDataset(const otOperationalDataset &aDataset)
975{
976 otError error = OT_ERROR_NONE;
977
Abtin Keshavarzian758e6472018-07-19 14:33:49 -0700978 if (aDataset.mComponents.mIsActiveTimestampPresent)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -0800979 {
980 SuccessOrExit(mEncoder.OpenStruct());
981 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_DATASET_ACTIVE_TIMESTAMP));
982 SuccessOrExit(mEncoder.WriteUint64(aDataset.mActiveTimestamp));
983 SuccessOrExit(mEncoder.CloseStruct());
984 }
985
Abtin Keshavarzian758e6472018-07-19 14:33:49 -0700986 if (aDataset.mComponents.mIsPendingTimestampPresent)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -0800987 {
988 SuccessOrExit(mEncoder.OpenStruct());
989 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_DATASET_PENDING_TIMESTAMP));
990 SuccessOrExit(mEncoder.WriteUint64(aDataset.mPendingTimestamp));
991 SuccessOrExit(mEncoder.CloseStruct());
992 }
993
Abtin Keshavarzian758e6472018-07-19 14:33:49 -0700994 if (aDataset.mComponents.mIsMasterKeyPresent)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -0800995 {
996 SuccessOrExit(mEncoder.OpenStruct());
997 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_NET_MASTER_KEY));
998 SuccessOrExit(mEncoder.WriteData(aDataset.mMasterKey.m8, OT_MASTER_KEY_SIZE));
999 SuccessOrExit(mEncoder.CloseStruct());
1000 }
1001
Abtin Keshavarzian758e6472018-07-19 14:33:49 -07001002 if (aDataset.mComponents.mIsNetworkNamePresent)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001003 {
1004 SuccessOrExit(mEncoder.OpenStruct());
1005 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_NET_NETWORK_NAME));
1006 SuccessOrExit(mEncoder.WriteUtf8(aDataset.mNetworkName.m8));
1007 SuccessOrExit(mEncoder.CloseStruct());
1008 }
1009
Abtin Keshavarzian758e6472018-07-19 14:33:49 -07001010 if (aDataset.mComponents.mIsExtendedPanIdPresent)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001011 {
1012 SuccessOrExit(mEncoder.OpenStruct());
1013 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_NET_XPANID));
1014 SuccessOrExit(mEncoder.WriteData(aDataset.mExtendedPanId.m8, OT_EXT_PAN_ID_SIZE));
1015 SuccessOrExit(mEncoder.CloseStruct());
1016 }
1017
Abtin Keshavarzian758e6472018-07-19 14:33:49 -07001018 if (aDataset.mComponents.mIsMeshLocalPrefixPresent)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001019 {
1020 otIp6Address addr;
1021
1022 memcpy(addr.mFields.m8, aDataset.mMeshLocalPrefix.m8, 8);
Yakun Xub8333732018-06-21 04:15:13 +08001023 memset(addr.mFields.m8 + 8, 0, 8); // Zero out the last 8 bytes.
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001024
1025 SuccessOrExit(mEncoder.OpenStruct());
1026 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_IPV6_ML_PREFIX));
Jintao Lin8788cf52020-01-10 10:15:23 +08001027 SuccessOrExit(error = mEncoder.WriteIp6Address(addr)); // Mesh local prefix
1028 SuccessOrExit(error = mEncoder.WriteUint8(OT_IP6_PREFIX_BITSIZE)); // Prefix length (in bits)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001029 SuccessOrExit(mEncoder.CloseStruct());
1030 }
1031
Abtin Keshavarzian758e6472018-07-19 14:33:49 -07001032 if (aDataset.mComponents.mIsDelayPresent)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001033 {
1034 SuccessOrExit(mEncoder.OpenStruct());
1035 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_DATASET_DELAY_TIMER));
1036 SuccessOrExit(mEncoder.WriteUint32(aDataset.mDelay));
1037 SuccessOrExit(mEncoder.CloseStruct());
1038 }
1039
Abtin Keshavarzian758e6472018-07-19 14:33:49 -07001040 if (aDataset.mComponents.mIsPanIdPresent)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001041 {
1042 SuccessOrExit(mEncoder.OpenStruct());
1043 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_MAC_15_4_PANID));
1044 SuccessOrExit(mEncoder.WriteUint16(aDataset.mPanId));
1045 SuccessOrExit(mEncoder.CloseStruct());
1046 }
1047
Abtin Keshavarzian758e6472018-07-19 14:33:49 -07001048 if (aDataset.mComponents.mIsChannelPresent)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001049 {
1050 SuccessOrExit(mEncoder.OpenStruct());
1051 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_PHY_CHAN));
1052
1053 // The channel is stored in Dataset as `uint16_t` (to accommodate
1054 // larger number of channels in sub-GHz band), however the current
1055 // definition of `SPINEL_PROP_PHY_CHAN` property limits the channel
1056 // to a `uint8_t`.
1057
1058 SuccessOrExit(mEncoder.WriteUint8(static_cast<uint8_t>(aDataset.mChannel)));
1059 SuccessOrExit(mEncoder.CloseStruct());
1060 }
1061
Abtin Keshavarzian1555b212019-09-18 19:11:07 -07001062 if (aDataset.mComponents.mIsPskcPresent)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001063 {
1064 SuccessOrExit(mEncoder.OpenStruct());
1065 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_NET_PSKC));
Abtin Keshavarzian1555b212019-09-18 19:11:07 -07001066 SuccessOrExit(mEncoder.WriteData(aDataset.mPskc.m8, sizeof(spinel_net_pskc_t)));
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001067 SuccessOrExit(mEncoder.CloseStruct());
1068 }
1069
Abtin Keshavarzian758e6472018-07-19 14:33:49 -07001070 if (aDataset.mComponents.mIsSecurityPolicyPresent)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001071 {
1072 SuccessOrExit(mEncoder.OpenStruct());
1073 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_DATASET_SECURITY_POLICY));
1074 SuccessOrExit(mEncoder.WriteUint16(aDataset.mSecurityPolicy.mRotationTime));
1075 SuccessOrExit(mEncoder.WriteUint8(aDataset.mSecurityPolicy.mFlags));
1076 SuccessOrExit(mEncoder.CloseStruct());
1077 }
1078
Zhanglong Xiace24abb2019-03-13 22:49:25 +08001079 if (aDataset.mComponents.mIsChannelMaskPresent)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001080 {
1081 SuccessOrExit(mEncoder.OpenStruct());
1082 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_PHY_CHAN_SUPPORTED));
Zhanglong Xiace24abb2019-03-13 22:49:25 +08001083 SuccessOrExit(EncodeChannelMask(aDataset.mChannelMask));
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001084 SuccessOrExit(mEncoder.CloseStruct());
1085 }
1086
1087exit:
1088 return error;
1089}
1090
Yakun Xu8ccf1382018-06-29 00:26:31 +08001091template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_ACTIVE_DATASET>(void)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001092{
1093 otOperationalDataset dataset;
1094
kangping49f36f82020-05-07 02:17:58 +08001095 IgnoreError(otDatasetGetActive(mInstance, &dataset));
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001096 return EncodeOperationalDataset(dataset);
1097}
1098
Yakun Xu8ccf1382018-06-29 00:26:31 +08001099template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_PENDING_DATASET>(void)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001100{
1101 otOperationalDataset dataset;
1102
kangping49f36f82020-05-07 02:17:58 +08001103 IgnoreError(otDatasetGetPending(mInstance, &dataset));
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001104 return EncodeOperationalDataset(dataset);
1105}
1106
rongli1253bec2018-12-04 13:28:09 +08001107otError NcpBase::DecodeOperationalDataset(otOperationalDataset &aDataset,
1108 const uint8_t ** aTlvs,
1109 uint8_t * aTlvsLength,
1110 const otIp6Address ** aDestIpAddress,
Jonathan Hui49c4b632019-03-21 09:52:32 -07001111 bool aAllowEmptyValues)
rongli1253bec2018-12-04 13:28:09 +08001112{
1113 otError error = OT_ERROR_NONE;
1114
1115 memset(&aDataset, 0, sizeof(otOperationalDataset));
1116
Jonathan Hui1326d642020-06-17 22:44:54 -07001117 if (aTlvs != nullptr)
rongli1253bec2018-12-04 13:28:09 +08001118 {
Jonathan Hui1326d642020-06-17 22:44:54 -07001119 *aTlvs = nullptr;
rongli1253bec2018-12-04 13:28:09 +08001120 }
1121
Jonathan Hui1326d642020-06-17 22:44:54 -07001122 if (aTlvsLength != nullptr)
rongli1253bec2018-12-04 13:28:09 +08001123 {
1124 *aTlvsLength = 0;
1125 }
1126
Jonathan Hui1326d642020-06-17 22:44:54 -07001127 if (aDestIpAddress != nullptr)
rongli1253bec2018-12-04 13:28:09 +08001128 {
Jonathan Hui1326d642020-06-17 22:44:54 -07001129 *aDestIpAddress = nullptr;
rongli1253bec2018-12-04 13:28:09 +08001130 }
1131
1132 while (!mDecoder.IsAllReadInStruct())
1133 {
1134 unsigned int propKey;
1135
1136 SuccessOrExit(error = mDecoder.OpenStruct());
1137 SuccessOrExit(error = mDecoder.ReadUintPacked(propKey));
1138
1139 switch (static_cast<spinel_prop_key_t>(propKey))
1140 {
1141 case SPINEL_PROP_DATASET_ACTIVE_TIMESTAMP:
1142
Jonathan Hui49c4b632019-03-21 09:52:32 -07001143 if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
rongli1253bec2018-12-04 13:28:09 +08001144 {
1145 SuccessOrExit(error = mDecoder.ReadUint64(aDataset.mActiveTimestamp));
1146 }
1147
1148 aDataset.mComponents.mIsActiveTimestampPresent = true;
1149 break;
1150
1151 case SPINEL_PROP_DATASET_PENDING_TIMESTAMP:
1152
Jonathan Hui49c4b632019-03-21 09:52:32 -07001153 if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
rongli1253bec2018-12-04 13:28:09 +08001154 {
1155 SuccessOrExit(error = mDecoder.ReadUint64(aDataset.mPendingTimestamp));
1156 }
1157
1158 aDataset.mComponents.mIsPendingTimestampPresent = true;
1159 break;
1160
1161 case SPINEL_PROP_NET_MASTER_KEY:
1162
Jonathan Hui49c4b632019-03-21 09:52:32 -07001163 if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
rongli1253bec2018-12-04 13:28:09 +08001164 {
1165 const uint8_t *key;
1166 uint16_t len;
1167
1168 SuccessOrExit(error = mDecoder.ReadData(key, len));
1169 VerifyOrExit(len == OT_MASTER_KEY_SIZE, error = OT_ERROR_INVALID_ARGS);
1170 memcpy(aDataset.mMasterKey.m8, key, len);
1171 }
1172
1173 aDataset.mComponents.mIsMasterKeyPresent = true;
1174 break;
1175
1176 case SPINEL_PROP_NET_NETWORK_NAME:
1177
Jonathan Hui49c4b632019-03-21 09:52:32 -07001178 if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
rongli1253bec2018-12-04 13:28:09 +08001179 {
1180 const char *name;
1181 size_t len;
1182
1183 SuccessOrExit(error = mDecoder.ReadUtf8(name));
1184 len = strlen(name);
1185 VerifyOrExit(len <= OT_NETWORK_NAME_MAX_SIZE, error = OT_ERROR_INVALID_ARGS);
1186 memcpy(aDataset.mNetworkName.m8, name, len + 1);
1187 }
1188
1189 aDataset.mComponents.mIsNetworkNamePresent = true;
1190 break;
1191
1192 case SPINEL_PROP_NET_XPANID:
1193
Jonathan Hui49c4b632019-03-21 09:52:32 -07001194 if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
rongli1253bec2018-12-04 13:28:09 +08001195 {
1196 const uint8_t *xpanid;
1197 uint16_t len;
1198
1199 SuccessOrExit(error = mDecoder.ReadData(xpanid, len));
1200 VerifyOrExit(len == OT_EXT_PAN_ID_SIZE, error = OT_ERROR_INVALID_ARGS);
1201 memcpy(aDataset.mExtendedPanId.m8, xpanid, len);
1202 }
1203
1204 aDataset.mComponents.mIsExtendedPanIdPresent = true;
1205 break;
1206
1207 case SPINEL_PROP_IPV6_ML_PREFIX:
1208
Jonathan Hui49c4b632019-03-21 09:52:32 -07001209 if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
rongli1253bec2018-12-04 13:28:09 +08001210 {
1211 const otIp6Address *addr;
1212 uint8_t prefixLen;
1213
1214 SuccessOrExit(error = mDecoder.ReadIp6Address(addr));
1215 SuccessOrExit(error = mDecoder.ReadUint8(prefixLen));
Jintao Lin8788cf52020-01-10 10:15:23 +08001216 VerifyOrExit(prefixLen == OT_IP6_PREFIX_BITSIZE, error = OT_ERROR_INVALID_ARGS);
rongli1253bec2018-12-04 13:28:09 +08001217 memcpy(aDataset.mMeshLocalPrefix.m8, addr, OT_MESH_LOCAL_PREFIX_SIZE);
1218 }
1219
1220 aDataset.mComponents.mIsMeshLocalPrefixPresent = true;
1221 break;
1222
1223 case SPINEL_PROP_DATASET_DELAY_TIMER:
1224
Jonathan Hui49c4b632019-03-21 09:52:32 -07001225 if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
rongli1253bec2018-12-04 13:28:09 +08001226 {
1227 SuccessOrExit(error = mDecoder.ReadUint32(aDataset.mDelay));
1228 }
1229
1230 aDataset.mComponents.mIsDelayPresent = true;
1231 break;
1232
1233 case SPINEL_PROP_MAC_15_4_PANID:
1234
Jonathan Hui49c4b632019-03-21 09:52:32 -07001235 if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
rongli1253bec2018-12-04 13:28:09 +08001236 {
1237 SuccessOrExit(error = mDecoder.ReadUint16(aDataset.mPanId));
1238 }
1239
1240 aDataset.mComponents.mIsPanIdPresent = true;
1241 break;
1242
1243 case SPINEL_PROP_PHY_CHAN:
1244
Jonathan Hui49c4b632019-03-21 09:52:32 -07001245 if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
rongli1253bec2018-12-04 13:28:09 +08001246 {
1247 uint8_t channel;
1248
1249 SuccessOrExit(error = mDecoder.ReadUint8(channel));
1250 aDataset.mChannel = channel;
1251 }
1252
1253 aDataset.mComponents.mIsChannelPresent = true;
1254 break;
1255
1256 case SPINEL_PROP_NET_PSKC:
1257
Jonathan Hui49c4b632019-03-21 09:52:32 -07001258 if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
rongli1253bec2018-12-04 13:28:09 +08001259 {
1260 const uint8_t *psk;
1261 uint16_t len;
1262
1263 SuccessOrExit(error = mDecoder.ReadData(psk, len));
1264 VerifyOrExit(len == OT_PSKC_MAX_SIZE, error = OT_ERROR_INVALID_ARGS);
Abtin Keshavarzian1555b212019-09-18 19:11:07 -07001265 memcpy(aDataset.mPskc.m8, psk, OT_PSKC_MAX_SIZE);
rongli1253bec2018-12-04 13:28:09 +08001266 }
1267
Abtin Keshavarzian1555b212019-09-18 19:11:07 -07001268 aDataset.mComponents.mIsPskcPresent = true;
rongli1253bec2018-12-04 13:28:09 +08001269 break;
1270
1271 case SPINEL_PROP_DATASET_SECURITY_POLICY:
1272
Jonathan Hui49c4b632019-03-21 09:52:32 -07001273 if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
rongli1253bec2018-12-04 13:28:09 +08001274 {
1275 SuccessOrExit(error = mDecoder.ReadUint16(aDataset.mSecurityPolicy.mRotationTime));
1276 SuccessOrExit(error = mDecoder.ReadUint8(aDataset.mSecurityPolicy.mFlags));
1277 }
1278
1279 aDataset.mComponents.mIsSecurityPolicyPresent = true;
1280 break;
1281
1282 case SPINEL_PROP_PHY_CHAN_SUPPORTED:
1283
Jonathan Hui49c4b632019-03-21 09:52:32 -07001284 if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
rongli1253bec2018-12-04 13:28:09 +08001285 {
1286 uint8_t channel;
1287
Zhanglong Xiace24abb2019-03-13 22:49:25 +08001288 aDataset.mChannelMask = 0;
rongli1253bec2018-12-04 13:28:09 +08001289
1290 while (!mDecoder.IsAllReadInStruct())
1291 {
1292 SuccessOrExit(error = mDecoder.ReadUint8(channel));
1293 VerifyOrExit(channel <= 31, error = OT_ERROR_INVALID_ARGS);
Zhanglong Xiace24abb2019-03-13 22:49:25 +08001294 aDataset.mChannelMask |= (1UL << channel);
rongli1253bec2018-12-04 13:28:09 +08001295 }
1296 }
1297
Zhanglong Xiace24abb2019-03-13 22:49:25 +08001298 aDataset.mComponents.mIsChannelMaskPresent = true;
rongli1253bec2018-12-04 13:28:09 +08001299 break;
1300
1301 case SPINEL_PROP_DATASET_RAW_TLVS:
1302
Jonathan Hui49c4b632019-03-21 09:52:32 -07001303 if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
rongli1253bec2018-12-04 13:28:09 +08001304 {
1305 const uint8_t *tlvs;
1306 uint16_t len;
1307
1308 SuccessOrExit(error = mDecoder.ReadData(tlvs, len));
1309 VerifyOrExit(len <= 255, error = OT_ERROR_INVALID_ARGS);
1310
Jonathan Hui1326d642020-06-17 22:44:54 -07001311 if (aTlvs != nullptr)
rongli1253bec2018-12-04 13:28:09 +08001312 {
1313 *aTlvs = tlvs;
1314 }
1315
Jonathan Hui1326d642020-06-17 22:44:54 -07001316 if (aTlvsLength != nullptr)
rongli1253bec2018-12-04 13:28:09 +08001317 {
1318 *aTlvsLength = static_cast<uint8_t>(len);
1319 }
1320 }
1321
1322 break;
1323
1324 case SPINEL_PROP_DATASET_DEST_ADDRESS:
1325
Jonathan Hui49c4b632019-03-21 09:52:32 -07001326 if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
rongli1253bec2018-12-04 13:28:09 +08001327 {
1328 const otIp6Address *addr;
1329
1330 SuccessOrExit(error = mDecoder.ReadIp6Address(addr));
1331
Jonathan Hui1326d642020-06-17 22:44:54 -07001332 if (aDestIpAddress != nullptr)
rongli1253bec2018-12-04 13:28:09 +08001333 {
1334 *aDestIpAddress = addr;
1335 }
1336 }
1337
1338 break;
1339
1340 default:
1341 break;
1342 }
1343
1344 SuccessOrExit(error = mDecoder.CloseStruct());
1345 }
1346
1347exit:
1348 return error;
1349}
1350
1351template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_ACTIVE_DATASET>(void)
1352{
1353 otError error = OT_ERROR_NONE;
1354 otOperationalDataset dataset;
1355
1356 SuccessOrExit(error = DecodeOperationalDataset(dataset));
1357 error = otDatasetSetActive(mInstance, &dataset);
1358
1359exit:
1360 return error;
1361}
1362
1363template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_PENDING_DATASET>(void)
1364{
1365 otError error = OT_ERROR_NONE;
1366 otOperationalDataset dataset;
1367
1368 SuccessOrExit(error = DecodeOperationalDataset(dataset));
1369 error = otDatasetSetPending(mInstance, &dataset);
1370
1371exit:
1372 return error;
1373}
1374
1375template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_MGMT_SET_ACTIVE_DATASET>(void)
1376{
1377 otError error = OT_ERROR_NONE;
1378 otOperationalDataset dataset;
1379 const uint8_t * extraTlvs;
1380 uint8_t extraTlvsLength;
1381
1382 SuccessOrExit(error = DecodeOperationalDataset(dataset, &extraTlvs, &extraTlvsLength));
1383 error = otDatasetSendMgmtActiveSet(mInstance, &dataset, extraTlvs, extraTlvsLength);
1384
1385exit:
1386 return error;
1387}
1388
1389template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_MGMT_SET_PENDING_DATASET>(void)
1390{
1391 otError error = OT_ERROR_NONE;
1392 otOperationalDataset dataset;
1393 const uint8_t * extraTlvs;
1394 uint8_t extraTlvsLength;
1395
1396 SuccessOrExit(error = DecodeOperationalDataset(dataset, &extraTlvs, &extraTlvsLength));
1397 error = otDatasetSendMgmtPendingSet(mInstance, &dataset, extraTlvs, extraTlvsLength);
1398
1399exit:
1400 return error;
1401}
1402
1403template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_MGMT_GET_ACTIVE_DATASET>(void)
1404{
1405 otError error = OT_ERROR_NONE;
1406 otOperationalDataset dataset;
1407 const uint8_t * extraTlvs;
1408 uint8_t extraTlvsLength;
1409 const otIp6Address * destIpAddress;
1410
1411 SuccessOrExit(error = DecodeOperationalDataset(dataset, &extraTlvs, &extraTlvsLength, &destIpAddress, true));
1412 error = otDatasetSendMgmtActiveGet(mInstance, &dataset.mComponents, extraTlvs, extraTlvsLength, destIpAddress);
1413
1414exit:
1415 return error;
1416}
1417
1418template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_MGMT_GET_PENDING_DATASET>(void)
1419{
1420 otError error = OT_ERROR_NONE;
1421 otOperationalDataset dataset;
1422 const uint8_t * extraTlvs;
1423 uint8_t extraTlvsLength;
1424 const otIp6Address * destIpAddress;
1425
1426 SuccessOrExit(error = DecodeOperationalDataset(dataset, &extraTlvs, &extraTlvsLength, &destIpAddress, true));
1427 error = otDatasetSendMgmtPendingGet(mInstance, &dataset.mComponents, extraTlvs, extraTlvsLength, destIpAddress);
1428
1429exit:
1430 return error;
1431}
Jonathan Hui31ffd162019-07-16 12:01:36 -07001432#if OPENTHREAD_CONFIG_JOINER_ENABLE
rongli90ee0a42018-08-09 02:18:53 +08001433template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MESHCOP_JOINER_STATE>(void)
1434{
Abtin Keshavarzian99f57902019-04-22 10:04:54 -07001435 spinel_meshcop_joiner_state_t state = SPINEL_MESHCOP_JOINER_STATE_IDLE;
1436
1437 switch (otJoinerGetState(mInstance))
1438 {
1439 case OT_JOINER_STATE_IDLE:
1440 state = SPINEL_MESHCOP_JOINER_STATE_IDLE;
1441 break;
1442 case OT_JOINER_STATE_DISCOVER:
1443 state = SPINEL_MESHCOP_JOINER_STATE_DISCOVER;
1444 break;
1445 case OT_JOINER_STATE_CONNECT:
1446 state = SPINEL_MESHCOP_JOINER_STATE_CONNECTING;
1447 break;
1448 case OT_JOINER_STATE_CONNECTED:
1449 state = SPINEL_MESHCOP_JOINER_STATE_CONNECTED;
1450 break;
1451 case OT_JOINER_STATE_ENTRUST:
1452 state = SPINEL_MESHCOP_JOINER_STATE_ENTRUST;
1453 break;
1454 case OT_JOINER_STATE_JOINED:
1455 state = SPINEL_MESHCOP_JOINER_STATE_JOINED;
1456 break;
1457 }
1458
1459 return mEncoder.WriteUint8(state);
rongli90ee0a42018-08-09 02:18:53 +08001460}
1461
1462template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MESHCOP_JOINER_COMMISSIONING>(void)
1463{
Abtin Keshavarzian987e96b2019-04-17 19:08:11 -07001464 otError error = OT_ERROR_NONE;
rongli90ee0a42018-08-09 02:18:53 +08001465 bool action = false;
Jonathan Hui1326d642020-06-17 22:44:54 -07001466 const char *psk = nullptr;
1467 const char *provisioningUrl = nullptr;
1468 const char *vendorName = nullptr;
1469 const char *vendorModel = nullptr;
1470 const char *vendorSwVersion = nullptr;
1471 const char *vendorData = nullptr;
rongli90ee0a42018-08-09 02:18:53 +08001472
1473 SuccessOrExit(error = mDecoder.ReadBool(action));
rongli90ee0a42018-08-09 02:18:53 +08001474
Abtin Keshavarzian987e96b2019-04-17 19:08:11 -07001475 if (action == false)
rongli90ee0a42018-08-09 02:18:53 +08001476 {
Yakun Xu957d79d2019-09-10 23:42:02 +08001477 otJoinerStop(mInstance);
Abtin Keshavarzian987e96b2019-04-17 19:08:11 -07001478 ExitNow();
rongli90ee0a42018-08-09 02:18:53 +08001479 }
Abtin Keshavarzian987e96b2019-04-17 19:08:11 -07001480
1481 SuccessOrExit(error = mDecoder.ReadUtf8(psk));
1482
1483 // Parse optional fields
1484
1485 if (!mDecoder.IsAllReadInStruct())
1486 {
1487 SuccessOrExit(error = mDecoder.ReadUtf8(provisioningUrl));
1488 }
1489
1490 if (!mDecoder.IsAllReadInStruct())
1491 {
1492 SuccessOrExit(error = mDecoder.ReadUtf8(vendorName));
1493 }
1494
1495 if (!mDecoder.IsAllReadInStruct())
1496 {
1497 SuccessOrExit(error = mDecoder.ReadUtf8(vendorModel));
1498 }
1499
1500 if (!mDecoder.IsAllReadInStruct())
1501 {
1502 SuccessOrExit(error = mDecoder.ReadUtf8(vendorSwVersion));
1503 }
1504
1505 if (!mDecoder.IsAllReadInStruct())
1506 {
1507 SuccessOrExit(error = mDecoder.ReadUtf8(vendorData));
1508 }
1509
1510 // Use OpenThread default values for vendor name, mode, sw version if
1511 // not specified or an empty string is given.
1512
Jonathan Hui1326d642020-06-17 22:44:54 -07001513 if ((vendorName == nullptr) || (vendorName[0] == 0))
Abtin Keshavarzian987e96b2019-04-17 19:08:11 -07001514 {
1515 vendorName = PACKAGE_NAME;
1516 }
1517
Jonathan Hui1326d642020-06-17 22:44:54 -07001518 if ((vendorModel == nullptr) || (vendorModel[0] == 0))
Abtin Keshavarzian987e96b2019-04-17 19:08:11 -07001519 {
1520 vendorModel = OPENTHREAD_CONFIG_PLATFORM_INFO;
1521 }
1522
Jonathan Hui1326d642020-06-17 22:44:54 -07001523 if ((vendorSwVersion == nullptr) || (vendorSwVersion[0] == 0))
Abtin Keshavarzian987e96b2019-04-17 19:08:11 -07001524 {
1525 vendorSwVersion = PACKAGE_VERSION;
1526 }
1527
1528 error = otJoinerStart(mInstance, psk, provisioningUrl, vendorName, vendorModel, vendorSwVersion, vendorData,
1529 &NcpBase::HandleJoinerCallback_Jump, this);
1530
rongli90ee0a42018-08-09 02:18:53 +08001531exit:
1532 return error;
1533}
1534
Abtin Keshavarziana7415b52020-06-20 00:35:57 -07001535template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MESHCOP_JOINER_DISCERNER>(void)
1536{
1537 otError error;
1538 const otJoinerDiscerner *discerner = otJoinerGetDiscerner(mInstance);
1539
1540 if (discerner == nullptr)
1541 {
1542 SuccessOrExit(error = mEncoder.WriteUint8(0));
1543 }
1544 else
1545 {
1546 SuccessOrExit(error = mEncoder.WriteUint8(discerner->mLength));
1547 SuccessOrExit(error = mEncoder.WriteUint64(discerner->mValue));
1548 }
1549
1550exit:
1551 return error;
1552}
1553
1554template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MESHCOP_JOINER_DISCERNER>(void)
1555{
1556 otError error = OT_ERROR_NONE;
1557 otJoinerDiscerner discerner;
1558
1559 SuccessOrExit(error = mDecoder.ReadUint8(discerner.mLength));
1560
1561 if (discerner.mLength == 0)
1562 {
1563 // Clearing any previously set Joiner Discerner
1564 error = otJoinerSetDiscerner(mInstance, nullptr);
1565 ExitNow();
1566 }
1567
1568 SuccessOrExit(error = mDecoder.ReadUint64(discerner.mValue));
1569 error = otJoinerSetDiscerner(mInstance, &discerner);
1570
1571exit:
1572 return error;
1573}
1574
1575#endif // OPENTHREAD_CONFIG_JOINER_ENABLE
rongli90ee0a42018-08-09 02:18:53 +08001576
Yakun Xu8ccf1382018-06-29 00:26:31 +08001577template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_IPV6_ML_PREFIX>(void)
Buke Po818998e2017-08-04 01:19:07 +08001578{
Jonathan Huic1164412018-08-17 08:59:37 -07001579 otError error = OT_ERROR_NONE;
1580 const otMeshLocalPrefix *mlPrefix = otThreadGetMeshLocalPrefix(mInstance);
1581 otIp6Address addr;
Buke Po818998e2017-08-04 01:19:07 +08001582
Jonathan Hui1326d642020-06-17 22:44:54 -07001583 VerifyOrExit(mlPrefix != nullptr, OT_NOOP); // If `mlPrefix` is nullptr send empty response.
Buke Po818998e2017-08-04 01:19:07 +08001584
Jonathan Huic1164412018-08-17 08:59:37 -07001585 memcpy(addr.mFields.m8, mlPrefix->m8, 8);
Buke Po818998e2017-08-04 01:19:07 +08001586
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001587 // Zero out the last 8 bytes.
1588 memset(addr.mFields.m8 + 8, 0, 8);
Buke Po818998e2017-08-04 01:19:07 +08001589
Jintao Lin8788cf52020-01-10 10:15:23 +08001590 SuccessOrExit(error = mEncoder.WriteIp6Address(addr)); // Mesh local prefix
1591 SuccessOrExit(error = mEncoder.WriteUint8(OT_IP6_PREFIX_BITSIZE)); // Prefix length (in bits)
Buke Po818998e2017-08-04 01:19:07 +08001592
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001593exit:
Buke Po818998e2017-08-04 01:19:07 +08001594 return error;
1595}
1596
Yakun Xu8ccf1382018-06-29 00:26:31 +08001597template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_IPV6_ML_PREFIX>(void)
Buke Po818998e2017-08-04 01:19:07 +08001598{
Jonathan Huic1164412018-08-17 08:59:37 -07001599 otError error = OT_ERROR_NONE;
1600 const otIp6Address *meshLocalPrefix;
1601 uint8_t prefixLength;
Buke Po818998e2017-08-04 01:19:07 +08001602
rongli11f32602018-03-20 23:55:41 +08001603 SuccessOrExit(error = mDecoder.ReadIp6Address(meshLocalPrefix));
1604 SuccessOrExit(error = mDecoder.ReadUint8(prefixLength));
Jintao Lin8788cf52020-01-10 10:15:23 +08001605 VerifyOrExit(prefixLength == OT_IP6_PREFIX_BITSIZE, error = OT_ERROR_INVALID_ARGS);
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001606
Jonathan Huic1164412018-08-17 08:59:37 -07001607 error = otThreadSetMeshLocalPrefix(mInstance, reinterpret_cast<const otMeshLocalPrefix *>(meshLocalPrefix));
Buke Po818998e2017-08-04 01:19:07 +08001608
1609exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001610 return error;
Buke Po818998e2017-08-04 01:19:07 +08001611}
1612
Yakun Xu8ccf1382018-06-29 00:26:31 +08001613template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_IPV6_ML_ADDR>(void)
Buke Po818998e2017-08-04 01:19:07 +08001614{
Yakun Xub8333732018-06-21 04:15:13 +08001615 otError error = OT_ERROR_NONE;
1616 const otIp6Address *ml64 = otThreadGetMeshLocalEid(mInstance);
Buke Po818998e2017-08-04 01:19:07 +08001617
Jonathan Hui1326d642020-06-17 22:44:54 -07001618 VerifyOrExit(ml64 != nullptr, OT_NOOP);
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001619 SuccessOrExit(error = mEncoder.WriteIp6Address(*ml64));
Buke Po818998e2017-08-04 01:19:07 +08001620
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001621exit:
Buke Po818998e2017-08-04 01:19:07 +08001622 return error;
1623}
1624
Yakun Xu8ccf1382018-06-29 00:26:31 +08001625template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_IPV6_LL_ADDR>(void)
Buke Po818998e2017-08-04 01:19:07 +08001626{
Yakun Xub8333732018-06-21 04:15:13 +08001627 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001628 const otIp6Address *address = otThreadGetLinkLocalIp6Address(mInstance);
1629
Jonathan Hui1326d642020-06-17 22:44:54 -07001630 VerifyOrExit(address != nullptr, OT_NOOP);
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001631 SuccessOrExit(error = mEncoder.WriteIp6Address(*address));
Buke Po818998e2017-08-04 01:19:07 +08001632
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001633exit:
Buke Po818998e2017-08-04 01:19:07 +08001634 return error;
1635}
1636
Yakun Xu8ccf1382018-06-29 00:26:31 +08001637template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_IPV6_ADDRESS_TABLE>(void)
Buke Po818998e2017-08-04 01:19:07 +08001638{
1639 otError error = OT_ERROR_NONE;
1640
Buke Po818998e2017-08-04 01:19:07 +08001641 for (const otNetifAddress *address = otIp6GetUnicastAddresses(mInstance); address; address = address->mNext)
1642 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001643 SuccessOrExit(error = mEncoder.OpenStruct());
Buke Po818998e2017-08-04 01:19:07 +08001644
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001645 SuccessOrExit(error = mEncoder.WriteIp6Address(address->mAddress));
1646 SuccessOrExit(error = mEncoder.WriteUint8(address->mPrefixLength));
1647 SuccessOrExit(error = mEncoder.WriteUint32(address->mPreferred ? 0xffffffff : 0));
1648 SuccessOrExit(error = mEncoder.WriteUint32(address->mValid ? 0xffffffff : 0));
1649
1650 SuccessOrExit(error = mEncoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08001651 }
1652
Buke Po818998e2017-08-04 01:19:07 +08001653exit:
Buke Po818998e2017-08-04 01:19:07 +08001654 return error;
1655}
1656
Yakun Xu8ccf1382018-06-29 00:26:31 +08001657template <> otError NcpBase::HandlePropertyInsert<SPINEL_PROP_IPV6_ADDRESS_TABLE>(void)
Buke Po818998e2017-08-04 01:19:07 +08001658{
Yakun Xub8333732018-06-21 04:15:13 +08001659 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001660 otNetifAddress netifAddr;
Yakun Xub8333732018-06-21 04:15:13 +08001661 uint32_t preferredLifetime;
1662 uint32_t validLifetime;
Buke Po818998e2017-08-04 01:19:07 +08001663
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001664 SuccessOrExit(error = mDecoder.ReadIp6Address(netifAddr.mAddress));
1665 SuccessOrExit(error = mDecoder.ReadUint8(netifAddr.mPrefixLength));
1666 SuccessOrExit(error = mDecoder.ReadUint32(preferredLifetime));
1667 SuccessOrExit(error = mDecoder.ReadUint32(validLifetime));
Buke Po818998e2017-08-04 01:19:07 +08001668
Markus Beckerbad53a22020-06-16 03:24:14 +02001669 netifAddr.mAddressOrigin = OT_ADDRESS_ORIGIN_MANUAL;
1670 netifAddr.mPreferred = (preferredLifetime != 0);
1671 netifAddr.mValid = (validLifetime != 0);
Buke Po818998e2017-08-04 01:19:07 +08001672
1673 error = otIp6AddUnicastAddress(mInstance, &netifAddr);
1674
Buke Po818998e2017-08-04 01:19:07 +08001675exit:
Buke Po818998e2017-08-04 01:19:07 +08001676 return error;
1677}
1678
Yakun Xu8ccf1382018-06-29 00:26:31 +08001679template <> otError NcpBase::HandlePropertyRemove<SPINEL_PROP_IPV6_ADDRESS_TABLE>(void)
Buke Po818998e2017-08-04 01:19:07 +08001680{
Yakun Xub8333732018-06-21 04:15:13 +08001681 otError error = OT_ERROR_NONE;
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001682 const otIp6Address *addrPtr;
Buke Po818998e2017-08-04 01:19:07 +08001683
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001684 SuccessOrExit(error = mDecoder.ReadIp6Address(addrPtr));
Buke Po818998e2017-08-04 01:19:07 +08001685
1686 error = otIp6RemoveUnicastAddress(mInstance, addrPtr);
Abtin Keshavarzian02bdc692017-08-15 09:11:19 -07001687
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001688 // If address was not on the list, "remove" command is successful.
1689 if (error == OT_ERROR_NOT_FOUND)
Buke Po818998e2017-08-04 01:19:07 +08001690 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001691 error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001692 }
1693
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001694exit:
Buke Po818998e2017-08-04 01:19:07 +08001695 return error;
1696}
1697
Yakun Xu8ccf1382018-06-29 00:26:31 +08001698template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_IPV6_ROUTE_TABLE>(void)
Buke Po818998e2017-08-04 01:19:07 +08001699{
1700 // TODO: Implement get route table
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001701 return mEncoder.OverwriteWithLastStatusError(SPINEL_STATUS_UNIMPLEMENTED);
Buke Po818998e2017-08-04 01:19:07 +08001702}
1703
Yakun Xu8ccf1382018-06-29 00:26:31 +08001704template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_IPV6_ICMP_PING_OFFLOAD>(void)
Buke Po818998e2017-08-04 01:19:07 +08001705{
Jonathan Huif602dcd2018-03-13 18:10:28 +00001706 return mEncoder.WriteBool(otIcmp6GetEchoMode(mInstance) != OT_ICMP6_ECHO_HANDLER_DISABLED);
Buke Po818998e2017-08-04 01:19:07 +08001707}
1708
Yakun Xu8ccf1382018-06-29 00:26:31 +08001709template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_IPV6_ICMP_PING_OFFLOAD>(void)
Buke Po818998e2017-08-04 01:19:07 +08001710{
Yakun Xub8333732018-06-21 04:15:13 +08001711 bool enabled = false;
1712 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001713
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001714 SuccessOrExit(error = mDecoder.ReadBool(enabled));
Buke Po818998e2017-08-04 01:19:07 +08001715
Jonathan Huif602dcd2018-03-13 18:10:28 +00001716 otIcmp6SetEchoMode(mInstance, enabled ? OT_ICMP6_ECHO_HANDLER_ALL : OT_ICMP6_ECHO_HANDLER_DISABLED);
Buke Po818998e2017-08-04 01:19:07 +08001717
1718exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001719 return error;
Buke Po818998e2017-08-04 01:19:07 +08001720}
1721
Yakun Xu8ccf1382018-06-29 00:26:31 +08001722template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE>(void)
Buke Po818998e2017-08-04 01:19:07 +08001723{
Yakun Xub8333732018-06-21 04:15:13 +08001724 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001725 const otNetifMulticastAddress *address;
1726
Buke Po818998e2017-08-04 01:19:07 +08001727 for (address = otIp6GetMulticastAddresses(mInstance); address; address = address->mNext)
1728 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001729 SuccessOrExit(error = mEncoder.OpenStruct());
1730 SuccessOrExit(error = mEncoder.WriteIp6Address(address->mAddress));
1731 SuccessOrExit(error = mEncoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08001732 }
1733
Buke Po818998e2017-08-04 01:19:07 +08001734exit:
Buke Po818998e2017-08-04 01:19:07 +08001735 return error;
1736}
1737
Yakun Xu8ccf1382018-06-29 00:26:31 +08001738template <> otError NcpBase::HandlePropertyInsert<SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE>(void)
Buke Po818998e2017-08-04 01:19:07 +08001739{
Yakun Xub8333732018-06-21 04:15:13 +08001740 otError error = OT_ERROR_NONE;
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001741 const otIp6Address *addrPtr;
Buke Po818998e2017-08-04 01:19:07 +08001742
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001743 SuccessOrExit(error = mDecoder.ReadIp6Address(addrPtr));
Buke Po818998e2017-08-04 01:19:07 +08001744
1745 error = otIp6SubscribeMulticastAddress(mInstance, addrPtr);
Abtin Keshavarzian02bdc692017-08-15 09:11:19 -07001746
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001747 if (error == OT_ERROR_ALREADY)
Buke Po818998e2017-08-04 01:19:07 +08001748 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001749 error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001750 }
1751
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001752exit:
Buke Po818998e2017-08-04 01:19:07 +08001753 return error;
1754}
1755
Yakun Xu8ccf1382018-06-29 00:26:31 +08001756template <> otError NcpBase::HandlePropertyRemove<SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE>(void)
Buke Po818998e2017-08-04 01:19:07 +08001757{
Yakun Xub8333732018-06-21 04:15:13 +08001758 otError error = OT_ERROR_NONE;
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001759 const otIp6Address *addrPtr;
Buke Po818998e2017-08-04 01:19:07 +08001760
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001761 SuccessOrExit(error = mDecoder.ReadIp6Address(addrPtr));
Buke Po818998e2017-08-04 01:19:07 +08001762
1763 error = otIp6UnsubscribeMulticastAddress(mInstance, addrPtr);
Abtin Keshavarzian02bdc692017-08-15 09:11:19 -07001764
1765 // If the address was not on the list, "remove" command is successful,
1766 // and we respond with a `SPINEL_STATUS_OK` status.
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001767 if (error == OT_ERROR_NOT_FOUND)
Buke Po818998e2017-08-04 01:19:07 +08001768 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001769 error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001770 }
1771
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001772exit:
Buke Po818998e2017-08-04 01:19:07 +08001773 return error;
1774}
1775
Yakun Xu8ccf1382018-06-29 00:26:31 +08001776template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_IPV6_ICMP_PING_OFFLOAD_MODE>(void)
Jonathan Huif602dcd2018-03-13 18:10:28 +00001777{
1778 spinel_ipv6_icmp_ping_offload_mode_t mode = SPINEL_IPV6_ICMP_PING_OFFLOAD_DISABLED;
1779
1780 switch (otIcmp6GetEchoMode(mInstance))
1781 {
1782 case OT_ICMP6_ECHO_HANDLER_DISABLED:
1783 mode = SPINEL_IPV6_ICMP_PING_OFFLOAD_DISABLED;
1784 break;
1785 case OT_ICMP6_ECHO_HANDLER_UNICAST_ONLY:
1786 mode = SPINEL_IPV6_ICMP_PING_OFFLOAD_UNICAST_ONLY;
1787 break;
1788 case OT_ICMP6_ECHO_HANDLER_MULTICAST_ONLY:
1789 mode = SPINEL_IPV6_ICMP_PING_OFFLOAD_MULTICAST_ONLY;
1790 break;
1791 case OT_ICMP6_ECHO_HANDLER_ALL:
1792 mode = SPINEL_IPV6_ICMP_PING_OFFLOAD_ALL;
1793 break;
1794 };
1795
1796 return mEncoder.WriteUint8(mode);
1797}
1798
Yakun Xu8ccf1382018-06-29 00:26:31 +08001799template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_IPV6_ICMP_PING_OFFLOAD_MODE>(void)
Jonathan Huif602dcd2018-03-13 18:10:28 +00001800{
Yakun Xub8333732018-06-21 04:15:13 +08001801 otError error = OT_ERROR_NONE;
1802 otIcmp6EchoMode mode = OT_ICMP6_ECHO_HANDLER_DISABLED;
1803 uint8_t spinelMode;
Jonathan Huif602dcd2018-03-13 18:10:28 +00001804
1805 SuccessOrExit(error = mDecoder.ReadUint8(spinelMode));
1806
1807 switch (spinelMode)
1808 {
1809 case SPINEL_IPV6_ICMP_PING_OFFLOAD_DISABLED:
1810 mode = OT_ICMP6_ECHO_HANDLER_DISABLED;
1811 break;
1812 case SPINEL_IPV6_ICMP_PING_OFFLOAD_UNICAST_ONLY:
1813 mode = OT_ICMP6_ECHO_HANDLER_UNICAST_ONLY;
1814 break;
1815 case SPINEL_IPV6_ICMP_PING_OFFLOAD_MULTICAST_ONLY:
1816 mode = OT_ICMP6_ECHO_HANDLER_MULTICAST_ONLY;
1817 break;
1818 case SPINEL_IPV6_ICMP_PING_OFFLOAD_ALL:
1819 mode = OT_ICMP6_ECHO_HANDLER_ALL;
1820 break;
1821 };
1822
1823 otIcmp6SetEchoMode(mInstance, mode);
1824
1825exit:
1826 return error;
1827}
1828
Yakun Xu8ccf1382018-06-29 00:26:31 +08001829template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_RLOC16_DEBUG_PASSTHRU>(void)
Buke Po818998e2017-08-04 01:19:07 +08001830{
1831 // Note reverse logic: passthru enabled = filter disabled
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001832 return mEncoder.WriteBool(!otIp6IsReceiveFilterEnabled(mInstance));
Buke Po818998e2017-08-04 01:19:07 +08001833}
1834
Yakun Xu8ccf1382018-06-29 00:26:31 +08001835template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_RLOC16_DEBUG_PASSTHRU>(void)
Buke Po818998e2017-08-04 01:19:07 +08001836{
Yakun Xub8333732018-06-21 04:15:13 +08001837 bool enabled = false;
1838 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001839
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001840 SuccessOrExit(error = mDecoder.ReadBool(enabled));
Buke Po818998e2017-08-04 01:19:07 +08001841
1842 // Note reverse logic: passthru enabled = filter disabled
1843 otIp6SetReceiveFilterEnabled(mInstance, !enabled);
1844
1845exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001846 return error;
Buke Po818998e2017-08-04 01:19:07 +08001847}
1848
Yakun Xu8ccf1382018-06-29 00:26:31 +08001849template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_OFF_MESH_ROUTES>(void)
Buke Po818998e2017-08-04 01:19:07 +08001850{
Yakun Xub8333732018-06-21 04:15:13 +08001851 otError error = OT_ERROR_NONE;
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001852 otExternalRouteConfig routeConfig;
Buke Po818998e2017-08-04 01:19:07 +08001853 otNetworkDataIterator iter = OT_NETWORK_DATA_ITERATOR_INIT;
1854
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001855 while (otNetDataGetNextRoute(mInstance, &iter, &routeConfig) == OT_ERROR_NONE)
Buke Po818998e2017-08-04 01:19:07 +08001856 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001857 SuccessOrExit(error = mEncoder.OpenStruct());
1858
1859 SuccessOrExit(error = mEncoder.WriteIp6Address(routeConfig.mPrefix.mPrefix));
1860 SuccessOrExit(error = mEncoder.WriteUint8(routeConfig.mPrefix.mLength));
1861 SuccessOrExit(error = mEncoder.WriteBool(routeConfig.mStable));
1862 SuccessOrExit(error = mEncoder.WriteUint8(ExternalRoutePreferenceToFlagByte(routeConfig.mPreference)));
Yakun Xub8333732018-06-21 04:15:13 +08001863 SuccessOrExit(error = mEncoder.WriteBool(false)); // IsLocal
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001864 SuccessOrExit(error = mEncoder.WriteBool(routeConfig.mNextHopIsThisDevice));
1865 SuccessOrExit(error = mEncoder.WriteUint16(routeConfig.mRloc16));
1866
1867 SuccessOrExit(error = mEncoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08001868 }
1869
Jonathan Huif1849732019-07-16 12:31:11 -07001870#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
Abtin Keshavarzian2c8f50b2017-09-01 21:27:58 -07001871
1872 iter = OT_NETWORK_DATA_ITERATOR_INIT;
1873
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001874 while (otBorderRouterGetNextRoute(mInstance, &iter, &routeConfig) == OT_ERROR_NONE)
Buke Po818998e2017-08-04 01:19:07 +08001875 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001876 SuccessOrExit(error = mEncoder.OpenStruct());
1877
1878 SuccessOrExit(error = mEncoder.WriteIp6Address(routeConfig.mPrefix.mPrefix));
1879 SuccessOrExit(error = mEncoder.WriteUint8(routeConfig.mPrefix.mLength));
1880 SuccessOrExit(error = mEncoder.WriteBool(routeConfig.mStable));
1881 SuccessOrExit(error = mEncoder.WriteUint8(ExternalRoutePreferenceToFlagByte(routeConfig.mPreference)));
Yakun Xub8333732018-06-21 04:15:13 +08001882 SuccessOrExit(error = mEncoder.WriteBool(true)); // IsLocal
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001883 SuccessOrExit(error = mEncoder.WriteBool(routeConfig.mNextHopIsThisDevice));
1884 SuccessOrExit(error = mEncoder.WriteUint16(routeConfig.mRloc16));
1885
1886 SuccessOrExit(error = mEncoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08001887 }
Jonathan Huif1849732019-07-16 12:31:11 -07001888#endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08001889
Buke Po818998e2017-08-04 01:19:07 +08001890exit:
Buke Po818998e2017-08-04 01:19:07 +08001891 return error;
1892}
1893
Jonathan Huif1849732019-07-16 12:31:11 -07001894#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08001895static int FlagByteToExternalRoutePreference(uint8_t aFlags)
1896{
1897 int route_preference = 0;
1898
1899 switch (aFlags & SPINEL_NET_FLAG_PREFERENCE_MASK)
1900 {
1901 case SPINEL_ROUTE_PREFERENCE_HIGH:
1902 route_preference = OT_ROUTE_PREFERENCE_HIGH;
1903 break;
1904
1905 case SPINEL_ROUTE_PREFERENCE_MEDIUM:
1906 route_preference = OT_ROUTE_PREFERENCE_MED;
1907 break;
1908
1909 case SPINEL_ROUTE_PREFERENCE_LOW:
1910 route_preference = OT_ROUTE_PREFERENCE_LOW;
1911 break;
1912 }
1913
1914 return route_preference;
1915}
1916
Yakun Xu8ccf1382018-06-29 00:26:31 +08001917template <> otError NcpBase::HandlePropertyInsert<SPINEL_PROP_THREAD_OFF_MESH_ROUTES>(void)
Buke Po818998e2017-08-04 01:19:07 +08001918{
Yakun Xub8333732018-06-21 04:15:13 +08001919 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001920 otExternalRouteConfig routeConfig;
Yakun Xub8333732018-06-21 04:15:13 +08001921 bool stable = false;
1922 uint8_t flags = 0;
1923 uint8_t prefixLength;
Buke Po818998e2017-08-04 01:19:07 +08001924
1925 memset(&routeConfig, 0, sizeof(otExternalRouteConfig));
1926
Abtin Keshavarzian31ce3d42019-08-01 10:30:08 -07001927 VerifyOrExit(mAllowLocalNetworkDataChange, error = OT_ERROR_INVALID_STATE);
Buke Po818998e2017-08-04 01:19:07 +08001928
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001929 SuccessOrExit(error = mDecoder.ReadIp6Address(routeConfig.mPrefix.mPrefix));
Łukasz Duda7b084ec2017-10-25 17:54:17 +02001930 SuccessOrExit(error = mDecoder.ReadUint8(prefixLength));
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001931 SuccessOrExit(error = mDecoder.ReadBool(stable));
1932 SuccessOrExit(error = mDecoder.ReadUint8(flags));
Buke Po818998e2017-08-04 01:19:07 +08001933
Łukasz Duda7b084ec2017-10-25 17:54:17 +02001934 routeConfig.mPrefix.mLength = prefixLength;
Yakun Xub8333732018-06-21 04:15:13 +08001935 routeConfig.mStable = stable;
1936 routeConfig.mPreference = FlagByteToExternalRoutePreference(flags);
Buke Po818998e2017-08-04 01:19:07 +08001937
1938 error = otBorderRouterAddRoute(mInstance, &routeConfig);
Buke Po818998e2017-08-04 01:19:07 +08001939
1940exit:
Buke Po818998e2017-08-04 01:19:07 +08001941 return error;
1942}
1943
Yakun Xu8ccf1382018-06-29 00:26:31 +08001944template <> otError NcpBase::HandlePropertyRemove<SPINEL_PROP_THREAD_OFF_MESH_ROUTES>(void)
Buke Po818998e2017-08-04 01:19:07 +08001945{
Yakun Xub8333732018-06-21 04:15:13 +08001946 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001947 otIp6Prefix ip6Prefix;
Yakun Xub8333732018-06-21 04:15:13 +08001948 uint8_t prefixLength;
Buke Po818998e2017-08-04 01:19:07 +08001949
1950 memset(&ip6Prefix, 0, sizeof(otIp6Prefix));
1951
Abtin Keshavarzian31ce3d42019-08-01 10:30:08 -07001952 VerifyOrExit(mAllowLocalNetworkDataChange, error = OT_ERROR_INVALID_STATE);
Buke Po818998e2017-08-04 01:19:07 +08001953
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001954 SuccessOrExit(error = mDecoder.ReadIp6Address(ip6Prefix.mPrefix));
Łukasz Duda7b084ec2017-10-25 17:54:17 +02001955 SuccessOrExit(error = mDecoder.ReadUint8(prefixLength));
1956
1957 ip6Prefix.mLength = prefixLength;
Buke Po818998e2017-08-04 01:19:07 +08001958
1959 error = otBorderRouterRemoveRoute(mInstance, &ip6Prefix);
Abtin Keshavarzian02bdc692017-08-15 09:11:19 -07001960
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001961 // If the route prefix was not on the list, "remove" command is successful.
1962 if (error == OT_ERROR_NOT_FOUND)
Buke Po818998e2017-08-04 01:19:07 +08001963 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001964 error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001965 }
1966
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001967exit:
Buke Po818998e2017-08-04 01:19:07 +08001968 return error;
1969}
Jonathan Huif1849732019-07-16 12:31:11 -07001970#endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08001971
Yakun Xu8ccf1382018-06-29 00:26:31 +08001972template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_STREAM_NET>(void)
Buke Po818998e2017-08-04 01:19:07 +08001973{
Jonathan Hui1326d642020-06-17 22:44:54 -07001974 const uint8_t *framePtr = nullptr;
Yakun Xub8333732018-06-21 04:15:13 +08001975 uint16_t frameLen = 0;
Jonathan Hui1326d642020-06-17 22:44:54 -07001976 const uint8_t *metaPtr = nullptr;
Yakun Xub8333732018-06-21 04:15:13 +08001977 uint16_t metaLen = 0;
Jonathan Hui1326d642020-06-17 22:44:54 -07001978 otMessage * message = nullptr;
Yakun Xub8333732018-06-21 04:15:13 +08001979 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001980
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001981 SuccessOrExit(error = mDecoder.ReadDataWithLen(framePtr, frameLen));
1982 SuccessOrExit(error = mDecoder.ReadData(metaPtr, metaLen));
Buke Po818998e2017-08-04 01:19:07 +08001983
1984 // We ignore metadata for now.
1985 // May later include TX power, allow retransmits, etc...
Buke Po818998e2017-08-04 01:19:07 +08001986
Zhanglong Xia19f25332018-12-20 05:55:26 +08001987 // STREAM_NET requires layer 2 security.
Jonathan Hui1326d642020-06-17 22:44:54 -07001988 message = otIp6NewMessageFromBuffer(mInstance, framePtr, frameLen, nullptr);
1989 VerifyOrExit(message != nullptr, error = OT_ERROR_NO_BUFS);
Buke Po818998e2017-08-04 01:19:07 +08001990
1991 error = otIp6Send(mInstance, message);
1992
Buke Po818998e2017-08-04 01:19:07 +08001993exit:
1994
Buke Po818998e2017-08-04 01:19:07 +08001995 if (error == OT_ERROR_NONE)
1996 {
1997 mInboundSecureIpFrameCounter++;
Buke Po818998e2017-08-04 01:19:07 +08001998 }
1999 else
2000 {
2001 mDroppedInboundIpFrameCounter++;
Buke Po818998e2017-08-04 01:19:07 +08002002 }
2003
Buke Po818998e2017-08-04 01:19:07 +08002004 return error;
2005}
2006
Jonathan Hui02da2062019-07-16 12:18:34 -07002007#if OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08002008
Yakun Xu8ccf1382018-06-29 00:26:31 +08002009template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_JAM_DETECT_ENABLE>(void)
Buke Po818998e2017-08-04 01:19:07 +08002010{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002011 return mEncoder.WriteBool(otJamDetectionIsEnabled(mInstance));
Buke Po818998e2017-08-04 01:19:07 +08002012}
2013
Yakun Xu8ccf1382018-06-29 00:26:31 +08002014template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_JAM_DETECTED>(void)
Buke Po818998e2017-08-04 01:19:07 +08002015{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002016 return mEncoder.WriteBool(otJamDetectionGetState(mInstance));
Buke Po818998e2017-08-04 01:19:07 +08002017}
2018
Yakun Xu8ccf1382018-06-29 00:26:31 +08002019template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_JAM_DETECT_RSSI_THRESHOLD>(void)
Buke Po818998e2017-08-04 01:19:07 +08002020{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002021 return mEncoder.WriteInt8(otJamDetectionGetRssiThreshold(mInstance));
Buke Po818998e2017-08-04 01:19:07 +08002022}
2023
Yakun Xu8ccf1382018-06-29 00:26:31 +08002024template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_JAM_DETECT_WINDOW>(void)
Buke Po818998e2017-08-04 01:19:07 +08002025{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002026 return mEncoder.WriteUint8(otJamDetectionGetWindow(mInstance));
Buke Po818998e2017-08-04 01:19:07 +08002027}
2028
Yakun Xu8ccf1382018-06-29 00:26:31 +08002029template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_JAM_DETECT_BUSY>(void)
Buke Po818998e2017-08-04 01:19:07 +08002030{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002031 return mEncoder.WriteUint8(otJamDetectionGetBusyPeriod(mInstance));
Buke Po818998e2017-08-04 01:19:07 +08002032}
2033
Yakun Xu8ccf1382018-06-29 00:26:31 +08002034template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_JAM_DETECT_HISTORY_BITMAP>(void)
Buke Po818998e2017-08-04 01:19:07 +08002035{
Abtin Keshavarzian07f4ae12017-12-07 10:22:24 -08002036 return mEncoder.WriteUint64(otJamDetectionGetHistoryBitmap(mInstance));
Buke Po818998e2017-08-04 01:19:07 +08002037}
2038
Yakun Xu8ccf1382018-06-29 00:26:31 +08002039template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_JAM_DETECT_ENABLE>(void)
Buke Po818998e2017-08-04 01:19:07 +08002040{
Yakun Xub8333732018-06-21 04:15:13 +08002041 bool enabled;
Buke Po818998e2017-08-04 01:19:07 +08002042 otError error = OT_ERROR_NONE;
2043
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002044 SuccessOrExit(error = mDecoder.ReadBool(enabled));
Buke Po818998e2017-08-04 01:19:07 +08002045
2046 if (enabled)
2047 {
kangping49f36f82020-05-07 02:17:58 +08002048 IgnoreError(otJamDetectionStart(mInstance, &NcpBase::HandleJamStateChange_Jump, this));
Buke Po818998e2017-08-04 01:19:07 +08002049 }
2050 else
2051 {
kangping49f36f82020-05-07 02:17:58 +08002052 IgnoreError(otJamDetectionStop(mInstance));
Buke Po818998e2017-08-04 01:19:07 +08002053 }
2054
2055exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002056 return error;
Buke Po818998e2017-08-04 01:19:07 +08002057}
2058
Yakun Xu8ccf1382018-06-29 00:26:31 +08002059template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_JAM_DETECT_RSSI_THRESHOLD>(void)
Buke Po818998e2017-08-04 01:19:07 +08002060{
Yakun Xub8333732018-06-21 04:15:13 +08002061 int8_t threshold = 0;
2062 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08002063
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002064 SuccessOrExit(error = mDecoder.ReadInt8(threshold));
Buke Po818998e2017-08-04 01:19:07 +08002065
2066 error = otJamDetectionSetRssiThreshold(mInstance, threshold);
2067
2068exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002069 return error;
Buke Po818998e2017-08-04 01:19:07 +08002070}
2071
Yakun Xu8ccf1382018-06-29 00:26:31 +08002072template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_JAM_DETECT_WINDOW>(void)
Buke Po818998e2017-08-04 01:19:07 +08002073{
2074 uint8_t window = 0;
Yakun Xub8333732018-06-21 04:15:13 +08002075 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08002076
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002077 SuccessOrExit(error = mDecoder.ReadUint8(window));
Buke Po818998e2017-08-04 01:19:07 +08002078
2079 error = otJamDetectionSetWindow(mInstance, window);
2080
2081exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002082 return error;
Buke Po818998e2017-08-04 01:19:07 +08002083}
2084
Yakun Xu8ccf1382018-06-29 00:26:31 +08002085template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_JAM_DETECT_BUSY>(void)
Buke Po818998e2017-08-04 01:19:07 +08002086{
Yakun Xub8333732018-06-21 04:15:13 +08002087 uint8_t busy = 0;
Buke Po818998e2017-08-04 01:19:07 +08002088 otError error = OT_ERROR_NONE;
2089
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002090 SuccessOrExit(error = mDecoder.ReadUint8(busy));
Buke Po818998e2017-08-04 01:19:07 +08002091
2092 error = otJamDetectionSetBusyPeriod(mInstance, busy);
2093
2094exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002095 return error;
Buke Po818998e2017-08-04 01:19:07 +08002096}
2097
2098void NcpBase::HandleJamStateChange_Jump(bool aJamState, void *aContext)
2099{
2100 static_cast<NcpBase *>(aContext)->HandleJamStateChange(aJamState);
2101}
2102
2103void NcpBase::HandleJamStateChange(bool aJamState)
2104{
2105 OT_UNUSED_VARIABLE(aJamState);
2106
2107 mChangedPropsSet.AddProperty(SPINEL_PROP_JAM_DETECTED);
Abtin Keshavarziana1adaac2020-05-11 10:24:58 -07002108 mUpdateChangedPropsTask.Post();
Buke Po818998e2017-08-04 01:19:07 +08002109}
2110
Jonathan Hui02da2062019-07-16 12:18:34 -07002111#endif // OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08002112
Jonathan Huiaa823912019-07-15 12:03:36 -07002113#if OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE
Abtin Keshavarzian1ca81fb2018-08-02 15:21:11 -07002114
2115template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHILD_SUPERVISION_CHECK_TIMEOUT>(void)
2116{
2117 return mEncoder.WriteUint16(otChildSupervisionGetCheckTimeout(mInstance));
2118}
2119
2120template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_CHILD_SUPERVISION_CHECK_TIMEOUT>(void)
2121{
2122 otError error = OT_ERROR_NONE;
2123 uint16_t timeout;
2124
2125 SuccessOrExit(error = mDecoder.ReadUint16(timeout));
2126 otChildSupervisionSetCheckTimeout(mInstance, timeout);
2127
2128exit:
2129 return error;
2130}
2131
Jonathan Huiaa823912019-07-15 12:03:36 -07002132#endif // OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE
Abtin Keshavarzian1ca81fb2018-08-02 15:21:11 -07002133
Jonathan Hui01ebc182019-07-12 15:21:49 -07002134#if OPENTHREAD_CONFIG_CHANNEL_MONITOR_ENABLE
Abtin Keshavarzianba5317a2018-01-13 13:37:04 -08002135
Yakun Xu8ccf1382018-06-29 00:26:31 +08002136template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHANNEL_MONITOR_SAMPLE_INTERVAL>(void)
Abtin Keshavarzianba5317a2018-01-13 13:37:04 -08002137{
2138 return mEncoder.WriteUint32(otChannelMonitorGetSampleInterval(mInstance));
2139}
2140
Yakun Xu8ccf1382018-06-29 00:26:31 +08002141template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHANNEL_MONITOR_RSSI_THRESHOLD>(void)
Abtin Keshavarzianba5317a2018-01-13 13:37:04 -08002142{
2143 return mEncoder.WriteInt8(otChannelMonitorGetRssiThreshold(mInstance));
2144}
2145
Yakun Xu8ccf1382018-06-29 00:26:31 +08002146template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHANNEL_MONITOR_SAMPLE_WINDOW>(void)
Abtin Keshavarzianba5317a2018-01-13 13:37:04 -08002147{
2148 return mEncoder.WriteUint32(otChannelMonitorGetSampleWindow(mInstance));
2149}
2150
Yakun Xu8ccf1382018-06-29 00:26:31 +08002151template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHANNEL_MONITOR_SAMPLE_COUNT>(void)
Abtin Keshavarzianba5317a2018-01-13 13:37:04 -08002152{
2153 return mEncoder.WriteUint32(otChannelMonitorGetSampleCount(mInstance));
2154}
2155
Yakun Xu8ccf1382018-06-29 00:26:31 +08002156template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHANNEL_MONITOR_CHANNEL_OCCUPANCY>(void)
Abtin Keshavarzianba5317a2018-01-13 13:37:04 -08002157{
Shu Chena43a2632019-04-09 12:25:16 +08002158 otError error = OT_ERROR_NONE;
2159 uint32_t channelMask = otLinkGetSupportedChannelMask(mInstance);
2160 uint8_t channelNum = sizeof(channelMask) * CHAR_BIT;
Abtin Keshavarzianba5317a2018-01-13 13:37:04 -08002161
Shu Chena43a2632019-04-09 12:25:16 +08002162 for (uint8_t channel = 0; channel < channelNum; channel++)
Abtin Keshavarzianba5317a2018-01-13 13:37:04 -08002163 {
Shu Chena43a2632019-04-09 12:25:16 +08002164 if (!((1UL << channel) & channelMask))
2165 {
2166 continue;
2167 }
2168
Abtin Keshavarzianba5317a2018-01-13 13:37:04 -08002169 SuccessOrExit(error = mEncoder.OpenStruct());
2170
2171 SuccessOrExit(error = mEncoder.WriteUint8(channel));
Abtin Keshavarziandf452402018-04-16 11:17:09 -07002172 SuccessOrExit(error = mEncoder.WriteUint16(otChannelMonitorGetChannelOccupancy(mInstance, channel)));
Abtin Keshavarzianba5317a2018-01-13 13:37:04 -08002173
2174 SuccessOrExit(error = mEncoder.CloseStruct());
2175 }
2176
2177exit:
2178 return error;
2179}
2180
Jonathan Hui01ebc182019-07-12 15:21:49 -07002181#endif // OPENTHREAD_CONFIG_CHANNEL_MONITOR_ENABLE
Abtin Keshavarzianba5317a2018-01-13 13:37:04 -08002182
Yakun Xu8ccf1382018-06-29 00:26:31 +08002183template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_CCA_FAILURE_RATE>(void)
Abtin Keshavarzian171c9512018-01-23 09:10:13 -08002184{
2185 return mEncoder.WriteUint16(otLinkGetCcaFailureRate(mInstance));
2186}
2187
Yakun Xu8ccf1382018-06-29 00:26:31 +08002188template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_PKT_TOTAL>(void)
Buke Po818998e2017-08-04 01:19:07 +08002189{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002190 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxTotal);
Buke Po818998e2017-08-04 01:19:07 +08002191}
2192
Yakun Xu8ccf1382018-06-29 00:26:31 +08002193template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_PKT_ACK_REQ>(void)
Buke Po818998e2017-08-04 01:19:07 +08002194{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002195 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxAckRequested);
Buke Po818998e2017-08-04 01:19:07 +08002196}
2197
Yakun Xu8ccf1382018-06-29 00:26:31 +08002198template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_PKT_ACKED>(void)
Buke Po818998e2017-08-04 01:19:07 +08002199{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002200 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxAcked);
Buke Po818998e2017-08-04 01:19:07 +08002201}
2202
Yakun Xu8ccf1382018-06-29 00:26:31 +08002203template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_PKT_NO_ACK_REQ>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002204{
2205 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxNoAckRequested);
2206}
2207
Yakun Xu8ccf1382018-06-29 00:26:31 +08002208template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_PKT_DATA>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002209{
2210 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxData);
2211}
2212
Yakun Xu8ccf1382018-06-29 00:26:31 +08002213template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_PKT_DATA_POLL>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002214{
2215 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxDataPoll);
2216}
2217
Yakun Xu8ccf1382018-06-29 00:26:31 +08002218template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_PKT_BEACON>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002219{
2220 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxBeacon);
2221}
2222
Yakun Xu8ccf1382018-06-29 00:26:31 +08002223template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_PKT_BEACON_REQ>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002224{
2225 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxBeaconRequest);
2226}
2227
Yakun Xu8ccf1382018-06-29 00:26:31 +08002228template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_PKT_OTHER>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002229{
2230 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxOther);
2231}
2232
Yakun Xu8ccf1382018-06-29 00:26:31 +08002233template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_PKT_RETRY>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002234{
2235 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxRetry);
2236}
2237
Yakun Xu8ccf1382018-06-29 00:26:31 +08002238template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_ERR_CCA>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002239{
2240 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxErrCca);
2241}
2242
Yakun Xu8ccf1382018-06-29 00:26:31 +08002243template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_PKT_UNICAST>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002244{
2245 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxUnicast);
2246}
2247
Yakun Xu8ccf1382018-06-29 00:26:31 +08002248template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_PKT_BROADCAST>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002249{
2250 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxBroadcast);
2251}
2252
Yakun Xu8ccf1382018-06-29 00:26:31 +08002253template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_ERR_ABORT>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002254{
2255 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxErrAbort);
2256}
2257
Yakun Xu8ccf1382018-06-29 00:26:31 +08002258template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_PKT_TOTAL>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002259{
2260 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxTotal);
2261}
2262
Yakun Xu8ccf1382018-06-29 00:26:31 +08002263template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_PKT_DATA>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002264{
2265 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxData);
2266}
2267
Yakun Xu8ccf1382018-06-29 00:26:31 +08002268template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_PKT_DATA_POLL>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002269{
2270 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxDataPoll);
2271}
2272
Yakun Xu8ccf1382018-06-29 00:26:31 +08002273template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_PKT_BEACON>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002274{
2275 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxBeacon);
2276}
2277
Yakun Xu8ccf1382018-06-29 00:26:31 +08002278template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_PKT_BEACON_REQ>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002279{
2280 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxBeaconRequest);
2281}
2282
Yakun Xu8ccf1382018-06-29 00:26:31 +08002283template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_PKT_OTHER>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002284{
2285 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxOther);
2286}
2287
Yakun Xu8ccf1382018-06-29 00:26:31 +08002288template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_PKT_FILT_WL>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002289{
ronglib1baa7d2017-10-14 00:33:23 +08002290 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxAddressFiltered);
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002291}
2292
Yakun Xu8ccf1382018-06-29 00:26:31 +08002293template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_PKT_FILT_DA>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002294{
2295 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxDestAddrFiltered);
2296}
2297
Yakun Xu8ccf1382018-06-29 00:26:31 +08002298template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_PKT_DUP>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002299{
2300 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxDuplicated);
2301}
2302
Yakun Xu8ccf1382018-06-29 00:26:31 +08002303template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_PKT_UNICAST>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002304{
2305 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxUnicast);
2306}
2307
Yakun Xu8ccf1382018-06-29 00:26:31 +08002308template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_PKT_BROADCAST>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002309{
2310 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxBroadcast);
2311}
2312
Yakun Xu8ccf1382018-06-29 00:26:31 +08002313template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_ERR_EMPTY>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002314{
2315 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxErrNoFrame);
2316}
2317
Yakun Xu8ccf1382018-06-29 00:26:31 +08002318template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_ERR_UKWN_NBR>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002319{
2320 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxErrUnknownNeighbor);
2321}
2322
Yakun Xu8ccf1382018-06-29 00:26:31 +08002323template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_ERR_NVLD_SADDR>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002324{
2325 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxErrInvalidSrcAddr);
2326}
2327
Yakun Xu8ccf1382018-06-29 00:26:31 +08002328template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_ERR_SECURITY>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002329{
2330 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxErrSec);
2331}
2332
Yakun Xu8ccf1382018-06-29 00:26:31 +08002333template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_ERR_BAD_FCS>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002334{
2335 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxErrFcs);
2336}
2337
Yakun Xu8ccf1382018-06-29 00:26:31 +08002338template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_ERR_OTHER>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002339{
2340 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxErrOther);
2341}
2342
Yakun Xu8ccf1382018-06-29 00:26:31 +08002343template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_IP_SEC_TOTAL>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002344{
2345 return mEncoder.WriteUint32(mInboundSecureIpFrameCounter);
2346}
2347
Yakun Xu8ccf1382018-06-29 00:26:31 +08002348template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_IP_INSEC_TOTAL>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002349{
2350 return mEncoder.WriteUint32(mInboundInsecureIpFrameCounter);
2351}
2352
Yakun Xu8ccf1382018-06-29 00:26:31 +08002353template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_IP_DROPPED>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002354{
2355 return mEncoder.WriteUint32(mDroppedInboundIpFrameCounter);
2356}
2357
Yakun Xu8ccf1382018-06-29 00:26:31 +08002358template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_IP_SEC_TOTAL>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002359{
2360 return mEncoder.WriteUint32(mOutboundSecureIpFrameCounter);
2361}
2362
Yakun Xu8ccf1382018-06-29 00:26:31 +08002363template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_IP_INSEC_TOTAL>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002364{
2365 return mEncoder.WriteUint32(mOutboundInsecureIpFrameCounter);
2366}
2367
Yakun Xu8ccf1382018-06-29 00:26:31 +08002368template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_IP_DROPPED>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002369{
2370 return mEncoder.WriteUint32(mDroppedOutboundIpFrameCounter);
2371}
2372
Yakun Xu8ccf1382018-06-29 00:26:31 +08002373template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_SPINEL_TOTAL>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002374{
2375 return mEncoder.WriteUint32(mTxSpinelFrameCounter);
2376}
2377
Yakun Xu8ccf1382018-06-29 00:26:31 +08002378template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_SPINEL_TOTAL>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002379{
2380 return mEncoder.WriteUint32(mRxSpinelFrameCounter);
2381}
2382
Yakun Xu8ccf1382018-06-29 00:26:31 +08002383template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_SPINEL_OUT_OF_ORDER_TID>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002384{
2385 return mEncoder.WriteUint32(mRxSpinelOutOfOrderTidCounter);
2386}
2387
Yakun Xu8ccf1382018-06-29 00:26:31 +08002388template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_SPINEL_ERR>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002389{
2390 return mEncoder.WriteUint32(mFramingErrorCounter);
2391}
2392
Yakun Xu8ccf1382018-06-29 00:26:31 +08002393template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_IP_TX_SUCCESS>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002394{
2395 return mEncoder.WriteUint32(otThreadGetIp6Counters(mInstance)->mTxSuccess);
2396}
2397
Yakun Xu8ccf1382018-06-29 00:26:31 +08002398template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_IP_RX_SUCCESS>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002399{
2400 return mEncoder.WriteUint32(otThreadGetIp6Counters(mInstance)->mRxSuccess);
2401}
2402
Yakun Xu8ccf1382018-06-29 00:26:31 +08002403template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_IP_TX_FAILURE>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002404{
2405 return mEncoder.WriteUint32(otThreadGetIp6Counters(mInstance)->mTxFailure);
2406}
2407
Yakun Xu8ccf1382018-06-29 00:26:31 +08002408template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_IP_RX_FAILURE>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002409{
2410 return mEncoder.WriteUint32(otThreadGetIp6Counters(mInstance)->mRxFailure);
2411}
2412
Yakun Xu8ccf1382018-06-29 00:26:31 +08002413template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MSG_BUFFER_COUNTERS>(void)
Buke Po818998e2017-08-04 01:19:07 +08002414{
Yakun Xub8333732018-06-21 04:15:13 +08002415 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08002416 otBufferInfo bufferInfo;
2417
2418 otMessageGetBufferInfo(mInstance, &bufferInfo);
2419
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002420 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mTotalBuffers));
2421 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mFreeBuffers));
2422 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.m6loSendMessages));
2423 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.m6loSendBuffers));
2424 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.m6loReassemblyMessages));
2425 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.m6loReassemblyBuffers));
2426 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mIp6Messages));
2427 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mIp6Buffers));
2428 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mMplMessages));
2429 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mMplBuffers));
2430 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mMleMessages));
2431 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mMleBuffers));
2432 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mArpMessages));
2433 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mArpBuffers));
2434 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mCoapMessages));
2435 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mCoapBuffers));
Buke Po818998e2017-08-04 01:19:07 +08002436
2437exit:
2438 return error;
2439}
2440
Yakun Xu8ccf1382018-06-29 00:26:31 +08002441template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_ALL_MAC_COUNTERS>(void)
Abtin Keshavarzian23069bb2018-01-23 09:00:27 -08002442{
Yakun Xub8333732018-06-21 04:15:13 +08002443 otError error = OT_ERROR_NONE;
Abtin Keshavarzian23069bb2018-01-23 09:00:27 -08002444 const otMacCounters *counters = otLinkGetCounters(mInstance);
2445
Abtin Keshavarzian23069bb2018-01-23 09:00:27 -08002446 // Encode Tx related counters
2447 SuccessOrExit(error = mEncoder.OpenStruct());
2448 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxTotal));
2449 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxUnicast));
2450 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxBroadcast));
2451 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxAckRequested));
2452 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxAcked));
2453 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxNoAckRequested));
2454 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxData));
2455 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxDataPoll));
2456 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxBeacon));
2457 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxBeaconRequest));
2458 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxOther));
2459 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxRetry));
2460 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxErrCca));
2461 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxErrAbort));
2462 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxErrBusyChannel));
Paweł Wańczykc646e6f2019-12-18 19:23:43 +01002463 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxDirectMaxRetryExpiry));
2464 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxIndirectMaxRetryExpiry));
Abtin Keshavarzian23069bb2018-01-23 09:00:27 -08002465 SuccessOrExit(error = mEncoder.CloseStruct());
2466
2467 // Encode Rx related counters
2468 SuccessOrExit(error = mEncoder.OpenStruct());
2469 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxTotal));
2470 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxUnicast));
2471 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxBroadcast));
2472 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxData));
2473 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxDataPoll));
2474 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxBeacon));
2475 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxBeaconRequest));
2476 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxOther));
2477 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxAddressFiltered));
2478 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxDestAddrFiltered));
2479 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxDuplicated));
2480 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxErrNoFrame));
2481 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxErrUnknownNeighbor));
2482 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxErrInvalidSrcAddr));
2483 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxErrSec));
2484 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxErrFcs));
2485 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxErrOther));
2486 SuccessOrExit(error = mEncoder.CloseStruct());
2487
2488exit:
2489 return error;
2490}
2491
Abtin Keshavarzian112d1bb2019-10-29 15:34:03 -07002492template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_CNTR_ALL_MAC_COUNTERS>(void)
2493{
2494 otLinkResetCounters(mInstance);
2495
2496 return OT_ERROR_NONE;
2497}
2498
Abtin Keshavarzianbd4ca812019-02-06 08:41:50 -08002499template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_MLE_COUNTERS>(void)
2500{
2501 otError error = OT_ERROR_NONE;
2502 const otMleCounters *counters = otThreadGetMleCounters(mInstance);
2503
Jonathan Hui1326d642020-06-17 22:44:54 -07002504 OT_ASSERT(counters != nullptr);
Abtin Keshavarzianbd4ca812019-02-06 08:41:50 -08002505
2506 SuccessOrExit(error = mEncoder.WriteUint16(counters->mDisabledRole));
2507 SuccessOrExit(error = mEncoder.WriteUint16(counters->mDetachedRole));
2508 SuccessOrExit(error = mEncoder.WriteUint16(counters->mChildRole));
2509 SuccessOrExit(error = mEncoder.WriteUint16(counters->mRouterRole));
2510 SuccessOrExit(error = mEncoder.WriteUint16(counters->mLeaderRole));
2511 SuccessOrExit(error = mEncoder.WriteUint16(counters->mAttachAttempts));
2512 SuccessOrExit(error = mEncoder.WriteUint16(counters->mPartitionIdChanges));
2513 SuccessOrExit(error = mEncoder.WriteUint16(counters->mBetterPartitionAttachAttempts));
2514 SuccessOrExit(error = mEncoder.WriteUint16(counters->mParentChanges));
2515
2516exit:
2517 return error;
2518}
2519
Abtin Keshavarzian112d1bb2019-10-29 15:34:03 -07002520template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_CNTR_MLE_COUNTERS>(void)
2521{
2522 otThreadResetMleCounters(mInstance);
2523
2524 return OT_ERROR_NONE;
2525}
2526
2527template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_ALL_IP_COUNTERS>(void)
2528{
2529 otError error = OT_ERROR_NONE;
2530 const otIpCounters *counters = otThreadGetIp6Counters(mInstance);
2531
Jonathan Hui1326d642020-06-17 22:44:54 -07002532 OT_ASSERT(counters != nullptr);
Abtin Keshavarzian112d1bb2019-10-29 15:34:03 -07002533
2534 // Encode Tx related counters
2535 SuccessOrExit(error = mEncoder.OpenStruct());
2536 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxSuccess));
2537 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxFailure));
2538 SuccessOrExit(error = mEncoder.CloseStruct());
2539
2540 // Encode Rx related counters
2541 SuccessOrExit(error = mEncoder.OpenStruct());
2542 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxSuccess));
2543 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxFailure));
2544 SuccessOrExit(error = mEncoder.CloseStruct());
2545
2546exit:
2547 return error;
2548}
2549
Paweł Wańczykc646e6f2019-12-18 19:23:43 +01002550#if OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE
2551template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_MAC_RETRY_HISTOGRAM>(void)
2552{
2553 otError error = OT_ERROR_NONE;
2554 const uint32_t *histogramDirect;
2555 const uint32_t *histogramIndirect;
2556 uint8_t histogramDirectEntries;
2557 uint8_t histogramIndirectEntries;
2558
2559 histogramDirect = otLinkGetTxDirectRetrySuccessHistogram(mInstance, &histogramDirectEntries);
2560 histogramIndirect = otLinkGetTxIndirectRetrySuccessHistogram(mInstance, &histogramIndirectEntries);
2561
Jonathan Hui1326d642020-06-17 22:44:54 -07002562 OT_ASSERT((histogramDirectEntries == 0) || (histogramDirect != nullptr));
2563 OT_ASSERT((histogramIndirectEntries == 0) || (histogramIndirect != nullptr));
Paweł Wańczykc646e6f2019-12-18 19:23:43 +01002564
2565 // Encode direct message retries histogram
2566 SuccessOrExit(error = mEncoder.OpenStruct());
2567 for (uint8_t i = 0; i < histogramDirectEntries; i++)
2568 {
2569 SuccessOrExit(error = mEncoder.WriteUint32(histogramDirect[i]));
2570 }
2571 SuccessOrExit(error = mEncoder.CloseStruct());
2572
2573 // Encode indirect message retries histogram
2574 SuccessOrExit(error = mEncoder.OpenStruct());
2575 for (uint8_t i = 0; i < histogramIndirectEntries; i++)
2576 {
2577 SuccessOrExit(error = mEncoder.WriteUint32(histogramIndirect[i]));
2578 }
2579 SuccessOrExit(error = mEncoder.CloseStruct());
2580
2581exit:
2582 return error;
2583}
2584
2585template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_CNTR_MAC_RETRY_HISTOGRAM>(void)
2586{
2587 otLinkResetTxRetrySuccessHistogram(mInstance);
2588
2589 return OT_ERROR_NONE;
2590}
2591#endif // OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE
2592
Abtin Keshavarzian112d1bb2019-10-29 15:34:03 -07002593template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_CNTR_ALL_IP_COUNTERS>(void)
2594{
2595 otThreadResetIp6Counters(mInstance);
2596
2597 return OT_ERROR_NONE;
2598}
2599
Jonathan Hui0baaf1a2019-07-15 12:57:32 -07002600#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08002601
Yakun Xu8ccf1382018-06-29 00:26:31 +08002602template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_WHITELIST>(void)
Buke Po818998e2017-08-04 01:19:07 +08002603{
Yakun Xub8333732018-06-21 04:15:13 +08002604 otMacFilterEntry entry;
Buke Po818998e2017-08-04 01:19:07 +08002605 otMacFilterIterator iterator = OT_MAC_FILTER_ITERATOR_INIT;
Yakun Xub8333732018-06-21 04:15:13 +08002606 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08002607
Buke Po818998e2017-08-04 01:19:07 +08002608 while (otLinkFilterGetNextAddress(mInstance, &iterator, &entry) == OT_ERROR_NONE)
2609 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002610 SuccessOrExit(error = mEncoder.OpenStruct());
2611
2612 SuccessOrExit(error = mEncoder.WriteEui64(entry.mExtAddress));
2613 SuccessOrExit(error = mEncoder.WriteInt8(entry.mRssIn));
2614
2615 SuccessOrExit(error = mEncoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08002616 }
2617
Buke Po818998e2017-08-04 01:19:07 +08002618exit:
Buke Po818998e2017-08-04 01:19:07 +08002619 return error;
2620}
2621
Yakun Xu8ccf1382018-06-29 00:26:31 +08002622template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_WHITELIST_ENABLED>(void)
Buke Po818998e2017-08-04 01:19:07 +08002623{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002624 return mEncoder.WriteBool(otLinkFilterGetAddressMode(mInstance) == OT_MAC_FILTER_ADDRESS_MODE_WHITELIST);
Buke Po818998e2017-08-04 01:19:07 +08002625}
2626
Yakun Xu8ccf1382018-06-29 00:26:31 +08002627template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_BLACKLIST>(void)
Buke Po818998e2017-08-04 01:19:07 +08002628{
Yakun Xub8333732018-06-21 04:15:13 +08002629 otMacFilterEntry entry;
Buke Po818998e2017-08-04 01:19:07 +08002630 otMacFilterIterator iterator = OT_MAC_FILTER_ITERATOR_INIT;
Yakun Xub8333732018-06-21 04:15:13 +08002631 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08002632
Buke Po818998e2017-08-04 01:19:07 +08002633 while (otLinkFilterGetNextAddress(mInstance, &iterator, &entry) == OT_ERROR_NONE)
2634 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002635 SuccessOrExit(error = mEncoder.OpenStruct());
2636 SuccessOrExit(error = mEncoder.WriteEui64(entry.mExtAddress));
2637 SuccessOrExit(error = mEncoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08002638 }
2639
Buke Po818998e2017-08-04 01:19:07 +08002640exit:
Buke Po818998e2017-08-04 01:19:07 +08002641 return error;
2642}
2643
Yakun Xu8ccf1382018-06-29 00:26:31 +08002644template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_BLACKLIST_ENABLED>(void)
Buke Po818998e2017-08-04 01:19:07 +08002645{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002646 return mEncoder.WriteBool(otLinkFilterGetAddressMode(mInstance) == OT_MAC_FILTER_ADDRESS_MODE_BLACKLIST);
Buke Po818998e2017-08-04 01:19:07 +08002647}
2648
Yakun Xu8ccf1382018-06-29 00:26:31 +08002649template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_FIXED_RSS>(void)
Buke Po818998e2017-08-04 01:19:07 +08002650{
Yakun Xub8333732018-06-21 04:15:13 +08002651 otMacFilterEntry entry;
Buke Po818998e2017-08-04 01:19:07 +08002652 otMacFilterIterator iterator = OT_MAC_FILTER_ITERATOR_INIT;
Yakun Xub8333732018-06-21 04:15:13 +08002653 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08002654
Buke Po818998e2017-08-04 01:19:07 +08002655 while (otLinkFilterGetNextRssIn(mInstance, &iterator, &entry) == OT_ERROR_NONE)
2656 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002657 SuccessOrExit(error = mEncoder.OpenStruct());
2658
2659 SuccessOrExit(error = mEncoder.WriteEui64(entry.mExtAddress));
2660 SuccessOrExit(error = mEncoder.WriteInt8(entry.mRssIn));
2661
2662 SuccessOrExit(error = mEncoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08002663 }
2664
Buke Po818998e2017-08-04 01:19:07 +08002665exit:
Buke Po818998e2017-08-04 01:19:07 +08002666 return error;
2667}
2668
Yakun Xu8ccf1382018-06-29 00:26:31 +08002669template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_WHITELIST>(void)
Buke Po818998e2017-08-04 01:19:07 +08002670{
Buke Po818998e2017-08-04 01:19:07 +08002671 otError error = OT_ERROR_NONE;
2672
2673 // First, clear the address filter entries.
2674 otLinkFilterClearAddresses(mInstance);
2675
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002676 while (mDecoder.GetRemainingLengthInStruct() > 0)
Buke Po818998e2017-08-04 01:19:07 +08002677 {
Jonathan Hui1326d642020-06-17 22:44:54 -07002678 const otExtAddress *extAddress = nullptr;
Yakun Xub8333732018-06-21 04:15:13 +08002679 int8_t rss;
Buke Po818998e2017-08-04 01:19:07 +08002680
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002681 SuccessOrExit(error = mDecoder.OpenStruct());
2682 SuccessOrExit(error = mDecoder.ReadEui64(extAddress));
Buke Po818998e2017-08-04 01:19:07 +08002683
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002684 if (!mDecoder.IsAllReadInStruct())
2685 {
2686 SuccessOrExit(error = mDecoder.ReadInt8(rss));
2687 }
2688 else
Buke Po818998e2017-08-04 01:19:07 +08002689 {
2690 rss = OT_MAC_FILTER_FIXED_RSS_DISABLED;
Buke Po818998e2017-08-04 01:19:07 +08002691 }
2692
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002693 SuccessOrExit(error = mDecoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08002694
2695 error = otLinkFilterAddAddress(mInstance, extAddress);
2696
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002697 if (error == OT_ERROR_ALREADY)
2698 {
2699 error = OT_ERROR_NONE;
2700 }
2701
2702 SuccessOrExit(error);
Buke Po818998e2017-08-04 01:19:07 +08002703
2704 if (rss != OT_MAC_FILTER_FIXED_RSS_DISABLED)
2705 {
2706 SuccessOrExit(error = otLinkFilterAddRssIn(mInstance, extAddress, rss));
2707 }
Buke Po818998e2017-08-04 01:19:07 +08002708 }
2709
2710exit:
2711 // If we had an error, we may have actually changed
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002712 // the state of the whitelist, so we need to report
Buke Po818998e2017-08-04 01:19:07 +08002713 // those incomplete changes via an asynchronous
2714 // change event.
Buke Po818998e2017-08-04 01:19:07 +08002715
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002716 if (error != OT_ERROR_NONE)
Buke Po818998e2017-08-04 01:19:07 +08002717 {
kangping49f36f82020-05-07 02:17:58 +08002718 IgnoreError(WritePropertyValueIsFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_PROP_MAC_WHITELIST));
Buke Po818998e2017-08-04 01:19:07 +08002719 }
2720
2721 return error;
2722}
2723
Yakun Xu8ccf1382018-06-29 00:26:31 +08002724template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_WHITELIST_ENABLED>(void)
Buke Po818998e2017-08-04 01:19:07 +08002725{
Yakun Xub8333732018-06-21 04:15:13 +08002726 bool enabled;
2727 otError error = OT_ERROR_NONE;
2728 otMacFilterAddressMode mode = OT_MAC_FILTER_ADDRESS_MODE_DISABLED;
Buke Po818998e2017-08-04 01:19:07 +08002729
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002730 SuccessOrExit(error = mDecoder.ReadBool(enabled));
Buke Po818998e2017-08-04 01:19:07 +08002731
2732 if (enabled)
2733 {
2734 mode = OT_MAC_FILTER_ADDRESS_MODE_WHITELIST;
2735 }
2736
Abtin Keshavarzian6f1fc2e2020-06-29 08:59:34 -07002737 otLinkFilterSetAddressMode(mInstance, mode);
Buke Po818998e2017-08-04 01:19:07 +08002738
2739exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002740 return error;
Buke Po818998e2017-08-04 01:19:07 +08002741}
2742
Yakun Xu8ccf1382018-06-29 00:26:31 +08002743template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_BLACKLIST>(void)
Buke Po818998e2017-08-04 01:19:07 +08002744{
Buke Po818998e2017-08-04 01:19:07 +08002745 otError error = OT_ERROR_NONE;
2746
2747 // First, clear the address filter entries.
2748 otLinkFilterClearAddresses(mInstance);
2749
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002750 while (mDecoder.GetRemainingLengthInStruct() > 0)
Buke Po818998e2017-08-04 01:19:07 +08002751 {
Jonathan Hui1326d642020-06-17 22:44:54 -07002752 const otExtAddress *extAddress = nullptr;
Buke Po818998e2017-08-04 01:19:07 +08002753
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002754 SuccessOrExit(error = mDecoder.OpenStruct());
2755 SuccessOrExit(error = mDecoder.ReadEui64(extAddress));
2756 SuccessOrExit(error = mDecoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08002757
Abtin Keshavarzian6f1fc2e2020-06-29 08:59:34 -07002758 otLinkFilterRemoveAddress(mInstance, extAddress);
Buke Po818998e2017-08-04 01:19:07 +08002759 }
2760
2761exit:
2762 // If we had an error, we may have actually changed
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002763 // the state of the blacklist, so we need to report
Buke Po818998e2017-08-04 01:19:07 +08002764 // those incomplete changes via an asynchronous
2765 // change event.
Buke Po818998e2017-08-04 01:19:07 +08002766
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002767 if (error != OT_ERROR_NONE)
Buke Po818998e2017-08-04 01:19:07 +08002768 {
kangping49f36f82020-05-07 02:17:58 +08002769 IgnoreError(WritePropertyValueIsFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_PROP_MAC_BLACKLIST));
Buke Po818998e2017-08-04 01:19:07 +08002770 }
2771
2772 return error;
2773}
2774
Yakun Xu8ccf1382018-06-29 00:26:31 +08002775template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_BLACKLIST_ENABLED>(void)
Buke Po818998e2017-08-04 01:19:07 +08002776{
Yakun Xub8333732018-06-21 04:15:13 +08002777 bool enabled;
2778 otError error = OT_ERROR_NONE;
2779 otMacFilterAddressMode mode = OT_MAC_FILTER_ADDRESS_MODE_DISABLED;
Buke Po818998e2017-08-04 01:19:07 +08002780
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002781 SuccessOrExit(error = mDecoder.ReadBool(enabled));
Buke Po818998e2017-08-04 01:19:07 +08002782
2783 if (enabled)
2784 {
2785 mode = OT_MAC_FILTER_ADDRESS_MODE_BLACKLIST;
2786 }
2787
Abtin Keshavarzian6f1fc2e2020-06-29 08:59:34 -07002788 otLinkFilterSetAddressMode(mInstance, mode);
Buke Po818998e2017-08-04 01:19:07 +08002789
2790exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002791 return error;
Buke Po818998e2017-08-04 01:19:07 +08002792}
2793
Yakun Xu8ccf1382018-06-29 00:26:31 +08002794template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_FIXED_RSS>(void)
Buke Po818998e2017-08-04 01:19:07 +08002795{
Buke Po818998e2017-08-04 01:19:07 +08002796 otError error = OT_ERROR_NONE;
2797
2798 // First, clear the address filter entries.
Abtin Keshavarzian6f1fc2e2020-06-29 08:59:34 -07002799 otLinkFilterClearAllRssIn(mInstance);
Buke Po818998e2017-08-04 01:19:07 +08002800
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002801 while (mDecoder.GetRemainingLengthInStruct() > 0)
Buke Po818998e2017-08-04 01:19:07 +08002802 {
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002803 const otExtAddress *extAddress;
Yakun Xub8333732018-06-21 04:15:13 +08002804 int8_t rss;
Buke Po818998e2017-08-04 01:19:07 +08002805
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002806 SuccessOrExit(error = mDecoder.OpenStruct());
Buke Po818998e2017-08-04 01:19:07 +08002807
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002808 if (mDecoder.GetRemainingLengthInStruct() > sizeof(otExtAddress))
2809 {
2810 SuccessOrExit(error = mDecoder.ReadEui64(extAddress));
2811 }
2812 else
Buke Po818998e2017-08-04 01:19:07 +08002813 {
Jonathan Hui1326d642020-06-17 22:44:54 -07002814 extAddress = nullptr;
Buke Po818998e2017-08-04 01:19:07 +08002815 }
2816
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002817 SuccessOrExit(error = mDecoder.ReadInt8(rss));
2818
2819 SuccessOrExit(error = mDecoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08002820
Abtin Keshavarzian6f1fc2e2020-06-29 08:59:34 -07002821 if (extAddress != nullptr)
2822 {
2823 SuccessOrExit(error = otLinkFilterAddRssIn(mInstance, extAddress, rss));
2824 }
2825 else
2826 {
2827 otLinkFilterSetDefaultRssIn(mInstance, rss);
2828 }
Buke Po818998e2017-08-04 01:19:07 +08002829 }
2830
2831exit:
2832 // If we had an error, we may have actually changed
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002833 // the state of the RssIn filter, so we need to report
Buke Po818998e2017-08-04 01:19:07 +08002834 // those incomplete changes via an asynchronous
2835 // change event.
Buke Po818998e2017-08-04 01:19:07 +08002836
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002837 if (error != OT_ERROR_NONE)
Buke Po818998e2017-08-04 01:19:07 +08002838 {
kangping49f36f82020-05-07 02:17:58 +08002839 IgnoreError(WritePropertyValueIsFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_PROP_MAC_FIXED_RSS));
Buke Po818998e2017-08-04 01:19:07 +08002840 }
2841
2842 return error;
2843}
Jonathan Hui0baaf1a2019-07-15 12:57:32 -07002844#endif // OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08002845
Yakun Xu8ccf1382018-06-29 00:26:31 +08002846template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_MODE>(void)
Buke Po818998e2017-08-04 01:19:07 +08002847{
Yakun Xub8333732018-06-21 04:15:13 +08002848 uint8_t numericMode;
Buke Po818998e2017-08-04 01:19:07 +08002849 otLinkModeConfig modeConfig = otThreadGetLinkMode(mInstance);
2850
Yakun Xub8333732018-06-21 04:15:13 +08002851 numericMode = LinkFlagsToFlagByte(modeConfig.mRxOnWhenIdle, modeConfig.mSecureDataRequests, modeConfig.mDeviceType,
2852 modeConfig.mNetworkData);
Buke Po818998e2017-08-04 01:19:07 +08002853
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002854 return mEncoder.WriteUint8(numericMode);
Buke Po818998e2017-08-04 01:19:07 +08002855}
2856
Yakun Xu8ccf1382018-06-29 00:26:31 +08002857template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_MODE>(void)
Buke Po818998e2017-08-04 01:19:07 +08002858{
Yakun Xub8333732018-06-21 04:15:13 +08002859 uint8_t numericMode = 0;
Buke Po818998e2017-08-04 01:19:07 +08002860 otLinkModeConfig modeConfig;
Yakun Xub8333732018-06-21 04:15:13 +08002861 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08002862
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002863 SuccessOrExit(mDecoder.ReadUint8(numericMode));
Buke Po818998e2017-08-04 01:19:07 +08002864
Yakun Xub8333732018-06-21 04:15:13 +08002865 modeConfig.mRxOnWhenIdle =
2866 ((numericMode & SPINEL_THREAD_MODE_RX_ON_WHEN_IDLE) == SPINEL_THREAD_MODE_RX_ON_WHEN_IDLE);
Buke Po818998e2017-08-04 01:19:07 +08002867 modeConfig.mSecureDataRequests =
2868 ((numericMode & SPINEL_THREAD_MODE_SECURE_DATA_REQUEST) == SPINEL_THREAD_MODE_SECURE_DATA_REQUEST);
Jonathan Hui5a489832018-09-27 09:33:03 -07002869 modeConfig.mDeviceType = ((numericMode & SPINEL_THREAD_MODE_FULL_THREAD_DEV) == SPINEL_THREAD_MODE_FULL_THREAD_DEV);
Yakun Xub8333732018-06-21 04:15:13 +08002870 modeConfig.mNetworkData =
2871 ((numericMode & SPINEL_THREAD_MODE_FULL_NETWORK_DATA) == SPINEL_THREAD_MODE_FULL_NETWORK_DATA);
Buke Po818998e2017-08-04 01:19:07 +08002872
2873 error = otThreadSetLinkMode(mInstance, modeConfig);
2874
2875exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002876 return error;
Buke Po818998e2017-08-04 01:19:07 +08002877}
2878
Yakun Xu8ccf1382018-06-29 00:26:31 +08002879template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_CHILD_TIMEOUT>(void)
Buke Po818998e2017-08-04 01:19:07 +08002880{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002881 return mEncoder.WriteUint32(otThreadGetChildTimeout(mInstance));
Buke Po818998e2017-08-04 01:19:07 +08002882}
2883
Abtin Keshavarziand67c4e22018-08-01 22:55:35 -07002884template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_CHILD_TIMEOUT>(void)
2885{
2886 uint32_t timeout = 0;
2887 otError error = OT_ERROR_NONE;
2888
2889 SuccessOrExit(error = mDecoder.ReadUint32(timeout));
2890
2891 otThreadSetChildTimeout(mInstance, timeout);
2892
2893exit:
2894 return error;
2895}
2896
Yakun Xu8ccf1382018-06-29 00:26:31 +08002897template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_RLOC16>(void)
Buke Po818998e2017-08-04 01:19:07 +08002898{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002899 return mEncoder.WriteUint16(otThreadGetRloc16(mInstance));
Buke Po818998e2017-08-04 01:19:07 +08002900}
2901
Yakun Xu8ccf1382018-06-29 00:26:31 +08002902template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NET_REQUIRE_JOIN_EXISTING>(void)
Buke Po818998e2017-08-04 01:19:07 +08002903{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002904 return mEncoder.WriteBool(mRequireJoinExistingNetwork);
Buke Po818998e2017-08-04 01:19:07 +08002905}
2906
Yakun Xu8ccf1382018-06-29 00:26:31 +08002907template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_NET_REQUIRE_JOIN_EXISTING>(void)
Buke Po818998e2017-08-04 01:19:07 +08002908{
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002909 return mDecoder.ReadBool(mRequireJoinExistingNetwork);
Buke Po818998e2017-08-04 01:19:07 +08002910}
2911
Yakun Xu8ccf1382018-06-29 00:26:31 +08002912template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_STREAM_NET_INSECURE>(void)
Buke Po818998e2017-08-04 01:19:07 +08002913{
Jonathan Hui1326d642020-06-17 22:44:54 -07002914 const uint8_t * framePtr = nullptr;
Zhanglong Xiaf8909592018-11-06 04:48:39 +08002915 uint16_t frameLen = 0;
Jonathan Hui1326d642020-06-17 22:44:54 -07002916 const uint8_t * metaPtr = nullptr;
Zhanglong Xiaf8909592018-11-06 04:48:39 +08002917 uint16_t metaLen = 0;
Jonathan Hui1326d642020-06-17 22:44:54 -07002918 otMessage * message = nullptr;
Zhanglong Xiaf8909592018-11-06 04:48:39 +08002919 otError error = OT_ERROR_NONE;
2920 otMessageSettings msgSettings = {false, OT_MESSAGE_PRIORITY_NORMAL};
Buke Po818998e2017-08-04 01:19:07 +08002921
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002922 SuccessOrExit(mDecoder.ReadDataWithLen(framePtr, frameLen));
2923 SuccessOrExit(mDecoder.ReadData(metaPtr, metaLen));
Buke Po818998e2017-08-04 01:19:07 +08002924
2925 // We ignore metadata for now.
2926 // May later include TX power, allow retransmits, etc...
Buke Po818998e2017-08-04 01:19:07 +08002927
Zhanglong Xia19f25332018-12-20 05:55:26 +08002928 // STREAM_NET_INSECURE packets are not secured at layer 2.
2929 message = otIp6NewMessageFromBuffer(mInstance, framePtr, frameLen, &msgSettings);
Jonathan Hui1326d642020-06-17 22:44:54 -07002930 VerifyOrExit(message != nullptr, error = OT_ERROR_NO_BUFS);
Buke Po818998e2017-08-04 01:19:07 +08002931
2932 // Ensure the insecure message is forwarded using direct transmission.
2933 otMessageSetDirectTransmission(message, true);
2934
2935 error = otIp6Send(mInstance, message);
2936
Buke Po818998e2017-08-04 01:19:07 +08002937exit:
Buke Po818998e2017-08-04 01:19:07 +08002938 if (error == OT_ERROR_NONE)
2939 {
2940 mInboundInsecureIpFrameCounter++;
Buke Po818998e2017-08-04 01:19:07 +08002941 }
2942 else
2943 {
2944 mDroppedInboundIpFrameCounter++;
Buke Po818998e2017-08-04 01:19:07 +08002945 }
2946
Buke Po818998e2017-08-04 01:19:07 +08002947 return error;
2948}
2949
Yakun Xu8ccf1382018-06-29 00:26:31 +08002950template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_CNTR_RESET>(void)
Buke Po818998e2017-08-04 01:19:07 +08002951{
Abtin Keshavarzian112d1bb2019-10-29 15:34:03 -07002952 otLinkResetCounters(mInstance);
Paweł Wańczykc646e6f2019-12-18 19:23:43 +01002953#if OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE
2954 otLinkResetTxRetrySuccessHistogram(mInstance);
2955#endif
Abtin Keshavarzian112d1bb2019-10-29 15:34:03 -07002956 otThreadResetIp6Counters(mInstance);
2957 otThreadResetMleCounters(mInstance);
2958 ResetCounters();
Buke Po818998e2017-08-04 01:19:07 +08002959
Abtin Keshavarzian112d1bb2019-10-29 15:34:03 -07002960 return OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08002961}
2962
Yakun Xu8ccf1382018-06-29 00:26:31 +08002963template <> otError NcpBase::HandlePropertyInsert<SPINEL_PROP_THREAD_ASSISTING_PORTS>(void)
Buke Po818998e2017-08-04 01:19:07 +08002964{
Yakun Xub8333732018-06-21 04:15:13 +08002965 otError error = OT_ERROR_NONE;
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002966 uint16_t port;
2967
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002968 SuccessOrExit(error = mDecoder.ReadUint16(port));
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002969
2970 error = otIp6AddUnsecurePort(mInstance, port);
2971exit:
2972 return error;
2973}
2974
Jonathan Hui0baaf1a2019-07-15 12:57:32 -07002975#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002976
Yakun Xu8ccf1382018-06-29 00:26:31 +08002977template <> otError NcpBase::HandlePropertyInsert<SPINEL_PROP_MAC_WHITELIST>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002978{
Abtin Keshavarzian6f1fc2e2020-06-29 08:59:34 -07002979 otError error = OT_ERROR_NONE;
2980 const otExtAddress *extAddress;
2981 int8_t rss = OT_MAC_FILTER_FIXED_RSS_DISABLED;
Buke Po818998e2017-08-04 01:19:07 +08002982
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002983 SuccessOrExit(error = mDecoder.ReadEui64(extAddress));
Buke Po818998e2017-08-04 01:19:07 +08002984
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002985 if (!mDecoder.IsAllRead())
2986 {
2987 SuccessOrExit(error = mDecoder.ReadInt8(rss));
2988 }
Buke Po818998e2017-08-04 01:19:07 +08002989
2990 error = otLinkFilterAddAddress(mInstance, extAddress);
2991
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002992 if (error == OT_ERROR_ALREADY)
2993 {
2994 error = OT_ERROR_NONE;
2995 }
2996
2997 SuccessOrExit(error);
Buke Po818998e2017-08-04 01:19:07 +08002998
2999 if (rss != OT_MAC_FILTER_FIXED_RSS_DISABLED)
3000 {
3001 error = otLinkFilterAddRssIn(mInstance, extAddress, rss);
Buke Po818998e2017-08-04 01:19:07 +08003002 }
3003
Buke Po818998e2017-08-04 01:19:07 +08003004exit:
Buke Po818998e2017-08-04 01:19:07 +08003005 return error;
3006}
3007
Yakun Xu8ccf1382018-06-29 00:26:31 +08003008template <> otError NcpBase::HandlePropertyInsert<SPINEL_PROP_MAC_BLACKLIST>(void)
Buke Po818998e2017-08-04 01:19:07 +08003009{
Abtin Keshavarzian6f1fc2e2020-06-29 08:59:34 -07003010 otError error = OT_ERROR_NONE;
3011 const otExtAddress *extAddress;
Buke Po818998e2017-08-04 01:19:07 +08003012
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07003013 SuccessOrExit(error = mDecoder.ReadEui64(extAddress));
Buke Po818998e2017-08-04 01:19:07 +08003014
3015 error = otLinkFilterAddAddress(mInstance, extAddress);
3016
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003017 if (error == OT_ERROR_ALREADY)
Buke Po818998e2017-08-04 01:19:07 +08003018 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003019 error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08003020 }
3021
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003022exit:
Buke Po818998e2017-08-04 01:19:07 +08003023 return error;
3024}
3025
Yakun Xu8ccf1382018-06-29 00:26:31 +08003026template <> otError NcpBase::HandlePropertyInsert<SPINEL_PROP_MAC_FIXED_RSS>(void)
Buke Po818998e2017-08-04 01:19:07 +08003027{
Yakun Xub8333732018-06-21 04:15:13 +08003028 otError error = OT_ERROR_NONE;
Jonathan Hui1326d642020-06-17 22:44:54 -07003029 const otExtAddress *extAddress = nullptr;
Yakun Xub8333732018-06-21 04:15:13 +08003030 int8_t rss = OT_MAC_FILTER_FIXED_RSS_DISABLED;
Buke Po818998e2017-08-04 01:19:07 +08003031
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07003032 if (mDecoder.GetRemainingLength() > sizeof(int8_t))
Buke Po818998e2017-08-04 01:19:07 +08003033 {
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07003034 SuccessOrExit(mDecoder.ReadEui64(extAddress));
Buke Po818998e2017-08-04 01:19:07 +08003035 }
3036
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07003037 SuccessOrExit(mDecoder.ReadInt8(rss));
Buke Po818998e2017-08-04 01:19:07 +08003038
Abtin Keshavarzian6f1fc2e2020-06-29 08:59:34 -07003039 if (extAddress != nullptr)
3040 {
3041 error = otLinkFilterAddRssIn(mInstance, extAddress, rss);
3042 }
3043 else
3044 {
3045 otLinkFilterSetDefaultRssIn(mInstance, rss);
3046 }
Buke Po818998e2017-08-04 01:19:07 +08003047
Buke Po818998e2017-08-04 01:19:07 +08003048exit:
Buke Po818998e2017-08-04 01:19:07 +08003049 return error;
3050}
3051
Jonathan Hui0baaf1a2019-07-15 12:57:32 -07003052#endif // OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08003053
Yakun Xu8ccf1382018-06-29 00:26:31 +08003054template <> otError NcpBase::HandlePropertyRemove<SPINEL_PROP_THREAD_ASSISTING_PORTS>(void)
Buke Po818998e2017-08-04 01:19:07 +08003055{
Yakun Xub8333732018-06-21 04:15:13 +08003056 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08003057 uint16_t port;
3058
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07003059 SuccessOrExit(error = mDecoder.ReadUint16(port));
Buke Po818998e2017-08-04 01:19:07 +08003060
3061 error = otIp6RemoveUnsecurePort(mInstance, port);
Abtin Keshavarzian02bdc692017-08-15 09:11:19 -07003062
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003063 // If unsecure port was not on the list, "remove" command is successful.
3064 if (error == OT_ERROR_NOT_FOUND)
Buke Po818998e2017-08-04 01:19:07 +08003065 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003066 error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08003067 }
3068
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003069exit:
Buke Po818998e2017-08-04 01:19:07 +08003070 return error;
3071}
3072
Jonathan Hui0baaf1a2019-07-15 12:57:32 -07003073#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08003074
Yakun Xu8ccf1382018-06-29 00:26:31 +08003075template <> otError NcpBase::HandlePropertyRemove<SPINEL_PROP_MAC_WHITELIST>(void)
Buke Po818998e2017-08-04 01:19:07 +08003076{
Yakun Xub8333732018-06-21 04:15:13 +08003077 otError error = OT_ERROR_NONE;
Jonathan Hui1326d642020-06-17 22:44:54 -07003078 const otExtAddress *extAddress = nullptr;
Buke Po818998e2017-08-04 01:19:07 +08003079
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07003080 SuccessOrExit(error = mDecoder.ReadEui64(extAddress));
Buke Po818998e2017-08-04 01:19:07 +08003081
Abtin Keshavarzian6f1fc2e2020-06-29 08:59:34 -07003082 otLinkFilterRemoveAddress(mInstance, extAddress);
Buke Po818998e2017-08-04 01:19:07 +08003083
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003084exit:
Buke Po818998e2017-08-04 01:19:07 +08003085 return error;
3086}
3087
Yakun Xu8ccf1382018-06-29 00:26:31 +08003088template <> otError NcpBase::HandlePropertyRemove<SPINEL_PROP_MAC_BLACKLIST>(void)
Buke Po818998e2017-08-04 01:19:07 +08003089{
Yakun Xub8333732018-06-21 04:15:13 +08003090 otError error = OT_ERROR_NONE;
Jonathan Hui1326d642020-06-17 22:44:54 -07003091 const otExtAddress *extAddress = nullptr;
Buke Po818998e2017-08-04 01:19:07 +08003092
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07003093 SuccessOrExit(error = mDecoder.ReadEui64(extAddress));
Buke Po818998e2017-08-04 01:19:07 +08003094
Abtin Keshavarzian6f1fc2e2020-06-29 08:59:34 -07003095 otLinkFilterRemoveAddress(mInstance, extAddress);
Buke Po818998e2017-08-04 01:19:07 +08003096
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003097exit:
Buke Po818998e2017-08-04 01:19:07 +08003098 return error;
3099}
3100
Yakun Xu8ccf1382018-06-29 00:26:31 +08003101template <> otError NcpBase::HandlePropertyRemove<SPINEL_PROP_MAC_FIXED_RSS>(void)
Buke Po818998e2017-08-04 01:19:07 +08003102{
Yakun Xub8333732018-06-21 04:15:13 +08003103 otError error = OT_ERROR_NONE;
Jonathan Hui1326d642020-06-17 22:44:54 -07003104 const otExtAddress *extAddress = nullptr;
Buke Po818998e2017-08-04 01:19:07 +08003105
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07003106 if (mDecoder.GetRemainingLength() > 0)
Buke Po818998e2017-08-04 01:19:07 +08003107 {
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07003108 SuccessOrExit(error = mDecoder.ReadEui64(extAddress));
Buke Po818998e2017-08-04 01:19:07 +08003109 }
3110
Abtin Keshavarzian6f1fc2e2020-06-29 08:59:34 -07003111 if (extAddress != nullptr)
Buke Po818998e2017-08-04 01:19:07 +08003112 {
Abtin Keshavarzian6f1fc2e2020-06-29 08:59:34 -07003113 otLinkFilterRemoveRssIn(mInstance, extAddress);
3114 }
3115 else
3116 {
3117 otLinkFilterClearDefaultRssIn(mInstance);
Buke Po818998e2017-08-04 01:19:07 +08003118 }
3119
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003120exit:
Buke Po818998e2017-08-04 01:19:07 +08003121 return error;
3122}
3123
Jonathan Hui0baaf1a2019-07-15 12:57:32 -07003124#endif // OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08003125
Yakun Xu65374592020-03-12 02:42:30 +08003126#if OPENTHREAD_PLATFORM_POSIX
Abtin Keshavarzian7c8a3722018-10-12 10:40:57 -07003127
3128template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_RCP_VERSION>(void)
3129{
3130 return mEncoder.WriteUtf8(otGetRadioVersionString(mInstance));
3131}
3132
Abtin Keshavarzian6e718a12019-04-04 17:39:22 -07003133#endif
Abtin Keshavarzian7c8a3722018-10-12 10:40:57 -07003134
Jonathan Hui4a475d52019-07-15 22:13:11 -07003135#if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
Abtin Keshavarzian89396ab2019-03-11 14:59:43 -07003136
3137template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_SLAAC_ENABLED>(void)
3138{
3139 return mEncoder.WriteBool(otIp6IsSlaacEnabled(mInstance));
3140}
3141
3142template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_SLAAC_ENABLED>(void)
3143{
3144 otError error = OT_ERROR_NONE;
3145 bool enabled;
3146
3147 SuccessOrExit(error = mDecoder.ReadBool(enabled));
3148 otIp6SetSlaacEnabled(mInstance, enabled);
3149
3150exit:
3151 return error;
3152}
3153
Jonathan Hui4a475d52019-07-15 22:13:11 -07003154#endif // OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
Abtin Keshavarzian89396ab2019-03-11 14:59:43 -07003155
Jonathan Hui02da2062019-07-16 12:18:34 -07003156#if OPENTHREAD_CONFIG_LEGACY_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08003157
3158void NcpBase::RegisterLegacyHandlers(const otNcpLegacyHandlers *aHandlers)
3159{
3160 mLegacyHandlers = aHandlers;
3161 bool isEnabled;
3162
Jonathan Hui1326d642020-06-17 22:44:54 -07003163 VerifyOrExit(mLegacyHandlers != nullptr, OT_NOOP);
Buke Po818998e2017-08-04 01:19:07 +08003164
3165 isEnabled = (otThreadGetDeviceRole(mInstance) != OT_DEVICE_ROLE_DISABLED);
3166
3167 if (isEnabled)
3168 {
3169 if (mLegacyHandlers->mStartLegacy)
3170 {
3171 mLegacyHandlers->mStartLegacy();
3172 }
3173 }
3174 else
3175 {
3176 if (mLegacyHandlers->mStopLegacy)
3177 {
3178 mLegacyHandlers->mStopLegacy();
3179 }
3180 }
3181
3182 if (mLegacyHandlers->mSetLegacyUlaPrefix)
3183 {
3184 mLegacyHandlers->mSetLegacyUlaPrefix(mLegacyUlaPrefix);
3185 }
3186
3187exit:
3188 return;
3189}
3190
3191void NcpBase::HandleDidReceiveNewLegacyUlaPrefix(const uint8_t *aUlaPrefix)
3192{
3193 memcpy(mLegacyUlaPrefix, aUlaPrefix, OT_NCP_LEGACY_ULA_PREFIX_LENGTH);
3194 mChangedPropsSet.AddProperty(SPINEL_PROP_NEST_LEGACY_ULA_PREFIX);
Abtin Keshavarziana1adaac2020-05-11 10:24:58 -07003195 mUpdateChangedPropsTask.Post();
Buke Po818998e2017-08-04 01:19:07 +08003196}
3197
3198void NcpBase::HandleLegacyNodeDidJoin(const otExtAddress *aExtAddr)
3199{
Yakun Xub8333732018-06-21 04:15:13 +08003200 mLegacyNodeDidJoin = true;
Buke Po818998e2017-08-04 01:19:07 +08003201 mLegacyLastJoinedNode = *aExtAddr;
3202 mChangedPropsSet.AddProperty(SPINEL_PROP_NEST_LEGACY_LAST_NODE_JOINED);
Abtin Keshavarziana1adaac2020-05-11 10:24:58 -07003203 mUpdateChangedPropsTask.Post();
Buke Po818998e2017-08-04 01:19:07 +08003204}
3205
Yakun Xu8ccf1382018-06-29 00:26:31 +08003206template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NEST_LEGACY_ULA_PREFIX>(void)
Buke Po818998e2017-08-04 01:19:07 +08003207{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003208 return mEncoder.WriteData(mLegacyUlaPrefix, sizeof(mLegacyUlaPrefix));
Buke Po818998e2017-08-04 01:19:07 +08003209}
3210
Yakun Xu8ccf1382018-06-29 00:26:31 +08003211template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_NEST_LEGACY_ULA_PREFIX>(void)
Buke Po818998e2017-08-04 01:19:07 +08003212{
Jonathan Hui1326d642020-06-17 22:44:54 -07003213 const uint8_t *ptr = nullptr;
Yakun Xub8333732018-06-21 04:15:13 +08003214 uint16_t len;
3215 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08003216
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07003217 SuccessOrExit(error = mDecoder.ReadData(ptr, len));
Buke Po818998e2017-08-04 01:19:07 +08003218
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07003219 VerifyOrExit(len <= sizeof(mLegacyUlaPrefix), error = OT_ERROR_PARSE);
Buke Po818998e2017-08-04 01:19:07 +08003220
3221 memset(mLegacyUlaPrefix, 0, sizeof(mLegacyUlaPrefix));
3222 memcpy(mLegacyUlaPrefix, ptr, len);
3223
Jonathan Hui1326d642020-06-17 22:44:54 -07003224 if ((mLegacyHandlers != nullptr) && (mLegacyHandlers->mSetLegacyUlaPrefix != nullptr))
Buke Po818998e2017-08-04 01:19:07 +08003225 {
3226 mLegacyHandlers->mSetLegacyUlaPrefix(mLegacyUlaPrefix);
3227 }
3228
3229exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07003230 return error;
Buke Po818998e2017-08-04 01:19:07 +08003231}
3232
Yakun Xu8ccf1382018-06-29 00:26:31 +08003233template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NEST_LEGACY_LAST_NODE_JOINED>(void)
Buke Po818998e2017-08-04 01:19:07 +08003234{
3235 if (!mLegacyNodeDidJoin)
3236 {
3237 memset(&mLegacyLastJoinedNode, 0, sizeof(mLegacyLastJoinedNode));
3238 }
3239
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003240 return mEncoder.WriteEui64(mLegacyLastJoinedNode);
Buke Po818998e2017-08-04 01:19:07 +08003241}
Abtin Keshavarzianecd28452018-04-05 10:20:47 -07003242
3243void NcpBase::StartLegacy(void)
3244{
3245 mLegacyNodeDidJoin = false;
3246
Jonathan Hui1326d642020-06-17 22:44:54 -07003247 if ((mLegacyHandlers != nullptr) && (mLegacyHandlers->mStartLegacy != nullptr))
Abtin Keshavarzianecd28452018-04-05 10:20:47 -07003248 {
3249 mLegacyHandlers->mStartLegacy();
3250 }
3251}
3252
3253void NcpBase::StopLegacy(void)
3254{
3255 mLegacyNodeDidJoin = false;
3256
Jonathan Hui1326d642020-06-17 22:44:54 -07003257 if ((mLegacyHandlers != nullptr) && (mLegacyHandlers->mStopLegacy != nullptr))
Abtin Keshavarzianecd28452018-04-05 10:20:47 -07003258 {
3259 mLegacyHandlers->mStopLegacy();
3260 }
3261}
3262
Jonathan Hui02da2062019-07-16 12:18:34 -07003263#endif // OPENTHREAD_CONFIG_LEGACY_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08003264
Jonathan Hui926b9e82019-07-15 21:16:37 -07003265#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
Yakun Xu8ccf1382018-06-29 00:26:31 +08003266template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_NETWORK_TIME>(void)
Shu Chene69019f2018-06-27 02:46:32 +08003267{
3268 otError error = OT_ERROR_NONE;
3269 otNetworkTimeStatus networkTimeStatus;
3270 uint64_t time;
3271
Jonathan Huifa395d72019-05-20 08:50:43 -07003272 networkTimeStatus = otNetworkTimeGet(mInstance, &time);
Shu Chene69019f2018-06-27 02:46:32 +08003273
3274 SuccessOrExit(error = mEncoder.WriteUint64(time));
3275 SuccessOrExit(error = mEncoder.WriteInt8((int8_t)networkTimeStatus));
3276
3277exit:
3278 return error;
3279}
Joseph Newman4f99bcf2018-11-08 06:32:31 +00003280
3281void NcpBase::HandleTimeSyncUpdate(void *aContext)
3282{
3283 static_cast<NcpBase *>(aContext)->HandleTimeSyncUpdate();
3284}
3285
3286void NcpBase::HandleTimeSyncUpdate(void)
3287{
3288 mChangedPropsSet.AddProperty(SPINEL_PROP_THREAD_NETWORK_TIME);
Abtin Keshavarziana1adaac2020-05-11 10:24:58 -07003289 mUpdateChangedPropsTask.Post();
Joseph Newman4f99bcf2018-11-08 06:32:31 +00003290}
Jonathan Hui926b9e82019-07-15 21:16:37 -07003291#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
Shu Chene69019f2018-06-27 02:46:32 +08003292
Buke Po818998e2017-08-04 01:19:07 +08003293void NcpBase::HandleActiveScanResult_Jump(otActiveScanResult *aResult, void *aContext)
3294{
3295 static_cast<NcpBase *>(aContext)->HandleActiveScanResult(aResult);
3296}
3297
3298// ----------------------------------------------------------------------------
3299// MARK: Scan Results Glue
3300// ----------------------------------------------------------------------------
3301
3302void NcpBase::HandleActiveScanResult(otActiveScanResult *aResult)
3303{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003304 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08003305
3306 if (aResult)
3307 {
3308 uint8_t flags = static_cast<uint8_t>(aResult->mVersion << SPINEL_BEACON_THREAD_FLAG_VERSION_SHIFT);
3309
3310 if (aResult->mIsJoinable)
3311 {
3312 flags |= SPINEL_BEACON_THREAD_FLAG_JOINABLE;
3313 }
3314
3315 if (aResult->mIsNative)
3316 {
3317 flags |= SPINEL_BEACON_THREAD_FLAG_NATIVE;
3318 }
3319
Yakun Xub8333732018-06-21 04:15:13 +08003320 SuccessOrExit(error = mEncoder.BeginFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0,
3321 SPINEL_CMD_PROP_VALUE_INSERTED, SPINEL_PROP_MAC_SCAN_BEACON));
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003322 SuccessOrExit(error = mEncoder.WriteUint8(aResult->mChannel));
3323 SuccessOrExit(error = mEncoder.WriteInt8(aResult->mRssi));
Buke Po818998e2017-08-04 01:19:07 +08003324
Yakun Xub8333732018-06-21 04:15:13 +08003325 SuccessOrExit(error = mEncoder.OpenStruct()); // "mac-layer data"
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003326 SuccessOrExit(error = mEncoder.WriteEui64(aResult->mExtAddress));
Yakun Xub8333732018-06-21 04:15:13 +08003327 SuccessOrExit(error = mEncoder.WriteUint16(0xffff)); // short address, not given
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003328 SuccessOrExit(error = mEncoder.WriteUint16(aResult->mPanId));
3329 SuccessOrExit(error = mEncoder.WriteUint8(aResult->mLqi));
3330 SuccessOrExit(error = mEncoder.CloseStruct());
3331
Yakun Xub8333732018-06-21 04:15:13 +08003332 SuccessOrExit(error = mEncoder.OpenStruct()); // "net-layer data"
3333 SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_PROTOCOL_TYPE_THREAD)); // type
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003334 SuccessOrExit(error = mEncoder.WriteUint8(flags));
3335 SuccessOrExit(error = mEncoder.WriteUtf8(aResult->mNetworkName.m8));
3336 SuccessOrExit(error = mEncoder.WriteDataWithLen(aResult->mExtendedPanId.m8, OT_EXT_PAN_ID_SIZE));
3337 SuccessOrExit(error = mEncoder.WriteDataWithLen(aResult->mSteeringData.m8, aResult->mSteeringData.mLength));
3338 SuccessOrExit(error = mEncoder.CloseStruct());
3339
3340 SuccessOrExit(error = mEncoder.EndFrame());
Buke Po818998e2017-08-04 01:19:07 +08003341 }
3342 else
3343 {
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07003344 // We are finished with the scan, send an unsolicited
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003345 // scan state update.
3346 mChangedPropsSet.AddProperty(SPINEL_PROP_MAC_SCAN_STATE);
Abtin Keshavarziana1adaac2020-05-11 10:24:58 -07003347 mUpdateChangedPropsTask.Post();
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003348 }
Buke Po818998e2017-08-04 01:19:07 +08003349
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003350exit:
3351
3352 if (error != OT_ERROR_NONE)
3353 {
3354 // We ran out of buffer adding a scan result so remember to send
3355 // an async `LAST_STATUS(NOMEM)` when buffer space becomes
Buke Po818998e2017-08-04 01:19:07 +08003356 // available.
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003357 mChangedPropsSet.AddLastStatus(SPINEL_STATUS_NOMEM);
Abtin Keshavarziana1adaac2020-05-11 10:24:58 -07003358 mUpdateChangedPropsTask.Post();
Buke Po818998e2017-08-04 01:19:07 +08003359 }
3360}
3361
3362void NcpBase::HandleEnergyScanResult_Jump(otEnergyScanResult *aResult, void *aContext)
3363{
3364 static_cast<NcpBase *>(aContext)->HandleEnergyScanResult(aResult);
3365}
3366
3367void NcpBase::HandleEnergyScanResult(otEnergyScanResult *aResult)
3368{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003369 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08003370
3371 if (aResult)
3372 {
Yakun Xub8333732018-06-21 04:15:13 +08003373 SuccessOrExit(error = mEncoder.BeginFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0,
3374 SPINEL_CMD_PROP_VALUE_INSERTED, SPINEL_PROP_MAC_ENERGY_SCAN_RESULT));
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003375 SuccessOrExit(error = mEncoder.WriteUint8(aResult->mChannel));
3376 SuccessOrExit(error = mEncoder.WriteInt8(aResult->mMaxRssi));
3377 SuccessOrExit(error = mEncoder.EndFrame());
Buke Po818998e2017-08-04 01:19:07 +08003378 }
3379 else
3380 {
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07003381 // We are finished with the scan, send an unsolicited
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003382 // scan state update.
3383 mChangedPropsSet.AddProperty(SPINEL_PROP_MAC_SCAN_STATE);
Abtin Keshavarziana1adaac2020-05-11 10:24:58 -07003384 mUpdateChangedPropsTask.Post();
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003385 }
Buke Po818998e2017-08-04 01:19:07 +08003386
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003387exit:
3388
3389 if (error != OT_ERROR_NONE)
3390 {
3391 mChangedPropsSet.AddLastStatus(SPINEL_STATUS_NOMEM);
Abtin Keshavarziana1adaac2020-05-11 10:24:58 -07003392 mUpdateChangedPropsTask.Post();
Buke Po818998e2017-08-04 01:19:07 +08003393 }
3394}
3395
Jonathan Hui31ffd162019-07-16 12:01:36 -07003396#if OPENTHREAD_CONFIG_JOINER_ENABLE
rongli90ee0a42018-08-09 02:18:53 +08003397void NcpBase::HandleJoinerCallback_Jump(otError aError, void *aContext)
3398{
3399 static_cast<NcpBase *>(aContext)->HandleJoinerCallback(aError);
3400}
3401
3402void NcpBase::HandleJoinerCallback(otError aError)
3403{
3404 switch (aError)
3405 {
3406 case OT_ERROR_NONE:
3407 mChangedPropsSet.AddLastStatus(SPINEL_STATUS_JOIN_SUCCESS);
3408 break;
3409 case OT_ERROR_SECURITY:
3410 mChangedPropsSet.AddLastStatus(SPINEL_STATUS_JOIN_SECURITY);
3411 break;
3412 case OT_ERROR_NOT_FOUND:
3413 mChangedPropsSet.AddLastStatus(SPINEL_STATUS_JOIN_NO_PEERS);
3414 break;
3415 case OT_ERROR_RESPONSE_TIMEOUT:
3416 mChangedPropsSet.AddLastStatus(SPINEL_STATUS_JOIN_RSP_TIMEOUT);
3417 break;
3418 default:
3419 mChangedPropsSet.AddLastStatus(SPINEL_STATUS_JOIN_FAILURE);
3420 break;
3421 }
3422
Abtin Keshavarziana1adaac2020-05-11 10:24:58 -07003423 mUpdateChangedPropsTask.Post();
rongli90ee0a42018-08-09 02:18:53 +08003424}
3425#endif
3426
Buke Po818998e2017-08-04 01:19:07 +08003427// ----------------------------------------------------------------------------
3428// MARK: Outbound Datagram Handling
3429// ----------------------------------------------------------------------------
3430
3431void NcpBase::HandleDatagramFromStack(otMessage *aMessage, void *aContext)
3432{
3433 static_cast<NcpBase *>(aContext)->HandleDatagramFromStack(aMessage);
3434}
3435
3436void NcpBase::HandleDatagramFromStack(otMessage *aMessage)
3437{
Jonathan Hui1326d642020-06-17 22:44:54 -07003438 VerifyOrExit(aMessage != nullptr, OT_NOOP);
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07003439
Duda, Lukasz9aa73402020-05-08 22:46:00 +02003440 // Do not forward frames larger than SPINEL payload size.
3441 VerifyOrExit(otMessageGetLength(aMessage) <= SPINEL_FRAME_MAX_COMMAND_PAYLOAD_SIZE, otMessageFree(aMessage));
3442
Jonathan Hui75407582020-05-08 20:43:40 -07003443 otMessageQueueEnqueue(&mMessageQueue, aMessage);
Abtin Keshavarzian9ce57b22017-12-05 18:33:53 -08003444
3445 // If there is no queued spinel command response, try to write/send
3446 // the datagram message immediately. If there is a queued response
3447 // or if currently out of buffer space, the IPv6 datagram message
3448 // will be sent from `HandleFrameRemovedFromNcpBuffer()` when buffer
3449 // space becomes available and after any pending spinel command
3450 // response.
3451
3452 if (IsResponseQueueEmpty())
3453 {
kangping49f36f82020-05-07 02:17:58 +08003454 IgnoreError(SendQueuedDatagramMessages());
Abtin Keshavarzian9ce57b22017-12-05 18:33:53 -08003455 }
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07003456
3457exit:
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07003458 return;
3459}
3460
3461otError NcpBase::SendDatagramMessage(otMessage *aMessage)
3462{
Yakun Xub8333732018-06-21 04:15:13 +08003463 otError error = OT_ERROR_NONE;
3464 uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0;
3465 bool isSecure = otMessageIsLinkSecurityEnabled(aMessage);
3466 spinel_prop_key_t propKey = isSecure ? SPINEL_PROP_STREAM_NET : SPINEL_PROP_STREAM_NET_INSECURE;
Buke Po818998e2017-08-04 01:19:07 +08003467
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07003468 SuccessOrExit(error = mEncoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_IS, propKey));
3469 SuccessOrExit(error = mEncoder.WriteUint16(otMessageGetLength(aMessage)));
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003470 SuccessOrExit(error = mEncoder.WriteMessage(aMessage));
Buke Po818998e2017-08-04 01:19:07 +08003471
Buke Po818998e2017-08-04 01:19:07 +08003472 // Append any metadata (rssi, lqi, channel, etc) here!
3473
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003474 SuccessOrExit(error = mEncoder.EndFrame());
Buke Po818998e2017-08-04 01:19:07 +08003475
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07003476 if (isSecure)
Buke Po818998e2017-08-04 01:19:07 +08003477 {
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07003478 mOutboundSecureIpFrameCounter++;
Buke Po818998e2017-08-04 01:19:07 +08003479 }
3480 else
3481 {
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07003482 mOutboundInsecureIpFrameCounter++;
Buke Po818998e2017-08-04 01:19:07 +08003483 }
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07003484
3485exit:
3486 return error;
Buke Po818998e2017-08-04 01:19:07 +08003487}
3488
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07003489otError NcpBase::SendQueuedDatagramMessages(void)
3490{
Yakun Xub8333732018-06-21 04:15:13 +08003491 otError error = OT_ERROR_NONE;
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07003492 otMessage *message;
3493
Jonathan Hui1326d642020-06-17 22:44:54 -07003494 while ((message = otMessageQueueGetHead(&mMessageQueue)) != nullptr)
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07003495 {
3496 // Since an `otMessage` instance can be in one queue at a time,
3497 // it is first dequeued from `mMessageQueue` before attempting
3498 // to include it in a spinel frame by calling `SendDatagramMessage()`
3499 // If forming of the spinel frame fails, the message is enqueued
3500 // back at the front of `mMessageQueue`.
3501
Jonathan Huicf571102020-05-08 21:42:11 -07003502 otMessageQueueDequeue(&mMessageQueue, message);
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07003503
3504 error = SendDatagramMessage(message);
3505
3506 if (error != OT_ERROR_NONE)
3507 {
Jonathan Hui75407582020-05-08 20:43:40 -07003508 otMessageQueueEnqueueAtHead(&mMessageQueue, message);
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07003509 }
3510
3511 SuccessOrExit(error);
3512 }
3513
3514exit:
3515 return error;
3516}
Buke Po818998e2017-08-04 01:19:07 +08003517
Jonathan Hui02da2062019-07-16 12:18:34 -07003518#if OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
Yakun Xub9b57cc2018-11-06 12:48:08 +08003519template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_UDP_FORWARD_STREAM>(void)
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003520{
Jonathan Hui1326d642020-06-17 22:44:54 -07003521 const uint8_t * framePtr = nullptr;
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003522 uint16_t frameLen = 0;
3523 const otIp6Address *peerAddr;
3524 uint16_t peerPort;
3525 uint16_t sockPort;
3526 otMessage * message;
Zhanglong Xiaf8909592018-11-06 04:48:39 +08003527 otError error = OT_ERROR_NONE;
3528 otMessageSettings msgSettings = {false, OT_MESSAGE_PRIORITY_NORMAL};
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003529
Zhanglong Xiaf8909592018-11-06 04:48:39 +08003530 message = otIp6NewMessage(mInstance, &msgSettings);
Jonathan Hui1326d642020-06-17 22:44:54 -07003531 VerifyOrExit(message != nullptr, error = OT_ERROR_NO_BUFS);
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003532
3533 SuccessOrExit(error = mDecoder.ReadDataWithLen(framePtr, frameLen));
3534 SuccessOrExit(error = mDecoder.ReadUint16(peerPort));
3535 SuccessOrExit(error = mDecoder.ReadIp6Address(peerAddr));
3536 SuccessOrExit(error = mDecoder.ReadUint16(sockPort));
3537
3538 SuccessOrExit(error = otMessageAppend(message, framePtr, static_cast<uint16_t>(frameLen)));
3539
Yakun Xub9b57cc2018-11-06 12:48:08 +08003540 otUdpForwardReceive(mInstance, message, peerPort, peerAddr, sockPort);
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003541
Yakun Xub9b57cc2018-11-06 12:48:08 +08003542 // `otUdpForwardReceive()` takes ownership of `message` (in both success
Jonathan Hui1326d642020-06-17 22:44:54 -07003543 // or failure cases). `message` is set to nullptr so it is not freed at
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003544 // exit.
Jonathan Hui1326d642020-06-17 22:44:54 -07003545 message = nullptr;
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003546
3547exit:
Jonathan Hui1326d642020-06-17 22:44:54 -07003548 if (message != nullptr)
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003549 {
3550 otMessageFree(message);
3551 }
3552
3553 return error;
3554}
3555
Yakun Xub9b57cc2018-11-06 12:48:08 +08003556void NcpBase::HandleUdpForwardStream(otMessage * aMessage,
3557 uint16_t aPeerPort,
3558 otIp6Address *aPeerAddr,
3559 uint16_t aSockPort,
3560 void * aContext)
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003561{
Yakun Xub9b57cc2018-11-06 12:48:08 +08003562 static_cast<NcpBase *>(aContext)->HandleUdpForwardStream(aMessage, aPeerPort, *aPeerAddr, aSockPort);
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003563}
3564
Yakun Xub9b57cc2018-11-06 12:48:08 +08003565void NcpBase::HandleUdpForwardStream(otMessage *aMessage, uint16_t aPeerPort, otIp6Address &aPeerAddr, uint16_t aPort)
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003566{
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003567 uint16_t length = otMessageGetLength(aMessage);
3568 uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0;
3569
Yakun Xub9b57cc2018-11-06 12:48:08 +08003570 SuccessOrExit(mEncoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_THREAD_UDP_FORWARD_STREAM));
Kamil Srokad7f8a5b2018-07-13 18:35:47 +02003571 SuccessOrExit(mEncoder.WriteUint16(length));
3572 SuccessOrExit(mEncoder.WriteMessage(aMessage));
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003573
Kamil Srokad7f8a5b2018-07-13 18:35:47 +02003574 SuccessOrExit(mEncoder.WriteUint16(aPeerPort));
3575 SuccessOrExit(mEncoder.WriteIp6Address(aPeerAddr));
3576 SuccessOrExit(mEncoder.WriteUint16(aPort));
3577 SuccessOrExit(mEncoder.EndFrame());
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003578
3579 // The `aMessage` is owned by the outbound frame and NCP buffer
3580 // after frame was finished/ended successfully. It will be freed
3581 // when the frame is successfully sent and removed.
3582
Jonathan Hui1326d642020-06-17 22:44:54 -07003583 aMessage = nullptr;
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003584
3585exit:
3586
Jonathan Hui1326d642020-06-17 22:44:54 -07003587 if (aMessage != nullptr)
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003588 {
3589 otMessageFree(aMessage);
3590 }
3591}
Jonathan Hui02da2062019-07-16 12:18:34 -07003592#endif // OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003593
Buke Po818998e2017-08-04 01:19:07 +08003594// ----------------------------------------------------------------------------
Abtin Keshavarzian765c45c2018-11-09 08:59:20 -08003595// MARK: Pcap frame handling
3596// ----------------------------------------------------------------------------
3597
Yakun Xu504331e2019-01-29 04:31:15 +08003598void NcpBase::HandlePcapFrame(const otRadioFrame *aFrame, bool aIsTx, void *aContext)
Abtin Keshavarzian765c45c2018-11-09 08:59:20 -08003599{
Yakun Xu504331e2019-01-29 04:31:15 +08003600 static_cast<NcpBase *>(aContext)->HandlePcapFrame(aFrame, aIsTx);
Abtin Keshavarzian765c45c2018-11-09 08:59:20 -08003601}
3602
Yakun Xu504331e2019-01-29 04:31:15 +08003603void NcpBase::HandlePcapFrame(const otRadioFrame *aFrame, bool aIsTx)
Abtin Keshavarzian765c45c2018-11-09 08:59:20 -08003604{
3605 uint16_t flags = 0;
3606 uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0;
3607
Jonathan Huia4592232020-04-08 15:22:25 -07003608 VerifyOrExit(mPcapEnabled, OT_NOOP);
Abtin Keshavarzian765c45c2018-11-09 08:59:20 -08003609
Yakun Xu504331e2019-01-29 04:31:15 +08003610 if (aIsTx)
Abtin Keshavarzian765c45c2018-11-09 08:59:20 -08003611 {
3612 flags |= SPINEL_MD_FLAG_TX;
3613 }
3614
3615 SuccessOrExit(mEncoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_STREAM_RAW));
3616 SuccessOrExit(mEncoder.WriteUint16(aFrame->mLength));
3617
3618 SuccessOrExit(mEncoder.WriteData(aFrame->mPsdu, aFrame->mLength));
3619
3620 // Append metadata (rssi, etc)
3621 SuccessOrExit(mEncoder.WriteInt8(aFrame->mInfo.mRxInfo.mRssi)); // RSSI
3622 SuccessOrExit(mEncoder.WriteInt8(-128)); // Noise floor (Currently unused)
3623 SuccessOrExit(mEncoder.WriteUint16(flags)); // Flags
3624
3625 SuccessOrExit(mEncoder.OpenStruct()); // PHY-data
3626 // Empty for now
3627 SuccessOrExit(mEncoder.CloseStruct());
3628
3629 SuccessOrExit(mEncoder.OpenStruct()); // Vendor-data
3630 // Empty for now
3631 SuccessOrExit(mEncoder.CloseStruct());
3632
3633 SuccessOrExit(mEncoder.EndFrame());
3634
3635exit:
3636 return;
3637}
3638
3639template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_PCAP_ENABLED>(void)
3640{
3641 return mEncoder.WriteBool(mPcapEnabled);
3642}
3643
3644template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_PHY_PCAP_ENABLED>(void)
3645{
3646 otError error = OT_ERROR_NONE;
3647 bool enabled;
3648
3649 SuccessOrExit(error = mDecoder.ReadBool(enabled));
Jonathan Huia4592232020-04-08 15:22:25 -07003650 VerifyOrExit(enabled != mPcapEnabled, OT_NOOP);
Abtin Keshavarzian765c45c2018-11-09 08:59:20 -08003651
3652 mPcapEnabled = enabled;
3653
3654 if (mPcapEnabled)
3655 {
3656 otLinkSetPcapCallback(mInstance, &NcpBase::HandlePcapFrame, static_cast<void *>(this));
3657 }
3658 else
3659 {
Jonathan Hui1326d642020-06-17 22:44:54 -07003660 otLinkSetPcapCallback(mInstance, nullptr, nullptr);
Abtin Keshavarzian765c45c2018-11-09 08:59:20 -08003661 }
3662
3663exit:
3664 return error;
3665}
3666
3667// ----------------------------------------------------------------------------
Buke Po818998e2017-08-04 01:19:07 +08003668// MARK: Property/Status Changed
3669// ----------------------------------------------------------------------------
3670
Abtin Keshavarzian9ce38e02018-06-22 15:09:18 -07003671void NcpBase::HandleStateChanged(otChangedFlags aFlags, void *aContext)
Buke Po818998e2017-08-04 01:19:07 +08003672{
3673 NcpBase *ncp = static_cast<NcpBase *>(aContext);
3674
3675 ncp->mThreadChangedFlags |= aFlags;
Abtin Keshavarziana1adaac2020-05-11 10:24:58 -07003676 ncp->mUpdateChangedPropsTask.Post();
Buke Po818998e2017-08-04 01:19:07 +08003677}
3678
3679void NcpBase::ProcessThreadChangedFlags(void)
3680{
3681 static const struct
3682 {
Abtin Keshavarzian9ce38e02018-06-22 15:09:18 -07003683 otChangedFlags mThreadFlag;
Buke Po818998e2017-08-04 01:19:07 +08003684 spinel_prop_key_t mPropKey;
Yakun Xub8333732018-06-21 04:15:13 +08003685 } kFlags[] = {
3686 {OT_CHANGED_IP6_ADDRESS_ADDED, SPINEL_PROP_IPV6_ADDRESS_TABLE},
3687 {OT_CHANGED_IP6_ADDRESS_REMOVED, SPINEL_PROP_IPV6_ADDRESS_TABLE},
3688 {OT_CHANGED_THREAD_ROLE, SPINEL_PROP_NET_ROLE},
3689 {OT_CHANGED_THREAD_LL_ADDR, SPINEL_PROP_IPV6_LL_ADDR},
3690 {OT_CHANGED_THREAD_ML_ADDR, SPINEL_PROP_IPV6_ML_ADDR},
3691 {OT_CHANGED_THREAD_PARTITION_ID, SPINEL_PROP_NET_PARTITION_ID},
3692 {OT_CHANGED_THREAD_KEY_SEQUENCE_COUNTER, SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER},
3693 {OT_CHANGED_THREAD_NETDATA, SPINEL_PROP_THREAD_LEADER_NETWORK_DATA},
3694 {OT_CHANGED_THREAD_CHILD_ADDED, SPINEL_PROP_THREAD_CHILD_TABLE},
3695 {OT_CHANGED_THREAD_CHILD_REMOVED, SPINEL_PROP_THREAD_CHILD_TABLE},
Jonathan Hui98fb9df2019-10-09 15:01:32 -07003696 {OT_CHANGED_IP6_MULTICAST_SUBSCRIBED, SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE},
3697 {OT_CHANGED_IP6_MULTICAST_UNSUBSCRIBED, SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE},
Yakun Xub8333732018-06-21 04:15:13 +08003698 {OT_CHANGED_THREAD_CHANNEL, SPINEL_PROP_PHY_CHAN},
3699 {OT_CHANGED_THREAD_PANID, SPINEL_PROP_MAC_15_4_PANID},
3700 {OT_CHANGED_THREAD_NETWORK_NAME, SPINEL_PROP_NET_NETWORK_NAME},
3701 {OT_CHANGED_THREAD_EXT_PANID, SPINEL_PROP_NET_XPANID},
Simon Linb5b97ae2020-03-10 23:55:25 +08003702 {OT_CHANGED_THREAD_RLOC_ADDED, SPINEL_PROP_IPV6_ADDRESS_TABLE},
3703 {OT_CHANGED_THREAD_RLOC_REMOVED, SPINEL_PROP_IPV6_ADDRESS_TABLE},
Yakun Xub8333732018-06-21 04:15:13 +08003704 {OT_CHANGED_MASTER_KEY, SPINEL_PROP_NET_MASTER_KEY},
3705 {OT_CHANGED_PSKC, SPINEL_PROP_NET_PSKC},
3706 {OT_CHANGED_CHANNEL_MANAGER_NEW_CHANNEL, SPINEL_PROP_CHANNEL_MANAGER_NEW_CHANNEL},
Abtin Keshavarzian31698ec2018-07-02 08:43:45 -07003707 {OT_CHANGED_SUPPORTED_CHANNEL_MASK, SPINEL_PROP_PHY_CHAN_SUPPORTED},
Buke Po818998e2017-08-04 01:19:07 +08003708 };
3709
Jonathan Huia4592232020-04-08 15:22:25 -07003710 VerifyOrExit(mThreadChangedFlags != 0, OT_NOOP);
Buke Po818998e2017-08-04 01:19:07 +08003711
3712 // If thread role has changed, check for possible "join" error.
3713
3714 if ((mThreadChangedFlags & OT_CHANGED_THREAD_ROLE) != 0)
3715 {
3716 if (mRequireJoinExistingNetwork)
3717 {
3718 switch (otThreadGetDeviceRole(mInstance))
3719 {
3720 case OT_DEVICE_ROLE_DETACHED:
3721 case OT_DEVICE_ROLE_DISABLED:
3722 break;
3723
3724 default:
3725 mRequireJoinExistingNetwork = false;
3726 mChangedPropsSet.AddProperty(SPINEL_PROP_NET_REQUIRE_JOIN_EXISTING);
3727 break;
3728 }
3729
Yakun Xub8333732018-06-21 04:15:13 +08003730 if ((otThreadGetDeviceRole(mInstance) == OT_DEVICE_ROLE_LEADER) && otThreadIsSingleton(mInstance)
Jonathan Hui02da2062019-07-16 12:18:34 -07003731#if OPENTHREAD_CONFIG_LEGACY_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08003732 && !mLegacyNodeDidJoin
3733#endif
Yakun Xub8333732018-06-21 04:15:13 +08003734 )
Buke Po818998e2017-08-04 01:19:07 +08003735 {
3736 mThreadChangedFlags &= ~static_cast<uint32_t>(OT_CHANGED_THREAD_PARTITION_ID);
kangping49f36f82020-05-07 02:17:58 +08003737 IgnoreError(otThreadSetEnabled(mInstance, false));
Buke Po818998e2017-08-04 01:19:07 +08003738
3739 mChangedPropsSet.AddProperty(SPINEL_PROP_NET_STACK_UP);
3740 mChangedPropsSet.AddLastStatus(SPINEL_STATUS_JOIN_FAILURE);
3741 }
3742 }
3743 }
3744
3745 // Convert OT_CHANGED flags to corresponding NCP property update.
3746
Simon Lin5e9b2812020-07-22 00:41:40 +08003747 for (auto flag : kFlags)
Buke Po818998e2017-08-04 01:19:07 +08003748 {
Simon Lin5e9b2812020-07-22 00:41:40 +08003749 uint32_t threadFlag = flag.mThreadFlag;
Buke Po818998e2017-08-04 01:19:07 +08003750
3751 if (mThreadChangedFlags & threadFlag)
3752 {
Simon Lin5e9b2812020-07-22 00:41:40 +08003753 spinel_prop_key_t propKey = flag.mPropKey;
Yakun Xub8333732018-06-21 04:15:13 +08003754 bool shouldAddProperty = true;
Abtin Keshavarzian73922002017-10-31 14:15:04 -07003755
3756 // Child table changes are reported using the `HandleChildAdded()` and
3757 // `HandleChildRemoved()` callbacks emitting spinel `VALUE_INSERTED` and
3758 // `VALUE_REMOVED` async spinel frames. If the spinel frames could not be
3759 // added (e.g., out of NCP buffer) from the above callbacks, the flag
3760 // `mShouldEmitChildTableUpdate` is set to `true` so that the entire
3761 // child table is emitted as an unsolicited `VALUE_IS` update.
3762
3763 if (propKey == SPINEL_PROP_THREAD_CHILD_TABLE)
3764 {
Yakun Xub8333732018-06-21 04:15:13 +08003765 shouldAddProperty = mShouldEmitChildTableUpdate;
Abtin Keshavarzian73922002017-10-31 14:15:04 -07003766 mShouldEmitChildTableUpdate = false;
3767 }
3768
3769 if (shouldAddProperty)
3770 {
3771 mChangedPropsSet.AddProperty(propKey);
3772 }
Buke Po818998e2017-08-04 01:19:07 +08003773
3774 if (threadFlag == OT_CHANGED_THREAD_NETDATA)
3775 {
3776 mChangedPropsSet.AddProperty(SPINEL_PROP_THREAD_ON_MESH_NETS);
3777 mChangedPropsSet.AddProperty(SPINEL_PROP_THREAD_OFF_MESH_ROUTES);
3778 }
3779
3780 mThreadChangedFlags &= ~threadFlag;
Jonathan Huia4592232020-04-08 15:22:25 -07003781 VerifyOrExit(mThreadChangedFlags != 0, OT_NOOP);
Buke Po818998e2017-08-04 01:19:07 +08003782 }
3783 }
3784
3785 // Clear any remaining ThreadFlag that has no matching
Simon Linb5b97ae2020-03-10 23:55:25 +08003786 // NCP property update (e.g., OT_CHANGED_SECURITY_POLICY)
Buke Po818998e2017-08-04 01:19:07 +08003787
3788 mThreadChangedFlags = 0;
3789
3790exit:
3791 return;
3792}
3793
Yakun Xub8333732018-06-21 04:15:13 +08003794} // namespace Ncp
3795} // namespace ot
Buke Po818998e2017-08-04 01:19:07 +08003796
3797// ----------------------------------------------------------------------------
3798// MARK: Legacy network APIs
3799// ----------------------------------------------------------------------------
3800
3801void otNcpRegisterLegacyHandlers(const otNcpLegacyHandlers *aHandlers)
3802{
Jonathan Hui02da2062019-07-16 12:18:34 -07003803#if OPENTHREAD_CONFIG_LEGACY_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08003804 ot::Ncp::NcpBase *ncp = ot::Ncp::NcpBase::GetNcpInstance();
3805
Jonathan Hui1326d642020-06-17 22:44:54 -07003806 if (ncp != nullptr)
Buke Po818998e2017-08-04 01:19:07 +08003807 {
3808 ncp->RegisterLegacyHandlers(aHandlers);
3809 }
3810
3811#else
3812 OT_UNUSED_VARIABLE(aHandlers);
3813#endif
3814}
3815
3816void otNcpHandleDidReceiveNewLegacyUlaPrefix(const uint8_t *aUlaPrefix)
3817{
Jonathan Hui02da2062019-07-16 12:18:34 -07003818#if OPENTHREAD_CONFIG_LEGACY_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08003819 ot::Ncp::NcpBase *ncp = ot::Ncp::NcpBase::GetNcpInstance();
3820
Jonathan Hui1326d642020-06-17 22:44:54 -07003821 if (ncp != nullptr)
Buke Po818998e2017-08-04 01:19:07 +08003822 {
3823 ncp->HandleDidReceiveNewLegacyUlaPrefix(aUlaPrefix);
3824 }
3825
3826#else
3827 OT_UNUSED_VARIABLE(aUlaPrefix);
3828#endif
3829}
3830
3831void otNcpHandleLegacyNodeDidJoin(const otExtAddress *aExtAddr)
3832{
Jonathan Hui02da2062019-07-16 12:18:34 -07003833#if OPENTHREAD_CONFIG_LEGACY_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08003834 ot::Ncp::NcpBase *ncp = ot::Ncp::NcpBase::GetNcpInstance();
3835
Jonathan Hui1326d642020-06-17 22:44:54 -07003836 if (ncp != nullptr)
Buke Po818998e2017-08-04 01:19:07 +08003837 {
3838 ncp->HandleLegacyNodeDidJoin(aExtAddr);
3839 }
3840
3841#else
3842 OT_UNUSED_VARIABLE(aExtAddr);
3843#endif
3844}
3845
3846#endif // OPENTHREAD_MTD || OPENTHREAD_FTD