source: SVN/rincon/u-boot/cpu/ixp/npe/IxEthDBCore.c @ 55

Last change on this file since 55 was 55, checked in by Tim Harvey, 22 months ago

rincon: added latest u-boot source

restored form server backup

Signed-off-by: Tim Harvey <tharvey@…>

File size: 13.9 KB
Line 
1/**
2 * @file IxEthDBDBCore.c
3 *
4 * @brief Database support functions
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
47/* list of database hashtables */
48IX_ETH_DB_PUBLIC HashTable dbHashtable;
49IX_ETH_DB_PUBLIC MatchFunction matchFunctions[IX_ETH_DB_MAX_KEY_INDEX + 1];
50IX_ETH_DB_PUBLIC BOOL ixEthDBPortUpdateRequired[IX_ETH_DB_MAX_RECORD_TYPE_INDEX + 1];
51IX_ETH_DB_PUBLIC UINT32 ixEthDBKeyType[IX_ETH_DB_MAX_RECORD_TYPE_INDEX + 1];
52
53/* private initialization flag */
54IX_ETH_DB_PRIVATE BOOL ethDBInitializationComplete = FALSE;
55
56/**
57 * @brief initializes EthDB
58 *
59 * This function must be called to initialize the component.
60 *
61 * It does the following things:
62 * - checks the port definition structure
63 * - scans the capabilities of the NPE images and sets the
64 *   capabilities of the ports accordingly
65 * - initializes the memory pools internally used in EthDB
66 *   for storing database records and handling data
67 * - registers automatic update handlers for add and remove
68 *   operations
69 * - registers hashing match functions, depending on key sets
70 * - initializes the main database hashtable
71 * - allocates contiguous memory zones to be used for NPE
72 *   updates
73 * - registers the serialize methods used to convert data
74 *   into NPE-readable format
75 * - starts the event processor
76 *
77 * Note that this function is documented in the public
78 * component header file, IxEthDB.h.
79 *
80 * @return IX_ETH_DB_SUCCESS or an appropriate error if the
81 * component failed to initialize correctly
82 */
83IX_ETH_DB_PUBLIC
84IxEthDBStatus ixEthDBInit(void)
85{
86    IxEthDBStatus result;
87
88    if (ethDBInitializationComplete)
89    {
90        /* redundant */
91        return IX_ETH_DB_SUCCESS;
92    }
93
94    /* trap an invalid port definition structure */
95    IX_ETH_DB_PORTS_ASSERTION;
96
97    /* memory management */
98    ixEthDBInitMemoryPools();
99
100    /* register hashing search methods */
101    ixEthDBMatchMethodsRegister(matchFunctions);
102
103    /* register type-based automatic port updates */
104    ixEthDBUpdateTypeRegister(ixEthDBPortUpdateRequired);
105
106    /* register record to key type mappings */
107    ixEthDBKeyTypeRegister(ixEthDBKeyType);
108
109    /* hash table */
110    ixEthDBInitHash(&dbHashtable, NUM_BUCKETS, ixEthDBEntryXORHash, matchFunctions, (FreeFunction) ixEthDBFreeMacDescriptor);
111
112    /* NPE update zones */
113    ixEthDBNPEUpdateAreasInit();
114
115    /* register record serialization methods */
116    ixEthDBRecordSerializeMethodsRegister();
117
118    /* start the event processor */
119    result = ixEthDBEventProcessorInit();
120
121    /* scan NPE features */
122    if (result == IX_ETH_DB_SUCCESS)
123    {
124        ixEthDBFeatureCapabilityScan();
125    }
126
127    ethDBInitializationComplete = TRUE;
128
129    return result;
130}
131
132/**
133 * @brief prepares EthDB for unloading
134 *
135 * This function must be called before removing the
136 * EthDB component from memory (e.g. doing rmmod in
137 * Linux) if the component is to be re-initialized again
138 * without rebooting the platform.
139 *
140 * All the EthDB ports must be disabled before this
141 * function is to be called. Failure to disable all
142 * the ports will return the IX_ETH_DB_BUSY error.
143 *
144 * This function will destroy mutexes, deallocate
145 * memory and stop the event processor.
146 *
147 * Note that this function is fully documented in the
148 * main component header file, IxEthDB.h.
149 *
150 * @return IX_ETH_DB_SUCCESS if de-initialization
151 * completed successfully or an appropriate error
152 * message otherwise
153 */
154IX_ETH_DB_PUBLIC
155IxEthDBStatus ixEthDBUnload(void)
156{
157    IxEthDBPortId portIndex;
158
159    if (!ethDBInitializationComplete)
160    {
161        /* redundant */
162        return IX_ETH_DB_SUCCESS;
163    }
164
165    /* check if any ports are enabled */
166    for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
167    {
168        if (ixEthDBPortInfo[portIndex].enabled)
169        {
170            return IX_ETH_DB_BUSY;
171        }
172    }
173
174    /* free port resources */
175    for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
176    {
177        if (ixEthDBPortDefinitions[portIndex].type == IX_ETH_NPE)
178        {
179            ixOsalMutexDestroy(&ixEthDBPortInfo[portIndex].npeAckLock);
180        }
181
182        ixEthDBPortInfo[portIndex].initialized = FALSE;
183    }
184
185    /* shutdown event processor */
186    ixEthDBStopLearningFunction();
187
188    /* deallocate NPE update zones */
189    ixEthDBNPEUpdateAreasUnload();
190
191    ethDBInitializationComplete = FALSE;
192
193    return IX_ETH_DB_SUCCESS;
194}
195
196/**
197 * @brief adds a new entry to the Ethernet database
198 *
199 * @param newRecordTemplate address of the record template to use
200 * @param updateTrigger port map containing the update triggers
201 * resulting from this update operation
202 *
203 * Creates a new database entry, populates it with the data
204 * copied from the given template and adds the record to the
205 * database hash table.
206 * It also checks whether the new record type is registered to trigger
207 * automatic updates; if it is, the update trigger will contain the
208 * port on which the record insertion was performed, as well as the
209 * old port in case the addition was a record migration (from one port
210 * to the other). The caller can use the updateTrigger to trigger
211 * automatic updates on the ports changed as a result of this addition.
212 *
213 * @retval IX_ETH_DB_SUCCESS addition successful
214 * @retval IX_ETH_DB_NOMEM insertion failed, no memory left in the mac descriptor memory pool
215 * @retval IX_ETH_DB_BUSY database busy, cannot insert due to locking
216 *
217 * @internal
218 */
219IX_ETH_DB_PUBLIC
220IxEthDBStatus ixEthDBAdd(MacDescriptor *newRecordTemplate, IxEthDBPortMap updateTrigger)
221{
222    IxEthDBStatus result;
223    MacDescriptor *newDescriptor;
224    IxEthDBPortId originalPortID;
225    HashNode *node = NULL;
226
227    BUSY_RETRY(ixEthDBSearchHashEntry(&dbHashtable, ixEthDBKeyType[newRecordTemplate->type], newRecordTemplate, &node));
228
229    TEST_FIXTURE_INCREMENT_DB_CORE_ACCESS_COUNTER;
230
231    if (node == NULL)
232    {
233        /* not found, create a new one */
234        newDescriptor = ixEthDBAllocMacDescriptor();
235
236        if (newDescriptor == NULL)
237        {
238            return IX_ETH_DB_NOMEM; /* no memory */
239        }
240
241        /* old port does not exist, avoid unnecessary updates */
242        originalPortID = newRecordTemplate->portID;
243    }
244    else
245    {
246        /* a node with the same key exists, will update node */
247        newDescriptor = (MacDescriptor *) node->data;
248
249        /* save original port id */
250        originalPortID = newDescriptor->portID;
251    }
252
253    /* copy/update fields into new record */
254    memcpy(newDescriptor->macAddress, newRecordTemplate->macAddress, sizeof (IxEthDBMacAddr));
255    memcpy(&newDescriptor->recordData, &newRecordTemplate->recordData, sizeof (IxEthDBRecordData));
256
257    newDescriptor->type   = newRecordTemplate->type;
258    newDescriptor->portID = newRecordTemplate->portID;
259    newDescriptor->user   = newRecordTemplate->user;
260
261    if (node == NULL)
262    {
263        /* new record, insert into hashtable */
264        BUSY_RETRY_WITH_RESULT(ixEthDBAddHashEntry(&dbHashtable, newDescriptor), result);
265
266        if (result != IX_ETH_DB_SUCCESS)
267        {
268            ixEthDBFreeMacDescriptor(newDescriptor);
269
270            return result; /* insertion failed */
271        }
272    }
273
274    if (node != NULL)
275    {
276        /* release access */
277        ixEthDBReleaseHashNode(node);
278    }
279
280    /* trigger add/remove update if required by type */
281    if (updateTrigger != NULL &&
282        ixEthDBPortUpdateRequired[newRecordTemplate->type])
283    {
284        /* add new port to update list */
285        JOIN_PORT_TO_MAP(updateTrigger, newRecordTemplate->portID);
286
287        /* check if record has moved, we'll need to update the old port as well */
288        if (originalPortID != newDescriptor->portID)
289        {
290            JOIN_PORT_TO_MAP(updateTrigger, originalPortID);
291        }
292    }
293
294    return IX_ETH_DB_SUCCESS;
295}
296
297/**
298 * @brief remove a record from the Ethernet database
299 *
300 * @param templateRecord template record used to determine
301 * what record is to be removed
302 * @param updateTrigger port map containing the update triggers
303 * resulting from this update operation
304 *
305 * This function will examine the template record it receives
306 * and attempts to delete a record of the same type and containing
307 * the same keys as the template record. If deletion is successful
308 * and the record type is registered for automatic port updates the
309 * port will also be set in the updateTrigger port map, so that the
310 * client can perform an update of the port.
311 *
312 * @retval IX_ETH_DB_SUCCESS removal was successful
313 * @retval IX_ETH_DB_NO_SUCH_ADDR the record with the given MAC address was not found
314 * @retval IX_ETH_DB_BUSY database busy, cannot remove due to locking
315 *
316 * @internal
317 */
318IX_ETH_DB_PUBLIC
319IxEthDBStatus ixEthDBRemove(MacDescriptor *templateRecord, IxEthDBPortMap updateTrigger)
320{
321    IxEthDBStatus result;
322
323    TEST_FIXTURE_INCREMENT_DB_CORE_ACCESS_COUNTER;
324
325    BUSY_RETRY_WITH_RESULT(ixEthDBRemoveHashEntry(&dbHashtable, ixEthDBKeyType[templateRecord->type], templateRecord), result);
326
327    if (result != IX_ETH_DB_SUCCESS)
328    {
329        return IX_ETH_DB_NO_SUCH_ADDR; /* not found */
330    }
331
332    /* trigger add/remove update if required by type */
333    if (updateTrigger != NULL
334        &&ixEthDBPortUpdateRequired[templateRecord->type])
335    {
336        /* add new port to update list */
337        JOIN_PORT_TO_MAP(updateTrigger, templateRecord->portID);
338    }
339
340    return IX_ETH_DB_SUCCESS;
341}
342
343/**
344 * @brief register record key types
345 *
346 * This function registers the appropriate key types,
347 * depending on record types.
348 *
349 * All filtering records use the MAC address as the key.
350 * WiFi and Firewall records use a compound key consisting
351 * in both the MAC address and the port ID.
352 *
353 * @return the number of registered record types
354 */
355IX_ETH_DB_PUBLIC
356UINT32 ixEthDBKeyTypeRegister(UINT32 *keyType)
357{
358    /* safety */
359    memset(keyType, 0, sizeof (keyType));
360
361    /* register all known record types */
362    keyType[IX_ETH_DB_FILTERING_RECORD]      = IX_ETH_DB_MAC_KEY;
363    keyType[IX_ETH_DB_FILTERING_VLAN_RECORD] = IX_ETH_DB_MAC_KEY;
364    keyType[IX_ETH_DB_ALL_FILTERING_RECORDS] = IX_ETH_DB_MAC_KEY;
365    keyType[IX_ETH_DB_WIFI_RECORD]           = IX_ETH_DB_MAC_PORT_KEY;
366    keyType[IX_ETH_DB_FIREWALL_RECORD]       = IX_ETH_DB_MAC_PORT_KEY;
367
368    return 5;
369}
370
371/**
372 * @brief Sets a user-defined field into a database record
373 *
374 * Note that this function is fully documented in the main component
375 * header file.
376 */
377IX_ETH_DB_PUBLIC
378IxEthDBStatus ixEthDBUserFieldSet(IxEthDBRecordType recordType, IxEthDBMacAddr *macAddr, IxEthDBPortId portID, IxEthDBVlanId vlanID, void *field)
379{
380    HashNode *result = NULL;
381
382    if (macAddr == NULL)
383    {
384        return IX_ETH_DB_INVALID_ARG;
385    }
386
387    if (recordType == IX_ETH_DB_FILTERING_RECORD)
388    {
389        result = ixEthDBSearch(macAddr, recordType);
390    }
391    else if (recordType == IX_ETH_DB_FILTERING_VLAN_RECORD)
392    {
393        result = ixEthDBVlanSearch(macAddr, vlanID, recordType);
394    }
395    else if (recordType == IX_ETH_DB_WIFI_RECORD || recordType == IX_ETH_DB_FIREWALL_RECORD)
396    {
397        IX_ETH_DB_CHECK_PORT_EXISTS(portID);
398
399        result = ixEthDBPortSearch(macAddr, portID, recordType);
400    }
401    else
402    {
403        return IX_ETH_DB_INVALID_ARG;
404    }
405
406    if (result == NULL)
407    {
408        return IX_ETH_DB_NO_SUCH_ADDR;
409    }
410
411    ((MacDescriptor *) result->data)->user = field;
412
413    ixEthDBReleaseHashNode(result);
414
415    return IX_ETH_DB_SUCCESS;
416}
417
418/**
419 * @brief Retrieves a user-defined field from a database record
420 *
421 * Note that this function is fully documented in the main component
422 * header file.
423 */
424IX_ETH_DB_PUBLIC
425IxEthDBStatus ixEthDBUserFieldGet(IxEthDBRecordType recordType, IxEthDBMacAddr *macAddr, IxEthDBPortId portID, IxEthDBVlanId vlanID, void **field)
426{
427    HashNode *result = NULL;
428
429    if (macAddr == NULL || field == NULL)
430    {
431        return IX_ETH_DB_INVALID_ARG;
432    }
433
434    if (recordType == IX_ETH_DB_FILTERING_RECORD)
435    {
436        result = ixEthDBSearch(macAddr, recordType);
437    }
438    else if (recordType == IX_ETH_DB_FILTERING_VLAN_RECORD)
439    {
440        result = ixEthDBVlanSearch(macAddr, vlanID, recordType);
441    }
442    else if (recordType == IX_ETH_DB_WIFI_RECORD || recordType == IX_ETH_DB_FIREWALL_RECORD)
443    {
444        IX_ETH_DB_CHECK_PORT_EXISTS(portID);
445
446        result = ixEthDBPortSearch(macAddr, portID, recordType);
447    }
448    else
449    {
450        return IX_ETH_DB_INVALID_ARG;
451    }
452
453    if (result == NULL)
454    {
455        return IX_ETH_DB_NO_SUCH_ADDR;
456    }
457
458    *field = ((MacDescriptor *) result->data)->user;
459
460    ixEthDBReleaseHashNode(result);
461
462    return IX_ETH_DB_SUCCESS;
463}
Note: See TracBrowser for help on using the repository browser.