2 * @file IxEthDBAPISupport.c
4 * @brief Public API 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 --
47 #include <IxFeatureCtrl.h>
49 #include "IxEthDB_p.h"
50 #include "IxEthDBMessages_p.h"
51 #include "IxEthDB_p.h"
52 #include "IxEthDBLog_p.h"
56 int dbAccessCounter = 0;
57 int overflowEvent = 0;
62 * External declaration
64 extern HashTable dbHashtable;
67 * Internal declaration
70 PortInfo ixEthDBPortInfo[IX_ETH_DB_NUMBER_OF_PORTS];
76 IxEthDBPriorityTable priorityTable;
77 IxEthDBVlanSet vlanMembership;
78 IxEthDBVlanSet transmitTaggingInfo;
79 IxEthDBFrameFilter frameFilter;
80 IxEthDBTaggingAction taggingAction;
81 IxEthDBFirewallMode firewallMode;
83 BOOL srcAddressFilterEnabled;
84 UINT32 maxRxFrameSize;
85 UINT32 maxTxFrameSize;
86 } ixEthDBPortState[IX_ETH_DB_NUMBER_OF_PORTS];
88 #define IX_ETH_DB_DEFAULT_FRAME_SIZE (1518)
91 * @brief initializes a port
93 * @param portID ID of the port to be initialized
95 * Note that redundant initializations are silently
96 * dealt with and do not constitute an error
98 * This function is fully documented in the main
99 * header file, IxEthDB.h
102 void ixEthDBPortInit(IxEthDBPortId portID)
106 if (portID >= IX_ETH_DB_NUMBER_OF_PORTS)
111 portInfo = &ixEthDBPortInfo[portID];
113 if (ixEthDBSingleEthNpeCheck(portID) != IX_ETH_DB_SUCCESS)
115 WARNING_LOG("EthDB: Unavailable Eth %d: Cannot initialize EthDB Port.\n", (UINT32) portID);
120 if (portInfo->initialized)
126 /* initialize core fields */
127 portInfo->portID = portID;
128 SET_DEPENDENCY_MAP(portInfo->dependencyPortMap, portID);
131 portInfo->agingEnabled = FALSE;
132 portInfo->enabled = FALSE;
133 portInfo->macAddressUploaded = FALSE;
134 portInfo->maxRxFrameSize = IX_ETHDB_DEFAULT_FRAME_SIZE;
135 portInfo->maxTxFrameSize = IX_ETHDB_DEFAULT_FRAME_SIZE;
137 /* default update control values */
138 portInfo->updateMethod.searchTree = NULL;
139 portInfo->updateMethod.searchTreePendingWrite = FALSE;
140 portInfo->updateMethod.treeInitialized = FALSE;
141 portInfo->updateMethod.updateEnabled = FALSE;
142 portInfo->updateMethod.userControlled = FALSE;
144 /* default WiFi parameters */
145 memset(portInfo->bbsid, 0, sizeof (portInfo->bbsid));
146 portInfo->frameControlDurationID = 0;
148 /* Ethernet NPE-specific initializations */
149 if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
152 portInfo->updateMethod.updateHandler = ixEthDBNPEUpdateHandler;
155 /* initialize state save */
156 ixEthDBPortState[portID].saved = FALSE;
158 portInfo->initialized = TRUE;
162 * @brief enables a port
164 * @param portID ID of the port to enable
166 * This function is fully documented in the main
167 * header file, IxEthDB.h
169 * @return IX_ETH_DB_SUCCESS if enabling was
170 * accomplished, or a meaningful error message otherwise
173 IxEthDBStatus ixEthDBPortEnable(IxEthDBPortId portID)
175 IxEthDBPortMap triggerPorts;
178 IX_ETH_DB_CHECK_PORT_EXISTS(portID);
180 IX_ETH_DB_CHECK_SINGLE_NPE(portID);
182 portInfo = &ixEthDBPortInfo[portID];
184 if (portInfo->enabled)
187 return IX_ETH_DB_SUCCESS;
190 SET_DEPENDENCY_MAP(triggerPorts, portID);
192 /* mark as enabled */
193 portInfo->enabled = TRUE;
195 /* Operation stops here when Ethernet Learning is not enabled */
196 if(IX_FEATURE_CTRL_SWCONFIG_DISABLED ==
197 ixFeatureCtrlSwConfigurationCheck(IX_FEATURECTRL_ETH_LEARNING))
199 return IX_ETH_DB_SUCCESS;
202 if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE && !portInfo->macAddressUploaded)
204 IX_ETH_DB_SUPPORT_TRACE("DB: (Support) MAC address not set on port %d, enable failed\n", portID);
206 /* must use UnicastAddressSet() before enabling an NPE port */
207 return IX_ETH_DB_MAC_UNINITIALIZED;
210 if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
212 IX_ETH_DB_SUPPORT_TRACE("DB: (Support) Attempting to enable the NPE callback for port %d...\n", portID);
214 if (!portInfo->updateMethod.userControlled
215 && ((portInfo->featureCapability & IX_ETH_DB_FILTERING) != 0))
217 portInfo->updateMethod.updateEnabled = TRUE;
220 /* if this is first time initialization then we already have
221 write access to the tree and can AccessRelease directly */
222 if (!portInfo->updateMethod.treeInitialized)
224 IX_ETH_DB_SUPPORT_TRACE("DB: (Support) Initializing tree for port %d\n", portID);
226 /* create an initial tree and release access into it */
227 ixEthDBUpdatePortLearningTrees(triggerPorts);
229 /* mark tree as being initialized */
230 portInfo->updateMethod.treeInitialized = TRUE;
234 if (ixEthDBPortState[portID].saved)
236 /* previous configuration data stored, restore state */
237 if ((portInfo->featureCapability & IX_ETH_DB_FIREWALL) != 0)
239 ixEthDBFirewallModeSet(portID, ixEthDBPortState[portID].firewallMode);
240 ixEthDBFirewallInvalidAddressFilterEnable(portID, ixEthDBPortState[portID].srcAddressFilterEnabled);
243 #if 0 /* test-only */
244 if ((portInfo->featureCapability & IX_ETH_DB_VLAN_QOS) != 0)
246 ixEthDBAcceptableFrameTypeSet(portID, ixEthDBPortState[portID].frameFilter);
247 ixEthDBIngressVlanTaggingEnabledSet(portID, ixEthDBPortState[portID].taggingAction);
249 ixEthDBEgressVlanTaggingEnabledSet(portID, ixEthDBPortState[portID].transmitTaggingInfo);
250 ixEthDBPortVlanMembershipSet(portID, ixEthDBPortState[portID].vlanMembership);
252 ixEthDBPriorityMappingTableSet(portID, ixEthDBPortState[portID].priorityTable);
256 if ((portInfo->featureCapability & IX_ETH_DB_SPANNING_TREE_PROTOCOL) != 0)
258 ixEthDBSpanningTreeBlockingStateSet(portID, ixEthDBPortState[portID].stpBlocked);
261 ixEthDBFilteringPortMaximumRxFrameSizeSet(portID, ixEthDBPortState[portID].maxRxFrameSize);
262 ixEthDBFilteringPortMaximumTxFrameSizeSet(portID, ixEthDBPortState[portID].maxTxFrameSize);
264 /* discard previous save */
265 ixEthDBPortState[portID].saved = FALSE;
268 IX_ETH_DB_SUPPORT_TRACE("DB: (Support) Enabling succeeded for port %d\n", portID);
270 return IX_ETH_DB_SUCCESS;
274 * @brief disables a port
276 * @param portID ID of the port to disable
278 * This function is fully documented in the
279 * main header file, IxEthDB.h
281 * @return IX_ETH_DB_SUCCESS if disabling was
282 * successful or an appropriate error message
286 IxEthDBStatus ixEthDBPortDisable(IxEthDBPortId portID)
288 HashIterator iterator;
289 IxEthDBPortMap triggerPorts; /* ports who will have deleted records and therefore will need updating */
292 IxEthDBFeature learningEnabled;
293 #if 0 /* test-only */
294 IxEthDBPriorityTable classZeroTable;
297 IX_ETH_DB_CHECK_PORT_EXISTS(portID);
299 IX_ETH_DB_CHECK_SINGLE_NPE(portID);
301 portInfo = &ixEthDBPortInfo[portID];
303 if (!portInfo->enabled)
306 return IX_ETH_DB_SUCCESS;
309 if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
311 /* save filtering state */
312 ixEthDBPortState[portID].firewallMode = portInfo->firewallMode;
313 ixEthDBPortState[portID].frameFilter = portInfo->frameFilter;
314 ixEthDBPortState[portID].taggingAction = portInfo->taggingAction;
315 ixEthDBPortState[portID].stpBlocked = portInfo->stpBlocked;
316 ixEthDBPortState[portID].srcAddressFilterEnabled = portInfo->srcAddressFilterEnabled;
317 ixEthDBPortState[portID].maxRxFrameSize = portInfo->maxRxFrameSize;
318 ixEthDBPortState[portID].maxTxFrameSize = portInfo->maxTxFrameSize;
320 memcpy(ixEthDBPortState[portID].vlanMembership, portInfo->vlanMembership, sizeof (IxEthDBVlanSet));
321 memcpy(ixEthDBPortState[portID].transmitTaggingInfo, portInfo->transmitTaggingInfo, sizeof (IxEthDBVlanSet));
322 memcpy(ixEthDBPortState[portID].priorityTable, portInfo->priorityTable, sizeof (IxEthDBPriorityTable));
324 ixEthDBPortState[portID].saved = TRUE;
326 /* now turn off all EthDB filtering features on the port */
328 #if 0 /* test-only */
330 if ((portInfo->featureCapability & IX_ETH_DB_VLAN_QOS) != 0)
332 ixEthDBPortVlanMembershipRangeAdd((IxEthDBPortId) portID, 0, IX_ETH_DB_802_1Q_MAX_VLAN_ID);
333 ixEthDBEgressVlanRangeTaggingEnabledSet((IxEthDBPortId) portID, 0, IX_ETH_DB_802_1Q_MAX_VLAN_ID, FALSE);
334 ixEthDBAcceptableFrameTypeSet((IxEthDBPortId) portID, IX_ETH_DB_ACCEPT_ALL_FRAMES);
335 ixEthDBIngressVlanTaggingEnabledSet((IxEthDBPortId) portID, IX_ETH_DB_PASS_THROUGH);
337 memset(classZeroTable, 0, sizeof (classZeroTable));
338 ixEthDBPriorityMappingTableSet((IxEthDBPortId) portID, classZeroTable);
343 if ((portInfo->featureCapability & IX_ETH_DB_SPANNING_TREE_PROTOCOL) != 0)
345 ixEthDBSpanningTreeBlockingStateSet((IxEthDBPortId) portID, FALSE);
349 if ((portInfo->featureCapability & IX_ETH_DB_FIREWALL) != 0)
351 ixEthDBFirewallModeSet((IxEthDBPortId) portID, IX_ETH_DB_FIREWALL_BLACK_LIST);
352 ixEthDBFirewallTableDownload((IxEthDBPortId) portID);
353 ixEthDBFirewallInvalidAddressFilterEnable((IxEthDBPortId) portID, FALSE);
356 /* Frame size filter */
357 ixEthDBFilteringPortMaximumFrameSizeSet((IxEthDBPortId) portID, IX_ETH_DB_DEFAULT_FRAME_SIZE);
360 if ((portInfo->featureCapability & IX_ETH_DB_WIFI_HEADER_CONVERSION) != 0)
362 ixEthDBWiFiConversionTableDownload((IxEthDBPortId) portID);
365 /* save and disable the learning feature bit */
366 learningEnabled = portInfo->featureStatus & IX_ETH_DB_LEARNING;
367 portInfo->featureStatus &= ~IX_ETH_DB_LEARNING;
371 /* save the learning feature bit */
372 learningEnabled = portInfo->featureStatus & IX_ETH_DB_LEARNING;
375 SET_EMPTY_DEPENDENCY_MAP(triggerPorts);
379 /* wipe out current entries for this port */
380 BUSY_RETRY(ixEthDBInitHashIterator(&dbHashtable, &iterator));
382 while (IS_ITERATOR_VALID(&iterator))
384 MacDescriptor *descriptor = (MacDescriptor *) iterator.node->data;
386 /* check if the port match. If so, remove the entry */
387 if (descriptor->portID == portID
388 && (descriptor->type == IX_ETH_DB_FILTERING_RECORD || descriptor->type == IX_ETH_DB_FILTERING_VLAN_RECORD)
389 && !descriptor->recordData.filteringData.staticEntry)
392 BUSY_RETRY(ixEthDBRemoveEntryAtHashIterator(&dbHashtable, &iterator));
394 /* add port to the set of update trigger ports */
395 JOIN_PORT_TO_MAP(triggerPorts, portID);
399 /* move to the next record */
400 BUSY_RETRY(ixEthDBIncrementHashIterator(&dbHashtable, &iterator));
404 if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
406 if (portInfo->updateMethod.searchTree != NULL)
408 ixEthDBFreeMacTreeNode(portInfo->updateMethod.searchTree);
409 portInfo->updateMethod.searchTree = NULL;
412 ixEthDBNPEUpdateHandler(portID, IX_ETH_DB_FILTERING_RECORD);
415 /* mark as disabled */
416 portInfo->enabled = FALSE;
418 /* disable updates unless the user has specifically altered the default behavior */
419 if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
421 if (!portInfo->updateMethod.userControlled)
423 portInfo->updateMethod.updateEnabled = FALSE;
426 /* make sure we re-initialize the NPE learning tree when the port is re-enabled */
427 portInfo->updateMethod.treeInitialized = FALSE;
430 ixEthDBUpdateUnlock();
432 /* restore learning feature bit */
433 portInfo->featureStatus |= learningEnabled;
435 /* if we've removed any records or lost any events make sure to force an update */
436 IS_EMPTY_DEPENDENCY_MAP(result, triggerPorts);
440 ixEthDBUpdatePortLearningTrees(triggerPorts);
443 return IX_ETH_DB_SUCCESS;
447 * @brief sends the updated maximum Tx/Rx frame lengths to the NPE
449 * @param portID ID of the port to update
451 * @return IX_ETH_DB_SUCCESS if the update completed
452 * successfully or an appropriate error message otherwise
457 IxEthDBStatus ixEthDBPortFrameLengthsUpdate(IxEthDBPortId portID)
459 IxNpeMhMessage message;
460 PortInfo *portInfo = &ixEthDBPortInfo[portID];
463 FILL_SETMAXFRAMELENGTHS_MSG(message, portID, portInfo->maxRxFrameSize, portInfo->maxTxFrameSize);
465 IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portID), message, result);
471 * @brief sets the port maximum Rx frame size
473 * @param portID ID of the port to set the frame size on
474 * @param maximumRxFrameSize maximum Rx frame size
476 * This function updates the internal data structures and
477 * calls ixEthDBPortFrameLengthsUpdate() for NPE update.
479 * This function is fully documented in the main header
482 * @return IX_ETH_DB_SUCCESS if the operation was
483 * successfull or an appropriate error message otherwise
486 IxEthDBStatus ixEthDBFilteringPortMaximumRxFrameSizeSet(IxEthDBPortId portID, UINT32 maximumRxFrameSize)
488 IX_ETH_DB_CHECK_PORT_EXISTS(portID);
490 IX_ETH_DB_CHECK_SINGLE_NPE(portID);
492 if (!ixEthDBPortInfo[portID].initialized)
494 return IX_ETH_DB_PORT_UNINITIALIZED;
497 if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
499 if ((maximumRxFrameSize < IX_ETHDB_MIN_NPE_FRAME_SIZE) ||
500 (maximumRxFrameSize > IX_ETHDB_MAX_NPE_FRAME_SIZE))
502 return IX_ETH_DB_INVALID_ARG;
507 return IX_ETH_DB_NO_PERMISSION;
510 /* update internal structure */
511 ixEthDBPortInfo[portID].maxRxFrameSize = maximumRxFrameSize;
513 /* update the maximum frame size in the NPE */
514 return ixEthDBPortFrameLengthsUpdate(portID);
518 * @brief sets the port maximum Tx frame size
520 * @param portID ID of the port to set the frame size on
521 * @param maximumTxFrameSize maximum Tx frame size
523 * This function updates the internal data structures and
524 * calls ixEthDBPortFrameLengthsUpdate() for NPE update.
526 * This function is fully documented in the main header
529 * @return IX_ETH_DB_SUCCESS if the operation was
530 * successfull or an appropriate error message otherwise
533 IxEthDBStatus ixEthDBFilteringPortMaximumTxFrameSizeSet(IxEthDBPortId portID, UINT32 maximumTxFrameSize)
535 IX_ETH_DB_CHECK_PORT_EXISTS(portID);
537 IX_ETH_DB_CHECK_SINGLE_NPE(portID);
539 if (!ixEthDBPortInfo[portID].initialized)
541 return IX_ETH_DB_PORT_UNINITIALIZED;
544 if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
546 if ((maximumTxFrameSize < IX_ETHDB_MIN_NPE_FRAME_SIZE) ||
547 (maximumTxFrameSize > IX_ETHDB_MAX_NPE_FRAME_SIZE))
549 return IX_ETH_DB_INVALID_ARG;
554 return IX_ETH_DB_NO_PERMISSION;
557 /* update internal structure */
558 ixEthDBPortInfo[portID].maxTxFrameSize = maximumTxFrameSize;
560 /* update the maximum frame size in the NPE */
561 return ixEthDBPortFrameLengthsUpdate(portID);
565 * @brief sets the port maximum Tx and Rx frame sizes
567 * @param portID ID of the port to set the frame size on
568 * @param maximumFrameSize maximum Tx and Rx frame sizes
570 * This function updates the internal data structures and
571 * calls ixEthDBPortFrameLengthsUpdate() for NPE update.
573 * Note that both the maximum Tx and Rx frame size are set
574 * to the same value. This function is kept for compatibility
577 * This function is fully documented in the main header
580 * @return IX_ETH_DB_SUCCESS if the operation was
581 * successfull or an appropriate error message otherwise
584 IxEthDBStatus ixEthDBFilteringPortMaximumFrameSizeSet(IxEthDBPortId portID, UINT32 maximumFrameSize)
586 IX_ETH_DB_CHECK_PORT_EXISTS(portID);
588 IX_ETH_DB_CHECK_SINGLE_NPE(portID);
590 if (!ixEthDBPortInfo[portID].initialized)
592 return IX_ETH_DB_PORT_UNINITIALIZED;
595 if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
597 if ((maximumFrameSize < IX_ETHDB_MIN_NPE_FRAME_SIZE) ||
598 (maximumFrameSize > IX_ETHDB_MAX_NPE_FRAME_SIZE))
600 return IX_ETH_DB_INVALID_ARG;
605 return IX_ETH_DB_NO_PERMISSION;
608 /* update internal structure */
609 ixEthDBPortInfo[portID].maxRxFrameSize = maximumFrameSize;
610 ixEthDBPortInfo[portID].maxTxFrameSize = maximumFrameSize;
612 /* update the maximum frame size in the NPE */
613 return ixEthDBPortFrameLengthsUpdate(portID);
617 * @brief sets the MAC address of an NPE port
619 * @param portID port ID to set the MAC address on
620 * @param macAddr pointer to the 6-byte MAC address
622 * This function is called by the EthAcc
623 * ixEthAccUnicastMacAddressSet() and should not be
624 * manually invoked unless required by special circumstances.
626 * @return IX_ETH_DB_SUCCESS if the operation succeeded
627 * or an appropriate error message otherwise
630 IxEthDBStatus ixEthDBPortAddressSet(IxEthDBPortId portID, IxEthDBMacAddr *macAddr)
632 IxNpeMhMessage message;
633 IxOsalMutex *ackPortAddressLock;
636 /* use this macro instead CHECK_PORT
637 as the port doesn't need to be enabled */
638 IX_ETH_DB_CHECK_PORT_EXISTS(portID);
640 IX_ETH_DB_CHECK_REFERENCE(macAddr);
642 if (!ixEthDBPortInfo[portID].initialized)
644 return IX_ETH_DB_PORT_UNINITIALIZED;
647 ackPortAddressLock = &ixEthDBPortInfo[portID].npeAckLock;
649 /* Operation stops here when Ethernet Learning is not enabled */
650 if(IX_FEATURE_CTRL_SWCONFIG_DISABLED ==
651 ixFeatureCtrlSwConfigurationCheck(IX_FEATURECTRL_ETH_LEARNING))
653 return IX_ETH_DB_SUCCESS;
656 IX_ETH_DB_CHECK_SINGLE_NPE(portID);
658 /* exit if the port is not an Ethernet NPE */
659 if (ixEthDBPortDefinitions[portID].type != IX_ETH_NPE)
661 return IX_ETH_DB_INVALID_PORT;
664 /* populate message */
665 FILL_SETPORTADDRESS_MSG(message, portID, macAddr->macAddress);
667 IX_ETH_DB_SUPPORT_TRACE("DB: (Support) Sending SetPortAddress on port %d...\n", portID);
669 /* send a SetPortAddress message */
670 IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portID), message, result);
672 if (result == IX_SUCCESS)
674 ixEthDBPortInfo[portID].macAddressUploaded = TRUE;