blob: 0030fba0c4ffe4f29e358a332302609c664277fe [file] [log] [blame]
/*
* Copyright (c) 2020, 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 OTNS utilities.
*
*/
#include "otns.hpp"
#if (OPENTHREAD_MTD || OPENTHREAD_FTD) && OPENTHREAD_CONFIG_OTNS_ENABLE
#include "common/debug.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
namespace ot {
namespace Utils {
RegisterLogModule("Otns");
const int kMaxStatusStringLength = 128;
void Otns::EmitShortAddress(uint16_t aShortAddress)
{
EmitStatus("rloc16=%d", aShortAddress);
}
void Otns::EmitExtendedAddress(const Mac::ExtAddress &aExtAddress)
{
Mac::ExtAddress revExtAddress;
revExtAddress.Set(aExtAddress.m8, Mac::ExtAddress::kReverseByteOrder);
EmitStatus("extaddr=%s", revExtAddress.ToString().AsCString());
}
void Otns::EmitPingRequest(const Ip6::Address &aPeerAddress,
uint16_t aPingLength,
uint32_t aTimestamp,
uint8_t aHopLimit)
{
OT_UNUSED_VARIABLE(aHopLimit);
EmitStatus("ping_request=%s,%d,%lu", aPeerAddress.ToString().AsCString(), aPingLength, aTimestamp);
}
void Otns::EmitPingReply(const Ip6::Address &aPeerAddress, uint16_t aPingLength, uint32_t aTimestamp, uint8_t aHopLimit)
{
EmitStatus("ping_reply=%s,%u,%lu,%d", aPeerAddress.ToString().AsCString(), aPingLength, aTimestamp, aHopLimit);
}
void Otns::EmitStatus(const char *aFmt, ...)
{
char statusStr[kMaxStatusStringLength + 1];
int n;
va_list ap;
va_start(ap, aFmt);
n = vsnprintf(statusStr, sizeof(statusStr), aFmt, ap);
OT_UNUSED_VARIABLE(n);
OT_ASSERT(n >= 0);
va_end(ap);
otPlatOtnsStatus(statusStr);
}
void Otns::HandleNotifierEvents(Events aEvents)
{
if (aEvents.Contains(kEventThreadRoleChanged))
{
EmitStatus("role=%d", Get<Mle::Mle>().GetRole());
}
if (aEvents.Contains(kEventThreadPartitionIdChanged))
{
EmitStatus("parid=%x", Get<Mle::Mle>().GetLeaderData().GetPartitionId());
}
#if OPENTHREAD_CONFIG_JOINER_ENABLE
if (aEvents.Contains(kEventJoinerStateChanged))
{
EmitStatus("joiner_state=%d", Get<MeshCoP::Joiner>().GetState());
}
#endif
}
void Otns::EmitNeighborChange(NeighborTable::Event aEvent, const Neighbor &aNeighbor)
{
switch (aEvent)
{
case NeighborTable::kRouterAdded:
EmitStatus("router_added=%s", aNeighbor.GetExtAddress().ToString().AsCString());
break;
case NeighborTable::kRouterRemoved:
EmitStatus("router_removed=%s", aNeighbor.GetExtAddress().ToString().AsCString());
break;
case NeighborTable::kChildAdded:
EmitStatus("child_added=%s", aNeighbor.GetExtAddress().ToString().AsCString());
break;
case NeighborTable::kChildRemoved:
EmitStatus("child_removed=%s", aNeighbor.GetExtAddress().ToString().AsCString());
break;
case NeighborTable::kChildModeChanged:
break;
}
}
void Otns::EmitTransmit(const Mac::TxFrame &aFrame)
{
Mac::Address dst;
uint16_t frameControlField = aFrame.GetFrameControlField();
uint8_t channel = aFrame.GetChannel();
uint8_t sequence = aFrame.GetSequence();
IgnoreError(aFrame.GetDstAddr(dst));
if (dst.IsShort())
{
EmitStatus("transmit=%d,%04x,%d,%04x", channel, frameControlField, sequence, dst.GetShort());
}
else if (dst.IsExtended())
{
EmitStatus("transmit=%d,%04x,%d,%s", channel, frameControlField, sequence, dst.ToString().AsCString());
}
else
{
EmitStatus("transmit=%d,%04x,%d", channel, frameControlField, sequence);
}
}
void Otns::EmitDeviceMode(Mle::DeviceMode aMode)
{
EmitStatus("mode=%s%s%s", aMode.IsRxOnWhenIdle() ? "r" : "", aMode.IsFullThreadDevice() ? "d" : "",
(aMode.GetNetworkDataType() == NetworkData::kFullSet) ? "n" : "");
}
void Otns::EmitCoapSend(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
char uriPath[Coap::Message::kMaxReceivedUriPath + 1];
Error error;
SuccessOrExit(error = aMessage.ReadUriPathOptions(uriPath));
EmitStatus("coap=send,%d,%d,%d,%s,%s,%d", aMessage.GetMessageId(), aMessage.GetType(), aMessage.GetCode(), uriPath,
aMessageInfo.GetPeerAddr().ToString().AsCString(), aMessageInfo.GetPeerPort());
exit:
if (error != kErrorNone)
{
LogWarn("EmitCoapSend failed: %s", ErrorToString(error));
}
}
void Otns::EmitCoapReceive(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
char uriPath[Coap::Message::kMaxReceivedUriPath + 1];
Error error = kErrorNone;
SuccessOrExit(error = aMessage.ReadUriPathOptions(uriPath));
EmitStatus("coap=recv,%d,%d,%d,%s,%s,%d", aMessage.GetMessageId(), aMessage.GetType(), aMessage.GetCode(), uriPath,
aMessageInfo.GetPeerAddr().ToString().AsCString(), aMessageInfo.GetPeerPort());
exit:
if (error != kErrorNone)
{
LogWarn("EmitCoapReceive failed: %s", ErrorToString(error));
}
}
void Otns::EmitCoapSendFailure(Error aError, Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
char uriPath[Coap::Message::kMaxReceivedUriPath + 1];
Error error = kErrorNone;
SuccessOrExit(error = aMessage.ReadUriPathOptions(uriPath));
EmitStatus("coap=send_error,%d,%d,%d,%s,%s,%d,%s", aMessage.GetMessageId(), aMessage.GetType(), aMessage.GetCode(),
uriPath, aMessageInfo.GetPeerAddr().ToString().AsCString(), aMessageInfo.GetPeerPort(),
ErrorToString(aError));
exit:
if (error != kErrorNone)
{
LogWarn("EmitCoapSendFailure failed: %s", ErrorToString(error));
}
}
} // namespace Utils
} // namespace ot
#endif // (OPENTHREAD_MTD || OPENTHREAD_FTD) && OPENTHREAD_CONFIG_OTNS_ENABLE