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