Exemplo n.º 1
0
/** 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 */
Exemplo n.º 2
0
/** 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 */