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