예제 #1
0
/** fmResetLBGMember
 * \ingroup intLbg
 *
 * \desc            Resets LBGMember to initial values.
 *
 * \param[out]      lbgMember is the LBG member which should be reset.
 *
 * \return          FM_OK if successful.
 *
 *****************************************************************************/
fm_status fmResetLBGMember(fm_LBGMember *lbgMember)
{
    fm_status  err = FM_OK;

    FM_LOG_ENTRY_VERBOSE(FM_LOG_CAT_LBG,
                         "lbgMember=%p\n",
                         (void *) lbgMember );

    if (lbgMember == NULL)
    {
        err = FM_ERR_INVALID_ARGUMENT;
        FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_LBG, err);
    }

    /* Reset lbgMember to default values */
    FM_CLEAR(*lbgMember);
    lbgMember->lbgMemberType = FM_LBG_MEMBER_TYPE_PORT;
    lbgMember->port          = FM_PORT_DROP;
    lbgMember->mcastGroup    = -1;
    lbgMember->l234Lbg       = -1;

ABORT:
    FM_LOG_EXIT_VERBOSE(FM_LOG_CAT_LBG, err);

}   /* end fmResetLBGMember */
예제 #2
0
/** fmInitDynamicLoadLibs
 * \ingroup intAlosDynLoadLib
 *
 * \desc            Initialize ALOS Dynamic Load Library support.
 *
 * \param[in]       None.
 *
 * \return          FM_ERR_UNINITIALIZED if fmRootAlos has not been initialized.
 * \return          FM_OK if successful.
 * \return          FM_ERR_NO_MEM if unable to allocate memory.
 * \return          FM_ERR_LOCK_INIT if unable to initialize the access lock.
 *
 *****************************************************************************/
fm_status fmInitDynamicLoadLibs(void)
{
    fm_status err;

    FM_LOG_ENTRY(FM_LOG_CAT_ALOS_DLLIB, "(no arguments)\n");

    if (fmRootAlos == NULL)
    {
        FM_LOG_EXIT(FM_LOG_CAT_ALOS_DLLIB, FM_ERR_UNINITIALIZED);
    }

    FM_CLEAR(fmRootAlos->dlLibs);

    err = fmCreateLock("DynLibLock", &fmRootAlos->dlAccessLock);

    FM_LOG_EXIT_ON_ERR(FM_LOG_CAT_ALOS_DLLIB, err);

    FM_LOG_EXIT(FM_LOG_CAT_ALOS_DLLIB, err);

}   /* end fmInitDynamicLoadLibs */
예제 #3
0
/** fm10000InitSFlows
 * \ingroup intSflow
 *
 * \desc            Initializes the SFlow subsystem.
 *
 * \param[in]       sw is the switch to operate on.
 *
 * \return          FM_OK if successful.
 *
 *****************************************************************************/
fm_status fm10000InitSFlows(fm_int sw)
{
    fm10000_sflowEntry *sflowEntry;
    fm_int              sflowId;

    FM_LOG_ENTRY(FM_LOG_CAT_SFLOW, "sw=%d\n", sw);

    for (sflowId = 0 ; sflowId < FM10000_MAX_SFLOWS ; ++sflowId)
    {
        sflowEntry = GetSflowEntry(sw, sflowId);

        FM_CLEAR(*sflowEntry);

        sflowEntry->mirrorId   = GET_SWITCH_PTR(sw)->mirrorTableSize
                                  - sflowId - 1;
        sflowEntry->isValid    = FALSE;
        sflowEntry->trapCodeId = sflowId;
    }

    FM_LOG_EXIT(FM_LOG_CAT_SFLOW, FM_OK);

}   /* end fm10000InitSFlows */
예제 #4
0
/** fmOpenDynamicLoadLibs
 * \ingroup alosDynLoadLib
 *
 * \desc            Open a Dynamic Load Library.
 *
 * \param[in]       filePath points to the string containing the library path.
 *
 * \param[out]      handle points to caller-provided memory into which the
 *                  dynamic-load-library's handle will be written.
 *
 * \return          FM_ERR_UNINITIALIZED if the ALOS subsystem has not been
 *                  properly initialized.
 * \return          FM_ERR_INVALID_ARGUMENT if one of the arguments is invalid.
 * \return          FM_OK if successful.
 * \return          FM_ERR_NO_MEM if unable to allocate memory.
 * \return          FM_ERR_TABLE_FULL if the dynamic-load library table is full.
 * \return          FM_ERR_NOT_FOUND if the dynamic-load library open failed.
 *
 *****************************************************************************/
fm_status fmOpenDynamicLoadLibrary(fm_text filePath, fm_int *handle)
{
    fm_status      err;
    fm_int         index;
    fm_dynLoadLib *lib;
    fm_int         availIndex;
    fm_int         pathLen;
    fm_bool        lockTaken;
    fm_bool        libAllocated;
    void *         libHandle;

    FM_LOG_ENTRY( FM_LOG_CAT_ALOS_DLLIB,
                  "filePath = %p (%s), handle = %p\n",
                  (void *) filePath,
                  (filePath != NULL) ? filePath : "<NULL>",
                  (void *) handle );

    lib          = NULL;
    availIndex   = -1;
    lockTaken    = FALSE;
    libAllocated = FALSE;

    if (fmRootAlos == NULL)
    {
        FM_LOG_EXIT(FM_LOG_CAT_ALOS_DLLIB, FM_ERR_UNINITIALIZED);
    }

    if (filePath == NULL)
    {
        FM_LOG_EXIT(FM_LOG_CAT_ALOS_DLLIB, FM_ERR_INVALID_ARGUMENT);
    }

    if (handle == NULL)
    {
        FM_LOG_EXIT(FM_LOG_CAT_ALOS_DLLIB, FM_ERR_INVALID_ARGUMENT);
    }

    pathLen = strlen(filePath);

    if (pathLen <= 0)
    {
        FM_LOG_EXIT(FM_LOG_CAT_ALOS_DLLIB, FM_ERR_INVALID_ARGUMENT);
    }

    err = fmCaptureLock(&fmRootAlos->dlAccessLock, FM_WAIT_FOREVER);

    FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_ALOS_DLLIB, err);

    lockTaken = TRUE;

    for (index = 0 ; index < FM_ALOS_INTERNAL_DYN_LOAD_LIBS ; index++)
    {
        if (fmRootAlos->dlLibs[index] == NULL)
        {
            if (availIndex < 0)
            {
                availIndex = index;
            }
        }
        else
        {
            lib = fmRootAlos->dlLibs[index];

            if ( strcmp(filePath, lib->filePath) == 0 )
            {
                break;
            }
        }
    }

    if (index >= FM_ALOS_INTERNAL_DYN_LOAD_LIBS)
    {
        index = availIndex;
    }

    if (index < 0)
    {
        err = FM_ERR_TABLE_FULL;
        FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_ALOS_DLLIB, err);
    }

    lib = fmRootAlos->dlLibs[index];

    if (lib == NULL)
    {
        lib = fmAlloc( sizeof(fm_dynLoadLib) );

        if (lib == NULL)
        {
            err = FM_ERR_NO_MEM;
            FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_ALOS_DLLIB, err);
        }

        libAllocated = TRUE;

        FM_CLEAR(*lib);

        lib->filePath = fmAlloc( pathLen + 1 );

        if (lib->filePath == NULL)
        {
            err = FM_ERR_NO_MEM;
            FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_ALOS_DLLIB, err);
        }

        FM_STRNCPY_S(lib->filePath, pathLen + 1, filePath, pathLen + 1 );

        lib->useCount = 0;

        fmRootAlos->dlLibs[index] = lib;
    }

    if ( ( fmProcessDynLoadLibStatus & (1 << index) ) == 0 )
    {
        libHandle = dlopen(filePath, RTLD_NOW | RTLD_GLOBAL);

        if (libHandle == NULL)
        {
            char *errMsg = dlerror();
            FM_LOG_ERROR(FM_LOG_CAT_ALOS_DLLIB,
                         "Error opening library %s: %s\n",
                         filePath,
                         errMsg);

            err = FM_ERR_NOT_FOUND;
            FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_ALOS_DLLIB, err);
        }

        ProcessHandles[index] = libHandle;

        lib->useCount++;
        
        fmProcessDynLoadLibStatus |= FM_LITERAL_U64(1) << index;
    }

    *handle = index;
    err     = FM_OK;


ABORT:

    if ( (err != FM_OK) && libAllocated )
    {
        if (lib->filePath != NULL)
        {
            fmFree(lib->filePath);
        }

        fmFree(lib);
    }

    if (lockTaken)
    {
        fmReleaseLock(&fmRootAlos->dlAccessLock);
    }

    FM_LOG_EXIT(FM_LOG_CAT_ALOS_DLLIB, err);

}   /* end fmOpenDynamicLoadLibrary */
예제 #5
0
/** fmRawPacketSocketReceivePackets
 * \ingroup intPlatformCommon
 *
 * \desc            Handles reception of packets by raw packet socket.
 *
 * \param[in]       args is a pointer to the switch number.
 *
 * \return          FM_OK if successful.
 *
 *****************************************************************************/
void * fmRawPacketSocketReceivePackets(void *args)
{
    fm_thread *        thread;
    fm_int             sw;
    fm_buffer *        recvChainHead = NULL;
    fm_buffer *        nextBuffer;
    struct pollfd      rfds;
    struct msghdr      msg;
    struct iovec       iov[UIO_MAXIOV];
    struct ifreq       ifr;
    fm_int             retval;
    fm_int             availableBuffers;
    fm_int             len;
    fm_int             iov_offset;
    fm_int             iov_count = 0;
    fm_int             maxMtu = 0;
    fm_int             newMtu;
    fm_status          status;
    char               strErrBuf[FM_STRERROR_BUF_SIZE];
    errno_t            strErrNum;
    fm_byte            rawTS[8];
    fm_pktSideBandData sbData;
#ifdef ENABLE_TIMESTAMP
    struct cmsghdr *   cmsg;
    union {
        struct cmsghdr  cm;
        char            control[512];

    } control;
#endif
    

    thread = FM_GET_THREAD_HANDLE(args);
    sw     = *(FM_GET_THREAD_PARAM(fm_int, args));

    FM_NOT_USED(thread);    /* If logging is disabled, thread won't be used */

    FM_LOG_ENTRY(FM_LOG_CAT_SWITCH,
                 "thread = %s, sw = %d\n",
                 thread->name,
                 sw);

    /* initialize the message header */
    FM_CLEAR(msg);
    msg.msg_name = NULL; /* Optional field */
    msg.msg_namelen = 0;
    msg.msg_iov = iov;
    msg.msg_iovlen = 0;
    msg.msg_flags = 0;
#ifdef ENABLE_TIMESTAMP
    msg.msg_control = &control;
    msg.msg_controllen = sizeof(control);
#endif

    /* Setup the name of the interface */
    FM_STRNCPY_S(ifr.ifr_name, 
                 sizeof(ifr.ifr_name), 
                 GET_PLAT_STATE(sw)->ifaceName, 
                 sizeof(GET_PLAT_STATE(sw)->ifaceName));

    /* Prepare the pollfd struct */
    rfds.fd = GET_PLAT_STATE(sw)->rawSocket;
    rfds.events = POLLIN;
    rfds.revents = 0;

    /**************************************************
     * Loop forever calling packet receive handler.
     **************************************************/

    while (TRUE)
    {
        errno = 0;
        retval = poll(&rfds, 1, FM_FDS_POLL_TIMEOUT_USEC);

        if (retval == -1)
        {
            strErrNum = FM_STRERROR_S(strErrBuf, FM_STRERROR_BUF_SIZE, errno);
            if (strErrNum == 0)
            {
                FM_LOG_WARNING(FM_LOG_CAT_SWITCH,
                               "ERROR: select failed: %s!\n",
                               strErrBuf);
            }
            else
            {
                FM_LOG_WARNING(FM_LOG_CAT_SWITCH,
                               "ERROR: select failed: %d!\n",
                               errno);
            }

            /* Switch was removed, kill the thread */
            if (GET_SWITCH_PTR(sw) == NULL)
            {
                break;
            }

            continue;
        }
        else if (!retval)
        {
            /* Switch was removed, kill the thread */
            if (GET_SWITCH_PTR(sw) == NULL)
            {
                break;
            }

            continue; /* timeout */
        }

        /* get the number of available buffers from the buffer manager*/
        fmPlatformGetAvailableBuffers(&availableBuffers);

        if (availableBuffers <= FM_RECV_BUFFER_THRESHOLD)
        {
            /* wait for buffer to come back, before dequeueing data */
            fmYield();
            continue;
        }

        if (ioctl(GET_PLAT_STATE(sw)->rawSocket, SIOCGIFMTU, &ifr) == -1)
        {
             FM_LOG_WARNING(FM_LOG_CAT_SWITCH,
                            "WARNING: failed to read netdev MTU\n");
             continue;
        }
        else
        {
            newMtu = ifr.ifr_mtu;
        }

        /* MTU Size change */
        if (newMtu != maxMtu)
        {
            if (recvChainHead != NULL)
            {
                /* release the existing buffer chain */
                status = fmFreeBufferChain(FM_FIRST_FOCALPOINT, recvChainHead);

                if (status != FM_OK)
                {
                    FM_LOG_ERROR( FM_LOG_CAT_SWITCH,
                                 "Unable to release prior buffer chain, "
                                 "status = %d (%s)\n",
                                 status,
                                 fmErrorMsg(status) );
                }

                recvChainHead = NULL;
            }

            /* compute new buffer count */
            iov_count = newMtu / FM_BUFFER_SIZE_BYTES;
            if (newMtu % FM_BUFFER_SIZE_BYTES)
            {
                iov_count++;
            }

            maxMtu = newMtu;
        }

        if (recvChainHead == NULL)
        {
            /* allocate a new buffer chain and initialize iovec array */
            msg.msg_iovlen = 0;
            
            /* 8-Byte Timestamp IOV */
            iov[msg.msg_iovlen].iov_base = rawTS;
            iov[msg.msg_iovlen].iov_len  = sizeof(rawTS);
            msg.msg_iovlen++;

            for (iov_offset = 0 ; iov_offset < iov_count ; iov_offset++)
            {
                do
                {
                    nextBuffer = fmAllocateBuffer(FM_FIRST_FOCALPOINT);

                    if (nextBuffer == NULL)
                    {
                        /* Wait a little while for buffer to return */
                        fmDbgGlobalDiagCountIncr(FM_GLOBAL_CTR_RX_OUT_OF_BUFFERS,
                                                 1);
                        fmYield();
                    }
                }
                while (nextBuffer == NULL);

                if (recvChainHead == NULL)
                {
                    recvChainHead    = nextBuffer;
                    nextBuffer->next = NULL;
                }
                else
                {
                    status = fmAddBuffer(recvChainHead, nextBuffer);

                    if (status != FM_OK)
                    {
                        FM_LOG_ERROR( FM_LOG_CAT_SWITCH,
                                     "Unable to add buffer %d (%p) to chain %p\n",
                                     iov_offset,
                                     (void *) nextBuffer,
                                     (void *) recvChainHead );
                        break;
                    }
                }

                iov[msg.msg_iovlen].iov_base = nextBuffer->data;
                iov[msg.msg_iovlen].iov_len  = FM_BUFFER_SIZE_BYTES;
                msg.msg_iovlen++;
            }
        }

        /* now receive from the driver */
        len = recvmsg(GET_PLAT_STATE(sw)->rawSocket,
                      &msg,
                      0);

        if (len == -1)
        {
            continue;
        }

#ifdef ENABLE_TIMESTAMP
        for (cmsg = CMSG_FIRSTHDR(&msg);
             cmsg;
             cmsg = CMSG_NXTHDR(&msg, cmsg)) 
        {
            if ( (cmsg->cmsg_level == SOL_SOCKET) &&
                 (cmsg->cmsg_type  == SO_TIMESTAMPING) &&
                 (cmsg->cmsg_len   == CMSG_LEN(sizeof(struct timespec) * 3)) )
            {
                    struct timespec *stamp =
                        (struct timespec *)CMSG_DATA(cmsg);
                    /* cmsg has 3 different timestamps. Timestamp we are interested is 
                     * located in index 2 */
                    sbData.ingressTimestamp.seconds     = ( (fm_int64)(stamp[2].tv_sec) );
                    sbData.ingressTimestamp.nanoseconds = ( (fm_int64)(stamp[2].tv_nsec) );
            }
            else
            {
                    FM_LOG_WARNING(FM_LOG_CAT_PLATFORM, 
                                  "Unknown control message of level %d type %d len %zu  received\n",
                                  cmsg->cmsg_level, 
                                  cmsg->cmsg_type,
                                  cmsg->cmsg_len);
            }
        }
#endif

        /* Remove the timestamp's length to get the length of the actual
         * packet */
        len -= sizeof(rawTS);

        /* The raw socket does not carry the FCS in either tx or rx, however
         * the API expects it to be present. Because the API clears the 
         * FCS value before sending the packet event to the application, don't 
         * bother about setting the correct FCS value and just increment the 
         * length. The FCS value is undefined (whatever is in the fm_buffer at 
         * the FCS position). */
        len += 4;

        /* fill in the used buffer sizes */
        nextBuffer = recvChainHead;

        while (nextBuffer != NULL)
        {
            if (len > FM_BUFFER_SIZE_BYTES)
            {
                nextBuffer->len = FM_BUFFER_SIZE_BYTES;
            }
            else
            {
                nextBuffer->len = len;
            }

            len -= nextBuffer->len;

            if ( (len <= 0) && (nextBuffer->next != NULL) )
            {
                status = fmFreeBufferChain(FM_FIRST_FOCALPOINT,
                                           nextBuffer->next);

                if (status != FM_OK)
                {
                    FM_LOG_ERROR( FM_LOG_CAT_SWITCH,
                                 "Unable to release unused buffer chain, "
                                 "status = %d (%s)\n",
                                 status,
                                 fmErrorMsg(status) );
                }

                nextBuffer->next = NULL;
            }

            nextBuffer = nextBuffer->next;
        }

        if (recvChainHead == NULL)
        {
            continue;
        }

        /* Store the raw timestamp in 64b format */
        sbData.rawTimeStamp  = ((fm_uint64) (rawTS[0] & 0xFF)) << 56;
        sbData.rawTimeStamp |= ((fm_uint64) (rawTS[1] & 0xFF)) << 48;
        sbData.rawTimeStamp |= ((fm_uint64) (rawTS[2] & 0xFF)) << 40;
        sbData.rawTimeStamp |= ((fm_uint64) (rawTS[3] & 0xFF)) << 32;
        sbData.rawTimeStamp |= ((fm_uint64) (rawTS[4] & 0xFF)) << 24;
        sbData.rawTimeStamp |= ((fm_uint64) (rawTS[5] & 0xFF)) << 16;
        sbData.rawTimeStamp |= ((fm_uint64) (rawTS[6] & 0xFF)) << 8;
        sbData.rawTimeStamp |= ((fm_uint64) (rawTS[7] & 0xFF));

        /* Don't provide an ISL tag pointer, let the API handle the ISL
         * tag information (included in the fm_buffer chain). */
        status = fmPlatformReceiveProcessV2(sw,
                                            recvChainHead,
                                            NULL,
                                            &sbData);

        if (status != FM_OK)
        {
            FM_LOG_ERROR( FM_LOG_CAT_SWITCH,
                         "Returned error status %d "
                         "(%s)\n",
                         status,
                         fmErrorMsg(status) );


        }
        /* Buffer chain has now been consumed */
        recvChainHead = NULL; 

    }   /* end while (TRUE) */

    fmExitThread(thread);

    return NULL;

}   /* end fmRawPacketSocketReceivePackets */
예제 #6
0
/** fmRawPacketSocketSendPackets
 * \ingroup intPlatformCommon
 *
 * \desc            When called, iterates through the packet queue and
 *                  continues to send packets until either the queue empties.
 *
 * \param[in]       sw refers to the switch number to send packets to.
 *
 * \return          FM_OK if successful.
 *
 *****************************************************************************/
fm_status fmRawPacketSocketSendPackets(fm_int sw)
{
    fm_status               err = FM_OK;
    fm_switch *             switchPtr;
    fm_packetHandlingState *pktState;
    fm_packetQueue *        txQueue;
    fm_packetEntry *        packet;
    fm_int32                rc;
    fm_buffer               *sendBuf;
    struct msghdr           msg;
    struct iovec            iov[UIO_MAXIOV];
    fm_islTag               islTag;
    fm_uint32               fcs;
    fm_uint64               rawTS;
    char                    strErrBuf[FM_STRERROR_BUF_SIZE];
    errno_t                 strErrNum;
    struct ifreq            ifr;

    FM_LOG_ENTRY(FM_LOG_CAT_EVENT_PKT_TX, "sw = %d\n", sw);

    switchPtr = GET_SWITCH_PTR(sw);
    pktState  = GET_PLAT_PKT_STATE(sw);

    if (GET_PLAT_STATE(sw)->rawSocket <= 0)
    {
        FM_LOG_ERROR(FM_LOG_CAT_EVENT_PKT_TX, 
                     "Socket is not initialized.\n");
        FM_LOG_EXIT(FM_LOG_CAT_EVENT_PKT_TX, FM_ERR_UNINITIALIZED);
    }

    /* initialize the message header */
    FM_CLEAR(msg);
    msg.msg_name = NULL; /* Optional field */
    msg.msg_namelen = 0;
    msg.msg_iov = iov;
    msg.msg_iovlen = 0;
    msg.msg_flags = 0;

    FM_STRNCPY_S(ifr.ifr_name, IF_NAMESIZE, GET_PLAT_STATE(sw)->ifaceName, IF_NAMESIZE);

    txQueue = &pktState->txQueue;
    fmPacketQueueLock(txQueue);

    if (ioctl(GET_PLAT_STATE(sw)->rawSocket, SIOCGIFFLAGS, &ifr) == -1)
    {
        strErrNum = FM_STRERROR_S(strErrBuf, FM_STRERROR_BUF_SIZE, errno);
        if (strErrNum == 0)
        {
            FM_LOG_FATAL(FM_LOG_CAT_EVENT_PKT_TX, 
                         "Failed to get socket %d flags for device %s: %s\n",
                         GET_PLAT_STATE(sw)->rawSocket,
                         ifr.ifr_name,
                         strErrBuf);
        }
        else
        {
            FM_LOG_FATAL(FM_LOG_CAT_EVENT_PKT_TX, 
                         "Failed to get socket %d flags for device %s: %d\n",
                         GET_PLAT_STATE(sw)->rawSocket,
                         ifr.ifr_name,
                         errno);
        }
        switchPtr->transmitterLock = TRUE;
        err = FM_FAIL;
        FM_LOG_ABORT(FM_LOG_CAT_EVENT_PKT_TX, err);
    }

    if ((ifr.ifr_flags & IFF_RUNNING) == 0)
    {    
        FM_LOG_WARNING(FM_LOG_CAT_EVENT_PKT_TX,
                       "Network device %s resources are not allocated.\n",
                       ifr.ifr_name);
        switchPtr->transmitterLock = TRUE;
        err = FM_FAIL;
        FM_LOG_ABORT(FM_LOG_CAT_EVENT_PKT_TX, err);
    }

    /* Iterate through the packets in the tx queue */
    for ( ;
          txQueue->pullIndex != txQueue->pushIndex ;
          txQueue->pullIndex = (txQueue->pullIndex + 1) % FM_PACKET_QUEUE_SIZE)
    {
        packet = &txQueue->packetQueueList[txQueue->pullIndex];

        FM_LOG_DEBUG(FM_LOG_CAT_EVENT_PKT_TX,
                     "sending packet in slot %d, length=%d tag=%d fcs=%08x\n",
                     txQueue->pullIndex, packet->length,
                     packet->suppressVlanTag, packet->fcsVal);
        msg.msg_iovlen = 0;

        /* Add the 8 byte timetag iovec. Note that the value is ignored
         * by the driver as it gets overwritten by the PEP. */
        rawTS = 0;
        iov[msg.msg_iovlen].iov_base = &rawTS;
        iov[msg.msg_iovlen].iov_len = sizeof(rawTS);
        msg.msg_iovlen++;

        if (packet->islTagFormat == FM_ISL_TAG_F56)
        {
            /* Add the FTAG (F56) iovec */
            islTag.f56.tag[0] = htonl(packet->islTag.f56.tag[0]);
            islTag.f56.tag[1] = htonl(packet->islTag.f56.tag[1]);
            iov[msg.msg_iovlen].iov_base = &islTag.f56.tag[0];
            iov[msg.msg_iovlen].iov_len = FM_F56_BYTE_LEN;
            msg.msg_iovlen++;
        }
        
        /* iterate through all buffers */
        for ( sendBuf = packet->packet ; sendBuf ; sendBuf = sendBuf->next )
        {
            /* if first buffer ... */
            if (sendBuf == packet->packet)
            {
                /* Cannot modify the send buffer, since the same buffer can be
                 * used multiple times to send to multiple ports */

                /* second iovec is the mac header */
                iov[msg.msg_iovlen].iov_base = sendBuf->data;
                iov[msg.msg_iovlen].iov_len = FM_MAC_HDR_BYTE_LEN;
                msg.msg_iovlen++;

                if (packet->islTagFormat == FM_ISL_TAG_F64)
                {
                    /* Insert the F64 ISL tag */
                    islTag.f64.tag[0] = htonl(packet->islTag.f64.tag[0]);
                    islTag.f64.tag[1] = htonl(packet->islTag.f64.tag[1]);
                    iov[msg.msg_iovlen].iov_base = &islTag.f64.tag[0];
                    iov[msg.msg_iovlen].iov_len = FM_F64_BYTE_LEN;
                    msg.msg_iovlen++;
                }

                /* Third is the data in the first chain */
                if (packet->suppressVlanTag)
                {
                    iov[msg.msg_iovlen].iov_base = &sendBuf->data[4];
                    iov[msg.msg_iovlen].iov_len = sendBuf->len-16;
                    msg.msg_iovlen++;
                }
                else
                {
                    iov[msg.msg_iovlen].iov_base = &sendBuf->data[3];
                    iov[msg.msg_iovlen].iov_len = sendBuf->len-12;
                    msg.msg_iovlen++;
                }
            }
            else
            {
                /* The rest of the chain */
                iov[msg.msg_iovlen].iov_base = sendBuf->data;
                iov[msg.msg_iovlen].iov_len = sendBuf->len;
                msg.msg_iovlen++;
            }

        }   /* end for (...) */

        /* Append user-supplied FCS value to packet. */
        if (pktState->sendUserFcs)
        {
            fcs = htonl(packet->fcsVal);
            iov[msg.msg_iovlen].iov_base = &fcs;
            iov[msg.msg_iovlen].iov_len = sizeof(fcs);
            msg.msg_iovlen++;
        }

        /* now send it to the driver */
        errno = 0;
        rc = sendmsg(GET_PLAT_STATE(sw)->rawSocket, &msg, MSG_DONTWAIT);
        if (rc == -1)
        {
            switchPtr->transmitterLock = TRUE;
            if (errno != EWOULDBLOCK)
            {
                err = FM_FAIL;

                FM_LOG_DEBUG(FM_LOG_CAT_EVENT_PKT_TX,
                             "rawSocket %d\n",
                             GET_PLAT_STATE(sw)->rawSocket);

                strErrNum = FM_STRERROR_S(strErrBuf,
                                          FM_STRERROR_BUF_SIZE,
                                          errno);
                if (strErrNum == 0)
                {
                    FM_LOG_ERROR(FM_LOG_CAT_EVENT_PKT_TX,
                                 "sendmsg failed: %s - errno %d\n",
                                 strErrBuf,
                                 errno);
                }
                else
                {
                    FM_LOG_ERROR(FM_LOG_CAT_EVENT_PKT_TX, 
                                 "sendmsg failed - errno %d\n", errno);
                }
            }
            if (errno == EMSGSIZE)
            {
                switchPtr->transmitterLock = FALSE;
            }
            else
            {
                goto ABORT;
            }
        }
        else
        {
            FM_LOG_DEBUG(FM_LOG_CAT_EVENT_PKT_TX, "%d bytes were sent\n", rc);

            switchPtr->transmitterLock = FALSE;
            fmDbgDiagCountIncr(sw, FM_CTR_TX_PKT_COMPLETE, 1);
        }

        /**************************************************
         * free buffer only when
         * (1) sending to a single port;
         * or (2) this is the last packet of multiple 
         * identical packets
         **************************************************/

        if (packet->freePacketBuffer)
        {
            /* ignore the error code since it's better to continue */
            (void) fmFreeBufferChain(sw, packet->packet);

            fmDbgGlobalDiagCountIncr(FM_GLOBAL_CTR_TX_BUFFER_FREES, 1);
        }
    }

ABORT:
    fmPacketQueueUnlock(txQueue);

    FM_LOG_EXIT(FM_LOG_CAT_EVENT_PKT_TX, err);

}   /* end fmRawPacketSocketSendPackets */
예제 #7
0
/** fmRawPacketSocketHandlingInitialize
 * \ingroup intPlatformCommon
 *
 * \desc            Initializes the raw packet socket transfer module.
 *
 * \param[in]       sw is the switch number to initialize.
 * 
 * \param[in]       hasFcs is TRUE if the packet includes the FCS field.
 * 
 * \param[in]       iface is a string containing the netdev's interface name
 *                  through which the packets should be sent / received.
 *
 * \return          FM_OK if successful.
 *
 *****************************************************************************/
fm_status fmRawPacketSocketHandlingInitialize(fm_int  sw, 
                                              fm_bool hasFcs, 
                                              fm_text iface)
{
    fm_status                err = FM_OK;
    fm_int                   rawSock = -1;
    struct ifreq             ifr;
    struct sockaddr_ll       sa;
    struct ethtool_value     ethValue;
#ifdef ENABLE_TIMESTAMP
    struct ifreq             hwtstamp;
    struct hwtstamp_config   hwconfig;
    struct hwtstamp_config   hwconfig_requested;
    fm_int                   val;
    socklen_t                len;
    fm_int                   so_timestamping_flags;
    struct cmsghdr *         cmsg;
#endif
    char                     strErrBuf[FM_STRERROR_BUF_SIZE];
    errno_t                  strErrNum;
    fm_switch               *switchPtr;

    FM_LOG_ENTRY(FM_LOG_CAT_PLATFORM,
                 "sw=%d hasFcs=%s\n",
                 sw,
                 FM_BOOLSTRING(hasFcs));

    if (iface == NULL)
    {
        err = FM_ERR_INVALID_ARGUMENT;
        FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_PLATFORM, err);
    }

    err = fmGenericPacketHandlingInitializeV2(sw, hasFcs);
    FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_PLATFORM, err);

    /* initialize the raw packet socket */
    rawSock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_XDSA));
    if (rawSock == -1)
    {
        FM_LOG_FATAL(FM_LOG_CAT_PLATFORM, 
                     "couldn't create raw packet socket\n");
        err = FM_FAIL;
        FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_PLATFORM, err);
    }

    /* retrieve ethernet interface index */
    FM_STRNCPY_S(ifr.ifr_name, IF_NAMESIZE, iface, IF_NAMESIZE);
    if (ioctl(rawSock, SIOCGIFINDEX, &ifr) == -1) 
    {
        FM_LOG_FATAL(FM_LOG_CAT_PLATFORM, 
                     "Failed to retrieve index for interface %s\n",
                     iface);
        err = FM_ERR_INVALID_ARGUMENT;
        FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_PLATFORM, err);
    }

    /* initialize sockaddr_ll */
    FM_CLEAR(sa);
    sa.sll_family   = PF_PACKET;
    sa.sll_protocol = htons(ETH_P_XDSA);
    sa.sll_ifindex  = ifr.ifr_ifindex;
    if (bind(rawSock, (struct sockaddr *)&sa, sizeof(sa)) < 0)
    {
        FM_LOG_FATAL(FM_LOG_CAT_PLATFORM, 
                     "Failed to bind to the raw packet socket\n");
        err = FM_FAIL;
        FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_PLATFORM, err);
    }
    
#ifdef ENABLE_TIMESTAMP
    /*Set timestamp related configurations */
    FM_CLEAR(hwconfig);
    FM_CLEAR(hwconfig_requested);
    FM_CLEAR(hwtstamp);

    strncpy(hwtstamp.ifr_name, iface, IF_NAMESIZE);
    hwtstamp.ifr_data = (void *)&hwconfig;
    hwconfig.rx_filter = HWTSTAMP_FILTER_ALL;
    hwconfig_requested = hwconfig;

    errno = 0;
    if (ioctl(rawSock, SIOCSHWTSTAMP, &hwtstamp) < 0) 
    {
        strErrNum = FM_STRERROR_S(strErrBuf, FM_STRERROR_BUF_SIZE, errno);
        if (strErrNum == 0)
        {
            FM_LOG_ERROR(FM_LOG_CAT_PLATFORM,
                         "Failed to configure RX hardware timestamp for all"
                         " received packets. Error: %s\n",
                         strErrBuf);
        }
        else
        {
            FM_LOG_ERROR(FM_LOG_CAT_PLATFORM,
                         "Failed to configure RX hardware timestamp for all"
                         " received packets. Error: %d\n",
                         errno);
        }
    }

    FM_LOG_DEBUG(FM_LOG_CAT_PLATFORM,
                 "SIOCSHWTSTAMP: tx_type %d requested, got %d; "
                 " rx_filter %d requested, got %d\n",
                  hwconfig_requested.tx_type, 
                  hwconfig.tx_type,
                  hwconfig_requested.rx_filter, 
                  hwconfig.rx_filter);

    so_timestamping_flags = SOF_TIMESTAMPING_RX_HARDWARE | 
                            SOF_TIMESTAMPING_RAW_HARDWARE;

    if (setsockopt(rawSock,
                   SOL_SOCKET,
                   SO_TIMESTAMPING,
                   &so_timestamping_flags,
                   sizeof(so_timestamping_flags)) < 0)
    {
        FM_LOG_ERROR(FM_LOG_CAT_PLATFORM,
                     "Failed to set timestamping on socket\n");
        /* Continue without timestamp */
    }

    len = sizeof(val);
    errno = 0;
    if (getsockopt(rawSock, SOL_SOCKET, SO_TIMESTAMPING, &val, &len) < 0)
    {
        strErrNum = FM_STRERROR_S(strErrBuf, FM_STRERROR_BUF_SIZE, errno);
        if (strErrNum == 0)
        {
            FM_LOG_ERROR(FM_LOG_CAT_PLATFORM,
                         "Failed to retrieve SO_TIMESTAMPING socket options."
                         " Error %s",
                         strErrBuf);
        }
        else
        {
            FM_LOG_ERROR(FM_LOG_CAT_PLATFORM,
                         "Failed to retrieve SO_TIMESTAMPING socket options."
                         " Error %d",
                         errno);
        }
    }
    else
    {
        FM_LOG_DEBUG(FM_LOG_CAT_PLATFORM, "SO_TIMESTAMPING %d\n", val);
        if (val != so_timestamping_flags)
        {
            FM_LOG_ERROR(FM_LOG_CAT_PLATFORM,
                         "Expected value %d but retrieved %d\n",
                         so_timestamping_flags,
                         val);
        }
    }
#endif

    /* Set the Driver in ies-tagging mode on management PEP */
    ethValue.cmd = ETHTOOL_SPFLAGS;
    ethValue.data = ETHTOOL_PRV_FLAG_IES;
    ifr.ifr_data = (void*) &ethValue;
    if (ioctl(rawSock, SIOCETHTOOL, &ifr) == -1)
    {
        strErrNum = FM_STRERROR_S(strErrBuf, FM_STRERROR_BUF_SIZE, errno);
        if (strErrNum == 0)
        {
            FM_LOG_ERROR(FM_LOG_CAT_PLATFORM,
                         "Failed to set ies-tagging: %s\n",
                         strErrBuf);
        }
        else
        {
            FM_LOG_ERROR(FM_LOG_CAT_PLATFORM,
                         "Failed to set ies-tagging: %d\n",
                         errno);
        }
    }

    if (ioctl(rawSock, SIOCGIFFLAGS, &ifr) == -1)
    {
        strErrNum = FM_STRERROR_S(strErrBuf, FM_STRERROR_BUF_SIZE, errno);
        if (strErrNum == 0)
        {
            FM_LOG_FATAL(FM_LOG_CAT_PLATFORM, 
                         "Failed to get socket flags: %s\n",
                         strErrBuf);
        }
        else
        {
            FM_LOG_FATAL(FM_LOG_CAT_PLATFORM, 
                         "Failed to get socket flags: %d\n",
                         errno);
        }

        err = FM_FAIL;
        FM_LOG_ABORT(FM_LOG_CAT_PLATFORM, err);
    }

    if ((ifr.ifr_flags & IFF_UP) == 0)
    {
        /* Bring the NIC up */
        ifr.ifr_flags |= IFF_UP;

        if (ioctl(rawSock, SIOCSIFFLAGS, &ifr) == -1)
        {
            strErrNum = FM_STRERROR_S(strErrBuf, FM_STRERROR_BUF_SIZE, errno);
            if (strErrNum == 0)
            {
                FM_LOG_FATAL(FM_LOG_CAT_PLATFORM, 
                             "Failed to bring up: %s\n",
                             strErrBuf);
            }
            else
            {
                FM_LOG_FATAL(FM_LOG_CAT_PLATFORM, 
                             "Failed to bring up: %d\n",
                             errno);
            }
            
            err = FM_FAIL;
            FM_LOG_ABORT(FM_LOG_CAT_PLATFORM, err);
        }
    }

    GET_PLAT_STATE(sw)->rawSocket = rawSock;
    FM_STRNCPY_S(GET_PLAT_STATE(sw)->ifaceName, IF_NAMESIZE, iface, IF_NAMESIZE);

    /* Create the receive packet thread */
    err = fmCreateThread("raw_packet_socket receive",
                         FM_EVENT_QUEUE_SIZE_NONE,
                         &fmRawPacketSocketReceivePackets,
                         &(GET_PLAT_STATE(sw)->sw),
                         GET_PLAT_RAW_LISTENER(sw));

    switchPtr = GET_SWITCH_PTR(sw);
    if (switchPtr)
    {
        switchPtr->isRawSocketInitialized = FM_ENABLED;
    }

ABORT:
    if ( (err != FM_OK) &&
         (rawSock != -1) )
    {
        close(rawSock);
    }

    FM_LOG_EXIT(FM_LOG_CAT_PLATFORM, err);

}   /* end fmRawPacketSocketHandlingInitialize */
예제 #8
0
파일: fm_netsock.c 프로젝트: huiweics/IES
/** fmWaitForNetworkEvent
 * \ingroup platformUtil
 *
 * \desc            Waits for network events.
 *
 * \param[out]      sockets points to an array of active and inactive sockets.
 *                  This function can activate inactive sockets when a client
 *                  attempts to make a connection. The array must be maxSockets
 *                  in length.
 *
 * \param[in]       numSockets is the current number of active sockets; it must
 *                  be in the range [1..maxSockets).
 *
 * \param[in]       maxSockets is the maximum number of sockets this function
 *                  can activate.
 *
 * \param[out]      eventReceived points to an array where this function places
 *                  the network event type for each active socket. The array
 *                  must be maxSockets elements in length.
 *
 * \param[in]       timeout is the amount of time to wait for a network event.
 *                  Set to ''FM_WAIT_FOREVER'' to wait indefinitely.
 *
 * \return          FM_OK if successful.
 * \return          Other ''Status Codes'' as appropriate in case of failure.
 *
 *****************************************************************************/
fm_status fmWaitForNetworkEvent(fm_socket **  sockets, 
                                fm_int *      numSockets,
                                fm_int        maxSockets,
                                fm_int *      eventReceived, 
                                fm_timestamp *timeout)
{
    fm_int         currNumSockets;
    fm_int         errResult;
    fm_int         i;
    fm_int         j;
    fm_int         slot;
    fm_bool        doIncrement;
    struct pollfd  fds[FM_MAX_FDS_NUM] = { {0} };
    fm_int         fdsCnt;
    socklen_t      addrLen = SOCKET_ADDRLEN;
    struct timeval ts;
    char           strErrBuf[FM_STRERROR_BUF_SIZE];
    errno_t        strErrNum;

    FM_LOG_ENTRY_VERBOSE(FM_LOG_CAT_PLATFORM,
                         "sockets=%p, numSockets=%p(%d), maxSockets=%d, "
                         "eventReceived=%p, timeout=%p\n",
                         (void *) sockets, 
                         (void *) numSockets, 
                         (numSockets ? *numSockets : -1),
                         maxSockets,
                         (void *) eventReceived, 
                         (void *) timeout);

    if ((!sockets || !eventReceived || !numSockets || (*numSockets == 0) || \
        (maxSockets > FM_MAX_FDS_NUM) || (*numSockets > FM_MAX_FDS_NUM)))
    {
        FM_LOG_EXIT_VERBOSE(FM_LOG_CAT_PLATFORM, FM_ERR_INVALID_ARGUMENT);
    }

    currNumSockets = *numSockets;

    for ( i = 0, fdsCnt = 0 ; i < currNumSockets ; i++ )
    {
#ifdef VERBOSE
        FM_LOG_DEBUG2(FM_LOG_CAT_PLATFORM, "Watching descriptor %d\n", sockets[i]->sock);
#endif

        if (sockets[i]->type != FM_SOCKET_TYPE_CLOSED)
        {
            fds[fdsCnt].fd = sockets[i]->sock;
            fds[fdsCnt].events = POLLIN;
            fds[fdsCnt].revents = 0;
            fdsCnt++;
        }
    }

    if (timeout != FM_WAIT_FOREVER)
    {
        FM_CLEAR(ts);
        ts.tv_sec  = (int) timeout->sec;
        ts.tv_usec = (int) timeout->usec;
    }

    errResult = poll(fds,
                     fdsCnt,
                     ((timeout == FM_WAIT_FOREVER) ? -1 : \
                      ((ts.tv_sec * 1000) + (ts.tv_usec / 1000)) ));

    FM_LOG_SYS_EXIT_ON_COND(FM_LOG_CAT_PLATFORM, errResult == -1);

    for ( i = 0, fdsCnt = 0 ; i < currNumSockets ; i++, fdsCnt++)
    {
        /* Default case */
        eventReceived[i] = FM_NETWORK_EVENT_NONE;

        if (sockets[i]->type != FM_SOCKET_TYPE_CLOSED && fds[fdsCnt].revents & POLLIN)
        {
            /* Handle TCP connection on server socket */
            if ((sockets[i]->type == FM_SOCKET_TYPE_TCP) &&
                (sockets[i]->serverPort > 0))
            {
                doIncrement = TRUE;
                slot = *numSockets;

                for ( j = 0 ; j < currNumSockets ; j++ )
                {
                    if (sockets[j]->type == FM_SOCKET_TYPE_CLOSED)
                    {
                        doIncrement = FALSE;
                        slot = j;
                        break;
                    }
                }

                if (slot >= maxSockets)
                {
                    FM_LOG_FATAL(FM_LOG_CAT_PLATFORM,
                                 "Not enough socket slots left to accept client\n");
                    break;
                }

                FM_CLEAR(*sockets[slot]);

                sockets[slot]->sock
                    = accept(sockets[i]->sock,
                             (struct sockaddr *) &sockets[slot]->address,
                             &addrLen);
                FM_LOG_SYS_EXIT_ON_COND(FM_LOG_CAT_PLATFORM,
                                        sockets[slot]->sock == -1);

                sockets[slot]->type = FM_SOCKET_TYPE_TCP;

                eventReceived[i] = FM_NETWORK_EVENT_NEW_CLIENT;

#ifdef VERBOSE
                FM_LOG_DEBUG2(FM_LOG_CAT_PLATFORM,
                              "Handled new client connection\n");
#endif

                if (doIncrement)
                {
                    (*numSockets)++;
                }

                break;
            }
            else
            {
                eventReceived[i] = FM_NETWORK_EVENT_DATA_AVAILABLE;

#ifdef VERBOSE
                FM_LOG_DEBUG2(FM_LOG_CAT_PLATFORM,
                              "Data available on client #%d\n", i - 1);
#endif
            }
        }
    }

    FM_LOG_EXIT_VERBOSE(FM_LOG_CAT_PLATFORM, FM_OK);

}   /* end fmWaitForNetworkEvent */
예제 #9
0
파일: fm_netsock.c 프로젝트: huiweics/IES
/** fmCreateNetworkClient
 * \ingroup platformUtil
 *
 * \desc            Creates a network client socket.
 *
 * \param[out]      socketInfo points to the information structure for the
 *                  client socket.
 *
 * \param[in]       type is the type of socket to create.
 *
 * \param[in]       host points to a string specifying the hostname.
 *
 * \param[in]       port is the port number.
 *
 * \return          FM_OK if successful.
 *
 *****************************************************************************/
fm_status fmCreateNetworkClient(fm_socket *   socketInfo, 
                                fm_socketType type,
                                fm_text       host, 
                                fm_int        port)
{
    struct hostent  h;
    struct hostent *hp;
    fm_int          errResult;
    char            strErrBuf[FM_STRERROR_BUF_SIZE];
    errno_t         strErrNum;
    char            buf[FM_GETHOSTBYNAME_BUF_SIZE];
    int             herrno;

    FM_LOG_ENTRY_VERBOSE(FM_LOG_CAT_PLATFORM,
                         "socketInfo=%p, port=%d\n",
                         (void *) socketInfo, 
                         port);

    if (!socketInfo)
    {
        FM_LOG_EXIT_VERBOSE(FM_LOG_CAT_PLATFORM, FM_ERR_INVALID_ARGUMENT);
    }

    FM_CLEAR(*socketInfo);

    if (type == FM_SOCKET_TYPE_TCP)
    {
        socketInfo->sock = socket(AF_INET, SOCK_STREAM, 0);
    }
    else if (type == FM_SOCKET_TYPE_UDP)
    {
        socketInfo->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    }

    if (socketInfo->sock == -1)
    {
        FM_LOG_FATAL(FM_LOG_CAT_PLATFORM,
                     "Unable to create socket type %d\n",
                     type);
        FM_LOG_EXIT(FM_LOG_CAT_PLATFORM, FM_FAIL);
    }

    FM_CLEAR(socketInfo->address);

    socketInfo->address.sin_family = AF_INET;

    if ((gethostbyname_r(host,
                         &h,
                         buf,
                         FM_GETHOSTBYNAME_BUF_SIZE,
                         &hp,
                         &herrno) != 0)
        || (hp == NULL))
    {
        FM_LOG_FATAL(FM_LOG_CAT_PLATFORM,
                     "Unable to resolve hostname: %s\n", 
                     host);
    }

    FM_LOG_SYS_EXIT_ON_COND(FM_LOG_CAT_PLATFORM, !hp);

    FM_MEMCPY_S(&socketInfo->address.sin_addr.s_addr,
                sizeof(socketInfo->address.sin_addr.s_addr),
                hp->h_addr,
                hp->h_length);

    socketInfo->address.sin_port = htons(port);

    if (type == FM_SOCKET_TYPE_TCP)
    {
        errResult = connect(socketInfo->sock,
                            (struct sockaddr *) &socketInfo->address,
                            SOCKET_ADDRLEN);
        FM_LOG_SYS_EXIT_ON_COND(FM_LOG_CAT_PLATFORM, errResult != 0);
    }

    FM_LOG_EXIT_VERBOSE(FM_LOG_CAT_PLATFORM, FM_OK);

}   /* end fmCreateNetworkClient */
예제 #10
0
파일: fm_netsock.c 프로젝트: huiweics/IES
/** fmCreateNetworkServer
 * \ingroup platformUtil
 *
 * \desc            Creates a network server socket.
 *
 * \param[out]      socketInfo points to the information structure for the
 *                  server socket.
 *
 * \param[in]       type is the type of socket to create.
 *
 * \param[in]       port is the port number for the socket.
 *
 * \param[in]       backlog is unused.
 *
 * \return          FM_OK if successful.
 *
 *****************************************************************************/
fm_status fmCreateNetworkServer(fm_socket *   socketInfo, 
                                fm_socketType type,
                                fm_int        port, 
                                fm_int        backlog)
{
    fm_status          status = FM_OK;
    fm_int             errResult;
    struct sockaddr_in addrInfo;
    socklen_t          addrLen = sizeof(addrInfo);
    char               strErrBuf[FM_STRERROR_BUF_SIZE];
    errno_t            strErrNum;

    FM_LOG_ENTRY_VERBOSE(FM_LOG_CAT_PLATFORM,
                         "socketInfo=%p, port=%d, backlog=%d\n",
                         (void *) socketInfo, 
                         port, 
                         backlog);

    if (!socketInfo)
    {
        FM_LOG_EXIT_VERBOSE(FM_LOG_CAT_PLATFORM, FM_ERR_INVALID_ARGUMENT);
    }

    FM_CLEAR(*socketInfo);

    if (type == FM_SOCKET_TYPE_TCP)
    {
        socketInfo->sock = socket(AF_INET, SOCK_STREAM, 0);
        FM_LOG_SYS_EXIT_ON_COND(FM_LOG_CAT_PLATFORM, socketInfo->sock == -1);

        socketInfo->address.sin_family      = AF_INET;
        socketInfo->address.sin_addr.s_addr = htonl(INADDR_ANY);
        socketInfo->address.sin_port        = htons(port);

        errResult = bind(socketInfo->sock, 
                         (struct sockaddr *) &socketInfo->address,  
                         SOCKET_ADDRLEN);
        FM_LOG_SYS_EXIT_ON_COND(FM_LOG_CAT_PLATFORM, errResult == -1);

        errResult = listen(socketInfo->sock, 3);
        FM_LOG_SYS_EXIT_ON_COND(FM_LOG_CAT_PLATFORM, errResult == -1);

#ifdef VERBOSE
        FM_LOG_DEBUG2(FM_LOG_CAT_PLATFORM,
                      "Socket descriptor %d initialized\n",
                      socketInfo->sock);
#endif
    }
    else if (type == FM_SOCKET_TYPE_UDP)
    {
        socketInfo->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
        FM_LOG_SYS_EXIT_ON_COND(FM_LOG_CAT_PLATFORM, socketInfo->sock == -1);

        socketInfo->address.sin_addr.s_addr = htonl(INADDR_ANY);
        socketInfo->address.sin_port        = htons(port);

        errResult = bind(socketInfo->sock, 
                         (struct sockaddr *) &socketInfo->address,  
                         SOCKET_ADDRLEN);
        FM_LOG_SYS_EXIT_ON_COND(FM_LOG_CAT_PLATFORM, errResult == -1);

    }
    else
    {
        FM_LOG_ASSERT(FM_LOG_CAT_PLATFORM,
                      FALSE,
                      "Unexpected socket type %d\n", type);
        FM_LOG_EXIT(FM_LOG_CAT_PLATFORM, FM_ERR_INVALID_ARGUMENT);
    }

    errResult = getsockname(socketInfo->sock,
                            (struct sockaddr *) &addrInfo,
                            &addrLen);
    FM_LOG_SYS_EXIT_ON_COND(FM_LOG_CAT_PLATFORM, errResult == -1);

    socketInfo->serverPort = ntohs(addrInfo.sin_port);

    FM_LOG_EXIT_VERBOSE(FM_LOG_CAT_PLATFORM, status);

}   /* end fmCreateNetworkServer */
예제 #11
0
/** fmLoadPortRemapTable
 * \ingroup intSwitch
 *
 * \desc            Load a new port mapping table from a given file.
 *
 * \param[in]       filename is the file name.
 *
 * \param[in]       portTable is ptr to table where to store port read from file
 *
 * \param[in]       origTable is ptr to the original port mapping table
 *
 * \param[in]       maxport is number of entries in portTable
 *
 * \return          FM_OK or FM_FAIL if unable to read table from file
 *
 *****************************************************************************/
fm_status fmLoadPortRemapTable(fm_char *filename,
                               fm_int *portTable,
                               fm_int *origTable,
                               fm_int maxport)
{
    FILE       *fp;
    fm_char    *pch;
    fm_char     line[200];
    fm_int      i;
    fm_int      j;
    fm_int      portNum;
    fm_char *   context;
    fm_uint     s1max;
    fm_uint     lineLeft;

    if ((fp = fopen(filename,"r")) == NULL)
    {
        FM_LOG_PRINT("cannot open file %s \n", filename);
        return(FM_FAIL);
    }

    /* Display the original port mapping table. */
    FM_CLEAR(line);
    lineLeft = sizeof(line);
    FM_SPRINTF_S(line, lineLeft, "\noriginalTable[%d,", origTable[0]);
    i = strlen(line);
    lineLeft -= i;
    pch = &line[i];

    for (i = 1 ; i < maxport ; i++)
    {
        FM_SPRINTF_S(pch, lineLeft, "%d,",origTable[i]);
        j = strlen(pch);
        lineLeft -= j;
        pch += j;
    }

    /* Reposition back to the trailing comma, then overwrite it */
    --pch;
    *pch = ']';
    FM_LOG_PRINT("%s\n", line);

    while ( fgets(line,200,fp) != NULL )
    {
        if (strstr(line,"mappingTable") != NULL)
        {
            FM_LOG_PRINT("%s\n", line);
            if ((pch = strchr(line,'[')) != NULL)
            {
                i       = 0;
                context = NULL;
                s1max   = RSIZE_MAX - 1;
                pch     = FM_STRTOK_S(++pch, &s1max, " ,", &context);

                while (pch != NULL && i < maxport)
                {
                    portNum = atoi(pch);
                    if (portNum >= 0 && portNum < maxport)
                    {
                        portTable[i++] = portNum;
                        pch = FM_STRTOK_S(NULL, &s1max, " ,]", &context);
                    }
                    else
                    {
                        FM_LOG_PRINT("*** Invalid port number %d ***\n",portNum);
                        fclose(fp);
                        return(FM_FAIL);
                    }
                }
            }
        }
    }

    fclose(fp);

    return FM_OK;

}   /* end fmLoadPortRemapTable */
예제 #12
0
/** UsedSweeperActiveState
 * \ingroup intFastMaint
 *
 * \desc            The MAC Address USED Table sweep is in progress.
 *
 * \param[in]       sw is the switch on which to operate
 * 
 * \param[in]       currentTime is the current value of the aging timer.
 *
 * \return          None.
 *
 *****************************************************************************/
static void UsedSweeperActiveState(fm_int sw, fm_uint64 currentTime)
{
    fm_switch *     switchPtr;
    fm10000_switch *switchExt;
    fm_sweepStats   stats;
    fm_int          upperBound;
    fm_int          numWords;

    switchPtr = GET_SWITCH_PTR(sw);
    switchExt = switchPtr->extension;

    FM_CLEAR(stats);

    upperBound = switchExt->usedTableSweeperIndex + USED_TABLE_SAMPLE_SIZE;
    if (upperBound > USED_TABLE_SIZE)
    {
        upperBound = USED_TABLE_SIZE;
    }

    numWords = USED_TABLE_SAMPLE_UNIT;

    while (switchExt->usedTableSweeperIndex < upperBound)
    {
        if ((switchExt->usedTableSweeperIndex + numWords) > upperBound)
        {
            numWords = upperBound - switchExt->usedTableSweeperIndex;
        }

        ProcessSample(sw,
                      switchExt->usedTableSweeperIndex,
                      numWords,
                      currentTime,
                      switchExt->usedTableAgingTime,
                      switchExt->usedTableExpiryTime,
                      &stats);

        switchExt->usedTableSweeperIndex += numWords;

    }   /* end while (switchExt->usedTableSweeperIndex < upperBound) */

    switchExt->usedTableNumExpired += stats.expired;

    if (switchExt->usedTableSweeperIndex >= USED_TABLE_SIZE)
    {
        if (stats.young || stats.old || stats.expired)
        {
            FM_LOG_DEBUG(FM_LOG_CAT_EVENT_FAST_MAINT,
                         "sw=%d young=%d old=%d expired=%d elapsed=%llu\n",
                         sw,
                         stats.young,
                         stats.old,
                         stats.expired,
                         currentTime - switchExt->usedTableLastSweepTime);
        }

        if (switchExt->usedTableNumExpired)
        {
            fm_maWorkTypeData   data;
            fm_status           err;

            FM_CLEAR(data);

            err = fmEnqueueMAPurge(sw, FM_UPD_FLUSH_EXPIRED, data, NULL, NULL);
            if (err != FM_OK)
            {
                FM_LOG_ERROR(FM_LOG_CAT_EVENT_FAST_MAINT,
                             "fmEnqueueMAPurge failed: %s\n",
                             fmErrorMsg(err));
            }
        }

        /* Enter READY state to wait for next pass. */
        switchExt->usedTableSweeperState = FM_USED_SWEEPER_READY;
        FM_LOG_DEBUG(FM_LOG_CAT_EVENT_FAST_MAINT, "sw=%d state=READY\n", sw);
    }

}   /* end UsedSweeperActiveState */
예제 #13
0
/** ProcessSample
 * \ingroup intFastMaint
 *
 * \desc            Processes a register sample from the MA_USED_TABLE.
 *
 * \param[in]       sw is the switch on which to operate
 * 
 * \param[in]       index is the index of the first entry in the
 *                  MA_USED_TABLE to be read.
 * 
 * \param[in]       numWords is the number of entries in the MA_USED_TABLE
 *                  to be read.
 * 
 * \param[in]       currentTime is the current value of the aging timer.
 * 
 * \param[in]       agingTime is the length of time required for an entry
 *                  to age from YOUNG to OLD.
 * 
 * \param[in]       expiryTime is the length of time required for an entry
 *                  to age out.
 * 
 * \param[in,out]   stats points to a structure containing a number of
 *                  counters that will be incremented to show the number
 *                  of MA Table entries that are updated.
 *
 * \return          FM_OK if successful.
 *
 *****************************************************************************/
static fm_status ProcessSample(fm_int          sw,
                               fm_int          index,
                               fm_int          numWords,
                               fm_uint64       currentTime,
                               fm_uint64       agingTime,
                               fm_uint64       expiryTime,
                               fm_sweepStats * stats)
{
    fm_internalMacAddrEntry * cachePtr;

    fm_switch *     switchPtr;
    fm_uint32       used[numWords];
    fm_status       status;
    fm_int          entryIndex;
    fm_int          i;
    fm_int          j;
    fm_uint64       elapsedTime;
    fm_sweepStats   sampleStats;

    switchPtr = GET_SWITCH_PTR(sw);

    FM_CLEAR(sampleStats);

    FM_TAKE_L2_LOCK(sw);

    /* Read next sample from MA_USED_TABLE. */
    status = switchPtr->ReadUINT32Mult(sw,
                                       FM10000_MA_USED_TABLE(1, index),
                                       numWords,
                                       used);

    if (status != FM_OK)
    {
        FM_DROP_L2_LOCK(sw);
        FM_LOG_ERROR(FM_LOG_CAT_EVENT_FAST_MAINT,
                     "Error reading MA_USED_TABLE: %s\n",
                     fmErrorMsg(status));
        goto ABORT;
    }

    /* Clear any hits we detected. */
    status = switchPtr->WriteUINT32Mult(sw,
                                        FM10000_MA_USED_TABLE(1, index),
                                        numWords,
                                        used);

    if (status != FM_OK)
    {
        FM_DROP_L2_LOCK(sw);
        FM_LOG_ERROR(FM_LOG_CAT_EVENT_FAST_MAINT,
                     "Error writing MA_USED_TABLE: %s\n",
                     fmErrorMsg(status));
        goto ABORT;
    }

    /* Process each word in the sample. */
    for (i = 0 ; i < numWords ; ++i)
    {
        /* Process each bit in the word. */
        for (j = 0 ; j < ENTRIES_PER_WORD ; ++j)
        {
            /* Get the MA Table entry corresponding to this bit. */
            entryIndex = (index + i) * ENTRIES_PER_WORD + j;
            cachePtr   = &switchPtr->maTable[entryIndex];

            /* We only care about dynamic entries that are eligible
             * for aging. If it's not one of these, keep going. */
            if (cachePtr->state != FM_MAC_ENTRY_STATE_OLD &&
                cachePtr->state != FM_MAC_ENTRY_STATE_YOUNG)
            {
                continue;
            }

            /* If the entry is USED, set its state to YOUNG
             * and restart its aging timer. */
            if (used[i] & (1 << j))
            {
                cachePtr->state = FM_MAC_ENTRY_STATE_YOUNG;
                cachePtr->agingCounter = currentTime;
                ++sampleStats.young;
                continue;
            }

            /* Get the age of this entry. */
            elapsedTime = currentTime - cachePtr->agingCounter;

            if (elapsedTime >= expiryTime)
            {
                /* The entry has aged out. */
                cachePtr->state = FM_MAC_ENTRY_STATE_EXPIRED;
                ++sampleStats.expired;
                FM_LOG_DEBUG(FM_LOG_CAT_EVENT_FAST_MAINT,
                             "expired: index=%d mac=%012llx vid=%u "
                             "elapsed=%llu\n",
                             entryIndex,
                             cachePtr->macAddress,
                             cachePtr->vlanID,
                             elapsedTime);
            }
            else if (cachePtr->state == FM_MAC_ENTRY_STATE_YOUNG &&
                     elapsedTime >= agingTime)
            {
                /* The entry has gone from YOUNG to OLD. */
                cachePtr->state = FM_MAC_ENTRY_STATE_OLD;
                ++sampleStats.old;
                FM_LOG_DEBUG(FM_LOG_CAT_EVENT_FAST_MAINT,
                             "aged: index=%d mac=%012llx vid=%u "
                             "elapsed=%llu\n",
                             entryIndex,
                             cachePtr->macAddress,
                             cachePtr->vlanID,
                             elapsedTime);
            }

        }   /* end for (j = 0 ; j < ENTRIES_PER_WORD ; ++j) */

    }   /* for (i = 0 ; i < numWords ; ++i) */

    FM_DROP_L2_LOCK(sw);

ABORT:
    stats->young   += sampleStats.young;
    stats->old     += sampleStats.old;
    stats->expired += sampleStats.expired;

    return status;

}   /* end ProcessSample */