]>
Commit | Line | Data |
---|---|---|
ba94a1bb WD |
1 | /** |
2 | * @file IxEthDBAPI.c | |
3 | * | |
4 | * @brief Implementation of the public API | |
5 | * | |
6 | * @par | |
7 | * IXP400 SW Release version 2.0 | |
8 | * | |
9 | * -- Copyright Notice -- | |
10 | * | |
11 | * @par | |
12 | * Copyright 2001-2005, Intel Corporation. | |
13 | * All rights reserved. | |
14 | * | |
15 | * @par | |
16 | * Redistribution and use in source and binary forms, with or without | |
17 | * modification, are permitted provided that the following conditions | |
18 | * are met: | |
19 | * 1. Redistributions of source code must retain the above copyright | |
20 | * notice, this list of conditions and the following disclaimer. | |
21 | * 2. Redistributions in binary form must reproduce the above copyright | |
22 | * notice, this list of conditions and the following disclaimer in the | |
23 | * documentation and/or other materials provided with the distribution. | |
24 | * 3. Neither the name of the Intel Corporation nor the names of its contributors | |
25 | * may be used to endorse or promote products derived from this software | |
26 | * without specific prior written permission. | |
27 | * | |
28 | * @par | |
29 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' | |
30 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
31 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
32 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE | |
33 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
34 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
35 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
36 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
37 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
38 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
39 | * SUCH DAMAGE. | |
40 | * | |
41 | * @par | |
42 | * -- End of Copyright Notice -- | |
43 | */ | |
44 | ||
45 | #include "IxEthDB_p.h" | |
46 | #include "IxFeatureCtrl.h" | |
47 | ||
48 | extern HashTable dbHashtable; | |
49 | extern IxEthDBPortMap overflowUpdatePortList; | |
50 | extern BOOL ixEthDBPortUpdateRequired[IX_ETH_DB_MAX_RECORD_TYPE_INDEX + 1]; | |
51 | ||
52 | IX_ETH_DB_PUBLIC | |
53 | IxEthDBStatus ixEthDBFilteringStaticEntryProvision(IxEthDBPortId portID, IxEthDBMacAddr *macAddr) | |
54 | { | |
55 | IX_ETH_DB_CHECK_PORT(portID); | |
56 | ||
57 | IX_ETH_DB_CHECK_SINGLE_NPE(portID); | |
58 | ||
59 | IX_ETH_DB_CHECK_REFERENCE(macAddr); | |
60 | ||
61 | IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_LEARNING); | |
62 | ||
472d5460 | 63 | return ixEthDBTriggerAddPortUpdate(macAddr, portID, true); |
ba94a1bb WD |
64 | } |
65 | ||
66 | IX_ETH_DB_PUBLIC | |
67 | IxEthDBStatus ixEthDBFilteringDynamicEntryProvision(IxEthDBPortId portID, IxEthDBMacAddr *macAddr) | |
68 | { | |
69 | IX_ETH_DB_CHECK_PORT(portID); | |
70 | ||
71 | IX_ETH_DB_CHECK_SINGLE_NPE(portID); | |
72 | ||
73 | IX_ETH_DB_CHECK_REFERENCE(macAddr); | |
74 | ||
75 | IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_LEARNING); | |
76 | ||
472d5460 | 77 | return ixEthDBTriggerAddPortUpdate(macAddr, portID, false); |
ba94a1bb WD |
78 | } |
79 | ||
80 | IX_ETH_DB_PUBLIC | |
81 | IxEthDBStatus ixEthDBFilteringEntryDelete(IxEthDBMacAddr *macAddr) | |
82 | { | |
83 | HashNode *searchResult; | |
84 | ||
85 | IX_ETH_DB_CHECK_REFERENCE(macAddr); | |
86 | ||
87 | searchResult = ixEthDBSearch(macAddr, IX_ETH_DB_ALL_FILTERING_RECORDS); | |
88 | ||
89 | if (searchResult == NULL) | |
90 | { | |
91 | return IX_ETH_DB_NO_SUCH_ADDR; /* not found */ | |
92 | } | |
93 | ||
94 | ixEthDBReleaseHashNode(searchResult); | |
95 | ||
96 | /* build a remove event and place it on the event queue */ | |
97 | return ixEthDBTriggerRemovePortUpdate(macAddr, ((MacDescriptor *) searchResult->data)->portID); | |
98 | } | |
99 | ||
100 | IX_ETH_DB_PUBLIC | |
101 | void ixEthDBDatabaseMaintenance() | |
102 | { | |
103 | HashIterator iterator; | |
104 | UINT32 portIndex; | |
472d5460 | 105 | BOOL agingRequired = false; |
ba94a1bb WD |
106 | |
107 | /* ports who will have deleted records and therefore will need updating */ | |
108 | IxEthDBPortMap triggerPorts; | |
109 | ||
110 | if (IX_FEATURE_CTRL_SWCONFIG_ENABLED != | |
111 | ixFeatureCtrlSwConfigurationCheck (IX_FEATURECTRL_ETH_LEARNING)) | |
112 | { | |
113 | return; | |
114 | } | |
115 | ||
116 | SET_EMPTY_DEPENDENCY_MAP(triggerPorts); | |
117 | ||
118 | /* check if there's at least a port that needs aging */ | |
119 | for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++) | |
120 | { | |
121 | if (ixEthDBPortInfo[portIndex].agingEnabled && ixEthDBPortInfo[portIndex].enabled) | |
122 | { | |
472d5460 | 123 | agingRequired = true; |
ba94a1bb WD |
124 | } |
125 | } | |
126 | ||
127 | if (agingRequired) | |
128 | { | |
129 | /* ask each NPE port to write back the database for aging inspection */ | |
130 | for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++) | |
131 | { | |
132 | if (ixEthDBPortDefinitions[portIndex].type == IX_ETH_NPE | |
133 | && ixEthDBPortInfo[portIndex].agingEnabled | |
134 | && ixEthDBPortInfo[portIndex].enabled) | |
135 | { | |
136 | IxNpeMhMessage message; | |
137 | IX_STATUS result; | |
138 | ||
139 | /* send EDB_GetMACAddressDatabase message */ | |
140 | FILL_GETMACADDRESSDATABASE(message, | |
141 | 0 /* unused */, | |
142 | IX_OSAL_MMU_VIRT_TO_PHYS(ixEthDBPortInfo[portIndex].updateMethod.npeUpdateZone)); | |
143 | ||
144 | IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portIndex), message, result); | |
145 | ||
146 | if (result == IX_SUCCESS) | |
147 | { | |
148 | /* analyze NPE copy */ | |
149 | ixEthDBNPESyncScan(portIndex, ixEthDBPortInfo[portIndex].updateMethod.npeUpdateZone, FULL_ELT_BYTE_SIZE); | |
150 | ||
151 | IX_ETH_DB_SUPPORT_TRACE("DB: (API) Finished scanning NPE tree on port %d\n", portIndex); | |
152 | } | |
153 | else | |
154 | { | |
472d5460 YS |
155 | ixEthDBPortInfo[portIndex].agingEnabled = false; |
156 | ixEthDBPortInfo[portIndex].updateMethod.updateEnabled = false; | |
157 | ixEthDBPortInfo[portIndex].updateMethod.userControlled = true; | |
ba94a1bb WD |
158 | |
159 | ixOsalLog(IX_OSAL_LOG_LVL_FATAL, | |
160 | IX_OSAL_LOG_DEV_STDOUT, | |
161 | "EthDB: (Maintenance) warning, disabling aging and updates for port %d (assumed dead)\n", | |
162 | portIndex, 0, 0, 0, 0, 0); | |
163 | ||
164 | ixEthDBDatabaseClear(portIndex, IX_ETH_DB_ALL_RECORD_TYPES); | |
165 | } | |
166 | } | |
167 | } | |
168 | ||
169 | /* browse database and age entries */ | |
170 | BUSY_RETRY(ixEthDBInitHashIterator(&dbHashtable, &iterator)); | |
171 | ||
172 | while (IS_ITERATOR_VALID(&iterator)) | |
173 | { | |
174 | MacDescriptor *descriptor = (MacDescriptor *) iterator.node->data; | |
175 | UINT32 *age = NULL; | |
472d5460 | 176 | BOOL staticEntry = true; |
ba94a1bb WD |
177 | |
178 | if (descriptor->type == IX_ETH_DB_FILTERING_RECORD) | |
179 | { | |
180 | age = &descriptor->recordData.filteringData.age; | |
181 | staticEntry = descriptor->recordData.filteringData.staticEntry; | |
182 | } | |
183 | else if (descriptor->type == IX_ETH_DB_FILTERING_VLAN_RECORD) | |
184 | { | |
185 | age = &descriptor->recordData.filteringVlanData.age; | |
186 | staticEntry = descriptor->recordData.filteringVlanData.staticEntry; | |
187 | } | |
188 | else | |
189 | { | |
472d5460 | 190 | staticEntry = true; |
ba94a1bb WD |
191 | } |
192 | ||
472d5460 | 193 | if (ixEthDBPortInfo[descriptor->portID].agingEnabled && (staticEntry == false)) |
ba94a1bb WD |
194 | { |
195 | /* manually increment the age if the port has no such capability */ | |
196 | if ((ixEthDBPortDefinitions[descriptor->portID].capabilities & IX_ETH_ENTRY_AGING) == 0) | |
197 | { | |
198 | *age += (IX_ETH_DB_MAINTENANCE_TIME / 60); | |
199 | } | |
200 | ||
201 | /* age entry if it exceeded the maximum time to live */ | |
202 | if (*age >= (IX_ETH_DB_LEARNING_ENTRY_AGE_TIME / 60)) | |
203 | { | |
204 | /* add port to the set of update trigger ports */ | |
205 | JOIN_PORT_TO_MAP(triggerPorts, descriptor->portID); | |
206 | ||
207 | /* delete entry */ | |
208 | BUSY_RETRY(ixEthDBRemoveEntryAtHashIterator(&dbHashtable, &iterator)); | |
209 | } | |
210 | else | |
211 | { | |
212 | /* move to the next record */ | |
213 | BUSY_RETRY(ixEthDBIncrementHashIterator(&dbHashtable, &iterator)); | |
214 | } | |
215 | } | |
216 | else | |
217 | { | |
218 | /* move to the next record */ | |
219 | BUSY_RETRY(ixEthDBIncrementHashIterator(&dbHashtable, &iterator)); | |
220 | } | |
221 | } | |
222 | ||
223 | /* update ports which lost records */ | |
224 | ixEthDBUpdatePortLearningTrees(triggerPorts); | |
225 | } | |
226 | } | |
227 | ||
228 | IX_ETH_DB_PUBLIC | |
229 | IxEthDBStatus ixEthDBDatabaseClear(IxEthDBPortId portID, IxEthDBRecordType recordType) | |
230 | { | |
231 | IxEthDBPortMap triggerPorts; | |
232 | HashIterator iterator; | |
233 | ||
234 | if (portID >= IX_ETH_DB_NUMBER_OF_PORTS && portID != IX_ETH_DB_ALL_PORTS) | |
235 | { | |
236 | return IX_ETH_DB_INVALID_PORT; | |
237 | } | |
238 | ||
239 | /* check if the user passes some extra bits */ | |
240 | if ((recordType | IX_ETH_DB_ALL_RECORD_TYPES) != IX_ETH_DB_ALL_RECORD_TYPES) | |
241 | { | |
242 | return IX_ETH_DB_INVALID_ARG; | |
243 | } | |
244 | ||
245 | SET_EMPTY_DEPENDENCY_MAP(triggerPorts); | |
246 | ||
247 | /* browse database and age entries */ | |
248 | BUSY_RETRY(ixEthDBInitHashIterator(&dbHashtable, &iterator)); | |
249 | ||
250 | while (IS_ITERATOR_VALID(&iterator)) | |
251 | { | |
252 | MacDescriptor *descriptor = (MacDescriptor *) iterator.node->data; | |
253 | ||
254 | if (((descriptor->portID == portID) || (portID == IX_ETH_DB_ALL_PORTS)) | |
255 | && ((descriptor->type & recordType) != 0)) | |
256 | { | |
257 | /* add to trigger if automatic updates are required */ | |
258 | if (ixEthDBPortUpdateRequired[descriptor->type]) | |
259 | { | |
260 | /* add port to the set of update trigger ports */ | |
261 | JOIN_PORT_TO_MAP(triggerPorts, descriptor->portID); | |
262 | } | |
263 | ||
264 | /* delete entry */ | |
265 | BUSY_RETRY(ixEthDBRemoveEntryAtHashIterator(&dbHashtable, &iterator)); | |
266 | } | |
267 | else | |
268 | { | |
269 | /* move to the next record */ | |
270 | BUSY_RETRY(ixEthDBIncrementHashIterator(&dbHashtable, &iterator)); | |
271 | } | |
272 | } | |
273 | ||
274 | /* update ports which lost records */ | |
275 | ixEthDBUpdatePortLearningTrees(triggerPorts); | |
276 | ||
277 | return IX_ETH_DB_SUCCESS; | |
278 | } | |
279 | ||
280 | IX_ETH_DB_PUBLIC | |
281 | IxEthDBStatus ixEthDBFilteringPortSearch(IxEthDBPortId portID, IxEthDBMacAddr *macAddr) | |
282 | { | |
283 | HashNode *searchResult; | |
284 | IxEthDBStatus result = IX_ETH_DB_NO_SUCH_ADDR; | |
285 | ||
286 | IX_ETH_DB_CHECK_PORT(portID); | |
287 | ||
288 | IX_ETH_DB_CHECK_SINGLE_NPE(portID); | |
289 | ||
290 | IX_ETH_DB_CHECK_REFERENCE(macAddr); | |
291 | ||
292 | IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_LEARNING); | |
293 | ||
294 | searchResult = ixEthDBSearch(macAddr, IX_ETH_DB_ALL_FILTERING_RECORDS); | |
295 | ||
296 | if (searchResult == NULL) | |
297 | { | |
298 | return IX_ETH_DB_NO_SUCH_ADDR; /* not found */ | |
299 | } | |
300 | ||
301 | if (((MacDescriptor *) (searchResult->data))->portID == portID) | |
302 | { | |
303 | result = IX_ETH_DB_SUCCESS; /* address and port match */ | |
304 | } | |
305 | ||
306 | ixEthDBReleaseHashNode(searchResult); | |
307 | ||
308 | return result; | |
309 | } | |
310 | ||
311 | IX_ETH_DB_PUBLIC | |
312 | IxEthDBStatus ixEthDBFilteringDatabaseSearch(IxEthDBPortId *portID, IxEthDBMacAddr *macAddr) | |
313 | { | |
314 | HashNode *searchResult; | |
315 | ||
316 | IX_ETH_DB_CHECK_REFERENCE(portID); | |
317 | ||
318 | IX_ETH_DB_CHECK_REFERENCE(macAddr); | |
319 | ||
320 | searchResult = ixEthDBSearch(macAddr, IX_ETH_DB_ALL_FILTERING_RECORDS); | |
321 | ||
322 | if (searchResult == NULL) | |
323 | { | |
324 | return IX_ETH_DB_NO_SUCH_ADDR; /* not found */ | |
325 | } | |
326 | ||
327 | /* return the port ID */ | |
328 | *portID = ((MacDescriptor *) searchResult->data)->portID; | |
329 | ||
330 | ixEthDBReleaseHashNode(searchResult); | |
331 | ||
332 | return IX_ETH_DB_SUCCESS; | |
333 | } | |
334 | ||
335 | IX_ETH_DB_PUBLIC | |
336 | IxEthDBStatus ixEthDBPortAgingDisable(IxEthDBPortId portID) | |
337 | { | |
338 | IX_ETH_DB_CHECK_PORT(portID); | |
339 | ||
340 | IX_ETH_DB_CHECK_SINGLE_NPE(portID); | |
341 | ||
342 | IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_LEARNING); | |
343 | ||
472d5460 | 344 | ixEthDBPortInfo[portID].agingEnabled = false; |
ba94a1bb WD |
345 | |
346 | return IX_ETH_DB_SUCCESS; | |
347 | } | |
348 | ||
349 | IX_ETH_DB_PUBLIC | |
350 | IxEthDBStatus ixEthDBPortAgingEnable(IxEthDBPortId portID) | |
351 | { | |
352 | IX_ETH_DB_CHECK_PORT(portID); | |
353 | ||
354 | IX_ETH_DB_CHECK_SINGLE_NPE(portID); | |
355 | ||
356 | IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_LEARNING); | |
357 | ||
472d5460 | 358 | ixEthDBPortInfo[portID].agingEnabled = true; |
ba94a1bb WD |
359 | |
360 | return IX_ETH_DB_SUCCESS; | |
361 | } | |
362 | ||
363 | IX_ETH_DB_PUBLIC | |
364 | IxEthDBStatus ixEthDBFilteringPortUpdatingSearch(IxEthDBPortId *portID, IxEthDBMacAddr *macAddr) | |
365 | { | |
366 | HashNode *searchResult; | |
367 | MacDescriptor *descriptor; | |
368 | ||
369 | IX_ETH_DB_CHECK_REFERENCE(portID); | |
370 | ||
371 | IX_ETH_DB_CHECK_REFERENCE(macAddr); | |
372 | ||
373 | searchResult = ixEthDBSearch(macAddr, IX_ETH_DB_ALL_FILTERING_RECORDS); | |
374 | ||
375 | if (searchResult == NULL) | |
376 | { | |
377 | return IX_ETH_DB_NO_SUCH_ADDR; /* not found */ | |
378 | } | |
379 | ||
380 | descriptor = (MacDescriptor *) searchResult->data; | |
381 | ||
382 | /* return the port ID */ | |
383 | *portID = descriptor->portID; | |
384 | ||
385 | /* reset entry age */ | |
386 | if (descriptor->type == IX_ETH_DB_FILTERING_RECORD) | |
387 | { | |
388 | descriptor->recordData.filteringData.age = 0; | |
389 | } | |
390 | else | |
391 | { | |
392 | descriptor->recordData.filteringVlanData.age = 0; | |
393 | } | |
394 | ||
395 | ixEthDBReleaseHashNode(searchResult); | |
396 | ||
397 | return IX_ETH_DB_SUCCESS; | |
398 | } | |
399 | ||
400 | IX_ETH_DB_PUBLIC | |
401 | IxEthDBStatus ixEthDBPortDependencyMapSet(IxEthDBPortId portID, IxEthDBPortMap dependencyPortMap) | |
402 | { | |
403 | IX_ETH_DB_CHECK_PORT(portID); | |
404 | ||
405 | IX_ETH_DB_CHECK_SINGLE_NPE(portID); | |
406 | ||
407 | IX_ETH_DB_CHECK_REFERENCE(dependencyPortMap); | |
408 | ||
409 | IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_FILTERING); | |
410 | ||
411 | /* force bit at offset 255 to 0 (reserved) */ | |
412 | dependencyPortMap[31] &= 0xFE; | |
413 | ||
414 | COPY_DEPENDENCY_MAP(ixEthDBPortInfo[portID].dependencyPortMap, dependencyPortMap); | |
415 | ||
416 | return IX_ETH_DB_SUCCESS; | |
417 | } | |
418 | ||
419 | IX_ETH_DB_PUBLIC | |
420 | IxEthDBStatus ixEthDBPortDependencyMapGet(IxEthDBPortId portID, IxEthDBPortMap dependencyPortMap) | |
421 | { | |
422 | IX_ETH_DB_CHECK_PORT(portID); | |
423 | ||
424 | IX_ETH_DB_CHECK_SINGLE_NPE(portID); | |
425 | ||
426 | IX_ETH_DB_CHECK_REFERENCE(dependencyPortMap); | |
427 | ||
428 | IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_FILTERING); | |
429 | ||
430 | COPY_DEPENDENCY_MAP(dependencyPortMap, ixEthDBPortInfo[portID].dependencyPortMap); | |
431 | ||
432 | return IX_ETH_DB_SUCCESS; | |
433 | } | |
434 | ||
435 | IX_ETH_DB_PUBLIC | |
436 | IxEthDBStatus ixEthDBPortUpdateEnableSet(IxEthDBPortId portID, BOOL enableUpdate) | |
437 | { | |
438 | IX_ETH_DB_CHECK_PORT(portID); | |
439 | ||
440 | IX_ETH_DB_CHECK_SINGLE_NPE(portID); | |
441 | ||
442 | IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_FILTERING); | |
443 | ||
444 | ixEthDBPortInfo[portID].updateMethod.updateEnabled = enableUpdate; | |
472d5460 | 445 | ixEthDBPortInfo[portID].updateMethod.userControlled = true; |
ba94a1bb WD |
446 | |
447 | return IX_ETH_DB_SUCCESS; | |
448 | } |