IxEthDBEvents.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. /**
  2. * @file IxEthDBEvents.c
  3. *
  4. * @brief Implementation of the event processor component
  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. * SPDX-License-Identifier: BSD-3-Clause
  17. * @par
  18. * -- End of Copyright Notice --
  19. */
  20. #include <IxNpeMh.h>
  21. #include <IxFeatureCtrl.h>
  22. #include "IxEthDB_p.h"
  23. /* forward prototype declarations */
  24. IX_ETH_DB_PUBLIC void ixEthDBEventProcessorLoop(void *);
  25. IX_ETH_DB_PUBLIC void ixEthDBNPEEventCallback(IxNpeMhNpeId npeID, IxNpeMhMessage msg);
  26. IX_ETH_DB_PRIVATE void ixEthDBProcessEvent(PortEvent *local_event, IxEthDBPortMap triggerPorts);
  27. IX_ETH_DB_PRIVATE IxEthDBStatus ixEthDBTriggerPortUpdate(UINT32 eventType, IxEthDBMacAddr *macAddr, IxEthDBPortId portID, BOOL staticEntry);
  28. IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBStartLearningFunction(void);
  29. IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBStopLearningFunction(void);
  30. /* data */
  31. IX_ETH_DB_PRIVATE IxOsalSemaphore eventQueueSemaphore;
  32. IX_ETH_DB_PRIVATE PortEventQueue eventQueue;
  33. IX_ETH_DB_PRIVATE IxOsalMutex eventQueueLock;
  34. IX_ETH_DB_PRIVATE IxOsalMutex portUpdateLock;
  35. IX_ETH_DB_PRIVATE BOOL ixEthDBLearningShutdown = false;
  36. IX_ETH_DB_PRIVATE BOOL ixEthDBEventProcessorRunning = false;
  37. /* imported data */
  38. extern HashTable dbHashtable;
  39. /**
  40. * @brief initializes the event processor
  41. *
  42. * Initializes the event processor queue and processing thread.
  43. * Called from ixEthDBInit() DB-subcomponent master init function.
  44. *
  45. * @warning do not call directly
  46. *
  47. * @retval IX_ETH_DB_SUCCESS initialization was successful
  48. * @retval IX_ETH_DB_FAIL initialization failed (OSAL or mutex init failure)
  49. *
  50. * @internal
  51. */
  52. IX_ETH_DB_PUBLIC
  53. IxEthDBStatus ixEthDBEventProcessorInit(void)
  54. {
  55. if (ixOsalMutexInit(&portUpdateLock) != IX_SUCCESS)
  56. {
  57. return IX_ETH_DB_FAIL;
  58. }
  59. if (ixOsalMutexInit(&eventQueueLock) != IX_SUCCESS)
  60. {
  61. return IX_ETH_DB_FAIL;
  62. }
  63. if (IX_FEATURE_CTRL_SWCONFIG_ENABLED ==
  64. ixFeatureCtrlSwConfigurationCheck (IX_FEATURECTRL_ETH_LEARNING))
  65. {
  66. /* start processor loop thread */
  67. if (ixEthDBStartLearningFunction() != IX_ETH_DB_SUCCESS)
  68. {
  69. return IX_ETH_DB_FAIL;
  70. }
  71. }
  72. return IX_ETH_DB_SUCCESS;
  73. }
  74. /**
  75. * @brief initializes the event queue and the event processor
  76. *
  77. * This function is called by the component initialization
  78. * function, ixEthDBInit().
  79. *
  80. * @warning do not call directly
  81. *
  82. * @return IX_ETH_DB_SUCCESS if the operation completed
  83. * successfully or IX_ETH_DB_FAIL otherwise
  84. *
  85. * @internal
  86. */
  87. IX_ETH_DB_PUBLIC
  88. IxEthDBStatus ixEthDBStartLearningFunction(void)
  89. {
  90. IxOsalThread eventProcessorThread;
  91. IxOsalThreadAttr threadAttr;
  92. threadAttr.name = "EthDB event thread";
  93. threadAttr.stackSize = 32 * 1024; /* 32kbytes */
  94. threadAttr.priority = 128;
  95. /* reset event queue */
  96. ixOsalMutexLock(&eventQueueLock, IX_OSAL_WAIT_FOREVER);
  97. RESET_QUEUE(&eventQueue);
  98. ixOsalMutexUnlock(&eventQueueLock);
  99. /* init event queue semaphore */
  100. if (ixOsalSemaphoreInit(&eventQueueSemaphore, 0) != IX_SUCCESS)
  101. {
  102. return IX_ETH_DB_FAIL;
  103. }
  104. ixEthDBLearningShutdown = false;
  105. /* create processor loop thread */
  106. if (ixOsalThreadCreate(&eventProcessorThread, &threadAttr, ixEthDBEventProcessorLoop, NULL) != IX_SUCCESS)
  107. {
  108. return IX_ETH_DB_FAIL;
  109. }
  110. /* start event processor */
  111. ixOsalThreadStart(&eventProcessorThread);
  112. return IX_ETH_DB_SUCCESS;
  113. }
  114. /**
  115. * @brief stops the event processor
  116. *
  117. * Stops the event processor and frees the event queue semaphore
  118. * Called by the component de-initialization function, ixEthDBUnload()
  119. *
  120. * @warning do not call directly
  121. *
  122. * @return IX_ETH_DB_SUCCESS if the operation completed
  123. * successfully or IX_ETH_DB_FAIL otherwise;
  124. *
  125. * @internal
  126. */
  127. IX_ETH_DB_PUBLIC
  128. IxEthDBStatus ixEthDBStopLearningFunction(void)
  129. {
  130. ixEthDBLearningShutdown = true;
  131. /* wake up event processing loop to actually process the shutdown event */
  132. ixOsalSemaphorePost(&eventQueueSemaphore);
  133. if (ixOsalSemaphoreDestroy(&eventQueueSemaphore) != IX_SUCCESS)
  134. {
  135. return IX_ETH_DB_FAIL;
  136. }
  137. return IX_ETH_DB_SUCCESS;
  138. }
  139. /**
  140. * @brief default NPE event processing callback
  141. *
  142. * @param npeID ID of the NPE that generated the event
  143. * @param msg NPE message (encapsulated event)
  144. *
  145. * Creates an event object on the Ethernet event processor queue
  146. * and signals the new event by incrementing the event queue semaphore.
  147. * Events are processed by @ref ixEthDBEventProcessorLoop() which runs
  148. * at user level.
  149. *
  150. * @see ixEthDBEventProcessorLoop()
  151. *
  152. * @warning do not call directly
  153. *
  154. * @internal
  155. */
  156. IX_ETH_DB_PUBLIC
  157. void ixEthDBNPEEventCallback(IxNpeMhNpeId npeID, IxNpeMhMessage msg)
  158. {
  159. PortEvent *local_event;
  160. IX_ETH_DB_IRQ_EVENTS_TRACE("DB: (Events) new event received by processor callback from port %d, id 0x%X\n", IX_ETH_DB_NPE_TO_PORT_ID(npeID), NPE_MSG_ID(msg), 0, 0, 0, 0);
  161. if (CAN_ENQUEUE(&eventQueue))
  162. {
  163. TEST_FIXTURE_LOCK_EVENT_QUEUE;
  164. local_event = QUEUE_HEAD(&eventQueue);
  165. /* create event structure on queue */
  166. local_event->eventType = NPE_MSG_ID(msg);
  167. local_event->portID = IX_ETH_DB_NPE_TO_PORT_ID(npeID);
  168. /* update queue */
  169. PUSH_UPDATE_QUEUE(&eventQueue);
  170. TEST_FIXTURE_UNLOCK_EVENT_QUEUE;
  171. IX_ETH_DB_IRQ_EVENTS_TRACE("DB: (Events) Waking up main processor loop...\n", 0, 0, 0, 0, 0, 0);
  172. /* increment event queue semaphore */
  173. ixOsalSemaphorePost(&eventQueueSemaphore);
  174. }
  175. else
  176. {
  177. IX_ETH_DB_IRQ_EVENTS_TRACE("DB: (Events) Warning: could not enqueue event (overflow)\n", 0, 0, 0, 0, 0, 0);
  178. }
  179. }
  180. /**
  181. * @brief Ethernet event processor loop
  182. *
  183. * Extracts at most EVENT_PROCESSING_LIMIT batches of events and
  184. * sends them for processing to @ref ixEthDBProcessEvent().
  185. * Triggers port updates which normally follow learning events.
  186. *
  187. * @warning do not call directly, executes in separate thread
  188. *
  189. * @internal
  190. */
  191. IX_ETH_DB_PUBLIC
  192. void ixEthDBEventProcessorLoop(void *unused1)
  193. {
  194. IxEthDBPortMap triggerPorts;
  195. IxEthDBPortId portIndex;
  196. ixEthDBEventProcessorRunning = true;
  197. IX_ETH_DB_EVENTS_TRACE("DB: (Events) Event processor loop was started\n");
  198. while (!ixEthDBLearningShutdown)
  199. {
  200. BOOL keepProcessing = true;
  201. UINT32 processedEvents = 0;
  202. IX_ETH_DB_EVENTS_VERBOSE_TRACE("DB: (Events) Waiting for new learning event...\n");
  203. ixOsalSemaphoreWait(&eventQueueSemaphore, IX_OSAL_WAIT_FOREVER);
  204. IX_ETH_DB_EVENTS_VERBOSE_TRACE("DB: (Events) Received new event\n");
  205. if (!ixEthDBLearningShutdown)
  206. {
  207. /* port update handling */
  208. SET_EMPTY_DEPENDENCY_MAP(triggerPorts);
  209. while (keepProcessing)
  210. {
  211. PortEvent local_event;
  212. UINT32 intLockKey;
  213. /* lock queue */
  214. ixOsalMutexLock(&eventQueueLock, IX_OSAL_WAIT_FOREVER);
  215. /* lock NPE interrupts */
  216. intLockKey = ixOsalIrqLock();
  217. /* extract event */
  218. local_event = *(QUEUE_TAIL(&eventQueue));
  219. SHIFT_UPDATE_QUEUE(&eventQueue);
  220. ixOsalIrqUnlock(intLockKey);
  221. ixOsalMutexUnlock(&eventQueueLock);
  222. IX_ETH_DB_EVENTS_TRACE("DB: (Events) Processing event with ID 0x%X\n", local_event.eventType);
  223. ixEthDBProcessEvent(&local_event, triggerPorts);
  224. processedEvents++;
  225. if (processedEvents > EVENT_PROCESSING_LIMIT /* maximum burst reached? */
  226. || ixOsalSemaphoreTryWait(&eventQueueSemaphore) != IX_SUCCESS) /* or empty queue? */
  227. {
  228. keepProcessing = false;
  229. }
  230. }
  231. ixEthDBUpdatePortLearningTrees(triggerPorts);
  232. }
  233. }
  234. /* turn off automatic updates */
  235. for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
  236. {
  237. ixEthDBPortInfo[portIndex].updateMethod.updateEnabled = false;
  238. }
  239. ixEthDBEventProcessorRunning = false;
  240. }
  241. /**
  242. * @brief event processor routine
  243. *
  244. * @param event event to be processed
  245. * @param triggerPorts port map accumulating ports to be updated
  246. *
  247. * Processes learning events by synchronizing the database with
  248. * newly learnt data. Called only by @ref ixEthDBEventProcessorLoop().
  249. *
  250. * @warning do not call directly
  251. *
  252. * @internal
  253. */
  254. IX_ETH_DB_PRIVATE
  255. void ixEthDBProcessEvent(PortEvent *local_event, IxEthDBPortMap triggerPorts)
  256. {
  257. MacDescriptor recordTemplate;
  258. switch (local_event->eventType)
  259. {
  260. case IX_ETH_DB_ADD_FILTERING_RECORD:
  261. /* add record */
  262. memset(&recordTemplate, 0, sizeof (recordTemplate));
  263. memcpy(recordTemplate.macAddress, local_event->macAddr.macAddress, sizeof (IxEthDBMacAddr));
  264. recordTemplate.type = IX_ETH_DB_FILTERING_RECORD;
  265. recordTemplate.portID = local_event->portID;
  266. recordTemplate.recordData.filteringData.staticEntry = local_event->staticEntry;
  267. ixEthDBAdd(&recordTemplate, triggerPorts);
  268. IX_ETH_DB_EVENTS_TRACE("DB: (Events) Added record on port %d\n", local_event->portID);
  269. break;
  270. case IX_ETH_DB_REMOVE_FILTERING_RECORD:
  271. /* remove record */
  272. memset(&recordTemplate, 0, sizeof (recordTemplate));
  273. memcpy(recordTemplate.macAddress, local_event->macAddr.macAddress, sizeof (IxEthDBMacAddr));
  274. recordTemplate.type = IX_ETH_DB_FILTERING_RECORD | IX_ETH_DB_FILTERING_VLAN_RECORD;
  275. ixEthDBRemove(&recordTemplate, triggerPorts);
  276. IX_ETH_DB_EVENTS_TRACE("DB: (Events) Removed record on port %d\n", local_event->portID);
  277. break;
  278. default:
  279. /* can't handle/not interested in this event type */
  280. ERROR_LOG("DB: (Events) Event processor received an unknown event type (0x%X)\n", local_event->eventType);
  281. return;
  282. }
  283. }
  284. /**
  285. * @brief asynchronously adds a filtering record
  286. * by posting an ADD_FILTERING_RECORD event to the event queue
  287. *
  288. * @param macAddr MAC address of the new record
  289. * @param portID port ID of the new record
  290. * @param staticEntry true if record is static, false if dynamic
  291. *
  292. * @return IX_ETH_DB_SUCCESS if the event creation was
  293. * successfull or IX_ETH_DB_BUSY if the event queue is full
  294. *
  295. * @internal
  296. */
  297. IX_ETH_DB_PUBLIC
  298. IxEthDBStatus ixEthDBTriggerAddPortUpdate(IxEthDBMacAddr *macAddr, IxEthDBPortId portID, BOOL staticEntry)
  299. {
  300. MacDescriptor reference;
  301. TEST_FIXTURE_INCREMENT_DB_CORE_ACCESS_COUNTER;
  302. /* fill search fields */
  303. memcpy(reference.macAddress, macAddr, sizeof (IxEthDBMacAddr));
  304. reference.portID = portID;
  305. /* set acceptable record types */
  306. reference.type = IX_ETH_DB_ALL_FILTERING_RECORDS;
  307. if (ixEthDBPeekHashEntry(&dbHashtable, IX_ETH_DB_MAC_PORT_KEY, &reference) == IX_ETH_DB_SUCCESS)
  308. {
  309. /* already have an identical record */
  310. return IX_ETH_DB_SUCCESS;
  311. }
  312. else
  313. {
  314. return ixEthDBTriggerPortUpdate(IX_ETH_DB_ADD_FILTERING_RECORD, macAddr, portID, staticEntry);
  315. }
  316. }
  317. /**
  318. * @brief asynchronously removes a filtering record
  319. * by posting a REMOVE_FILTERING_RECORD event to the event queue
  320. *
  321. * @param macAddr MAC address of the record to remove
  322. * @param portID port ID of the record to remove
  323. *
  324. * @return IX_ETH_DB_SUCCESS if the event creation was
  325. * successfull or IX_ETH_DB_BUSY if the event queue is full
  326. *
  327. * @internal
  328. */
  329. IX_ETH_DB_PUBLIC
  330. IxEthDBStatus ixEthDBTriggerRemovePortUpdate(IxEthDBMacAddr *macAddr, IxEthDBPortId portID)
  331. {
  332. if (ixEthDBPeek(macAddr, IX_ETH_DB_ALL_FILTERING_RECORDS) != IX_ETH_DB_NO_SUCH_ADDR)
  333. {
  334. return ixEthDBTriggerPortUpdate(IX_ETH_DB_REMOVE_FILTERING_RECORD, macAddr, portID, false);
  335. }
  336. else
  337. {
  338. return IX_ETH_DB_NO_SUCH_ADDR;
  339. }
  340. }
  341. /**
  342. * @brief adds an ADD or REMOVE event to the main event queue
  343. *
  344. * @param eventType event type - IX_ETH_DB_ADD_FILTERING_RECORD
  345. * to add and IX_ETH_DB_REMOVE_FILTERING_RECORD to remove a
  346. * record.
  347. *
  348. * @return IX_ETH_DB_SUCCESS if the event was successfully
  349. * sent or IX_ETH_DB_BUSY if the event queue is full
  350. *
  351. * @internal
  352. */
  353. IX_ETH_DB_PRIVATE
  354. IxEthDBStatus ixEthDBTriggerPortUpdate(UINT32 eventType, IxEthDBMacAddr *macAddr, IxEthDBPortId portID, BOOL staticEntry)
  355. {
  356. UINT32 intLockKey;
  357. /* lock interrupts to protect queue */
  358. intLockKey = ixOsalIrqLock();
  359. if (CAN_ENQUEUE(&eventQueue))
  360. {
  361. PortEvent *queueEvent = QUEUE_HEAD(&eventQueue);
  362. /* update fields on the queue */
  363. memcpy(queueEvent->macAddr.macAddress, macAddr->macAddress, sizeof (IxEthDBMacAddr));
  364. queueEvent->eventType = eventType;
  365. queueEvent->portID = portID;
  366. queueEvent->staticEntry = staticEntry;
  367. PUSH_UPDATE_QUEUE(&eventQueue);
  368. /* imcrement event queue semaphore */
  369. ixOsalSemaphorePost(&eventQueueSemaphore);
  370. /* unlock interrupts */
  371. ixOsalIrqUnlock(intLockKey);
  372. return IX_ETH_DB_SUCCESS;
  373. }
  374. else /* event queue full */
  375. {
  376. /* unlock interrupts */
  377. ixOsalIrqUnlock(intLockKey);
  378. return IX_ETH_DB_BUSY;
  379. }
  380. }
  381. /**
  382. * @brief Locks learning tree updates and port disable
  383. *
  384. *
  385. * This function locks portUpdateLock single mutex. It is primarily used
  386. * to avoid executing 'port disable' during ELT maintenance.
  387. *
  388. * @internal
  389. */
  390. IX_ETH_DB_PUBLIC
  391. void ixEthDBUpdateLock(void)
  392. {
  393. ixOsalMutexLock(&portUpdateLock, IX_OSAL_WAIT_FOREVER);
  394. }
  395. /**
  396. * @brief Unlocks learning tree updates and port disable
  397. *
  398. *
  399. * This function unlocks a portUpdateLock mutex. It is primarily used
  400. * to avoid executing 'port disable' during ELT maintenance.
  401. *
  402. * @internal
  403. */
  404. IX_ETH_DB_PUBLIC
  405. void ixEthDBUpdateUnlock(void)
  406. {
  407. ixOsalMutexUnlock(&portUpdateLock);
  408. }