1 /*
2 * Copyright (c) 2019, 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 a software Source Match table, for radios that don't have
32 * such hardware acceleration. It supports only the single-instance build of
33 * OpenThread.
34 *
35 */
36
37 #include "utils/soft_source_match_table.h"
38
39 #include <stdlib.h>
40 #include <string.h>
41
42 #include <openthread/logging.h>
43
44 #include "utils/code_utils.h"
45
46 #if RADIO_CONFIG_SRC_MATCH_SHORT_ENTRY_NUM || RADIO_CONFIG_SRC_MATCH_EXT_ENTRY_NUM
47 static uint16_t sPanId = 0;
48
utilsSoftSrcMatchSetPanId(uint16_t aPanId)49 void utilsSoftSrcMatchSetPanId(uint16_t aPanId) { sPanId = aPanId; }
50 #endif // RADIO_CONFIG_SRC_MATCH_SHORT_ENTRY_NUM || RADIO_CONFIG_SRC_MATCH_EXT_ENTRY_NUM
51
52 #if RADIO_CONFIG_SRC_MATCH_SHORT_ENTRY_NUM
53 typedef struct srcMatchShortEntry
54 {
55 uint16_t checksum;
56 bool allocated;
57 } sSrcMatchShortEntry;
58
59 static sSrcMatchShortEntry srcMatchShortEntry[RADIO_CONFIG_SRC_MATCH_SHORT_ENTRY_NUM];
60
utilsSoftSrcMatchShortFindEntry(uint16_t aShortAddress)61 int16_t utilsSoftSrcMatchShortFindEntry(uint16_t aShortAddress)
62 {
63 int16_t entry = -1;
64 uint16_t checksum = aShortAddress + sPanId;
65
66 for (int16_t i = 0; i < RADIO_CONFIG_SRC_MATCH_SHORT_ENTRY_NUM; i++)
67 {
68 if (checksum == srcMatchShortEntry[i].checksum && srcMatchShortEntry[i].allocated)
69 {
70 entry = i;
71 break;
72 }
73 }
74
75 return entry;
76 }
77
findSrcMatchShortAvailEntry(void)78 static int16_t findSrcMatchShortAvailEntry(void)
79 {
80 int16_t entry = -1;
81
82 for (int16_t i = 0; i < RADIO_CONFIG_SRC_MATCH_SHORT_ENTRY_NUM; i++)
83 {
84 if (!srcMatchShortEntry[i].allocated)
85 {
86 entry = i;
87 break;
88 }
89 }
90
91 return entry;
92 }
93
addToSrcMatchShortIndirect(uint16_t entry,uint16_t aShortAddress)94 static inline void addToSrcMatchShortIndirect(uint16_t entry, uint16_t aShortAddress)
95 {
96 uint16_t checksum = aShortAddress + sPanId;
97
98 srcMatchShortEntry[entry].checksum = checksum;
99 srcMatchShortEntry[entry].allocated = true;
100 }
101
removeFromSrcMatchShortIndirect(uint16_t entry)102 static inline void removeFromSrcMatchShortIndirect(uint16_t entry)
103 {
104 srcMatchShortEntry[entry].allocated = false;
105 srcMatchShortEntry[entry].checksum = 0;
106 }
107
otPlatRadioAddSrcMatchShortEntry(otInstance * aInstance,uint16_t aShortAddress)108 otError otPlatRadioAddSrcMatchShortEntry(otInstance *aInstance, uint16_t aShortAddress)
109 {
110 OT_UNUSED_VARIABLE(aInstance);
111
112 otError error = OT_ERROR_NONE;
113 int16_t entry = -1;
114
115 entry = findSrcMatchShortAvailEntry();
116 otLogDebgPlat("Add ShortAddr entry: %d", entry);
117
118 otEXPECT_ACTION(entry >= 0 && entry < RADIO_CONFIG_SRC_MATCH_SHORT_ENTRY_NUM, error = OT_ERROR_NO_BUFS);
119
120 addToSrcMatchShortIndirect((uint16_t)entry, aShortAddress);
121
122 exit:
123 return error;
124 }
125
otPlatRadioClearSrcMatchShortEntry(otInstance * aInstance,uint16_t aShortAddress)126 otError otPlatRadioClearSrcMatchShortEntry(otInstance *aInstance, uint16_t aShortAddress)
127 {
128 OT_UNUSED_VARIABLE(aInstance);
129
130 otError error = OT_ERROR_NONE;
131 int16_t entry = -1;
132
133 entry = utilsSoftSrcMatchShortFindEntry(aShortAddress);
134 otLogDebgPlat("Clear ShortAddr entry: %d", entry);
135
136 otEXPECT_ACTION(entry >= 0 && entry < RADIO_CONFIG_SRC_MATCH_SHORT_ENTRY_NUM, error = OT_ERROR_NO_ADDRESS);
137
138 removeFromSrcMatchShortIndirect((uint16_t)entry);
139
140 exit:
141 return error;
142 }
143
otPlatRadioClearSrcMatchShortEntries(otInstance * aInstance)144 void otPlatRadioClearSrcMatchShortEntries(otInstance *aInstance)
145 {
146 OT_UNUSED_VARIABLE(aInstance);
147
148 otLogDebgPlat("Clear ShortAddr entries");
149
150 memset(srcMatchShortEntry, 0, sizeof(srcMatchShortEntry));
151 }
152 #endif // RADIO_CONFIG_SRC_MATCH_SHORT_ENTRY_NUM
153
154 #if RADIO_CONFIG_SRC_MATCH_EXT_ENTRY_NUM
155 typedef struct srcMatchExtEntry
156 {
157 uint16_t checksum;
158 bool allocated;
159 } sSrcMatchExtEntry;
160
161 static sSrcMatchExtEntry srcMatchExtEntry[RADIO_CONFIG_SRC_MATCH_EXT_ENTRY_NUM];
162
utilsSoftSrcMatchExtFindEntry(const otExtAddress * aExtAddress)163 int16_t utilsSoftSrcMatchExtFindEntry(const otExtAddress *aExtAddress)
164 {
165 int16_t entry = -1;
166 uint16_t checksum = sPanId;
167
168 checksum += (uint16_t)aExtAddress->m8[0] | (uint16_t)(aExtAddress->m8[1] << 8);
169 checksum += (uint16_t)aExtAddress->m8[2] | (uint16_t)(aExtAddress->m8[3] << 8);
170 checksum += (uint16_t)aExtAddress->m8[4] | (uint16_t)(aExtAddress->m8[5] << 8);
171 checksum += (uint16_t)aExtAddress->m8[6] | (uint16_t)(aExtAddress->m8[7] << 8);
172
173 for (int16_t i = 0; i < RADIO_CONFIG_SRC_MATCH_EXT_ENTRY_NUM; i++)
174 {
175 if (checksum == srcMatchExtEntry[i].checksum && srcMatchExtEntry[i].allocated)
176 {
177 entry = i;
178 break;
179 }
180 }
181
182 return entry;
183 }
184
findSrcMatchExtAvailEntry(void)185 static int16_t findSrcMatchExtAvailEntry(void)
186 {
187 int16_t entry = -1;
188
189 for (int16_t i = 0; i < RADIO_CONFIG_SRC_MATCH_EXT_ENTRY_NUM; i++)
190 {
191 if (!srcMatchExtEntry[i].allocated)
192 {
193 entry = i;
194 break;
195 }
196 }
197
198 return entry;
199 }
200
addToSrcMatchExtIndirect(uint16_t entry,const otExtAddress * aExtAddress)201 static inline void addToSrcMatchExtIndirect(uint16_t entry, const otExtAddress *aExtAddress)
202 {
203 uint16_t checksum = sPanId;
204
205 checksum += (uint16_t)aExtAddress->m8[0] | (uint16_t)(aExtAddress->m8[1] << 8);
206 checksum += (uint16_t)aExtAddress->m8[2] | (uint16_t)(aExtAddress->m8[3] << 8);
207 checksum += (uint16_t)aExtAddress->m8[4] | (uint16_t)(aExtAddress->m8[5] << 8);
208 checksum += (uint16_t)aExtAddress->m8[6] | (uint16_t)(aExtAddress->m8[7] << 8);
209
210 srcMatchExtEntry[entry].checksum = checksum;
211 srcMatchExtEntry[entry].allocated = true;
212 }
213
removeFromSrcMatchExtIndirect(uint16_t entry)214 static inline void removeFromSrcMatchExtIndirect(uint16_t entry)
215 {
216 srcMatchExtEntry[entry].allocated = false;
217 srcMatchExtEntry[entry].checksum = 0;
218 }
219
otPlatRadioAddSrcMatchExtEntry(otInstance * aInstance,const otExtAddress * aExtAddress)220 otError otPlatRadioAddSrcMatchExtEntry(otInstance *aInstance, const otExtAddress *aExtAddress)
221 {
222 OT_UNUSED_VARIABLE(aInstance);
223
224 otError error = OT_ERROR_NONE;
225 int16_t entry = -1;
226
227 entry = findSrcMatchExtAvailEntry();
228 otLogDebgPlat("Add ExtAddr entry: %d", entry);
229
230 otEXPECT_ACTION(entry >= 0 && entry < RADIO_CONFIG_SRC_MATCH_EXT_ENTRY_NUM, error = OT_ERROR_NO_BUFS);
231
232 addToSrcMatchExtIndirect((uint16_t)entry, aExtAddress);
233
234 exit:
235 return error;
236 }
237
otPlatRadioClearSrcMatchExtEntry(otInstance * aInstance,const otExtAddress * aExtAddress)238 otError otPlatRadioClearSrcMatchExtEntry(otInstance *aInstance, const otExtAddress *aExtAddress)
239 {
240 OT_UNUSED_VARIABLE(aInstance);
241
242 otError error = OT_ERROR_NONE;
243 int16_t entry = -1;
244
245 entry = utilsSoftSrcMatchExtFindEntry(aExtAddress);
246 otLogDebgPlat("Clear ExtAddr entry: %d", entry);
247
248 otEXPECT_ACTION(entry >= 0 && entry < RADIO_CONFIG_SRC_MATCH_EXT_ENTRY_NUM, error = OT_ERROR_NO_ADDRESS);
249
250 removeFromSrcMatchExtIndirect((uint16_t)entry);
251
252 exit:
253 return error;
254 }
255
otPlatRadioClearSrcMatchExtEntries(otInstance * aInstance)256 void otPlatRadioClearSrcMatchExtEntries(otInstance *aInstance)
257 {
258 OT_UNUSED_VARIABLE(aInstance);
259
260 otLogDebgPlat("Clear ExtAddr entries");
261
262 memset(srcMatchExtEntry, 0, sizeof(srcMatchExtEntry));
263 }
264 #endif // RADIO_CONFIG_SRC_MATCH_EXT_ENTRY_NUM
265