Exemplo n.º 1
0
/** fmGetPolicerFirst
 * \ingroup policer
 *
 * \chips           FM3000, FM4000, FM6000, FM10000
 *
 * \desc            Retrieve the first policer number.
 *
 * \param[in]       sw is the switch on which to operate.
 *
 * \param[out]      firstPolicer points to caller-allocated storage
 *                  where this function should place the number of the first
 *                  policer.  Will be set to -1 if no policers are found.
 *
 * \return          FM_OK if successful.
 * \return          FM_ERR_INVALID_SWITCH if sw is invalid.
 * \return          FM_ERR_NO_POLICERS if no policers found.
 *
 *****************************************************************************/
fm_status fmGetPolicerFirst(fm_int sw, fm_int *firstPolicer)
{
    fm_policerInfo *info;
    fm_treeIterator it;
    fm_uint64       nextKey;
    void *          nextValue;

    FM_API_PREAMBLE("sw = %d, firstPolicer = %p\n",
                    sw, (void *) firstPolicer);

    if (firstPolicer == NULL)
    {
        err = FM_ERR_INVALID_ARGUMENT;
        goto ABORT;
    }

    info = &GET_SWITCH_PTR(sw)->policerInfo;
    fmTreeIterInit(&it, &info->policers);
    err = fmTreeIterNext(&it, &nextKey, &nextValue);

    if (err == FM_OK)
    {
        *firstPolicer = nextKey;
    }
    else if (err == FM_ERR_NO_MORE)
    {
        *firstPolicer = -1;
        err           = FM_ERR_NO_POLICERS;
    }

    FM_API_POSTAMBLE;

}   /* end fmGetPolicerFirst */
Exemplo n.º 2
0
/** fmGetPolicerList
 * \ingroup policer
 *
 * \chips           FM3000, FM4000, FM6000, FM10000
 *
 * \desc            Return a list of valid policer numbers.
 *
 * \param[in]       sw is the switch on which to operate.
 *
 * \param[out]      numPolicers points to caller allocated storage where
 *                  this function should place the number of valid policers
 *                  returned in policers.
 *
 * \param[out]      policers is an array that this function will fill
 *                  with the list of valid policer numbers.
 *
 * \param[in]       max is the size of policers, being the maximum number of
 *                  policer numbers that policers can hold.
 *
 * \return          FM_OK if successful.
 * \return          FM_ERR_INVALID_SWITCH if sw is invalid.
 * \return          FM_ERR_BUFFER_FULL if max was too small to accommodate
 *                  the entire list of valid policer numbers.
 *
 *****************************************************************************/
fm_status fmGetPolicerList(fm_int  sw,
                           fm_int *numPolicers,
                           fm_int *policers,
                           fm_int  max)
{
    fm_policerInfo *info;
    fm_treeIterator it;
    fm_uint64       nextKey;
    void *          nextValue;

    FM_API_PREAMBLE("sw = %d, numPolicers = %p, policers = %p, max = %d\n",
                    sw,
                    (void *) numPolicers,
                    (void *) policers,
                    max);

    if ((numPolicers == NULL) || (policers == NULL))
    {
        err = FM_ERR_INVALID_ARGUMENT;
        goto ABORT;
    }

    *numPolicers = 0;
    info         = &GET_SWITCH_PTR(sw)->policerInfo;

    for (fmTreeIterInit(&it, &info->policers) ;
         ( err = fmTreeIterNext(&it, &nextKey, &nextValue) ) == FM_OK ; )
    {
        FM_API_REQUIRE(*numPolicers < max, FM_ERR_BUFFER_FULL);
        policers[(*numPolicers)++] = nextKey;
    }

    if (err == FM_ERR_NO_MORE)
    {
        err = FM_OK;
    }

    FM_API_POSTAMBLE;

}   /* end fmGetPolicerList */
Exemplo n.º 3
0
/** fm10000CreateLogicalPortForGlort
 * \ingroup intStacking
 *
 * \desc            Creates a logical port for the given glort.  This occurs
 *                  only if the glort is not local to the current switch and
 *                  a forwarding rule exists for the glort, otherwise an
 *                  error is returned.
 *
 * \param[in]       sw is the switch number to operate on.
 *
 * \param[in]       glort is the glort for which a logical port is to be created
 *
 * \param[out]      logicalPort is a pointer to an integer into which the
 *                  new logical port will be written.
 *
 * \return          FM_OK if successful.
 * \return          FM_ERR_GLORT_IN_USE if the specified is already being used
 *                  by others.
 * \return          FM_ERR_NO_FORWARDING_RULES if no forwarding rule associated
 *                  with glort.
 * \return          FM_ERR_NO_FREE_RESOURCES if logical port numbers available
 *                  for allocation.
 * \return          FM_ERR_NO_MEM if no memory available to store logical
 *                  port data structure.
 *
 *****************************************************************************/
fm_status fm10000CreateLogicalPortForGlort(fm_int    sw,
                                           fm_uint32 glort,
                                           fm_int *  logicalPort)
{
    fm_status               err;
    fm_switch *             switchPtr;
    fm_stackingInfo *       stackingInfo;
    fm_port *               portPtr;
    fm_glortCamEntry *      camEntry;
    fm10000_port *          portExt;
    fm_treeIterator         iter;
    fm_forwardRuleInternal *tmpRule;
    fm_uint64               tmpId;
    fm_bool                 found;

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

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

    /* If there is an existing entry already, then return the existing one */
    err = fmGetGlortLogicalPort(sw, glort, logicalPort);
    if (err == FM_OK)
    {
        /* The port already exists, see if it is the same type */
        portPtr = GET_PORT_PTR(sw, *logicalPort);

        if (portPtr->portType == FM_PORT_TYPE_REMOTE)
        {
            /* Yes, return the existing port */
            FM_LOG_EXIT(FM_LOG_CAT_STACKING, FM_OK);
        }
        else
        {
            /* The glort is being used for something else */
            FM_LOG_EXIT(FM_LOG_CAT_STACKING, FM_ERR_GLORT_IN_USE);
        }
    }

    /***************************************************
     * Search the tree for a forwarding rule with a
     * matching glort.
     **************************************************/
    fmTreeIterInit(&iter, &stackingInfo->fwdRules);

    err = fmTreeIterNext( &iter, &tmpId, (void **) &tmpRule );

    while (err != FM_ERR_NO_MORE)
    {
        if ( ( ~tmpRule->rule.mask & tmpRule->rule.glort ) ==
             ( ~tmpRule->rule.mask & glort ) )
        {
            found = TRUE;
            break;
        }

        err = fmTreeIterNext( &iter, &tmpId, (void **) &tmpRule );
    }

    if ( !found )
    {
        FM_LOG_DEBUG(FM_LOG_CAT_STACKING,
                     "Glort 0x%x was not matched to a forwarding rule\n",
                     glort);

        FM_LOG_EXIT(FM_LOG_CAT_STACKING, FM_ERR_NO_FORWARDING_RULES);
    }

    FM_LOG_DEBUG(FM_LOG_CAT_STACKING,
                 "Glort 0x%x was matched to forwarding rule #%lld\n",
                 glort,
                 tmpId);

    camEntry = ( (fm10000_forwardRuleInternal *) tmpRule->extension )->camEntry;

    /***************************************************
     * Find an unused logical port number.
     **************************************************/
    *logicalPort = fmFindUnusedLogicalPorts(sw, 1);
    if (*logicalPort == -1)
    {
        FM_LOG_EXIT(FM_LOG_CAT_STACKING, FM_ERR_NO_FREE_RESOURCES);
    }

    /***************************************************
     * Create an entry for the remote logical port.
     **************************************************/
    portPtr = (fm_port *) fmAlloc(sizeof(fm_port));
    if (portPtr == NULL)
    {
        FM_LOG_EXIT(FM_LOG_CAT_STACKING, FM_ERR_NO_MEM);
    }

    FM_MEMSET_S( portPtr, sizeof(fm_port), 0, sizeof(fm_port) );

    portExt = (fm10000_port *) fmAlloc( sizeof(fm10000_port) );
    if (portExt == NULL)
    {
        fmFree(portPtr);
        FM_LOG_EXIT(FM_LOG_CAT_STACKING, FM_ERR_NO_MEM);
    }

    FM_MEMSET_S( portExt, sizeof(fm10000_port), 0, sizeof(fm10000_port) );

    portPtr->switchPtr   = switchPtr;
    portPtr->portNumber  = *logicalPort;
    portPtr->portType    = FM_PORT_TYPE_REMOTE;
    portPtr->extension   = portExt;
    portPtr->lagIndex    = -1;
    portPtr->memberIndex = -1;
    portPtr->glort       = glort;
    portPtr->swagPort    = -1;
    portPtr->camEntry    = camEntry;

    /* Increase the CAM reference use count */
    portPtr->camEntry->useCount++;

    portPtr->destEntry  = NULL;
    portPtr->numDestEntries = 0;

    /* Initialize multicast group membership list */
    fmTreeInit(&portPtr->mcastGroupList);

    /* Set the default to down, the application must
     * bring it up, similar to physical port. */
    portPtr->mode = FM_PORT_STATE_DOWN;

    /***************************************************
     * Add it to the logical port table.
     **************************************************/
    switchPtr->portTable[*logicalPort] = portPtr;

    FM_LOG_EXIT(FM_LOG_CAT_STACKING, err);

}   /* end fm10000CreateLogicalPortForGlort */
Exemplo n.º 4
0
/** MoveListenersToReplicationGroup
 * \ingroup intMulticast
 *
 * \desc            Move a group of listeners to a replication group.
 *
 * \param[in]       sw is the switch number.
 * 
 * \param[in]       repliGroup is the replication group number.
 *
 * \param[in]       mcastGroup points to the multicast group entry,
 *
 * \return          FM_OK if successful.
 * \return          FM_ERR_INVALID_PORT if a listener port is invalid
 *
 *****************************************************************************/
static fm_status MoveListenersToReplicationGroup(fm_int                sw, 
                                                 fm_int                repliGroup,
                                                 fm_intMulticastGroup *mcastGroup)
{ 
    fm_status                err;
    fm_switch *              switchPtr;
    fm_int                   mcastLogicalPort;
    fm_intMulticastListener *intListener;
    fm_int                   listenerCount;
    fm_int                   i;
    fm_treeIterator          iter;
    fm_uint64                key;
    fm10000_mtableEntry      listener;
    fm_port                 *portPtr;
    fm_int                   port;

    FM_LOG_ENTRY( FM_LOG_CAT_MULTICAST,
                 "sw=%d repliGroup=%d mcastLogPort=%d\n",
                 sw, repliGroup, mcastGroup->logicalPort);

    switchPtr        = GET_SWITCH_PTR(sw);
    err              = FM_OK;
    listenerCount    = 0;
    mcastLogicalPort = mcastGroup->logicalPort;

    /* Get the number of listeners to move */
    listenerCount = (fm_int) fmTreeSize(&mcastGroup->listenerTree);

    if (listenerCount > 0)
    {
        i = 0;
        fmTreeIterInit(&iter, &mcastGroup->listenerTree);

        while (1)
        {
            err = fmTreeIterNext(&iter, &key, (void **) &intListener);

            if (err != FM_OK)
            {
                if (err != FM_ERR_NO_MORE)
                {
                    FM_LOG_ABORT(FM_LOG_CAT_MULTICAST, err);
                }

                err = FM_OK;
                break;
            }

            if (intListener->listener.listenerType != FM_MCAST_GROUP_LISTENER_PORT_VLAN)
            {
                continue;
            }

            if (i++ >= listenerCount)
            {
                err = FM_FAIL;
                FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_MULTICAST, err);
            }

            listener.vlan       = intListener->listener.info.portVlanListener.vlan;
            listener.vlanUpdate = TRUE;

            if ( (intListener->listener.info.portVlanListener.vlan == 0)
                 && (intListener->listener.info.portVlanListener.port == -1) )
            {
                port    = switchPtr->cpuPort;
                portPtr = NULL;
                
            }
            else
            {
                port = intListener->listener.info.portVlanListener.port;
                portPtr = GET_PORT_PTR(sw, port);

                if (!portPtr)
                {
                    FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_MULTICAST,
                                        FM_ERR_INVALID_PORT);
                }
            }

            if ( (portPtr != NULL) && (portPtr->portType == FM_PORT_TYPE_VIRTUAL) )
            {
                err = fm10000MapVirtualGlortToLogicalPort(sw,
                                                          portPtr->glort,
                                                          &listener.port);
                FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_MULTICAST, err);
                
                listener.dglortUpdate = TRUE;
                listener.dglort       = portPtr->glort;

               if (intListener->listener.info.portVlanListener.vlan == 0)
               {
                   listener.vlanUpdate = FALSE;
               }

            }
            else
            {
                listener.port         = port;
                listener.dglortUpdate = FALSE;
                listener.dglort =     0;
            }
           
            err = fm10000MTableAddListener(sw, 
                                           mcastLogicalPort, 
                                           repliGroup, 
                                           listener);
            FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_MULTICAST, err);
        }

        /* Sanity check */
        if (i != listenerCount)
        {
            err = FM_FAIL;
            FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_MULTICAST, err);
        }
    }

ABORT:

    FM_LOG_EXIT(FM_LOG_CAT_MULTICAST, err);

}   /* end MoveListenersToReplicationGroup */
Exemplo n.º 5
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 */