[child-supervision] change how child supervision gets started/stopped (#2627)

This commit removes the `Start()/Stop()` APIs from `ChildSupervisor`
class. Instead `ChildSupervisor` class itself would decide when to
start/stop. It registers a `Notifier` callback to be notified when the
Thread role changes and/or when a child is added or removed. If MLE
operation is enabled and there is at least one "valid" child in the
child table, child supervision starts, otherwise it is stopped.
This commit is contained in:
Abtin Keshavarzian
2018-03-20 17:48:27 +00:00
committed by Jonathan Hui
parent 11f326068c
commit 302c999367
4 changed files with 58 additions and 22 deletions
+1 -1
View File
@@ -80,7 +80,7 @@ public:
*
* @param[in] aCallback A reference to callback instance.
* @param[in] aFlags A bit-field indicating specific state that has changed. See `OT_CHANGED_<STATE>`
* definitions in `types.h`.
* definitions in `instance.h`.
*
*/
typedef void (*Handler)(Callback &aCallback, uint32_t aFlags);
-2
View File
@@ -140,7 +140,6 @@ otError ThreadNetif::Up(void)
#if OPENTHREAD_ENABLE_CHANNEL_MONITOR
GetInstance().GetChannelMonitor().Start();
#endif
mChildSupervisor.Start();
mMleRouter.Enable();
mIsUp = true;
}
@@ -157,7 +156,6 @@ otError ThreadNetif::Down(void)
#if OPENTHREAD_ENABLE_CHANNEL_MONITOR
GetInstance().GetChannelMonitor().Stop();
#endif
mChildSupervisor.Stop();
mMleRouter.Disable();
mMeshForwarder.Stop();
GetIp6().RemoveNetif(*this);
+50 -17
View File
@@ -53,28 +53,15 @@ ChildSupervisor::ChildSupervisor(Instance &aInstance)
: InstanceLocator(aInstance)
, mSupervisionInterval(kDefaultSupervisionInterval)
, mTimer(aInstance, &ChildSupervisor::HandleTimer, this)
, mNotifierCallback(&ChildSupervisor::HandleStateChanged, this)
{
}
void ChildSupervisor::Start(void)
{
VerifyOrExit(mSupervisionInterval != 0);
VerifyOrExit(!mTimer.IsRunning());
mTimer.Start(kOneSecond);
exit:
return;
}
void ChildSupervisor::Stop(void)
{
mTimer.Stop();
aInstance.GetNotifier().RegisterCallback(mNotifierCallback);
}
void ChildSupervisor::SetSupervisionInterval(uint16_t aInterval)
{
mSupervisionInterval = aInterval;
Start();
CheckState();
}
Child *ChildSupervisor::GetDestination(const Message &aMessage) const
@@ -147,7 +134,7 @@ void ChildSupervisor::HandleTimer(void)
for (uint8_t i = 0; i < numChildren; i++, child++)
{
if (!child->IsStateValidOrRestoring())
if (child->GetState() != Child::kStateValid)
{
continue;
}
@@ -166,6 +153,52 @@ exit:
return;
}
void ChildSupervisor::CheckState(void)
{
bool shouldRun = false;
uint8_t numChildren = 0;
Mle::MleRouter &mle = GetInstance().Get<Mle::MleRouter>();
// Child Supervision should run if `mSupervisionInterval` is not
// zero, Thread MLE operation is enabled, and there is at least one
// "valid" child in the child table.
VerifyOrExit(mSupervisionInterval != 0);
VerifyOrExit(mle.GetRole() != OT_DEVICE_ROLE_DISABLED);
for (Child *child = mle.GetChildren(&numChildren); numChildren > 0; child++, numChildren--)
{
VerifyOrExit(child->GetState() != Child::kStateValid, shouldRun = true);
}
exit:
if (shouldRun && !mTimer.IsRunning())
{
mTimer.Start(kOneSecond);
otLogInfoUtil(GetInstance(), "Starting Child Supervision");
}
if (!shouldRun && mTimer.IsRunning())
{
mTimer.Stop();
otLogInfoUtil(GetInstance(), "Stopping Child Supervision");
}
}
void ChildSupervisor::HandleStateChanged(Notifier::Callback &aCallback, uint32_t aFlags)
{
aCallback.GetOwner<ChildSupervisor>().HandleStateChanged(aFlags);
}
void ChildSupervisor::HandleStateChanged(uint32_t aFlags)
{
if ((aFlags & (OT_CHANGED_THREAD_ROLE | OT_CHANGED_THREAD_CHILD_ADDED | OT_CHANGED_THREAD_CHILD_REMOVED)) != 0)
{
CheckState();
}
}
#endif // #if OPENTHREAD_FTD
SupervisionListener::SupervisionListener(Instance &aInstance)
+7 -2
View File
@@ -39,6 +39,7 @@
#include "common/locator.hpp"
#include "common/message.hpp"
#include "common/notifier.hpp"
#include "common/timer.hpp"
#include "mac/mac_frame.hpp"
#include "thread/topology.hpp"
@@ -155,11 +156,15 @@ private:
};
void SendMessage(Child &aChild);
void CheckState(void);
static void HandleTimer(Timer &aTimer);
void HandleTimer(void);
static void HandleStateChanged(Notifier::Callback &aCallback, uint32_t aFlags);
void HandleStateChanged(uint32_t aFlags);
uint16_t mSupervisionInterval;
TimerMilli mTimer;
uint16_t mSupervisionInterval;
TimerMilli mTimer;
Notifier::Callback mNotifierCallback;
};
#else // #if OPENTHREAD_ENABLE_CHILD_SUPERVISION && OPENTHREAD_FTD