/**fm10000InformRedirectCPUPortLinkChange * \ingroup intStacking * * \desc Inform a link change for a port. This will update * the port mask appropriately for the CPU port * when the traffic is redirected over a LAG. * * \param[in] sw is the switch number to operate on. * * \param[in] port is the logical port. * * \param[in] linkStatus is the link status of the port. * * \return FM_OK if successful. * *****************************************************************************/ fm_status fm10000InformRedirectCPUPortLinkChange(fm_int sw, fm_int port, fm_portLinkStatus linkStatus) { fm_status err; fm_switch *switchPtr; fm_int members[FM_MAX_NUM_LAG_MEMBERS]; fm_int numMembers; fm_int cnt; FM_NOT_USED(linkStatus); FM_LOG_ENTRY(FM_LOG_CAT_STACKING, "sw=%d port=%d\n", sw, port); switchPtr = GET_SWITCH_PTR(sw); if (switchPtr->cpuPort == 0) { /* real CPU port is always up, no need to do anything */ FM_LOG_EXIT(FM_LOG_CAT_STACKING, FM_OK); } err = fmGetLAGCardinalPortList(sw, switchPtr->cpuPort, &numMembers, members, FM_MAX_NUM_LAG_MEMBERS); FM_LOG_EXIT_ON_ERR(FM_LOG_CAT_STACKING, err); for (cnt = 0 ; cnt < numMembers ; cnt++) { if (members[cnt] == port) { /* Link change for a member, update */ err = fm10000RedirectCpuTrafficToPort(sw, -1); break; } } FM_LOG_EXIT(FM_LOG_CAT_STACKING, err); } /* end fm10000InformRedirectCPUPortLinkChange */
/** 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 */