1 /*
2 * Copyright (c) 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 implements source address match controller.
32 */
33
34 #include "src_match_controller.hpp"
35
36 #if OPENTHREAD_FTD
37
38 #include "common/code_utils.hpp"
39 #include "common/debug.hpp"
40 #include "common/instance.hpp"
41 #include "common/locator_getters.hpp"
42 #include "common/logging.hpp"
43 #include "mac/mac_types.hpp"
44 #include "radio/radio.hpp"
45 #include "thread/mesh_forwarder.hpp"
46 #include "thread/thread_netif.hpp"
47 #include "thread/topology.hpp"
48
49 namespace ot {
50
SourceMatchController(Instance & aInstance)51 SourceMatchController::SourceMatchController(Instance &aInstance)
52 : InstanceLocator(aInstance)
53 , mEnabled(false)
54 {
55 ClearTable();
56 }
57
IncrementMessageCount(Child & aChild)58 void SourceMatchController::IncrementMessageCount(Child &aChild)
59 {
60 if (aChild.GetIndirectMessageCount() == 0)
61 {
62 AddEntry(aChild);
63 }
64
65 aChild.IncrementIndirectMessageCount();
66 }
67
DecrementMessageCount(Child & aChild)68 void SourceMatchController::DecrementMessageCount(Child &aChild)
69 {
70 if (aChild.GetIndirectMessageCount() == 0)
71 {
72 otLogWarnMac("DecrementMessageCount(child 0x%04x) called when already at zero count.", aChild.GetRloc16());
73 ExitNow();
74 }
75
76 aChild.DecrementIndirectMessageCount();
77
78 if (aChild.GetIndirectMessageCount() == 0)
79 {
80 ClearEntry(aChild);
81 }
82
83 exit:
84 return;
85 }
86
ResetMessageCount(Child & aChild)87 void SourceMatchController::ResetMessageCount(Child &aChild)
88 {
89 aChild.ResetIndirectMessageCount();
90 ClearEntry(aChild);
91 }
92
SetSrcMatchAsShort(Child & aChild,bool aUseShortAddress)93 void SourceMatchController::SetSrcMatchAsShort(Child &aChild, bool aUseShortAddress)
94 {
95 VerifyOrExit(aChild.IsIndirectSourceMatchShort() != aUseShortAddress);
96
97 if (aChild.GetIndirectMessageCount() > 0)
98 {
99 ClearEntry(aChild);
100 aChild.SetIndirectSourceMatchShort(aUseShortAddress);
101 AddEntry(aChild);
102 }
103 else
104 {
105 aChild.SetIndirectSourceMatchShort(aUseShortAddress);
106 }
107
108 exit:
109 return;
110 }
111
ClearTable(void)112 void SourceMatchController::ClearTable(void)
113 {
114 Get<Radio>().ClearSrcMatchShortEntries();
115 Get<Radio>().ClearSrcMatchExtEntries();
116 otLogDebgMac("SrcAddrMatch - Cleared all entries");
117 }
118
Enable(bool aEnable)119 void SourceMatchController::Enable(bool aEnable)
120 {
121 mEnabled = aEnable;
122 Get<Radio>().EnableSrcMatch(mEnabled);
123 otLogDebgMac("SrcAddrMatch - %sabling", mEnabled ? "En" : "Dis");
124 }
125
AddEntry(Child & aChild)126 void SourceMatchController::AddEntry(Child &aChild)
127 {
128 aChild.SetIndirectSourceMatchPending(true);
129
130 if (!IsEnabled())
131 {
132 SuccessOrExit(AddPendingEntries());
133 Enable(true);
134 }
135 else
136 {
137 VerifyOrExit(AddAddress(aChild) == kErrorNone, Enable(false));
138 aChild.SetIndirectSourceMatchPending(false);
139 }
140
141 exit:
142 return;
143 }
144
AddAddress(const Child & aChild)145 Error SourceMatchController::AddAddress(const Child &aChild)
146 {
147 Error error = kErrorNone;
148
149 if (aChild.IsIndirectSourceMatchShort())
150 {
151 error = Get<Radio>().AddSrcMatchShortEntry(aChild.GetRloc16());
152
153 otLogDebgMac("SrcAddrMatch - Adding short addr: 0x%04x -- %s (%d)", aChild.GetRloc16(), ErrorToString(error),
154 error);
155 }
156 else
157 {
158 Mac::ExtAddress address;
159
160 address.Set(aChild.GetExtAddress().m8, Mac::ExtAddress::kReverseByteOrder);
161 error = Get<Radio>().AddSrcMatchExtEntry(address);
162
163 otLogDebgMac("SrcAddrMatch - Adding addr: %s -- %s (%d)", aChild.GetExtAddress().ToString().AsCString(),
164 ErrorToString(error), error);
165 }
166
167 return error;
168 }
169
ClearEntry(Child & aChild)170 void SourceMatchController::ClearEntry(Child &aChild)
171 {
172 Error error = kErrorNone;
173
174 if (aChild.IsIndirectSourceMatchPending())
175 {
176 otLogDebgMac("SrcAddrMatch - Clearing pending flag for 0x%04x", aChild.GetRloc16());
177 aChild.SetIndirectSourceMatchPending(false);
178 ExitNow();
179 }
180
181 if (aChild.IsIndirectSourceMatchShort())
182 {
183 error = Get<Radio>().ClearSrcMatchShortEntry(aChild.GetRloc16());
184
185 otLogDebgMac("SrcAddrMatch - Clearing short addr: 0x%04x -- %s (%d)", aChild.GetRloc16(), ErrorToString(error),
186 error);
187 }
188 else
189 {
190 Mac::ExtAddress address;
191
192 address.Set(aChild.GetExtAddress().m8, Mac::ExtAddress::kReverseByteOrder);
193 error = Get<Radio>().ClearSrcMatchExtEntry(address);
194
195 otLogDebgMac("SrcAddrMatch - Clearing addr: %s -- %s (%d)", aChild.GetExtAddress().ToString().AsCString(),
196 ErrorToString(error), error);
197 }
198
199 SuccessOrExit(error);
200
201 if (!IsEnabled())
202 {
203 SuccessOrExit(AddPendingEntries());
204 Enable(true);
205 }
206
207 exit:
208 return;
209 }
210
AddPendingEntries(void)211 Error SourceMatchController::AddPendingEntries(void)
212 {
213 Error error = kErrorNone;
214
215 for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValidOrRestoring))
216 {
217 if (child.IsIndirectSourceMatchPending())
218 {
219 SuccessOrExit(error = AddAddress(child));
220 child.SetIndirectSourceMatchPending(false);
221 }
222 }
223
224 exit:
225 return error;
226 }
227
228 } // namespace ot
229
230 #endif // OPENTHREAD_FTD
231