2 * @file IxEthDBDBCore.c
4 * @brief Database support functions
7 * IXP400 SW Release version 2.0
9 * -- Copyright Notice --
12 * Copyright 2001-2005, Intel Corporation.
13 * All rights reserved.
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
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.
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
42 * -- End of Copyright Notice --
45 #include "IxEthDB_p.h"
47 /* list of database hashtables */
48 IX_ETH_DB_PUBLIC HashTable dbHashtable;
49 IX_ETH_DB_PUBLIC MatchFunction matchFunctions[IX_ETH_DB_MAX_KEY_INDEX + 1];
50 IX_ETH_DB_PUBLIC BOOL ixEthDBPortUpdateRequired[IX_ETH_DB_MAX_RECORD_TYPE_INDEX + 1];
51 IX_ETH_DB_PUBLIC UINT32 ixEthDBKeyType[IX_ETH_DB_MAX_RECORD_TYPE_INDEX + 1];
53 /* private initialization flag */
54 IX_ETH_DB_PRIVATE BOOL ethDBInitializationComplete = FALSE;
57 * @brief initializes EthDB
59 * This function must be called to initialize the component.
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
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
73 * - registers the serialize methods used to convert data
74 * into NPE-readable format
75 * - starts the event processor
77 * Note that this function is documented in the public
78 * component header file, IxEthDB.h.
80 * @return IX_ETH_DB_SUCCESS or an appropriate error if the
81 * component failed to initialize correctly
84 IxEthDBStatus ixEthDBInit(void)
88 if (ethDBInitializationComplete)
91 return IX_ETH_DB_SUCCESS;
94 /* trap an invalid port definition structure */
95 IX_ETH_DB_PORTS_ASSERTION;
97 /* memory management */
98 ixEthDBInitMemoryPools();
100 /* register hashing search methods */
101 ixEthDBMatchMethodsRegister(matchFunctions);
103 /* register type-based automatic port updates */
104 ixEthDBUpdateTypeRegister(ixEthDBPortUpdateRequired);
106 /* register record to key type mappings */
107 ixEthDBKeyTypeRegister(ixEthDBKeyType);
110 ixEthDBInitHash(&dbHashtable, NUM_BUCKETS, ixEthDBEntryXORHash, matchFunctions, (FreeFunction) ixEthDBFreeMacDescriptor);
112 /* NPE update zones */
113 ixEthDBNPEUpdateAreasInit();
115 /* register record serialization methods */
116 ixEthDBRecordSerializeMethodsRegister();
118 /* start the event processor */
119 result = ixEthDBEventProcessorInit();
121 /* scan NPE features */
122 if (result == IX_ETH_DB_SUCCESS)
124 ixEthDBFeatureCapabilityScan();
127 ethDBInitializationComplete = TRUE;
133 * @brief prepares EthDB for unloading
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.
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.
144 * This function will destroy mutexes, deallocate
145 * memory and stop the event processor.
147 * Note that this function is fully documented in the
148 * main component header file, IxEthDB.h.
150 * @return IX_ETH_DB_SUCCESS if de-initialization
151 * completed successfully or an appropriate error
155 IxEthDBStatus ixEthDBUnload(void)
157 IxEthDBPortId portIndex;
159 if (!ethDBInitializationComplete)
162 return IX_ETH_DB_SUCCESS;
165 /* check if any ports are enabled */
166 for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
168 if (ixEthDBPortInfo[portIndex].enabled)
170 return IX_ETH_DB_BUSY;
174 /* free port resources */
175 for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
177 if (ixEthDBPortDefinitions[portIndex].type == IX_ETH_NPE)
179 ixOsalMutexDestroy(&ixEthDBPortInfo[portIndex].npeAckLock);
182 ixEthDBPortInfo[portIndex].initialized = FALSE;
185 /* shutdown event processor */
186 ixEthDBStopLearningFunction();
188 /* deallocate NPE update zones */
189 ixEthDBNPEUpdateAreasUnload();
191 ethDBInitializationComplete = FALSE;
193 return IX_ETH_DB_SUCCESS;
197 * @brief adds a new entry to the Ethernet database
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
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.
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
220 IxEthDBStatus ixEthDBAdd(MacDescriptor *newRecordTemplate, IxEthDBPortMap updateTrigger)
222 IxEthDBStatus result;
223 MacDescriptor *newDescriptor;
224 IxEthDBPortId originalPortID;
225 HashNode *node = NULL;
227 BUSY_RETRY(ixEthDBSearchHashEntry(&dbHashtable, ixEthDBKeyType[newRecordTemplate->type], newRecordTemplate, &node));
229 TEST_FIXTURE_INCREMENT_DB_CORE_ACCESS_COUNTER;
233 /* not found, create a new one */
234 newDescriptor = ixEthDBAllocMacDescriptor();
236 if (newDescriptor == NULL)
238 return IX_ETH_DB_NOMEM; /* no memory */
241 /* old port does not exist, avoid unnecessary updates */
242 originalPortID = newRecordTemplate->portID;
246 /* a node with the same key exists, will update node */
247 newDescriptor = (MacDescriptor *) node->data;
249 /* save original port id */
250 originalPortID = newDescriptor->portID;
253 /* copy/update fields into new record */
254 memcpy(newDescriptor->macAddress, newRecordTemplate->macAddress, sizeof (IxEthDBMacAddr));
255 memcpy(&newDescriptor->recordData, &newRecordTemplate->recordData, sizeof (IxEthDBRecordData));
257 newDescriptor->type = newRecordTemplate->type;
258 newDescriptor->portID = newRecordTemplate->portID;
259 newDescriptor->user = newRecordTemplate->user;
263 /* new record, insert into hashtable */
264 BUSY_RETRY_WITH_RESULT(ixEthDBAddHashEntry(&dbHashtable, newDescriptor), result);
266 if (result != IX_ETH_DB_SUCCESS)
268 ixEthDBFreeMacDescriptor(newDescriptor);
270 return result; /* insertion failed */
277 ixEthDBReleaseHashNode(node);
280 /* trigger add/remove update if required by type */
281 if (updateTrigger != NULL &&
282 ixEthDBPortUpdateRequired[newRecordTemplate->type])
284 /* add new port to update list */
285 JOIN_PORT_TO_MAP(updateTrigger, newRecordTemplate->portID);
287 /* check if record has moved, we'll need to update the old port as well */
288 if (originalPortID != newDescriptor->portID)
290 JOIN_PORT_TO_MAP(updateTrigger, originalPortID);
294 return IX_ETH_DB_SUCCESS;
298 * @brief remove a record from the Ethernet database
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
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.
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
319 IxEthDBStatus ixEthDBRemove(MacDescriptor *templateRecord, IxEthDBPortMap updateTrigger)
321 IxEthDBStatus result;
323 TEST_FIXTURE_INCREMENT_DB_CORE_ACCESS_COUNTER;
325 BUSY_RETRY_WITH_RESULT(ixEthDBRemoveHashEntry(&dbHashtable, ixEthDBKeyType[templateRecord->type], templateRecord), result);
327 if (result != IX_ETH_DB_SUCCESS)
329 return IX_ETH_DB_NO_SUCH_ADDR; /* not found */
332 /* trigger add/remove update if required by type */
333 if (updateTrigger != NULL
334 &&ixEthDBPortUpdateRequired[templateRecord->type])
336 /* add new port to update list */
337 JOIN_PORT_TO_MAP(updateTrigger, templateRecord->portID);
340 return IX_ETH_DB_SUCCESS;
344 * @brief register record key types
346 * This function registers the appropriate key types,
347 * depending on record types.
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.
353 * @return the number of registered record types
356 UINT32 ixEthDBKeyTypeRegister(UINT32 *keyType)
359 memset(keyType, 0, sizeof (keyType));
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;
372 * @brief Sets a user-defined field into a database record
374 * Note that this function is fully documented in the main component
378 IxEthDBStatus ixEthDBUserFieldSet(IxEthDBRecordType recordType, IxEthDBMacAddr *macAddr, IxEthDBPortId portID, IxEthDBVlanId vlanID, void *field)
380 HashNode *result = NULL;
384 return IX_ETH_DB_INVALID_ARG;
387 if (recordType == IX_ETH_DB_FILTERING_RECORD)
389 result = ixEthDBSearch(macAddr, recordType);
391 else if (recordType == IX_ETH_DB_FILTERING_VLAN_RECORD)
393 result = ixEthDBVlanSearch(macAddr, vlanID, recordType);
395 else if (recordType == IX_ETH_DB_WIFI_RECORD || recordType == IX_ETH_DB_FIREWALL_RECORD)
397 IX_ETH_DB_CHECK_PORT_EXISTS(portID);
399 result = ixEthDBPortSearch(macAddr, portID, recordType);
403 return IX_ETH_DB_INVALID_ARG;
408 return IX_ETH_DB_NO_SUCH_ADDR;
411 ((MacDescriptor *) result->data)->user = field;
413 ixEthDBReleaseHashNode(result);
415 return IX_ETH_DB_SUCCESS;
419 * @brief Retrieves a user-defined field from a database record
421 * Note that this function is fully documented in the main component
425 IxEthDBStatus ixEthDBUserFieldGet(IxEthDBRecordType recordType, IxEthDBMacAddr *macAddr, IxEthDBPortId portID, IxEthDBVlanId vlanID, void **field)
427 HashNode *result = NULL;
429 if (macAddr == NULL || field == NULL)
431 return IX_ETH_DB_INVALID_ARG;
434 if (recordType == IX_ETH_DB_FILTERING_RECORD)
436 result = ixEthDBSearch(macAddr, recordType);
438 else if (recordType == IX_ETH_DB_FILTERING_VLAN_RECORD)
440 result = ixEthDBVlanSearch(macAddr, vlanID, recordType);
442 else if (recordType == IX_ETH_DB_WIFI_RECORD || recordType == IX_ETH_DB_FIREWALL_RECORD)
444 IX_ETH_DB_CHECK_PORT_EXISTS(portID);
446 result = ixEthDBPortSearch(macAddr, portID, recordType);
450 return IX_ETH_DB_INVALID_ARG;
455 return IX_ETH_DB_NO_SUCH_ADDR;
458 *field = ((MacDescriptor *) result->data)->user;
460 ixEthDBReleaseHashNode(result);
462 return IX_ETH_DB_SUCCESS;