1 /* 2 * Copyright (c) 2023, 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 #ifndef LINK_METRICS_MANAGER_HPP_ 30 #define LINK_METRICS_MANAGER_HPP_ 31 32 #include "openthread-core-config.h" 33 34 #if OPENTHREAD_CONFIG_LINK_METRICS_MANAGER_ENABLE 35 36 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE == 0 37 #error \ 38 "OPENTHREAD_CONFIG_LINK_METRICS_MANAGER_ENABLE can only be used when OPENTHREAD_CONFIG_LINK_METRICS_INITIATOR_ENABLE is true" 39 #endif 40 41 #include <openthread/link_metrics.h> 42 43 #include "common/clearable.hpp" 44 #include "common/linked_list.hpp" 45 #include "common/locator.hpp" 46 #include "common/non_copyable.hpp" 47 #include "common/notifier.hpp" 48 #include "common/pool.hpp" 49 #include "common/time.hpp" 50 #include "common/timer.hpp" 51 #include "mac/mac_types.hpp" 52 #include "thread/link_metrics_types.hpp" 53 54 namespace ot { 55 class UnitTester; 56 namespace Utils { 57 58 /** 59 * @addtogroup utils-link-metrics-manager 60 * 61 * @brief 62 * This module includes definitions for Link Metrics Manager. 63 * 64 * @{ 65 */ 66 67 /** 68 * 69 * Link Metrics Manager feature utilizes the Enhanced-ACK Based 70 * Probing (abbreviated as "EAP" below) to get the Link Metrics 71 * data of neighboring devices. It is a user of the Link Metrics 72 * feature. 73 * 74 * The feature works as follow: 75 * - Start/Stop 76 * The switch `OPENTHREAD_CONFIG_LINK_METRICS_MANAGER_ON_BY_DEFAULT` 77 * controls enabling/disabling this feature by default. The feature 78 * will only start to work after it joins a Thread network. 79 * 80 * A CLI interface is provided to enable/disable this feature. 81 * 82 * Once enabled, it will regularly check current neighbors (all 83 * devices in the neighbor table, including 'Child' and 'Router') 84 * and configure the probing with them if haven't done that. 85 * If disabled, it will clear the configuration with its subjects 86 * and the local data. 87 * 88 * - Maintenance 89 * The manager will regularly check the status of each subject. If 90 * it finds that the link metrics data for one subject hasn't been 91 * updated for `kStateUpdateIntervalMilliSec`, it will configure 92 * EAP with the subject again. 93 * The manager may find that some subject (neighbor) no longer 94 * exist when trying to configure EAP. It will remove the stale 95 * subject then. 96 * 97 * - Show data 98 * An OT API is provided to get the link metrics data of any 99 * subject (neighbor) by its extended address. In production, this 100 * data may be fetched by some other means like RPC. 101 * 102 */ 103 104 class LinkMetricsManager : public InstanceLocator, private NonCopyable 105 { 106 friend class ot::Notifier; 107 friend class ot::UnitTester; 108 109 struct LinkMetricsData 110 { 111 uint8_t mLqi; ///< Link Quality Indicator. Value range: [0, 255]. 112 int8_t mRssi; ///< Receive Signal Strength Indicator. Value range: [-128, 0]. 113 uint8_t mLinkMargin; ///< Link Margin. The relative signal strength is recorded as 114 ///< db above the local noise floor. Value range: [0, 130]. 115 }; 116 117 enum SubjectState : uint8_t 118 { 119 kNotConfigured = 0, 120 kConfiguring, 121 kActive, 122 kRenewing, 123 kNotSupported, 124 }; 125 126 struct Subject : LinkedListEntry<Subject>, Clearable<Subject> 127 { 128 Mac::ExtAddress mExtAddress; ///< Use the extended address to identify the neighbor. 129 SubjectState mState; ///< Current State of the Subject 130 uint8_t mAttempts; ///< The count of attempt that has been made to 131 ///< configure EAP 132 TimeMilli mLastUpdateTime; ///< The time `mData` was updated last time 133 LinkMetricsData mData; 134 135 Subject *mNext; 136 Matchesot::Utils::LinkMetricsManager::Subject137 bool Matches(const Mac::ExtAddress &aExtAddress) const { return mExtAddress == aExtAddress; } 138 bool Matches(const LinkMetricsManager &aLinkMetricsMgr); 139 140 Error ConfigureEap(Instance &aInstance); 141 Error UnregisterEap(Instance &aInstance); 142 Error UpdateState(Instance &aInstance); 143 }; 144 145 public: 146 /** 147 * Initializes a `LinkMetricsManager` object. 148 * 149 * @param[in] aInstance A reference to the OpenThread instance. 150 * 151 */ 152 explicit LinkMetricsManager(Instance &aInstance); 153 154 /** 155 * Enable/Disable the LinkMetricsManager feature. 156 * 157 * @param[in] aEnable A boolean to indicate enable or disable. 158 * 159 */ 160 void SetEnabled(bool aEnable); 161 162 /** 163 * Get Link Metrics data of subject by the extended address. 164 * 165 * @param[in] aExtAddress A reference to the extended address of the subject. 166 * @param[out] aMetricsValues A reference to the MetricsValues object to place the result. 167 * 168 * @retval kErrorNone Successfully got the metrics value. 169 * @retval kErrorInvalidArgs The arguments are invalid. 170 * @retval kNotFound No neighbor with the given extended address is found. 171 * 172 */ 173 Error GetLinkMetricsValueByExtAddr(const Mac::ExtAddress &aExtAddress, LinkMetrics::MetricsValues &aMetricsValues); 174 175 private: 176 static constexpr uint16_t kTimeBeforeStartMilliSec = 5000; 177 static constexpr uint32_t kStateUpdateIntervalMilliSec = 150000; 178 static constexpr uint8_t kConfigureLinkMetricsMaxAttempts = 3; 179 #if OPENTHREAD_FTD 180 static constexpr uint8_t kMaximumSubjectToTrack = 128; 181 #elif OPENTHREAD_MTD 182 static constexpr uint8_t kMaximumSubjectToTrack = 1; 183 #endif 184 185 void Start(void); 186 void Stop(void); 187 void Update(void); 188 void UpdateSubjects(void); 189 void UpdateLinkMetricsStates(void); 190 void UnregisterAllSubjects(void); 191 void ReleaseAllSubjects(void); 192 193 void HandleNotifierEvents(Events aEvents); 194 void HandleTimer(void); 195 static void HandleMgmtResponse(const otIp6Address *aAddress, otLinkMetricsStatus aStatus, void *aContext); 196 void HandleMgmtResponse(const otIp6Address *aAddress, otLinkMetricsStatus aStatus); 197 static void HandleEnhAckIe(otShortAddress aShortAddress, 198 const otExtAddress *aExtAddress, 199 const otLinkMetricsValues *aMetricsValues, 200 void *aContext); 201 void HandleEnhAckIe(otShortAddress aShortAddress, 202 const otExtAddress *aExtAddress, 203 const otLinkMetricsValues *aMetricsValues); 204 205 using LinkMetricsMgrTimer = TimerMilliIn<LinkMetricsManager, &LinkMetricsManager::HandleTimer>; 206 207 Pool<Subject, kMaximumSubjectToTrack> mPool; 208 LinkedList<Subject> mSubjectList; 209 LinkMetricsMgrTimer mTimer; 210 bool mEnabled; 211 }; 212 213 /** 214 * @} 215 * 216 */ 217 218 } // namespace Utils 219 } // namespace ot 220 221 #endif // OPENTHREAD_CONFIG_LINK_METRICS_MANAGER_ENABLE 222 223 #endif // LINK_METRICS_MANAGER_HPP_ 224