diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp index 49d2e7b89..9fc1d792a 100644 --- a/src/core/mac/mac.cpp +++ b/src/core/mac/mac.cpp @@ -1564,8 +1564,39 @@ void Mac::ReceiveDoneTask(Frame *aFrame, otError aError) SuccessOrExit(error = aFrame->ValidatePsdu()); aFrame->GetSrcAddr(srcaddr); + aFrame->GetDstAddr(dstaddr); neighbor = GetNetif().GetMle().GetNeighbor(srcaddr); + // Destination Address Filtering + switch (dstaddr.mLength) + { + case 0: + break; + + case sizeof(ShortAddress): + aFrame->GetDstPanId(panid); + VerifyOrExit((panid == kShortAddrBroadcast || panid == mPanId) && + ((mRxOnWhenIdle && dstaddr.mShortAddress == kShortAddrBroadcast) || + dstaddr.mShortAddress == mShortAddress), error = OT_ERROR_DESTINATION_ADDRESS_FILTERED); + + // Allow multicasts from neighbor routers if FFD + if (neighbor == NULL && dstaddr.mShortAddress == kShortAddrBroadcast && + (GetNetif().GetMle().GetDeviceMode() & Mle::ModeTlv::kModeFFD)) + { + neighbor = GetNetif().GetMle().GetRxOnlyNeighborRouter(srcaddr); + } + + break; + + case sizeof(ExtAddress): + aFrame->GetDstPanId(panid); + VerifyOrExit(panid == mPanId && + memcmp(&dstaddr.mExtAddress, &mExtAddress, sizeof(dstaddr.mExtAddress)) == 0, + error = OT_ERROR_DESTINATION_ADDRESS_FILTERED); + break; + } + + // Source Address Filtering switch (srcaddr.mLength) { case 0: @@ -1613,29 +1644,6 @@ void Mac::ReceiveDoneTask(Frame *aFrame, otError aError) #endif // OPENTHREAD_ENABLE_MAC_FILTER - // Destination Address Filtering - aFrame->GetDstAddr(dstaddr); - - switch (dstaddr.mLength) - { - case 0: - break; - - case sizeof(ShortAddress): - aFrame->GetDstPanId(panid); - VerifyOrExit((panid == kShortAddrBroadcast || panid == mPanId) && - ((mRxOnWhenIdle && dstaddr.mShortAddress == kShortAddrBroadcast) || - dstaddr.mShortAddress == mShortAddress), error = OT_ERROR_DESTINATION_ADDRESS_FILTERED); - break; - - case sizeof(ExtAddress): - aFrame->GetDstPanId(panid); - VerifyOrExit(panid == mPanId && - memcmp(&dstaddr.mExtAddress, &mExtAddress, sizeof(dstaddr.mExtAddress)) == 0, - error = OT_ERROR_DESTINATION_ADDRESS_FILTERED); - break; - } - // Increment counters if (dstaddr.mShortAddress == kShortAddrBroadcast) { diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index fa5e1e513..da3136691 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -3300,16 +3300,14 @@ Neighbor *MleRouter::GetNeighbor(uint16_t aAddress) } } - for (int i = 0; i <= kMaxRouterId; i++) + if (IsActiveRouter(aAddress)) { - if (i == mRouterId) - { - continue; - } + uint8_t routerId = GetRouterId(aAddress); + Router *router = &mRouters[routerId]; - if (mRouters[i].GetState() == Neighbor::kStateValid && mRouters[i].GetRloc16() == aAddress) + if (router->GetState() == Neighbor::kStateValid && router->GetRloc16() == aAddress) { - ExitNow(rval = &mRouters[i]); + ExitNow(rval = router); } } @@ -3471,6 +3469,54 @@ exit: return rval; } +Neighbor *MleRouter::GetRxOnlyNeighborRouter(const Mac::Address &aAddress) +{ + Neighbor *rval = NULL; + + VerifyOrExit(mRole == OT_DEVICE_ROLE_CHILD, rval = NULL); + + switch (aAddress.mLength) + { + case sizeof(aAddress.mShortAddress): + if (IsActiveRouter(aAddress.mShortAddress)) + { + uint8_t routerId = GetRouterId(aAddress.mShortAddress); + Router *router = &mRouters[routerId]; + + if (router->GetState() == Neighbor::kStateValid && + router->GetRloc16() == aAddress.mShortAddress) + { + ExitNow(rval = router); + } + } + + break; + + case sizeof(aAddress.mExtAddress): + for (int i = 0; i <= kMaxRouterId; i++) + { + if (i == mRouterId) + { + continue; + } + + if (mRouters[i].GetState() == Neighbor::kStateValid && + memcmp(&mRouters[i].GetExtAddress(), &aAddress.mExtAddress, sizeof(aAddress.mExtAddress)) == 0) + { + ExitNow(rval = &mRouters[i]); + } + } + + break; + + default: + break; + } + +exit: + return rval; +} + uint16_t MleRouter::GetNextHop(uint16_t aDestination) { uint8_t destinationId = GetRouterId(aDestination); diff --git a/src/core/thread/mle_router_ftd.hpp b/src/core/thread/mle_router_ftd.hpp index e9f8b60f2..3bb30e31a 100644 --- a/src/core/thread/mle_router_ftd.hpp +++ b/src/core/thread/mle_router_ftd.hpp @@ -503,6 +503,17 @@ public: */ Neighbor *GetNeighbor(const Ip6::Address &aAddress); + /** + * This method returns a pointer to a Neighbor object if a one-way link is maintained + * as in the instance of an FFD child with neighbor routers. + * + * @param[in] aAddress The address of the Neighbor. + * + * @returns A pointer to the Neighbor corresponding to @p aAddress, NULL otherwise. + * + */ + Neighbor *GetRxOnlyNeighborRouter(const Mac::Address &aAddress); + /** * This method retains diagnostic information for an attached child by Child ID or RLOC16. * diff --git a/src/core/thread/mle_router_mtd.hpp b/src/core/thread/mle_router_mtd.hpp index 2303ae954..08c5ea449 100644 --- a/src/core/thread/mle_router_mtd.hpp +++ b/src/core/thread/mle_router_mtd.hpp @@ -101,6 +101,7 @@ public: Neighbor *GetNeighbor(const Mac::ExtAddress &aAddress) { return Mle::GetNeighbor(aAddress); } Neighbor *GetNeighbor(const Mac::Address &aAddress) { return Mle::GetNeighbor(aAddress); } Neighbor *GetNeighbor(const Ip6::Address &aAddress) { return Mle::GetNeighbor(aAddress); } + Neighbor *GetRxOnlyNeighborRouter(const Mac::Address &aAddress) { OT_UNUSED_VARIABLE(aAddress); return NULL; } otError GetNextNeighborInfo(otNeighborInfoIterator &, otNeighborInfo &) { return OT_ERROR_NOT_IMPLEMENTED; }