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 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 * Is the LinkMetricsManager feature enabled. 156 * 157 * @retval TRUE Link Metrics Manager is enabled. 158 * @retval FALSE Link Metrics Manager is not enabled. 159 * 160 */ IsEnabled(void)161 bool IsEnabled(void) { return mEnabled; } 162 163 /** 164 * Enable/Disable the LinkMetricsManager feature. 165 * 166 * @param[in] aEnable A boolean to indicate enable or disable. 167 * 168 */ 169 void SetEnabled(bool aEnable); 170 171 /** 172 * Get Link Metrics data of subject by the extended address. 173 * 174 * @param[in] aExtAddress A reference to the extended address of the subject. 175 * @param[out] aMetricsValues A reference to the MetricsValues object to place the result. 176 * 177 * @retval kErrorNone Successfully got the metrics value. 178 * @retval kErrorInvalidArgs The arguments are invalid. 179 * @retval kNotFound No neighbor with the given extended address is found. 180 * 181 */ 182 Error GetLinkMetricsValueByExtAddr(const Mac::ExtAddress &aExtAddress, LinkMetrics::MetricsValues &aMetricsValues); 183 184 private: 185 static constexpr uint16_t kTimeBeforeStartMilliSec = 5000; 186 static constexpr uint32_t kStateUpdateIntervalMilliSec = 150000; 187 static constexpr uint8_t kConfigureLinkMetricsMaxAttempts = 3; 188 #if OPENTHREAD_FTD 189 static constexpr uint8_t kMaximumSubjectToTrack = 128; 190 #elif OPENTHREAD_MTD 191 static constexpr uint8_t kMaximumSubjectToTrack = 1; 192 #endif 193 194 void Start(void); 195 void Stop(void); 196 void Update(void); 197 void UpdateSubjects(void); 198 void UpdateLinkMetricsStates(void); 199 void UnregisterAllSubjects(void); 200 void ReleaseAllSubjects(void); 201 202 void HandleNotifierEvents(Events aEvents); 203 void HandleTimer(void); 204 static void HandleMgmtResponse(const otIp6Address *aAddress, otLinkMetricsStatus aStatus, void *aContext); 205 void HandleMgmtResponse(const otIp6Address *aAddress, otLinkMetricsStatus aStatus); 206 static void HandleEnhAckIe(otShortAddress aShortAddress, 207 const otExtAddress *aExtAddress, 208 const otLinkMetricsValues *aMetricsValues, 209 void *aContext); 210 void HandleEnhAckIe(otShortAddress aShortAddress, 211 const otExtAddress *aExtAddress, 212 const otLinkMetricsValues *aMetricsValues); 213 214 using LinkMetricsMgrTimer = TimerMilliIn<LinkMetricsManager, &LinkMetricsManager::HandleTimer>; 215 216 Pool<Subject, kMaximumSubjectToTrack> mPool; 217 LinkedList<Subject> mSubjectList; 218 LinkMetricsMgrTimer mTimer; 219 bool mEnabled; 220 }; 221 222 /** 223 * @} 224 * 225 */ 226 227 } // namespace Utils 228 } // namespace ot 229 230 #endif // OPENTHREAD_CONFIG_LINK_METRICS_MANAGER_ENABLE 231 232 #endif // LINK_METRICS_MANAGER_HPP_ 233