Add notifications on configuration and state changes from OpenThread. (#146)

Example state changes that will cause a notification:
- IPv6 address added/removed
- Device state (offline, detached, attached)
- Device role (disabled, detached, child, router, leader)
- Partition ID
- Key Sequence
- Child added/removed
This commit is contained in:
Jonathan Hui
2016-06-15 12:17:05 -07:00
committed by GitHub
parent c7f2d4b917
commit a7e34a6f17
13 changed files with 196 additions and 67 deletions
+18
View File
@@ -206,6 +206,24 @@ typedef struct otLinkModeConfig
uint8_t mNetworkData : 1;
} otLinkModeConfig;
/**
* This enumeration represents flags that indicate what configuration or state has changed within OpenThread.
*
*/
enum
{
OT_IP6_ADDRESS_ADDED = 1 << 0, ///< IPv6 address was added
OT_IP6_ADDRESS_REMOVED = 1 << 1, ///< IPv6 address was removed
OT_NET_STATE = 1 << 2, ///< Device state (offline, detached, attached) changed
OT_NET_ROLE = 1 << 3, ///< Device role (disabled, detached, child, router, leader) changed
OT_NET_PARTITION_ID = 1 << 4, ///< Partition ID changed
OT_NET_KEY_SEQUENCE = 1 << 5, ///< Thread Key Sequence changed
OT_THREAD_CHILD_ADDED = 1 << 6, ///< Child was added
OT_THREAD_CHILD_REMOVED = 1 << 7 ///< Child was removed
};
/**
* @}
*/
+18
View File
@@ -457,6 +457,24 @@ ThreadError otAddUnicastAddress(otNetifAddress *aAddress);
*/
ThreadError otRemoveUnicastAddress(otNetifAddress *aAddress);
/**
* This function pointer is called to notify certain configuration or state changes within OpenThread.
*
* @param[in] aFlags A bit-field indicating specific state that has changed.
* @param[in] aContext A pointer to application-specific context.
*
*/
typedef void (*otStateChangedCallback)(uint32_t aFlags, void *aContext);
/**
* This function registers a callback to indicate when certain configuration or state changes within OpenThread.
*
* @param[in] aCallback A pointer to a function that is called with certain configuration or state changes.
* @param[in] aContext A pointer to application-specific context.
*
*/
void otSetStateChangedCallback(otStateChangedCallback aCallback, void *aContext);
/**
* @}
*/
+6
View File
@@ -73,6 +73,7 @@ Mac::Mac(ThreadNetif &aThreadNetif):
mReceiveTimer(&HandleReceiveTimer, this),
mKeyManager(aThreadNetif.GetKeyManager()),
mMle(aThreadNetif.GetMle()),
mNetif(aThreadNetif),
mWhitelist()
{
sMac = this;
@@ -611,6 +612,11 @@ void Mac::SentFrame(bool aAcked)
if ((neighbor = mMle.GetNeighbor(destination)) != NULL)
{
if (neighbor->mState == Neighbor::kStateValid && mMle.GetChildId(neighbor->mValid.mRloc16) != 0)
{
mNetif.SetStateChangedFlags(OT_THREAD_CHILD_REMOVED);
}
neighbor->mState = Neighbor::kStateInvalid;
}
}
+1
View File
@@ -455,6 +455,7 @@ private:
KeyManager &mKeyManager;
Mle::MleRouter &mMle;
ThreadNetif &mNetif;
ExtAddress mExtAddress;
ShortAddress mShortAddress;
+27 -15
View File
@@ -43,30 +43,32 @@ Netif *Netif::sNetifListHead = NULL;
int Netif::sNextInterfaceId = 1;
Netif::Netif() :
mUnicastChangedTask(&HandleUnicastChangedTask, this)
mStateChangedTask(&HandleStateChangedTask, this)
{
mHandlers = NULL;
mCallbacks = NULL;
mUnicastAddresses = NULL;
mMulticastAddresses = NULL;
mInterfaceId = -1;
mAllRoutersSubscribed = false;
mNext = NULL;
mStateChangedFlags = 0;
}
ThreadError Netif::RegisterHandler(NetifHandler &aHandler)
ThreadError Netif::RegisterCallback(NetifCallback &aCallback)
{
ThreadError error = kThreadError_None;
for (NetifHandler *cur = mHandlers; cur; cur = cur->mNext)
for (NetifCallback *cur = mCallbacks; cur; cur = cur->mNext)
{
if (cur == &aHandler)
if (cur == &aCallback)
{
ExitNow(error = kThreadError_Busy);
}
}
aHandler.mNext = mHandlers;
mHandlers = &aHandler;
aCallback.mNext = mCallbacks;
mCallbacks = &aCallback;
exit:
return error;
@@ -283,7 +285,7 @@ ThreadError Netif::AddUnicastAddress(NetifUnicastAddress &aAddress)
if (!aAddress.GetAddress().IsRoutingLocator())
{
mUnicastChangedTask.Post();
SetStateChangedFlags(OT_IP6_ADDRESS_ADDED);
}
exit:
@@ -317,7 +319,7 @@ exit:
if (!aAddress.GetAddress().IsRoutingLocator())
{
mUnicastChangedTask.Post();
SetStateChangedFlags(OT_IP6_ADDRESS_REMOVED);
}
return error;
@@ -451,17 +453,27 @@ exit:
return rval;
}
void Netif::HandleUnicastChangedTask(void *aContext)
void Netif::SetStateChangedFlags(uint32_t aFlags)
{
Netif *obj = reinterpret_cast<Netif *>(aContext);
obj->HandleUnicastChangedTask();
mStateChangedFlags |= aFlags;
mStateChangedTask.Post();
}
void Netif::HandleUnicastChangedTask()
void Netif::HandleStateChangedTask(void *aContext)
{
for (NetifHandler *handler = mHandlers; handler; handler = handler->mNext)
Netif *obj = reinterpret_cast<Netif *>(aContext);
obj->HandleStateChangedTask();
}
void Netif::HandleStateChangedTask(void)
{
uint32_t flags = mStateChangedFlags;
mStateChangedFlags = 0;
for (NetifCallback *callback = mCallbacks; callback; callback = callback->mNext)
{
handler->HandleUnicastAddressesChanged();
callback->Callback(flags);
}
}
+34 -27
View File
@@ -157,38 +157,33 @@ private:
* This class implements network interface handlers.
*
*/
class NetifHandler
class NetifCallback
{
friend class Netif;
public:
/**
* This function pointer is called when the set of assigned unicast addresses change.
* This method sets the callback information.
*
* @param[in] aContext A pointer to arbitrary context information.
* @param[in] aCallback A pointer to a function that is called when configuration or state changes.
* @param[in] aContext A pointer to arbitrary context information.
*
*/
typedef void (*UnicastAddressesChangedHandler)(void *aContext);
/**
* This constructor initializes the network interface handlers.
*
* @param[in] aHandler A pointer to a function that is called when the set of assigned unicast addresses
* change.
* @param[in] aContext A pointer to arbitrary context information.
*
*/
NetifHandler(UnicastAddressesChangedHandler aHandler, void *aContext) {
mUnicastHandler = aHandler;
void Set(otStateChangedCallback aCallback, void *aContext) {
mCallback = aCallback;
mContext = aContext;
}
private:
void HandleUnicastAddressesChanged(void) { mUnicastHandler(mContext); }
void Callback(uint32_t aFlags) {
if (mCallback != NULL) {
mCallback(aFlags, mContext);
}
}
UnicastAddressesChangedHandler mUnicastHandler;
otStateChangedCallback mCallback;
void *mContext;
NetifHandler *mNext;
NetifCallback *mNext;
};
/**
@@ -313,14 +308,24 @@ public:
ThreadError UnsubscribeMulticast(const NetifMulticastAddress &aAddress);
/**
* This method registers a network interface handler.
* This method registers a network interface callback.
*
* @param[in] aHandler A reference to the handler.
* @param[in] aCallback A reference to the callback.
*
* @retval kThreadError_None Successfully registered the handler.
* @retval kThreadError_Busy The handler was already registered.
* @retval kThreadError_None Successfully registered the callback.
* @retval kThreadError_Busy The callback was already registered.
*/
ThreadError RegisterHandler(NetifHandler &aHandler);
ThreadError RegisterCallback(NetifCallback &aCallback);
/**
* This method schedules notification of @p aFlags.
*
* The @p aFlags are combined (bitwise-or) with other flags that have not been provided in a callback yet.
*
* @param[in] aFlags A bit-field indicating what configuration or state has changed.
*
*/
void SetStateChangedFlags(uint32_t aFlags);
/**
* This virtual method enqueues an IPv6 messages on this network interface.
@@ -424,17 +429,19 @@ public:
static int GetOnLinkNetif(const Address &aAddress);
private:
static void HandleUnicastChangedTask(void *aContext);
void HandleUnicastChangedTask(void);
static void HandleStateChangedTask(void *aContext);
void HandleStateChangedTask(void);
NetifHandler *mHandlers;
NetifCallback *mCallbacks;
NetifUnicastAddress *mUnicastAddresses;
NetifMulticastAddress *mMulticastAddresses;
int mInterfaceId;
bool mAllRoutersSubscribed;
Tasklet mUnicastChangedTask;
Tasklet mStateChangedTask;
Netif *mNext;
uint32_t mStateChangedFlags;
static Netif *sNetifListHead;
static int sNextInterfaceId;
};
+8
View File
@@ -49,6 +49,8 @@ namespace Thread {
// of of the features in the NCP.
ThreadNetif *sThreadNetif;
static Ip6::NetifCallback sNetifCallback;
#ifdef __cplusplus
extern "C" {
#endif
@@ -545,6 +547,12 @@ ThreadError otRemoveUnicastAddress(otNetifAddress *address)
return sThreadNetif->RemoveUnicastAddress(*static_cast<Ip6::NetifUnicastAddress *>(address));
}
void otSetStateChangedCallback(otStateChangedCallback aCallback, void *aContext)
{
sNetifCallback.Set(aCallback, aContext);
sThreadNetif->RegisterCallback(sNetifCallback);
}
ThreadError otEnable(void)
{
ThreadError error = kThreadError_None;
+1
View File
@@ -96,6 +96,7 @@ ThreadError KeyManager::ComputeKey(uint32_t aKeySequence, uint8_t *aKey)
uint32_t KeyManager::GetCurrentKeySequence() const
{
mNetif.SetStateChangedFlags(OT_NET_KEY_SEQUENCE);
return mCurrentKeySequence;
}
+39 -9
View File
@@ -59,8 +59,7 @@ Mle::Mle(ThreadNetif &aThreadNetif) :
mMesh(aThreadNetif.GetMeshForwarder()),
mMleRouter(aThreadNetif.GetMle()),
mNetworkData(aThreadNetif.GetNetworkDataLeader()),
mParentRequestTimer(&HandleParentRequestTimer, this),
mNetifHandler(&HandleUnicastAddressesChanged, this)
mParentRequestTimer(&HandleParentRequestTimer, this)
{
mDeviceState = kDeviceStateDisabled;
mDeviceMode = ModeTlv::kModeRxOnWhenIdle | ModeTlv::kModeSecureDataRequest | ModeTlv::kModeFFD |
@@ -135,7 +134,8 @@ Mle::Mle(ThreadNetif &aThreadNetif) :
mRealmLocalAllThreadNodes.GetAddress().m16[7] = HostSwap16(0x0001);
mNetif.SubscribeMulticast(mRealmLocalAllThreadNodes);
mNetif.RegisterHandler(mNetifHandler);
mNetifCallback.Set(&HandleNetifStateChanged, this);
mNetif.RegisterCallback(mNetifCallback);
}
ThreadError Mle::Start(void)
@@ -229,6 +229,11 @@ DeviceState Mle::GetDeviceState(void) const
ThreadError Mle::SetStateDetached(void)
{
if (mDeviceState != kDeviceStateDetached)
{
mNetif.SetStateChangedFlags(OT_NET_STATE | OT_NET_ROLE);
}
mAddressResolver.Clear();
mDeviceState = kDeviceStateDetached;
mParentRequestState = kParentIdle;
@@ -241,6 +246,16 @@ ThreadError Mle::SetStateDetached(void)
ThreadError Mle::SetStateChild(uint16_t aRloc16)
{
if (mDeviceState == kDeviceStateDetached)
{
mNetif.SetStateChangedFlags(OT_NET_STATE);
}
if (mDeviceState != kDeviceStateChild)
{
mNetif.SetStateChangedFlags(OT_NET_ROLE);
}
SetRloc16(aRloc16);
mDeviceState = kDeviceStateChild;
mParentRequestState = kParentIdle;
@@ -403,6 +418,18 @@ uint8_t Mle::GetLeaderId(void) const
return mLeaderData.GetLeaderRouterId();
}
void Mle::SetLeaderData(uint32_t aPartitionId, uint8_t aWeighting, uint8_t aLeaderRouterId)
{
if (mLeaderData.GetPartitionId() != aPartitionId)
{
mNetif.SetStateChangedFlags(OT_NET_PARTITION_ID);
}
mLeaderData.SetPartitionId(aPartitionId);
mLeaderData.SetWeighting(aWeighting);
mLeaderData.SetLeaderRouterId(aLeaderRouterId);
}
const Ip6::Address *Mle::GetMeshLocal16(void) const
{
return &mMeshLocal16.GetAddress();
@@ -695,14 +722,16 @@ exit:
return error;
}
void Mle::HandleUnicastAddressesChanged(void *aContext)
void Mle::HandleNetifStateChanged(uint32_t aFlags, void *aContext)
{
Mle *obj = reinterpret_cast<Mle *>(aContext);
obj->HandleUnicastAddressesChanged();
obj->HandleNetifStateChanged(aFlags);
}
void Mle::HandleUnicastAddressesChanged(void)
void Mle::HandleNetifStateChanged(uint32_t aFlags)
{
VerifyOrExit((aFlags & (OT_IP6_ADDRESS_ADDED | OT_IP6_ADDRESS_REMOVED)) != 0, ;);
if (!mNetif.IsUnicastAddress(mMeshLocal64.GetAddress()))
{
// Mesh Local EID was removed, choose a new one and add it back
@@ -723,6 +752,9 @@ void Mle::HandleUnicastAddressesChanged(void)
default:
break;
}
exit:
return;
}
void Mle::HandleParentRequestTimer(void *aContext)
@@ -1667,9 +1699,7 @@ ThreadError Mle::HandleChildIdResponse(const Message &aMessage, const Ip6::Messa
// Parent Attach Success
mParentRequestTimer.Stop();
mLeaderData.SetPartitionId(leaderData.GetPartitionId());
mLeaderData.SetWeighting(leaderData.GetWeighting());
mLeaderData.SetLeaderRouterId(leaderData.GetLeaderRouterId());
SetLeaderData(leaderData.GetPartitionId(), leaderData.GetWeighting(), leaderData.GetLeaderRouterId());
if ((mDeviceMode & ModeTlv::kModeRxOnWhenIdle) == 0)
{
+13 -3
View File
@@ -888,6 +888,16 @@ protected:
*/
ThreadError SetStateChild(uint16_t aRloc16);
/**
* This method sets the Leader's Partition ID, Weighting, and Router ID values.
*
* @param[in] aPartitionId The Leader's Parititon ID value.
* @param[in] aWeighting The Leader's Weighting value.
* @param[in] aLeaderRouterId The Leader's Router ID value.
*
*/
void SetLeaderData(uint32_t aPartitionId, uint8_t aWeighting, uint8_t aLeaderRouterId);
ThreadNetif &mNetif; ///< The Thread Network Interface object.
AddressResolver &mAddressResolver; ///< The Address Resolver object.
KeyManager &mKeyManager; ///< The Key Manager object.
@@ -928,8 +938,8 @@ private:
void GenerateNonce(const Mac::ExtAddress &aMacAddr, uint32_t aFrameCounter, uint8_t aSecurityLevel,
uint8_t *aNonce);
static void HandleUnicastAddressesChanged(void *aContext);
void HandleUnicastAddressesChanged(void);
static void HandleNetifStateChanged(uint32_t aFlags, void *aContext);
void HandleNetifStateChanged(uint32_t aFlags);
static void HandleParentRequestTimer(void *aContext);
void HandleParentRequestTimer(void);
static void HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo);
@@ -970,7 +980,7 @@ private:
Ip6::NetifMulticastAddress mLinkLocalAllThreadNodes;
Ip6::NetifMulticastAddress mRealmLocalAllThreadNodes;
Ip6::NetifHandler mNetifHandler;
Ip6::NetifCallback mNetifCallback;
};
} // namespace Mle
+24 -6
View File
@@ -227,9 +227,7 @@ ThreadError MleRouter::BecomeLeader(void)
memcpy(&mRouters[mRouterId].mMacAddr, mMac.GetExtAddress(), sizeof(mRouters[mRouterId].mMacAddr));
mLeaderData.SetPartitionId(otPlatRandomGet());
mLeaderData.SetWeighting(mLeaderWeight);
mLeaderData.SetLeaderRouterId(mRouterId);
SetLeaderData(otPlatRandomGet(), mLeaderWeight, mRouterId);
mNetworkData.Reset();
@@ -302,6 +300,16 @@ ThreadError MleRouter::HandleChildStart(otMleAttachFilter aFilter)
ThreadError MleRouter::SetStateRouter(uint16_t aRloc16)
{
if (mDeviceState == kDeviceStateDetached)
{
mNetif.SetStateChangedFlags(OT_NET_STATE);
}
if (mDeviceState != kDeviceStateRouter)
{
mNetif.SetStateChangedFlags(OT_NET_ROLE);
}
SetRloc16(aRloc16);
mDeviceState = kDeviceStateRouter;
mParentRequestState = kParentIdle;
@@ -318,6 +326,16 @@ ThreadError MleRouter::SetStateRouter(uint16_t aRloc16)
ThreadError MleRouter::SetStateLeader(uint16_t aRloc16)
{
if (mDeviceState == kDeviceStateDetached)
{
mNetif.SetStateChangedFlags(OT_NET_STATE);
}
if (mDeviceState != kDeviceStateLeader)
{
mNetif.SetStateChangedFlags(OT_NET_ROLE);
}
SetRloc16(aRloc16);
mDeviceState = kDeviceStateLeader;
mParentRequestState = kParentIdle;
@@ -819,9 +837,7 @@ ThreadError MleRouter::HandleLinkAccept(const Message &aMessage, const Ip6::Mess
// Leader Data
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kLeaderData, sizeof(leaderData), leaderData));
VerifyOrExit(leaderData.IsValid(), error = kThreadError_Parse);
mLeaderData.SetPartitionId(leaderData.GetPartitionId());
mLeaderData.SetWeighting(leaderData.GetWeighting());
mLeaderData.SetLeaderRouterId(leaderData.GetLeaderRouterId());
SetLeaderData(leaderData.GetPartitionId(), leaderData.GetWeighting(), leaderData.GetLeaderRouterId());
// Network Data
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kNetworkData, sizeof(networkData), networkData));
@@ -1456,6 +1472,7 @@ void MleRouter::HandleStateUpdateTimer(void)
if ((Timer::GetNow() - mChildren[i].mLastHeard) >= Timer::SecToMsec(mChildren[i].mTimeout))
{
mChildren[i].mState = Neighbor::kStateInvalid;
mNetif.SetStateChangedFlags(OT_THREAD_CHILD_REMOVED);
}
}
@@ -1842,6 +1859,7 @@ ThreadError MleRouter::SendChildIdResponse(Child *aChild)
}
aChild->mState = Neighbor::kStateValid;
mNetif.SetStateChangedFlags(OT_THREAD_CHILD_ADDED);
memset(&destination, 0, sizeof(destination));
destination.m16[0] = HostSwap16(0xfe80);
+6 -4
View File
@@ -224,7 +224,6 @@ static spinel_status_t ThreadErrorToSpinelStatus(ThreadError error)
// ----------------------------------------------------------------------------
NcpBase::NcpBase():
mNetifHandler(&HandleUnicastAddressesChanged, this),
mUpdateAddressesTask(&RunUpdateAddressesTask, this)
{
mSupportedChannelMask = (0xFFFF << 11); // Default to 2.4GHz 802.15.4 channels.
@@ -233,7 +232,7 @@ NcpBase::NcpBase():
sNcpContext = this;
assert(sThreadNetif != NULL);
sThreadNetif->RegisterHandler(mNetifHandler);
otSetStateChangedCallback(&HandleNetifStateChanged, this);
otSetReceiveIp6DatagramCallback(&HandleDatagramFromStack);
}
@@ -366,10 +365,13 @@ exit:
// MARK: Address Table Changed Glue
// ----------------------------------------------------------------------------
void NcpBase::HandleUnicastAddressesChanged(void *context)
void NcpBase::HandleNetifStateChanged(uint32_t flags, void *context)
{
NcpBase *obj = reinterpret_cast<NcpBase *>(context);
obj->mUpdateAddressesTask.Post();
if ((flags & (OT_IP6_ADDRESS_ADDED | OT_IP6_ADDRESS_REMOVED)) != 0)
{
obj->mUpdateAddressesTask.Post();
}
}
void NcpBase::RunUpdateAddressesTask(void *context)
+1 -3
View File
@@ -95,7 +95,7 @@ private:
void RunUpdateAddressesTask(void);
static void HandleUnicastAddressesChanged(void *context);
static void HandleNetifStateChanged(uint32_t flags, void *context);
private:
@@ -278,8 +278,6 @@ private:
private:
Ip6::NetifHandler mNetifHandler;
spinel_status_t mLastStatus;
uint32_t mSupportedChannelMask;