/* * Copyright (c) 2017, 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. */ /** * @file * This file implements source address match controller. */ #include "src_match_controller.hpp" #if OPENTHREAD_FTD #include "instance/instance.hpp" namespace ot { RegisterLogModule("SrcMatchCtrl"); SourceMatchController::SourceMatchController(Instance &aInstance) : InstanceLocator(aInstance) , mEnabled(false) { ClearTable(); } void SourceMatchController::IncrementMessageCount(Child &aChild) { if (aChild.GetIndirectMessageCount() == 0) { AddEntry(aChild); } aChild.IncrementIndirectMessageCount(); } void SourceMatchController::DecrementMessageCount(Child &aChild) { if (aChild.GetIndirectMessageCount() == 0) { LogWarn("DecrementMessageCount(child 0x%04x) called when already at zero count.", aChild.GetRloc16()); ExitNow(); } aChild.DecrementIndirectMessageCount(); if (aChild.GetIndirectMessageCount() == 0) { ClearEntry(aChild); } exit: return; } void SourceMatchController::ResetMessageCount(Child &aChild) { aChild.ResetIndirectMessageCount(); ClearEntry(aChild); } void SourceMatchController::SetSrcMatchAsShort(Child &aChild, bool aUseShortAddress) { VerifyOrExit(aChild.IsIndirectSourceMatchShort() != aUseShortAddress); if (aChild.GetIndirectMessageCount() > 0) { ClearEntry(aChild); aChild.SetIndirectSourceMatchShort(aUseShortAddress); AddEntry(aChild); } else { aChild.SetIndirectSourceMatchShort(aUseShortAddress); } exit: return; } void SourceMatchController::ClearTable(void) { Get().ClearSrcMatchShortEntries(); Get().ClearSrcMatchExtEntries(); LogDebg("Cleared all entries"); } void SourceMatchController::Enable(bool aEnable) { mEnabled = aEnable; Get().EnableSrcMatch(mEnabled); LogDebg("%sabling", mEnabled ? "En" : "Dis"); } void SourceMatchController::AddEntry(Child &aChild) { aChild.SetIndirectSourceMatchPending(true); if (!IsEnabled()) { SuccessOrExit(AddPendingEntries()); Enable(true); } else { VerifyOrExit(AddAddress(aChild) == kErrorNone, Enable(false)); aChild.SetIndirectSourceMatchPending(false); } exit: return; } Error SourceMatchController::AddAddress(const Child &aChild) { Error error = kErrorNone; if (aChild.IsIndirectSourceMatchShort()) { error = Get().AddSrcMatchShortEntry(aChild.GetRloc16()); LogDebg("Adding short addr: 0x%04x -- %s (%d)", aChild.GetRloc16(), ErrorToString(error), error); } else { error = Get().AddSrcMatchExtEntry(aChild.GetExtAddress()); LogDebg("Adding addr: %s -- %s (%d)", aChild.GetExtAddress().ToString().AsCString(), ErrorToString(error), error); } return error; } void SourceMatchController::ClearEntry(Child &aChild) { Error error = kErrorNone; if (aChild.IsIndirectSourceMatchPending()) { LogDebg("Clearing pending flag for 0x%04x", aChild.GetRloc16()); aChild.SetIndirectSourceMatchPending(false); ExitNow(); } if (aChild.IsIndirectSourceMatchShort()) { error = Get().ClearSrcMatchShortEntry(aChild.GetRloc16()); LogDebg("Clearing short addr: 0x%04x -- %s (%d)", aChild.GetRloc16(), ErrorToString(error), error); } else { error = Get().ClearSrcMatchExtEntry(aChild.GetExtAddress()); LogDebg("Clearing addr: %s -- %s (%d)", aChild.GetExtAddress().ToString().AsCString(), ErrorToString(error), error); } SuccessOrExit(error); if (!IsEnabled()) { SuccessOrExit(AddPendingEntries()); Enable(true); } exit: return; } Error SourceMatchController::AddPendingEntries(void) { Error error = kErrorNone; for (Child &child : Get().Iterate(Child::kInStateValidOrRestoring)) { if (child.IsIndirectSourceMatchPending()) { SuccessOrExit(error = AddAddress(child)); child.SetIndirectSourceMatchPending(false); } } exit: return error; } } // namespace ot #endif // OPENTHREAD_FTD