/** fm10000RedirectCpuTrafficToPort * \ingroup intStacking * * \desc Redirect CPU traffic to the specified logical port. * The logical port can be a physical port or a LAG. * * \note This function may be called before the port table has * been initialized. * * \param[in] sw is the switch number to operate on. * * \param[in] port is the logical port. * port value -1 indicates current cpu port configuration. * * \return FM_OK if successful. * \return FM_ERR_INVALID_PORT if port is invalid. * \return Other 'Status Codes' ad appropriate in case of failure. * *****************************************************************************/ fm_status fm10000RedirectCpuTrafficToPort(fm_int sw, fm_int port) { fm_switch * switchPtr; fm10000_switch *switchExt; fm_uint64 rv1; fm_portmask destMask; fm_status err; fm_int portList[FM_MAX_NUM_LAG_MEMBERS]; fm_int numPorts; fm_int physPort; FM_LOG_ENTRY(FM_LOG_CAT_STACKING, "sw=%d port=%d\n", sw, port); switchPtr = GET_SWITCH_PTR(sw); switchExt = GET_SWITCH_EXT(sw); FM_PORTMASK_DISABLE_ALL(&destMask); if (port < 0) { if (port == -1) { /* Use the current configuration */ port = switchPtr->cpuPort; } else { /* port number is invalid, return error */ FM_LOG_EXIT(FM_LOG_CAT_STACKING, FM_ERR_INVALID_PORT); } } else { switchPtr->cpuPort = port; } if ( fmIsCardinalPort(sw, port) ) { err = fmEnablePortInPortMask(sw, &destMask, port); FM_LOG_EXIT_ON_ERR(FM_LOG_CAT_STACKING, err); /* We have to do a formal translation here, since the port table * may not exist yet. */ err = fmMapLogicalPortToPhysical(switchPtr, port, &physPort); FM_LOG_EXIT_ON_ERR(FM_LOG_CAT_STACKING, err); rv1 = (1 << physPort); } else if ( fmIsValidLagPort(sw, port) ) { /* CPU traffic can't be filtered over internal LAG; hence, we can * only redirect the traffic to a single active member port, or * result in duplicate packets. */ err = fmGetLAGMemberPorts(sw, GET_PORT_PTR(sw, port)->lagIndex, &numPorts, portList, FM_MAX_NUM_LAG_MEMBERS, TRUE); FM_LOG_EXIT_ON_ERR(FM_LOG_CAT_STACKING, err); rv1 = 0; if (numPorts > 0) { err = fmMapLogicalPortToPhysical(switchPtr, portList[0], &physPort); FM_LOG_EXIT_ON_ERR(FM_LOG_CAT_STACKING, err); rv1 |= (FM_LITERAL_U64(1) << physPort); err = fmEnablePortInPortMask(sw, &destMask, portList[0]); FM_LOG_EXIT_ON_ERR(FM_LOG_CAT_STACKING, err); } } else { FM_LOG_EXIT_ON_ERR(FM_LOG_CAT_STACKING, FM_ERR_INVALID_PORT); } /* Change the destination mask for cpu port so traffic * matching CPU glort will be redirected to the specified port. */ err = switchPtr->SetLogicalPortAttribute(sw, switchPtr->cpuPort, FM_LPORT_DEST_MASK, &destMask); FM_LOG_EXIT_ON_ERR(FM_LOG_CAT_STACKING, err); /* Update the CPU_TRAP_MASK so trapped frames go to the CPU. */ err = switchPtr->WriteUINT64(sw, FM10000_CPU_TRAP_MASK_FH(0), rv1); FM_LOG_EXIT(FM_LOG_CAT_STACKING, err); } /* end fm10000RedirectCpuTrafficToPort */
/** MapLagPortToMemberPort * \ingroup intSwitch * * \desc Maps a LAG logical port to one of its member ports. * * \param[in] sw is the switch to operate on. * * \param[in] port is the LAG logical port number. * * \param[out] logPort points to the location to receive the logical * port number. * * \return FM_OK if successful. * \return FM_ERR_INVALID_PORT if the port number is invalid. * \return FM_ERR_NO_PORTS_IN_LAG if port refers to an empty LAG. * *****************************************************************************/ static fm_status MapLagPortToMemberPort(fm_int sw, fm_int port, fm_int *logPort) { fm_int portList[FM_MAX_NUM_LAG_MEMBERS]; fm_port * portPtr; fm_lag * lagPtr; fm_int numPorts; fm_status err; portPtr = GET_PORT_PTR(sw, port); if (portPtr == NULL) { return FM_ERR_INVALID_PORT; } lagPtr = GET_LAG_PTR(sw, portPtr->lagIndex); if(lagPtr == NULL) { return FM_ERR_INVALID_PORT; } /* Get a list of active member ports. */ err = fmGetLAGCardinalPortList(sw, lagPtr->logicalPort, &numPorts, portList, FM_MAX_NUM_LAG_MEMBERS); if (err != FM_OK) { return err; } if (numPorts == 0) { /* Return the first port even if the link is currently down. * This should ensure that a SWAG or Stacked Configuration * works properly at init time. */ err = fmGetLAGMemberPorts(sw, portPtr->lagIndex, &numPorts, portList, FM_MAX_NUM_LAG_MEMBERS, FALSE); if (err != FM_OK) { return err; } else if (numPorts == 0) { return FM_ERR_NO_PORTS_IN_LAG; } } /* * Select one of the LAG ports using pseudo-random selection. * * Why are we doing "pseudo-random" selection? Why not (for * example) return the logical port that corresponds to the canonical * logical port? */ *logPort = portList[port % numPorts]; return FM_OK; } /* end MapLagPortToMemberPort */