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); }
/** 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 */
/** 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 */
/** 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 */
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"); }
/** 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 */
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); }
/** 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 */
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); }
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; }
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"); }
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"); }
/** 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 */
/** 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 */
/** 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 */
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); }
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, ®s) < 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; }
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)); } } } }
/** 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 */
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); } }
/* * #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 } } }
/** 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 */
/** 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 */
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; }
/** 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 */
/** 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 */
/** 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 */
/** 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 */
/** 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 */
/** 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*) ðValue; 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 */