blob: b2bfb72606e1e1f67c78ada3ee1dc009de10c33e [file] [log] [blame]
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02001/**
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
48extern HashTable dbHashtable;
49extern IxEthDBPortMap overflowUpdatePortList;
50extern BOOL ixEthDBPortUpdateRequired[IX_ETH_DB_MAX_RECORD_TYPE_INDEX + 1];
51
52IX_ETH_DB_PUBLIC
53IxEthDBStatus 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
63 return ixEthDBTriggerAddPortUpdate(macAddr, portID, TRUE);
64}
65
66IX_ETH_DB_PUBLIC
67IxEthDBStatus 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
77 return ixEthDBTriggerAddPortUpdate(macAddr, portID, FALSE);
78}
79
80IX_ETH_DB_PUBLIC
81IxEthDBStatus 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
100IX_ETH_DB_PUBLIC
101void ixEthDBDatabaseMaintenance()
102{
103 HashIterator iterator;
104 UINT32 portIndex;
105 BOOL agingRequired = FALSE;
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 {
123 agingRequired = TRUE;
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 {
155 ixEthDBPortInfo[portIndex].agingEnabled = FALSE;
156 ixEthDBPortInfo[portIndex].updateMethod.updateEnabled = FALSE;
157 ixEthDBPortInfo[portIndex].updateMethod.userControlled = TRUE;
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;
176 BOOL staticEntry = TRUE;
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 {
190 staticEntry = TRUE;
191 }
192
193 if (ixEthDBPortInfo[descriptor->portID].agingEnabled && (staticEntry == FALSE))
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
228IX_ETH_DB_PUBLIC
229IxEthDBStatus 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
280IX_ETH_DB_PUBLIC
281IxEthDBStatus 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
311IX_ETH_DB_PUBLIC
312IxEthDBStatus 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
335IX_ETH_DB_PUBLIC
336IxEthDBStatus 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
344 ixEthDBPortInfo[portID].agingEnabled = FALSE;
345
346 return IX_ETH_DB_SUCCESS;
347}
348
349IX_ETH_DB_PUBLIC
350IxEthDBStatus 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
358 ixEthDBPortInfo[portID].agingEnabled = TRUE;
359
360 return IX_ETH_DB_SUCCESS;
361}
362
363IX_ETH_DB_PUBLIC
364IxEthDBStatus 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
400IX_ETH_DB_PUBLIC
401IxEthDBStatus 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
419IX_ETH_DB_PUBLIC
420IxEthDBStatus 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
435IX_ETH_DB_PUBLIC
436IxEthDBStatus 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;
445 ixEthDBPortInfo[portID].updateMethod.userControlled = TRUE;
446
447 return IX_ETH_DB_SUCCESS;
448}