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_MLE_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 class LinkMetricsManager : public InstanceLocator, private NonCopyable 104 { 105 friend class ot::Notifier; 106 friend class ot::UnitTester; 107 108 struct LinkMetricsData 109 { 110 uint8_t mLqi; ///< Link Quality Indicator. Value range: [0, 255]. 111 int8_t mRssi; ///< Receive Signal Strength Indicator. Value range: [-128, 0]. 112 uint8_t mLinkMargin; ///< Link Margin. The relative signal strength is recorded as 113 ///< db above the local noise floor. Value range: [0, 130]. 114 }; 115 116 enum SubjectState : uint8_t 117 { 118 kNotConfigured = 0, 119 kConfiguring, 120 kActive, 121 kRenewing, 122 kNotSupported, 123 }; 124 125 struct Subject : LinkedListEntry<Subject>, Clearable<Subject> 126 { 127 Mac::ExtAddress mExtAddress; ///< Use the extended address to identify the neighbor. 128 SubjectState mState; ///< Current State of the Subject 129 uint8_t mAttempts; ///< The count of attempt that has been made to 130 ///< configure EAP 131 TimeMilli mLastUpdateTime; ///< The time `mData` was updated last time 132 LinkMetricsData mData; 133 134 Subject *mNext; 135 Matchesot::Utils::LinkMetricsManager::Subject136 bool Matches(const Mac::ExtAddress &aExtAddress) const { return mExtAddress == aExtAddress; } 137 bool Matches(const LinkMetricsManager &aLinkMetricsMgr); 138 139 Error ConfigureEap(Instance &aInstance); 140 Error UnregisterEap(Instance &aInstance); 141 Error UpdateState(Instance &aInstance); 142 }; 143 144 public: 145 /** 146 * Initializes a `LinkMetricsManager` object. 147 * 148 * @param[in] aInstance A reference to the OpenThread instance. 149 */ 150 explicit LinkMetricsManager(Instance &aInstance); 151 152 /** 153 * Is the LinkMetricsManager feature enabled. 154 * 155 * @retval TRUE Link Metrics Manager is enabled. 156 * @retval FALSE Link Metrics Manager is not enabled. 157 */ IsEnabled(void)158 bool IsEnabled(void) { return mEnabled; } 159 160 /** 161 * Enable/Disable the LinkMetricsManager feature. 162 * 163 * @param[in] aEnable A boolean to indicate enable or disable. 164 */ 165 void SetEnabled(bool aEnable); 166 167 /** 168 * Get Link Metrics data of subject by the extended address. 169 * 170 * @param[in] aExtAddress A reference to the extended address of the subject. 171 * @param[out] aMetricsValues A reference to the MetricsValues object to place the result. 172 * 173 * @retval kErrorNone Successfully got the metrics value. 174 * @retval kErrorInvalidArgs The arguments are invalid. 175 * @retval kNotFound No neighbor with the given extended address is found. 176 */ 177 Error GetLinkMetricsValueByExtAddr(const Mac::ExtAddress &aExtAddress, LinkMetrics::MetricsValues &aMetricsValues); 178 179 private: 180 static constexpr uint16_t kTimeBeforeStartMilliSec = 5000; 181 static constexpr uint32_t kStateUpdateIntervalMilliSec = 150000; 182 static constexpr uint8_t kConfigureLinkMetricsMaxAttempts = 3; 183 #if OPENTHREAD_FTD 184 static constexpr uint8_t kMaximumSubjectToTrack = 128; 185 #elif OPENTHREAD_MTD 186 static constexpr uint8_t kMaximumSubjectToTrack = 1; 187 #endif 188 189 void Start(void); 190 void Stop(void); 191 void Update(void); 192 void UpdateSubjects(void); 193 void UpdateLinkMetricsStates(void); 194 void UnregisterAllSubjects(void); 195 void ReleaseAllSubjects(void); 196 197 void HandleNotifierEvents(Events aEvents); 198 void HandleTimer(void); 199 static void HandleMgmtResponse(const otIp6Address *aAddress, otLinkMetricsStatus aStatus, void *aContext); 200 void HandleMgmtResponse(const otIp6Address *aAddress, otLinkMetricsStatus aStatus); 201 static void HandleEnhAckIe(otShortAddress aShortAddress, 202 const otExtAddress *aExtAddress, 203 const otLinkMetricsValues *aMetricsValues, 204 void *aContext); 205 void HandleEnhAckIe(otShortAddress aShortAddress, 206 const otExtAddress *aExtAddress, 207 const otLinkMetricsValues *aMetricsValues); 208 209 using LinkMetricsMgrTimer = TimerMilliIn<LinkMetricsManager, &LinkMetricsManager::HandleTimer>; 210 211 Pool<Subject, kMaximumSubjectToTrack> mPool; 212 LinkedList<Subject> mSubjectList; 213 LinkMetricsMgrTimer mTimer; 214 bool mEnabled; 215 }; 216 217 /** 218 * @} 219 */ 220 221 } // namespace Utils 222 } // namespace ot 223 224 #endif // OPENTHREAD_CONFIG_LINK_METRICS_MANAGER_ENABLE 225 226 #endif // LINK_METRICS_MANAGER_HPP_ 227