blob: df42809c21d85857eecfd576ea4882ad43485ea3 [file] [log] [blame]
/*
* Copyright (c) 2023, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef LINK_METRICS_MANAGER_HPP_
#define LINK_METRICS_MANAGER_HPP_
#include "openthread-core-config.h"
#if OPENTHREAD_CONFIG_LINK_METRICS_MANAGER_ENABLE
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE == 0
#error \
"OPENTHREAD_CONFIG_LINK_METRICS_MANAGER_ENABLE can only be used when OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE is true"
#endif
#include <openthread/link_metrics.h>
#include "common/clearable.hpp"
#include "common/linked_list.hpp"
#include "common/locator.hpp"
#include "common/non_copyable.hpp"
#include "common/notifier.hpp"
#include "common/pool.hpp"
#include "common/time.hpp"
#include "common/timer.hpp"
#include "mac/mac_types.hpp"
#include "thread/link_metrics_types.hpp"
namespace ot {
class UnitTester;
namespace Utils {
/**
* @addtogroup utils-link-metrics-manager
*
* @brief
* This module includes definitions for Link Metrics Manager.
*
* @{
*/
/**
*
* Link Metrics Manager feature utilizes the Enhanced-ACK Based
* Probing (abbreviated as "EAP" below) to get the Link Metrics
* data of neighboring devices. It is a user of the Link Metrics
* feature.
*
* The feature works as follow:
* - Start/Stop
* The switch `OPENTHREAD_CONFIG_LINK_METRICS_MANAGER_ON_BY_DEFAULT`
* controls enabling/disabling this feature by default. The feature
* will only start to work after it joins a Thread network.
*
* A CLI interface is provided to enable/disable this feature.
*
* Once enabled, it will regularly check current neighbors (all
* devices in the neighbor table, including 'Child' and 'Router')
* and configure the probing with them if haven't done that.
* If disabled, it will clear the configuration with its subjects
* and the local data.
*
* - Maintenance
* The manager will regularly check the status of each subject. If
* it finds that the link metrics data for one subject hasn't been
* updated for `kStateUpdateIntervalMilliSec`, it will configure
* EAP with the subject again.
* The manager may find that some subject (neighbor) no longer
* exist when trying to configure EAP. It will remove the stale
* subject then.
*
* - Show data
* An OT API is provided to get the link metrics data of any
* subject (neighbor) by its extended address. In production, this
* data may be fetched by some other means like RPC.
*
*/
class LinkMetricsManager : public InstanceLocator, private NonCopyable
{
friend class ot::Notifier;
friend class ot::UnitTester;
struct LinkMetricsData
{
uint8_t mLqi; ///< Link Quality Indicator. Value range: [0, 255].
int8_t mRssi; ///< Receive Signal Strength Indicator. Value range: [-128, 0].
uint8_t mLinkMargin; ///< Link Margin. The relative signal strength is recorded as
///< db above the local noise floor. Value range: [0, 130].
};
enum SubjectState : uint8_t
{
kNotConfigured = 0,
kConfiguring,
kActive,
kRenewing,
kNotSupported,
};
struct Subject : LinkedListEntry<Subject>, Clearable<Subject>
{
Mac::ExtAddress mExtAddress; ///< Use the extended address to identify the neighbor.
SubjectState mState; ///< Current State of the Subject
uint8_t mAttempts; ///< The count of attempt that has been made to
///< configure EAP
TimeMilli mLastUpdateTime; ///< The time `mData` was updated last time
LinkMetricsData mData;
Subject *mNext;
bool Matches(const Mac::ExtAddress &aExtAddress) const { return mExtAddress == aExtAddress; }
bool Matches(const LinkMetricsManager &aLinkMetricsMgr);
Error ConfigureEap(Instance &aInstance);
Error UnregisterEap(Instance &aInstance);
Error UpdateState(Instance &aInstance);
};
public:
/**
* Initializes a `LinkMetricsManager` object.
*
* @param[in] aInstance A reference to the OpenThread instance.
*
*/
explicit LinkMetricsManager(Instance &aInstance);
/**
* Is the LinkMetricsManager feature enabled.
*
* @retval TRUE Link Metrics Manager is enabled.
* @retval FALSE Link Metrics Manager is not enabled.
*
*/
bool IsEnabled(void) { return mEnabled; }
/**
* Enable/Disable the LinkMetricsManager feature.
*
* @param[in] aEnable A boolean to indicate enable or disable.
*
*/
void SetEnabled(bool aEnable);
/**
* Get Link Metrics data of subject by the extended address.
*
* @param[in] aExtAddress A reference to the extended address of the subject.
* @param[out] aMetricsValues A reference to the MetricsValues object to place the result.
*
* @retval kErrorNone Successfully got the metrics value.
* @retval kErrorInvalidArgs The arguments are invalid.
* @retval kNotFound No neighbor with the given extended address is found.
*
*/
Error GetLinkMetricsValueByExtAddr(const Mac::ExtAddress &aExtAddress, LinkMetrics::MetricsValues &aMetricsValues);
private:
static constexpr uint16_t kTimeBeforeStartMilliSec = 5000;
static constexpr uint32_t kStateUpdateIntervalMilliSec = 150000;
static constexpr uint8_t kConfigureLinkMetricsMaxAttempts = 3;
#if OPENTHREAD_FTD
static constexpr uint8_t kMaximumSubjectToTrack = 128;
#elif OPENTHREAD_MTD
static constexpr uint8_t kMaximumSubjectToTrack = 1;
#endif
void Start(void);
void Stop(void);
void Update(void);
void UpdateSubjects(void);
void UpdateLinkMetricsStates(void);
void UnregisterAllSubjects(void);
void ReleaseAllSubjects(void);
void HandleNotifierEvents(Events aEvents);
void HandleTimer(void);
static void HandleMgmtResponse(const otIp6Address *aAddress, otLinkMetricsStatus aStatus, void *aContext);
void HandleMgmtResponse(const otIp6Address *aAddress, otLinkMetricsStatus aStatus);
static void HandleEnhAckIe(otShortAddress aShortAddress,
const otExtAddress *aExtAddress,
const otLinkMetricsValues *aMetricsValues,
void *aContext);
void HandleEnhAckIe(otShortAddress aShortAddress,
const otExtAddress *aExtAddress,
const otLinkMetricsValues *aMetricsValues);
using LinkMetricsMgrTimer = TimerMilliIn<LinkMetricsManager, &LinkMetricsManager::HandleTimer>;
Pool<Subject, kMaximumSubjectToTrack> mPool;
LinkedList<Subject> mSubjectList;
LinkMetricsMgrTimer mTimer;
bool mEnabled;
};
/**
* @}
*
*/
} // namespace Utils
} // namespace ot
#endif // OPENTHREAD_CONFIG_LINK_METRICS_MANAGER_ENABLE
#endif // LINK_METRICS_MANAGER_HPP_