Esempio n. 1
0
/** fmUpdatePolicer
 * \ingroup policer
 *
 * \chips           FM6000, FM10000
 *
 * \desc            Updates policer configuration in hardware without 
 *                  disrupting existing ACLs. The configuration is updated
 *                  with values obtained from the policer attributes. 
 *                  This function is used to update the configuration of a
 *                  policer that has already been created, and whose previous
 *                  configuration is in hardware. For setting policer
 *                  attributes see ''fmSetPolicerAttribute''.
 *
 * \param[in]       sw is the switch on which to operate.
 *
 * \param[in]       policer is the policer number to be updated.
 *
 * \return          FM_OK if successful.
 * \return          FM_ERR_INVALID_POLICER if policer is not present in the
 *                  software cache or has invalid attribute values.
 * \return          FM_ERR_INVALID_ACL_IMAGE if no applied acl image is found.
 * \return          FM_ERR_INVALID_COUNTER_BANK if policer's current bank is 
 *                  invalid.
 * \return          FM_ERR_INVALID_COUNTER_INDEX if policer's index in the bank 
 *                  is invalid.
 * \return          FM_ERR_UNSUPPORTED if this api is not supported by this
 *                  type of switch.
 * \return          FM_ERR_INVALID_SWITCH if sw is invalid.
 * \return          FM_ERR_CONFLICT_POLICER_PARAM if the new configuration
 *                  conflicts with the policer bank configuration.
 *                  (FM10000 only)
 *
 *****************************************************************************/
fm_status fmUpdatePolicer(fm_int sw, fm_int policer)
{
    fm_switch      *switchPtr;
    fm_policerInfo *info;
    void           *value;

    FM_API_PREAMBLE("sw = %d, policer = %d\n",
                    sw,
                    policer);

    switchPtr = GET_SWITCH_PTR(sw);
    info      = &switchPtr->policerInfo;

    err = fmTreeFind(&info->policers, policer, &value);

    if (value == NULL || err == FM_ERR_NOT_FOUND)
    {
        FM_API_ABORT(FM_ERR_INVALID_POLICER);
    }

    FM_API_CALL_FAMILY(err,
                       switchPtr->UpdatePolicer,
                       sw,
                       policer);
    
    FM_API_POSTAMBLE;

}   /* end fmUpdatePolicer */
Esempio n. 2
0
/** fm10000DeleteForwardingRule
 * \ingroup intStacking
 *
 * \desc            Deletes a rule given the rule ID.
 *
 * \param[in]       sw is the switch number to operate on.
 *
 * \param[in]       ruleId is the ID number of the rule to delete.
 *
 *
 * \return          FM_OK if successful.
 * \return          FM_ERR_NOT_FOUND if id not recognized.
 *
 *****************************************************************************/
fm_status fm10000DeleteForwardingRule(fm_int sw, fm_int ruleId)
{
    fm_switch *                  switchPtr;
    fm_stackingInfo *            stackingInfo;
    fm_forwardRuleInternal *     internalRule;
    fm10000_forwardRuleInternal *fwdExt;
    fm_status                    err;

    FM_LOG_ENTRY(FM_LOG_CAT_STACKING, "sw=%d, id=%d\n", sw, ruleId);

    switchPtr    = GET_SWITCH_PTR(sw);
    stackingInfo = &switchPtr->stackingInfo;

    err = fmTreeFind( &stackingInfo->fwdRules,
                      ruleId,
                      (void **) &internalRule );
    FM_LOG_EXIT_ON_ERR(FM_LOG_CAT_STACKING, err);

    fwdExt = (fm10000_forwardRuleInternal *) internalRule->extension;

    /* this invalidates the CAM entry */
    fwdExt->camEntry->camKey = 0;
    fwdExt->camEntry->camMask = 0;

    err = fm10000WriteGlortCamEntry(sw, fwdExt->camEntry, FM_UPDATE_CAM_ONLY);
    FM_LOG_EXIT_ON_ERR(FM_LOG_CAT_STACKING, err);

    FM_LOG_DEBUG(FM_LOG_CAT_STACKING,
                 "Reset CAM entry 0x%x\n",
                 fwdExt->camEntry->camIndex);

    /* mark it available */
    fwdExt->camEntry->useCount = 0;

    FM_LOG_EXIT(FM_LOG_CAT_STACKING, FM_OK);

}   /* end fm10000DeleteForwardingRule */
Esempio n. 3
0
/** fm10000CreateForwardingRule
 * \ingroup intStacking
 *
 * \desc            Creates a forwarding rule.
 *
 * \param[in]       sw is the switch number to operate on.
 *
 * \param[in]       ruleId points to caller allocated storage where the handle
 *                  of the new rule is written to.
 *
 * \param[in]       rule points to caller allocated storage containing the
 *                  rule to create.
 *
 * \return          FM_OK if successful.
 * \return          FM_ERR_NO_FREE_RESOURCES if there are no hardware resources
 *                  to accommodate the new forwarding rule.
 * \return          FM_ERR_NO_MEM if there is not enough memory to store
 *                  the forwarding rule data structure.
 *
 *****************************************************************************/
fm_status fm10000CreateForwardingRule(fm_int sw,
                                      fm_int *ruleId,
                                      fm_forwardRule *rule)
{
    fm_status                    err;
    fm_int                       camIndex;
    fm_glortCamEntry *           camEntry;
    fm_switch *                  switchPtr;
    fm_logicalPortInfo *         lportInfo;
    fm_forwardRuleInternal *     internalRule;
    fm10000_forwardRuleInternal *fwdExt;
    fm_stackingInfo *            stackingInfo;
    fm_port *                    portPtr;

    FM_LOG_ENTRY( FM_LOG_CAT_STACKING,
                  "sw=%d, ruleId=%p, rule=%p\n",
                  sw,
                  (void *) ruleId,
                  (void *) rule );

    switchPtr = GET_SWITCH_PTR(sw);
    lportInfo = &switchPtr->logicalPortInfo;
    portPtr   = GET_PORT_PTR(sw, rule->logicalPort);
    fwdExt    = NULL;

    if (portPtr == NULL)
    {
        err = FM_ERR_INVALID_PORT;
        FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_STACKING, err);
    }

    stackingInfo = &switchPtr->stackingInfo;

    /***************************************************
     * Find an unused CAM entry.
     **************************************************/
    camIndex = fmFindUnusedCamEntry(sw);
    if (camIndex < 0)
    {
        err = FM_ERR_NO_FREE_RESOURCES;
        FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_STACKING, err);
    }

    camEntry = &lportInfo->camEntries[camIndex];

    /***************************************************
     * Create an FM10000 forwarding rule extension.
     **************************************************/
    fwdExt = (fm10000_forwardRuleInternal *) fmAlloc( sizeof(fm10000_forwardRuleInternal) );

    if (fwdExt == NULL)
    {
        err = FM_ERR_NO_MEM;
        FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_STACKING, err);
    }

    fwdExt->camEntry = camEntry;

    /***************************************************
     * Initialize the CAM entry.
     **************************************************/
    FM_MEMSET_S( camEntry, sizeof(fm_glortCamEntry), 0, sizeof(fm_glortCamEntry) );

    camEntry->camIndex = camIndex;
    camEntry->camKey   = rule->glort;
    camEntry->camMask  = ~rule->mask;   /* Hardware stores mask inverted from rule mask */

    if ( fmIsCardinalPort(sw, rule->logicalPort) )
    {
        camEntry->strict = FM_GLORT_ENTRY_TYPE_STRICT;
    }
    else
    {
        /* Needs to be hashed to support LAG on internal port for traffic
         * to be hashed across the internal LAG link. Especially
         * CPU traffic, since FTYPE is special delivery and won't
         * be hashed if set to ISL */
        camEntry->strict = FM_GLORT_ENTRY_TYPE_HASHED;
    }

    /***************************************************
     * This makes the assumption that the rule points
     * to a physical port that is not going to have its
     * dest table entry changing.
     **************************************************/
    camEntry->destIndex    = portPtr->destEntry->destIndex;
    camEntry->destCount    = 1;
    camEntry->useCount     = 1;

    /***************************************************
     * Write CAM entry to hardware.
     **************************************************/
    err = fm10000WriteGlortCamEntry(sw, camEntry, FM_UPDATE_CAM_AND_RAM);
    FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_STACKING, err);

    FM_LOG_DEBUG(FM_LOG_CAT_STACKING, "Wrote to CAM entry 0x%x\n", camIndex);

    /***************************************************
     * Get the underlying forwarding rule object.
     **************************************************/
    err = fmTreeFind( &stackingInfo->fwdRules,
                      *ruleId,
                      (void **) &internalRule );
    FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_STACKING, err);

    /***************************************************
     * Store pointer to extension.
     **************************************************/
    internalRule->extension = fwdExt;
    err                     = FM_OK;


ABORT:

    if (err != FM_OK)
    {
        if (fwdExt != NULL)
        {
            fmFree(fwdExt);
        }
    }

    FM_LOG_EXIT(FM_LOG_CAT_STACKING, err);

}   /* end fm10000CreateForwardingRule */
Esempio n. 4
0
/** fm10000MoveReplicationGroupMcastGroup
 * \ingroup intMulticast
 *
 * \desc            Move the mcast group to a given replication group.
 *
 * \param[in]       sw is the switch number.
 *
 * \param[in]       groupHandle is the new replication group handle.
 *
 * \param[in]       mcastGroup is the mcast group number.
 *
 * \return          FM_OK if successful.
 * \return          FM_ERR_INVALID_MULTICAST_GROUP if the replication group
 *                  is invalid.
 * \return          FM_ERR_INVALID_PORT if a listener port is invalid
 *
 *****************************************************************************/
fm_status fm10000MoveReplicationGroupMcastGroup(fm_int sw, 
                                               fm_int groupHandle,
                                               fm_int mcastGroup)
{
    fm_status               err=FM_OK;
    fm_switch *             switchPtr;
    fm_intReplicationGroup *repliGroup;
    fm_intReplicationGroup *prevGroup;
    fm_intMulticastGroup *  mcastGroupPtr;
    fm_intMulticastGroup *  mcastGroupTmp;
    fm10000_MulticastGroup *mcastGroupExt;
    fm_int                  groupDestIndex;
    fm_int                  newGroupId=FM_MCASTGROUP_REPLICATION_GROUP_DISABLE;
    fm_int                  mtableDestIndex;
    fm_int                  privateGroup=FALSE;
    fm_bool                 removeFromPreviousTree=FALSE;
    fm_treeIterator         iter;
    fm_uint64               key;
    fm_intMulticastEcmp *   ecmpGroup;

    FM_LOG_ENTRY( FM_LOG_CAT_MULTICAST,
                 "sw=%d newrepliGroup=%d mcastGroup=%d\n",
                 sw,
                 groupHandle,
                 mcastGroup);

    switchPtr = GET_SWITCH_PTR(sw);

    mcastGroupPtr = fmFindMcastGroup(sw, mcastGroup);

    if ( mcastGroupPtr == NULL )
    {
        err = FM_ERR_INVALID_MULTICAST_GROUP;
        FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_MULTICAST, err);
    }

    mcastGroupExt  = mcastGroupPtr->extension;
    groupDestIndex = -1;

    /* If the given new replication group is -1, i.e. disable, then we
     * need to allocate a private replication group for this mcast group
     * if the latter is active */

    if ( groupHandle == FM_MCASTGROUP_REPLICATION_GROUP_DISABLE )
    {
        if (mcastGroupPtr->activated)
        {
            privateGroup = TRUE;
    
            err = fmCreateReplicationGroupInt(sw, 
                                              &newGroupId, 
                                              mcastGroupPtr->logicalPort, 
                                              &mtableDestIndex,
                                              TRUE);
            FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_MULTICAST, err);
    
            FM_LOG_DEBUG(FM_LOG_CAT_MULTICAST, 
                         "newRepliGroup %d DestIndex=%d\n", 
                         newGroupId, mtableDestIndex);
        }
    }
    else
    {
        privateGroup = FALSE;
        newGroupId = groupHandle;
    }

    if (newGroupId != FM_MCASTGROUP_REPLICATION_GROUP_DISABLE)
    {
        /* We have to move the mcast group to a new replication group */

        repliGroup = findReplicationGroup(sw, newGroupId);

        if (repliGroup == NULL)
        {
            err = FM_ERR_INVALID_MULTICAST_GROUP;
            FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_MULTICAST, err);
        }
    
        /* Search the tree of mcast groups for a matching entry. */
        err = fmTreeFind( &repliGroup->mcastGroupList,
                         (fm_uint64) mcastGroup,
                         (void **) &mcastGroupTmp );
    
        if (err == FM_OK)
        {
            /* Error if already in group */
            err = FM_ERR_ALREADY_EXISTS;
            FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_MULTICAST, err);
        }

        groupDestIndex = repliGroup->hwDestIndex;
    
        if (mcastGroupPtr->activated)
        {
            /* This mcast group is active; move all its listeners to the
             * new replication group. */
    
            /* Update the multicast index attribute for this mcast group */
            err = switchPtr->SetLogicalPortAttribute(sw,
                                                     mcastGroupPtr->logicalPort,
                                                     FM_LPORT_MULTICAST_INDEX,
                                                     &groupDestIndex);
            FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_MULTICAST, err);
            if (!mcastGroupPtr->readOnlyRepliGroup)
            {
                err = MoveListenersToReplicationGroup(sw, newGroupId, mcastGroupPtr);
                FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_MULTICAST, err);
            }
            /* Update the NextHop entry to use the new replicate group. */
            mcastGroupExt->mtableDestIndex = groupDestIndex;
            err = fm10000UpdateNextHopMulticast(sw,
                                               mcastGroupPtr->ecmpGroup);
            FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_MULTICAST, err);
    
            fmTreeIterInit(&iter, &mcastGroupPtr->ecmpTree);
            while (1)
            {
                err = fmTreeIterNext(&iter,
                                     &key,
                                     (void **) &ecmpGroup);
                if (err != FM_OK)
                {
                    if (err == FM_ERR_NO_MORE)
                    {
                        err = FM_OK;
                    }

                    break;
                }

                err = fm10000UpdateNextHopMulticast(sw,
                                                   ecmpGroup->ecmpId);
                FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_MULTICAST, err);
            }

            FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_MULTICAST, err);

            /* Remove the mcastgroup's listeners from previous replication group */
            if (!mcastGroupPtr->readOnlyRepliGroup)
            {
                err = RemoveListenersFromReplicationGroup(sw, 
                                                      mcastGroupPtr->repliGroup, 
                                                      mcastGroupPtr);
                FM_LOG_ABORT_ON_ERR ( FM_LOG_CAT_MULTICAST, err );
            }

            /* Release the previous replication group if it was a private one */
            if (mcastGroupPtr->privateGroup)
            {
                /* No need to remove it from previous group Tree since
                 * the group will be deleted or freed */
                removeFromPreviousTree = FALSE;

                err =
                    fmDeleteReplicationGroupInt(sw,
                                                mcastGroupPtr->repliGroup,
                                                TRUE);
                FM_LOG_ABORT_ON_ERR ( FM_LOG_CAT_MULTICAST, err );
            }
            else
            {
                /* Remove mcast group from the list of the previous
                 * replication group */
                removeFromPreviousTree = TRUE;
            }
        }
        else if (mcastGroupPtr->repliGroup != 
                 FM_MCASTGROUP_REPLICATION_GROUP_DISABLE)
        {
            /* Remove mcast group from the list of the previous
             * replication group */
            removeFromPreviousTree = TRUE;
        }

        /* Insert the mcast group in the list of the new replication group */
        err = fmTreeInsert(&repliGroup->mcastGroupList,
                           (fm_uint64) mcastGroup,
                           (void *) mcastGroupPtr);
    
        FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_MULTICAST, err);

    }
    else if (mcastGroupPtr->repliGroup != FM_MCASTGROUP_REPLICATION_GROUP_DISABLE)
    {
        /* Removing a none active mcast group from its replication group */
        privateGroup = FALSE;
        groupDestIndex = -1;
        removeFromPreviousTree = TRUE;
    }

    if (removeFromPreviousTree)
    {
        /* Remove mcast group from the list of the previous replication group */

        prevGroup = findReplicationGroup(sw, mcastGroupPtr->repliGroup);

        if (prevGroup == NULL)
        {
            err = FM_ERR_INVALID_MULTICAST_GROUP;
            FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_MULTICAST, err);
        }

        err = fmTreeRemove(&prevGroup->mcastGroupList,
                           (fm_uint64) mcastGroup,
                           NULL );
        FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_MULTICAST, err);
    
        FM_LOG_DEBUG(FM_LOG_CAT_MULTICAST,
                     "mcast group %d deleted from Replication group %d\n",
                     mcastGroup, prevGroup->handle);
    }

    /* Update mcast group with info from the new replication group */
    mcastGroupPtr->repliGroup      = newGroupId;
    mcastGroupPtr->privateGroup    = privateGroup;
    mcastGroupExt->mtableDestIndex = groupDestIndex;

    FM_LOG_DEBUG(FM_LOG_CAT_MULTICAST,
                 "mcastgroup %d moved to Replication group %d, index %d\n",
                 mcastGroup, mcastGroupPtr->repliGroup, groupDestIndex);

ABORT:

    FM_LOG_EXIT(FM_LOG_CAT_MULTICAST, err);

}   /* end fm10000MoveReplicationGroupMcastGroup */
Esempio n. 5
0
/** GetAttributeLocation
 * \ingroup intPolicer
 *
 * \desc            This function contains the logic for the policer
 *                  attributes in one place, instead of replicating the
 *                  logic in both the get and set functions, as is done
 *                  in other attribute systems in the API.  This function
 *                  returns the location and size of the specified attribute,
 *                  and the caller can then copy into or out of it as
 *                  appropriate.
 *
 * \param[in]       sw is the switch on which to operate.
 *
 * \param[in]       policer is the policer number whose attribute is to be
 *                  accessed. This argument is ignored for global attributes.
 *
 * \param[in]       attr is the policer attribute to access (see
 *                  ''Policer Attributes'').
 *
 * \param[out]      location receives the address of the attribute
 *
 * \param[out]      size receives the size of the attribute, in bytes
 *
 * \return          FM_OK if successful.
 * \return          FM_ERR_INVALID_POLICER if policer is invalid.
 * \return          FM_ERR_INVALID_ARGUMENT if unrecognized attribute.
 *
 *****************************************************************************/
static fm_status GetAttributeLocation(fm_int  sw,
                                      fm_int  policer,
                                      fm_int  attr,
                                      void ** location,
                                      fm_int *size)
{
    void *                value;
    fm_individualPolicer *entry;
    fm_policerInfo *      info;
    fm_status             treeErr;

    info    = &GET_SWITCH_PTR(sw)->policerInfo;
    treeErr = fmTreeFind(&info->policers, policer, &value);
    entry   = (fm_individualPolicer *) value;

    if (treeErr == FM_ERR_NOT_FOUND)
    {
        treeErr = FM_ERR_INVALID_POLICER;
    }

    switch (attr)
    {
        case FM_POLICER_MKDN_DSCP:
            RETURN_POLICER_ATTRIBUTE(mkdnDscp);

        case FM_POLICER_MKDN_SWPRI:
            RETURN_POLICER_ATTRIBUTE(mkdnSwPri);

        case FM_POLICER_COLOR_SOURCE:
            RETURN_POLICER_ATTRIBUTE(colorSource);

        case FM_POLICER_CIR_ACTION:
            RETURN_POLICER_ATTRIBUTE(cirAction);

        case FM_POLICER_CIR_ACTION_DATA_DSCP:
            RETURN_POLICER_ATTRIBUTE(cirActionData.dscp);

        case FM_POLICER_CIR_ACTION_DATA_VPRI:
            RETURN_POLICER_ATTRIBUTE(cirActionData.vPri);

        case FM_POLICER_CIR_ACTION_DATA_SWPRI:
            RETURN_POLICER_ATTRIBUTE(cirActionData.swPri);

        case FM_POLICER_CIR_CAPACITY:
            RETURN_POLICER_ATTRIBUTE(cirCapacity);

        case FM_POLICER_CIR_RATE:
            RETURN_POLICER_ATTRIBUTE(cirRate);

        case FM_POLICER_EIR_ACTION:
            RETURN_POLICER_ATTRIBUTE(eirAction);

        case FM_POLICER_EIR_ACTION_DATA_DSCP:
            RETURN_POLICER_ATTRIBUTE(eirActionData.dscp);

        case FM_POLICER_EIR_ACTION_DATA_VPRI:
            RETURN_POLICER_ATTRIBUTE(eirActionData.vPri);

        case FM_POLICER_EIR_ACTION_DATA_SWPRI:
            RETURN_POLICER_ATTRIBUTE(eirActionData.swPri);

        case FM_POLICER_EIR_CAPACITY:
            RETURN_POLICER_ATTRIBUTE(eirCapacity);

        case FM_POLICER_EIR_RATE:
            RETURN_POLICER_ATTRIBUTE(eirRate);

        case FM_POLICER_SWPRI_MKDN_MAP:
            *location = info->swPriMkdnMap;
            *size     = sizeof(info->swPriMkdnMap);
            return FM_OK;

        case FM_POLICER_DSCP_MKDN_MAP:
            *location = info->dscpMkdnMap;
            *size     = sizeof(info->dscpMkdnMap);
            return FM_OK;

        default:
            return FM_ERR_INVALID_ARGUMENT;

    }   /* end switch (attr) */

}   /* end GetAttributeLocation */