IxEthDBCore.c 14 KB

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