1 /*
2 * Copyright (c) 2016-2017, 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 includes definitions for a Thread `Neighbor`.
32 */
33
34 #include "neighbor.hpp"
35
36 #include "common/array.hpp"
37 #include "common/code_utils.hpp"
38 #include "common/debug.hpp"
39 #include "common/locator_getters.hpp"
40 #include "common/num_utils.hpp"
41 #include "instance/instance.hpp"
42
43 namespace ot {
44
SetState(State aState)45 void Neighbor::SetState(State aState)
46 {
47 VerifyOrExit(mState != aState);
48 mState = static_cast<uint8_t>(aState);
49
50 #if OPENTHREAD_CONFIG_UPTIME_ENABLE
51 if (mState == kStateValid)
52 {
53 mConnectionStart = Uptime::MsecToSec(Get<Uptime>().GetUptime());
54 }
55 #endif
56
57 exit:
58 return;
59 }
60
61 #if OPENTHREAD_CONFIG_UPTIME_ENABLE
GetConnectionTime(void) const62 uint32_t Neighbor::GetConnectionTime(void) const
63 {
64 return IsStateValid() ? Uptime::MsecToSec(Get<Uptime>().GetUptime()) - mConnectionStart : 0;
65 }
66 #endif
67
Matches(const Neighbor & aNeighbor) const68 bool Neighbor::AddressMatcher::Matches(const Neighbor &aNeighbor) const
69 {
70 bool matches = false;
71
72 VerifyOrExit(aNeighbor.MatchesFilter(mStateFilter));
73
74 if (mShortAddress != Mac::kShortAddrInvalid)
75 {
76 VerifyOrExit(mShortAddress == aNeighbor.GetRloc16());
77 }
78
79 if (mExtAddress != nullptr)
80 {
81 VerifyOrExit(*mExtAddress == aNeighbor.GetExtAddress());
82 }
83
84 matches = true;
85
86 exit:
87 return matches;
88 }
89
SetFrom(const Neighbor & aNeighbor)90 void Neighbor::Info::SetFrom(const Neighbor &aNeighbor)
91 {
92 Clear();
93
94 mExtAddress = aNeighbor.GetExtAddress();
95 mAge = Time::MsecToSec(TimerMilli::GetNow() - aNeighbor.GetLastHeard());
96 mRloc16 = aNeighbor.GetRloc16();
97 mLinkFrameCounter = aNeighbor.GetLinkFrameCounters().GetMaximum();
98 mMleFrameCounter = aNeighbor.GetMleFrameCounter();
99 mLinkQualityIn = aNeighbor.GetLinkQualityIn();
100 mAverageRssi = aNeighbor.GetLinkInfo().GetAverageRss();
101 mLastRssi = aNeighbor.GetLinkInfo().GetLastRss();
102 mLinkMargin = aNeighbor.GetLinkInfo().GetLinkMargin();
103 mFrameErrorRate = aNeighbor.GetLinkInfo().GetFrameErrorRate();
104 mMessageErrorRate = aNeighbor.GetLinkInfo().GetMessageErrorRate();
105 mRxOnWhenIdle = aNeighbor.IsRxOnWhenIdle();
106 mFullThreadDevice = aNeighbor.IsFullThreadDevice();
107 mFullNetworkData = (aNeighbor.GetNetworkDataType() == NetworkData::kFullSet);
108 mVersion = aNeighbor.GetVersion();
109 #if OPENTHREAD_CONFIG_UPTIME_ENABLE
110 mConnectionTime = aNeighbor.GetConnectionTime();
111 #endif
112 }
113
Init(Instance & aInstance)114 void Neighbor::Init(Instance &aInstance)
115 {
116 InstanceLocatorInit::Init(aInstance);
117 mLinkInfo.Init(aInstance);
118 SetState(kStateInvalid);
119 }
120
IsStateValidOrAttaching(void) const121 bool Neighbor::IsStateValidOrAttaching(void) const
122 {
123 bool rval = false;
124
125 switch (GetState())
126 {
127 case kStateInvalid:
128 case kStateParentRequest:
129 case kStateParentResponse:
130 break;
131
132 case kStateRestored:
133 case kStateChildIdRequest:
134 case kStateLinkRequest:
135 case kStateChildUpdateRequest:
136 case kStateValid:
137 rval = true;
138 break;
139 }
140
141 return rval;
142 }
143
MatchesFilter(StateFilter aFilter) const144 bool Neighbor::MatchesFilter(StateFilter aFilter) const
145 {
146 bool matches = false;
147
148 switch (aFilter)
149 {
150 case kInStateValid:
151 matches = IsStateValid();
152 break;
153
154 case kInStateValidOrRestoring:
155 matches = IsStateValidOrRestoring();
156 break;
157
158 case kInStateChildIdRequest:
159 matches = IsStateChildIdRequest();
160 break;
161
162 case kInStateValidOrAttaching:
163 matches = IsStateValidOrAttaching();
164 break;
165
166 case kInStateInvalid:
167 matches = IsStateInvalid();
168 break;
169
170 case kInStateAnyExceptInvalid:
171 matches = !IsStateInvalid();
172 break;
173
174 case kInStateAnyExceptValidOrRestoring:
175 matches = !IsStateValidOrRestoring();
176 break;
177
178 case kInStateAny:
179 matches = true;
180 break;
181 }
182
183 return matches;
184 }
185
186 #if OPENTHREAD_CONFIG_MULTI_RADIO
SetLastRxFragmentTag(uint16_t aTag)187 void Neighbor::SetLastRxFragmentTag(uint16_t aTag)
188 {
189 mLastRxFragmentTag = (aTag == 0) ? 0xffff : aTag;
190 mLastRxFragmentTagTime = TimerMilli::GetNow();
191 }
192
IsLastRxFragmentTagSet(void) const193 bool Neighbor::IsLastRxFragmentTagSet(void) const
194 {
195 return (mLastRxFragmentTag != 0) && (TimerMilli::GetNow() <= mLastRxFragmentTagTime + kLastRxFragmentTagTimeout);
196 }
197 #endif
198
199 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
AggregateLinkMetrics(uint8_t aSeriesId,uint8_t aFrameType,uint8_t aLqi,int8_t aRss)200 void Neighbor::AggregateLinkMetrics(uint8_t aSeriesId, uint8_t aFrameType, uint8_t aLqi, int8_t aRss)
201 {
202 for (LinkMetrics::SeriesInfo &entry : mLinkMetricsSeriesInfoList)
203 {
204 if (aSeriesId == 0 || aSeriesId == entry.GetSeriesId())
205 {
206 entry.AggregateLinkMetrics(aFrameType, aLqi, aRss);
207 }
208 }
209 }
210
GetForwardTrackingSeriesInfo(const uint8_t & aSeriesId)211 LinkMetrics::SeriesInfo *Neighbor::GetForwardTrackingSeriesInfo(const uint8_t &aSeriesId)
212 {
213 return mLinkMetricsSeriesInfoList.FindMatching(aSeriesId);
214 }
215
AddForwardTrackingSeriesInfo(LinkMetrics::SeriesInfo & aSeriesInfo)216 void Neighbor::AddForwardTrackingSeriesInfo(LinkMetrics::SeriesInfo &aSeriesInfo)
217 {
218 mLinkMetricsSeriesInfoList.Push(aSeriesInfo);
219 }
220
RemoveForwardTrackingSeriesInfo(const uint8_t & aSeriesId)221 LinkMetrics::SeriesInfo *Neighbor::RemoveForwardTrackingSeriesInfo(const uint8_t &aSeriesId)
222 {
223 return mLinkMetricsSeriesInfoList.RemoveMatching(aSeriesId);
224 }
225
RemoveAllForwardTrackingSeriesInfo(void)226 void Neighbor::RemoveAllForwardTrackingSeriesInfo(void)
227 {
228 while (!mLinkMetricsSeriesInfoList.IsEmpty())
229 {
230 LinkMetrics::SeriesInfo *seriesInfo = mLinkMetricsSeriesInfoList.Pop();
231 Get<LinkMetrics::Subject>().Free(*seriesInfo);
232 }
233 }
234 #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
235
StateToString(State aState)236 const char *Neighbor::StateToString(State aState)
237 {
238 static const char *const kStateStrings[] = {
239 "Invalid", // (0) kStateInvalid
240 "Restored", // (1) kStateRestored
241 "ParentReq", // (2) kStateParentRequest
242 "ParentRes", // (3) kStateParentResponse
243 "ChildIdReq", // (4) kStateChildIdRequest
244 "LinkReq", // (5) kStateLinkRequest
245 "ChildUpdateReq", // (6) kStateChildUpdateRequest
246 "Valid", // (7) kStateValid
247 };
248
249 static_assert(0 == kStateInvalid, "kStateInvalid value is incorrect");
250 static_assert(1 == kStateRestored, "kStateRestored value is incorrect");
251 static_assert(2 == kStateParentRequest, "kStateParentRequest value is incorrect");
252 static_assert(3 == kStateParentResponse, "kStateParentResponse value is incorrect");
253 static_assert(4 == kStateChildIdRequest, "kStateChildIdRequest value is incorrect");
254 static_assert(5 == kStateLinkRequest, "kStateLinkRequest value is incorrect");
255 static_assert(6 == kStateChildUpdateRequest, "kStateChildUpdateRequest value is incorrect");
256 static_assert(7 == kStateValid, "kStateValid value is incorrect");
257
258 return kStateStrings[aState];
259 }
260
261 } // namespace ot
262