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