Esempio n. 1
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. 2
0
/** fmCreatePolicer
 * \ingroup policer
 *
 * \chips           FM3000, FM4000, FM6000, FM10000
 *
 * \desc            Create a policer. Policers are used to manage
 *                  ingress bandwidth usage based on traffic flows
 *                  characterized by an ACL rule. Once created, a policer is
 *                  associated with an ACL rule in a call to ''fmAddACLRuleExt''.
 *                                                                      \lb\lb
 *                  Policers can be used to manage the bandwidth of a traffic
 *                  flow, or merely count frames and octets for a flow.
 *                                                                      \lb\lb
 *                  Policers are organized into "banks." Multiple ACLs can
 *                  simultaneously "hit" multiple policers, as long as they
 *                  are in different banks. The application need not be
 *                  concerned with the selection of which policers are placed
 *                  in which banks; the ACL compiler (''fmCompileACL'') will
 *                  make the placements automatically. However, not all
 *                  combinations of policer attributes are possible in hardware
 *                  (some attributes are per-bank). The user may want to
 *                  control the arrangement of policers in banks to better
 *                  understand which attribute combinations are foiling the
 *                  compiler. Whether bank selection is performed by the
 *                  application or by the ACL compiler, the choice should be
 *                  consistent for all policers created.
 *
 * \param[in]       sw is the switch on which to operate.
 *
 * \param[in]       bank is the bank in which to create the policer.
 *                  Set to FM_POLICER_BANK_AUTOMATIC to have the ACL compiler
 *                  (''fmCompileACL'') automatically assign the policer to a
 *                  bank.
 *
 * \param[in]       policer is the policer number to create. Policer numbers
 *                  are unique across all banks.
 *
 * \param[in]       config points to a structure of type ''fm_policerConfig''
 *                  that contains the initial configuration of the policer.
 *                  Alternatively, config can be NULL and the policer
 *                  configuration can be set with calls to
 *                  ''fmSetPolicerAttribute''
 *
 * \return          FM_OK if successful.
 * \return          FM_ERR_INVALID_SWITCH if sw is invalid.
 * \return          FM_ERR_INVALID_POLICER if policer already created.
 * \return          FM_ERR_INVALID_ARGUMENT if bank or policer values are
 *                  out of range.
 *
 *****************************************************************************/
fm_status fmCreatePolicer(fm_int                  sw,
                          fm_int                  bank,
                          fm_int                  policer,
                          const fm_policerConfig *config)
{
    fm_policerInfo *      info;
    fm_individualPolicer *entry;
    fm_switch *           switchPtr;

    FM_API_PREAMBLE("sw = %d, bank = %d, policer = %d, config = %p\n",
                    sw,
                    bank,
                    policer,
                    (void *) config);

    FM_API_REQUIRE(POLICER_VALID(policer) && BANK_VALID(sw, bank),
                   FM_ERR_INVALID_ARGUMENT);

    switchPtr = GET_SWITCH_PTR(sw);

    info  = &switchPtr->policerInfo;
    entry = (fm_individualPolicer *) fmAlloc( sizeof(fm_individualPolicer) );
    FM_API_REQUIRE(entry != NULL, FM_ERR_NO_MEM);

    entry->bank = bank;

    if (config == NULL)
    {
        /* default attribute values */
        entry->attributes.mkdnDscp    = FM_DISABLED;
        entry->attributes.mkdnSwPri   = FM_DISABLED;
        entry->attributes.colorSource = FM_POLICER_COLOR_SRC_GREEN;
        entry->attributes.cirAction   = FM_POLICER_ACTION_DROP;
        entry->attributes.cirCapacity = 0;
        entry->attributes.cirRate     = 0;
        entry->attributes.eirAction   = FM_POLICER_ACTION_DROP;
        entry->attributes.eirCapacity = 0;
        entry->attributes.eirRate     = 0;
        entry->attributes.cirActionData.dscp = 0;
        entry->attributes.cirActionData.swPri = 0;
        entry->attributes.cirActionData.vPri = 0;
        entry->attributes.eirActionData.dscp = 0;
        entry->attributes.eirActionData.swPri = 0;
        entry->attributes.eirActionData.vPri = 0;
    }
    else
    {
        entry->attributes = *config;
    }

    err = fmTreeInsert(&info->policers, policer, entry);

    if (err != FM_OK)
    {
        fmFree(entry);

        if (err == FM_ERR_ALREADY_EXISTS)
        {
            err = FM_ERR_INVALID_POLICER;
        }
    }

    if ( (err == FM_OK) && (switchPtr->CreatePolicer != NULL) )
    {
        /* for SWAG */
        err = switchPtr->CreatePolicer(sw, bank, policer, config);

        /* Try to return a clean state by removing the policer from switches that
         * actually created it (if some). Sorting order of creation and deletion
         * should be the same. */
        if (err != FM_OK)
        {
            switchPtr->DeletePolicer(sw, policer);
            fmTreeRemoveCertain(&info->policers, policer, fmFree);
        }
    }

    FM_API_POSTAMBLE;

}   /* end fmCreatePolicer */