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