• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2020, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file implements OTNS utilities.
32  *
33  */
34 
35 #include "otns.hpp"
36 
37 #if (OPENTHREAD_MTD || OPENTHREAD_FTD) && OPENTHREAD_CONFIG_OTNS_ENABLE
38 
39 #include "common/debug.hpp"
40 #include "common/locator_getters.hpp"
41 #include "common/log.hpp"
42 
43 namespace ot {
44 namespace Utils {
45 
46 RegisterLogModule("Otns");
47 
48 const int kMaxStatusStringLength = 128;
49 
EmitShortAddress(uint16_t aShortAddress)50 void Otns::EmitShortAddress(uint16_t aShortAddress)
51 {
52     EmitStatus("rloc16=%d", aShortAddress);
53 }
54 
EmitExtendedAddress(const Mac::ExtAddress & aExtAddress)55 void Otns::EmitExtendedAddress(const Mac::ExtAddress &aExtAddress)
56 {
57     Mac::ExtAddress revExtAddress;
58     revExtAddress.Set(aExtAddress.m8, Mac::ExtAddress::kReverseByteOrder);
59     EmitStatus("extaddr=%s", revExtAddress.ToString().AsCString());
60 }
61 
EmitPingRequest(const Ip6::Address & aPeerAddress,uint16_t aPingLength,uint32_t aTimestamp,uint8_t aHopLimit)62 void Otns::EmitPingRequest(const Ip6::Address &aPeerAddress,
63                            uint16_t            aPingLength,
64                            uint32_t            aTimestamp,
65                            uint8_t             aHopLimit)
66 {
67     OT_UNUSED_VARIABLE(aHopLimit);
68     EmitStatus("ping_request=%s,%d,%lu", aPeerAddress.ToString().AsCString(), aPingLength, aTimestamp);
69 }
70 
EmitPingReply(const Ip6::Address & aPeerAddress,uint16_t aPingLength,uint32_t aTimestamp,uint8_t aHopLimit)71 void Otns::EmitPingReply(const Ip6::Address &aPeerAddress, uint16_t aPingLength, uint32_t aTimestamp, uint8_t aHopLimit)
72 {
73     EmitStatus("ping_reply=%s,%u,%lu,%d", aPeerAddress.ToString().AsCString(), aPingLength, aTimestamp, aHopLimit);
74 }
75 
EmitStatus(const char * aFmt,...)76 void Otns::EmitStatus(const char *aFmt, ...)
77 {
78     char statusStr[kMaxStatusStringLength + 1];
79     int  n;
80 
81     va_list ap;
82     va_start(ap, aFmt);
83 
84     n = vsnprintf(statusStr, sizeof(statusStr), aFmt, ap);
85     OT_UNUSED_VARIABLE(n);
86     OT_ASSERT(n >= 0);
87 
88     va_end(ap);
89 
90     otPlatOtnsStatus(statusStr);
91 }
92 
HandleNotifierEvents(Events aEvents)93 void Otns::HandleNotifierEvents(Events aEvents)
94 {
95     if (aEvents.Contains(kEventThreadRoleChanged))
96     {
97         EmitStatus("role=%d", Get<Mle::Mle>().GetRole());
98     }
99 
100     if (aEvents.Contains(kEventThreadPartitionIdChanged))
101     {
102         EmitStatus("parid=%x", Get<Mle::Mle>().GetLeaderData().GetPartitionId());
103     }
104 
105 #if OPENTHREAD_CONFIG_JOINER_ENABLE
106     if (aEvents.Contains(kEventJoinerStateChanged))
107     {
108         EmitStatus("joiner_state=%d", Get<MeshCoP::Joiner>().GetState());
109     }
110 #endif
111 }
112 
EmitNeighborChange(NeighborTable::Event aEvent,const Neighbor & aNeighbor)113 void Otns::EmitNeighborChange(NeighborTable::Event aEvent, const Neighbor &aNeighbor)
114 {
115     switch (aEvent)
116     {
117     case NeighborTable::kRouterAdded:
118         EmitStatus("router_added=%s", aNeighbor.GetExtAddress().ToString().AsCString());
119         break;
120     case NeighborTable::kRouterRemoved:
121         EmitStatus("router_removed=%s", aNeighbor.GetExtAddress().ToString().AsCString());
122         break;
123     case NeighborTable::kChildAdded:
124         EmitStatus("child_added=%s", aNeighbor.GetExtAddress().ToString().AsCString());
125         break;
126     case NeighborTable::kChildRemoved:
127         EmitStatus("child_removed=%s", aNeighbor.GetExtAddress().ToString().AsCString());
128         break;
129     case NeighborTable::kChildModeChanged:
130         break;
131     }
132 }
133 
EmitTransmit(const Mac::TxFrame & aFrame)134 void Otns::EmitTransmit(const Mac::TxFrame &aFrame)
135 {
136     Mac::Address dst;
137     uint16_t     frameControlField = aFrame.GetFrameControlField();
138     uint8_t      channel           = aFrame.GetChannel();
139     uint8_t      sequence          = aFrame.GetSequence();
140 
141     IgnoreError(aFrame.GetDstAddr(dst));
142 
143     if (dst.IsShort())
144     {
145         EmitStatus("transmit=%d,%04x,%d,%04x", channel, frameControlField, sequence, dst.GetShort());
146     }
147     else if (dst.IsExtended())
148     {
149         EmitStatus("transmit=%d,%04x,%d,%s", channel, frameControlField, sequence, dst.ToString().AsCString());
150     }
151     else
152     {
153         EmitStatus("transmit=%d,%04x,%d", channel, frameControlField, sequence);
154     }
155 }
156 
EmitDeviceMode(Mle::DeviceMode aMode)157 void Otns::EmitDeviceMode(Mle::DeviceMode aMode)
158 {
159     EmitStatus("mode=%s%s%s", aMode.IsRxOnWhenIdle() ? "r" : "", aMode.IsFullThreadDevice() ? "d" : "",
160                (aMode.GetNetworkDataType() == NetworkData::kFullSet) ? "n" : "");
161 }
162 
EmitCoapSend(const Coap::Message & aMessage,const Ip6::MessageInfo & aMessageInfo)163 void Otns::EmitCoapSend(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
164 {
165     char  uriPath[Coap::Message::kMaxReceivedUriPath + 1];
166     Error error;
167 
168     SuccessOrExit(error = aMessage.ReadUriPathOptions(uriPath));
169 
170     EmitStatus("coap=send,%d,%d,%d,%s,%s,%d", aMessage.GetMessageId(), aMessage.GetType(), aMessage.GetCode(), uriPath,
171                aMessageInfo.GetPeerAddr().ToString().AsCString(), aMessageInfo.GetPeerPort());
172 exit:
173     if (error != kErrorNone)
174     {
175         LogWarn("EmitCoapSend failed: %s", ErrorToString(error));
176     }
177 }
178 
EmitCoapReceive(const Coap::Message & aMessage,const Ip6::MessageInfo & aMessageInfo)179 void Otns::EmitCoapReceive(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
180 {
181     char  uriPath[Coap::Message::kMaxReceivedUriPath + 1];
182     Error error = kErrorNone;
183 
184     SuccessOrExit(error = aMessage.ReadUriPathOptions(uriPath));
185 
186     EmitStatus("coap=recv,%d,%d,%d,%s,%s,%d", aMessage.GetMessageId(), aMessage.GetType(), aMessage.GetCode(), uriPath,
187                aMessageInfo.GetPeerAddr().ToString().AsCString(), aMessageInfo.GetPeerPort());
188 exit:
189     if (error != kErrorNone)
190     {
191         LogWarn("EmitCoapReceive failed: %s", ErrorToString(error));
192     }
193 }
194 
EmitCoapSendFailure(Error aError,Coap::Message & aMessage,const Ip6::MessageInfo & aMessageInfo)195 void Otns::EmitCoapSendFailure(Error aError, Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
196 {
197     char  uriPath[Coap::Message::kMaxReceivedUriPath + 1];
198     Error error = kErrorNone;
199 
200     SuccessOrExit(error = aMessage.ReadUriPathOptions(uriPath));
201 
202     EmitStatus("coap=send_error,%d,%d,%d,%s,%s,%d,%s", aMessage.GetMessageId(), aMessage.GetType(), aMessage.GetCode(),
203                uriPath, aMessageInfo.GetPeerAddr().ToString().AsCString(), aMessageInfo.GetPeerPort(),
204                ErrorToString(aError));
205 exit:
206     if (error != kErrorNone)
207     {
208         LogWarn("EmitCoapSendFailure failed: %s", ErrorToString(error));
209     }
210 }
211 
212 } // namespace Utils
213 } // namespace ot
214 
215 #endif // (OPENTHREAD_MTD || OPENTHREAD_FTD) && OPENTHREAD_CONFIG_OTNS_ENABLE
216