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
;