blob: 51980358cec0b783206ad48005c098c157e24799 [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
Jonathan Huidc9b0322020-09-29 15:30:37 -0700138uint8_t NcpBase::LinkFlagsToFlagByte(bool aRxOnWhenIdle, bool aDeviceType, bool aNetworkData)
Buke Po818998e2017-08-04 01:19:07 +0800139{
140 uint8_t flags(0);
141
142 if (aRxOnWhenIdle)
143 {
144 flags |= SPINEL_THREAD_MODE_RX_ON_WHEN_IDLE;
145 }
146
Buke Po818998e2017-08-04 01:19:07 +0800147 if (aDeviceType)
148 {
Jonathan Hui5a489832018-09-27 09:33:03 -0700149 flags |= SPINEL_THREAD_MODE_FULL_THREAD_DEV;
Buke Po818998e2017-08-04 01:19:07 +0800150 }
151
152 if (aNetworkData)
153 {
154 flags |= SPINEL_THREAD_MODE_FULL_NETWORK_DATA;
155 }
156
157 return flags;
158}
159
Abtin Keshavarziana1b2d352019-05-19 00:05:21 -0700160otError NcpBase::EncodeNeighborInfo(const otNeighborInfo &aNeighborInfo)
161{
162 otError error;
163 uint8_t modeFlags;
164
Jonathan Huidc9b0322020-09-29 15:30:37 -0700165 modeFlags = LinkFlagsToFlagByte(aNeighborInfo.mRxOnWhenIdle, aNeighborInfo.mFullThreadDevice,
166 aNeighborInfo.mFullNetworkData);
Abtin Keshavarziana1b2d352019-05-19 00:05:21 -0700167
168 SuccessOrExit(error = mEncoder.OpenStruct());
169
170 SuccessOrExit(error = mEncoder.WriteEui64(aNeighborInfo.mExtAddress));
171 SuccessOrExit(error = mEncoder.WriteUint16(aNeighborInfo.mRloc16));
172 SuccessOrExit(error = mEncoder.WriteUint32(aNeighborInfo.mAge));
173 SuccessOrExit(error = mEncoder.WriteUint8(aNeighborInfo.mLinkQualityIn));
174 SuccessOrExit(error = mEncoder.WriteInt8(aNeighborInfo.mAverageRssi));
175 SuccessOrExit(error = mEncoder.WriteUint8(modeFlags));
176 SuccessOrExit(error = mEncoder.WriteBool(aNeighborInfo.mIsChild));
177 SuccessOrExit(error = mEncoder.WriteUint32(aNeighborInfo.mLinkFrameCounter));
178 SuccessOrExit(error = mEncoder.WriteUint32(aNeighborInfo.mMleFrameCounter));
179 SuccessOrExit(error = mEncoder.WriteInt8(aNeighborInfo.mLastRssi));
180
181 SuccessOrExit(error = mEncoder.CloseStruct());
182
183exit:
184 return error;
185}
186
Yakun Xu8ccf1382018-06-29 00:26:31 +0800187template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_DATA_POLL_PERIOD>(void)
Buke Po818998e2017-08-04 01:19:07 +0800188{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700189 return mEncoder.WriteUint32(otLinkGetPollPeriod(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800190}
191
Yakun Xu8ccf1382018-06-29 00:26:31 +0800192template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_DATA_POLL_PERIOD>(void)
Buke Po818998e2017-08-04 01:19:07 +0800193{
194 uint32_t pollPeriod;
Yakun Xub8333732018-06-21 04:15:13 +0800195 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800196
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700197 SuccessOrExit(error = mDecoder.ReadUint32(pollPeriod));
Buke Po818998e2017-08-04 01:19:07 +0800198
rongli32823982018-12-28 14:35:57 +0800199 error = otLinkSetPollPeriod(mInstance, pollPeriod);
Buke Po818998e2017-08-04 01:19:07 +0800200
201exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700202 return error;
Buke Po818998e2017-08-04 01:19:07 +0800203}
204
Yakun Xu8ccf1382018-06-29 00:26:31 +0800205template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_EXTENDED_ADDR>(void)
Buke Po818998e2017-08-04 01:19:07 +0800206{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700207 return mEncoder.WriteEui64(*otLinkGetExtendedAddress(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800208}
209
Rafał Kuźnia5a7e1902019-10-29 17:04:26 +0100210template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_MAX_RETRY_NUMBER_DIRECT>(void)
211{
212 return mEncoder.WriteUint8(otLinkGetMaxFrameRetriesDirect(mInstance));
213}
214
215template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_MAX_RETRY_NUMBER_DIRECT>(void)
216{
217 uint8_t maxFrameRetriesDirect;
218 otError error = OT_ERROR_NONE;
219
220 SuccessOrExit(error = mDecoder.ReadUint8(maxFrameRetriesDirect));
221 otLinkSetMaxFrameRetriesDirect(mInstance, maxFrameRetriesDirect);
222
223exit:
224 return error;
225}
226
Abtin Keshavarzian31698ec2018-07-02 08:43:45 -0700227template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_PHY_CHAN_SUPPORTED>(void)
228{
229 uint32_t newMask = 0;
230 otError error = OT_ERROR_NONE;
231
232 SuccessOrExit(error = DecodeChannelMask(newMask));
233 error = otLinkSetSupportedChannelMask(mInstance, newMask);
234
235exit:
236 return error;
Buke Po818998e2017-08-04 01:19:07 +0800237}
238
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700239otError NcpBase::CommandHandler_NET_CLEAR(uint8_t aHeader)
Buke Po818998e2017-08-04 01:19:07 +0800240{
Abtin Keshavarzian9ce57b22017-12-05 18:33:53 -0800241 return PrepareLastStatusResponse(aHeader, ThreadErrorToSpinelStatus(otInstanceErasePersistentInfo(mInstance)));
Buke Po818998e2017-08-04 01:19:07 +0800242}
243
Yakun Xu8ccf1382018-06-29 00:26:31 +0800244template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NET_SAVED>(void)
Buke Po818998e2017-08-04 01:19:07 +0800245{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700246 return mEncoder.WriteBool(otDatasetIsCommissioned(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800247}
248
Yakun Xu8ccf1382018-06-29 00:26:31 +0800249template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NET_IF_UP>(void)
Buke Po818998e2017-08-04 01:19:07 +0800250{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700251 return mEncoder.WriteBool(otIp6IsEnabled(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800252}
253
Yakun Xu8ccf1382018-06-29 00:26:31 +0800254template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_NET_IF_UP>(void)
Buke Po818998e2017-08-04 01:19:07 +0800255{
Yakun Xub8333732018-06-21 04:15:13 +0800256 bool enabled = false;
257 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800258
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700259 SuccessOrExit(error = mDecoder.ReadBool(enabled));
Buke Po818998e2017-08-04 01:19:07 +0800260
261 error = otIp6SetEnabled(mInstance, enabled);
262
263exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700264 return error;
Buke Po818998e2017-08-04 01:19:07 +0800265}
266
Yakun Xu8ccf1382018-06-29 00:26:31 +0800267template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NET_STACK_UP>(void)
Buke Po818998e2017-08-04 01:19:07 +0800268{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700269 return mEncoder.WriteBool(otThreadGetDeviceRole(mInstance) != OT_DEVICE_ROLE_DISABLED);
Buke Po818998e2017-08-04 01:19:07 +0800270}
271
Yakun Xu8ccf1382018-06-29 00:26:31 +0800272template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_NET_STACK_UP>(void)
Buke Po818998e2017-08-04 01:19:07 +0800273{
Yakun Xub8333732018-06-21 04:15:13 +0800274 bool enabled = false;
275 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800276
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700277 SuccessOrExit(error = mDecoder.ReadBool(enabled));
Buke Po818998e2017-08-04 01:19:07 +0800278
279 // If the value has changed...
280 if ((enabled != false) != (otThreadGetDeviceRole(mInstance) != OT_DEVICE_ROLE_DISABLED))
281 {
282 if (enabled != false)
283 {
284 error = otThreadSetEnabled(mInstance, true);
Abtin Keshavarzianecd28452018-04-05 10:20:47 -0700285 StartLegacy();
Buke Po818998e2017-08-04 01:19:07 +0800286 }
287 else
288 {
289 error = otThreadSetEnabled(mInstance, false);
Abtin Keshavarzianecd28452018-04-05 10:20:47 -0700290 StopLegacy();
Buke Po818998e2017-08-04 01:19:07 +0800291 }
292 }
293
294exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700295 return error;
Buke Po818998e2017-08-04 01:19:07 +0800296}
297
Yakun Xu8ccf1382018-06-29 00:26:31 +0800298template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NET_ROLE>(void)
Buke Po818998e2017-08-04 01:19:07 +0800299{
300 spinel_net_role_t role(SPINEL_NET_ROLE_DETACHED);
301
302 switch (otThreadGetDeviceRole(mInstance))
303 {
304 case OT_DEVICE_ROLE_DISABLED:
305 case OT_DEVICE_ROLE_DETACHED:
306 role = SPINEL_NET_ROLE_DETACHED;
307 break;
308
309 case OT_DEVICE_ROLE_CHILD:
310 role = SPINEL_NET_ROLE_CHILD;
311 break;
312
313 case OT_DEVICE_ROLE_ROUTER:
314 role = SPINEL_NET_ROLE_ROUTER;
315 break;
316
317 case OT_DEVICE_ROLE_LEADER:
318 role = SPINEL_NET_ROLE_LEADER;
319 break;
320 }
321
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700322 return mEncoder.WriteUint8(role);
Buke Po818998e2017-08-04 01:19:07 +0800323}
324
Yakun Xu8ccf1382018-06-29 00:26:31 +0800325template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_NET_ROLE>(void)
Buke Po818998e2017-08-04 01:19:07 +0800326{
Yakun Xub8333732018-06-21 04:15:13 +0800327 unsigned int role = 0;
328 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800329
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700330 SuccessOrExit(error = mDecoder.ReadUintPacked(role));
Buke Po818998e2017-08-04 01:19:07 +0800331
332 switch (role)
333 {
334 case SPINEL_NET_ROLE_DETACHED:
335 error = otThreadBecomeDetached(mInstance);
336 break;
337
338#if OPENTHREAD_FTD
339 case SPINEL_NET_ROLE_ROUTER:
340 error = otThreadBecomeRouter(mInstance);
341 break;
342
343 case SPINEL_NET_ROLE_LEADER:
344 error = otThreadBecomeLeader(mInstance);
345 break;
Yakun Xub8333732018-06-21 04:15:13 +0800346#endif // OPENTHREAD_FTD
Buke Po818998e2017-08-04 01:19:07 +0800347
348 case SPINEL_NET_ROLE_CHILD:
349 error = otThreadBecomeChild(mInstance);
350 break;
351 }
352
353exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700354 return error;
Buke Po818998e2017-08-04 01:19:07 +0800355}
356
Yakun Xu8ccf1382018-06-29 00:26:31 +0800357template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NET_NETWORK_NAME>(void)
Buke Po818998e2017-08-04 01:19:07 +0800358{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700359 return mEncoder.WriteUtf8(otThreadGetNetworkName(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800360}
361
Yakun Xu8ccf1382018-06-29 00:26:31 +0800362template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_NET_NETWORK_NAME>(void)
Buke Po818998e2017-08-04 01:19:07 +0800363{
Jonathan Hui1326d642020-06-17 22:44:54 -0700364 const char *string = nullptr;
Yakun Xub8333732018-06-21 04:15:13 +0800365 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800366
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700367 SuccessOrExit(mDecoder.ReadUtf8(string));
Buke Po818998e2017-08-04 01:19:07 +0800368
369 error = otThreadSetNetworkName(mInstance, string);
370
371exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700372 return error;
Buke Po818998e2017-08-04 01:19:07 +0800373}
374
Yakun Xu8ccf1382018-06-29 00:26:31 +0800375template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NET_XPANID>(void)
Buke Po818998e2017-08-04 01:19:07 +0800376{
Jonathan Hui92019732018-08-15 10:12:49 -0700377 return mEncoder.WriteData(otThreadGetExtendedPanId(mInstance)->m8, sizeof(spinel_net_xpanid_t));
Buke Po818998e2017-08-04 01:19:07 +0800378}
379
Yakun Xu8ccf1382018-06-29 00:26:31 +0800380template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_NET_XPANID>(void)
Buke Po818998e2017-08-04 01:19:07 +0800381{
Jonathan Hui1326d642020-06-17 22:44:54 -0700382 const uint8_t *ptr = nullptr;
Yakun Xub8333732018-06-21 04:15:13 +0800383 uint16_t len;
384 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800385
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700386 SuccessOrExit(error = mDecoder.ReadData(ptr, len));
Buke Po818998e2017-08-04 01:19:07 +0800387
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700388 VerifyOrExit(len == sizeof(spinel_net_xpanid_t), error = OT_ERROR_PARSE);
Buke Po818998e2017-08-04 01:19:07 +0800389
Jonathan Hui92019732018-08-15 10:12:49 -0700390 error = otThreadSetExtendedPanId(mInstance, reinterpret_cast<const otExtendedPanId *>(ptr));
Buke Po818998e2017-08-04 01:19:07 +0800391
392exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700393 return error;
Buke Po818998e2017-08-04 01:19:07 +0800394}
395
Yakun Xu8ccf1382018-06-29 00:26:31 +0800396template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NET_MASTER_KEY>(void)
Buke Po818998e2017-08-04 01:19:07 +0800397{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700398 return mEncoder.WriteData(otThreadGetMasterKey(mInstance)->m8, OT_MASTER_KEY_SIZE);
Buke Po818998e2017-08-04 01:19:07 +0800399}
400
Yakun Xu8ccf1382018-06-29 00:26:31 +0800401template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_NET_MASTER_KEY>(void)
Buke Po818998e2017-08-04 01:19:07 +0800402{
Jonathan Hui1326d642020-06-17 22:44:54 -0700403 const uint8_t *ptr = nullptr;
Yakun Xub8333732018-06-21 04:15:13 +0800404 uint16_t len;
405 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800406
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700407 SuccessOrExit(error = mDecoder.ReadData(ptr, len));
Buke Po818998e2017-08-04 01:19:07 +0800408
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700409 VerifyOrExit(len == OT_MASTER_KEY_SIZE, error = OT_ERROR_PARSE);
Buke Po818998e2017-08-04 01:19:07 +0800410
411 error = otThreadSetMasterKey(mInstance, reinterpret_cast<const otMasterKey *>(ptr));
412
413exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700414 return error;
Buke Po818998e2017-08-04 01:19:07 +0800415}
416
Yakun Xu8ccf1382018-06-29 00:26:31 +0800417template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER>(void)
Buke Po818998e2017-08-04 01:19:07 +0800418{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700419 return mEncoder.WriteUint32(otThreadGetKeySequenceCounter(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800420}
421
Yakun Xu8ccf1382018-06-29 00:26:31 +0800422template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER>(void)
Buke Po818998e2017-08-04 01:19:07 +0800423{
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700424 uint32_t keySeqCounter;
Yakun Xub8333732018-06-21 04:15:13 +0800425 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800426
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700427 SuccessOrExit(error = mDecoder.ReadUint32(keySeqCounter));
Buke Po818998e2017-08-04 01:19:07 +0800428
429 otThreadSetKeySequenceCounter(mInstance, keySeqCounter);
430
431exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700432 return error;
Buke Po818998e2017-08-04 01:19:07 +0800433}
434
Yakun Xu8ccf1382018-06-29 00:26:31 +0800435template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NET_PARTITION_ID>(void)
Buke Po818998e2017-08-04 01:19:07 +0800436{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700437 return mEncoder.WriteUint32(otThreadGetPartitionId(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800438}
439
Yakun Xu8ccf1382018-06-29 00:26:31 +0800440template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NET_KEY_SWITCH_GUARDTIME>(void)
Buke Po818998e2017-08-04 01:19:07 +0800441{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700442 return mEncoder.WriteUint32(otThreadGetKeySwitchGuardTime(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800443}
444
Yakun Xu8ccf1382018-06-29 00:26:31 +0800445template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_NET_KEY_SWITCH_GUARDTIME>(void)
Buke Po818998e2017-08-04 01:19:07 +0800446{
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700447 uint32_t keyGuardTime;
Yakun Xub8333732018-06-21 04:15:13 +0800448 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800449
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700450 SuccessOrExit(error = mDecoder.ReadUint32(keyGuardTime));
Buke Po818998e2017-08-04 01:19:07 +0800451
452 otThreadSetKeySwitchGuardTime(mInstance, keyGuardTime);
453
454exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700455 return error;
Buke Po818998e2017-08-04 01:19:07 +0800456}
457
Yakun Xu8ccf1382018-06-29 00:26:31 +0800458template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_NETWORK_DATA_VERSION>(void)
Buke Po818998e2017-08-04 01:19:07 +0800459{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700460 return mEncoder.WriteUint8(otNetDataGetVersion(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800461}
462
Yakun Xu8ccf1382018-06-29 00:26:31 +0800463template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_STABLE_NETWORK_DATA_VERSION>(void)
Buke Po818998e2017-08-04 01:19:07 +0800464{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700465 return mEncoder.WriteUint8(otNetDataGetStableVersion(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800466}
467
Jonathan Huif1849732019-07-16 12:31:11 -0700468#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
Yakun Xu8ccf1382018-06-29 00:26:31 +0800469template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_NETWORK_DATA>(void)
Buke Po818998e2017-08-04 01:19:07 +0800470{
Buke Po818998e2017-08-04 01:19:07 +0800471 uint8_t networkData[255];
472 uint8_t networkDataLen = 255;
473
kangping49f36f82020-05-07 02:17:58 +0800474 IgnoreError(otBorderRouterGetNetData(mInstance,
475 false, // Stable?
476 networkData, &networkDataLen));
Buke Po818998e2017-08-04 01:19:07 +0800477
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700478 return mEncoder.WriteData(networkData, networkDataLen);
Buke Po818998e2017-08-04 01:19:07 +0800479}
480
Yakun Xu8ccf1382018-06-29 00:26:31 +0800481template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_STABLE_NETWORK_DATA>(void)
Buke Po818998e2017-08-04 01:19:07 +0800482{
Buke Po818998e2017-08-04 01:19:07 +0800483 uint8_t networkData[255];
484 uint8_t networkDataLen = 255;
485
kangping49f36f82020-05-07 02:17:58 +0800486 IgnoreError(otBorderRouterGetNetData(mInstance,
487 true, // Stable?
488 networkData, &networkDataLen));
Buke Po818998e2017-08-04 01:19:07 +0800489
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700490 return mEncoder.WriteData(networkData, networkDataLen);
Buke Po818998e2017-08-04 01:19:07 +0800491}
Jonathan Huif1849732019-07-16 12:31:11 -0700492#endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
Buke Po818998e2017-08-04 01:19:07 +0800493
Yakun Xu8ccf1382018-06-29 00:26:31 +0800494template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_LEADER_NETWORK_DATA>(void)
Buke Po818998e2017-08-04 01:19:07 +0800495{
Buke Po818998e2017-08-04 01:19:07 +0800496 uint8_t networkData[255];
497 uint8_t networkDataLen = 255;
498
kangping49f36f82020-05-07 02:17:58 +0800499 IgnoreError(otNetDataGet(mInstance,
500 false, // Stable?
501 networkData, &networkDataLen));
Buke Po818998e2017-08-04 01:19:07 +0800502
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700503 return mEncoder.WriteData(networkData, networkDataLen);
Buke Po818998e2017-08-04 01:19:07 +0800504}
505
Yakun Xu8ccf1382018-06-29 00:26:31 +0800506template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_STABLE_LEADER_NETWORK_DATA>(void)
Buke Po818998e2017-08-04 01:19:07 +0800507{
Buke Po818998e2017-08-04 01:19:07 +0800508 uint8_t networkData[255];
509 uint8_t networkDataLen = 255;
510
kangping49f36f82020-05-07 02:17:58 +0800511 IgnoreError(otNetDataGet(mInstance,
512 true, // Stable?
513 networkData, &networkDataLen));
Buke Po818998e2017-08-04 01:19:07 +0800514
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700515 return mEncoder.WriteData(networkData, networkDataLen);
Buke Po818998e2017-08-04 01:19:07 +0800516}
517
Yakun Xu8ccf1382018-06-29 00:26:31 +0800518template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_LEADER_RID>(void)
Buke Po818998e2017-08-04 01:19:07 +0800519{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700520 return mEncoder.WriteUint8(otThreadGetLeaderRouterId(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800521}
522
Yakun Xu8ccf1382018-06-29 00:26:31 +0800523template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_LEADER_ADDR>(void)
Buke Po818998e2017-08-04 01:19:07 +0800524{
Yakun Xub8333732018-06-21 04:15:13 +0800525 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800526 otIp6Address address;
527
528 error = otThreadGetLeaderRloc(mInstance, &address);
529
530 if (error == OT_ERROR_NONE)
531 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700532 error = mEncoder.WriteIp6Address(address);
Buke Po818998e2017-08-04 01:19:07 +0800533 }
534 else
535 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700536 error = mEncoder.OverwriteWithLastStatusError(ThreadErrorToSpinelStatus(error));
Buke Po818998e2017-08-04 01:19:07 +0800537 }
538
539 return error;
540}
541
Yakun Xu8ccf1382018-06-29 00:26:31 +0800542template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_PARENT>(void)
Buke Po818998e2017-08-04 01:19:07 +0800543{
544 otError error = OT_ERROR_NONE;
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700545
Buke Po818998e2017-08-04 01:19:07 +0800546 otRouterInfo parentInfo;
547
548 error = otThreadGetParentInfo(mInstance, &parentInfo);
549
550 if (error == OT_ERROR_NONE)
551 {
Abtin Keshavarzian52354e72018-07-04 13:40:40 -0700552 if (parentInfo.mLinkEstablished)
553 {
554 int8_t averageRssi;
555 int8_t lastRssi;
556
kangping49f36f82020-05-07 02:17:58 +0800557 IgnoreError(otThreadGetParentAverageRssi(mInstance, &averageRssi));
558 IgnoreError(otThreadGetParentLastRssi(mInstance, &lastRssi));
Abtin Keshavarzian52354e72018-07-04 13:40:40 -0700559
560 SuccessOrExit(error = mEncoder.WriteEui64(parentInfo.mExtAddress));
561 SuccessOrExit(error = mEncoder.WriteUint16(parentInfo.mRloc16));
562 SuccessOrExit(error = mEncoder.WriteUint32(parentInfo.mAge));
563 SuccessOrExit(error = mEncoder.WriteInt8(averageRssi));
564 SuccessOrExit(error = mEncoder.WriteInt8(lastRssi));
565 SuccessOrExit(error = mEncoder.WriteUint8(parentInfo.mLinkQualityIn));
566 SuccessOrExit(error = mEncoder.WriteUint8(parentInfo.mLinkQualityOut));
567 }
568 else
569 {
570 SuccessOrExit(error = mEncoder.OverwriteWithLastStatusError(SPINEL_STATUS_ITEM_NOT_FOUND));
571 }
Buke Po818998e2017-08-04 01:19:07 +0800572 }
573 else
574 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700575 error = mEncoder.OverwriteWithLastStatusError(ThreadErrorToSpinelStatus(error));
Buke Po818998e2017-08-04 01:19:07 +0800576 }
577
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700578exit:
Buke Po818998e2017-08-04 01:19:07 +0800579 return error;
580}
581
Yakun Xu8ccf1382018-06-29 00:26:31 +0800582template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_NEIGHBOR_TABLE>(void)
Buke Po818998e2017-08-04 01:19:07 +0800583{
Yakun Xub8333732018-06-21 04:15:13 +0800584 otError error = OT_ERROR_NONE;
585 otNeighborInfoIterator iter = OT_NEIGHBOR_INFO_ITERATOR_INIT;
586 otNeighborInfo neighInfo;
Buke Po818998e2017-08-04 01:19:07 +0800587
Buke Po818998e2017-08-04 01:19:07 +0800588 while (otThreadGetNextNeighborInfo(mInstance, &iter, &neighInfo) == OT_ERROR_NONE)
589 {
Abtin Keshavarziana1b2d352019-05-19 00:05:21 -0700590 SuccessOrExit(error = EncodeNeighborInfo(neighInfo));
Buke Po818998e2017-08-04 01:19:07 +0800591 }
592
Buke Po818998e2017-08-04 01:19:07 +0800593exit:
Buke Po818998e2017-08-04 01:19:07 +0800594 return error;
595}
596
Yakun Xu8ccf1382018-06-29 00:26:31 +0800597template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_NEIGHBOR_TABLE_ERROR_RATES>(void)
Abtin Keshavarzian10f6c4f2018-02-02 10:29:52 -0800598{
Yakun Xub8333732018-06-21 04:15:13 +0800599 otError error = OT_ERROR_NONE;
600 otNeighborInfoIterator iter = OT_NEIGHBOR_INFO_ITERATOR_INIT;
601 otNeighborInfo neighInfo;
Abtin Keshavarzian10f6c4f2018-02-02 10:29:52 -0800602
603 while (otThreadGetNextNeighborInfo(mInstance, &iter, &neighInfo) == OT_ERROR_NONE)
604 {
605 SuccessOrExit(error = mEncoder.OpenStruct());
606
607 SuccessOrExit(error = mEncoder.WriteEui64(neighInfo.mExtAddress));
608 SuccessOrExit(error = mEncoder.WriteUint16(neighInfo.mRloc16));
609 SuccessOrExit(error = mEncoder.WriteUint16(neighInfo.mFrameErrorRate));
610 SuccessOrExit(error = mEncoder.WriteUint16(neighInfo.mMessageErrorRate));
611 SuccessOrExit(error = mEncoder.WriteInt8(neighInfo.mAverageRssi));
612 SuccessOrExit(error = mEncoder.WriteInt8(neighInfo.mLastRssi));
613
614 SuccessOrExit(error = mEncoder.CloseStruct());
615 }
616
617exit:
618 return error;
619}
620
Yakun Xu8ccf1382018-06-29 00:26:31 +0800621template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_ASSISTING_PORTS>(void)
Buke Po818998e2017-08-04 01:19:07 +0800622{
Yakun Xub8333732018-06-21 04:15:13 +0800623 otError error = OT_ERROR_NONE;
624 uint8_t numEntries = 0;
625 const uint16_t *ports = otIp6GetUnsecurePorts(mInstance, &numEntries);
Buke Po818998e2017-08-04 01:19:07 +0800626
Buke Po818998e2017-08-04 01:19:07 +0800627 for (; numEntries != 0; ports++, numEntries--)
628 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700629 SuccessOrExit(error = mEncoder.WriteUint16(*ports));
Buke Po818998e2017-08-04 01:19:07 +0800630 }
631
Buke Po818998e2017-08-04 01:19:07 +0800632exit:
633 return error;
634}
635
Yakun Xu8ccf1382018-06-29 00:26:31 +0800636template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_ASSISTING_PORTS>(void)
Buke Po818998e2017-08-04 01:19:07 +0800637{
Zhanglong Xiac573daf2018-09-11 08:39:06 +0800638 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800639
640 // First, we need to remove all of the current assisting ports.
Zhanglong Xiac573daf2018-09-11 08:39:06 +0800641 otIp6RemoveAllUnsecurePorts(mInstance);
Buke Po818998e2017-08-04 01:19:07 +0800642
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700643 while (mDecoder.GetRemainingLengthInStruct() >= sizeof(uint16_t))
Buke Po818998e2017-08-04 01:19:07 +0800644 {
645 uint16_t port;
646
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700647 SuccessOrExit(mDecoder.ReadUint16(port));
Buke Po818998e2017-08-04 01:19:07 +0800648
649 SuccessOrExit(error = otIp6AddUnsecurePort(mInstance, port));
Buke Po818998e2017-08-04 01:19:07 +0800650 }
651
Buke Po818998e2017-08-04 01:19:07 +0800652exit:
Buke Po818998e2017-08-04 01:19:07 +0800653
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700654 if (error != OT_ERROR_NONE)
Buke Po818998e2017-08-04 01:19:07 +0800655 {
656 // We had an error, but we've actually changed
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700657 // the state of these ports, so we need to report
Buke Po818998e2017-08-04 01:19:07 +0800658 // those incomplete changes via an asynchronous
659 // change event.
kangping49f36f82020-05-07 02:17:58 +0800660 IgnoreError(
661 WritePropertyValueIsFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_PROP_THREAD_ASSISTING_PORTS));
Buke Po818998e2017-08-04 01:19:07 +0800662 }
663
664 return error;
665}
666
Yakun Xu8ccf1382018-06-29 00:26:31 +0800667template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE>(void)
Buke Po818998e2017-08-04 01:19:07 +0800668{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700669 return mEncoder.WriteBool(mAllowLocalNetworkDataChange);
Buke Po818998e2017-08-04 01:19:07 +0800670}
671
Jonathan Huif1849732019-07-16 12:31:11 -0700672#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
Yakun Xu8ccf1382018-06-29 00:26:31 +0800673template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE>(void)
Buke Po818998e2017-08-04 01:19:07 +0800674{
Yakun Xub8333732018-06-21 04:15:13 +0800675 bool value = false;
676 otError error = OT_ERROR_NONE;
677 bool shouldRegisterWithLeader = false;
Buke Po818998e2017-08-04 01:19:07 +0800678
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700679 SuccessOrExit(error = mDecoder.ReadBool(value));
Buke Po818998e2017-08-04 01:19:07 +0800680
681 // Register any net data changes on transition from `true` to `false`.
682 shouldRegisterWithLeader = (mAllowLocalNetworkDataChange == true) && (value == false);
683
684 mAllowLocalNetworkDataChange = value;
685
686exit:
Buke Po818998e2017-08-04 01:19:07 +0800687
688 if (shouldRegisterWithLeader)
689 {
kangping49f36f82020-05-07 02:17:58 +0800690 IgnoreError(otBorderRouterRegister(mInstance));
Buke Po818998e2017-08-04 01:19:07 +0800691 }
692
693 return error;
694}
Jonathan Huif1849732019-07-16 12:31:11 -0700695#endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
Buke Po818998e2017-08-04 01:19:07 +0800696
Yakun Xu8ccf1382018-06-29 00:26:31 +0800697template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_ON_MESH_NETS>(void)
Buke Po818998e2017-08-04 01:19:07 +0800698{
Yakun Xub8333732018-06-21 04:15:13 +0800699 otError error = OT_ERROR_NONE;
700 otBorderRouterConfig borderRouterConfig;
Abtin Keshavarzian2c8f50b2017-09-01 21:27:58 -0700701 otNetworkDataIterator iter = OT_NETWORK_DATA_ITERATOR_INIT;
Buke Po818998e2017-08-04 01:19:07 +0800702
703 // Fill from non-local network data first
Abtin Keshavarzian2c8f50b2017-09-01 21:27:58 -0700704 while (otNetDataGetNextOnMeshPrefix(mInstance, &iter, &borderRouterConfig) == OT_ERROR_NONE)
Buke Po818998e2017-08-04 01:19:07 +0800705 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700706 SuccessOrExit(error = mEncoder.OpenStruct());
Buke Po818998e2017-08-04 01:19:07 +0800707
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700708 SuccessOrExit(error = mEncoder.WriteIp6Address(borderRouterConfig.mPrefix.mPrefix));
709 SuccessOrExit(error = mEncoder.WriteUint8(borderRouterConfig.mPrefix.mLength));
710 SuccessOrExit(error = mEncoder.WriteBool(borderRouterConfig.mStable));
711 SuccessOrExit(error = mEncoder.WriteUint8(BorderRouterConfigToFlagByte(borderRouterConfig)));
Yakun Xub8333732018-06-21 04:15:13 +0800712 SuccessOrExit(error = mEncoder.WriteBool(false)); // isLocal
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700713 SuccessOrExit(error = mEncoder.WriteUint16(borderRouterConfig.mRloc16));
714
715 SuccessOrExit(error = mEncoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +0800716 }
717
Jonathan Huif1849732019-07-16 12:31:11 -0700718#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
Abtin Keshavarzian2c8f50b2017-09-01 21:27:58 -0700719
720 iter = OT_NETWORK_DATA_ITERATOR_INIT;
721
Buke Po818998e2017-08-04 01:19:07 +0800722 // Fill from local network data last
Abtin Keshavarzian2c8f50b2017-09-01 21:27:58 -0700723 while (otBorderRouterGetNextOnMeshPrefix(mInstance, &iter, &borderRouterConfig) == OT_ERROR_NONE)
Buke Po818998e2017-08-04 01:19:07 +0800724 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700725 SuccessOrExit(error = mEncoder.OpenStruct());
Buke Po818998e2017-08-04 01:19:07 +0800726
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700727 SuccessOrExit(error = mEncoder.WriteIp6Address(borderRouterConfig.mPrefix.mPrefix));
728 SuccessOrExit(error = mEncoder.WriteUint8(borderRouterConfig.mPrefix.mLength));
729 SuccessOrExit(error = mEncoder.WriteBool(borderRouterConfig.mStable));
730 SuccessOrExit(error = mEncoder.WriteUint8(BorderRouterConfigToFlagByte(borderRouterConfig)));
Yakun Xub8333732018-06-21 04:15:13 +0800731 SuccessOrExit(error = mEncoder.WriteBool(true)); // isLocal
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700732 SuccessOrExit(error = mEncoder.WriteUint16(borderRouterConfig.mRloc16));
733
734 SuccessOrExit(error = mEncoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +0800735 }
Jonathan Huif1849732019-07-16 12:31:11 -0700736#endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
Buke Po818998e2017-08-04 01:19:07 +0800737
Buke Po818998e2017-08-04 01:19:07 +0800738exit:
Buke Po818998e2017-08-04 01:19:07 +0800739 return error;
740}
741
Jonathan Huif1849732019-07-16 12:31:11 -0700742#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
Yakun Xu8ccf1382018-06-29 00:26:31 +0800743template <> otError NcpBase::HandlePropertyInsert<SPINEL_PROP_THREAD_ON_MESH_NETS>(void)
Buke Po818998e2017-08-04 01:19:07 +0800744{
Yakun Xub8333732018-06-21 04:15:13 +0800745 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800746 otBorderRouterConfig borderRouterConfig;
Yakun Xub8333732018-06-21 04:15:13 +0800747 bool stable = false;
748 uint8_t flags = 0;
749 uint8_t prefixLength;
Buke Po818998e2017-08-04 01:19:07 +0800750
751 memset(&borderRouterConfig, 0, sizeof(otBorderRouterConfig));
752
Abtin Keshavarzian31ce3d42019-08-01 10:30:08 -0700753 VerifyOrExit(mAllowLocalNetworkDataChange, error = OT_ERROR_INVALID_STATE);
Buke Po818998e2017-08-04 01:19:07 +0800754
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700755 SuccessOrExit(error = mDecoder.ReadIp6Address(borderRouterConfig.mPrefix.mPrefix));
Łukasz Duda7b084ec2017-10-25 17:54:17 +0200756 SuccessOrExit(error = mDecoder.ReadUint8(prefixLength));
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700757 SuccessOrExit(error = mDecoder.ReadBool(stable));
758 SuccessOrExit(error = mDecoder.ReadUint8(flags));
Buke Po818998e2017-08-04 01:19:07 +0800759
Łukasz Duda7b084ec2017-10-25 17:54:17 +0200760 borderRouterConfig.mPrefix.mLength = prefixLength;
Yakun Xub8333732018-06-21 04:15:13 +0800761 borderRouterConfig.mStable = stable;
762 borderRouterConfig.mPreference = ((flags & SPINEL_NET_FLAG_PREFERENCE_MASK) >> SPINEL_NET_FLAG_PREFERENCE_OFFSET);
763 borderRouterConfig.mPreferred = ((flags & SPINEL_NET_FLAG_PREFERRED) != 0);
764 borderRouterConfig.mSlaac = ((flags & SPINEL_NET_FLAG_SLAAC) != 0);
765 borderRouterConfig.mDhcp = ((flags & SPINEL_NET_FLAG_DHCP) != 0);
766 borderRouterConfig.mConfigure = ((flags & SPINEL_NET_FLAG_CONFIGURE) != 0);
Buke Po818998e2017-08-04 01:19:07 +0800767 borderRouterConfig.mDefaultRoute = ((flags & SPINEL_NET_FLAG_DEFAULT_ROUTE) != 0);
Yakun Xub8333732018-06-21 04:15:13 +0800768 borderRouterConfig.mOnMesh = ((flags & SPINEL_NET_FLAG_ON_MESH) != 0);
Buke Po818998e2017-08-04 01:19:07 +0800769
770 error = otBorderRouterAddOnMeshPrefix(mInstance, &borderRouterConfig);
Buke Po818998e2017-08-04 01:19:07 +0800771
772exit:
Buke Po818998e2017-08-04 01:19:07 +0800773 return error;
774}
775
Yakun Xu8ccf1382018-06-29 00:26:31 +0800776template <> otError NcpBase::HandlePropertyRemove<SPINEL_PROP_THREAD_ON_MESH_NETS>(void)
Buke Po818998e2017-08-04 01:19:07 +0800777{
Yakun Xub8333732018-06-21 04:15:13 +0800778 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800779 otIp6Prefix ip6Prefix;
Yakun Xub8333732018-06-21 04:15:13 +0800780 uint8_t prefixLength;
Buke Po818998e2017-08-04 01:19:07 +0800781
782 memset(&ip6Prefix, 0, sizeof(otIp6Prefix));
783
Abtin Keshavarzian31ce3d42019-08-01 10:30:08 -0700784 VerifyOrExit(mAllowLocalNetworkDataChange, error = OT_ERROR_INVALID_STATE);
Buke Po818998e2017-08-04 01:19:07 +0800785
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700786 SuccessOrExit(error = mDecoder.ReadIp6Address(ip6Prefix.mPrefix));
Łukasz Duda7b084ec2017-10-25 17:54:17 +0200787 SuccessOrExit(error = mDecoder.ReadUint8(prefixLength));
788
789 ip6Prefix.mLength = prefixLength;
Buke Po818998e2017-08-04 01:19:07 +0800790
791 error = otBorderRouterRemoveOnMeshPrefix(mInstance, &ip6Prefix);
792
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700793 // If prefix was not on the list, "remove" command can be considred
794 // successful.
Abtin Keshavarzian02bdc692017-08-15 09:11:19 -0700795
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700796 if (error == OT_ERROR_NOT_FOUND)
Buke Po818998e2017-08-04 01:19:07 +0800797 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700798 error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +0800799 }
800
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700801exit:
Buke Po818998e2017-08-04 01:19:07 +0800802 return error;
803}
Jonathan Huif1849732019-07-16 12:31:11 -0700804#endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
Buke Po818998e2017-08-04 01:19:07 +0800805
Jonathan Hui149640d2019-07-16 11:06:03 -0700806#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
Joseph Newmanecad7172019-03-29 05:29:25 +0000807
808template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_SERVER_ALLOW_LOCAL_DATA_CHANGE>(void)
809{
810 return mEncoder.WriteBool(mAllowLocalServerDataChange);
811}
812
813template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_SERVER_ALLOW_LOCAL_DATA_CHANGE>(void)
814{
815 bool value = false;
816 otError error = OT_ERROR_NONE;
817 bool shouldRegisterWithLeader = false;
818
819 SuccessOrExit(error = mDecoder.ReadBool(value));
820
821 // Register any server data changes on transition from `true` to `false`.
822 shouldRegisterWithLeader = (mAllowLocalServerDataChange == true) && (value == false);
823
824 mAllowLocalServerDataChange = value;
825
826exit:
827
828 if (shouldRegisterWithLeader)
829 {
kangping49f36f82020-05-07 02:17:58 +0800830 IgnoreError(otServerRegister(mInstance));
Joseph Newmanecad7172019-03-29 05:29:25 +0000831 }
832
833 return error;
834}
835
836template <> otError NcpBase::HandlePropertyInsert<SPINEL_PROP_SERVER_SERVICES>(void)
837{
838 otError error = OT_ERROR_NONE;
839 otServiceConfig cfg;
840 bool stable;
841 const uint8_t * data;
842 uint16_t dataLen;
843
Abtin Keshavarzian31ce3d42019-08-01 10:30:08 -0700844 VerifyOrExit(mAllowLocalServerDataChange, error = OT_ERROR_INVALID_STATE);
Joseph Newmanecad7172019-03-29 05:29:25 +0000845
846 SuccessOrExit(error = mDecoder.ReadUint32(cfg.mEnterpriseNumber));
847 SuccessOrExit(error = mDecoder.ReadDataWithLen(data, dataLen));
848
849 VerifyOrExit((dataLen <= sizeof(cfg.mServiceData)), error = OT_ERROR_INVALID_ARGS);
850 memcpy(cfg.mServiceData, data, dataLen);
851
Abtin Keshavarzian53d23b52020-06-20 18:09:14 -0700852 static_assert((sizeof(cfg.mServiceData) <= UINT8_MAX), "Cannot handle full range of buffer length");
Joseph Newmanecad7172019-03-29 05:29:25 +0000853 cfg.mServiceDataLength = static_cast<uint8_t>(dataLen);
854
855 SuccessOrExit(error = mDecoder.ReadBool(stable));
856 cfg.mServerConfig.mStable = stable;
857 SuccessOrExit(error = mDecoder.ReadDataWithLen(data, dataLen));
858
859 VerifyOrExit((dataLen <= sizeof(cfg.mServerConfig.mServerData)), error = OT_ERROR_INVALID_ARGS);
860 memcpy(cfg.mServerConfig.mServerData, data, dataLen);
861
Abtin Keshavarzian53d23b52020-06-20 18:09:14 -0700862 static_assert((sizeof(cfg.mServerConfig.mServerData) <= UINT8_MAX), "Cannot handle full range of buffer length");
Joseph Newmanecad7172019-03-29 05:29:25 +0000863 cfg.mServerConfig.mServerDataLength = static_cast<uint8_t>(dataLen);
864
865 SuccessOrExit(error = otServerAddService(mInstance, &cfg));
866exit:
867 return error;
868}
869
870template <> otError NcpBase::HandlePropertyRemove<SPINEL_PROP_SERVER_SERVICES>(void)
871{
872 otError error = OT_ERROR_NONE;
873
874 uint32_t enterpriseNumber;
875 const uint8_t *serviceData;
876 uint16_t serviceDataLength;
877
Abtin Keshavarzian31ce3d42019-08-01 10:30:08 -0700878 VerifyOrExit(mAllowLocalServerDataChange, error = OT_ERROR_INVALID_STATE);
Joseph Newmanecad7172019-03-29 05:29:25 +0000879
880 SuccessOrExit(error = mDecoder.ReadUint32(enterpriseNumber));
881 SuccessOrExit(error = mDecoder.ReadDataWithLen(serviceData, serviceDataLength));
882
883 VerifyOrExit(serviceDataLength <= UINT8_MAX, error = OT_ERROR_INVALID_ARGS);
884
885 SuccessOrExit(error = otServerRemoveService(mInstance, enterpriseNumber, serviceData,
886 static_cast<uint8_t>(serviceDataLength)));
887exit:
888 return error;
889}
890
891template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_SERVER_SERVICES>(void)
892{
893 otError error = OT_ERROR_NONE;
894 otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
895 otServiceConfig cfg;
896
897 while (otServerGetNextService(mInstance, &iterator, &cfg) == OT_ERROR_NONE)
898 {
899 SuccessOrExit(error = mEncoder.OpenStruct());
900
901 SuccessOrExit(error = mEncoder.WriteUint32(cfg.mEnterpriseNumber));
902 SuccessOrExit(error = mEncoder.WriteDataWithLen(cfg.mServiceData, cfg.mServiceDataLength));
903 SuccessOrExit(error = mEncoder.WriteBool(cfg.mServerConfig.mStable));
904 SuccessOrExit(
905 error = mEncoder.WriteDataWithLen(cfg.mServerConfig.mServerData, cfg.mServerConfig.mServerDataLength));
906 SuccessOrExit(error = mEncoder.WriteUint16(cfg.mServerConfig.mRloc16));
907
908 SuccessOrExit(error = mEncoder.CloseStruct());
909 }
910exit:
911 return error;
912}
Rongli Sune8600092019-12-03 00:42:46 +0800913#endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
Joseph Newmanecad7172019-03-29 05:29:25 +0000914
915template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_SERVER_LEADER_SERVICES>(void)
916{
917 otError error = OT_ERROR_NONE;
918 otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
919 otServiceConfig cfg;
920
Rongli Sune8600092019-12-03 00:42:46 +0800921 while (otNetDataGetNextService(mInstance, &iterator, &cfg) == OT_ERROR_NONE)
Joseph Newmanecad7172019-03-29 05:29:25 +0000922 {
923 SuccessOrExit(error = mEncoder.OpenStruct());
924
Rongli Sun315a27b2020-03-26 23:54:23 +0800925 SuccessOrExit(error = mEncoder.WriteUint8(cfg.mServiceId));
Joseph Newmanecad7172019-03-29 05:29:25 +0000926 SuccessOrExit(error = mEncoder.WriteUint32(cfg.mEnterpriseNumber));
927 SuccessOrExit(error = mEncoder.WriteDataWithLen(cfg.mServiceData, cfg.mServiceDataLength));
928 SuccessOrExit(error = mEncoder.WriteBool(cfg.mServerConfig.mStable));
929 SuccessOrExit(
930 error = mEncoder.WriteDataWithLen(cfg.mServerConfig.mServerData, cfg.mServerConfig.mServerDataLength));
931 SuccessOrExit(error = mEncoder.WriteUint16(cfg.mServerConfig.mRloc16));
932
933 SuccessOrExit(error = mEncoder.CloseStruct());
934 }
935exit:
936 return error;
937}
938
Yakun Xu8ccf1382018-06-29 00:26:31 +0800939template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_DISCOVERY_SCAN_JOINER_FLAG>(void)
Buke Po818998e2017-08-04 01:19:07 +0800940{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700941 return mEncoder.WriteBool(mDiscoveryScanJoinerFlag);
Buke Po818998e2017-08-04 01:19:07 +0800942}
943
Yakun Xu8ccf1382018-06-29 00:26:31 +0800944template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_DISCOVERY_SCAN_JOINER_FLAG>(void)
Buke Po818998e2017-08-04 01:19:07 +0800945{
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700946 return mDecoder.ReadBool(mDiscoveryScanJoinerFlag);
Buke Po818998e2017-08-04 01:19:07 +0800947}
948
Yakun Xu8ccf1382018-06-29 00:26:31 +0800949template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_DISCOVERY_SCAN_ENABLE_FILTERING>(void)
Buke Po818998e2017-08-04 01:19:07 +0800950{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700951 return mEncoder.WriteBool(mDiscoveryScanEnableFiltering);
Buke Po818998e2017-08-04 01:19:07 +0800952}
953
Yakun Xu8ccf1382018-06-29 00:26:31 +0800954template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_DISCOVERY_SCAN_ENABLE_FILTERING>(void)
Buke Po818998e2017-08-04 01:19:07 +0800955{
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -0700956 return mDecoder.ReadBool(mDiscoveryScanEnableFiltering);
Buke Po818998e2017-08-04 01:19:07 +0800957}
958
Yakun Xu8ccf1382018-06-29 00:26:31 +0800959template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_DISCOVERY_SCAN_PANID>(void)
Buke Po818998e2017-08-04 01:19:07 +0800960{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -0700961 return mEncoder.WriteUint16(mDiscoveryScanPanId);
Buke Po818998e2017-08-04 01:19:07 +0800962}
963
Yakun Xu8ccf1382018-06-29 00:26:31 +0800964template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_DISCOVERY_SCAN_PANID>(void)
Buke Po818998e2017-08-04 01:19:07 +0800965{
Yakun Xub8333732018-06-21 04:15:13 +0800966 return mDecoder.ReadUint16(mDiscoveryScanPanId);
Buke Po818998e2017-08-04 01:19:07 +0800967}
968
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -0800969otError NcpBase::EncodeOperationalDataset(const otOperationalDataset &aDataset)
970{
971 otError error = OT_ERROR_NONE;
972
Abtin Keshavarzian758e6472018-07-19 14:33:49 -0700973 if (aDataset.mComponents.mIsActiveTimestampPresent)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -0800974 {
975 SuccessOrExit(mEncoder.OpenStruct());
976 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_DATASET_ACTIVE_TIMESTAMP));
977 SuccessOrExit(mEncoder.WriteUint64(aDataset.mActiveTimestamp));
978 SuccessOrExit(mEncoder.CloseStruct());
979 }
980
Abtin Keshavarzian758e6472018-07-19 14:33:49 -0700981 if (aDataset.mComponents.mIsPendingTimestampPresent)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -0800982 {
983 SuccessOrExit(mEncoder.OpenStruct());
984 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_DATASET_PENDING_TIMESTAMP));
985 SuccessOrExit(mEncoder.WriteUint64(aDataset.mPendingTimestamp));
986 SuccessOrExit(mEncoder.CloseStruct());
987 }
988
Abtin Keshavarzian758e6472018-07-19 14:33:49 -0700989 if (aDataset.mComponents.mIsMasterKeyPresent)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -0800990 {
991 SuccessOrExit(mEncoder.OpenStruct());
992 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_NET_MASTER_KEY));
993 SuccessOrExit(mEncoder.WriteData(aDataset.mMasterKey.m8, OT_MASTER_KEY_SIZE));
994 SuccessOrExit(mEncoder.CloseStruct());
995 }
996
Abtin Keshavarzian758e6472018-07-19 14:33:49 -0700997 if (aDataset.mComponents.mIsNetworkNamePresent)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -0800998 {
999 SuccessOrExit(mEncoder.OpenStruct());
1000 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_NET_NETWORK_NAME));
1001 SuccessOrExit(mEncoder.WriteUtf8(aDataset.mNetworkName.m8));
1002 SuccessOrExit(mEncoder.CloseStruct());
1003 }
1004
Abtin Keshavarzian758e6472018-07-19 14:33:49 -07001005 if (aDataset.mComponents.mIsExtendedPanIdPresent)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001006 {
1007 SuccessOrExit(mEncoder.OpenStruct());
1008 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_NET_XPANID));
1009 SuccessOrExit(mEncoder.WriteData(aDataset.mExtendedPanId.m8, OT_EXT_PAN_ID_SIZE));
1010 SuccessOrExit(mEncoder.CloseStruct());
1011 }
1012
Abtin Keshavarzian758e6472018-07-19 14:33:49 -07001013 if (aDataset.mComponents.mIsMeshLocalPrefixPresent)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001014 {
1015 otIp6Address addr;
1016
1017 memcpy(addr.mFields.m8, aDataset.mMeshLocalPrefix.m8, 8);
Yakun Xub8333732018-06-21 04:15:13 +08001018 memset(addr.mFields.m8 + 8, 0, 8); // Zero out the last 8 bytes.
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001019
1020 SuccessOrExit(mEncoder.OpenStruct());
1021 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_IPV6_ML_PREFIX));
Jintao Lin8788cf52020-01-10 10:15:23 +08001022 SuccessOrExit(error = mEncoder.WriteIp6Address(addr)); // Mesh local prefix
1023 SuccessOrExit(error = mEncoder.WriteUint8(OT_IP6_PREFIX_BITSIZE)); // Prefix length (in bits)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001024 SuccessOrExit(mEncoder.CloseStruct());
1025 }
1026
Abtin Keshavarzian758e6472018-07-19 14:33:49 -07001027 if (aDataset.mComponents.mIsDelayPresent)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001028 {
1029 SuccessOrExit(mEncoder.OpenStruct());
1030 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_DATASET_DELAY_TIMER));
1031 SuccessOrExit(mEncoder.WriteUint32(aDataset.mDelay));
1032 SuccessOrExit(mEncoder.CloseStruct());
1033 }
1034
Abtin Keshavarzian758e6472018-07-19 14:33:49 -07001035 if (aDataset.mComponents.mIsPanIdPresent)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001036 {
1037 SuccessOrExit(mEncoder.OpenStruct());
1038 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_MAC_15_4_PANID));
1039 SuccessOrExit(mEncoder.WriteUint16(aDataset.mPanId));
1040 SuccessOrExit(mEncoder.CloseStruct());
1041 }
1042
Abtin Keshavarzian758e6472018-07-19 14:33:49 -07001043 if (aDataset.mComponents.mIsChannelPresent)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001044 {
1045 SuccessOrExit(mEncoder.OpenStruct());
1046 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_PHY_CHAN));
1047
1048 // The channel is stored in Dataset as `uint16_t` (to accommodate
1049 // larger number of channels in sub-GHz band), however the current
1050 // definition of `SPINEL_PROP_PHY_CHAN` property limits the channel
1051 // to a `uint8_t`.
1052
1053 SuccessOrExit(mEncoder.WriteUint8(static_cast<uint8_t>(aDataset.mChannel)));
1054 SuccessOrExit(mEncoder.CloseStruct());
1055 }
1056
Abtin Keshavarzian1555b212019-09-18 19:11:07 -07001057 if (aDataset.mComponents.mIsPskcPresent)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001058 {
1059 SuccessOrExit(mEncoder.OpenStruct());
1060 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_NET_PSKC));
Abtin Keshavarzian1555b212019-09-18 19:11:07 -07001061 SuccessOrExit(mEncoder.WriteData(aDataset.mPskc.m8, sizeof(spinel_net_pskc_t)));
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001062 SuccessOrExit(mEncoder.CloseStruct());
1063 }
1064
Abtin Keshavarzian758e6472018-07-19 14:33:49 -07001065 if (aDataset.mComponents.mIsSecurityPolicyPresent)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001066 {
1067 SuccessOrExit(mEncoder.OpenStruct());
1068 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_DATASET_SECURITY_POLICY));
1069 SuccessOrExit(mEncoder.WriteUint16(aDataset.mSecurityPolicy.mRotationTime));
1070 SuccessOrExit(mEncoder.WriteUint8(aDataset.mSecurityPolicy.mFlags));
1071 SuccessOrExit(mEncoder.CloseStruct());
1072 }
1073
Zhanglong Xiace24abb2019-03-13 22:49:25 +08001074 if (aDataset.mComponents.mIsChannelMaskPresent)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001075 {
1076 SuccessOrExit(mEncoder.OpenStruct());
1077 SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_PHY_CHAN_SUPPORTED));
Zhanglong Xiace24abb2019-03-13 22:49:25 +08001078 SuccessOrExit(EncodeChannelMask(aDataset.mChannelMask));
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001079 SuccessOrExit(mEncoder.CloseStruct());
1080 }
1081
1082exit:
1083 return error;
1084}
1085
Yakun Xu8ccf1382018-06-29 00:26:31 +08001086template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_ACTIVE_DATASET>(void)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001087{
1088 otOperationalDataset dataset;
1089
kangping49f36f82020-05-07 02:17:58 +08001090 IgnoreError(otDatasetGetActive(mInstance, &dataset));
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001091 return EncodeOperationalDataset(dataset);
1092}
1093
Yakun Xu8ccf1382018-06-29 00:26:31 +08001094template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_PENDING_DATASET>(void)
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001095{
1096 otOperationalDataset dataset;
1097
kangping49f36f82020-05-07 02:17:58 +08001098 IgnoreError(otDatasetGetPending(mInstance, &dataset));
Abtin Keshavarzian4e060e42017-11-16 05:43:13 -08001099 return EncodeOperationalDataset(dataset);
1100}
1101
rongli1253bec2018-12-04 13:28:09 +08001102otError NcpBase::DecodeOperationalDataset(otOperationalDataset &aDataset,
1103 const uint8_t ** aTlvs,
1104 uint8_t * aTlvsLength,
1105 const otIp6Address ** aDestIpAddress,
Jonathan Hui49c4b632019-03-21 09:52:32 -07001106 bool aAllowEmptyValues)
rongli1253bec2018-12-04 13:28:09 +08001107{
1108 otError error = OT_ERROR_NONE;
1109
1110 memset(&aDataset, 0, sizeof(otOperationalDataset));
1111
Jonathan Hui1326d642020-06-17 22:44:54 -07001112 if (aTlvs != nullptr)
rongli1253bec2018-12-04 13:28:09 +08001113 {
Jonathan Hui1326d642020-06-17 22:44:54 -07001114 *aTlvs = nullptr;
rongli1253bec2018-12-04 13:28:09 +08001115 }
1116
Jonathan Hui1326d642020-06-17 22:44:54 -07001117 if (aTlvsLength != nullptr)
rongli1253bec2018-12-04 13:28:09 +08001118 {
1119 *aTlvsLength = 0;
1120 }
1121
Jonathan Hui1326d642020-06-17 22:44:54 -07001122 if (aDestIpAddress != nullptr)
rongli1253bec2018-12-04 13:28:09 +08001123 {
Jonathan Hui1326d642020-06-17 22:44:54 -07001124 *aDestIpAddress = nullptr;
rongli1253bec2018-12-04 13:28:09 +08001125 }
1126
1127 while (!mDecoder.IsAllReadInStruct())
1128 {
1129 unsigned int propKey;
1130
1131 SuccessOrExit(error = mDecoder.OpenStruct());
1132 SuccessOrExit(error = mDecoder.ReadUintPacked(propKey));
1133
1134 switch (static_cast<spinel_prop_key_t>(propKey))
1135 {
1136 case SPINEL_PROP_DATASET_ACTIVE_TIMESTAMP:
1137
Jonathan Hui49c4b632019-03-21 09:52:32 -07001138 if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
rongli1253bec2018-12-04 13:28:09 +08001139 {
1140 SuccessOrExit(error = mDecoder.ReadUint64(aDataset.mActiveTimestamp));
1141 }
1142
1143 aDataset.mComponents.mIsActiveTimestampPresent = true;
1144 break;
1145
1146 case SPINEL_PROP_DATASET_PENDING_TIMESTAMP:
1147
Jonathan Hui49c4b632019-03-21 09:52:32 -07001148 if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
rongli1253bec2018-12-04 13:28:09 +08001149 {
1150 SuccessOrExit(error = mDecoder.ReadUint64(aDataset.mPendingTimestamp));
1151 }
1152
1153 aDataset.mComponents.mIsPendingTimestampPresent = true;
1154 break;
1155
1156 case SPINEL_PROP_NET_MASTER_KEY:
1157
Jonathan Hui49c4b632019-03-21 09:52:32 -07001158 if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
rongli1253bec2018-12-04 13:28:09 +08001159 {
1160 const uint8_t *key;
1161 uint16_t len;
1162
1163 SuccessOrExit(error = mDecoder.ReadData(key, len));
1164 VerifyOrExit(len == OT_MASTER_KEY_SIZE, error = OT_ERROR_INVALID_ARGS);
1165 memcpy(aDataset.mMasterKey.m8, key, len);
1166 }
1167
1168 aDataset.mComponents.mIsMasterKeyPresent = true;
1169 break;
1170
1171 case SPINEL_PROP_NET_NETWORK_NAME:
1172
Jonathan Hui49c4b632019-03-21 09:52:32 -07001173 if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
rongli1253bec2018-12-04 13:28:09 +08001174 {
1175 const char *name;
1176 size_t len;
1177
1178 SuccessOrExit(error = mDecoder.ReadUtf8(name));
1179 len = strlen(name);
1180 VerifyOrExit(len <= OT_NETWORK_NAME_MAX_SIZE, error = OT_ERROR_INVALID_ARGS);
1181 memcpy(aDataset.mNetworkName.m8, name, len + 1);
1182 }
1183
1184 aDataset.mComponents.mIsNetworkNamePresent = true;
1185 break;
1186
1187 case SPINEL_PROP_NET_XPANID:
1188
Jonathan Hui49c4b632019-03-21 09:52:32 -07001189 if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
rongli1253bec2018-12-04 13:28:09 +08001190 {
1191 const uint8_t *xpanid;
1192 uint16_t len;
1193
1194 SuccessOrExit(error = mDecoder.ReadData(xpanid, len));
1195 VerifyOrExit(len == OT_EXT_PAN_ID_SIZE, error = OT_ERROR_INVALID_ARGS);
1196 memcpy(aDataset.mExtendedPanId.m8, xpanid, len);
1197 }
1198
1199 aDataset.mComponents.mIsExtendedPanIdPresent = true;
1200 break;
1201
1202 case SPINEL_PROP_IPV6_ML_PREFIX:
1203
Jonathan Hui49c4b632019-03-21 09:52:32 -07001204 if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
rongli1253bec2018-12-04 13:28:09 +08001205 {
1206 const otIp6Address *addr;
1207 uint8_t prefixLen;
1208
1209 SuccessOrExit(error = mDecoder.ReadIp6Address(addr));
1210 SuccessOrExit(error = mDecoder.ReadUint8(prefixLen));
Jintao Lin8788cf52020-01-10 10:15:23 +08001211 VerifyOrExit(prefixLen == OT_IP6_PREFIX_BITSIZE, error = OT_ERROR_INVALID_ARGS);
rongli1253bec2018-12-04 13:28:09 +08001212 memcpy(aDataset.mMeshLocalPrefix.m8, addr, OT_MESH_LOCAL_PREFIX_SIZE);
1213 }
1214
1215 aDataset.mComponents.mIsMeshLocalPrefixPresent = true;
1216 break;
1217
1218 case SPINEL_PROP_DATASET_DELAY_TIMER:
1219
Jonathan Hui49c4b632019-03-21 09:52:32 -07001220 if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
rongli1253bec2018-12-04 13:28:09 +08001221 {
1222 SuccessOrExit(error = mDecoder.ReadUint32(aDataset.mDelay));
1223 }
1224
1225 aDataset.mComponents.mIsDelayPresent = true;
1226 break;
1227
1228 case SPINEL_PROP_MAC_15_4_PANID:
1229
Jonathan Hui49c4b632019-03-21 09:52:32 -07001230 if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
rongli1253bec2018-12-04 13:28:09 +08001231 {
1232 SuccessOrExit(error = mDecoder.ReadUint16(aDataset.mPanId));
1233 }
1234
1235 aDataset.mComponents.mIsPanIdPresent = true;
1236 break;
1237
1238 case SPINEL_PROP_PHY_CHAN:
1239
Jonathan Hui49c4b632019-03-21 09:52:32 -07001240 if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
rongli1253bec2018-12-04 13:28:09 +08001241 {
1242 uint8_t channel;
1243
1244 SuccessOrExit(error = mDecoder.ReadUint8(channel));
1245 aDataset.mChannel = channel;
1246 }
1247
1248 aDataset.mComponents.mIsChannelPresent = true;
1249 break;
1250
1251 case SPINEL_PROP_NET_PSKC:
1252
Jonathan Hui49c4b632019-03-21 09:52:32 -07001253 if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
rongli1253bec2018-12-04 13:28:09 +08001254 {
1255 const uint8_t *psk;
1256 uint16_t len;
1257
1258 SuccessOrExit(error = mDecoder.ReadData(psk, len));
1259 VerifyOrExit(len == OT_PSKC_MAX_SIZE, error = OT_ERROR_INVALID_ARGS);
Abtin Keshavarzian1555b212019-09-18 19:11:07 -07001260 memcpy(aDataset.mPskc.m8, psk, OT_PSKC_MAX_SIZE);
rongli1253bec2018-12-04 13:28:09 +08001261 }
1262
Abtin Keshavarzian1555b212019-09-18 19:11:07 -07001263 aDataset.mComponents.mIsPskcPresent = true;
rongli1253bec2018-12-04 13:28:09 +08001264 break;
1265
1266 case SPINEL_PROP_DATASET_SECURITY_POLICY:
1267
Jonathan Hui49c4b632019-03-21 09:52:32 -07001268 if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
rongli1253bec2018-12-04 13:28:09 +08001269 {
1270 SuccessOrExit(error = mDecoder.ReadUint16(aDataset.mSecurityPolicy.mRotationTime));
1271 SuccessOrExit(error = mDecoder.ReadUint8(aDataset.mSecurityPolicy.mFlags));
1272 }
1273
1274 aDataset.mComponents.mIsSecurityPolicyPresent = true;
1275 break;
1276
1277 case SPINEL_PROP_PHY_CHAN_SUPPORTED:
1278
Jonathan Hui49c4b632019-03-21 09:52:32 -07001279 if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
rongli1253bec2018-12-04 13:28:09 +08001280 {
1281 uint8_t channel;
1282
Zhanglong Xiace24abb2019-03-13 22:49:25 +08001283 aDataset.mChannelMask = 0;
rongli1253bec2018-12-04 13:28:09 +08001284
1285 while (!mDecoder.IsAllReadInStruct())
1286 {
1287 SuccessOrExit(error = mDecoder.ReadUint8(channel));
1288 VerifyOrExit(channel <= 31, error = OT_ERROR_INVALID_ARGS);
Zhanglong Xiace24abb2019-03-13 22:49:25 +08001289 aDataset.mChannelMask |= (1UL << channel);
rongli1253bec2018-12-04 13:28:09 +08001290 }
1291 }
1292
Zhanglong Xiace24abb2019-03-13 22:49:25 +08001293 aDataset.mComponents.mIsChannelMaskPresent = true;
rongli1253bec2018-12-04 13:28:09 +08001294 break;
1295
1296 case SPINEL_PROP_DATASET_RAW_TLVS:
1297
Jonathan Hui49c4b632019-03-21 09:52:32 -07001298 if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
rongli1253bec2018-12-04 13:28:09 +08001299 {
1300 const uint8_t *tlvs;
1301 uint16_t len;
1302
1303 SuccessOrExit(error = mDecoder.ReadData(tlvs, len));
1304 VerifyOrExit(len <= 255, error = OT_ERROR_INVALID_ARGS);
1305
Jonathan Hui1326d642020-06-17 22:44:54 -07001306 if (aTlvs != nullptr)
rongli1253bec2018-12-04 13:28:09 +08001307 {
1308 *aTlvs = tlvs;
1309 }
1310
Jonathan Hui1326d642020-06-17 22:44:54 -07001311 if (aTlvsLength != nullptr)
rongli1253bec2018-12-04 13:28:09 +08001312 {
1313 *aTlvsLength = static_cast<uint8_t>(len);
1314 }
1315 }
1316
1317 break;
1318
1319 case SPINEL_PROP_DATASET_DEST_ADDRESS:
1320
Jonathan Hui49c4b632019-03-21 09:52:32 -07001321 if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
rongli1253bec2018-12-04 13:28:09 +08001322 {
1323 const otIp6Address *addr;
1324
1325 SuccessOrExit(error = mDecoder.ReadIp6Address(addr));
1326
Jonathan Hui1326d642020-06-17 22:44:54 -07001327 if (aDestIpAddress != nullptr)
rongli1253bec2018-12-04 13:28:09 +08001328 {
1329 *aDestIpAddress = addr;
1330 }
1331 }
1332
1333 break;
1334
1335 default:
1336 break;
1337 }
1338
1339 SuccessOrExit(error = mDecoder.CloseStruct());
1340 }
1341
1342exit:
1343 return error;
1344}
1345
1346template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_ACTIVE_DATASET>(void)
1347{
1348 otError error = OT_ERROR_NONE;
1349 otOperationalDataset dataset;
1350
1351 SuccessOrExit(error = DecodeOperationalDataset(dataset));
1352 error = otDatasetSetActive(mInstance, &dataset);
1353
1354exit:
1355 return error;
1356}
1357
1358template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_PENDING_DATASET>(void)
1359{
1360 otError error = OT_ERROR_NONE;
1361 otOperationalDataset dataset;
1362
1363 SuccessOrExit(error = DecodeOperationalDataset(dataset));
1364 error = otDatasetSetPending(mInstance, &dataset);
1365
1366exit:
1367 return error;
1368}
1369
1370template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_MGMT_SET_ACTIVE_DATASET>(void)
1371{
1372 otError error = OT_ERROR_NONE;
1373 otOperationalDataset dataset;
1374 const uint8_t * extraTlvs;
1375 uint8_t extraTlvsLength;
1376
1377 SuccessOrExit(error = DecodeOperationalDataset(dataset, &extraTlvs, &extraTlvsLength));
1378 error = otDatasetSendMgmtActiveSet(mInstance, &dataset, extraTlvs, extraTlvsLength);
1379
1380exit:
1381 return error;
1382}
1383
1384template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_MGMT_SET_PENDING_DATASET>(void)
1385{
1386 otError error = OT_ERROR_NONE;
1387 otOperationalDataset dataset;
1388 const uint8_t * extraTlvs;
1389 uint8_t extraTlvsLength;
1390
1391 SuccessOrExit(error = DecodeOperationalDataset(dataset, &extraTlvs, &extraTlvsLength));
1392 error = otDatasetSendMgmtPendingSet(mInstance, &dataset, extraTlvs, extraTlvsLength);
1393
1394exit:
1395 return error;
1396}
1397
1398template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_MGMT_GET_ACTIVE_DATASET>(void)
1399{
1400 otError error = OT_ERROR_NONE;
1401 otOperationalDataset dataset;
1402 const uint8_t * extraTlvs;
1403 uint8_t extraTlvsLength;
1404 const otIp6Address * destIpAddress;
1405
1406 SuccessOrExit(error = DecodeOperationalDataset(dataset, &extraTlvs, &extraTlvsLength, &destIpAddress, true));
1407 error = otDatasetSendMgmtActiveGet(mInstance, &dataset.mComponents, extraTlvs, extraTlvsLength, destIpAddress);
1408
1409exit:
1410 return error;
1411}
1412
1413template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_MGMT_GET_PENDING_DATASET>(void)
1414{
1415 otError error = OT_ERROR_NONE;
1416 otOperationalDataset dataset;
1417 const uint8_t * extraTlvs;
1418 uint8_t extraTlvsLength;
1419 const otIp6Address * destIpAddress;
1420
1421 SuccessOrExit(error = DecodeOperationalDataset(dataset, &extraTlvs, &extraTlvsLength, &destIpAddress, true));
1422 error = otDatasetSendMgmtPendingGet(mInstance, &dataset.mComponents, extraTlvs, extraTlvsLength, destIpAddress);
1423
1424exit:
1425 return error;
1426}
Jonathan Hui31ffd162019-07-16 12:01:36 -07001427#if OPENTHREAD_CONFIG_JOINER_ENABLE
rongli90ee0a42018-08-09 02:18:53 +08001428template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MESHCOP_JOINER_STATE>(void)
1429{
Abtin Keshavarzian99f57902019-04-22 10:04:54 -07001430 spinel_meshcop_joiner_state_t state = SPINEL_MESHCOP_JOINER_STATE_IDLE;
1431
1432 switch (otJoinerGetState(mInstance))
1433 {
1434 case OT_JOINER_STATE_IDLE:
1435 state = SPINEL_MESHCOP_JOINER_STATE_IDLE;
1436 break;
1437 case OT_JOINER_STATE_DISCOVER:
1438 state = SPINEL_MESHCOP_JOINER_STATE_DISCOVER;
1439 break;
1440 case OT_JOINER_STATE_CONNECT:
1441 state = SPINEL_MESHCOP_JOINER_STATE_CONNECTING;
1442 break;
1443 case OT_JOINER_STATE_CONNECTED:
1444 state = SPINEL_MESHCOP_JOINER_STATE_CONNECTED;
1445 break;
1446 case OT_JOINER_STATE_ENTRUST:
1447 state = SPINEL_MESHCOP_JOINER_STATE_ENTRUST;
1448 break;
1449 case OT_JOINER_STATE_JOINED:
1450 state = SPINEL_MESHCOP_JOINER_STATE_JOINED;
1451 break;
1452 }
1453
1454 return mEncoder.WriteUint8(state);
rongli90ee0a42018-08-09 02:18:53 +08001455}
1456
1457template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MESHCOP_JOINER_COMMISSIONING>(void)
1458{
Abtin Keshavarzian987e96b2019-04-17 19:08:11 -07001459 otError error = OT_ERROR_NONE;
rongli90ee0a42018-08-09 02:18:53 +08001460 bool action = false;
Jonathan Hui1326d642020-06-17 22:44:54 -07001461 const char *psk = nullptr;
1462 const char *provisioningUrl = nullptr;
1463 const char *vendorName = nullptr;
1464 const char *vendorModel = nullptr;
1465 const char *vendorSwVersion = nullptr;
1466 const char *vendorData = nullptr;
rongli90ee0a42018-08-09 02:18:53 +08001467
1468 SuccessOrExit(error = mDecoder.ReadBool(action));
rongli90ee0a42018-08-09 02:18:53 +08001469
Abtin Keshavarzian987e96b2019-04-17 19:08:11 -07001470 if (action == false)
rongli90ee0a42018-08-09 02:18:53 +08001471 {
Yakun Xu957d79d2019-09-10 23:42:02 +08001472 otJoinerStop(mInstance);
Abtin Keshavarzian987e96b2019-04-17 19:08:11 -07001473 ExitNow();
rongli90ee0a42018-08-09 02:18:53 +08001474 }
Abtin Keshavarzian987e96b2019-04-17 19:08:11 -07001475
1476 SuccessOrExit(error = mDecoder.ReadUtf8(psk));
1477
1478 // Parse optional fields
1479
1480 if (!mDecoder.IsAllReadInStruct())
1481 {
1482 SuccessOrExit(error = mDecoder.ReadUtf8(provisioningUrl));
1483 }
1484
1485 if (!mDecoder.IsAllReadInStruct())
1486 {
1487 SuccessOrExit(error = mDecoder.ReadUtf8(vendorName));
1488 }
1489
1490 if (!mDecoder.IsAllReadInStruct())
1491 {
1492 SuccessOrExit(error = mDecoder.ReadUtf8(vendorModel));
1493 }
1494
1495 if (!mDecoder.IsAllReadInStruct())
1496 {
1497 SuccessOrExit(error = mDecoder.ReadUtf8(vendorSwVersion));
1498 }
1499
1500 if (!mDecoder.IsAllReadInStruct())
1501 {
1502 SuccessOrExit(error = mDecoder.ReadUtf8(vendorData));
1503 }
1504
1505 // Use OpenThread default values for vendor name, mode, sw version if
1506 // not specified or an empty string is given.
1507
Jonathan Hui1326d642020-06-17 22:44:54 -07001508 if ((vendorName == nullptr) || (vendorName[0] == 0))
Abtin Keshavarzian987e96b2019-04-17 19:08:11 -07001509 {
1510 vendorName = PACKAGE_NAME;
1511 }
1512
Jonathan Hui1326d642020-06-17 22:44:54 -07001513 if ((vendorModel == nullptr) || (vendorModel[0] == 0))
Abtin Keshavarzian987e96b2019-04-17 19:08:11 -07001514 {
1515 vendorModel = OPENTHREAD_CONFIG_PLATFORM_INFO;
1516 }
1517
Jonathan Hui1326d642020-06-17 22:44:54 -07001518 if ((vendorSwVersion == nullptr) || (vendorSwVersion[0] == 0))
Abtin Keshavarzian987e96b2019-04-17 19:08:11 -07001519 {
1520 vendorSwVersion = PACKAGE_VERSION;
1521 }
1522
1523 error = otJoinerStart(mInstance, psk, provisioningUrl, vendorName, vendorModel, vendorSwVersion, vendorData,
1524 &NcpBase::HandleJoinerCallback_Jump, this);
1525
rongli90ee0a42018-08-09 02:18:53 +08001526exit:
1527 return error;
1528}
1529
Abtin Keshavarziana7415b52020-06-20 00:35:57 -07001530template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MESHCOP_JOINER_DISCERNER>(void)
1531{
1532 otError error;
1533 const otJoinerDiscerner *discerner = otJoinerGetDiscerner(mInstance);
1534
1535 if (discerner == nullptr)
1536 {
1537 SuccessOrExit(error = mEncoder.WriteUint8(0));
1538 }
1539 else
1540 {
1541 SuccessOrExit(error = mEncoder.WriteUint8(discerner->mLength));
1542 SuccessOrExit(error = mEncoder.WriteUint64(discerner->mValue));
1543 }
1544
1545exit:
1546 return error;
1547}
1548
1549template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MESHCOP_JOINER_DISCERNER>(void)
1550{
1551 otError error = OT_ERROR_NONE;
1552 otJoinerDiscerner discerner;
1553
1554 SuccessOrExit(error = mDecoder.ReadUint8(discerner.mLength));
1555
1556 if (discerner.mLength == 0)
1557 {
1558 // Clearing any previously set Joiner Discerner
1559 error = otJoinerSetDiscerner(mInstance, nullptr);
1560 ExitNow();
1561 }
1562
1563 SuccessOrExit(error = mDecoder.ReadUint64(discerner.mValue));
1564 error = otJoinerSetDiscerner(mInstance, &discerner);
1565
1566exit:
1567 return error;
1568}
1569
1570#endif // OPENTHREAD_CONFIG_JOINER_ENABLE
rongli90ee0a42018-08-09 02:18:53 +08001571
Yakun Xu8ccf1382018-06-29 00:26:31 +08001572template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_IPV6_ML_PREFIX>(void)
Buke Po818998e2017-08-04 01:19:07 +08001573{
Jonathan Huic1164412018-08-17 08:59:37 -07001574 otError error = OT_ERROR_NONE;
1575 const otMeshLocalPrefix *mlPrefix = otThreadGetMeshLocalPrefix(mInstance);
1576 otIp6Address addr;
Buke Po818998e2017-08-04 01:19:07 +08001577
Jonathan Hui1326d642020-06-17 22:44:54 -07001578 VerifyOrExit(mlPrefix != nullptr, OT_NOOP); // If `mlPrefix` is nullptr send empty response.
Buke Po818998e2017-08-04 01:19:07 +08001579
Jonathan Huic1164412018-08-17 08:59:37 -07001580 memcpy(addr.mFields.m8, mlPrefix->m8, 8);
Buke Po818998e2017-08-04 01:19:07 +08001581
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001582 // Zero out the last 8 bytes.
1583 memset(addr.mFields.m8 + 8, 0, 8);
Buke Po818998e2017-08-04 01:19:07 +08001584
Jintao Lin8788cf52020-01-10 10:15:23 +08001585 SuccessOrExit(error = mEncoder.WriteIp6Address(addr)); // Mesh local prefix
1586 SuccessOrExit(error = mEncoder.WriteUint8(OT_IP6_PREFIX_BITSIZE)); // Prefix length (in bits)
Buke Po818998e2017-08-04 01:19:07 +08001587
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001588exit:
Buke Po818998e2017-08-04 01:19:07 +08001589 return error;
1590}
1591
Yakun Xu8ccf1382018-06-29 00:26:31 +08001592template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_IPV6_ML_PREFIX>(void)
Buke Po818998e2017-08-04 01:19:07 +08001593{
Jonathan Huic1164412018-08-17 08:59:37 -07001594 otError error = OT_ERROR_NONE;
1595 const otIp6Address *meshLocalPrefix;
1596 uint8_t prefixLength;
Buke Po818998e2017-08-04 01:19:07 +08001597
rongli11f32602018-03-20 23:55:41 +08001598 SuccessOrExit(error = mDecoder.ReadIp6Address(meshLocalPrefix));
1599 SuccessOrExit(error = mDecoder.ReadUint8(prefixLength));
Jintao Lin8788cf52020-01-10 10:15:23 +08001600 VerifyOrExit(prefixLength == OT_IP6_PREFIX_BITSIZE, error = OT_ERROR_INVALID_ARGS);
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001601
Jonathan Huic1164412018-08-17 08:59:37 -07001602 error = otThreadSetMeshLocalPrefix(mInstance, reinterpret_cast<const otMeshLocalPrefix *>(meshLocalPrefix));
Buke Po818998e2017-08-04 01:19:07 +08001603
1604exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001605 return error;
Buke Po818998e2017-08-04 01:19:07 +08001606}
1607
Yakun Xu8ccf1382018-06-29 00:26:31 +08001608template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_IPV6_ML_ADDR>(void)
Buke Po818998e2017-08-04 01:19:07 +08001609{
Yakun Xub8333732018-06-21 04:15:13 +08001610 otError error = OT_ERROR_NONE;
1611 const otIp6Address *ml64 = otThreadGetMeshLocalEid(mInstance);
Buke Po818998e2017-08-04 01:19:07 +08001612
Jonathan Hui1326d642020-06-17 22:44:54 -07001613 VerifyOrExit(ml64 != nullptr, OT_NOOP);
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001614 SuccessOrExit(error = mEncoder.WriteIp6Address(*ml64));
Buke Po818998e2017-08-04 01:19:07 +08001615
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001616exit:
Buke Po818998e2017-08-04 01:19:07 +08001617 return error;
1618}
1619
Yakun Xu8ccf1382018-06-29 00:26:31 +08001620template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_IPV6_LL_ADDR>(void)
Buke Po818998e2017-08-04 01:19:07 +08001621{
Yakun Xub8333732018-06-21 04:15:13 +08001622 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001623 const otIp6Address *address = otThreadGetLinkLocalIp6Address(mInstance);
1624
Jonathan Hui1326d642020-06-17 22:44:54 -07001625 VerifyOrExit(address != nullptr, OT_NOOP);
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001626 SuccessOrExit(error = mEncoder.WriteIp6Address(*address));
Buke Po818998e2017-08-04 01:19:07 +08001627
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001628exit:
Buke Po818998e2017-08-04 01:19:07 +08001629 return error;
1630}
1631
Yakun Xu8ccf1382018-06-29 00:26:31 +08001632template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_IPV6_ADDRESS_TABLE>(void)
Buke Po818998e2017-08-04 01:19:07 +08001633{
1634 otError error = OT_ERROR_NONE;
1635
Buke Po818998e2017-08-04 01:19:07 +08001636 for (const otNetifAddress *address = otIp6GetUnicastAddresses(mInstance); address; address = address->mNext)
1637 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001638 SuccessOrExit(error = mEncoder.OpenStruct());
Buke Po818998e2017-08-04 01:19:07 +08001639
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001640 SuccessOrExit(error = mEncoder.WriteIp6Address(address->mAddress));
1641 SuccessOrExit(error = mEncoder.WriteUint8(address->mPrefixLength));
1642 SuccessOrExit(error = mEncoder.WriteUint32(address->mPreferred ? 0xffffffff : 0));
1643 SuccessOrExit(error = mEncoder.WriteUint32(address->mValid ? 0xffffffff : 0));
1644
1645 SuccessOrExit(error = mEncoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08001646 }
1647
Buke Po818998e2017-08-04 01:19:07 +08001648exit:
Buke Po818998e2017-08-04 01:19:07 +08001649 return error;
1650}
1651
Yakun Xu8ccf1382018-06-29 00:26:31 +08001652template <> otError NcpBase::HandlePropertyInsert<SPINEL_PROP_IPV6_ADDRESS_TABLE>(void)
Buke Po818998e2017-08-04 01:19:07 +08001653{
Yakun Xub8333732018-06-21 04:15:13 +08001654 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001655 otNetifAddress netifAddr;
Yakun Xub8333732018-06-21 04:15:13 +08001656 uint32_t preferredLifetime;
1657 uint32_t validLifetime;
Buke Po818998e2017-08-04 01:19:07 +08001658
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001659 SuccessOrExit(error = mDecoder.ReadIp6Address(netifAddr.mAddress));
1660 SuccessOrExit(error = mDecoder.ReadUint8(netifAddr.mPrefixLength));
1661 SuccessOrExit(error = mDecoder.ReadUint32(preferredLifetime));
1662 SuccessOrExit(error = mDecoder.ReadUint32(validLifetime));
Buke Po818998e2017-08-04 01:19:07 +08001663
Markus Beckerbad53a22020-06-16 03:24:14 +02001664 netifAddr.mAddressOrigin = OT_ADDRESS_ORIGIN_MANUAL;
1665 netifAddr.mPreferred = (preferredLifetime != 0);
1666 netifAddr.mValid = (validLifetime != 0);
Buke Po818998e2017-08-04 01:19:07 +08001667
1668 error = otIp6AddUnicastAddress(mInstance, &netifAddr);
1669
Buke Po818998e2017-08-04 01:19:07 +08001670exit:
Buke Po818998e2017-08-04 01:19:07 +08001671 return error;
1672}
1673
Yakun Xu8ccf1382018-06-29 00:26:31 +08001674template <> otError NcpBase::HandlePropertyRemove<SPINEL_PROP_IPV6_ADDRESS_TABLE>(void)
Buke Po818998e2017-08-04 01:19:07 +08001675{
Yakun Xub8333732018-06-21 04:15:13 +08001676 otError error = OT_ERROR_NONE;
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001677 const otIp6Address *addrPtr;
Buke Po818998e2017-08-04 01:19:07 +08001678
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001679 SuccessOrExit(error = mDecoder.ReadIp6Address(addrPtr));
Buke Po818998e2017-08-04 01:19:07 +08001680
1681 error = otIp6RemoveUnicastAddress(mInstance, addrPtr);
Abtin Keshavarzian02bdc692017-08-15 09:11:19 -07001682
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001683 // If address was not on the list, "remove" command is successful.
1684 if (error == OT_ERROR_NOT_FOUND)
Buke Po818998e2017-08-04 01:19:07 +08001685 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001686 error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001687 }
1688
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001689exit:
Buke Po818998e2017-08-04 01:19:07 +08001690 return error;
1691}
1692
Yakun Xu8ccf1382018-06-29 00:26:31 +08001693template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_IPV6_ROUTE_TABLE>(void)
Buke Po818998e2017-08-04 01:19:07 +08001694{
1695 // TODO: Implement get route table
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001696 return mEncoder.OverwriteWithLastStatusError(SPINEL_STATUS_UNIMPLEMENTED);
Buke Po818998e2017-08-04 01:19:07 +08001697}
1698
Yakun Xu8ccf1382018-06-29 00:26:31 +08001699template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_IPV6_ICMP_PING_OFFLOAD>(void)
Buke Po818998e2017-08-04 01:19:07 +08001700{
Jonathan Huif602dcd2018-03-13 18:10:28 +00001701 return mEncoder.WriteBool(otIcmp6GetEchoMode(mInstance) != OT_ICMP6_ECHO_HANDLER_DISABLED);
Buke Po818998e2017-08-04 01:19:07 +08001702}
1703
Yakun Xu8ccf1382018-06-29 00:26:31 +08001704template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_IPV6_ICMP_PING_OFFLOAD>(void)
Buke Po818998e2017-08-04 01:19:07 +08001705{
Yakun Xub8333732018-06-21 04:15:13 +08001706 bool enabled = false;
1707 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001708
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001709 SuccessOrExit(error = mDecoder.ReadBool(enabled));
Buke Po818998e2017-08-04 01:19:07 +08001710
Jonathan Huif602dcd2018-03-13 18:10:28 +00001711 otIcmp6SetEchoMode(mInstance, enabled ? OT_ICMP6_ECHO_HANDLER_ALL : OT_ICMP6_ECHO_HANDLER_DISABLED);
Buke Po818998e2017-08-04 01:19:07 +08001712
1713exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001714 return error;
Buke Po818998e2017-08-04 01:19:07 +08001715}
1716
Yakun Xu8ccf1382018-06-29 00:26:31 +08001717template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE>(void)
Buke Po818998e2017-08-04 01:19:07 +08001718{
Yakun Xub8333732018-06-21 04:15:13 +08001719 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001720 const otNetifMulticastAddress *address;
1721
Buke Po818998e2017-08-04 01:19:07 +08001722 for (address = otIp6GetMulticastAddresses(mInstance); address; address = address->mNext)
1723 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001724 SuccessOrExit(error = mEncoder.OpenStruct());
1725 SuccessOrExit(error = mEncoder.WriteIp6Address(address->mAddress));
1726 SuccessOrExit(error = mEncoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08001727 }
1728
Buke Po818998e2017-08-04 01:19:07 +08001729exit:
Buke Po818998e2017-08-04 01:19:07 +08001730 return error;
1731}
1732
Yakun Xu8ccf1382018-06-29 00:26:31 +08001733template <> otError NcpBase::HandlePropertyInsert<SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE>(void)
Buke Po818998e2017-08-04 01:19:07 +08001734{
Yakun Xub8333732018-06-21 04:15:13 +08001735 otError error = OT_ERROR_NONE;
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001736 const otIp6Address *addrPtr;
Buke Po818998e2017-08-04 01:19:07 +08001737
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001738 SuccessOrExit(error = mDecoder.ReadIp6Address(addrPtr));
Buke Po818998e2017-08-04 01:19:07 +08001739
1740 error = otIp6SubscribeMulticastAddress(mInstance, addrPtr);
Abtin Keshavarzian02bdc692017-08-15 09:11:19 -07001741
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001742 if (error == OT_ERROR_ALREADY)
Buke Po818998e2017-08-04 01:19:07 +08001743 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001744 error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001745 }
1746
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001747exit:
Buke Po818998e2017-08-04 01:19:07 +08001748 return error;
1749}
1750
Yakun Xu8ccf1382018-06-29 00:26:31 +08001751template <> otError NcpBase::HandlePropertyRemove<SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE>(void)
Buke Po818998e2017-08-04 01:19:07 +08001752{
Yakun Xub8333732018-06-21 04:15:13 +08001753 otError error = OT_ERROR_NONE;
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001754 const otIp6Address *addrPtr;
Buke Po818998e2017-08-04 01:19:07 +08001755
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001756 SuccessOrExit(error = mDecoder.ReadIp6Address(addrPtr));
Buke Po818998e2017-08-04 01:19:07 +08001757
1758 error = otIp6UnsubscribeMulticastAddress(mInstance, addrPtr);
Abtin Keshavarzian02bdc692017-08-15 09:11:19 -07001759
1760 // If the address was not on the list, "remove" command is successful,
1761 // and we respond with a `SPINEL_STATUS_OK` status.
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001762 if (error == OT_ERROR_NOT_FOUND)
Buke Po818998e2017-08-04 01:19:07 +08001763 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001764 error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001765 }
1766
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001767exit:
Buke Po818998e2017-08-04 01:19:07 +08001768 return error;
1769}
1770
Yakun Xu8ccf1382018-06-29 00:26:31 +08001771template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_IPV6_ICMP_PING_OFFLOAD_MODE>(void)
Jonathan Huif602dcd2018-03-13 18:10:28 +00001772{
1773 spinel_ipv6_icmp_ping_offload_mode_t mode = SPINEL_IPV6_ICMP_PING_OFFLOAD_DISABLED;
1774
1775 switch (otIcmp6GetEchoMode(mInstance))
1776 {
1777 case OT_ICMP6_ECHO_HANDLER_DISABLED:
1778 mode = SPINEL_IPV6_ICMP_PING_OFFLOAD_DISABLED;
1779 break;
1780 case OT_ICMP6_ECHO_HANDLER_UNICAST_ONLY:
1781 mode = SPINEL_IPV6_ICMP_PING_OFFLOAD_UNICAST_ONLY;
1782 break;
1783 case OT_ICMP6_ECHO_HANDLER_MULTICAST_ONLY:
1784 mode = SPINEL_IPV6_ICMP_PING_OFFLOAD_MULTICAST_ONLY;
1785 break;
1786 case OT_ICMP6_ECHO_HANDLER_ALL:
1787 mode = SPINEL_IPV6_ICMP_PING_OFFLOAD_ALL;
1788 break;
1789 };
1790
1791 return mEncoder.WriteUint8(mode);
1792}
1793
Yakun Xu8ccf1382018-06-29 00:26:31 +08001794template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_IPV6_ICMP_PING_OFFLOAD_MODE>(void)
Jonathan Huif602dcd2018-03-13 18:10:28 +00001795{
Yakun Xub8333732018-06-21 04:15:13 +08001796 otError error = OT_ERROR_NONE;
1797 otIcmp6EchoMode mode = OT_ICMP6_ECHO_HANDLER_DISABLED;
1798 uint8_t spinelMode;
Jonathan Huif602dcd2018-03-13 18:10:28 +00001799
1800 SuccessOrExit(error = mDecoder.ReadUint8(spinelMode));
1801
1802 switch (spinelMode)
1803 {
1804 case SPINEL_IPV6_ICMP_PING_OFFLOAD_DISABLED:
1805 mode = OT_ICMP6_ECHO_HANDLER_DISABLED;
1806 break;
1807 case SPINEL_IPV6_ICMP_PING_OFFLOAD_UNICAST_ONLY:
1808 mode = OT_ICMP6_ECHO_HANDLER_UNICAST_ONLY;
1809 break;
1810 case SPINEL_IPV6_ICMP_PING_OFFLOAD_MULTICAST_ONLY:
1811 mode = OT_ICMP6_ECHO_HANDLER_MULTICAST_ONLY;
1812 break;
1813 case SPINEL_IPV6_ICMP_PING_OFFLOAD_ALL:
1814 mode = OT_ICMP6_ECHO_HANDLER_ALL;
1815 break;
1816 };
1817
1818 otIcmp6SetEchoMode(mInstance, mode);
1819
1820exit:
1821 return error;
1822}
1823
Yakun Xu8ccf1382018-06-29 00:26:31 +08001824template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_RLOC16_DEBUG_PASSTHRU>(void)
Buke Po818998e2017-08-04 01:19:07 +08001825{
1826 // Note reverse logic: passthru enabled = filter disabled
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001827 return mEncoder.WriteBool(!otIp6IsReceiveFilterEnabled(mInstance));
Buke Po818998e2017-08-04 01:19:07 +08001828}
1829
Yakun Xu8ccf1382018-06-29 00:26:31 +08001830template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_RLOC16_DEBUG_PASSTHRU>(void)
Buke Po818998e2017-08-04 01:19:07 +08001831{
Yakun Xub8333732018-06-21 04:15:13 +08001832 bool enabled = false;
1833 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001834
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001835 SuccessOrExit(error = mDecoder.ReadBool(enabled));
Buke Po818998e2017-08-04 01:19:07 +08001836
1837 // Note reverse logic: passthru enabled = filter disabled
1838 otIp6SetReceiveFilterEnabled(mInstance, !enabled);
1839
1840exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001841 return error;
Buke Po818998e2017-08-04 01:19:07 +08001842}
1843
Yakun Xu8ccf1382018-06-29 00:26:31 +08001844template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_OFF_MESH_ROUTES>(void)
Buke Po818998e2017-08-04 01:19:07 +08001845{
Yakun Xub8333732018-06-21 04:15:13 +08001846 otError error = OT_ERROR_NONE;
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001847 otExternalRouteConfig routeConfig;
Buke Po818998e2017-08-04 01:19:07 +08001848 otNetworkDataIterator iter = OT_NETWORK_DATA_ITERATOR_INIT;
1849
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001850 while (otNetDataGetNextRoute(mInstance, &iter, &routeConfig) == OT_ERROR_NONE)
Buke Po818998e2017-08-04 01:19:07 +08001851 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001852 SuccessOrExit(error = mEncoder.OpenStruct());
1853
1854 SuccessOrExit(error = mEncoder.WriteIp6Address(routeConfig.mPrefix.mPrefix));
1855 SuccessOrExit(error = mEncoder.WriteUint8(routeConfig.mPrefix.mLength));
1856 SuccessOrExit(error = mEncoder.WriteBool(routeConfig.mStable));
1857 SuccessOrExit(error = mEncoder.WriteUint8(ExternalRoutePreferenceToFlagByte(routeConfig.mPreference)));
Yakun Xub8333732018-06-21 04:15:13 +08001858 SuccessOrExit(error = mEncoder.WriteBool(false)); // IsLocal
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001859 SuccessOrExit(error = mEncoder.WriteBool(routeConfig.mNextHopIsThisDevice));
1860 SuccessOrExit(error = mEncoder.WriteUint16(routeConfig.mRloc16));
1861
1862 SuccessOrExit(error = mEncoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08001863 }
1864
Jonathan Huif1849732019-07-16 12:31:11 -07001865#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
Abtin Keshavarzian2c8f50b2017-09-01 21:27:58 -07001866
1867 iter = OT_NETWORK_DATA_ITERATOR_INIT;
1868
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001869 while (otBorderRouterGetNextRoute(mInstance, &iter, &routeConfig) == OT_ERROR_NONE)
Buke Po818998e2017-08-04 01:19:07 +08001870 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001871 SuccessOrExit(error = mEncoder.OpenStruct());
1872
1873 SuccessOrExit(error = mEncoder.WriteIp6Address(routeConfig.mPrefix.mPrefix));
1874 SuccessOrExit(error = mEncoder.WriteUint8(routeConfig.mPrefix.mLength));
1875 SuccessOrExit(error = mEncoder.WriteBool(routeConfig.mStable));
1876 SuccessOrExit(error = mEncoder.WriteUint8(ExternalRoutePreferenceToFlagByte(routeConfig.mPreference)));
Yakun Xub8333732018-06-21 04:15:13 +08001877 SuccessOrExit(error = mEncoder.WriteBool(true)); // IsLocal
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001878 SuccessOrExit(error = mEncoder.WriteBool(routeConfig.mNextHopIsThisDevice));
1879 SuccessOrExit(error = mEncoder.WriteUint16(routeConfig.mRloc16));
1880
1881 SuccessOrExit(error = mEncoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08001882 }
Jonathan Huif1849732019-07-16 12:31:11 -07001883#endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08001884
Buke Po818998e2017-08-04 01:19:07 +08001885exit:
Buke Po818998e2017-08-04 01:19:07 +08001886 return error;
1887}
1888
Jonathan Huif1849732019-07-16 12:31:11 -07001889#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08001890static int FlagByteToExternalRoutePreference(uint8_t aFlags)
1891{
1892 int route_preference = 0;
1893
1894 switch (aFlags & SPINEL_NET_FLAG_PREFERENCE_MASK)
1895 {
1896 case SPINEL_ROUTE_PREFERENCE_HIGH:
1897 route_preference = OT_ROUTE_PREFERENCE_HIGH;
1898 break;
1899
1900 case SPINEL_ROUTE_PREFERENCE_MEDIUM:
1901 route_preference = OT_ROUTE_PREFERENCE_MED;
1902 break;
1903
1904 case SPINEL_ROUTE_PREFERENCE_LOW:
1905 route_preference = OT_ROUTE_PREFERENCE_LOW;
1906 break;
1907 }
1908
1909 return route_preference;
1910}
1911
Yakun Xu8ccf1382018-06-29 00:26:31 +08001912template <> otError NcpBase::HandlePropertyInsert<SPINEL_PROP_THREAD_OFF_MESH_ROUTES>(void)
Buke Po818998e2017-08-04 01:19:07 +08001913{
Yakun Xub8333732018-06-21 04:15:13 +08001914 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001915 otExternalRouteConfig routeConfig;
Yakun Xub8333732018-06-21 04:15:13 +08001916 bool stable = false;
1917 uint8_t flags = 0;
1918 uint8_t prefixLength;
Buke Po818998e2017-08-04 01:19:07 +08001919
1920 memset(&routeConfig, 0, sizeof(otExternalRouteConfig));
1921
Abtin Keshavarzian31ce3d42019-08-01 10:30:08 -07001922 VerifyOrExit(mAllowLocalNetworkDataChange, error = OT_ERROR_INVALID_STATE);
Buke Po818998e2017-08-04 01:19:07 +08001923
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001924 SuccessOrExit(error = mDecoder.ReadIp6Address(routeConfig.mPrefix.mPrefix));
Łukasz Duda7b084ec2017-10-25 17:54:17 +02001925 SuccessOrExit(error = mDecoder.ReadUint8(prefixLength));
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001926 SuccessOrExit(error = mDecoder.ReadBool(stable));
1927 SuccessOrExit(error = mDecoder.ReadUint8(flags));
Buke Po818998e2017-08-04 01:19:07 +08001928
Łukasz Duda7b084ec2017-10-25 17:54:17 +02001929 routeConfig.mPrefix.mLength = prefixLength;
Yakun Xub8333732018-06-21 04:15:13 +08001930 routeConfig.mStable = stable;
1931 routeConfig.mPreference = FlagByteToExternalRoutePreference(flags);
Buke Po818998e2017-08-04 01:19:07 +08001932
1933 error = otBorderRouterAddRoute(mInstance, &routeConfig);
Buke Po818998e2017-08-04 01:19:07 +08001934
1935exit:
Buke Po818998e2017-08-04 01:19:07 +08001936 return error;
1937}
1938
Yakun Xu8ccf1382018-06-29 00:26:31 +08001939template <> otError NcpBase::HandlePropertyRemove<SPINEL_PROP_THREAD_OFF_MESH_ROUTES>(void)
Buke Po818998e2017-08-04 01:19:07 +08001940{
Yakun Xub8333732018-06-21 04:15:13 +08001941 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001942 otIp6Prefix ip6Prefix;
Yakun Xub8333732018-06-21 04:15:13 +08001943 uint8_t prefixLength;
Buke Po818998e2017-08-04 01:19:07 +08001944
1945 memset(&ip6Prefix, 0, sizeof(otIp6Prefix));
1946
Abtin Keshavarzian31ce3d42019-08-01 10:30:08 -07001947 VerifyOrExit(mAllowLocalNetworkDataChange, error = OT_ERROR_INVALID_STATE);
Buke Po818998e2017-08-04 01:19:07 +08001948
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001949 SuccessOrExit(error = mDecoder.ReadIp6Address(ip6Prefix.mPrefix));
Łukasz Duda7b084ec2017-10-25 17:54:17 +02001950 SuccessOrExit(error = mDecoder.ReadUint8(prefixLength));
1951
1952 ip6Prefix.mLength = prefixLength;
Buke Po818998e2017-08-04 01:19:07 +08001953
1954 error = otBorderRouterRemoveRoute(mInstance, &ip6Prefix);
Abtin Keshavarzian02bdc692017-08-15 09:11:19 -07001955
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001956 // If the route prefix was not on the list, "remove" command is successful.
1957 if (error == OT_ERROR_NOT_FOUND)
Buke Po818998e2017-08-04 01:19:07 +08001958 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001959 error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001960 }
1961
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07001962exit:
Buke Po818998e2017-08-04 01:19:07 +08001963 return error;
1964}
Jonathan Huif1849732019-07-16 12:31:11 -07001965#endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08001966
Yakun Xu8ccf1382018-06-29 00:26:31 +08001967template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_STREAM_NET>(void)
Buke Po818998e2017-08-04 01:19:07 +08001968{
Jonathan Hui1326d642020-06-17 22:44:54 -07001969 const uint8_t *framePtr = nullptr;
Yakun Xub8333732018-06-21 04:15:13 +08001970 uint16_t frameLen = 0;
Jonathan Hui1326d642020-06-17 22:44:54 -07001971 const uint8_t *metaPtr = nullptr;
Yakun Xub8333732018-06-21 04:15:13 +08001972 uint16_t metaLen = 0;
Jonathan Hui1326d642020-06-17 22:44:54 -07001973 otMessage * message = nullptr;
Yakun Xub8333732018-06-21 04:15:13 +08001974 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08001975
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07001976 SuccessOrExit(error = mDecoder.ReadDataWithLen(framePtr, frameLen));
1977 SuccessOrExit(error = mDecoder.ReadData(metaPtr, metaLen));
Buke Po818998e2017-08-04 01:19:07 +08001978
1979 // We ignore metadata for now.
1980 // May later include TX power, allow retransmits, etc...
Buke Po818998e2017-08-04 01:19:07 +08001981
Zhanglong Xia19f25332018-12-20 05:55:26 +08001982 // STREAM_NET requires layer 2 security.
Jonathan Hui1326d642020-06-17 22:44:54 -07001983 message = otIp6NewMessageFromBuffer(mInstance, framePtr, frameLen, nullptr);
1984 VerifyOrExit(message != nullptr, error = OT_ERROR_NO_BUFS);
Buke Po818998e2017-08-04 01:19:07 +08001985
1986 error = otIp6Send(mInstance, message);
1987
Buke Po818998e2017-08-04 01:19:07 +08001988exit:
1989
Buke Po818998e2017-08-04 01:19:07 +08001990 if (error == OT_ERROR_NONE)
1991 {
1992 mInboundSecureIpFrameCounter++;
Buke Po818998e2017-08-04 01:19:07 +08001993 }
1994 else
1995 {
1996 mDroppedInboundIpFrameCounter++;
Buke Po818998e2017-08-04 01:19:07 +08001997 }
1998
Buke Po818998e2017-08-04 01:19:07 +08001999 return error;
2000}
2001
Jonathan Hui02da2062019-07-16 12:18:34 -07002002#if OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08002003
Yakun Xu8ccf1382018-06-29 00:26:31 +08002004template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_JAM_DETECT_ENABLE>(void)
Buke Po818998e2017-08-04 01:19:07 +08002005{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002006 return mEncoder.WriteBool(otJamDetectionIsEnabled(mInstance));
Buke Po818998e2017-08-04 01:19:07 +08002007}
2008
Yakun Xu8ccf1382018-06-29 00:26:31 +08002009template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_JAM_DETECTED>(void)
Buke Po818998e2017-08-04 01:19:07 +08002010{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002011 return mEncoder.WriteBool(otJamDetectionGetState(mInstance));
Buke Po818998e2017-08-04 01:19:07 +08002012}
2013
Yakun Xu8ccf1382018-06-29 00:26:31 +08002014template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_JAM_DETECT_RSSI_THRESHOLD>(void)
Buke Po818998e2017-08-04 01:19:07 +08002015{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002016 return mEncoder.WriteInt8(otJamDetectionGetRssiThreshold(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_WINDOW>(void)
Buke Po818998e2017-08-04 01:19:07 +08002020{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002021 return mEncoder.WriteUint8(otJamDetectionGetWindow(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_BUSY>(void)
Buke Po818998e2017-08-04 01:19:07 +08002025{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002026 return mEncoder.WriteUint8(otJamDetectionGetBusyPeriod(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_HISTORY_BITMAP>(void)
Buke Po818998e2017-08-04 01:19:07 +08002030{
Abtin Keshavarzian07f4ae12017-12-07 10:22:24 -08002031 return mEncoder.WriteUint64(otJamDetectionGetHistoryBitmap(mInstance));
Buke Po818998e2017-08-04 01:19:07 +08002032}
2033
Yakun Xu8ccf1382018-06-29 00:26:31 +08002034template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_JAM_DETECT_ENABLE>(void)
Buke Po818998e2017-08-04 01:19:07 +08002035{
Yakun Xub8333732018-06-21 04:15:13 +08002036 bool enabled;
Buke Po818998e2017-08-04 01:19:07 +08002037 otError error = OT_ERROR_NONE;
2038
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002039 SuccessOrExit(error = mDecoder.ReadBool(enabled));
Buke Po818998e2017-08-04 01:19:07 +08002040
2041 if (enabled)
2042 {
kangping49f36f82020-05-07 02:17:58 +08002043 IgnoreError(otJamDetectionStart(mInstance, &NcpBase::HandleJamStateChange_Jump, this));
Buke Po818998e2017-08-04 01:19:07 +08002044 }
2045 else
2046 {
kangping49f36f82020-05-07 02:17:58 +08002047 IgnoreError(otJamDetectionStop(mInstance));
Buke Po818998e2017-08-04 01:19:07 +08002048 }
2049
2050exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002051 return error;
Buke Po818998e2017-08-04 01:19:07 +08002052}
2053
Yakun Xu8ccf1382018-06-29 00:26:31 +08002054template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_JAM_DETECT_RSSI_THRESHOLD>(void)
Buke Po818998e2017-08-04 01:19:07 +08002055{
Yakun Xub8333732018-06-21 04:15:13 +08002056 int8_t threshold = 0;
2057 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08002058
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002059 SuccessOrExit(error = mDecoder.ReadInt8(threshold));
Buke Po818998e2017-08-04 01:19:07 +08002060
2061 error = otJamDetectionSetRssiThreshold(mInstance, threshold);
2062
2063exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002064 return error;
Buke Po818998e2017-08-04 01:19:07 +08002065}
2066
Yakun Xu8ccf1382018-06-29 00:26:31 +08002067template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_JAM_DETECT_WINDOW>(void)
Buke Po818998e2017-08-04 01:19:07 +08002068{
2069 uint8_t window = 0;
Yakun Xub8333732018-06-21 04:15:13 +08002070 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08002071
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002072 SuccessOrExit(error = mDecoder.ReadUint8(window));
Buke Po818998e2017-08-04 01:19:07 +08002073
2074 error = otJamDetectionSetWindow(mInstance, window);
2075
2076exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002077 return error;
Buke Po818998e2017-08-04 01:19:07 +08002078}
2079
Yakun Xu8ccf1382018-06-29 00:26:31 +08002080template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_JAM_DETECT_BUSY>(void)
Buke Po818998e2017-08-04 01:19:07 +08002081{
Yakun Xub8333732018-06-21 04:15:13 +08002082 uint8_t busy = 0;
Buke Po818998e2017-08-04 01:19:07 +08002083 otError error = OT_ERROR_NONE;
2084
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002085 SuccessOrExit(error = mDecoder.ReadUint8(busy));
Buke Po818998e2017-08-04 01:19:07 +08002086
2087 error = otJamDetectionSetBusyPeriod(mInstance, busy);
2088
2089exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002090 return error;
Buke Po818998e2017-08-04 01:19:07 +08002091}
2092
2093void NcpBase::HandleJamStateChange_Jump(bool aJamState, void *aContext)
2094{
2095 static_cast<NcpBase *>(aContext)->HandleJamStateChange(aJamState);
2096}
2097
2098void NcpBase::HandleJamStateChange(bool aJamState)
2099{
2100 OT_UNUSED_VARIABLE(aJamState);
2101
2102 mChangedPropsSet.AddProperty(SPINEL_PROP_JAM_DETECTED);
Abtin Keshavarziana1adaac2020-05-11 10:24:58 -07002103 mUpdateChangedPropsTask.Post();
Buke Po818998e2017-08-04 01:19:07 +08002104}
2105
Jonathan Hui02da2062019-07-16 12:18:34 -07002106#endif // OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08002107
Jonathan Huiaa823912019-07-15 12:03:36 -07002108#if OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE
Abtin Keshavarzian1ca81fb2018-08-02 15:21:11 -07002109
2110template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHILD_SUPERVISION_CHECK_TIMEOUT>(void)
2111{
2112 return mEncoder.WriteUint16(otChildSupervisionGetCheckTimeout(mInstance));
2113}
2114
2115template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_CHILD_SUPERVISION_CHECK_TIMEOUT>(void)
2116{
2117 otError error = OT_ERROR_NONE;
2118 uint16_t timeout;
2119
2120 SuccessOrExit(error = mDecoder.ReadUint16(timeout));
2121 otChildSupervisionSetCheckTimeout(mInstance, timeout);
2122
2123exit:
2124 return error;
2125}
2126
Jonathan Huiaa823912019-07-15 12:03:36 -07002127#endif // OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE
Abtin Keshavarzian1ca81fb2018-08-02 15:21:11 -07002128
Jonathan Hui01ebc182019-07-12 15:21:49 -07002129#if OPENTHREAD_CONFIG_CHANNEL_MONITOR_ENABLE
Abtin Keshavarzianba5317a2018-01-13 13:37:04 -08002130
Yakun Xu8ccf1382018-06-29 00:26:31 +08002131template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHANNEL_MONITOR_SAMPLE_INTERVAL>(void)
Abtin Keshavarzianba5317a2018-01-13 13:37:04 -08002132{
2133 return mEncoder.WriteUint32(otChannelMonitorGetSampleInterval(mInstance));
2134}
2135
Yakun Xu8ccf1382018-06-29 00:26:31 +08002136template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHANNEL_MONITOR_RSSI_THRESHOLD>(void)
Abtin Keshavarzianba5317a2018-01-13 13:37:04 -08002137{
2138 return mEncoder.WriteInt8(otChannelMonitorGetRssiThreshold(mInstance));
2139}
2140
Yakun Xu8ccf1382018-06-29 00:26:31 +08002141template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHANNEL_MONITOR_SAMPLE_WINDOW>(void)
Abtin Keshavarzianba5317a2018-01-13 13:37:04 -08002142{
2143 return mEncoder.WriteUint32(otChannelMonitorGetSampleWindow(mInstance));
2144}
2145
Yakun Xu8ccf1382018-06-29 00:26:31 +08002146template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHANNEL_MONITOR_SAMPLE_COUNT>(void)
Abtin Keshavarzianba5317a2018-01-13 13:37:04 -08002147{
2148 return mEncoder.WriteUint32(otChannelMonitorGetSampleCount(mInstance));
2149}
2150
Yakun Xu8ccf1382018-06-29 00:26:31 +08002151template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHANNEL_MONITOR_CHANNEL_OCCUPANCY>(void)
Abtin Keshavarzianba5317a2018-01-13 13:37:04 -08002152{
Shu Chena43a2632019-04-09 12:25:16 +08002153 otError error = OT_ERROR_NONE;
2154 uint32_t channelMask = otLinkGetSupportedChannelMask(mInstance);
2155 uint8_t channelNum = sizeof(channelMask) * CHAR_BIT;
Abtin Keshavarzianba5317a2018-01-13 13:37:04 -08002156
Shu Chena43a2632019-04-09 12:25:16 +08002157 for (uint8_t channel = 0; channel < channelNum; channel++)
Abtin Keshavarzianba5317a2018-01-13 13:37:04 -08002158 {
Shu Chena43a2632019-04-09 12:25:16 +08002159 if (!((1UL << channel) & channelMask))
2160 {
2161 continue;
2162 }
2163
Abtin Keshavarzianba5317a2018-01-13 13:37:04 -08002164 SuccessOrExit(error = mEncoder.OpenStruct());
2165
2166 SuccessOrExit(error = mEncoder.WriteUint8(channel));
Abtin Keshavarziandf452402018-04-16 11:17:09 -07002167 SuccessOrExit(error = mEncoder.WriteUint16(otChannelMonitorGetChannelOccupancy(mInstance, channel)));
Abtin Keshavarzianba5317a2018-01-13 13:37:04 -08002168
2169 SuccessOrExit(error = mEncoder.CloseStruct());
2170 }
2171
2172exit:
2173 return error;
2174}
2175
Jonathan Hui01ebc182019-07-12 15:21:49 -07002176#endif // OPENTHREAD_CONFIG_CHANNEL_MONITOR_ENABLE
Abtin Keshavarzianba5317a2018-01-13 13:37:04 -08002177
Yakun Xu8ccf1382018-06-29 00:26:31 +08002178template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_CCA_FAILURE_RATE>(void)
Abtin Keshavarzian171c9512018-01-23 09:10:13 -08002179{
2180 return mEncoder.WriteUint16(otLinkGetCcaFailureRate(mInstance));
2181}
2182
Yakun Xu8ccf1382018-06-29 00:26:31 +08002183template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_PKT_TOTAL>(void)
Buke Po818998e2017-08-04 01:19:07 +08002184{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002185 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxTotal);
Buke Po818998e2017-08-04 01:19:07 +08002186}
2187
Yakun Xu8ccf1382018-06-29 00:26:31 +08002188template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_PKT_ACK_REQ>(void)
Buke Po818998e2017-08-04 01:19:07 +08002189{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002190 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxAckRequested);
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_ACKED>(void)
Buke Po818998e2017-08-04 01:19:07 +08002194{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002195 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxAcked);
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_NO_ACK_REQ>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002199{
2200 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxNoAckRequested);
2201}
2202
Yakun Xu8ccf1382018-06-29 00:26:31 +08002203template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_PKT_DATA>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002204{
2205 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxData);
2206}
2207
Yakun Xu8ccf1382018-06-29 00:26:31 +08002208template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_PKT_DATA_POLL>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002209{
2210 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxDataPoll);
2211}
2212
Yakun Xu8ccf1382018-06-29 00:26:31 +08002213template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_PKT_BEACON>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002214{
2215 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxBeacon);
2216}
2217
Yakun Xu8ccf1382018-06-29 00:26:31 +08002218template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_PKT_BEACON_REQ>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002219{
2220 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxBeaconRequest);
2221}
2222
Yakun Xu8ccf1382018-06-29 00:26:31 +08002223template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_PKT_OTHER>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002224{
2225 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxOther);
2226}
2227
Yakun Xu8ccf1382018-06-29 00:26:31 +08002228template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_PKT_RETRY>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002229{
2230 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxRetry);
2231}
2232
Yakun Xu8ccf1382018-06-29 00:26:31 +08002233template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_ERR_CCA>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002234{
2235 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxErrCca);
2236}
2237
Yakun Xu8ccf1382018-06-29 00:26:31 +08002238template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_PKT_UNICAST>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002239{
2240 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxUnicast);
2241}
2242
Yakun Xu8ccf1382018-06-29 00:26:31 +08002243template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_PKT_BROADCAST>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002244{
2245 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxBroadcast);
2246}
2247
Yakun Xu8ccf1382018-06-29 00:26:31 +08002248template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_ERR_ABORT>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002249{
2250 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mTxErrAbort);
2251}
2252
Yakun Xu8ccf1382018-06-29 00:26:31 +08002253template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_PKT_TOTAL>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002254{
2255 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxTotal);
2256}
2257
Yakun Xu8ccf1382018-06-29 00:26:31 +08002258template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_PKT_DATA>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002259{
2260 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxData);
2261}
2262
Yakun Xu8ccf1382018-06-29 00:26:31 +08002263template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_PKT_DATA_POLL>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002264{
2265 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxDataPoll);
2266}
2267
Yakun Xu8ccf1382018-06-29 00:26:31 +08002268template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_PKT_BEACON>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002269{
2270 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxBeacon);
2271}
2272
Yakun Xu8ccf1382018-06-29 00:26:31 +08002273template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_PKT_BEACON_REQ>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002274{
2275 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxBeaconRequest);
2276}
2277
Yakun Xu8ccf1382018-06-29 00:26:31 +08002278template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_PKT_OTHER>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002279{
2280 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxOther);
2281}
2282
Yakun Xu8ccf1382018-06-29 00:26:31 +08002283template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_PKT_FILT_WL>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002284{
ronglib1baa7d2017-10-14 00:33:23 +08002285 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxAddressFiltered);
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002286}
2287
Yakun Xu8ccf1382018-06-29 00:26:31 +08002288template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_PKT_FILT_DA>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002289{
2290 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxDestAddrFiltered);
2291}
2292
Yakun Xu8ccf1382018-06-29 00:26:31 +08002293template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_PKT_DUP>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002294{
2295 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxDuplicated);
2296}
2297
Yakun Xu8ccf1382018-06-29 00:26:31 +08002298template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_PKT_UNICAST>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002299{
2300 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxUnicast);
2301}
2302
Yakun Xu8ccf1382018-06-29 00:26:31 +08002303template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_PKT_BROADCAST>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002304{
2305 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxBroadcast);
2306}
2307
Yakun Xu8ccf1382018-06-29 00:26:31 +08002308template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_ERR_EMPTY>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002309{
2310 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxErrNoFrame);
2311}
2312
Yakun Xu8ccf1382018-06-29 00:26:31 +08002313template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_ERR_UKWN_NBR>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002314{
2315 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxErrUnknownNeighbor);
2316}
2317
Yakun Xu8ccf1382018-06-29 00:26:31 +08002318template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_ERR_NVLD_SADDR>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002319{
2320 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxErrInvalidSrcAddr);
2321}
2322
Yakun Xu8ccf1382018-06-29 00:26:31 +08002323template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_ERR_SECURITY>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002324{
2325 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxErrSec);
2326}
2327
Yakun Xu8ccf1382018-06-29 00:26:31 +08002328template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_ERR_BAD_FCS>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002329{
2330 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxErrFcs);
2331}
2332
Yakun Xu8ccf1382018-06-29 00:26:31 +08002333template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_ERR_OTHER>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002334{
2335 return mEncoder.WriteUint32(otLinkGetCounters(mInstance)->mRxErrOther);
2336}
2337
Yakun Xu8ccf1382018-06-29 00:26:31 +08002338template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_IP_SEC_TOTAL>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002339{
2340 return mEncoder.WriteUint32(mInboundSecureIpFrameCounter);
2341}
2342
Yakun Xu8ccf1382018-06-29 00:26:31 +08002343template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_IP_INSEC_TOTAL>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002344{
2345 return mEncoder.WriteUint32(mInboundInsecureIpFrameCounter);
2346}
2347
Yakun Xu8ccf1382018-06-29 00:26:31 +08002348template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_IP_DROPPED>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002349{
2350 return mEncoder.WriteUint32(mDroppedInboundIpFrameCounter);
2351}
2352
Yakun Xu8ccf1382018-06-29 00:26:31 +08002353template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_IP_SEC_TOTAL>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002354{
2355 return mEncoder.WriteUint32(mOutboundSecureIpFrameCounter);
2356}
2357
Yakun Xu8ccf1382018-06-29 00:26:31 +08002358template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_IP_INSEC_TOTAL>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002359{
2360 return mEncoder.WriteUint32(mOutboundInsecureIpFrameCounter);
2361}
2362
Yakun Xu8ccf1382018-06-29 00:26:31 +08002363template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_IP_DROPPED>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002364{
2365 return mEncoder.WriteUint32(mDroppedOutboundIpFrameCounter);
2366}
2367
Yakun Xu8ccf1382018-06-29 00:26:31 +08002368template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_TX_SPINEL_TOTAL>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002369{
2370 return mEncoder.WriteUint32(mTxSpinelFrameCounter);
2371}
2372
Yakun Xu8ccf1382018-06-29 00:26:31 +08002373template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_SPINEL_TOTAL>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002374{
2375 return mEncoder.WriteUint32(mRxSpinelFrameCounter);
2376}
2377
Yakun Xu8ccf1382018-06-29 00:26:31 +08002378template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_SPINEL_OUT_OF_ORDER_TID>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002379{
2380 return mEncoder.WriteUint32(mRxSpinelOutOfOrderTidCounter);
2381}
2382
Yakun Xu8ccf1382018-06-29 00:26:31 +08002383template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_RX_SPINEL_ERR>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002384{
2385 return mEncoder.WriteUint32(mFramingErrorCounter);
2386}
2387
Yakun Xu8ccf1382018-06-29 00:26:31 +08002388template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_IP_TX_SUCCESS>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002389{
2390 return mEncoder.WriteUint32(otThreadGetIp6Counters(mInstance)->mTxSuccess);
2391}
2392
Yakun Xu8ccf1382018-06-29 00:26:31 +08002393template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_IP_RX_SUCCESS>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002394{
2395 return mEncoder.WriteUint32(otThreadGetIp6Counters(mInstance)->mRxSuccess);
2396}
2397
Yakun Xu8ccf1382018-06-29 00:26:31 +08002398template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_IP_TX_FAILURE>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002399{
2400 return mEncoder.WriteUint32(otThreadGetIp6Counters(mInstance)->mTxFailure);
2401}
2402
Yakun Xu8ccf1382018-06-29 00:26:31 +08002403template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_IP_RX_FAILURE>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002404{
2405 return mEncoder.WriteUint32(otThreadGetIp6Counters(mInstance)->mRxFailure);
2406}
2407
Yakun Xu8ccf1382018-06-29 00:26:31 +08002408template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MSG_BUFFER_COUNTERS>(void)
Buke Po818998e2017-08-04 01:19:07 +08002409{
Yakun Xub8333732018-06-21 04:15:13 +08002410 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08002411 otBufferInfo bufferInfo;
2412
2413 otMessageGetBufferInfo(mInstance, &bufferInfo);
2414
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002415 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mTotalBuffers));
2416 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mFreeBuffers));
2417 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.m6loSendMessages));
2418 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.m6loSendBuffers));
2419 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.m6loReassemblyMessages));
2420 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.m6loReassemblyBuffers));
2421 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mIp6Messages));
2422 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mIp6Buffers));
2423 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mMplMessages));
2424 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mMplBuffers));
2425 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mMleMessages));
2426 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mMleBuffers));
2427 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mArpMessages));
2428 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mArpBuffers));
2429 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mCoapMessages));
2430 SuccessOrExit(mEncoder.WriteUint16(bufferInfo.mCoapBuffers));
Buke Po818998e2017-08-04 01:19:07 +08002431
2432exit:
2433 return error;
2434}
2435
Yakun Xu8ccf1382018-06-29 00:26:31 +08002436template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_ALL_MAC_COUNTERS>(void)
Abtin Keshavarzian23069bb2018-01-23 09:00:27 -08002437{
Yakun Xub8333732018-06-21 04:15:13 +08002438 otError error = OT_ERROR_NONE;
Abtin Keshavarzian23069bb2018-01-23 09:00:27 -08002439 const otMacCounters *counters = otLinkGetCounters(mInstance);
2440
Abtin Keshavarzian23069bb2018-01-23 09:00:27 -08002441 // Encode Tx related counters
2442 SuccessOrExit(error = mEncoder.OpenStruct());
2443 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxTotal));
2444 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxUnicast));
2445 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxBroadcast));
2446 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxAckRequested));
2447 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxAcked));
2448 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxNoAckRequested));
2449 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxData));
2450 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxDataPoll));
2451 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxBeacon));
2452 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxBeaconRequest));
2453 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxOther));
2454 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxRetry));
2455 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxErrCca));
2456 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxErrAbort));
2457 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxErrBusyChannel));
Paweł Wańczykc646e6f2019-12-18 19:23:43 +01002458 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxDirectMaxRetryExpiry));
2459 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxIndirectMaxRetryExpiry));
Abtin Keshavarzian23069bb2018-01-23 09:00:27 -08002460 SuccessOrExit(error = mEncoder.CloseStruct());
2461
2462 // Encode Rx related counters
2463 SuccessOrExit(error = mEncoder.OpenStruct());
2464 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxTotal));
2465 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxUnicast));
2466 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxBroadcast));
2467 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxData));
2468 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxDataPoll));
2469 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxBeacon));
2470 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxBeaconRequest));
2471 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxOther));
2472 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxAddressFiltered));
2473 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxDestAddrFiltered));
2474 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxDuplicated));
2475 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxErrNoFrame));
2476 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxErrUnknownNeighbor));
2477 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxErrInvalidSrcAddr));
2478 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxErrSec));
2479 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxErrFcs));
2480 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxErrOther));
2481 SuccessOrExit(error = mEncoder.CloseStruct());
2482
2483exit:
2484 return error;
2485}
2486
Abtin Keshavarzian112d1bb2019-10-29 15:34:03 -07002487template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_CNTR_ALL_MAC_COUNTERS>(void)
2488{
2489 otLinkResetCounters(mInstance);
2490
2491 return OT_ERROR_NONE;
2492}
2493
Abtin Keshavarzianbd4ca812019-02-06 08:41:50 -08002494template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_MLE_COUNTERS>(void)
2495{
2496 otError error = OT_ERROR_NONE;
2497 const otMleCounters *counters = otThreadGetMleCounters(mInstance);
2498
Jonathan Hui1326d642020-06-17 22:44:54 -07002499 OT_ASSERT(counters != nullptr);
Abtin Keshavarzianbd4ca812019-02-06 08:41:50 -08002500
2501 SuccessOrExit(error = mEncoder.WriteUint16(counters->mDisabledRole));
2502 SuccessOrExit(error = mEncoder.WriteUint16(counters->mDetachedRole));
2503 SuccessOrExit(error = mEncoder.WriteUint16(counters->mChildRole));
2504 SuccessOrExit(error = mEncoder.WriteUint16(counters->mRouterRole));
2505 SuccessOrExit(error = mEncoder.WriteUint16(counters->mLeaderRole));
2506 SuccessOrExit(error = mEncoder.WriteUint16(counters->mAttachAttempts));
2507 SuccessOrExit(error = mEncoder.WriteUint16(counters->mPartitionIdChanges));
2508 SuccessOrExit(error = mEncoder.WriteUint16(counters->mBetterPartitionAttachAttempts));
2509 SuccessOrExit(error = mEncoder.WriteUint16(counters->mParentChanges));
2510
2511exit:
2512 return error;
2513}
2514
Abtin Keshavarzian112d1bb2019-10-29 15:34:03 -07002515template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_CNTR_MLE_COUNTERS>(void)
2516{
2517 otThreadResetMleCounters(mInstance);
2518
2519 return OT_ERROR_NONE;
2520}
2521
2522template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_ALL_IP_COUNTERS>(void)
2523{
2524 otError error = OT_ERROR_NONE;
2525 const otIpCounters *counters = otThreadGetIp6Counters(mInstance);
2526
Jonathan Hui1326d642020-06-17 22:44:54 -07002527 OT_ASSERT(counters != nullptr);
Abtin Keshavarzian112d1bb2019-10-29 15:34:03 -07002528
2529 // Encode Tx related counters
2530 SuccessOrExit(error = mEncoder.OpenStruct());
2531 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxSuccess));
2532 SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxFailure));
2533 SuccessOrExit(error = mEncoder.CloseStruct());
2534
2535 // Encode Rx related counters
2536 SuccessOrExit(error = mEncoder.OpenStruct());
2537 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxSuccess));
2538 SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxFailure));
2539 SuccessOrExit(error = mEncoder.CloseStruct());
2540
2541exit:
2542 return error;
2543}
2544
Paweł Wańczykc646e6f2019-12-18 19:23:43 +01002545#if OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE
2546template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CNTR_MAC_RETRY_HISTOGRAM>(void)
2547{
2548 otError error = OT_ERROR_NONE;
2549 const uint32_t *histogramDirect;
2550 const uint32_t *histogramIndirect;
2551 uint8_t histogramDirectEntries;
2552 uint8_t histogramIndirectEntries;
2553
2554 histogramDirect = otLinkGetTxDirectRetrySuccessHistogram(mInstance, &histogramDirectEntries);
2555 histogramIndirect = otLinkGetTxIndirectRetrySuccessHistogram(mInstance, &histogramIndirectEntries);
2556
Jonathan Hui1326d642020-06-17 22:44:54 -07002557 OT_ASSERT((histogramDirectEntries == 0) || (histogramDirect != nullptr));
2558 OT_ASSERT((histogramIndirectEntries == 0) || (histogramIndirect != nullptr));
Paweł Wańczykc646e6f2019-12-18 19:23:43 +01002559
2560 // Encode direct message retries histogram
2561 SuccessOrExit(error = mEncoder.OpenStruct());
2562 for (uint8_t i = 0; i < histogramDirectEntries; i++)
2563 {
2564 SuccessOrExit(error = mEncoder.WriteUint32(histogramDirect[i]));
2565 }
2566 SuccessOrExit(error = mEncoder.CloseStruct());
2567
2568 // Encode indirect message retries histogram
2569 SuccessOrExit(error = mEncoder.OpenStruct());
2570 for (uint8_t i = 0; i < histogramIndirectEntries; i++)
2571 {
2572 SuccessOrExit(error = mEncoder.WriteUint32(histogramIndirect[i]));
2573 }
2574 SuccessOrExit(error = mEncoder.CloseStruct());
2575
2576exit:
2577 return error;
2578}
2579
2580template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_CNTR_MAC_RETRY_HISTOGRAM>(void)
2581{
2582 otLinkResetTxRetrySuccessHistogram(mInstance);
2583
2584 return OT_ERROR_NONE;
2585}
2586#endif // OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE
2587
Abtin Keshavarzian112d1bb2019-10-29 15:34:03 -07002588template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_CNTR_ALL_IP_COUNTERS>(void)
2589{
2590 otThreadResetIp6Counters(mInstance);
2591
2592 return OT_ERROR_NONE;
2593}
2594
Jonathan Hui0baaf1a2019-07-15 12:57:32 -07002595#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08002596
Jonathan Hui5bffd8b2020-09-11 16:03:39 -07002597template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_ALLOWLIST>(void)
Buke Po818998e2017-08-04 01:19:07 +08002598{
Yakun Xub8333732018-06-21 04:15:13 +08002599 otMacFilterEntry entry;
Buke Po818998e2017-08-04 01:19:07 +08002600 otMacFilterIterator iterator = OT_MAC_FILTER_ITERATOR_INIT;
Yakun Xub8333732018-06-21 04:15:13 +08002601 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08002602
Buke Po818998e2017-08-04 01:19:07 +08002603 while (otLinkFilterGetNextAddress(mInstance, &iterator, &entry) == OT_ERROR_NONE)
2604 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002605 SuccessOrExit(error = mEncoder.OpenStruct());
2606
2607 SuccessOrExit(error = mEncoder.WriteEui64(entry.mExtAddress));
2608 SuccessOrExit(error = mEncoder.WriteInt8(entry.mRssIn));
2609
2610 SuccessOrExit(error = mEncoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08002611 }
2612
Buke Po818998e2017-08-04 01:19:07 +08002613exit:
Buke Po818998e2017-08-04 01:19:07 +08002614 return error;
2615}
2616
Jonathan Hui5bffd8b2020-09-11 16:03:39 -07002617template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_ALLOWLIST_ENABLED>(void)
Buke Po818998e2017-08-04 01:19:07 +08002618{
Jonathan Hui5bffd8b2020-09-11 16:03:39 -07002619 return mEncoder.WriteBool(otLinkFilterGetAddressMode(mInstance) == OT_MAC_FILTER_ADDRESS_MODE_ALLOWLIST);
Buke Po818998e2017-08-04 01:19:07 +08002620}
2621
Jonathan Hui5bffd8b2020-09-11 16:03:39 -07002622template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_DENYLIST>(void)
Buke Po818998e2017-08-04 01:19:07 +08002623{
Yakun Xub8333732018-06-21 04:15:13 +08002624 otMacFilterEntry entry;
Buke Po818998e2017-08-04 01:19:07 +08002625 otMacFilterIterator iterator = OT_MAC_FILTER_ITERATOR_INIT;
Yakun Xub8333732018-06-21 04:15:13 +08002626 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08002627
Buke Po818998e2017-08-04 01:19:07 +08002628 while (otLinkFilterGetNextAddress(mInstance, &iterator, &entry) == OT_ERROR_NONE)
2629 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002630 SuccessOrExit(error = mEncoder.OpenStruct());
2631 SuccessOrExit(error = mEncoder.WriteEui64(entry.mExtAddress));
2632 SuccessOrExit(error = mEncoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08002633 }
2634
Buke Po818998e2017-08-04 01:19:07 +08002635exit:
Buke Po818998e2017-08-04 01:19:07 +08002636 return error;
2637}
2638
Jonathan Hui5bffd8b2020-09-11 16:03:39 -07002639template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_DENYLIST_ENABLED>(void)
Buke Po818998e2017-08-04 01:19:07 +08002640{
Jonathan Hui5bffd8b2020-09-11 16:03:39 -07002641 return mEncoder.WriteBool(otLinkFilterGetAddressMode(mInstance) == OT_MAC_FILTER_ADDRESS_MODE_DENYLIST);
Buke Po818998e2017-08-04 01:19:07 +08002642}
2643
Yakun Xu8ccf1382018-06-29 00:26:31 +08002644template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_FIXED_RSS>(void)
Buke Po818998e2017-08-04 01:19:07 +08002645{
Yakun Xub8333732018-06-21 04:15:13 +08002646 otMacFilterEntry entry;
Buke Po818998e2017-08-04 01:19:07 +08002647 otMacFilterIterator iterator = OT_MAC_FILTER_ITERATOR_INIT;
Yakun Xub8333732018-06-21 04:15:13 +08002648 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08002649
Buke Po818998e2017-08-04 01:19:07 +08002650 while (otLinkFilterGetNextRssIn(mInstance, &iterator, &entry) == OT_ERROR_NONE)
2651 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002652 SuccessOrExit(error = mEncoder.OpenStruct());
2653
2654 SuccessOrExit(error = mEncoder.WriteEui64(entry.mExtAddress));
2655 SuccessOrExit(error = mEncoder.WriteInt8(entry.mRssIn));
2656
2657 SuccessOrExit(error = mEncoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08002658 }
2659
Buke Po818998e2017-08-04 01:19:07 +08002660exit:
Buke Po818998e2017-08-04 01:19:07 +08002661 return error;
2662}
2663
Jonathan Hui5bffd8b2020-09-11 16:03:39 -07002664template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_ALLOWLIST>(void)
Buke Po818998e2017-08-04 01:19:07 +08002665{
Buke Po818998e2017-08-04 01:19:07 +08002666 otError error = OT_ERROR_NONE;
2667
2668 // First, clear the address filter entries.
2669 otLinkFilterClearAddresses(mInstance);
2670
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002671 while (mDecoder.GetRemainingLengthInStruct() > 0)
Buke Po818998e2017-08-04 01:19:07 +08002672 {
Jonathan Hui1326d642020-06-17 22:44:54 -07002673 const otExtAddress *extAddress = nullptr;
Yakun Xub8333732018-06-21 04:15:13 +08002674 int8_t rss;
Buke Po818998e2017-08-04 01:19:07 +08002675
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002676 SuccessOrExit(error = mDecoder.OpenStruct());
2677 SuccessOrExit(error = mDecoder.ReadEui64(extAddress));
Buke Po818998e2017-08-04 01:19:07 +08002678
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002679 if (!mDecoder.IsAllReadInStruct())
2680 {
2681 SuccessOrExit(error = mDecoder.ReadInt8(rss));
2682 }
2683 else
Buke Po818998e2017-08-04 01:19:07 +08002684 {
2685 rss = OT_MAC_FILTER_FIXED_RSS_DISABLED;
Buke Po818998e2017-08-04 01:19:07 +08002686 }
2687
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002688 SuccessOrExit(error = mDecoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08002689
2690 error = otLinkFilterAddAddress(mInstance, extAddress);
2691
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002692 if (error == OT_ERROR_ALREADY)
2693 {
2694 error = OT_ERROR_NONE;
2695 }
2696
2697 SuccessOrExit(error);
Buke Po818998e2017-08-04 01:19:07 +08002698
2699 if (rss != OT_MAC_FILTER_FIXED_RSS_DISABLED)
2700 {
2701 SuccessOrExit(error = otLinkFilterAddRssIn(mInstance, extAddress, rss));
2702 }
Buke Po818998e2017-08-04 01:19:07 +08002703 }
2704
2705exit:
2706 // If we had an error, we may have actually changed
Jonathan Hui5bffd8b2020-09-11 16:03:39 -07002707 // the state of the allowlist, so we need to report
Buke Po818998e2017-08-04 01:19:07 +08002708 // those incomplete changes via an asynchronous
2709 // change event.
Buke Po818998e2017-08-04 01:19:07 +08002710
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002711 if (error != OT_ERROR_NONE)
Buke Po818998e2017-08-04 01:19:07 +08002712 {
Jonathan Hui5bffd8b2020-09-11 16:03:39 -07002713 IgnoreError(WritePropertyValueIsFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_PROP_MAC_ALLOWLIST));
Buke Po818998e2017-08-04 01:19:07 +08002714 }
2715
2716 return error;
2717}
2718
Jonathan Hui5bffd8b2020-09-11 16:03:39 -07002719template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_ALLOWLIST_ENABLED>(void)
Buke Po818998e2017-08-04 01:19:07 +08002720{
Yakun Xub8333732018-06-21 04:15:13 +08002721 bool enabled;
2722 otError error = OT_ERROR_NONE;
2723 otMacFilterAddressMode mode = OT_MAC_FILTER_ADDRESS_MODE_DISABLED;
Buke Po818998e2017-08-04 01:19:07 +08002724
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002725 SuccessOrExit(error = mDecoder.ReadBool(enabled));
Buke Po818998e2017-08-04 01:19:07 +08002726
2727 if (enabled)
2728 {
Jonathan Hui5bffd8b2020-09-11 16:03:39 -07002729 mode = OT_MAC_FILTER_ADDRESS_MODE_ALLOWLIST;
Buke Po818998e2017-08-04 01:19:07 +08002730 }
2731
Abtin Keshavarzian6f1fc2e2020-06-29 08:59:34 -07002732 otLinkFilterSetAddressMode(mInstance, mode);
Buke Po818998e2017-08-04 01:19:07 +08002733
2734exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002735 return error;
Buke Po818998e2017-08-04 01:19:07 +08002736}
2737
Jonathan Hui5bffd8b2020-09-11 16:03:39 -07002738template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_DENYLIST>(void)
Buke Po818998e2017-08-04 01:19:07 +08002739{
Buke Po818998e2017-08-04 01:19:07 +08002740 otError error = OT_ERROR_NONE;
2741
2742 // First, clear the address filter entries.
2743 otLinkFilterClearAddresses(mInstance);
2744
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002745 while (mDecoder.GetRemainingLengthInStruct() > 0)
Buke Po818998e2017-08-04 01:19:07 +08002746 {
Jonathan Hui1326d642020-06-17 22:44:54 -07002747 const otExtAddress *extAddress = nullptr;
Buke Po818998e2017-08-04 01:19:07 +08002748
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002749 SuccessOrExit(error = mDecoder.OpenStruct());
2750 SuccessOrExit(error = mDecoder.ReadEui64(extAddress));
2751 SuccessOrExit(error = mDecoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08002752
Abtin Keshavarzian6f1fc2e2020-06-29 08:59:34 -07002753 otLinkFilterRemoveAddress(mInstance, extAddress);
Buke Po818998e2017-08-04 01:19:07 +08002754 }
2755
2756exit:
2757 // If we had an error, we may have actually changed
Jonathan Hui5bffd8b2020-09-11 16:03:39 -07002758 // the state of the denylist, so we need to report
Buke Po818998e2017-08-04 01:19:07 +08002759 // those incomplete changes via an asynchronous
2760 // change event.
Buke Po818998e2017-08-04 01:19:07 +08002761
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002762 if (error != OT_ERROR_NONE)
Buke Po818998e2017-08-04 01:19:07 +08002763 {
Jonathan Hui5bffd8b2020-09-11 16:03:39 -07002764 IgnoreError(WritePropertyValueIsFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_PROP_MAC_DENYLIST));
Buke Po818998e2017-08-04 01:19:07 +08002765 }
2766
2767 return error;
2768}
2769
Jonathan Hui5bffd8b2020-09-11 16:03:39 -07002770template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_DENYLIST_ENABLED>(void)
Buke Po818998e2017-08-04 01:19:07 +08002771{
Yakun Xub8333732018-06-21 04:15:13 +08002772 bool enabled;
2773 otError error = OT_ERROR_NONE;
2774 otMacFilterAddressMode mode = OT_MAC_FILTER_ADDRESS_MODE_DISABLED;
Buke Po818998e2017-08-04 01:19:07 +08002775
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002776 SuccessOrExit(error = mDecoder.ReadBool(enabled));
Buke Po818998e2017-08-04 01:19:07 +08002777
2778 if (enabled)
2779 {
Jonathan Hui5bffd8b2020-09-11 16:03:39 -07002780 mode = OT_MAC_FILTER_ADDRESS_MODE_DENYLIST;
Buke Po818998e2017-08-04 01:19:07 +08002781 }
2782
Abtin Keshavarzian6f1fc2e2020-06-29 08:59:34 -07002783 otLinkFilterSetAddressMode(mInstance, mode);
Buke Po818998e2017-08-04 01:19:07 +08002784
2785exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002786 return error;
Buke Po818998e2017-08-04 01:19:07 +08002787}
2788
Yakun Xu8ccf1382018-06-29 00:26:31 +08002789template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_FIXED_RSS>(void)
Buke Po818998e2017-08-04 01:19:07 +08002790{
Buke Po818998e2017-08-04 01:19:07 +08002791 otError error = OT_ERROR_NONE;
2792
2793 // First, clear the address filter entries.
Abtin Keshavarzian6f1fc2e2020-06-29 08:59:34 -07002794 otLinkFilterClearAllRssIn(mInstance);
Buke Po818998e2017-08-04 01:19:07 +08002795
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002796 while (mDecoder.GetRemainingLengthInStruct() > 0)
Buke Po818998e2017-08-04 01:19:07 +08002797 {
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002798 const otExtAddress *extAddress;
Yakun Xub8333732018-06-21 04:15:13 +08002799 int8_t rss;
Buke Po818998e2017-08-04 01:19:07 +08002800
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002801 SuccessOrExit(error = mDecoder.OpenStruct());
Buke Po818998e2017-08-04 01:19:07 +08002802
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002803 if (mDecoder.GetRemainingLengthInStruct() > sizeof(otExtAddress))
2804 {
2805 SuccessOrExit(error = mDecoder.ReadEui64(extAddress));
2806 }
2807 else
Buke Po818998e2017-08-04 01:19:07 +08002808 {
Jonathan Hui1326d642020-06-17 22:44:54 -07002809 extAddress = nullptr;
Buke Po818998e2017-08-04 01:19:07 +08002810 }
2811
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002812 SuccessOrExit(error = mDecoder.ReadInt8(rss));
2813
2814 SuccessOrExit(error = mDecoder.CloseStruct());
Buke Po818998e2017-08-04 01:19:07 +08002815
Abtin Keshavarzian6f1fc2e2020-06-29 08:59:34 -07002816 if (extAddress != nullptr)
2817 {
2818 SuccessOrExit(error = otLinkFilterAddRssIn(mInstance, extAddress, rss));
2819 }
2820 else
2821 {
2822 otLinkFilterSetDefaultRssIn(mInstance, rss);
2823 }
Buke Po818998e2017-08-04 01:19:07 +08002824 }
2825
2826exit:
2827 // If we had an error, we may have actually changed
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002828 // the state of the RssIn filter, so we need to report
Buke Po818998e2017-08-04 01:19:07 +08002829 // those incomplete changes via an asynchronous
2830 // change event.
Buke Po818998e2017-08-04 01:19:07 +08002831
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002832 if (error != OT_ERROR_NONE)
Buke Po818998e2017-08-04 01:19:07 +08002833 {
kangping49f36f82020-05-07 02:17:58 +08002834 IgnoreError(WritePropertyValueIsFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_PROP_MAC_FIXED_RSS));
Buke Po818998e2017-08-04 01:19:07 +08002835 }
2836
2837 return error;
2838}
Jonathan Hui0baaf1a2019-07-15 12:57:32 -07002839#endif // OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08002840
Yakun Xu8ccf1382018-06-29 00:26:31 +08002841template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_MODE>(void)
Buke Po818998e2017-08-04 01:19:07 +08002842{
Yakun Xub8333732018-06-21 04:15:13 +08002843 uint8_t numericMode;
Buke Po818998e2017-08-04 01:19:07 +08002844 otLinkModeConfig modeConfig = otThreadGetLinkMode(mInstance);
2845
Jonathan Huidc9b0322020-09-29 15:30:37 -07002846 numericMode = LinkFlagsToFlagByte(modeConfig.mRxOnWhenIdle, modeConfig.mDeviceType, modeConfig.mNetworkData);
Buke Po818998e2017-08-04 01:19:07 +08002847
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002848 return mEncoder.WriteUint8(numericMode);
Buke Po818998e2017-08-04 01:19:07 +08002849}
2850
Yakun Xu8ccf1382018-06-29 00:26:31 +08002851template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_MODE>(void)
Buke Po818998e2017-08-04 01:19:07 +08002852{
Yakun Xub8333732018-06-21 04:15:13 +08002853 uint8_t numericMode = 0;
Buke Po818998e2017-08-04 01:19:07 +08002854 otLinkModeConfig modeConfig;
Yakun Xub8333732018-06-21 04:15:13 +08002855 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08002856
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002857 SuccessOrExit(mDecoder.ReadUint8(numericMode));
Buke Po818998e2017-08-04 01:19:07 +08002858
Yakun Xub8333732018-06-21 04:15:13 +08002859 modeConfig.mRxOnWhenIdle =
2860 ((numericMode & SPINEL_THREAD_MODE_RX_ON_WHEN_IDLE) == SPINEL_THREAD_MODE_RX_ON_WHEN_IDLE);
Jonathan Hui5a489832018-09-27 09:33:03 -07002861 modeConfig.mDeviceType = ((numericMode & SPINEL_THREAD_MODE_FULL_THREAD_DEV) == SPINEL_THREAD_MODE_FULL_THREAD_DEV);
Yakun Xub8333732018-06-21 04:15:13 +08002862 modeConfig.mNetworkData =
2863 ((numericMode & SPINEL_THREAD_MODE_FULL_NETWORK_DATA) == SPINEL_THREAD_MODE_FULL_NETWORK_DATA);
Buke Po818998e2017-08-04 01:19:07 +08002864
2865 error = otThreadSetLinkMode(mInstance, modeConfig);
2866
2867exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002868 return error;
Buke Po818998e2017-08-04 01:19:07 +08002869}
2870
Yakun Xu8ccf1382018-06-29 00:26:31 +08002871template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_CHILD_TIMEOUT>(void)
Buke Po818998e2017-08-04 01:19:07 +08002872{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002873 return mEncoder.WriteUint32(otThreadGetChildTimeout(mInstance));
Buke Po818998e2017-08-04 01:19:07 +08002874}
2875
Abtin Keshavarziand67c4e22018-08-01 22:55:35 -07002876template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_CHILD_TIMEOUT>(void)
2877{
2878 uint32_t timeout = 0;
2879 otError error = OT_ERROR_NONE;
2880
2881 SuccessOrExit(error = mDecoder.ReadUint32(timeout));
2882
2883 otThreadSetChildTimeout(mInstance, timeout);
2884
2885exit:
2886 return error;
2887}
2888
Yakun Xu8ccf1382018-06-29 00:26:31 +08002889template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_RLOC16>(void)
Buke Po818998e2017-08-04 01:19:07 +08002890{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002891 return mEncoder.WriteUint16(otThreadGetRloc16(mInstance));
Buke Po818998e2017-08-04 01:19:07 +08002892}
2893
Yakun Xu8ccf1382018-06-29 00:26:31 +08002894template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NET_REQUIRE_JOIN_EXISTING>(void)
Buke Po818998e2017-08-04 01:19:07 +08002895{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002896 return mEncoder.WriteBool(mRequireJoinExistingNetwork);
Buke Po818998e2017-08-04 01:19:07 +08002897}
2898
Yakun Xu8ccf1382018-06-29 00:26:31 +08002899template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_NET_REQUIRE_JOIN_EXISTING>(void)
Buke Po818998e2017-08-04 01:19:07 +08002900{
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002901 return mDecoder.ReadBool(mRequireJoinExistingNetwork);
Buke Po818998e2017-08-04 01:19:07 +08002902}
2903
Yakun Xu8ccf1382018-06-29 00:26:31 +08002904template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_STREAM_NET_INSECURE>(void)
Buke Po818998e2017-08-04 01:19:07 +08002905{
Jonathan Hui1326d642020-06-17 22:44:54 -07002906 const uint8_t * framePtr = nullptr;
Zhanglong Xiaf8909592018-11-06 04:48:39 +08002907 uint16_t frameLen = 0;
Jonathan Hui1326d642020-06-17 22:44:54 -07002908 const uint8_t * metaPtr = nullptr;
Zhanglong Xiaf8909592018-11-06 04:48:39 +08002909 uint16_t metaLen = 0;
Jonathan Hui1326d642020-06-17 22:44:54 -07002910 otMessage * message = nullptr;
Zhanglong Xiaf8909592018-11-06 04:48:39 +08002911 otError error = OT_ERROR_NONE;
2912 otMessageSettings msgSettings = {false, OT_MESSAGE_PRIORITY_NORMAL};
Buke Po818998e2017-08-04 01:19:07 +08002913
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002914 SuccessOrExit(mDecoder.ReadDataWithLen(framePtr, frameLen));
2915 SuccessOrExit(mDecoder.ReadData(metaPtr, metaLen));
Buke Po818998e2017-08-04 01:19:07 +08002916
2917 // We ignore metadata for now.
2918 // May later include TX power, allow retransmits, etc...
Buke Po818998e2017-08-04 01:19:07 +08002919
Zhanglong Xia19f25332018-12-20 05:55:26 +08002920 // STREAM_NET_INSECURE packets are not secured at layer 2.
2921 message = otIp6NewMessageFromBuffer(mInstance, framePtr, frameLen, &msgSettings);
Jonathan Hui1326d642020-06-17 22:44:54 -07002922 VerifyOrExit(message != nullptr, error = OT_ERROR_NO_BUFS);
Buke Po818998e2017-08-04 01:19:07 +08002923
2924 // Ensure the insecure message is forwarded using direct transmission.
2925 otMessageSetDirectTransmission(message, true);
2926
2927 error = otIp6Send(mInstance, message);
2928
Buke Po818998e2017-08-04 01:19:07 +08002929exit:
Buke Po818998e2017-08-04 01:19:07 +08002930 if (error == OT_ERROR_NONE)
2931 {
2932 mInboundInsecureIpFrameCounter++;
Buke Po818998e2017-08-04 01:19:07 +08002933 }
2934 else
2935 {
2936 mDroppedInboundIpFrameCounter++;
Buke Po818998e2017-08-04 01:19:07 +08002937 }
2938
Buke Po818998e2017-08-04 01:19:07 +08002939 return error;
2940}
2941
Yakun Xu8ccf1382018-06-29 00:26:31 +08002942template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_CNTR_RESET>(void)
Buke Po818998e2017-08-04 01:19:07 +08002943{
Abtin Keshavarzian112d1bb2019-10-29 15:34:03 -07002944 otLinkResetCounters(mInstance);
Paweł Wańczykc646e6f2019-12-18 19:23:43 +01002945#if OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE
2946 otLinkResetTxRetrySuccessHistogram(mInstance);
2947#endif
Abtin Keshavarzian112d1bb2019-10-29 15:34:03 -07002948 otThreadResetIp6Counters(mInstance);
2949 otThreadResetMleCounters(mInstance);
2950 ResetCounters();
Buke Po818998e2017-08-04 01:19:07 +08002951
Abtin Keshavarzian112d1bb2019-10-29 15:34:03 -07002952 return OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08002953}
2954
Yakun Xu8ccf1382018-06-29 00:26:31 +08002955template <> otError NcpBase::HandlePropertyInsert<SPINEL_PROP_THREAD_ASSISTING_PORTS>(void)
Buke Po818998e2017-08-04 01:19:07 +08002956{
Yakun Xub8333732018-06-21 04:15:13 +08002957 otError error = OT_ERROR_NONE;
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002958 uint16_t port;
2959
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002960 SuccessOrExit(error = mDecoder.ReadUint16(port));
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002961
2962 error = otIp6AddUnsecurePort(mInstance, port);
2963exit:
2964 return error;
2965}
2966
Jonathan Hui0baaf1a2019-07-15 12:57:32 -07002967#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002968
Jonathan Hui5bffd8b2020-09-11 16:03:39 -07002969template <> otError NcpBase::HandlePropertyInsert<SPINEL_PROP_MAC_ALLOWLIST>(void)
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002970{
Abtin Keshavarzian6f1fc2e2020-06-29 08:59:34 -07002971 otError error = OT_ERROR_NONE;
2972 const otExtAddress *extAddress;
2973 int8_t rss = OT_MAC_FILTER_FIXED_RSS_DISABLED;
Buke Po818998e2017-08-04 01:19:07 +08002974
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002975 SuccessOrExit(error = mDecoder.ReadEui64(extAddress));
Buke Po818998e2017-08-04 01:19:07 +08002976
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07002977 if (!mDecoder.IsAllRead())
2978 {
2979 SuccessOrExit(error = mDecoder.ReadInt8(rss));
2980 }
Buke Po818998e2017-08-04 01:19:07 +08002981
2982 error = otLinkFilterAddAddress(mInstance, extAddress);
2983
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07002984 if (error == OT_ERROR_ALREADY)
2985 {
2986 error = OT_ERROR_NONE;
2987 }
2988
2989 SuccessOrExit(error);
Buke Po818998e2017-08-04 01:19:07 +08002990
2991 if (rss != OT_MAC_FILTER_FIXED_RSS_DISABLED)
2992 {
2993 error = otLinkFilterAddRssIn(mInstance, extAddress, rss);
Buke Po818998e2017-08-04 01:19:07 +08002994 }
2995
Buke Po818998e2017-08-04 01:19:07 +08002996exit:
Buke Po818998e2017-08-04 01:19:07 +08002997 return error;
2998}
2999
Jonathan Hui5bffd8b2020-09-11 16:03:39 -07003000template <> otError NcpBase::HandlePropertyInsert<SPINEL_PROP_MAC_DENYLIST>(void)
Buke Po818998e2017-08-04 01:19:07 +08003001{
Abtin Keshavarzian6f1fc2e2020-06-29 08:59:34 -07003002 otError error = OT_ERROR_NONE;
3003 const otExtAddress *extAddress;
Buke Po818998e2017-08-04 01:19:07 +08003004
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07003005 SuccessOrExit(error = mDecoder.ReadEui64(extAddress));
Buke Po818998e2017-08-04 01:19:07 +08003006
3007 error = otLinkFilterAddAddress(mInstance, extAddress);
3008
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003009 if (error == OT_ERROR_ALREADY)
Buke Po818998e2017-08-04 01:19:07 +08003010 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003011 error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08003012 }
3013
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003014exit:
Buke Po818998e2017-08-04 01:19:07 +08003015 return error;
3016}
3017
Yakun Xu8ccf1382018-06-29 00:26:31 +08003018template <> otError NcpBase::HandlePropertyInsert<SPINEL_PROP_MAC_FIXED_RSS>(void)
Buke Po818998e2017-08-04 01:19:07 +08003019{
Yakun Xub8333732018-06-21 04:15:13 +08003020 otError error = OT_ERROR_NONE;
Jonathan Hui1326d642020-06-17 22:44:54 -07003021 const otExtAddress *extAddress = nullptr;
Yakun Xub8333732018-06-21 04:15:13 +08003022 int8_t rss = OT_MAC_FILTER_FIXED_RSS_DISABLED;
Buke Po818998e2017-08-04 01:19:07 +08003023
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07003024 if (mDecoder.GetRemainingLength() > sizeof(int8_t))
Buke Po818998e2017-08-04 01:19:07 +08003025 {
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07003026 SuccessOrExit(mDecoder.ReadEui64(extAddress));
Buke Po818998e2017-08-04 01:19:07 +08003027 }
3028
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07003029 SuccessOrExit(mDecoder.ReadInt8(rss));
Buke Po818998e2017-08-04 01:19:07 +08003030
Abtin Keshavarzian6f1fc2e2020-06-29 08:59:34 -07003031 if (extAddress != nullptr)
3032 {
3033 error = otLinkFilterAddRssIn(mInstance, extAddress, rss);
3034 }
3035 else
3036 {
3037 otLinkFilterSetDefaultRssIn(mInstance, rss);
3038 }
Buke Po818998e2017-08-04 01:19:07 +08003039
Buke Po818998e2017-08-04 01:19:07 +08003040exit:
Buke Po818998e2017-08-04 01:19:07 +08003041 return error;
3042}
3043
Jonathan Hui0baaf1a2019-07-15 12:57:32 -07003044#endif // OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08003045
Yakun Xu8ccf1382018-06-29 00:26:31 +08003046template <> otError NcpBase::HandlePropertyRemove<SPINEL_PROP_THREAD_ASSISTING_PORTS>(void)
Buke Po818998e2017-08-04 01:19:07 +08003047{
Yakun Xub8333732018-06-21 04:15:13 +08003048 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08003049 uint16_t port;
3050
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07003051 SuccessOrExit(error = mDecoder.ReadUint16(port));
Buke Po818998e2017-08-04 01:19:07 +08003052
3053 error = otIp6RemoveUnsecurePort(mInstance, port);
Abtin Keshavarzian02bdc692017-08-15 09:11:19 -07003054
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003055 // If unsecure port was not on the list, "remove" command is successful.
3056 if (error == OT_ERROR_NOT_FOUND)
Buke Po818998e2017-08-04 01:19:07 +08003057 {
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003058 error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08003059 }
3060
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003061exit:
Buke Po818998e2017-08-04 01:19:07 +08003062 return error;
3063}
3064
Jonathan Hui0baaf1a2019-07-15 12:57:32 -07003065#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08003066
Jonathan Hui5bffd8b2020-09-11 16:03:39 -07003067template <> otError NcpBase::HandlePropertyRemove<SPINEL_PROP_MAC_ALLOWLIST>(void)
Buke Po818998e2017-08-04 01:19:07 +08003068{
Yakun Xub8333732018-06-21 04:15:13 +08003069 otError error = OT_ERROR_NONE;
Jonathan Hui1326d642020-06-17 22:44:54 -07003070 const otExtAddress *extAddress = nullptr;
Buke Po818998e2017-08-04 01:19:07 +08003071
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07003072 SuccessOrExit(error = mDecoder.ReadEui64(extAddress));
Buke Po818998e2017-08-04 01:19:07 +08003073
Abtin Keshavarzian6f1fc2e2020-06-29 08:59:34 -07003074 otLinkFilterRemoveAddress(mInstance, extAddress);
Buke Po818998e2017-08-04 01:19:07 +08003075
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003076exit:
Buke Po818998e2017-08-04 01:19:07 +08003077 return error;
3078}
3079
Jonathan Hui5bffd8b2020-09-11 16:03:39 -07003080template <> otError NcpBase::HandlePropertyRemove<SPINEL_PROP_MAC_DENYLIST>(void)
Buke Po818998e2017-08-04 01:19:07 +08003081{
Yakun Xub8333732018-06-21 04:15:13 +08003082 otError error = OT_ERROR_NONE;
Jonathan Hui1326d642020-06-17 22:44:54 -07003083 const otExtAddress *extAddress = nullptr;
Buke Po818998e2017-08-04 01:19:07 +08003084
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07003085 SuccessOrExit(error = mDecoder.ReadEui64(extAddress));
Buke Po818998e2017-08-04 01:19:07 +08003086
Abtin Keshavarzian6f1fc2e2020-06-29 08:59:34 -07003087 otLinkFilterRemoveAddress(mInstance, extAddress);
Buke Po818998e2017-08-04 01:19:07 +08003088
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003089exit:
Buke Po818998e2017-08-04 01:19:07 +08003090 return error;
3091}
3092
Yakun Xu8ccf1382018-06-29 00:26:31 +08003093template <> otError NcpBase::HandlePropertyRemove<SPINEL_PROP_MAC_FIXED_RSS>(void)
Buke Po818998e2017-08-04 01:19:07 +08003094{
Yakun Xub8333732018-06-21 04:15:13 +08003095 otError error = OT_ERROR_NONE;
Jonathan Hui1326d642020-06-17 22:44:54 -07003096 const otExtAddress *extAddress = nullptr;
Buke Po818998e2017-08-04 01:19:07 +08003097
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07003098 if (mDecoder.GetRemainingLength() > 0)
Buke Po818998e2017-08-04 01:19:07 +08003099 {
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07003100 SuccessOrExit(error = mDecoder.ReadEui64(extAddress));
Buke Po818998e2017-08-04 01:19:07 +08003101 }
3102
Abtin Keshavarzian6f1fc2e2020-06-29 08:59:34 -07003103 if (extAddress != nullptr)
Buke Po818998e2017-08-04 01:19:07 +08003104 {
Abtin Keshavarzian6f1fc2e2020-06-29 08:59:34 -07003105 otLinkFilterRemoveRssIn(mInstance, extAddress);
3106 }
3107 else
3108 {
3109 otLinkFilterClearDefaultRssIn(mInstance);
Buke Po818998e2017-08-04 01:19:07 +08003110 }
3111
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003112exit:
Buke Po818998e2017-08-04 01:19:07 +08003113 return error;
3114}
3115
Jonathan Hui0baaf1a2019-07-15 12:57:32 -07003116#endif // OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08003117
Yakun Xu65374592020-03-12 02:42:30 +08003118#if OPENTHREAD_PLATFORM_POSIX
Abtin Keshavarzian7c8a3722018-10-12 10:40:57 -07003119
3120template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_RCP_VERSION>(void)
3121{
3122 return mEncoder.WriteUtf8(otGetRadioVersionString(mInstance));
3123}
3124
Abtin Keshavarzian6e718a12019-04-04 17:39:22 -07003125#endif
Abtin Keshavarzian7c8a3722018-10-12 10:40:57 -07003126
Jonathan Hui4a475d52019-07-15 22:13:11 -07003127#if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
Abtin Keshavarzian89396ab2019-03-11 14:59:43 -07003128
3129template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_SLAAC_ENABLED>(void)
3130{
3131 return mEncoder.WriteBool(otIp6IsSlaacEnabled(mInstance));
3132}
3133
3134template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_SLAAC_ENABLED>(void)
3135{
3136 otError error = OT_ERROR_NONE;
3137 bool enabled;
3138
3139 SuccessOrExit(error = mDecoder.ReadBool(enabled));
3140 otIp6SetSlaacEnabled(mInstance, enabled);
3141
3142exit:
3143 return error;
3144}
3145
Jonathan Hui4a475d52019-07-15 22:13:11 -07003146#endif // OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
Abtin Keshavarzian89396ab2019-03-11 14:59:43 -07003147
Jonathan Hui02da2062019-07-16 12:18:34 -07003148#if OPENTHREAD_CONFIG_LEGACY_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08003149
3150void NcpBase::RegisterLegacyHandlers(const otNcpLegacyHandlers *aHandlers)
3151{
3152 mLegacyHandlers = aHandlers;
3153 bool isEnabled;
3154
Jonathan Hui1326d642020-06-17 22:44:54 -07003155 VerifyOrExit(mLegacyHandlers != nullptr, OT_NOOP);
Buke Po818998e2017-08-04 01:19:07 +08003156
3157 isEnabled = (otThreadGetDeviceRole(mInstance) != OT_DEVICE_ROLE_DISABLED);
3158
3159 if (isEnabled)
3160 {
3161 if (mLegacyHandlers->mStartLegacy)
3162 {
3163 mLegacyHandlers->mStartLegacy();
3164 }
3165 }
3166 else
3167 {
3168 if (mLegacyHandlers->mStopLegacy)
3169 {
3170 mLegacyHandlers->mStopLegacy();
3171 }
3172 }
3173
3174 if (mLegacyHandlers->mSetLegacyUlaPrefix)
3175 {
3176 mLegacyHandlers->mSetLegacyUlaPrefix(mLegacyUlaPrefix);
3177 }
3178
3179exit:
3180 return;
3181}
3182
3183void NcpBase::HandleDidReceiveNewLegacyUlaPrefix(const uint8_t *aUlaPrefix)
3184{
3185 memcpy(mLegacyUlaPrefix, aUlaPrefix, OT_NCP_LEGACY_ULA_PREFIX_LENGTH);
3186 mChangedPropsSet.AddProperty(SPINEL_PROP_NEST_LEGACY_ULA_PREFIX);
Abtin Keshavarziana1adaac2020-05-11 10:24:58 -07003187 mUpdateChangedPropsTask.Post();
Buke Po818998e2017-08-04 01:19:07 +08003188}
3189
3190void NcpBase::HandleLegacyNodeDidJoin(const otExtAddress *aExtAddr)
3191{
Yakun Xub8333732018-06-21 04:15:13 +08003192 mLegacyNodeDidJoin = true;
Buke Po818998e2017-08-04 01:19:07 +08003193 mLegacyLastJoinedNode = *aExtAddr;
3194 mChangedPropsSet.AddProperty(SPINEL_PROP_NEST_LEGACY_LAST_NODE_JOINED);
Abtin Keshavarziana1adaac2020-05-11 10:24:58 -07003195 mUpdateChangedPropsTask.Post();
Buke Po818998e2017-08-04 01:19:07 +08003196}
3197
Yakun Xu8ccf1382018-06-29 00:26:31 +08003198template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NEST_LEGACY_ULA_PREFIX>(void)
Buke Po818998e2017-08-04 01:19:07 +08003199{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003200 return mEncoder.WriteData(mLegacyUlaPrefix, sizeof(mLegacyUlaPrefix));
Buke Po818998e2017-08-04 01:19:07 +08003201}
3202
Yakun Xu8ccf1382018-06-29 00:26:31 +08003203template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_NEST_LEGACY_ULA_PREFIX>(void)
Buke Po818998e2017-08-04 01:19:07 +08003204{
Jonathan Hui1326d642020-06-17 22:44:54 -07003205 const uint8_t *ptr = nullptr;
Yakun Xub8333732018-06-21 04:15:13 +08003206 uint16_t len;
3207 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08003208
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07003209 SuccessOrExit(error = mDecoder.ReadData(ptr, len));
Buke Po818998e2017-08-04 01:19:07 +08003210
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07003211 VerifyOrExit(len <= sizeof(mLegacyUlaPrefix), error = OT_ERROR_PARSE);
Buke Po818998e2017-08-04 01:19:07 +08003212
3213 memset(mLegacyUlaPrefix, 0, sizeof(mLegacyUlaPrefix));
3214 memcpy(mLegacyUlaPrefix, ptr, len);
3215
Jonathan Hui1326d642020-06-17 22:44:54 -07003216 if ((mLegacyHandlers != nullptr) && (mLegacyHandlers->mSetLegacyUlaPrefix != nullptr))
Buke Po818998e2017-08-04 01:19:07 +08003217 {
3218 mLegacyHandlers->mSetLegacyUlaPrefix(mLegacyUlaPrefix);
3219 }
3220
3221exit:
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07003222 return error;
Buke Po818998e2017-08-04 01:19:07 +08003223}
3224
Yakun Xu8ccf1382018-06-29 00:26:31 +08003225template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NEST_LEGACY_LAST_NODE_JOINED>(void)
Buke Po818998e2017-08-04 01:19:07 +08003226{
3227 if (!mLegacyNodeDidJoin)
3228 {
3229 memset(&mLegacyLastJoinedNode, 0, sizeof(mLegacyLastJoinedNode));
3230 }
3231
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003232 return mEncoder.WriteEui64(mLegacyLastJoinedNode);
Buke Po818998e2017-08-04 01:19:07 +08003233}
Abtin Keshavarzianecd28452018-04-05 10:20:47 -07003234
3235void NcpBase::StartLegacy(void)
3236{
3237 mLegacyNodeDidJoin = false;
3238
Jonathan Hui1326d642020-06-17 22:44:54 -07003239 if ((mLegacyHandlers != nullptr) && (mLegacyHandlers->mStartLegacy != nullptr))
Abtin Keshavarzianecd28452018-04-05 10:20:47 -07003240 {
3241 mLegacyHandlers->mStartLegacy();
3242 }
3243}
3244
3245void NcpBase::StopLegacy(void)
3246{
3247 mLegacyNodeDidJoin = false;
3248
Jonathan Hui1326d642020-06-17 22:44:54 -07003249 if ((mLegacyHandlers != nullptr) && (mLegacyHandlers->mStopLegacy != nullptr))
Abtin Keshavarzianecd28452018-04-05 10:20:47 -07003250 {
3251 mLegacyHandlers->mStopLegacy();
3252 }
3253}
3254
Jonathan Hui02da2062019-07-16 12:18:34 -07003255#endif // OPENTHREAD_CONFIG_LEGACY_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08003256
Jonathan Hui926b9e82019-07-15 21:16:37 -07003257#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
Yakun Xu8ccf1382018-06-29 00:26:31 +08003258template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_NETWORK_TIME>(void)
Shu Chene69019f2018-06-27 02:46:32 +08003259{
3260 otError error = OT_ERROR_NONE;
3261 otNetworkTimeStatus networkTimeStatus;
3262 uint64_t time;
3263
Jonathan Huifa395d72019-05-20 08:50:43 -07003264 networkTimeStatus = otNetworkTimeGet(mInstance, &time);
Shu Chene69019f2018-06-27 02:46:32 +08003265
3266 SuccessOrExit(error = mEncoder.WriteUint64(time));
3267 SuccessOrExit(error = mEncoder.WriteInt8((int8_t)networkTimeStatus));
3268
3269exit:
3270 return error;
3271}
Joseph Newman4f99bcf2018-11-08 06:32:31 +00003272
3273void NcpBase::HandleTimeSyncUpdate(void *aContext)
3274{
3275 static_cast<NcpBase *>(aContext)->HandleTimeSyncUpdate();
3276}
3277
3278void NcpBase::HandleTimeSyncUpdate(void)
3279{
3280 mChangedPropsSet.AddProperty(SPINEL_PROP_THREAD_NETWORK_TIME);
Abtin Keshavarziana1adaac2020-05-11 10:24:58 -07003281 mUpdateChangedPropsTask.Post();
Joseph Newman4f99bcf2018-11-08 06:32:31 +00003282}
Jonathan Hui926b9e82019-07-15 21:16:37 -07003283#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
Shu Chene69019f2018-06-27 02:46:32 +08003284
Buke Po818998e2017-08-04 01:19:07 +08003285void NcpBase::HandleActiveScanResult_Jump(otActiveScanResult *aResult, void *aContext)
3286{
3287 static_cast<NcpBase *>(aContext)->HandleActiveScanResult(aResult);
3288}
3289
3290// ----------------------------------------------------------------------------
3291// MARK: Scan Results Glue
3292// ----------------------------------------------------------------------------
3293
3294void NcpBase::HandleActiveScanResult(otActiveScanResult *aResult)
3295{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003296 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08003297
3298 if (aResult)
3299 {
3300 uint8_t flags = static_cast<uint8_t>(aResult->mVersion << SPINEL_BEACON_THREAD_FLAG_VERSION_SHIFT);
3301
3302 if (aResult->mIsJoinable)
3303 {
3304 flags |= SPINEL_BEACON_THREAD_FLAG_JOINABLE;
3305 }
3306
3307 if (aResult->mIsNative)
3308 {
3309 flags |= SPINEL_BEACON_THREAD_FLAG_NATIVE;
3310 }
3311
Yakun Xub8333732018-06-21 04:15:13 +08003312 SuccessOrExit(error = mEncoder.BeginFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0,
3313 SPINEL_CMD_PROP_VALUE_INSERTED, SPINEL_PROP_MAC_SCAN_BEACON));
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003314 SuccessOrExit(error = mEncoder.WriteUint8(aResult->mChannel));
3315 SuccessOrExit(error = mEncoder.WriteInt8(aResult->mRssi));
Buke Po818998e2017-08-04 01:19:07 +08003316
Yakun Xub8333732018-06-21 04:15:13 +08003317 SuccessOrExit(error = mEncoder.OpenStruct()); // "mac-layer data"
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003318 SuccessOrExit(error = mEncoder.WriteEui64(aResult->mExtAddress));
Yakun Xub8333732018-06-21 04:15:13 +08003319 SuccessOrExit(error = mEncoder.WriteUint16(0xffff)); // short address, not given
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003320 SuccessOrExit(error = mEncoder.WriteUint16(aResult->mPanId));
3321 SuccessOrExit(error = mEncoder.WriteUint8(aResult->mLqi));
3322 SuccessOrExit(error = mEncoder.CloseStruct());
3323
Yakun Xub8333732018-06-21 04:15:13 +08003324 SuccessOrExit(error = mEncoder.OpenStruct()); // "net-layer data"
3325 SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_PROTOCOL_TYPE_THREAD)); // type
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003326 SuccessOrExit(error = mEncoder.WriteUint8(flags));
3327 SuccessOrExit(error = mEncoder.WriteUtf8(aResult->mNetworkName.m8));
3328 SuccessOrExit(error = mEncoder.WriteDataWithLen(aResult->mExtendedPanId.m8, OT_EXT_PAN_ID_SIZE));
3329 SuccessOrExit(error = mEncoder.WriteDataWithLen(aResult->mSteeringData.m8, aResult->mSteeringData.mLength));
3330 SuccessOrExit(error = mEncoder.CloseStruct());
3331
3332 SuccessOrExit(error = mEncoder.EndFrame());
Buke Po818998e2017-08-04 01:19:07 +08003333 }
3334 else
3335 {
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07003336 // We are finished with the scan, send an unsolicited
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003337 // scan state update.
3338 mChangedPropsSet.AddProperty(SPINEL_PROP_MAC_SCAN_STATE);
Abtin Keshavarziana1adaac2020-05-11 10:24:58 -07003339 mUpdateChangedPropsTask.Post();
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003340 }
Buke Po818998e2017-08-04 01:19:07 +08003341
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003342exit:
3343
3344 if (error != OT_ERROR_NONE)
3345 {
3346 // We ran out of buffer adding a scan result so remember to send
3347 // an async `LAST_STATUS(NOMEM)` when buffer space becomes
Buke Po818998e2017-08-04 01:19:07 +08003348 // available.
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003349 mChangedPropsSet.AddLastStatus(SPINEL_STATUS_NOMEM);
Abtin Keshavarziana1adaac2020-05-11 10:24:58 -07003350 mUpdateChangedPropsTask.Post();
Buke Po818998e2017-08-04 01:19:07 +08003351 }
3352}
3353
3354void NcpBase::HandleEnergyScanResult_Jump(otEnergyScanResult *aResult, void *aContext)
3355{
3356 static_cast<NcpBase *>(aContext)->HandleEnergyScanResult(aResult);
3357}
3358
3359void NcpBase::HandleEnergyScanResult(otEnergyScanResult *aResult)
3360{
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003361 otError error = OT_ERROR_NONE;
Buke Po818998e2017-08-04 01:19:07 +08003362
3363 if (aResult)
3364 {
Yakun Xub8333732018-06-21 04:15:13 +08003365 SuccessOrExit(error = mEncoder.BeginFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0,
3366 SPINEL_CMD_PROP_VALUE_INSERTED, SPINEL_PROP_MAC_ENERGY_SCAN_RESULT));
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003367 SuccessOrExit(error = mEncoder.WriteUint8(aResult->mChannel));
3368 SuccessOrExit(error = mEncoder.WriteInt8(aResult->mMaxRssi));
3369 SuccessOrExit(error = mEncoder.EndFrame());
Buke Po818998e2017-08-04 01:19:07 +08003370 }
3371 else
3372 {
Abtin Keshavarzian92ba27a2017-10-13 09:18:37 -07003373 // We are finished with the scan, send an unsolicited
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003374 // scan state update.
3375 mChangedPropsSet.AddProperty(SPINEL_PROP_MAC_SCAN_STATE);
Abtin Keshavarziana1adaac2020-05-11 10:24:58 -07003376 mUpdateChangedPropsTask.Post();
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003377 }
Buke Po818998e2017-08-04 01:19:07 +08003378
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003379exit:
3380
3381 if (error != OT_ERROR_NONE)
3382 {
3383 mChangedPropsSet.AddLastStatus(SPINEL_STATUS_NOMEM);
Abtin Keshavarziana1adaac2020-05-11 10:24:58 -07003384 mUpdateChangedPropsTask.Post();
Buke Po818998e2017-08-04 01:19:07 +08003385 }
3386}
3387
Jonathan Hui31ffd162019-07-16 12:01:36 -07003388#if OPENTHREAD_CONFIG_JOINER_ENABLE
rongli90ee0a42018-08-09 02:18:53 +08003389void NcpBase::HandleJoinerCallback_Jump(otError aError, void *aContext)
3390{
3391 static_cast<NcpBase *>(aContext)->HandleJoinerCallback(aError);
3392}
3393
3394void NcpBase::HandleJoinerCallback(otError aError)
3395{
3396 switch (aError)
3397 {
3398 case OT_ERROR_NONE:
3399 mChangedPropsSet.AddLastStatus(SPINEL_STATUS_JOIN_SUCCESS);
3400 break;
3401 case OT_ERROR_SECURITY:
3402 mChangedPropsSet.AddLastStatus(SPINEL_STATUS_JOIN_SECURITY);
3403 break;
3404 case OT_ERROR_NOT_FOUND:
3405 mChangedPropsSet.AddLastStatus(SPINEL_STATUS_JOIN_NO_PEERS);
3406 break;
3407 case OT_ERROR_RESPONSE_TIMEOUT:
3408 mChangedPropsSet.AddLastStatus(SPINEL_STATUS_JOIN_RSP_TIMEOUT);
3409 break;
3410 default:
3411 mChangedPropsSet.AddLastStatus(SPINEL_STATUS_JOIN_FAILURE);
3412 break;
3413 }
3414
Abtin Keshavarziana1adaac2020-05-11 10:24:58 -07003415 mUpdateChangedPropsTask.Post();
rongli90ee0a42018-08-09 02:18:53 +08003416}
3417#endif
3418
Buke Po818998e2017-08-04 01:19:07 +08003419// ----------------------------------------------------------------------------
3420// MARK: Outbound Datagram Handling
3421// ----------------------------------------------------------------------------
3422
3423void NcpBase::HandleDatagramFromStack(otMessage *aMessage, void *aContext)
3424{
3425 static_cast<NcpBase *>(aContext)->HandleDatagramFromStack(aMessage);
3426}
3427
3428void NcpBase::HandleDatagramFromStack(otMessage *aMessage)
3429{
Jonathan Hui1326d642020-06-17 22:44:54 -07003430 VerifyOrExit(aMessage != nullptr, OT_NOOP);
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07003431
Duda, Lukasz9aa73402020-05-08 22:46:00 +02003432 // Do not forward frames larger than SPINEL payload size.
3433 VerifyOrExit(otMessageGetLength(aMessage) <= SPINEL_FRAME_MAX_COMMAND_PAYLOAD_SIZE, otMessageFree(aMessage));
3434
Jonathan Hui75407582020-05-08 20:43:40 -07003435 otMessageQueueEnqueue(&mMessageQueue, aMessage);
Abtin Keshavarzian9ce57b22017-12-05 18:33:53 -08003436
3437 // If there is no queued spinel command response, try to write/send
3438 // the datagram message immediately. If there is a queued response
3439 // or if currently out of buffer space, the IPv6 datagram message
3440 // will be sent from `HandleFrameRemovedFromNcpBuffer()` when buffer
3441 // space becomes available and after any pending spinel command
3442 // response.
3443
3444 if (IsResponseQueueEmpty())
3445 {
kangping49f36f82020-05-07 02:17:58 +08003446 IgnoreError(SendQueuedDatagramMessages());
Abtin Keshavarzian9ce57b22017-12-05 18:33:53 -08003447 }
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07003448
3449exit:
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07003450 return;
3451}
3452
3453otError NcpBase::SendDatagramMessage(otMessage *aMessage)
3454{
Yakun Xub8333732018-06-21 04:15:13 +08003455 otError error = OT_ERROR_NONE;
3456 uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0;
3457 bool isSecure = otMessageIsLinkSecurityEnabled(aMessage);
3458 spinel_prop_key_t propKey = isSecure ? SPINEL_PROP_STREAM_NET : SPINEL_PROP_STREAM_NET_INSECURE;
Buke Po818998e2017-08-04 01:19:07 +08003459
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07003460 SuccessOrExit(error = mEncoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_IS, propKey));
3461 SuccessOrExit(error = mEncoder.WriteUint16(otMessageGetLength(aMessage)));
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003462 SuccessOrExit(error = mEncoder.WriteMessage(aMessage));
Buke Po818998e2017-08-04 01:19:07 +08003463
Buke Po818998e2017-08-04 01:19:07 +08003464 // Append any metadata (rssi, lqi, channel, etc) here!
3465
Abtin Keshavarzian192df6c2017-09-27 23:04:53 -07003466 SuccessOrExit(error = mEncoder.EndFrame());
Buke Po818998e2017-08-04 01:19:07 +08003467
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07003468 if (isSecure)
Buke Po818998e2017-08-04 01:19:07 +08003469 {
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07003470 mOutboundSecureIpFrameCounter++;
Buke Po818998e2017-08-04 01:19:07 +08003471 }
3472 else
3473 {
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07003474 mOutboundInsecureIpFrameCounter++;
Buke Po818998e2017-08-04 01:19:07 +08003475 }
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07003476
3477exit:
3478 return error;
Buke Po818998e2017-08-04 01:19:07 +08003479}
3480
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07003481otError NcpBase::SendQueuedDatagramMessages(void)
3482{
Yakun Xub8333732018-06-21 04:15:13 +08003483 otError error = OT_ERROR_NONE;
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07003484 otMessage *message;
3485
Jonathan Hui1326d642020-06-17 22:44:54 -07003486 while ((message = otMessageQueueGetHead(&mMessageQueue)) != nullptr)
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07003487 {
3488 // Since an `otMessage` instance can be in one queue at a time,
3489 // it is first dequeued from `mMessageQueue` before attempting
3490 // to include it in a spinel frame by calling `SendDatagramMessage()`
3491 // If forming of the spinel frame fails, the message is enqueued
3492 // back at the front of `mMessageQueue`.
3493
Jonathan Huicf571102020-05-08 21:42:11 -07003494 otMessageQueueDequeue(&mMessageQueue, message);
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07003495
3496 error = SendDatagramMessage(message);
3497
3498 if (error != OT_ERROR_NONE)
3499 {
Jonathan Hui75407582020-05-08 20:43:40 -07003500 otMessageQueueEnqueueAtHead(&mMessageQueue, message);
Abtin Keshavarzian54fa0f12017-10-13 09:29:18 -07003501 }
3502
3503 SuccessOrExit(error);
3504 }
3505
3506exit:
3507 return error;
3508}
Buke Po818998e2017-08-04 01:19:07 +08003509
Jonathan Hui02da2062019-07-16 12:18:34 -07003510#if OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
Yakun Xub9b57cc2018-11-06 12:48:08 +08003511template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_UDP_FORWARD_STREAM>(void)
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003512{
Jonathan Hui1326d642020-06-17 22:44:54 -07003513 const uint8_t * framePtr = nullptr;
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003514 uint16_t frameLen = 0;
3515 const otIp6Address *peerAddr;
3516 uint16_t peerPort;
3517 uint16_t sockPort;
3518 otMessage * message;
Zhanglong Xiaf8909592018-11-06 04:48:39 +08003519 otError error = OT_ERROR_NONE;
3520 otMessageSettings msgSettings = {false, OT_MESSAGE_PRIORITY_NORMAL};
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003521
Zhanglong Xiaf8909592018-11-06 04:48:39 +08003522 message = otIp6NewMessage(mInstance, &msgSettings);
Jonathan Hui1326d642020-06-17 22:44:54 -07003523 VerifyOrExit(message != nullptr, error = OT_ERROR_NO_BUFS);
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003524
3525 SuccessOrExit(error = mDecoder.ReadDataWithLen(framePtr, frameLen));
3526 SuccessOrExit(error = mDecoder.ReadUint16(peerPort));
3527 SuccessOrExit(error = mDecoder.ReadIp6Address(peerAddr));
3528 SuccessOrExit(error = mDecoder.ReadUint16(sockPort));
3529
3530 SuccessOrExit(error = otMessageAppend(message, framePtr, static_cast<uint16_t>(frameLen)));
3531
Yakun Xub9b57cc2018-11-06 12:48:08 +08003532 otUdpForwardReceive(mInstance, message, peerPort, peerAddr, sockPort);
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003533
Yakun Xub9b57cc2018-11-06 12:48:08 +08003534 // `otUdpForwardReceive()` takes ownership of `message` (in both success
Jonathan Hui1326d642020-06-17 22:44:54 -07003535 // or failure cases). `message` is set to nullptr so it is not freed at
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003536 // exit.
Jonathan Hui1326d642020-06-17 22:44:54 -07003537 message = nullptr;
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003538
3539exit:
Jonathan Hui1326d642020-06-17 22:44:54 -07003540 if (message != nullptr)
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003541 {
3542 otMessageFree(message);
3543 }
3544
3545 return error;
3546}
3547
Yakun Xub9b57cc2018-11-06 12:48:08 +08003548void NcpBase::HandleUdpForwardStream(otMessage * aMessage,
3549 uint16_t aPeerPort,
3550 otIp6Address *aPeerAddr,
3551 uint16_t aSockPort,
3552 void * aContext)
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003553{
Yakun Xub9b57cc2018-11-06 12:48:08 +08003554 static_cast<NcpBase *>(aContext)->HandleUdpForwardStream(aMessage, aPeerPort, *aPeerAddr, aSockPort);
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003555}
3556
Yakun Xub9b57cc2018-11-06 12:48:08 +08003557void NcpBase::HandleUdpForwardStream(otMessage *aMessage, uint16_t aPeerPort, otIp6Address &aPeerAddr, uint16_t aPort)
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003558{
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003559 uint16_t length = otMessageGetLength(aMessage);
3560 uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0;
3561
Yakun Xub9b57cc2018-11-06 12:48:08 +08003562 SuccessOrExit(mEncoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_THREAD_UDP_FORWARD_STREAM));
Kamil Srokad7f8a5b2018-07-13 18:35:47 +02003563 SuccessOrExit(mEncoder.WriteUint16(length));
3564 SuccessOrExit(mEncoder.WriteMessage(aMessage));
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003565
Kamil Srokad7f8a5b2018-07-13 18:35:47 +02003566 SuccessOrExit(mEncoder.WriteUint16(aPeerPort));
3567 SuccessOrExit(mEncoder.WriteIp6Address(aPeerAddr));
3568 SuccessOrExit(mEncoder.WriteUint16(aPort));
3569 SuccessOrExit(mEncoder.EndFrame());
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003570
3571 // The `aMessage` is owned by the outbound frame and NCP buffer
3572 // after frame was finished/ended successfully. It will be freed
3573 // when the frame is successfully sent and removed.
3574
Jonathan Hui1326d642020-06-17 22:44:54 -07003575 aMessage = nullptr;
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003576
3577exit:
3578
Jonathan Hui1326d642020-06-17 22:44:54 -07003579 if (aMessage != nullptr)
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003580 {
3581 otMessageFree(aMessage);
3582 }
3583}
Jonathan Hui02da2062019-07-16 12:18:34 -07003584#endif // OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
Yakun Xu96a7e2d2018-07-10 04:25:23 +08003585
Buke Po818998e2017-08-04 01:19:07 +08003586// ----------------------------------------------------------------------------
Abtin Keshavarzian765c45c2018-11-09 08:59:20 -08003587// MARK: Pcap frame handling
3588// ----------------------------------------------------------------------------
3589
Yakun Xu504331e2019-01-29 04:31:15 +08003590void NcpBase::HandlePcapFrame(const otRadioFrame *aFrame, bool aIsTx, void *aContext)
Abtin Keshavarzian765c45c2018-11-09 08:59:20 -08003591{
Yakun Xu504331e2019-01-29 04:31:15 +08003592 static_cast<NcpBase *>(aContext)->HandlePcapFrame(aFrame, aIsTx);
Abtin Keshavarzian765c45c2018-11-09 08:59:20 -08003593}
3594
Yakun Xu504331e2019-01-29 04:31:15 +08003595void NcpBase::HandlePcapFrame(const otRadioFrame *aFrame, bool aIsTx)
Abtin Keshavarzian765c45c2018-11-09 08:59:20 -08003596{
3597 uint16_t flags = 0;
3598 uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0;
3599
Jonathan Huia4592232020-04-08 15:22:25 -07003600 VerifyOrExit(mPcapEnabled, OT_NOOP);
Abtin Keshavarzian765c45c2018-11-09 08:59:20 -08003601
Yakun Xu504331e2019-01-29 04:31:15 +08003602 if (aIsTx)
Abtin Keshavarzian765c45c2018-11-09 08:59:20 -08003603 {
3604 flags |= SPINEL_MD_FLAG_TX;
3605 }
3606
3607 SuccessOrExit(mEncoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_STREAM_RAW));
3608 SuccessOrExit(mEncoder.WriteUint16(aFrame->mLength));
3609
3610 SuccessOrExit(mEncoder.WriteData(aFrame->mPsdu, aFrame->mLength));
3611
3612 // Append metadata (rssi, etc)
3613 SuccessOrExit(mEncoder.WriteInt8(aFrame->mInfo.mRxInfo.mRssi)); // RSSI
3614 SuccessOrExit(mEncoder.WriteInt8(-128)); // Noise floor (Currently unused)
3615 SuccessOrExit(mEncoder.WriteUint16(flags)); // Flags
3616
3617 SuccessOrExit(mEncoder.OpenStruct()); // PHY-data
3618 // Empty for now
3619 SuccessOrExit(mEncoder.CloseStruct());
3620
3621 SuccessOrExit(mEncoder.OpenStruct()); // Vendor-data
3622 // Empty for now
3623 SuccessOrExit(mEncoder.CloseStruct());
3624
3625 SuccessOrExit(mEncoder.EndFrame());
3626
3627exit:
3628 return;
3629}
3630
3631template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_PCAP_ENABLED>(void)
3632{
3633 return mEncoder.WriteBool(mPcapEnabled);
3634}
3635
3636template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_PHY_PCAP_ENABLED>(void)
3637{
3638 otError error = OT_ERROR_NONE;
3639 bool enabled;
3640
3641 SuccessOrExit(error = mDecoder.ReadBool(enabled));
Jonathan Huia4592232020-04-08 15:22:25 -07003642 VerifyOrExit(enabled != mPcapEnabled, OT_NOOP);
Abtin Keshavarzian765c45c2018-11-09 08:59:20 -08003643
3644 mPcapEnabled = enabled;
3645
3646 if (mPcapEnabled)
3647 {
3648 otLinkSetPcapCallback(mInstance, &NcpBase::HandlePcapFrame, static_cast<void *>(this));
3649 }
3650 else
3651 {
Jonathan Hui1326d642020-06-17 22:44:54 -07003652 otLinkSetPcapCallback(mInstance, nullptr, nullptr);
Abtin Keshavarzian765c45c2018-11-09 08:59:20 -08003653 }
3654
3655exit:
3656 return error;
3657}
3658
3659// ----------------------------------------------------------------------------
Buke Po818998e2017-08-04 01:19:07 +08003660// MARK: Property/Status Changed
3661// ----------------------------------------------------------------------------
3662
Abtin Keshavarzian9ce38e02018-06-22 15:09:18 -07003663void NcpBase::HandleStateChanged(otChangedFlags aFlags, void *aContext)
Buke Po818998e2017-08-04 01:19:07 +08003664{
3665 NcpBase *ncp = static_cast<NcpBase *>(aContext);
3666
3667 ncp->mThreadChangedFlags |= aFlags;
Abtin Keshavarziana1adaac2020-05-11 10:24:58 -07003668 ncp->mUpdateChangedPropsTask.Post();
Buke Po818998e2017-08-04 01:19:07 +08003669}
3670
3671void NcpBase::ProcessThreadChangedFlags(void)
3672{
3673 static const struct
3674 {
Abtin Keshavarzian9ce38e02018-06-22 15:09:18 -07003675 otChangedFlags mThreadFlag;
Buke Po818998e2017-08-04 01:19:07 +08003676 spinel_prop_key_t mPropKey;
Yakun Xub8333732018-06-21 04:15:13 +08003677 } kFlags[] = {
3678 {OT_CHANGED_IP6_ADDRESS_ADDED, SPINEL_PROP_IPV6_ADDRESS_TABLE},
3679 {OT_CHANGED_IP6_ADDRESS_REMOVED, SPINEL_PROP_IPV6_ADDRESS_TABLE},
3680 {OT_CHANGED_THREAD_ROLE, SPINEL_PROP_NET_ROLE},
3681 {OT_CHANGED_THREAD_LL_ADDR, SPINEL_PROP_IPV6_LL_ADDR},
3682 {OT_CHANGED_THREAD_ML_ADDR, SPINEL_PROP_IPV6_ML_ADDR},
3683 {OT_CHANGED_THREAD_PARTITION_ID, SPINEL_PROP_NET_PARTITION_ID},
3684 {OT_CHANGED_THREAD_KEY_SEQUENCE_COUNTER, SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER},
3685 {OT_CHANGED_THREAD_NETDATA, SPINEL_PROP_THREAD_LEADER_NETWORK_DATA},
3686 {OT_CHANGED_THREAD_CHILD_ADDED, SPINEL_PROP_THREAD_CHILD_TABLE},
3687 {OT_CHANGED_THREAD_CHILD_REMOVED, SPINEL_PROP_THREAD_CHILD_TABLE},
Jonathan Hui98fb9df2019-10-09 15:01:32 -07003688 {OT_CHANGED_IP6_MULTICAST_SUBSCRIBED, SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE},
3689 {OT_CHANGED_IP6_MULTICAST_UNSUBSCRIBED, SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE},
Yakun Xub8333732018-06-21 04:15:13 +08003690 {OT_CHANGED_THREAD_CHANNEL, SPINEL_PROP_PHY_CHAN},
3691 {OT_CHANGED_THREAD_PANID, SPINEL_PROP_MAC_15_4_PANID},
3692 {OT_CHANGED_THREAD_NETWORK_NAME, SPINEL_PROP_NET_NETWORK_NAME},
3693 {OT_CHANGED_THREAD_EXT_PANID, SPINEL_PROP_NET_XPANID},
Simon Linb5b97ae2020-03-10 23:55:25 +08003694 {OT_CHANGED_THREAD_RLOC_ADDED, SPINEL_PROP_IPV6_ADDRESS_TABLE},
3695 {OT_CHANGED_THREAD_RLOC_REMOVED, SPINEL_PROP_IPV6_ADDRESS_TABLE},
Yakun Xub8333732018-06-21 04:15:13 +08003696 {OT_CHANGED_MASTER_KEY, SPINEL_PROP_NET_MASTER_KEY},
3697 {OT_CHANGED_PSKC, SPINEL_PROP_NET_PSKC},
3698 {OT_CHANGED_CHANNEL_MANAGER_NEW_CHANNEL, SPINEL_PROP_CHANNEL_MANAGER_NEW_CHANNEL},
Abtin Keshavarzian31698ec2018-07-02 08:43:45 -07003699 {OT_CHANGED_SUPPORTED_CHANNEL_MASK, SPINEL_PROP_PHY_CHAN_SUPPORTED},
Buke Po818998e2017-08-04 01:19:07 +08003700 };
3701
Jonathan Huia4592232020-04-08 15:22:25 -07003702 VerifyOrExit(mThreadChangedFlags != 0, OT_NOOP);
Buke Po818998e2017-08-04 01:19:07 +08003703
3704 // If thread role has changed, check for possible "join" error.
3705
3706 if ((mThreadChangedFlags & OT_CHANGED_THREAD_ROLE) != 0)
3707 {
3708 if (mRequireJoinExistingNetwork)
3709 {
3710 switch (otThreadGetDeviceRole(mInstance))
3711 {
3712 case OT_DEVICE_ROLE_DETACHED:
3713 case OT_DEVICE_ROLE_DISABLED:
3714 break;
3715
3716 default:
3717 mRequireJoinExistingNetwork = false;
3718 mChangedPropsSet.AddProperty(SPINEL_PROP_NET_REQUIRE_JOIN_EXISTING);
3719 break;
3720 }
3721
Yakun Xub8333732018-06-21 04:15:13 +08003722 if ((otThreadGetDeviceRole(mInstance) == OT_DEVICE_ROLE_LEADER) && otThreadIsSingleton(mInstance)
Jonathan Hui02da2062019-07-16 12:18:34 -07003723#if OPENTHREAD_CONFIG_LEGACY_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08003724 && !mLegacyNodeDidJoin
3725#endif
Yakun Xub8333732018-06-21 04:15:13 +08003726 )
Buke Po818998e2017-08-04 01:19:07 +08003727 {
3728 mThreadChangedFlags &= ~static_cast<uint32_t>(OT_CHANGED_THREAD_PARTITION_ID);
kangping49f36f82020-05-07 02:17:58 +08003729 IgnoreError(otThreadSetEnabled(mInstance, false));
Buke Po818998e2017-08-04 01:19:07 +08003730
3731 mChangedPropsSet.AddProperty(SPINEL_PROP_NET_STACK_UP);
3732 mChangedPropsSet.AddLastStatus(SPINEL_STATUS_JOIN_FAILURE);
3733 }
3734 }
3735 }
3736
3737 // Convert OT_CHANGED flags to corresponding NCP property update.
3738
Simon Lin5e9b2812020-07-22 00:41:40 +08003739 for (auto flag : kFlags)
Buke Po818998e2017-08-04 01:19:07 +08003740 {
Simon Lin5e9b2812020-07-22 00:41:40 +08003741 uint32_t threadFlag = flag.mThreadFlag;
Buke Po818998e2017-08-04 01:19:07 +08003742
3743 if (mThreadChangedFlags & threadFlag)
3744 {
Simon Lin5e9b2812020-07-22 00:41:40 +08003745 spinel_prop_key_t propKey = flag.mPropKey;
Yakun Xub8333732018-06-21 04:15:13 +08003746 bool shouldAddProperty = true;
Abtin Keshavarzian73922002017-10-31 14:15:04 -07003747
3748 // Child table changes are reported using the `HandleChildAdded()` and
3749 // `HandleChildRemoved()` callbacks emitting spinel `VALUE_INSERTED` and
3750 // `VALUE_REMOVED` async spinel frames. If the spinel frames could not be
3751 // added (e.g., out of NCP buffer) from the above callbacks, the flag
3752 // `mShouldEmitChildTableUpdate` is set to `true` so that the entire
3753 // child table is emitted as an unsolicited `VALUE_IS` update.
3754
3755 if (propKey == SPINEL_PROP_THREAD_CHILD_TABLE)
3756 {
Yakun Xub8333732018-06-21 04:15:13 +08003757 shouldAddProperty = mShouldEmitChildTableUpdate;
Abtin Keshavarzian73922002017-10-31 14:15:04 -07003758 mShouldEmitChildTableUpdate = false;
3759 }
3760
3761 if (shouldAddProperty)
3762 {
3763 mChangedPropsSet.AddProperty(propKey);
3764 }
Buke Po818998e2017-08-04 01:19:07 +08003765
3766 if (threadFlag == OT_CHANGED_THREAD_NETDATA)
3767 {
3768 mChangedPropsSet.AddProperty(SPINEL_PROP_THREAD_ON_MESH_NETS);
3769 mChangedPropsSet.AddProperty(SPINEL_PROP_THREAD_OFF_MESH_ROUTES);
3770 }
3771
3772 mThreadChangedFlags &= ~threadFlag;
Jonathan Huia4592232020-04-08 15:22:25 -07003773 VerifyOrExit(mThreadChangedFlags != 0, OT_NOOP);
Buke Po818998e2017-08-04 01:19:07 +08003774 }
3775 }
3776
3777 // Clear any remaining ThreadFlag that has no matching
Simon Linb5b97ae2020-03-10 23:55:25 +08003778 // NCP property update (e.g., OT_CHANGED_SECURITY_POLICY)
Buke Po818998e2017-08-04 01:19:07 +08003779
3780 mThreadChangedFlags = 0;
3781
3782exit:
3783 return;
3784}
3785
Yakun Xub8333732018-06-21 04:15:13 +08003786} // namespace Ncp
3787} // namespace ot
Buke Po818998e2017-08-04 01:19:07 +08003788
3789// ----------------------------------------------------------------------------
3790// MARK: Legacy network APIs
3791// ----------------------------------------------------------------------------
3792
3793void otNcpRegisterLegacyHandlers(const otNcpLegacyHandlers *aHandlers)
3794{
Jonathan Hui02da2062019-07-16 12:18:34 -07003795#if OPENTHREAD_CONFIG_LEGACY_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08003796 ot::Ncp::NcpBase *ncp = ot::Ncp::NcpBase::GetNcpInstance();
3797
Jonathan Hui1326d642020-06-17 22:44:54 -07003798 if (ncp != nullptr)
Buke Po818998e2017-08-04 01:19:07 +08003799 {
3800 ncp->RegisterLegacyHandlers(aHandlers);
3801 }
3802
3803#else
3804 OT_UNUSED_VARIABLE(aHandlers);
3805#endif
3806}
3807
3808void otNcpHandleDidReceiveNewLegacyUlaPrefix(const uint8_t *aUlaPrefix)
3809{
Jonathan Hui02da2062019-07-16 12:18:34 -07003810#if OPENTHREAD_CONFIG_LEGACY_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08003811 ot::Ncp::NcpBase *ncp = ot::Ncp::NcpBase::GetNcpInstance();
3812
Jonathan Hui1326d642020-06-17 22:44:54 -07003813 if (ncp != nullptr)
Buke Po818998e2017-08-04 01:19:07 +08003814 {
3815 ncp->HandleDidReceiveNewLegacyUlaPrefix(aUlaPrefix);
3816 }
3817
3818#else
3819 OT_UNUSED_VARIABLE(aUlaPrefix);
3820#endif
3821}
3822
3823void otNcpHandleLegacyNodeDidJoin(const otExtAddress *aExtAddr)
3824{
Jonathan Hui02da2062019-07-16 12:18:34 -07003825#if OPENTHREAD_CONFIG_LEGACY_ENABLE
Buke Po818998e2017-08-04 01:19:07 +08003826 ot::Ncp::NcpBase *ncp = ot::Ncp::NcpBase::GetNcpInstance();
3827
Jonathan Hui1326d642020-06-17 22:44:54 -07003828 if (ncp != nullptr)
Buke Po818998e2017-08-04 01:19:07 +08003829 {
3830 ncp->HandleLegacyNodeDidJoin(aExtAddr);
3831 }
3832
3833#else
3834 OT_UNUSED_VARIABLE(aExtAddr);
3835#endif
3836}
3837
3838#endif // OPENTHREAD_MTD || OPENTHREAD_FTD