예제 #1
0
void print_solution() {
    FM_LOG_DEBUG("-- Solution Information --");
    FM_LOG_MONITOR("solution id %d", oj_solution.sid);
    FM_LOG_TRACE("problem id    %d", oj_solution.pid);
    FM_LOG_TRACE("language(%d)   %s", oj_solution.lang, languages[oj_solution.lang]);
    FM_LOG_TRACE("time limit    %d ms", oj_solution.time_limit);
    FM_LOG_TRACE("memory limit  %d KB", oj_solution.memory_limit);
    FM_LOG_DEBUG("work dir      %s", oj_solution.work_dir);
    FM_LOG_DEBUG("data dir      %s", oj_solution.data_dir);
}
예제 #2
0
/** UsedSweeperReadyState
 * \ingroup intFastMaint
 *
 * \desc            The MAC Address USED sweeper is waiting for the start
 *                  of the next pass.
 *
 * \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 UsedSweeperReadyState(fm_int sw, fm_uint64 currentTime)
{
    fm_switch *     switchPtr;
    fm10000_switch *switchExt;
    fm_uint64       elapsedTime;
    fm_uint64       startInterval;
    fm_float        readyFactor;

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

    if (switchPtr->macAgingTicks == 0)
    {
        /* Revert to IDLE state.*/
        switchExt->usedTableSweeperState = FM_USED_SWEEPER_IDLE;
        FM_LOG_DEBUG(FM_LOG_CAT_EVENT_FAST_MAINT, "sw=%d state=IDLE\n", sw);
        return;
    }

    /* Elapsed time in milliseconds since start of previous pass. */
    elapsedTime = currentTime - switchExt->usedTableLastSweepTime;

    readyFactor = FM_AAD_API_FM10000_MA_USED_TABLE_READY_FACTOR;

    /* Minimum interval until start of next pass. */
    startInterval = (fm_uint64) (readyFactor * switchPtr->macAgingTicks);

    if (elapsedTime >= startInterval)
    {
        EnterActiveState(sw, currentTime);
    }

}   /* end UsedSweeperReadyState */
예제 #3
0
/** InitiatePurge
 * \ingroup intAddr
 *
 * \desc            Initiates an MA table purge operation.
 *
 * \note            The caller is assumed to have taken the purge lock
 *                  (FM_TAKE_MA_PURGE_LOCK).
 *
 * \param[in]       sw is the switch on which to operate.
 *
 * \return          FM_OK if successful.
 *
 *****************************************************************************/
static fm_status InitiatePurge(fm_int sw)
{
    fm_switch *         switchPtr;
    fm_maPurge *        purgePtr;
    fm_maPurgeRequest * request;
    fm_status           err;

    switchPtr = GET_SWITCH_PTR(sw);
    purgePtr  = &switchPtr->maPurge;
    request   = &purgePtr->request;

    FM_LOG_DEBUG(FM_LOG_CAT_EVENT_MAC_MAINT,
                 "sw=%d, port=%d, vlan=%d\n",
                 sw,
                 request->port,
                 request->vid1);

    purgePtr->restoreLocked = FALSE;
    purgePtr->purgeTimeout = 0;

    /* Get purge start time. */
    err = fmGetTime( &purgePtr->startTime );
    if (err != FM_OK)
    {
        FM_LOG_ERROR(FM_LOG_CAT_EVENT_MAC_MAINT,
                     "Error getting purge start time: %s\n",
                     fmErrorMsg(err));
    }

    purgePtr->purgeState = FM_PURGE_STATE_ACTIVE;

    return FM_OK;

}   /* end InitiatePurge */
예제 #4
0
/** EnterActiveState
 * \ingroup intFastMaint
 *
 * \desc            Make the transition to ACTIVE state.
 *
 * \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 EnterActiveState(fm_int sw, fm_uint64 currentTime)
{
    fm_switch *     switchPtr;
    fm10000_switch *switchExt;
    fm_float        agingTicks;
    fm_float        agingFactor;
    fm_float        expiryFactor;

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

    agingFactor = FM_AAD_API_FM10000_MA_USED_TABLE_AGING_FACTOR;

    expiryFactor = FM_AAD_API_FM10000_MA_USED_TABLE_EXPIRY_FACTOR;

    agingTicks = (fm_float) switchPtr->macAgingTicks;

    switchExt->usedTableAgingTime  = (fm_uint64) (agingTicks * agingFactor);
    switchExt->usedTableExpiryTime = (fm_uint64) (agingTicks * expiryFactor);

    switchExt->usedTableSweeperIndex = 0;
    switchExt->usedTableNumExpired = 0;
    switchExt->usedTableLastSweepTime = currentTime;

    switchExt->usedTableSweeperState = FM_USED_SWEEPER_ACTIVE;

    FM_LOG_DEBUG(FM_LOG_CAT_EVENT_FAST_MAINT,
                 "sw=%d state=ACTIVE currentTime=%llu\n",
                 sw,
                 currentTime);

}   /* end EnterActiveState */
예제 #5
0
void set_compile_limit() {
    if (oj_solution.lang == LANG_JAVA || oj_solution.lang == LANG_PYTHON27 || oj_solution.lang == LANG_PYTHON3 ||
        oj_solution.lang == LANG_KOTLIN)
        return;

    rlimit lim{};
    lim.rlim_cur = lim.rlim_max = compile_time_limit / 1000;
    if (setrlimit(RLIMIT_CPU, &lim) < 0) {
        FM_LOG_FATAL("setrlimit RLIMIT_CPU failed: %s", strerror(errno));
        exit(EXIT_SET_LIMIT);
    }

    if (EXIT_SUCCESS != malarm(ITIMER_REAL, compile_time_limit)) {
        FM_LOG_FATAL("malarm for compiler failed: %s", strerror(errno));
        exit(EXIT_SET_LIMIT);
    }

    lim.rlim_cur = lim.rlim_max = compile_memory_limit * STD_MB;
    if (setrlimit(RLIMIT_AS, &lim) < 0) {
        FM_LOG_FATAL("setrlimit RLIMIT_AS failed: %s", strerror(errno));
        exit(EXIT_SET_LIMIT);
    }

    lim.rlim_cur = lim.rlim_max = compile_fsize_limit * STD_MB;
    if (setrlimit(RLIMIT_FSIZE, &lim) < 0) {
        FM_LOG_FATAL("setrlimit RLIMIT_FSIZE failed: %s", strerror(errno));
        exit(EXIT_SET_LIMIT);
    }

    FM_LOG_DEBUG("set compile limit ok");
}
예제 #6
0
/** fm10000InitUsedTableSweeper
 * \ingroup intFastMaint
 *
 * \desc            Initializes the MAC Table USED sweeper.
 *
 * \param[in]       sw is the switch on which to operate
 *
 * \return          None.
 *
 *****************************************************************************/
static void fm10000InitUsedTableSweeper(fm_int sw)
{
    fm10000_switch *switchExt;

    switchExt = GET_SWITCH_EXT(sw);

    /* Advance sweeper to IDLE state. */
    switchExt->usedTableSweeperState = FM_USED_SWEEPER_IDLE;
    FM_LOG_DEBUG(FM_LOG_CAT_EVENT_FAST_MAINT, "sw=%d state=IDLE\n", sw);

}   /* end fm10000InitUsedTableSweeper */
예제 #7
0
void prepare_files(const char *filename, char *infile, char *outfile, char *userfile) {
    size_t namelen = strlen(filename) - 3;
    char fname[PATH_SIZE];
    strncpy(fname, filename, namelen);
    fname[namelen] = 0;

    snprintf(infile, PATH_SIZE, "%s/%s.in", oj_solution.data_dir, fname);
    snprintf(outfile, PATH_SIZE, "%s/%s.out", oj_solution.data_dir, fname);
    snprintf(userfile, PATH_SIZE, "%s/%s.out", oj_solution.work_dir, fname);

    char buff[PATH_SIZE];
    snprintf(buff, PATH_SIZE, "%s/%s.in", oj_solution.work_dir, fname);
    if (symlink(infile, buff) == -1) {
        FM_LOG_NOTICE("make symlink for %s failed: %s", buff, strerror(errno));
    }

    FM_LOG_DEBUG("std  input  file: %s", infile);
    FM_LOG_DEBUG("std  output file: %s", outfile);
    FM_LOG_DEBUG("user output file: %s", userfile);
}
예제 #8
0
/** GetTransitionHandler
 * \ingroup intLbg
 *
 * \desc            Validates that the transition is valid from oldMode to
 *                  newMode in the given state. If valid, the transition
 *                  handler is returned. 
 * 
 * \param[in]       state is the LBG state for which the transition should
 *                  be validated against.
 * 
 * \param[in]       oldMode is the old port mode.
 * 
 * \param[in]       newMode is the new port mode we want to transition to.
 * 
 * \param[out]      handler is a pointer to the caller allocated storage
 *                  where th the transition handler pointer should be stored.
 *
 * \return          FM_OK if successful.
 *
 *****************************************************************************/
static fm_status GetTransitionHandler(fm_int state, 
                                      fm_int oldMode, 
                                      fm_int newMode, 
                                      fm_LBGPortTransHandler *handler)
{
    fm_int    numAllowedTransitions;
    fm_int    j;

    FM_LOG_DEBUG(FM_LOG_CAT_LBG,
                 "Searching for mode transition %d to %d\n",
                 oldMode, newMode);

    numAllowedTransitions = (sizeof(validPortModeTransitions) /
                             sizeof(fm_LBGPortTransTable));

    for ( j = 0 ; j < numAllowedTransitions ; j++ )
    {
        if ( ( state        == validPortModeTransitions[j].groupState ) &&
             ( -1           == validPortModeTransitions[j].oldMode ) &&
             ( -1           == validPortModeTransitions[j].newMode ) )
        {
            break;
        }
        else if ( ( state   == validPortModeTransitions[j].groupState ) &&
                  ( oldMode == validPortModeTransitions[j].oldMode ) &&
                  ( newMode == validPortModeTransitions[j].newMode ) )
        {
            break;
        }
        else if ( ( state   == validPortModeTransitions[j].groupState ) &&
                  ( -1      == validPortModeTransitions[j].oldMode ) &&
                  ( newMode == validPortModeTransitions[j].newMode ) )
        {
            break;
        }
        else if ( ( state   == validPortModeTransitions[j].groupState ) &&
                  ( oldMode == validPortModeTransitions[j].oldMode ) &&
                  ( -1      == validPortModeTransitions[j].newMode ) )
        {
            break;
        }
    }

    if (j >= numAllowedTransitions)
    {
        return FM_ERR_INVALID_LBG_PORT_TRANS;
    }

    *handler = validPortModeTransitions[j].handler;

    return FM_OK;

}   /* end GetTransitionHandler */
예제 #9
0
void work(int newsockfd, struct sockaddr_in cli_addr) {
    if (newsockfd < 0) {
        FM_LOG_WARNING("ERROR on accept");
        return;
    }
    FM_LOG_NOTICE("connect from %s:%d", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));

    char buffer[BUFF_SIZE];
    bzero(buffer, BUFF_SIZE);
    ssize_t n = read(newsockfd, buffer, BUFF_SIZE);
    if (n < 0) FM_LOG_WARNING("ERROR reading from socket");

    FM_LOG_NOTICE("Here is the password: %s", buffer);
    if (check_password(oj_config.password, buffer)) {
        FM_LOG_DEBUG("Authentication Ok.");
        n = write(newsockfd, "Authentication Ok.", 18);
        if (n < 0) FM_LOG_WARNING("ERROR writing to socket");

        bzero(buffer, BUFF_SIZE);
        n = read(newsockfd, buffer, BUFF_SIZE);
        if (n <= 0) {
            FM_LOG_WARNING("ERROR reading from socket");
            close(newsockfd);
            return;
        }
        FM_LOG_NOTICE("Here is the message: %s(%d)", buffer, n);
        oj_solution_t oj_solution{};
        if (parse_arguments(buffer, oj_solution) < 0) {
            FM_LOG_WARNING("Missing some parameters.");
            n = write(newsockfd, "Missing some parameters.", 24);
            if (n < 0) FM_LOG_WARNING("ERROR writing to socket");
            close(newsockfd);
            return;
        } else {
            n = write(newsockfd, "I got your request.", 19);
            if (n < 0) FM_LOG_WARNING("ERROR writing to socket");

            close(newsockfd);
            ProcessQueue.push(oj_solution);
            return;
        }
    } else {
        FM_LOG_WARNING("Authentication Failed.");
        n = write(newsockfd, "Authentication Failed.", 22);
        if (n < 0) FM_LOG_WARNING("ERROR writing to socket");
    }

    close(newsockfd);
}
예제 #10
0
int main(int argc, char *argv[], char *envp[]) {
    if (nice(10) == -1) {  // increase nice value(decrease pripority)
        FM_LOG_WARNING("increase nice value failed: %s", strerror(errno));
    }

    init();

    parse_arguments(argc, argv);

    if (geteuid() == 0) {  // effective user is not root
        FM_LOG_FATAL("please do not run as root, run as judge");
        exit(EXIT_PRIVILEGED);
    }

    if (EXIT_SUCCESS != chdir(oj_solution.work_dir)) {  // change current directory
        FM_LOG_FATAL("chdir(%s) failed: %s", oj_solution.work_dir, strerror(errno));
        exit(EXIT_CHDIR);
    }
    FM_LOG_DEBUG("\n\x1b[31m----- Power Judge 1.0 -----\x1b[0m");

    judge_time_limit += oj_solution.time_limit;
    judge_time_limit *= get_num_of_test();

    if (EXIT_SUCCESS != malarm(ITIMER_REAL, judge_time_limit)) {
        FM_LOG_FATAL("set alarm for judge failed: %s", strerror(errno));
        exit(EXIT_VERY_FIRST);
    }

    if (signal(SIGALRM, timeout_hander) == SIG_ERR) {  // install signal hander for timeout
        FM_LOG_FATAL("cannot handle SIGALRM");
        exit(EXIT_VERY_FIRST);
    }
    init_connet();
    compile();

    run_solution();
    close_connet();
    return 0;
}
예제 #11
0
void set_security_option() {
    if (oj_solution.lang != LANG_JAVA && oj_solution.lang != LANG_KOTLIN
#ifdef FAST_JUDGE
        && oj_solution.lang != LANG_PYTHON3 && oj_solution.lang != LANG_PYTHON27
#endif
            ) {
        char cwd[PATH_SIZE];
        char *tmp = getcwd(cwd, PATH_SIZE - 1);
        if (tmp == nullptr) {
            FM_LOG_FATAL("getcwd failed: %s", strerror(errno));
            exit(EXIT_SET_SECURITY);
        }

        // chroot, current directory will be the root dir
        if (EXIT_SUCCESS != chroot(cwd)) {
            FM_LOG_FATAL("chroot(%s) failed: %s", cwd, strerror(errno));
            exit(EXIT_SET_SECURITY);
        }
        FM_LOG_DEBUG("chroot(%s)", cwd);
    }

    FM_LOG_TRACE("set_security_option ok");
}
예제 #12
0
void set_limit(off_t fsize) {
    rlimit lim{};

    // Set CPU time limit round up, raise SIGXCPU
    lim.rlim_max = (oj_solution.time_limit + 999) / 1000 + 1;
    lim.rlim_cur = lim.rlim_max;
    if (setrlimit(RLIMIT_CPU, &lim) < 0) {
        FM_LOG_FATAL("setrlimit RLIMIT_CPU failed: %s", strerror(errno));
        exit(EXIT_SET_LIMIT);
    }

    if (oj_solution.lang <= LANG_PASCAL) {
        // Memory control, raise SIGSEGV
        lim.rlim_cur = lim.rlim_max = (STD_MB << 10) + oj_solution.memory_limit * STD_KB;
        if (setrlimit(RLIMIT_AS, &lim) < 0) {
            FM_LOG_FATAL("setrlimit RLIMIT_AS failed: %s", strerror(errno));
            exit(EXIT_SET_LIMIT);
        }
    }

    // Stack space, raise SIGSEGV
    lim.rlim_cur = lim.rlim_max = stack_size_limit * STD_KB;
    if (setrlimit(RLIMIT_STACK, &lim) < 0) {
        FM_LOG_FATAL("setrlimit RLIMIT_STACK failed: %s", strerror(errno));
        exit(EXIT_SET_LIMIT);
    }

    // Output file size limit, raise SIGXFSZ
    lim.rlim_cur = lim.rlim_max = (rlim_t) (4 * MAX_LOG_FILE_SIZE);
    if (setrlimit(RLIMIT_FSIZE, &lim) < 0) {
        FM_LOG_FATAL("setrlimit RLIMIT_FSIZE failed: %s", strerror(errno));
        exit(EXIT_SET_LIMIT);
    }
    FM_LOG_DEBUG("File size limit: %d", lim.rlim_max);

    FM_LOG_TRACE("set execute limit ok");
}
예제 #13
0
/** fm10000DeleteForwardingRule
 * \ingroup intStacking
 *
 * \desc            Deletes a rule given the rule ID.
 *
 * \param[in]       sw is the switch number to operate on.
 *
 * \param[in]       ruleId is the ID number of the rule to delete.
 *
 *
 * \return          FM_OK if successful.
 * \return          FM_ERR_NOT_FOUND if id not recognized.
 *
 *****************************************************************************/
fm_status fm10000DeleteForwardingRule(fm_int sw, fm_int ruleId)
{
    fm_switch *                  switchPtr;
    fm_stackingInfo *            stackingInfo;
    fm_forwardRuleInternal *     internalRule;
    fm10000_forwardRuleInternal *fwdExt;
    fm_status                    err;

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

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

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

    fwdExt = (fm10000_forwardRuleInternal *) internalRule->extension;

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

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

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

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

    FM_LOG_EXIT(FM_LOG_CAT_STACKING, FM_OK);

}   /* end fm10000DeleteForwardingRule */
예제 #14
0
/** RedistributeFailoverSlot
 * \ingroup intLbg
 *
 * \desc            Redistributes the slots belonging to the given port
 *                  which has gone into failover.
 *
 * \param[in]       sw is the switch number to operate on.
 *
 * \param[out]      group is the group state object.
 *
 * \param[out]      member is the member state object for the port in failover.
 *
 * \return          FM_OK if successful.
 *
 *****************************************************************************/
static fm_status RedistributeFailoverSlot(fm_int sw,
                                          fm_LBGGroup *group,
                                          fm_intLBGMember *member)
{
    fm_intLBGMember *memberPort;
    fm_intLBGMember *nextAvailStandby = NULL;
    fm_bool          drop = FALSE;
    fm_bool          stripeAll = FALSE;
    fm_bool          stripeStandby = FALSE;
    fm_int           newPort = -1;
    fm_int           bin;

    FM_LOG_ENTRY(FM_LOG_CAT_LBG,
                 "sw=%d, group=%p, member=%p\n",
                 sw,
                 (void *) group,
                 (void *) member);

    FM_NOT_USED(sw);

    if ( (group->redirectMode == FM_LBG_REDIRECT_STANDBY) ||
         (group->redirectMode == FM_LBG_REDIRECT_PREFER_STANDBY) )
    {
        nextAvailStandby = GetNextMember(group,
                                         NULL,   /* Start at the first member */
                                         FALSE,  /* Skip active ports */
                                         FALSE,  /* Skip all standby ports (regardless of use) */
                                         TRUE,   /* Include unused standby ports, overrides the above */
                                         FALSE,  /* Skip failover ports */
                                         FALSE); /* Skip inactive ports */

        if (!nextAvailStandby)
        {
            /***************************************************
             * Standby only, but no standby ports available,
             * all bins using the failover member will start
             * dropping frames.
             **************************************************/
            if (group->redirectMode == FM_LBG_REDIRECT_STANDBY)
            {
                drop = TRUE;
            }
        }
    }

    FM_LOG_DEBUG(FM_LOG_CAT_LBG,
                 "Processing a redirect mode of %d\n",
                 group->redirectMode);

    switch (group->redirectMode)
    {
        case FM_LBG_REDIRECT_ALL_PORTS:
            stripeAll = TRUE;
            break;

        case FM_LBG_REDIRECT_PORT:
            newPort = member->redirectTarget;
            break;

        case FM_LBG_REDIRECT_PREFER_STANDBY:
            if (nextAvailStandby)
            {
                newPort = nextAvailStandby->lbgMemberPort;
                nextAvailStandby->standbyUsed = TRUE;
            }
            else
            {
                stripeStandby = TRUE;
            }
            break;

        case FM_LBG_REDIRECT_STANDBY:
            stripeStandby = TRUE;
            break;

        default:
            FM_LOG_ASSERT(FM_LOG_CAT_LBG,
                          FALSE,
                         "Unknown LBG redirect mode %d\n",
                         group->redirectMode);
            break;
    }

    FM_LOG_DEBUG(FM_LOG_CAT_LBG,
                 "stripeAll=%d stripeStandby=%d drop=%d newPort=%d\n",
                 stripeAll,
                 stripeStandby,
                 drop,
                 newPort);

    /***************************************************
     * Use the last member port used as starting point 
     * to improve hashing distribution (if striping 
     * required)
     **************************************************/

    if (stripeAll || stripeStandby)
    {
        memberPort = group->lastStripeMember;
    }
    else
    {
        memberPort = NULL;
    }

    for ( bin = 0 ; bin < group->numBins ; bin++ )
    {
        if ( group->hwDistribution[bin] == member->lbgMemberPort )
        {
            if (stripeAll)
            {
                memberPort = GetNextMember(group,
                                           (memberPort ? memberPort->nextMember : NULL),
                                           TRUE,   /* Include active ports */
                                           TRUE,   /* Include standby ports */
                                           FALSE,  /* Ignore standby in use */
                                           FALSE,  /* Skip failover ports */
                                           FALSE); /* Skip inactive ports */

                group->hwDistribution[bin] = (memberPort ?
                                              memberPort->lbgMemberPort :
                                              FM_PORT_DROP);

                /* Keep track of the last member port striped on */
                group->lastStripeMember = memberPort;
            }
            else if (stripeStandby)
            {
                memberPort = GetNextMember(group,
                                           (memberPort ? memberPort->nextMember : NULL),
                                           FALSE,  /* Include active ports */
                                           TRUE,   /* Include standby ports */
                                           FALSE,  /* Ignore standby in use */
                                           FALSE,  /* Skip standby ports */
                                           FALSE); /* Skip inactive ports */

                group->hwDistribution[bin] = (memberPort ?
                                              memberPort->lbgMemberPort :
                                              FM_PORT_DROP);

                /* Keep track of the last member port striped on */
                group->lastStripeMember = memberPort;
            }
            else if (newPort != -1)
            {
                group->hwDistribution[bin] = newPort;
            }
            else if (drop)
            {
                group->hwDistribution[bin] = FM_PORT_DROP;
            }
            else
            {
                FM_LOG_ASSERT(FM_LOG_CAT_LBG,
                              FALSE,
                              "Unhandled LBG redirect case: "
                              "stripeAll=%d stripeStandby=%d "
                              "newPort=%d drop=%d\n",
                              stripeAll,
                              stripeStandby,
                              newPort,
                              drop);

                FM_LOG_EXIT(FM_LOG_CAT_LBG, FM_FAIL);
            }

            FM_LOG_DEBUG(FM_LOG_CAT_LBG, "Replaced bin %d with port %d\n",
                         bin, group->hwDistribution[bin]);
        }
    }

    FM_LOG_EXIT(FM_LOG_CAT_LBG, FM_OK);

}   /* end RedistributeFailoverSlot */
예제 #15
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 */
예제 #16
0
void run_solution() {
    FM_LOG_DEBUG("run_solution");
#ifndef FAST_JUDGE
    if (oj_solution.lang == LANG_PYTHON27) {
        copy_python_runtime_python2(oj_solution.work_dir);
        FM_LOG_DEBUG("copy_python_runtime");
    } else if (oj_solution.lang == LANG_PYTHON3) {
        copy_python_runtime_python3(oj_solution.work_dir);
        FM_LOG_DEBUG("copy_python_runtime");
    }
#endif

    check_spj();

    struct dirent **namelist;
    int num_of_test;

    num_of_test = scandir(oj_solution.data_dir, &namelist, data_filter, alphasort);
    if (num_of_test < 0) {
        FM_LOG_FATAL("scan data directory failed: %s", strerror(errno));
        exit(EXIT_PRE_JUDGE_DAA);
    }

    int first_failed_test = 0;
    char input_file[PATH_SIZE];
    char output_file_std[PATH_SIZE];
    char stdout_file_executive[PATH_SIZE];
    char stderr_file_executive[PATH_SIZE];

    snprintf(stderr_file_executive, PATH_SIZE, "%s/stderr_executive.txt", oj_solution.work_dir);
    FM_LOG_DEBUG("start run solution (%d cases)", num_of_test);

    for (int i = 0; i < num_of_test; ++i) {
        update_solution_status(oj_solution.cid, oj_solution.sid, OJ_RUN, i + 1);

        prepare_files(namelist[i]->d_name, input_file, output_file_std, stdout_file_executive);

        FM_LOG_TRACE("run case: %d", i + 1);

        bool result = judge(input_file, output_file_std, stdout_file_executive, stderr_file_executive);

        if (oj_solution.result != OJ_AC && !first_failed_test) {
            first_failed_test = i + 1;
        }

        if (!result && oj_solution.judge_type == ACM) {
            break;
        }
    }

    for (int i = 0; i < num_of_test; ++i) {
        free(namelist[i]);
    }
    free(namelist);

#ifndef FAST_JUDGE
    if (oj_solution.lang == LANG_PYTHON27 || oj_solution.lang == LANG_PYTHON3) {
        clean_workdir(oj_solution.work_dir);
    }
#endif

    output_acm_result(oj_solution.result, oj_solution.time_usage, oj_solution.memory_usage, first_failed_test);
}
예제 #17
0
bool judge(const char *input_file,
           const char *output_file_std,
           const char *stdout_file_executive,
           const char *stderr_file_executive) {
    rusage rused{};
    pid_t executor = fork();  // create a child process for executor

    if (executor < 0) {
        FM_LOG_FATAL("fork executor failed: %s", strerror(errno));
        exit(EXIT_PRE_JUDGE);
    } else if (executor == 0) {  // child process
        log_add_info("executor");

        off_t fsize = file_size(output_file_std);

        // io redirect, must before set_security_option()
        io_redirect(input_file, stdout_file_executive, stderr_file_executive);

        // chroot & setuid
        set_security_option();

        // set memory, time and file size limit etc.
        set_limit(fsize);  // must after set_security_option()

        FM_LOG_DEBUG("time limit: %d, time limit addtion: %d",
                     oj_solution.time_limit, time_limit_addtion);


        uint64_t real_time_limit = oj_solution.time_limit + time_limit_addtion;  // time fix
        // set real time alarm
        if (EXIT_SUCCESS != malarm(ITIMER_REAL, real_time_limit)) {
            FM_LOG_FATAL("malarm for executor failed: %s", strerror(errno));
            exit(EXIT_PRE_JUDGE);
        }

        FM_LOG_TRACE("begin execute");

        if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) < 0) {
            FM_LOG_FATAL("Trace executor failed: %s", strerror(errno));
            exit(EXIT_PRE_JUDGE_PTRACE);
        }

        // load program
        if (oj_solution.lang == LANG_JAVA) {
            print_executor(EXEC_J);
            execvp(EXEC_J[0], (char *const *) EXEC_J);
        } else if (oj_solution.lang == LANG_KOTLIN) {
            print_executor(EXEC_KT);
            execvp(EXEC_KT[0], (char *const *) EXEC_KT);
        } else if (oj_solution.lang == LANG_PYTHON27) {
            print_executor(EXEC_PY27);
#ifdef FAST_JUDGE
            execvp(EXEC_PY27[0], (char * const *) EXEC_PY27);
#else
            execv(EXEC_PY27[0], (char *const *) EXEC_PY27);
#endif
        } else if (oj_solution.lang == LANG_PYTHON3) {
            print_executor(EXEC_PY3);
#ifdef FAST_JUDGE
            execvp(EXEC_PY3[0], (char * const *) EXEC_PY3);
#else
            execv(EXEC_PY3[0], (char *const *) EXEC_PY3);
#endif
        } else {
            execl("./Main", "./Main", NULL);
        }

        // exec error
        FM_LOG_FATAL("exec error");
        exit(EXIT_PRE_JUDGE_EXECLP);
    } else {
        // Judger
        int status = 0;
        user_regs_struct regs{};
        stderr = freopen("error.txt", "a+", stderr);

        init_syscalls(oj_solution.lang);

        while (true) {
            if (wait4(executor, &status, 0, &rused) < 0) {
                FM_LOG_FATAL("wait4 executor failed: %s", strerror(errno));
                kill(executor, SIGKILL);
                exit(EXIT_JUDGE);
            }

            if (WIFEXITED(status)) {
                if ((oj_solution.lang != LANG_JAVA && oj_solution.lang != LANG_KOTLIN) ||
                    WEXITSTATUS(status) == EXIT_SUCCESS) {
                    // AC PE WA
                    FM_LOG_TRACE("normal quit");
                    int result;
                    if (oj_solution.spj) {
                        // use SPJ
                        result = oj_compare_output_spj(input_file, output_file_std, stdout_file_executive,
                                                       oj_solution.spj_exe_file);
                    } else {
                        // compare file
                        result = oj_compare_output(output_file_std, stdout_file_executive);
                    }
                    // WA
                    if (result == OJ_WA) {
                        oj_solution.result = OJ_WA;
                    } else if (oj_solution.result != OJ_PE) {  // previous case is AC
                        oj_solution.result = result;  // AC or PE
                    } else /* (oj_solution.result == OJ_PE) */ {  // previous case is PE
                        oj_solution.result = OJ_PE;
                    }
                    FM_LOG_NOTICE("case result: %d, problem result: %d", result, oj_solution.result);
                } else {
                    // not return 0
                    oj_solution.result = OJ_RE;
                    FM_LOG_NOTICE("abnormal quit, exit_code: %d", WEXITSTATUS(status));
                }
                break;
            }

            // RE/TLE/OLE
            if (WIFSIGNALED(status) || (WIFSTOPPED(status) && WSTOPSIG(status) != SIGTRAP)) {
                int signo = 0;
                if (WIFSIGNALED(status)) {
                    signo = WTERMSIG(status);
                    FM_LOG_NOTICE("child process killed by signal %d, %s", signo, strsignal(signo));
                } else {
                    signo = WSTOPSIG(status);
                    FM_LOG_NOTICE("child process stopped by signal %d, %s", signo, strsignal(signo));
                }
                switch (signo) {
                    // Ignore
                    case SIGCHLD:
                        oj_solution.result = OJ_AC;
                        break;
                        // TLE
                    case SIGALRM:    // alarm() and setitimer(ITIMER_REAL)
                    case SIGVTALRM:  // setitimer(ITIMER_VIRTUAL)
                    case SIGXCPU:    // exceeds soft processor limit
                        oj_solution.result = OJ_TLE;
                        FM_LOG_TRACE("Time Limit Exceeded: %s", strsignal(signo));
                        break;
                        // OLE
                    case SIGXFSZ:  // exceeds file size limit
                        oj_solution.result = OJ_OLE;
                        FM_LOG_TRACE("Output Limit Exceeded");
                        break;
                        // RE
                    case SIGSEGV:  // segmentation violation
                    case SIGFPE:   // any arithmetic exception
                    case SIGBUS:   // the process incurs a hardware fault
                    case SIGABRT:  // abort() function
                    case SIGKILL:  // exceeds hard processor limit
                    default:
                        oj_solution.result = OJ_RE;
                        FILE *fp = fopen(stderr_file_executive, "a+");
                        if (fp == nullptr) {
                            fprintf(stderr, "%s\n", strsignal(signo));
                            FM_LOG_WARNING("Runtime Error: %s", strsignal(signo));
                        } else {
                            fprintf(fp, "%s\n", strsignal(signo));
                            fclose(fp);
                        }
                        break;
                }  // end of swtich
                kill(executor, SIGKILL);
                break;
            }  // end of  "if (WIFSIGNALED(status) ...)"

            oj_solution.memory_usage = std::max(oj_solution.memory_usage, (unsigned long) rused.ru_maxrss);
            // TODO(power): check why memory exceed too much
            if (oj_solution.memory_usage > oj_solution.memory_limit) {
                oj_solution.result = OJ_MLE;
                kill(executor, SIGKILL);
                break;
            }

            // check syscall
            if (ptrace(PTRACE_GETREGS, executor, NULL, &regs) < 0) {
                FM_LOG_FATAL("ptrace(PTRACE_GETREGS) failed: %s", strerror(errno));
                kill(executor, SIGKILL);
                exit(EXIT_JUDGE);
            }
            int syscall_id = 0;
#ifdef __i386__
            syscall_id = (int)regs.orig_eax;
#else
            syscall_id = (int) regs.orig_rax;
#endif
            if (syscall_id > 0 && !is_valid_syscall(syscall_id)) {
                oj_solution.result = OJ_RF;
                FM_LOG_FATAL("restricted function, syscall_id: %d", syscall_id);
                kill(executor, SIGKILL);
                break;
            }

            if (ptrace(PTRACE_SYSCALL, executor, NULL, NULL) < 0) {
                FM_LOG_FATAL("ptrace(PTRACE_SYSCALL) failed: %s", strerror(errno));
                kill(executor, SIGKILL);
                exit(EXIT_JUDGE);
            }
        }  // end of while
    }  // end of fork for judge process

    oj_solution.memory_usage = std::max(oj_solution.memory_usage, (unsigned long) rused.ru_maxrss);
    if (oj_solution.memory_usage > oj_solution.memory_limit) {
        oj_solution.result = OJ_MLE;
        FM_LOG_NOTICE("memory limit exceeded: %d (fault: %d * %d)",
                      oj_solution.memory_usage, rused.ru_minflt, page_size);
    }

    oj_solution.time_usage = std::max(oj_solution.time_usage,
                                      (unsigned long) rused.ru_utime.tv_sec * 1000 + rused.ru_utime.tv_usec / 1000);

    if (oj_solution.time_usage > oj_solution.time_limit) {
        oj_solution.result = OJ_TLE;
        FM_LOG_TRACE("Time Limit Exceeded");
    }

    if (oj_solution.result != OJ_AC) {
        if (oj_solution.judge_type == ACM) {
            FM_LOG_NOTICE("not AC/PE, no need to continue");
        }
        if (oj_solution.result == OJ_TLE) {
            oj_solution.time_usage = oj_solution.time_limit;
        } else if (oj_solution.result == OJ_WA) {
            if (oj_solution.lang == LANG_JAVA) { // TODO: kotlin
                fix_java_result(stdout_file_executive, stderr_file_executive);
            } else if ((oj_solution.lang == LANG_PYTHON27 || oj_solution.lang == LANG_PYTHON3) &&
                       file_size(stderr_file_executive)) {
                oj_solution.result = OJ_RE;
                FM_LOG_TRACE("Runtime Error");
            }
        }
        return false;
    }
    return true;
}
예제 #18
0
void run(oj_solution_t &oj_solution) {
    if (oj_solution.cid > 0) {
        snprintf(oj_solution.work_dir, PATH_SIZE, "%s/c%d", oj_config.temp_dir, oj_solution.cid);
    } else {
        strncpy(oj_solution.work_dir, oj_config.temp_dir, strlen(oj_config.temp_dir) + 1);
    }
    char stderr_file[PATH_SIZE];
    snprintf(stderr_file, PATH_SIZE, "%s/%s/error.txt", oj_solution.work_dir, oj_solution.sid);
    FM_LOG_NOTICE("/usr/local/bin/powerjudge -s %s -p %s -l %s -t %s -m %s -w %s -D %s",
                  oj_solution.sid, oj_solution.pid, oj_solution.language,
                  oj_solution.time_limit, oj_solution.memory_limit,
                  oj_solution.work_dir, oj_config.data_dir);
    pid_t pid = fork();
    if (pid < 0) {
        FM_LOG_FATAL("fork judger failed: %s", strerror(errno));
        SendQueue.push(std::make_pair(EXIT_FORK_ERROR, oj_solution));
    } else if (pid == 0) {
        execl("/usr/local/bin/powerjudge",
              "/usr/local/bin/powerjudge",
              "-s", oj_solution.sid,
              "-p", oj_solution.pid,
              "-l", oj_solution.language,
              "-t", oj_solution.time_limit,
              "-m", oj_solution.memory_limit,
              "-w", oj_solution.work_dir,
              "-D", oj_config.data_dir,
              "-c", std::to_string(oj_solution.cid).c_str(),
              NULL);
        stderr = freopen(stderr_file, "a+", stderr);
        FM_LOG_FATAL("exec error: %s", strerror(errno));
        SendQueue.push(std::make_pair(EXIT_EXEC_ERROR, oj_solution));
    } else {
        int status = 0;
        FM_LOG_TRACE("process ID=%d", pid);
        if (waitpid(pid, &status, WUNTRACED) == -1) {
            FM_LOG_FATAL("waitpid for judger failed: %s", strerror(errno));
        }

        if (WIFEXITED(status))    // normal termination
        {
            if (EXIT_SUCCESS == WEXITSTATUS(status)) {
                FM_LOG_DEBUG("judge succeeded");
                SendQueue.push(std::make_pair(EXIT_OK, oj_solution));
            } else if (EXIT_COMPILE_ERROR == WEXITSTATUS(status)) {
                FM_LOG_TRACE("compile error");
                SendQueue.push(std::make_pair(EXIT_OK, oj_solution));
            } else if (EXIT_JUDGE == WEXITSTATUS(status)) {
                FM_LOG_TRACE("judge error");
                SendQueue.push(std::make_pair(OJ_SE, oj_solution));
            } else {
                FM_LOG_TRACE("judge error");
                SendQueue.push(std::make_pair(WEXITSTATUS(status), oj_solution));
            }
        } else {
            if (WIFSIGNALED(status))    // killed by signal
            {
                int signo = WTERMSIG(status);
                FM_LOG_WARNING("judger killed by signal: %s", strsignal(signo));
                SendQueue.push(std::make_pair(signo, oj_solution));
            } else if (WIFSTOPPED(status))      // stopped by signal
            {
                int signo = WSTOPSIG(status);
                FM_LOG_FATAL("judger stopped by signal: %s\n", strsignal(signo));
                SendQueue.push(std::make_pair(signo, oj_solution));
            } else {
                FM_LOG_FATAL("judger stopped with unknown reason, status(%d)", status);
                SendQueue.push(std::make_pair(EXIT_UNKNOWN, oj_solution));
            }
        }
    }
}
예제 #19
0
/** fmReceivePacketTask
 * \ingroup intApi
 *
 * \desc            Handles reception of packets.
 *
 * \param[in]       args contains a pointer to the thread information.
 *
 * \return          FM_OK if successful.
 *
 *****************************************************************************/
void *fmReceivePacketTask(void *args)
{
    fm_thread *thread;
    fm_status  err = FM_OK;
    fm_int     sw;

    thread = FM_GET_THREAD_HANDLE(args);

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


    /**************************************************
     * Loop forever, waiting for signals from the
     * interrupt handler.
     **************************************************/

    while (TRUE)
    {
        /**************************************************
         * Wait for a signal from the interrupt handler.
         **************************************************/

        FM_LOG_DEBUG(FM_LOG_CAT_EVENT_PKT_RX,
                     "fmLCIReceivePacketTask: waiting for signal..\n");

        err = fmWaitSemaphore(&fmRootApi->packetReceiveSemaphore,
                              FM_WAIT_FOREVER);

        if (err != FM_OK)
        {
            FM_LOG_ERROR( FM_LOG_CAT_SWITCH,
                         "%s: %s\n",
                         thread->name,
                         fmErrorMsg(err) );
            continue;
        }

        FM_LOG_DEBUG(FM_LOG_CAT_EVENT_PKT_RX,
                     "fmReceivePacketTask: signaled!\n");

        for (sw = FM_FIRST_FOCALPOINT ; sw <= FM_LAST_FOCALPOINT ; sw++)
        {
            if ( (fmRootApi->fmSwitchStateTable[sw] != NULL) 
                  && (!fmRootApi->isSwitchFibmSlave[sw]) )
            {

                fmReceivePacket(sw);
            }
        }

    } /* end while (TRUE) */

    /**************************************************
     * Should never exit.
     **************************************************/

    FM_LOG_ERROR(FM_LOG_CAT_SWITCH,
                 "ERROR: fmReceivePacketTask: exiting inadvertently!\n");

    return NULL;

}   /* end fmReceivePacketTask */
예제 #20
0
void send_multi_result(char *file_path, oj_solution_t &oj_solution) {
    FM_LOG_TRACE("send_multi_result");
    CURL *curl;

    CURLM *multi_handle;
    int still_running = 1;

    struct curl_httppost *formpost = nullptr;
    struct curl_httppost *lastptr = nullptr;
    struct curl_slist *headerlist = nullptr;
    static const char buf[] = "Expect:";
    const size_t size = 25;
    char data[size] = {0};
    curl_formadd(&formpost,
                 &lastptr,
                 CURLFORM_COPYNAME, "sid",
                 CURLFORM_COPYCONTENTS, oj_solution.sid,
                 CURLFORM_END);

    curl_formadd(&formpost,
                 &lastptr,
                 CURLFORM_COPYNAME, "token",
                 CURLFORM_COPYCONTENTS, oj_solution.token,
                 CURLFORM_END);

    snprintf(data, size, "%d", oj_solution.cid);
    curl_formadd(&formpost,
                 &lastptr,
                 CURLFORM_COPYNAME, "cid",
                 CURLFORM_COPYCONTENTS, data,
                 CURLFORM_END);

    snprintf(data, size, "%d", oj_solution.result);
    curl_formadd(&formpost,
                 &lastptr,
                 CURLFORM_COPYNAME, "result",
                 CURLFORM_COPYCONTENTS, data,
                 CURLFORM_END);

    snprintf(data, size, "%d", oj_solution.time_usage);
    curl_formadd(&formpost,
                 &lastptr,
                 CURLFORM_COPYNAME, "time",
                 CURLFORM_COPYCONTENTS, data,
                 CURLFORM_END);

    snprintf(data, size, "%d", oj_solution.memory_usage);
    curl_formadd(&formpost,
                 &lastptr,
                 CURLFORM_COPYNAME, "memory",
                 CURLFORM_COPYCONTENTS, data,
                 CURLFORM_END);

    snprintf(data, size, "%d", oj_solution.test);
    curl_formadd(&formpost,
                 &lastptr,
                 CURLFORM_COPYNAME, "test",
                 CURLFORM_COPYCONTENTS, data,
                 CURLFORM_END);

    if (file_path != NULL && access(file_path, F_OK) != -1) {
        truncate_upload_file(file_path);
        FM_LOG_NOTICE("will upload error file %s", file_path);
        curl_formadd(&formpost,
                     &lastptr,
                     CURLFORM_COPYNAME, "error",
                     CURLFORM_FILE, file_path,
                     CURLFORM_END);
    }

    FM_LOG_TRACE("try curl_easy_init");
    curl = curl_easy_init();
    multi_handle = curl_multi_init();

    headerlist = curl_slist_append(headerlist, buf);
    if (curl && multi_handle) {
        FM_LOG_TRACE("curl_multi_init OK");
        curl_easy_setopt(curl, CURLOPT_URL, oj_config.api_url);
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
        curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);

        curl_multi_add_handle(multi_handle, curl);

        curl_multi_perform(multi_handle, &still_running);

        do {
            struct timeval timeout{};
            int rc; /* select() return code */
            CURLMcode mc; /* curl_multi_fdset() return code */

            fd_set fdread;
            fd_set fdwrite;
            fd_set fdexcep;
            int maxfd = -1;

            long curl_timeo = -1;

            FD_ZERO(&fdread);
            FD_ZERO(&fdwrite);
            FD_ZERO(&fdexcep);

            /* set a suitable timeout to play around with */
            timeout.tv_sec = 1;
            timeout.tv_usec = 0;

            curl_multi_timeout(multi_handle, &curl_timeo);
            if (curl_timeo >= 0) {
                timeout.tv_sec = curl_timeo / 1000;
                if (timeout.tv_sec > 1)
                    timeout.tv_sec = 1;
                else
                    timeout.tv_usec = (curl_timeo % 1000) * 1000;
            }

            /* get file descriptors from the transfers */
            mc = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);

            if (mc != CURLM_OK) {
                fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
                break;
            }

            if (maxfd == -1) {
#ifdef _WIN32
                Sleep(100);
                rc = 0;
#else
                /* Portable sleep for platforms other than Windows. */
                struct timeval wait = {0, 100 * 1000}; /* 100ms */
                rc = select(0, NULL, NULL, NULL, &wait);
#endif
            } else {
                /* Note that on some platforms 'timeout' may be modified by select().
                   If you need access to the original value save a copy beforehand. */
                rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
            }

            switch (rc) {
                case -1:
                    /* select error */
                    break;
                case 0:
                default:
                    /* timeout or readable/writable sockets */
                    curl_multi_perform(multi_handle, &still_running);
                    break;
            }
        } while (still_running);

        curl_multi_cleanup(multi_handle);

        curl_easy_cleanup(curl);

        curl_formfree(formpost);

        curl_slist_free_all(headerlist);
        FM_LOG_DEBUG("send_multi_result finished");
    } else {
        FM_LOG_FATAL("cannot init curl: %s", strerror(errno));
        update_system_error(EXIT_CURL_ERROR, oj_solution);
    }
}
예제 #21
0
/*
 * #error "This make CE"
 * #warning "Just warning message"
 * #include </dev/core>
 * #include </dev/zero>
 * #include </dev/random>
 * #include </etc/passwd>
 * #include <../../../etc/passwd>
 * egrep '^\s*#include\s*[<"][./].*[>"]' Main.cc
 */
void compile() {
    update_solution_status(oj_solution.cid, oj_solution.sid, OJ_COM, 0);
    char stdout_compiler[PATH_SIZE];
    char stderr_compiler[PATH_SIZE];
    snprintf(stdout_compiler, PATH_SIZE, "%s/stdout_compiler.txt", oj_solution.work_dir);
    snprintf(stderr_compiler, PATH_SIZE, "%s/stderr_compiler.txt", oj_solution.work_dir);

    pid_t compiler = fork();  // create a child process for compiler

    if (compiler < 0) {
        FM_LOG_FATAL("fork compiler failed: %s", strerror(errno));
        exit(EXIT_FORK_COMPILER);
    } else if (compiler == 0) {
        // child process: run compiler
        log_add_info("compiler");

        set_compile_limit();

        stdout = freopen(stdout_compiler, "w", stdout);
        stderr = freopen(stderr_compiler, "w", stderr);
        if (stdout == nullptr || stderr == nullptr) {
            FM_LOG_FATAL("error freopen: stdout(%p), stderr(%p)", stdout, stderr);
            exit(EXIT_COMPILE_IO);
        }
        print_user_group();
        print_word_dir();

        switch (oj_solution.lang) {
            case LANG_C99:
                print_compiler(CP_C99);
                execvp(CP_C99[0], (char *const *) CP_C99);
                break;
            case LANG_C11:
                print_compiler(CP_C11);
                execvp(CP_C11[0], (char *const *) CP_C11);
                break;
            case LANG_CPP98:
                print_compiler(CP_CC98);
                execvp(CP_CC98[0], (char *const *) CP_CC98);
                break;
            case LANG_CPP11:
                print_compiler(CP_CC11);
                execvp(CP_CC11[0], (char *const *) CP_CC11);
                break;
            case LANG_CPP14:
                print_compiler(CP_CC14);
                execvp(CP_CC14[0], (char *const *) CP_CC14);
                break;
            case LANG_CPP17:
                print_compiler(CP_CC98);
                execvp(CP_CC98[0], (char *const *) CP_CC17);
                break;
            case LANG_PASCAL:
                print_compiler(CP_PAS);
                execvp(CP_PAS[0], (char *const *) CP_PAS);
                break;
            case LANG_JAVA:
                print_compiler(CP_J);
                execvp(CP_J[0], (char *const *) CP_J);
                break;
            case LANG_PYTHON27:
                print_compiler(CP_PY27);
                execvp(CP_PY27[0], (char *const *) CP_PY27);
                break;
            case LANG_PYTHON3:
                print_compiler(CP_PY3);
                execvp(CP_PY3[0], (char *const *) CP_PY3);
                break;
            case LANG_KOTLIN:
                print_compiler(CP_KT);
                execvp(CP_KT[0], (char *const *) CP_KT);
                break;
            default:
                FM_LOG_FATAL("Unknown language %d", oj_solution.lang);
                break;
        }

        // execvp error
        FM_LOG_FATAL("execvp compiler error");
        exit(EXIT_COMPILE_EXEC);
    } else {
        // parent process: Judger
        int status = 0;
        if (waitpid(compiler, &status, WUNTRACED) == -1) {
            FM_LOG_FATAL("waitpid for compiler failed: %s", strerror(errno));
            exit(EXIT_COMPILE_ERROR);  // SE
        }
        FM_LOG_DEBUG("compiler finished");

        if ((oj_solution.lang == LANG_PYTHON27 || oj_solution.lang == LANG_PYTHON3) && file_size(stderr_compiler)) {
            FM_LOG_TRACE("compile error");
            output_acm_result(OJ_CE, 0, 0, 0);
            exit(EXIT_OK);
        }

        if (WIFEXITED(status)) {  // normal termination
            if (EXIT_SUCCESS == WEXITSTATUS(status)) {
                FM_LOG_DEBUG("compile succeeded");
            } else if (GCC_COMPILE_ERROR == WEXITSTATUS(status)) {
                FM_LOG_TRACE("compile error");
                output_acm_result(OJ_CE, 0, 0, 0);
                exit(EXIT_OK);
            } else {
                if (fix_gcc_result(stderr_compiler)) {
                    FM_LOG_WARNING("Compiler Limit Exceeded!");
                    output_acm_result(OJ_CE, 0, 0, 0);
                    exit(EXIT_OK);
                } else {
                    FM_LOG_FATAL("compiler unknown exit status %d", WEXITSTATUS(status));
                    output_acm_result(OJ_CE, 0, 0, 0);
                    exit(EXIT_COMPILE_ERROR);
                }
            }
        } else {
            if (WIFSIGNALED(status)) {  // killed by signal
                int signo = WTERMSIG(status);
                FM_LOG_WARNING("Compiler Limit Exceeded: %s", strsignal(signo));
                output_acm_result(OJ_CE, 0, 0, 0);
                stderr = freopen(stderr_compiler, "w", stderr);
                fprintf(stderr, "Compiler Limit Exceeded: %s\n", strsignal(signo));
                exit(EXIT_OK);
            } else if (WIFSTOPPED(status)) {  // stopped by signal
                int signo = WSTOPSIG(status);
                FM_LOG_FATAL("stopped by signal: %s\n", strsignal(signo));
            } else {
                FM_LOG_FATAL("unknown stop reason, status(%d)", status);
            }
            exit(EXIT_COMPILE_ERROR);  // SE
        }
    }
}
예제 #22
0
/** fmGetDynamicLoadSymbol
 * \ingroup alosDynLoadLib
 *
 * \desc            Find a symbol in a Dynamic Load Library.
 *
 * \param[in]       handle contains the dynamic-load-library's handle.
 *
 * \param[in]       symName points to the symbol whose address is to be retrieved.
 *
 * \param[out]      symAddr points to caller-provided memory into which the
 *                  symbol's address is 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_ERR_NOT_FOUND if the symbol wasn't found in the library.
 * \return          FM_OK if successful.
 *
 *****************************************************************************/
fm_status fmGetDynamicLoadSymbol(fm_int  handle,
                                 fm_text symName,
                                 void ** symAddr)
{
    fm_status      err;
    fm_dynLoadLib *lib;
    void *         addr;
    fm_bool        lockTaken = FALSE;

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

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

    if ( (handle < 0) || (handle >= FM_ALOS_INTERNAL_DYN_LOAD_LIBS) )
    {
        FM_LOG_EXIT(FM_LOG_CAT_ALOS_DLLIB, FM_ERR_INVALID_ARGUMENT);
    }

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

    if (symAddr == NULL)
    {
        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;

    lib = fmRootAlos->dlLibs[handle];

    if (lib == NULL)
    {
        err = FM_ERR_INVALID_ARGUMENT;

        FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_ALOS_DLLIB, err);
    }

    addr = dlsym(ProcessHandles[handle], symName);

    if (addr == NULL)
    {
        FM_LOG_DEBUG(FM_LOG_CAT_ALOS_DLLIB, "Unable to find symbol: %s", symName);
        err = FM_ERR_NOT_FOUND;
        FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_ALOS_DLLIB, err);
    }

    *symAddr = addr;
    err      = FM_OK;


ABORT:

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

    FM_LOG_EXIT(FM_LOG_CAT_ALOS_DLLIB, err);

}   /* end fmGetDynamicLoadSymbol */
예제 #23
0
/** fmCommonResetLBGDistributionForRedirect
 * \ingroup intLbg
 *
 * \desc            This updates the distribution for when the
 *                  mode is FM_LBG_MODE_REDIRECT;
 *
 * \param[in]       sw is the switch number to operate on.
 *
 * \param[in]       group points to the state structure for the group.
 *
 * \return          FM_OK if successful.
 *
 *****************************************************************************/
fm_status fmCommonResetLBGDistributionForRedirect(fm_int sw, fm_LBGGroup *group)
{
    fm_status           err = FM_OK;
    fm_intLBGMember *   lbgMember;
    fm_int              bin = 0;
    
    FM_LOG_ENTRY(FM_LOG_CAT_LBG,
                 "sw=%d group=%p\n",
                 sw, (void *) group);

    if (group->lbgMode != FM_LBG_MODE_REDIRECT)
    {
        FM_LOG_EXIT(FM_LOG_CAT_LBG, FM_ERR_INVALID_ARGUMENT);
    }

    /* Clear old distribution */
    err = ClearUserDistribution(group);
    FM_LOG_EXIT_ON_ERR(FM_LOG_CAT_LBG, err);

    group->lastStripeMember = NULL;
    
    /* Only if there are valid ports to distribute to... */
    if ((group->numActive + group->numFailover) > 0)
    {
        /* Ensure all bins are filled */
        while (bin < group->numBins)
        {
            /* Start out with the actual distribution for all members */
            for ( lbgMember = group->firstMember ;
                  (lbgMember && (bin < group->numBins)) ;
                  lbgMember = lbgMember->nextMember )
            {
                /* Mark each member as not in standby use */
                lbgMember->standbyUsed = FALSE;

                if ((lbgMember->mode == FM_LBG_PORT_ACTIVE) ||
                    (lbgMember->mode == FM_LBG_PORT_FAILOVER))
                {
                    FM_LOG_ASSERT(FM_LOG_CAT_LBG,
                                  ((bin >= 0) && (bin < group->numBins)),
                                  "During redistribution, bin has gone "
                                  "out of range: %d\n",
                                  bin);

                    group->userDistribution[bin] = lbgMember->lbgMemberPort;

                    /* Copy into the hwDistribution for now, we will update later */
                    group->hwDistribution[bin] = lbgMember->lbgMemberPort;

                    /* Keep track of the last member port striped on */
                    group->lastStripeMember = lbgMember;

                    bin++;
                }
            }
        }
    }
    else
    {
        FM_LOG_DEBUG(FM_LOG_CAT_LBG,
                     "No active or failover bins, all bins will drop frames\n");
    }

    /* Handle failover cases */
    for ( lbgMember = group->firstMember ;
          lbgMember ;
          lbgMember = lbgMember->nextMember )
    {
        if (lbgMember->mode == FM_LBG_PORT_FAILOVER)
        {
            RedistributeFailoverSlot(sw, group, lbgMember);
        }
    }

    FM_LOG_EXIT(FM_LOG_CAT_LBG, err);

}   /* end fmCommonResetLBGDistributionForRedirect */
예제 #24
0
int main(int argc, char *argv[], char *envp[]) {
    log_open(LOG_FILE);
    FM_LOG_TRACE("---");
    check_pid();

    int sockfd;
    socklen_t clilen;
    struct sockaddr_in serv_addr{};
    struct sockaddr_in cli_addr{};
    const char *cfg_file;

    if (argc > 1) {
        cfg_file = argv[1];
    } else {
        cfg_file = DEFAULT_CFG_FILE;
    }
    read_config(cfg_file);
    FM_LOG_TRACE("read_config");

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        fatal_error("ERROR opening socket");
    }
    FM_LOG_TRACE("socket");

    bzero((char *) &serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    if (inet_aton(oj_config.ip, &serv_addr.sin_addr) == 0) {
        serv_addr.sin_addr.s_addr = INADDR_ANY;
    }
    serv_addr.sin_port = htons(oj_config.port);
    FM_LOG_NOTICE("IP address: %s %s", oj_config.ip, inet_ntoa(serv_addr.sin_addr));
    FM_LOG_NOTICE("port: %d %d", oj_config.port, ntohs(serv_addr.sin_port));

    int yes = 1;
    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
        fatal_error("setsockopt SO_REUSEADDR failed");
    }

    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
        fatal_error("ERROR on binding");
    }
    FM_LOG_TRACE("bind");

    clilen = sizeof(cli_addr);

    if (listen(sockfd, oj_config.backlog) < 0) {
        fatal_error("ERROR on listening");
    }
    FM_LOG_NOTICE("listen  backlog: %d", oj_config.backlog);

    if (daemon(0, 0) == -1) {
        FM_LOG_FATAL("Cannot daemonize");
        pidfile_remove(pfh);

        exit(EXIT_FAILURE);
    }

    print_word_dir();
    print_user_group();

    pidfile_write(pfh);

    struct sigaction sa{};
    sa.sa_handler = signal_handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    if (sigaction(SIGTERM, &sa, nullptr) == -1) {   // install signal hander for timeout
        FM_LOG_FATAL("cannot handle SIGTERM");
        exit(EXIT_FAILURE);
    } else {
        FM_LOG_DEBUG("set signal_handler");
    }
    for (int i = 0; i < oj_config.thread_num; i++) {
        std::thread t(ThreadWork);
        t.detach();
    }
    FM_LOG_NOTICE("thread count: %d", oj_config.thread_num);

    std::thread(SendWork).detach();

    while (isRunning) {
        int newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
        if (newsockfd != -1) {
            work(newsockfd, cli_addr);
        }
    }

    pidfile_remove(pfh);
    close(sockfd);
    return 0;
}
예제 #25
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 */
예제 #26
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 */
예제 #27
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 */
예제 #28
0
/** fmGlobalEventHandler
 * \ingroup intSwitch
 *
 * \desc            event handler for handling system events
 *
 * \param[in]       args points to the thread arguments
 *
 * \return          Nothing.
 *
 *****************************************************************************/
void *fmGlobalEventHandler(void *args)
{
    fm_thread *               thread;
    fm_event *                event;
    fm_status                 err       = FM_OK;
    fm_eventPort *            portEvent = NULL;
    fm_eventTableUpdateBurst *updateEvent;
    fm_int                    physPort;
    fm_int                    logicalPort;
    fm_eventPktRecv *         rcvPktEvent;
    fm_eventSwitchInserted *  insertEvent;
    fm_eventSwitchRemoved *   removeEvent;
    fm_int                    sw = 0;
    fm_bool                   discardEvent;
    fm_port *                 portPtr = NULL;
    fm_bool                   switchIsProtected;
    fm_switch *               switchPtr;
    fm_int                    mode;
    fm_int                    info[8];
    fm_int                    state;
    fm_int                    numLanes;
    fm_uint32                 i;
    fm_bool                   isPhysicalSwitch;
    fm_switchEventHandler     eventHandler;
    fm_bool                   distributeEvent;
    fm_eventTableUpdate *     fpUpdateEvent;

    /* grab arguments */
    thread = FM_GET_THREAD_HANDLE(args);

    /* wait for initialization to finish before processing events */
    fmCaptureSemaphore(&fmRootApi->startGlobalEventHandler, FM_WAIT_FOREVER);

    enableFramePriority = GET_PROPERTY()->priorityBufQueues;

    while (1)
    {
        /* wait forever for an event */
        err = fmGetThreadEvent(thread, &event, FM_WAIT_FOREVER);

        if (err == FM_ERR_NO_EVENTS_AVAILABLE)
        {
            /* A timeout occurred - should never happen. */
            continue;
        }

        if (event == NULL)
        {
            /* NULL event should never happen. */
            continue;
        }

        sw                = event->sw;
        discardEvent      = FALSE;
        switchIsProtected = FALSE;
        switchPtr         = NULL;

        if (sw < 0 || sw >= fmRootPlatform->cfg.numSwitches)
        {
            discardEvent      = TRUE;
            switchIsProtected = FALSE;
        }
        else if ( SWITCH_LOCK_EXISTS(sw) )
        {
            if ( ( err = PROTECT_SWITCH(sw) ) != FM_OK )
            {
                discardEvent      = TRUE;
                switchIsProtected = FALSE;
            }
            else
            {
                switchIsProtected = TRUE;
                switchPtr         = fmRootApi->fmSwitchStateTable[sw];

                if (!fmRootApi->fmSwitchStateTable[sw])
                {
                    if ((event->type != FM_EVENT_SWITCH_REMOVED) &&
                        (event->type != FM_EVENT_SWITCH_INSERTED) )
                    {
                        discardEvent = TRUE;
                    }
                }
                else if (fmRootApi->fmSwitchStateTable[sw]->state != FM_SWITCH_STATE_UP)
                {
                    if ((event->type != FM_EVENT_SWITCH_REMOVED) &&
                        (event->type != FM_EVENT_SWITCH_INSERTED) )
                    {
                        discardEvent = TRUE;
                    }
                }
            }
        }
        else if (event->type != FM_EVENT_SWITCH_INSERTED)
        {
            discardEvent = TRUE;
        }


        if (discardEvent)
        {
            switch (event->type)
            {
                case FM_EVENT_PKT_RECV:
                case FM_EVENT_SFLOW_PKT_RECV:
                    /* Only dig into the event if the switch is valid */
                    if  ( (sw >= 0) && (sw < fmRootPlatform->cfg.numSwitches) )
                    {
                        rcvPktEvent = &event->info.fpPktEvent;
                        if (enableFramePriority)
                        {
                            err = fmFreeBufferQueueNode(sw, rcvPktEvent);
                            if (err != FM_OK)
                            {
                                FM_LOG_ERROR(FM_LOG_CAT_EVENT_PKT_RX,
                                             "Freeing Buffer queue node from the queue failed"
                                             "status = %d (%s) \n",
                                              err,
                                              fmErrorMsg(err));

                            }
                        }
                        fmFreeBufferChain(sw, rcvPktEvent->pkt);
                        fmDbgDiagCountIncr(sw, FM_CTR_RX_API_PKT_DROPS, 1);
                    }
                    break;

                default:
                    break;
            }

            goto FINISHED;
        }

        eventHandler     = NULL;

        if (switchPtr != NULL)
        {
            /* If the switch state table has an eventHandler pointer,
             * it overrides the global handler.  Call the switch-specific
             * function to handle the event.  This is intended to be used
             * for switches in a switch aggregate (and potentially
             * nested switch aggregates inside other switch aggregates?).
             */
            eventHandler = switchPtr->eventHandler;

            switch (switchPtr->switchModel)
            {
                case FM_SWITCH_MODEL_SWAG:
                    isPhysicalSwitch = FALSE;
                    break;

                default:
                    isPhysicalSwitch = TRUE;
                    break;
            }
        }
        else
        {
            /* Only physical switches should ever get here with a NULL pointer
             * because logical switches such as switch aggregates are always
             * created by application code before any events related to
             * the switch are possible.
             */
            isPhysicalSwitch = TRUE;
        }

        distributeEvent = FALSE;

        switch (event->type)
        {
            case FM_EVENT_SWITCH_INSERTED:
                insertEvent = &event->info.fpSwitchInsertedEvent;
                
                if (switchIsProtected)
                {
                    UNPROTECT_SWITCH(sw);
                    switchIsProtected = FALSE;
                }

                if (switchPtr == NULL)
                {
                    if (fmHandleSwitchInserted(sw, insertEvent) != FM_OK)
                    {
                        /* Don't generate an insert event if there error */
                        goto FINISHED;
                    }
                }

                distributeEvent = TRUE;

                break;

            case FM_EVENT_SWITCH_REMOVED:
                removeEvent = &event->info.fpSwitchRemovedEvent;

                if (switchIsProtected)
                {
                    UNPROTECT_SWITCH(sw);
                    switchIsProtected = FALSE;
                }

                if (switchPtr != NULL)
                {
                    fmHandleSwitchRemoved(sw, removeEvent);
                }

                distributeEvent = TRUE;
                break;

            case FM_EVENT_PORT:
                portEvent = &event->info.fpPortEvent;

                if (isPhysicalSwitch && portEvent->activeMac)
                {
                    logicalPort = portEvent->port;

                    if (switchPtr != NULL)
                    {
                        fmMapLogicalPortToPhysical(switchPtr,
                                                   logicalPort,
                                                   &physPort);

                        portPtr = switchPtr->portTable[logicalPort];
                    }
                    else
                    {
                        portPtr = NULL;
                    }

                    if (portPtr == NULL)
                    {
                        FM_LOG_ERROR(FM_LOG_CAT_EVENT_PORT,
                                     "Unexpected NULL port pointer for logical"
                                     " port %d\n",
                                     logicalPort);
                        break;
                    }

                    /* This attribute indicate whether the API should flush
                     * all the addresses on a port down event or not. */
                    if (GET_PROPERTY()->maFlushOnPortDown)
                    {
                        /* If a link goes down for a non-LAG port, remove any
                         * addresses associated with the port from the MA Table. */
                        if (portEvent->linkStatus == FM_PORT_STATUS_LINK_DOWN)
                        {
                            if (portPtr->portType != FM_PORT_TYPE_LAG)
                            {
                                err = fmFlushPortAddresses(sw, portEvent->port);

                                if (err != FM_OK)
                                {
                                    FM_LOG_WARNING(FM_LOG_CAT_EVENT_PORT,
                                                   "%s\n",
                                                   fmErrorMsg(err));
                                }
                            }
                        }
                    }

                    FM_LOG_DEBUG( FM_LOG_CAT_EVENT_PORT,
                                  "Port %s event reported on port %d.\n",
                                  (portPtr != NULL )
                                    ? ( (portPtr->linkUp) ? "UP  " : "DOWN" )
                                    : "UNKN",
                                  portEvent->port );

                    /* inform LAG module of port state changes */
                    if (portEvent->linkStatus == FM_PORT_STATUS_LINK_UP)
                    {
                        fmInformLAGPortUp(sw, portEvent->port);
                        
                        /* Inform LBGs of port link state change. */
                        FM_API_CALL_FAMILY_VOID(switchPtr->InformLBGLinkChange,
                                                sw, 
                                                portEvent->port, 
                                                FM_PORT_STATUS_LINK_UP);
                    }
                    else if (portEvent->linkStatus == FM_PORT_STATUS_LINK_DOWN)
                    {
                        fmInformLAGPortDown(sw, portEvent->port);
                        
                        /* Inform LBGs of port link state change. */
                        FM_API_CALL_FAMILY_VOID(switchPtr->InformLBGLinkChange,
                                                sw, 
                                                portEvent->port, 
                                                FM_PORT_STATUS_LINK_DOWN);
                    }

                    /* now update all the source masks */
                    fmUpdateSwitchPortMasks(sw);

                    if (switchPtr->UpdateRemoveDownPortsTrigger != NULL)
                    {
                        /**************************************************** 
                         * Update the switchExt->removeDownPortsTrigger
                         * used to drop routed/multicast/special delivery 
                         * frames which can not be handled by the PORT_CFG_2. 
                         * See Bugzilla 11387.
                         ***************************************************/
                        if (portEvent->linkStatus == FM_PORT_STATUS_LINK_UP)
                        {
                            switchPtr->UpdateRemoveDownPortsTrigger(sw, 
                                                                    physPort,
                                                                    FALSE);
                        }
                        else if (portEvent->linkStatus == FM_PORT_STATUS_LINK_DOWN)
                        {
                            if (!portPtr->isPortForceUp)
                            {
                                switchPtr->UpdateRemoveDownPortsTrigger(sw, 
                                                                        physPort,
                                                                        TRUE);
                            }
                        }
                    }

                    if (switchPtr->UpdateMirrorGroups != NULL)
                    {
                        /**************************************************** 
                         * Enable/Disable mirror groups based on the link
                         * status of the mirror port.
                         * See Bugzilla 11387.
                         ***************************************************/
                        if (portEvent->linkStatus == FM_PORT_STATUS_LINK_UP)
                        {
                            switchPtr->UpdateMirrorGroups(sw, 
                                                          logicalPort,
                                                          TRUE);
                        }
                        else if (portEvent->linkStatus == FM_PORT_STATUS_LINK_DOWN)
                        {
                            switchPtr->UpdateMirrorGroups(sw, 
                                                          logicalPort,
                                                          FALSE);
                        }
                    }

                    /* notify anyone else who needs to know */
                    if (portPtr && portPtr->NotifyLinkEvent)
                    {
                        err = portPtr->NotifyLinkEvent(sw, portEvent->port);

                        if (err != FM_OK)
                        {
                            FM_LOG_WARNING(FM_LOG_CAT_EVENT_PORT,
                                           "%s\n",
                                           fmErrorMsg(err));
                        }
                    }

                    /* Get port state and notify platform */

                    err = fmGetPortStateV3( sw,
                                            portEvent->port,
                                            portEvent->mac,
                                            8,
                                            &numLanes,
                                            &mode,
                                            &state,
                                            info );

                    if (err != FM_OK)
                    {
                        FM_LOG_WARNING(FM_LOG_CAT_EVENT_PORT,
                                       "fmGetPortState(%d,%u) failed: %s\n",
                                       sw,
                                       portEvent->port,
                                       fmErrorMsg(err));
                    }

                    fmPlatformNotifyPortState(sw,
                                              portEvent->port,
                                              portEvent->mac,
                                              FALSE,
                                              state);

                    if (switchIsProtected)
                    {
                        UNPROTECT_SWITCH(sw);
                        switchIsProtected = FALSE;
                    }

                }   /* end if (isPhysicalSwitch) */

                distributeEvent = TRUE;
                break;

            case FM_EVENT_PKT_RECV:
            case FM_EVENT_SFLOW_PKT_RECV:
                fmDbgDiagCountIncr(sw, FM_CTR_RX_API_PKT_FWD, 1);
                distributeEvent = TRUE;
                break;

            case FM_EVENT_PURGE_SCAN_COMPLETE:
                distributeEvent = TRUE;
                break; 

            case FM_EVENT_TABLE_UPDATE:
                if (switchPtr == NULL)
                {
                    break;
                }

                /* Update diagnostic counters. */
                updateEvent = &event->info.fpUpdateEvent;
                i = 0;

                while (i < updateEvent->numUpdates)
                {
                    fpUpdateEvent = &updateEvent->updates[i];

                    if (fpUpdateEvent->event == FM_EVENT_ENTRY_LEARNED)
                    {
                        /* Make sure the MA Table entry matches the entry
                         * in the update event. */
                        if (switchPtr->RemoveStaleLearnEvent != NULL &&
                            switchPtr->RemoveStaleLearnEvent(sw, updateEvent, i))
                        {
                            /* The learn event has been removed.
                             * Do not update 'i', since it now contains the 
                             * following event (if any). */
                            fmDbgDiagCountIncr(sw, FM_CTR_MAC_LEARN_DISCARDED, 1);
                        }
                        else
                        {
                            fmDbgDiagCountIncr(sw, FM_CTR_MAC_ALPS_LEARN, 1);
                            i++;
                        }
                    }
                    else
                    {
                        if (fpUpdateEvent->event == FM_EVENT_ENTRY_AGED)
                        {
                            fmDbgDiagCountIncr(sw, FM_CTR_MAC_ALPS_AGE, 1);
                        }
                        i++;
                    }
                }

                /* If all updates have been removed, don't distribute the
                   event */
                if (updateEvent->numUpdates > 0)
                {
                    distributeEvent = TRUE;
                }
                break;

            case FM_EVENT_SECURITY:
            case FM_EVENT_FRAME:
            case FM_EVENT_SOFTWARE:
            case FM_EVENT_PARITY_ERROR:
            case FM_EVENT_FIBM_THRESHOLD:
            case FM_EVENT_CRM:
            case FM_EVENT_ARP:
            case FM_EVENT_EGRESS_TIMESTAMP:
            case FM_EVENT_PLATFORM:
            case FM_EVENT_LOGICAL_PORT:
                distributeEvent = TRUE;
                break;

            default:
                FM_LOG_WARNING(FM_LOG_CAT_EVENT_PORT,
                               "Received unknown event %d\n",
                               event->type);
                break;

        }   /* end switch (event->type) */

        if (distributeEvent)
        {
            if (switchIsProtected)
            {
                UNPROTECT_SWITCH(sw);
                switchIsProtected = FALSE;
            }

            if (eventHandler != NULL)
            {
                if (enableFramePriority && 
                    ( (event->type == FM_EVENT_PKT_RECV) ||
                      (event->type == FM_EVENT_SFLOW_PKT_RECV) ) )
                {
                    rcvPktEvent = &event->info.fpPktEvent;
                    err = fmFreeBufferQueueNode(sw, rcvPktEvent);
                    if (err != FM_OK)
                    {
                        FM_LOG_ERROR(FM_LOG_CAT_EVENT_PKT_RX,
                                     "Freeing Buffer queue node from the queue failed"
                                     "status = %d (%s) \n",
                                      err,
                                      fmErrorMsg(err));

                    }
                }

                eventHandler(event);
            }
            else
            {
                fmDistributeEvent(event);
            }
        }

FINISHED:

        fmReleaseEvent(event);

        /* release the switch lock if any is held */
        if (switchIsProtected)
        {
            UNPROTECT_SWITCH(sw);
        }

    }   /* end while (1) */

    fmExitThread(thread);

    return NULL;

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

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

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

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

    stackingInfo = &switchPtr->stackingInfo;

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

    camEntry = &lportInfo->camEntries[camIndex];

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

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

    fwdExt->camEntry = camEntry;

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

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

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

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

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

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

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

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


ABORT:

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

    FM_LOG_EXIT(FM_LOG_CAT_STACKING, err);

}   /* end fm10000CreateForwardingRule */
예제 #30
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 */