xref: /aosp_15_r20/external/ot-br-posix/src/utils/thread_helper.hpp (revision 4a64e381480ef79f0532b2421e44e6ee336b8e0d)
1 /*
2  *    Copyright (c) 2020, The OpenThread Authors.
3  *    All rights reserved.
4  *
5  *    Redistribution and use in source and binary forms, with or without
6  *    modification, are permitted provided that the following conditions are met:
7  *    1. Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *    2. Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *    3. Neither the name of the copyright holder nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *    POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file includes definitions for Thread helper.
32  */
33 
34 #ifndef OTBR_THREAD_HELPER_HPP_
35 #define OTBR_THREAD_HELPER_HPP_
36 
37 #include "openthread-br/config.h"
38 
39 #include <chrono>
40 #include <functional>
41 #include <map>
42 #include <random>
43 #include <string>
44 #include <vector>
45 
46 #include <openthread/border_routing.h>
47 #include <openthread/instance.h>
48 #include <openthread/ip6.h>
49 #include <openthread/jam_detection.h>
50 #include <openthread/joiner.h>
51 #include <openthread/netdata.h>
52 #include <openthread/thread.h>
53 #include "mdns/mdns.hpp"
54 #if OTBR_ENABLE_TELEMETRY_DATA_API
55 #include "proto/thread_telemetry.pb.h"
56 #endif
57 
58 namespace otbr {
59 namespace Ncp {
60 class RcpHost;
61 }
62 } // namespace otbr
63 
64 namespace otbr {
65 namespace agent {
66 
67 /**
68  * This class implements Thread helper.
69  */
70 class ThreadHelper
71 {
72 public:
73     using DeviceRoleHandler       = std::function<void(otDeviceRole)>;
74     using ScanHandler             = std::function<void(otError, const std::vector<otActiveScanResult> &)>;
75     using EnergyScanHandler       = std::function<void(otError, const std::vector<otEnergyScanResult> &)>;
76     using ResultHandler           = std::function<void(otError)>;
77     using AttachHandler           = std::function<void(otError, int64_t)>;
78     using UpdateMeshCopTxtHandler = std::function<void(std::map<std::string, std::vector<uint8_t>>)>;
79     using DatasetChangeHandler    = std::function<void(const otOperationalDatasetTlvs &)>;
80 #if OTBR_ENABLE_DHCP6_PD
81     using Dhcp6PdStateCallback = std::function<void(otBorderRoutingDhcp6PdState)>;
82 #endif
83 
84     /**
85      * The constructor of a Thread helper.
86      *
87      * @param[in] aInstance  The Thread instance.
88      * @param[in] aHost      The Thread controller.
89      */
90     ThreadHelper(otInstance *aInstance, otbr::Ncp::RcpHost *aHost);
91 
92     /**
93      * This method adds a callback for device role change.
94      *
95      * @param[in] aHandler  The device role handler.
96      */
97     void AddDeviceRoleHandler(DeviceRoleHandler aHandler);
98 
99 #if OTBR_ENABLE_DHCP6_PD
100     /**
101      * This method adds a callback for DHCPv6 PD state change.
102      *
103      * @param[in] aCallback  The DHCPv6 PD state change callback.
104      */
105     void SetDhcp6PdStateCallback(Dhcp6PdStateCallback aCallback);
106 #endif
107 
108     /**
109      * This method adds a callback for active dataset change.
110      *
111      * @param[in]  aHandler   The active dataset change handler.
112      */
113     void AddActiveDatasetChangeHandler(DatasetChangeHandler aHandler);
114 
115     /**
116      * This method permits unsecure join on port.
117      *
118      * @param[in] aPort     The port number.
119      * @param[in] aSeconds  The timeout to close the port, 0 for never close.
120      *
121      * @returns The error value of underlying OpenThread api calls.
122      */
123     otError PermitUnsecureJoin(uint16_t aPort, uint32_t aSeconds);
124 
125     /**
126      * This method performs a Thread network scan.
127      *
128      * @param[in] aHandler  The scan result handler.
129      */
130     void Scan(ScanHandler aHandler);
131 
132     /**
133      * This method performs an IEEE 802.15.4 Energy Scan.
134      *
135      * @param[in] aScanDuration  The duration for the scan, in milliseconds.
136      * @param[in] aHandler       The scan result handler.
137      */
138     void EnergyScan(uint32_t aScanDuration, EnergyScanHandler aHandler);
139 
140     /**
141      * This method attaches the device to the Thread network.
142      *
143      * @note The joiner start and the attach proccesses are exclusive
144      *
145      * @param[in] aNetworkName  The network name.
146      * @param[in] aPanId        The pan id, UINT16_MAX for random.
147      * @param[in] aExtPanId     The extended pan id, UINT64_MAX for random.
148      * @param[in] aNetworkKey   The network key, empty for random.
149      * @param[in] aPSKc         The pre-shared commissioner key, empty for random.
150      * @param[in] aChannelMask  A bitmask for valid channels, will random select one.
151      * @param[in] aHandler      The attach result handler.
152      */
153     void Attach(const std::string          &aNetworkName,
154                 uint16_t                    aPanId,
155                 uint64_t                    aExtPanId,
156                 const std::vector<uint8_t> &aNetworkKey,
157                 const std::vector<uint8_t> &aPSKc,
158                 uint32_t                    aChannelMask,
159                 AttachHandler               aHandler);
160 
161     /**
162      * This method detaches the device from the Thread network.
163      *
164      * @returns The error value of underlying OpenThread API calls.
165      */
166     otError Detach(void);
167 
168     /**
169      * This method attaches the device to the Thread network.
170      *
171      * @note The joiner start and the attach proccesses are exclusive, and the
172      *       network parameter will be set through the active dataset.
173      *
174      * @param[in] aHandler  The attach result handler.
175      */
176     void Attach(AttachHandler aHandler);
177 
178     /**
179      * This method makes all nodes in the current network attach to the network specified by the dataset TLVs.
180      *
181      * @param[in] aDatasetTlvs  The dataset TLVs.
182      * @param[in] aHandler      The result handler.
183      */
184     void AttachAllNodesTo(const std::vector<uint8_t> &aDatasetTlvs, AttachHandler aHandler);
185 
186     /**
187      * This method resets the OpenThread stack.
188      *
189      * @returns The error value of underlying OpenThread api calls.
190      */
191     otError Reset(void);
192 
193     /**
194      * This method triggers a thread join process.
195      *
196      * @note The joiner start and the attach proccesses are exclusive
197      *
198      * @param[in] aPskd             The pre-shared key for device.
199      * @param[in] aProvisioningUrl  The provision url.
200      * @param[in] aVendorName       The vendor name.
201      * @param[in] aVendorModel      The vendor model.
202      * @param[in] aVendorSwVersion  The vendor software version.
203      * @param[in] aVendorData       The vendor custom data.
204      * @param[in] aHandler          The join result handler.
205      */
206     void JoinerStart(const std::string &aPskd,
207                      const std::string &aProvisioningUrl,
208                      const std::string &aVendorName,
209                      const std::string &aVendorModel,
210                      const std::string &aVendorSwVersion,
211                      const std::string &aVendorData,
212                      ResultHandler      aHandler);
213 
214     /**
215      * This method tries to restore the network after reboot
216      *
217      * @returns The error value of underlying OpenThread api calls.
218      */
219     otError TryResumeNetwork(void);
220 
221     /**
222      * This method returns the underlying OpenThread instance.
223      *
224      * @returns The underlying instance.
225      */
GetInstance(void)226     otInstance *GetInstance(void)
227     {
228         return mInstance;
229     }
230 
231     /**
232      * This method handles OpenThread state changed notification.
233      *
234      * @param[in] aFlags    A bit-field indicating specific state that has changed.  See `OT_CHANGED_*` definitions.
235      */
236     void StateChangedCallback(otChangedFlags aFlags);
237 
238 #if OTBR_ENABLE_DBUS_SERVER
239     /**
240      * This method sets a callback for calls of UpdateVendorMeshCopTxtEntries D-Bus API.
241      *
242      * @param[in] aHandler  The handler on MeshCoP TXT changes.
243      */
SetUpdateMeshCopTxtHandler(UpdateMeshCopTxtHandler aHandler)244     void SetUpdateMeshCopTxtHandler(UpdateMeshCopTxtHandler aHandler)
245     {
246         mUpdateMeshCopTxtHandler = std::move(aHandler);
247     }
248 
249     /**
250      * This method handles MeshCoP TXT updates done by UpdateVendorMeshCopTxtEntries D-Bus API.
251      *
252      * @param[in] aUpdate  The key-value pairs to be updated in the TXT record.
253      */
254     void OnUpdateMeshCopTxt(std::map<std::string, std::vector<uint8_t>> aUpdate);
255 #endif
256 
257     void DetachGracefully(ResultHandler aHandler);
258 
259 #if OTBR_ENABLE_TELEMETRY_DATA_API
260     /**
261      * This method populates the telemetry data with best effort. The best effort means, for a given
262      * telemetry, if its retrieval has error, it is left unpopulated and the process continues to
263      * retrieve the remaining telemetries instead of the immediately return. The error code
264      * OT_ERRROR_FAILED will be returned if there is one or more error(s) happened in the process.
265      *
266      * @param[in] aPublisher     The Mdns::Publisher to provide MDNS telemetry if it is not `nullptr`.
267      * @param[in] telemetryData  The telemetry data to be populated.
268      *
269      * @retval OTBR_ERROR_NONE  There is no error happened in the process.
270      * @retval OT_ERRROR_FAILED There is one or more error(s) happened in the process.
271      */
272     otError RetrieveTelemetryData(Mdns::Publisher *aPublisher, threadnetwork::TelemetryData &telemetryData);
273 #endif // OTBR_ENABLE_TELEMETRY_DATA_API
274 
275     /**
276      * This method logs OpenThread action result.
277      *
278      * @param[in] aAction  The action OpenThread performs.
279      * @param[in] aError   The action result.
280      */
281     static void LogOpenThreadResult(const char *aAction, otError aError);
282 
283     /**
284      * This method validates and updates a pending dataset do Thread network migration.
285      *
286      * This method validates that:
287      * 1. the given dataset doesn't contain a meshcop Pending Timestamp TLV or a meshcop Delay Timer TLV.
288      * 2. the given dataset has sufficient space to append a Pending Timestamp TLV and a Delay Timer TLV.
289      *
290      * If it's valid, the method will append a meshcop Pending Timestamp TLV with value being the current unix
291      * timestamp and a meshcop Delay Timer TLV with value being @p aDelayMilli.
292      *
293      * @param[in/out] aDatasetTlvs  The dataset to validate and process in TLVs format.
294      * @param[in]     aDelayMilli   The delay time for migration in milliseconds.
295      *
296      * @retval OT_ERROR_NONE          Dataset is valid to do Thread network migration.
297      * @retval OT_ERROR_INVALID_ARGS  Dataset is invalid to do Thread network migration.
298      */
299     static otError ProcessDatasetForMigration(otOperationalDatasetTlvs &aDatasetTlvs, uint32_t aDelayMilli);
300 
301 private:
302     static void ActiveScanHandler(otActiveScanResult *aResult, void *aThreadHelper);
303     void        ActiveScanHandler(otActiveScanResult *aResult);
304 
305     static void EnergyScanCallback(otEnergyScanResult *aResult, void *aThreadHelper);
306     void        EnergyScanCallback(otEnergyScanResult *aResult);
307 
308     static void JoinerCallback(otError aError, void *aThreadHelper);
309     void        JoinerCallback(otError aResult);
310 
311     static void MgmtSetResponseHandler(otError aResult, void *aContext);
312     void        MgmtSetResponseHandler(otError aResult);
313 
314     static void DetachGracefullyCallback(void *aContext);
315     void        DetachGracefullyCallback(void);
316 
317     void    RandomFill(void *aBuf, size_t size);
318     uint8_t RandomChannelFromChannelMask(uint32_t aChannelMask);
319 
320     void ActiveDatasetChangedCallback(void);
321 
322 #if OTBR_ENABLE_DHCP6_PD
323     static void BorderRoutingDhcp6PdCallback(otBorderRoutingDhcp6PdState aState, void *aThreadHelper);
324     void        BorderRoutingDhcp6PdCallback(otBorderRoutingDhcp6PdState aState);
325 #endif
326 #if OTBR_ENABLE_TELEMETRY_DATA_API
327 #if OTBR_ENABLE_BORDER_ROUTING
328     void RetrieveInfraLinkInfo(threadnetwork::TelemetryData::InfraLinkInfo &aInfraLinkInfo);
329     void RetrieveExternalRouteInfo(threadnetwork::TelemetryData::ExternalRoutes &aExternalRouteInfo);
330 #endif
331 #if OTBR_ENABLE_DHCP6_PD
332     void RetrievePdInfo(threadnetwork::TelemetryData::WpanBorderRouter *aWpanBorderRouter);
333     void RetrieveHashedPdPrefix(std::string *aHashedPdPrefix);
334     void RetrievePdProcessedRaInfo(threadnetwork::TelemetryData::PdProcessedRaInfo *aPdProcessedRaInfo);
335 #endif
336 #if OTBR_ENABLE_BORDER_AGENT
337     void RetrieveBorderAgentInfo(threadnetwork::TelemetryData::BorderAgentInfo *aBorderAgentInfo);
338 #endif
339 #endif // OTBR_ENABLE_TELEMETRY_DATA_API
340 
341     otInstance *mInstance;
342 
343     otbr::Ncp::RcpHost *mHost;
344 
345     ScanHandler                     mScanHandler;
346     std::vector<otActiveScanResult> mScanResults;
347     EnergyScanHandler               mEnergyScanHandler;
348     std::vector<otEnergyScanResult> mEnergyScanResults;
349 
350     std::vector<DeviceRoleHandler>    mDeviceRoleHandlers;
351     std::vector<DatasetChangeHandler> mActiveDatasetChangeHandlers;
352 
353     std::map<uint16_t, size_t> mUnsecurePortRefCounter;
354 
355     bool mWaitingMgmtSetResponse =
356         false; // During waiting for mgmt set response, calls to AttachHandler by StateChangedCallback will be ignored
357     int64_t       mAttachDelayMs = 0;
358     AttachHandler mAttachHandler;
359     ResultHandler mJoinerHandler;
360 
361     ResultHandler mDetachGracefullyHandler = nullptr;
362 
363     otOperationalDatasetTlvs mAttachPendingDatasetTlvs = {};
364 
365     std::random_device mRandomDevice;
366 
367 #if OTBR_ENABLE_DHCP6_PD
368     Dhcp6PdStateCallback mDhcp6PdCallback;
369 #endif
370 
371 #if OTBR_ENABLE_DBUS_SERVER
372     UpdateMeshCopTxtHandler mUpdateMeshCopTxtHandler;
373 #endif
374 
375 #if OTBR_ENABLE_TELEMETRY_DATA_API && (OTBR_ENABLE_NAT64 || OTBR_ENABLE_DHCP6_PD)
376     static constexpr uint8_t kNat64PdCommonHashSaltLength = 16;
377     uint8_t                  mNat64PdCommonSalt[kNat64PdCommonHashSaltLength];
378 #endif
379 };
380 
381 } // namespace agent
382 } // namespace otbr
383 
384 #endif // OTBR_THREAD_HELPER_HPP_
385