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 * SPDX-License-Identifier: BSD-3-Clause
18 * -- End of Copyright Notice --
23 #include <IxFeatureCtrl.h>
25 #include "IxEthDB_p.h"
26 #include "IxEthDBMessages_p.h"
27 #include "IxEthDB_p.h"
28 #include "IxEthDBLog_p.h"
32 int dbAccessCounter = 0;
33 int overflowEvent = 0;
38 * External declaration
40 extern HashTable dbHashtable;
43 * Internal declaration
46 PortInfo ixEthDBPortInfo[IX_ETH_DB_NUMBER_OF_PORTS];
52 IxEthDBPriorityTable priorityTable;
53 IxEthDBVlanSet vlanMembership;
54 IxEthDBVlanSet transmitTaggingInfo;
55 IxEthDBFrameFilter frameFilter;
56 IxEthDBTaggingAction taggingAction;
57 IxEthDBFirewallMode firewallMode;
59 BOOL srcAddressFilterEnabled;
60 UINT32 maxRxFrameSize;
61 UINT32 maxTxFrameSize;
62 } ixEthDBPortState[IX_ETH_DB_NUMBER_OF_PORTS];
64 #define IX_ETH_DB_DEFAULT_FRAME_SIZE (1518)
67 * @brief initializes a port
69 * @param portID ID of the port to be initialized
71 * Note that redundant initializations are silently
72 * dealt with and do not constitute an error
74 * This function is fully documented in the main
75 * header file, IxEthDB.h
78 void ixEthDBPortInit(IxEthDBPortId portID)
82 if (portID >= IX_ETH_DB_NUMBER_OF_PORTS)
87 portInfo = &ixEthDBPortInfo[portID];
89 if (ixEthDBSingleEthNpeCheck(portID) != IX_ETH_DB_SUCCESS)
91 WARNING_LOG("EthDB: Unavailable Eth %d: Cannot initialize EthDB Port.\n", (UINT32) portID);
96 if (portInfo->initialized)
102 /* initialize core fields */
103 portInfo->portID = portID;
104 SET_DEPENDENCY_MAP(portInfo->dependencyPortMap, portID);
107 portInfo->agingEnabled = false;
108 portInfo->enabled = false;
109 portInfo->macAddressUploaded = false;
110 portInfo->maxRxFrameSize = IX_ETHDB_DEFAULT_FRAME_SIZE;
111 portInfo->maxTxFrameSize = IX_ETHDB_DEFAULT_FRAME_SIZE;
113 /* default update control values */
114 portInfo->updateMethod.searchTree = NULL;
115 portInfo->updateMethod.searchTreePendingWrite = false;
116 portInfo->updateMethod.treeInitialized = false;
117 portInfo->updateMethod.updateEnabled = false;
118 portInfo->updateMethod.userControlled = false;
120 /* default WiFi parameters */
121 memset(portInfo->bbsid, 0, sizeof (portInfo->bbsid));
122 portInfo->frameControlDurationID = 0;
124 /* Ethernet NPE-specific initializations */
125 if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
128 portInfo->updateMethod.updateHandler = ixEthDBNPEUpdateHandler;
131 /* initialize state save */
132 ixEthDBPortState[portID].saved = false;
134 portInfo->initialized = true;
138 * @brief enables a port
140 * @param portID ID of the port to enable
142 * This function is fully documented in the main
143 * header file, IxEthDB.h
145 * @return IX_ETH_DB_SUCCESS if enabling was
146 * accomplished, or a meaningful error message otherwise
149 IxEthDBStatus ixEthDBPortEnable(IxEthDBPortId portID)
151 IxEthDBPortMap triggerPorts;
154 IX_ETH_DB_CHECK_PORT_EXISTS(portID);
156 IX_ETH_DB_CHECK_SINGLE_NPE(portID);
158 portInfo = &ixEthDBPortInfo[portID];
160 if (portInfo->enabled)
163 return IX_ETH_DB_SUCCESS;
166 SET_DEPENDENCY_MAP(triggerPorts, portID);
168 /* mark as enabled */
169 portInfo->enabled = true;
171 /* Operation stops here when Ethernet Learning is not enabled */
172 if(IX_FEATURE_CTRL_SWCONFIG_DISABLED ==
173 ixFeatureCtrlSwConfigurationCheck(IX_FEATURECTRL_ETH_LEARNING))
175 return IX_ETH_DB_SUCCESS;
178 if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE && !portInfo->macAddressUploaded)
180 IX_ETH_DB_SUPPORT_TRACE("DB: (Support) MAC address not set on port %d, enable failed\n", portID);
182 /* must use UnicastAddressSet() before enabling an NPE port */
183 return IX_ETH_DB_MAC_UNINITIALIZED;
186 if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
188 IX_ETH_DB_SUPPORT_TRACE("DB: (Support) Attempting to enable the NPE callback for port %d...\n", portID);
190 if (!portInfo->updateMethod.userControlled
191 && ((portInfo->featureCapability & IX_ETH_DB_FILTERING) != 0))
193 portInfo->updateMethod.updateEnabled = true;
196 /* if this is first time initialization then we already have
197 write access to the tree and can AccessRelease directly */
198 if (!portInfo->updateMethod.treeInitialized)
200 IX_ETH_DB_SUPPORT_TRACE("DB: (Support) Initializing tree for port %d\n", portID);
202 /* create an initial tree and release access into it */
203 ixEthDBUpdatePortLearningTrees(triggerPorts);
205 /* mark tree as being initialized */
206 portInfo->updateMethod.treeInitialized = true;
210 if (ixEthDBPortState[portID].saved)
212 /* previous configuration data stored, restore state */
213 if ((portInfo->featureCapability & IX_ETH_DB_FIREWALL) != 0)
215 ixEthDBFirewallModeSet(portID, ixEthDBPortState[portID].firewallMode);
216 ixEthDBFirewallInvalidAddressFilterEnable(portID, ixEthDBPortState[portID].srcAddressFilterEnabled);
219 #if 0 /* test-only */
220 if ((portInfo->featureCapability & IX_ETH_DB_VLAN_QOS) != 0)
222 ixEthDBAcceptableFrameTypeSet(portID, ixEthDBPortState[portID].frameFilter);
223 ixEthDBIngressVlanTaggingEnabledSet(portID, ixEthDBPortState[portID].taggingAction);
225 ixEthDBEgressVlanTaggingEnabledSet(portID, ixEthDBPortState[portID].transmitTaggingInfo);
226 ixEthDBPortVlanMembershipSet(portID, ixEthDBPortState[portID].vlanMembership);
228 ixEthDBPriorityMappingTableSet(portID, ixEthDBPortState[portID].priorityTable);
232 if ((portInfo->featureCapability & IX_ETH_DB_SPANNING_TREE_PROTOCOL) != 0)
234 ixEthDBSpanningTreeBlockingStateSet(portID, ixEthDBPortState[portID].stpBlocked);
237 ixEthDBFilteringPortMaximumRxFrameSizeSet(portID, ixEthDBPortState[portID].maxRxFrameSize);
238 ixEthDBFilteringPortMaximumTxFrameSizeSet(portID, ixEthDBPortState[portID].maxTxFrameSize);
240 /* discard previous save */
241 ixEthDBPortState[portID].saved = false;
244 IX_ETH_DB_SUPPORT_TRACE("DB: (Support) Enabling succeeded for port %d\n", portID);
246 return IX_ETH_DB_SUCCESS;
250 * @brief disables a port
252 * @param portID ID of the port to disable
254 * This function is fully documented in the
255 * main header file, IxEthDB.h
257 * @return IX_ETH_DB_SUCCESS if disabling was
258 * successful or an appropriate error message
262 IxEthDBStatus ixEthDBPortDisable(IxEthDBPortId portID)
264 HashIterator iterator;
265 IxEthDBPortMap triggerPorts; /* ports who will have deleted records and therefore will need updating */
268 IxEthDBFeature learningEnabled;
269 #if 0 /* test-only */
270 IxEthDBPriorityTable classZeroTable;
273 IX_ETH_DB_CHECK_PORT_EXISTS(portID);
275 IX_ETH_DB_CHECK_SINGLE_NPE(portID);
277 portInfo = &ixEthDBPortInfo[portID];
279 if (!portInfo->enabled)
282 return IX_ETH_DB_SUCCESS;
285 if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
287 /* save filtering state */
288 ixEthDBPortState[portID].firewallMode = portInfo->firewallMode;
289 ixEthDBPortState[portID].frameFilter = portInfo->frameFilter;
290 ixEthDBPortState[portID].taggingAction = portInfo->taggingAction;
291 ixEthDBPortState[portID].stpBlocked = portInfo->stpBlocked;
292 ixEthDBPortState[portID].srcAddressFilterEnabled = portInfo->srcAddressFilterEnabled;
293 ixEthDBPortState[portID].maxRxFrameSize = portInfo->maxRxFrameSize;
294 ixEthDBPortState[portID].maxTxFrameSize = portInfo->maxTxFrameSize;
296 memcpy(ixEthDBPortState[portID].vlanMembership, portInfo->vlanMembership, sizeof (IxEthDBVlanSet));
297 memcpy(ixEthDBPortState[portID].transmitTaggingInfo, portInfo->transmitTaggingInfo, sizeof (IxEthDBVlanSet));
298 memcpy(ixEthDBPortState[portID].priorityTable, portInfo->priorityTable, sizeof (IxEthDBPriorityTable));
300 ixEthDBPortState[portID].saved = true;
302 /* now turn off all EthDB filtering features on the port */
304 #if 0 /* test-only */
306 if ((portInfo->featureCapability & IX_ETH_DB_VLAN_QOS) != 0)
308 ixEthDBPortVlanMembershipRangeAdd((IxEthDBPortId) portID, 0, IX_ETH_DB_802_1Q_MAX_VLAN_ID);
309 ixEthDBEgressVlanRangeTaggingEnabledSet((IxEthDBPortId) portID, 0, IX_ETH_DB_802_1Q_MAX_VLAN_ID, false);
310 ixEthDBAcceptableFrameTypeSet((IxEthDBPortId) portID, IX_ETH_DB_ACCEPT_ALL_FRAMES);
311 ixEthDBIngressVlanTaggingEnabledSet((IxEthDBPortId) portID, IX_ETH_DB_PASS_THROUGH);
313 memset(classZeroTable, 0, sizeof (classZeroTable));
314 ixEthDBPriorityMappingTableSet((IxEthDBPortId) portID, classZeroTable);
319 if ((portInfo->featureCapability & IX_ETH_DB_SPANNING_TREE_PROTOCOL) != 0)
321 ixEthDBSpanningTreeBlockingStateSet((IxEthDBPortId) portID, false);
325 if ((portInfo->featureCapability & IX_ETH_DB_FIREWALL) != 0)
327 ixEthDBFirewallModeSet((IxEthDBPortId) portID, IX_ETH_DB_FIREWALL_BLACK_LIST);
328 ixEthDBFirewallTableDownload((IxEthDBPortId) portID);
329 ixEthDBFirewallInvalidAddressFilterEnable((IxEthDBPortId) portID, false);
332 /* Frame size filter */
333 ixEthDBFilteringPortMaximumFrameSizeSet((IxEthDBPortId) portID, IX_ETH_DB_DEFAULT_FRAME_SIZE);
336 if ((portInfo->featureCapability & IX_ETH_DB_WIFI_HEADER_CONVERSION) != 0)
338 ixEthDBWiFiConversionTableDownload((IxEthDBPortId) portID);
341 /* save and disable the learning feature bit */
342 learningEnabled = portInfo->featureStatus & IX_ETH_DB_LEARNING;
343 portInfo->featureStatus &= ~IX_ETH_DB_LEARNING;
347 /* save the learning feature bit */
348 learningEnabled = portInfo->featureStatus & IX_ETH_DB_LEARNING;
351 SET_EMPTY_DEPENDENCY_MAP(triggerPorts);
355 /* wipe out current entries for this port */
356 BUSY_RETRY(ixEthDBInitHashIterator(&dbHashtable, &iterator));
358 while (IS_ITERATOR_VALID(&iterator))
360 MacDescriptor *descriptor = (MacDescriptor *) iterator.node->data;
362 /* check if the port match. If so, remove the entry */
363 if (descriptor->portID == portID
364 && (descriptor->type == IX_ETH_DB_FILTERING_RECORD || descriptor->type == IX_ETH_DB_FILTERING_VLAN_RECORD)
365 && !descriptor->recordData.filteringData.staticEntry)
368 BUSY_RETRY(ixEthDBRemoveEntryAtHashIterator(&dbHashtable, &iterator));
370 /* add port to the set of update trigger ports */
371 JOIN_PORT_TO_MAP(triggerPorts, portID);
375 /* move to the next record */
376 BUSY_RETRY(ixEthDBIncrementHashIterator(&dbHashtable, &iterator));
380 if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
382 if (portInfo->updateMethod.searchTree != NULL)
384 ixEthDBFreeMacTreeNode(portInfo->updateMethod.searchTree);
385 portInfo->updateMethod.searchTree = NULL;
388 ixEthDBNPEUpdateHandler(portID, IX_ETH_DB_FILTERING_RECORD);
391 /* mark as disabled */
392 portInfo->enabled = false;
394 /* disable updates unless the user has specifically altered the default behavior */
395 if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
397 if (!portInfo->updateMethod.userControlled)
399 portInfo->updateMethod.updateEnabled = false;
402 /* make sure we re-initialize the NPE learning tree when the port is re-enabled */
403 portInfo->updateMethod.treeInitialized = false;
406 ixEthDBUpdateUnlock();
408 /* restore learning feature bit */
409 portInfo->featureStatus |= learningEnabled;
411 /* if we've removed any records or lost any events make sure to force an update */
412 IS_EMPTY_DEPENDENCY_MAP(result, triggerPorts);
416 ixEthDBUpdatePortLearningTrees(triggerPorts);
419 return IX_ETH_DB_SUCCESS;
423 * @brief sends the updated maximum Tx/Rx frame lengths to the NPE
425 * @param portID ID of the port to update
427 * @return IX_ETH_DB_SUCCESS if the update completed
428 * successfully or an appropriate error message otherwise
433 IxEthDBStatus ixEthDBPortFrameLengthsUpdate(IxEthDBPortId portID)
435 IxNpeMhMessage message;
436 PortInfo *portInfo = &ixEthDBPortInfo[portID];
439 FILL_SETMAXFRAMELENGTHS_MSG(message, portID, portInfo->maxRxFrameSize, portInfo->maxTxFrameSize);
441 IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portID), message, result);
447 * @brief sets the port maximum Rx frame size
449 * @param portID ID of the port to set the frame size on
450 * @param maximumRxFrameSize maximum Rx frame size
452 * This function updates the internal data structures and
453 * calls ixEthDBPortFrameLengthsUpdate() for NPE update.
455 * This function is fully documented in the main header
458 * @return IX_ETH_DB_SUCCESS if the operation was
459 * successfull or an appropriate error message otherwise
462 IxEthDBStatus ixEthDBFilteringPortMaximumRxFrameSizeSet(IxEthDBPortId portID, UINT32 maximumRxFrameSize)
464 IX_ETH_DB_CHECK_PORT_EXISTS(portID);
466 IX_ETH_DB_CHECK_SINGLE_NPE(portID);
468 if (!ixEthDBPortInfo[portID].initialized)
470 return IX_ETH_DB_PORT_UNINITIALIZED;
473 if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
475 if ((maximumRxFrameSize < IX_ETHDB_MIN_NPE_FRAME_SIZE) ||
476 (maximumRxFrameSize > IX_ETHDB_MAX_NPE_FRAME_SIZE))
478 return IX_ETH_DB_INVALID_ARG;
483 return IX_ETH_DB_NO_PERMISSION;
486 /* update internal structure */
487 ixEthDBPortInfo[portID].maxRxFrameSize = maximumRxFrameSize;
489 /* update the maximum frame size in the NPE */
490 return ixEthDBPortFrameLengthsUpdate(portID);
494 * @brief sets the port maximum Tx frame size
496 * @param portID ID of the port to set the frame size on
497 * @param maximumTxFrameSize maximum Tx frame size
499 * This function updates the internal data structures and
500 * calls ixEthDBPortFrameLengthsUpdate() for NPE update.
502 * This function is fully documented in the main header
505 * @return IX_ETH_DB_SUCCESS if the operation was
506 * successfull or an appropriate error message otherwise
509 IxEthDBStatus ixEthDBFilteringPortMaximumTxFrameSizeSet(IxEthDBPortId portID, UINT32 maximumTxFrameSize)
511 IX_ETH_DB_CHECK_PORT_EXISTS(portID);
513 IX_ETH_DB_CHECK_SINGLE_NPE(portID);
515 if (!ixEthDBPortInfo[portID].initialized)
517 return IX_ETH_DB_PORT_UNINITIALIZED;
520 if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
522 if ((maximumTxFrameSize < IX_ETHDB_MIN_NPE_FRAME_SIZE) ||
523 (maximumTxFrameSize > IX_ETHDB_MAX_NPE_FRAME_SIZE))
525 return IX_ETH_DB_INVALID_ARG;
530 return IX_ETH_DB_NO_PERMISSION;
533 /* update internal structure */
534 ixEthDBPortInfo[portID].maxTxFrameSize = maximumTxFrameSize;
536 /* update the maximum frame size in the NPE */
537 return ixEthDBPortFrameLengthsUpdate(portID);
541 * @brief sets the port maximum Tx and Rx frame sizes
543 * @param portID ID of the port to set the frame size on
544 * @param maximumFrameSize maximum Tx and Rx frame sizes
546 * This function updates the internal data structures and
547 * calls ixEthDBPortFrameLengthsUpdate() for NPE update.
549 * Note that both the maximum Tx and Rx frame size are set
550 * to the same value. This function is kept for compatibility
553 * This function is fully documented in the main header
556 * @return IX_ETH_DB_SUCCESS if the operation was
557 * successfull or an appropriate error message otherwise
560 IxEthDBStatus ixEthDBFilteringPortMaximumFrameSizeSet(IxEthDBPortId portID, UINT32 maximumFrameSize)
562 IX_ETH_DB_CHECK_PORT_EXISTS(portID);
564 IX_ETH_DB_CHECK_SINGLE_NPE(portID);
566 if (!ixEthDBPortInfo[portID].initialized)
568 return IX_ETH_DB_PORT_UNINITIALIZED;
571 if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
573 if ((maximumFrameSize < IX_ETHDB_MIN_NPE_FRAME_SIZE) ||
574 (maximumFrameSize > IX_ETHDB_MAX_NPE_FRAME_SIZE))
576 return IX_ETH_DB_INVALID_ARG;
581 return IX_ETH_DB_NO_PERMISSION;
584 /* update internal structure */
585 ixEthDBPortInfo[portID].maxRxFrameSize = maximumFrameSize;
586 ixEthDBPortInfo[portID].maxTxFrameSize = maximumFrameSize;
588 /* update the maximum frame size in the NPE */
589 return ixEthDBPortFrameLengthsUpdate(portID);
593 * @brief sets the MAC address of an NPE port
595 * @param portID port ID to set the MAC address on
596 * @param macAddr pointer to the 6-byte MAC address
598 * This function is called by the EthAcc
599 * ixEthAccUnicastMacAddressSet() and should not be
600 * manually invoked unless required by special circumstances.
602 * @return IX_ETH_DB_SUCCESS if the operation succeeded
603 * or an appropriate error message otherwise
606 IxEthDBStatus ixEthDBPortAddressSet(IxEthDBPortId portID, IxEthDBMacAddr *macAddr)
608 IxNpeMhMessage message;
611 /* use this macro instead CHECK_PORT
612 as the port doesn't need to be enabled */
613 IX_ETH_DB_CHECK_PORT_EXISTS(portID);
615 IX_ETH_DB_CHECK_REFERENCE(macAddr);
617 if (!ixEthDBPortInfo[portID].initialized)
619 return IX_ETH_DB_PORT_UNINITIALIZED;
622 /* Operation stops here when Ethernet Learning is not enabled */
623 if(IX_FEATURE_CTRL_SWCONFIG_DISABLED ==
624 ixFeatureCtrlSwConfigurationCheck(IX_FEATURECTRL_ETH_LEARNING))
626 return IX_ETH_DB_SUCCESS;
629 IX_ETH_DB_CHECK_SINGLE_NPE(portID);
631 /* exit if the port is not an Ethernet NPE */
632 if (ixEthDBPortDefinitions[portID].type != IX_ETH_NPE)
634 return IX_ETH_DB_INVALID_PORT;
637 /* populate message */
638 FILL_SETPORTADDRESS_MSG(message, portID, macAddr->macAddress);
640 IX_ETH_DB_SUPPORT_TRACE("DB: (Support) Sending SetPortAddress on port %d...\n", portID);
642 /* send a SetPortAddress message */
643 IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portID), message, result);
645 if (result == IX_SUCCESS)
647 ixEthDBPortInfo[portID].macAddressUploaded = true;