示例#1
0
文件: startup.c 项目: skreuzer/ptpd
/**
 * Signal handler for HUP which tells us to swap the log file
 * and reload configuration file if specified
 *
 * @param sig
 */
void
do_signal_sighup(RunTimeOpts * rtOpts, PtpClock * ptpClock)
{



	NOTIFY("SIGHUP received\n");

#ifdef RUNTIME_DEBUG
	if(rtOpts->transport == UDP_IPV4 && rtOpts->ipMode != IPMODE_UNICAST) {
		DBG("SIGHUP - running an ipv4 multicast based mode, re-sending IGMP joins\n");
		netRefreshIGMP(&ptpClock->netPath, rtOpts, ptpClock);
	}
#endif /* RUNTIME_DEBUG */


	/* if we don't have a config file specified, we're done - just reopen log files*/
	if(strlen(rtOpts->configFile) !=  0) {

	    dictionary* tmpConfig = dictionary_new(0);

	    /* Try reloading the config file */
	    NOTIFY("Reloading configuration file: %s\n",rtOpts->configFile);

            if(!loadConfigFile(&tmpConfig, rtOpts)) {

		    dictionary_del(&tmpConfig);

	    } else {
		    dictionary_merge(rtOpts->cliConfig, tmpConfig, 1, 1, "from command line");
		    applyConfig(tmpConfig, rtOpts, ptpClock);
		    dictionary_del(&tmpConfig);

	    }

	}

	/* tell the service it can perform any HUP-triggered actions */
	ptpClock->timingService.reloadRequested = TRUE;

	if(rtOpts->recordLog.logEnabled ||
	    rtOpts->eventLog.logEnabled ||
	    (rtOpts->statisticsLog.logEnabled))
		INFO("Reopening log files\n");

	restartLogging(rtOpts);

	if(rtOpts->statisticsLog.logEnabled)
		ptpClock->resetStatisticsLog = TRUE;


}
示例#2
0
/* perform actions required when leaving 'port_state' and entering 'state' */
void 
toState(UInteger8 state, RunTimeOpts *rtOpts, PtpClock *ptpClock)
{
	ptpClock->message_activity = TRUE;
	
	/* leaving state tasks */
	switch (ptpClock->portState)
	{
	case PTP_MASTER:
		timerStop(SYNC_INTERVAL_TIMER, ptpClock->itimer);  
		timerStop(ANNOUNCE_INTERVAL_TIMER, ptpClock->itimer);
		timerStop(PDELAYREQ_INTERVAL_TIMER, ptpClock->itimer); 
		break;
		
	case PTP_SLAVE:
		timerStop(ANNOUNCE_RECEIPT_TIMER, ptpClock->itimer);
		
		if (ptpClock->delayMechanism == E2E)
			timerStop(DELAYREQ_INTERVAL_TIMER, ptpClock->itimer);
		else if (ptpClock->delayMechanism == P2P)
			timerStop(PDELAYREQ_INTERVAL_TIMER, ptpClock->itimer);
		
		initClock(rtOpts, ptpClock); 
		break;
		
	case PTP_PASSIVE:
		timerStop(PDELAYREQ_INTERVAL_TIMER, ptpClock->itimer);
		timerStop(ANNOUNCE_RECEIPT_TIMER, ptpClock->itimer);
		break;
		
	case PTP_LISTENING:
		timerStop(ANNOUNCE_RECEIPT_TIMER, ptpClock->itimer);
		break;
		
	default:
		break;
	}
	
	/* entering state tasks */

	/*
	 * No need of PRE_MASTER state because of only ordinary clock
	 * implementation.
	 */
	
	switch (state)
	{
	case PTP_INITIALIZING:
		DBG("state PTP_INITIALIZING\n");
		ptpClock->portState = PTP_INITIALIZING;
		break;
		
	case PTP_FAULTY:
		DBG("state PTP_FAULTY\n");
		ptpClock->portState = PTP_FAULTY;
		break;
		
	case PTP_DISABLED:
		DBG("state PTP_DISABLED\n");
		ptpClock->portState = PTP_DISABLED;
		break;
		
	case PTP_LISTENING:
		/* in Listening mode, make sure we don't send anything. Instead we just expect/wait for announces (started below) */
		timerStop(SYNC_INTERVAL_TIMER,      ptpClock->itimer);
		timerStop(ANNOUNCE_INTERVAL_TIMER,  ptpClock->itimer);
		timerStop(PDELAYREQ_INTERVAL_TIMER, ptpClock->itimer);
		timerStop(DELAYREQ_INTERVAL_TIMER,  ptpClock->itimer);
		
		/*
		 *  Count how many _unique_ timeouts happen to us.
		 *  If we were already in Listen mode, then do not count this as a seperate reset, but stil do a new IGMP refresh
		 */
		if (ptpClock->portState != PTP_LISTENING) {
			ptpClock->reset_count++;
		}

		/* Revert to the original DelayReq interval, and ignore the one for the last master */
		ptpClock->logMinDelayReqInterval = rtOpts->initial_delayreq;

		/* force a IGMP refresh per reset */
		if (rtOpts->do_IGMP_refresh) {
			netRefreshIGMP(&ptpClock->netPath, rtOpts, ptpClock);
		}
		

		DBG("state PTP_LISTENING\n");
		INFO("  now in state PTP_LISTENING\n");
		timerStart(ANNOUNCE_RECEIPT_TIMER, 
			   (ptpClock->announceReceiptTimeout) * 
			   (pow(2,ptpClock->logAnnounceInterval)), 
			   ptpClock->itimer);
		ptpClock->portState = PTP_LISTENING;
		break;

	case PTP_MASTER:
		DBG("state PTP_MASTER\n");
		INFO("  now in state PTP_MASTER\n");
		
		timerStart(SYNC_INTERVAL_TIMER, 
			   pow(2,ptpClock->logSyncInterval), ptpClock->itimer);
		DBG("SYNC INTERVAL TIMER : %f \n",
		    pow(2,ptpClock->logSyncInterval));
		timerStart(ANNOUNCE_INTERVAL_TIMER, 
			   pow(2,ptpClock->logAnnounceInterval), 
			   ptpClock->itimer);
		timerStart(PDELAYREQ_INTERVAL_TIMER, 
			   pow(2,ptpClock->logMinPdelayReqInterval), 
			   ptpClock->itimer);
		ptpClock->portState = PTP_MASTER;
		break;

	case PTP_PASSIVE:
		DBG("state PTP_PASSIVE\n");
		INFO("  now in state PTP_PASSIVE\n");

		
		timerStart(PDELAYREQ_INTERVAL_TIMER, 
			   pow(2,ptpClock->logMinPdelayReqInterval), 
			   ptpClock->itimer);
		timerStart(ANNOUNCE_RECEIPT_TIMER, 
			   (ptpClock->announceReceiptTimeout) * 
			   (pow(2,ptpClock->logAnnounceInterval)), 
			   ptpClock->itimer);
		ptpClock->portState = PTP_PASSIVE;
		p1(ptpClock, rtOpts);
		break;

	case PTP_UNCALIBRATED:
		DBG("state PTP_UNCALIBRATED\n");
		ptpClock->portState = PTP_UNCALIBRATED;
		break;

	case PTP_SLAVE:
		DBG("state PTP_SLAVE\n");
		INFO("  now in state PTP_SLAVE\n");
		
		initClock(rtOpts, ptpClock);
		
		ptpClock->waitingForFollow = FALSE;
		ptpClock->waitingForDelayResp = FALSE;

		// FIXME: clear these vars inside initclock
		clearTime(&ptpClock->pdelay_req_send_time);
		clearTime(&ptpClock->pdelay_req_receive_time);
		clearTime(&ptpClock->pdelay_resp_send_time);
		clearTime(&ptpClock->pdelay_resp_receive_time);
		
		timerStart(OPERATOR_MESSAGES_TIMER,
			   OPERATOR_MESSAGES_INTERVAL,
			   ptpClock->itimer);
		
		timerStart(ANNOUNCE_RECEIPT_TIMER,
			   (ptpClock->announceReceiptTimeout) * 
			   (pow(2,ptpClock->logAnnounceInterval)), 
			   ptpClock->itimer);
		
		/*
		 * Previously, this state transition would start the delayreq timer immediately.
		 * However, if this was faster than the first received sync, then the servo would drop the delayResp
		 * Now, we only start the timer after we receive the first sync (in handle_sync())
		 */
		ptpClock->waiting_for_first_sync = TRUE;
		ptpClock->waiting_for_first_delayresp = TRUE;

		ptpClock->portState = PTP_SLAVE;
		break;

	default:
		DBG("to unrecognized state\n");
		break;
	}

	if (rtOpts->displayStats)
		displayStats(rtOpts, ptpClock);
}
示例#3
0
文件: startup.c 项目: DomChey/ptpd
/**
 * Signal handler for HUP which tells us to swap the log file
 * and reload configuration file if specified
 *
 * @param sig
 */
void
do_signal_sighup(RunTimeOpts * rtOpts, PtpClock * ptpClock)
{

    NOTIFY("SIGHUP received\n");

#ifdef RUNTIME_DEBUG
    if(rtOpts->transport == UDP_IPV4 && rtOpts->ip_mode != IPMODE_UNICAST) {
        DBG("SIGHUP - running an ipv4 multicast based mode, re-sending IGMP joins\n");
        netRefreshIGMP(&ptpClock->netPath, rtOpts, ptpClock);
    }
#endif /* RUNTIME_DEBUG */


    /* if we don't have a config file specified, we're done - just reopen log files*/
    if(strlen(rtOpts->configFile) ==  0)
        goto end;

    dictionary* tmpConfig = dictionary_new(0);
    /* Try reloading the config file */
    NOTIFY("Reloading configuration file: %s\n",rtOpts->configFile);
    if(!loadConfigFile(&tmpConfig, rtOpts)) {
        dictionary_del(tmpConfig);
        goto end;
    }
    dictionary_merge(rtOpts->cliConfig, tmpConfig, 1, "from command line");
    /* Load default config to fill in the blanks in the config file */
    RunTimeOpts tmpOpts;
    loadDefaultSettings(&tmpOpts);

    /* Check the new configuration for errors, fill in the blanks from defaults */
    if( ( rtOpts->candidateConfig = parseConfig(tmpConfig,&tmpOpts)) == NULL ) {
        WARNING("Configuration file has errors, reload aborted\n");
        dictionary_del(tmpConfig);
        goto end;
    }

    /* Check for changes between old and new configuration */
    if(compareConfig(rtOpts->candidateConfig,rtOpts->currentConfig)) {
        INFO("Configuration unchanged\n");
        goto cleanup;
    }

    /*
     * Mark which subsystems have to be restarted. Most of this will be picked up by doState()
     * If there are errors past config correctness (such as non-existent NIC,
     * or lock file clashes if automatic lock files used - abort the mission
     */

    rtOpts->restartSubsystems =
        checkSubsystemRestart(rtOpts->candidateConfig, rtOpts->currentConfig);

    /* If we're told to re-check lock files, do it: tmpOpts already has what rtOpts should */
    if( (rtOpts->restartSubsystems & PTPD_CHECK_LOCKS) &&
            tmpOpts.autoLockFile && !checkOtherLocks(&tmpOpts)) {
        rtOpts->restartSubsystems = -1;
    }

    /* If the network configuration has changed, check if the interface is OK */
    if(rtOpts->restartSubsystems & PTPD_RESTART_NETWORK) {
        INFO("Network configuration changed - checking interface\n");
        if(!testInterface(tmpOpts.ifaceName, &tmpOpts)) {
            rtOpts->restartSubsystems = -1;
            ERROR("Error: Cannot use %s interface\n",tmpOpts.ifaceName);
        }

    }


#if defined(linux) && defined(HAVE_SCHED_H)
    /* Changing the CPU affinity mask */
    if(rtOpts->restartSubsystems & PTPD_CHANGE_CPUAFFINITY) {
        NOTIFY("Applying CPU binding configuration: changing selected CPU core\n");
        cpu_set_t mask;
        CPU_ZERO(&mask);
        if(tmpOpts.cpuNumber > -1) {
            CPU_SET(tmpOpts.cpuNumber,&mask);
        } else {
            int i;
            for(i = 0;  i < CPU_SETSIZE; i++) {
                CPU_SET(i, &mask);
            }
        }
        if(sched_setaffinity(0, sizeof(mask), &mask) < 0) {
            if(tmpOpts.cpuNumber == -1) {
                PERROR("Could not unbind from CPU core %d", rtOpts->cpuNumber);
            } else {
                PERROR("Could bind to CPU core %d", tmpOpts.cpuNumber);
            }
            rtOpts->restartSubsystems = -1;
        } else {
            if(tmpOpts.cpuNumber > -1)
                INFO("Successfully bound "PTPD_PROGNAME" to CPU core %d\n", tmpOpts.cpuNumber);
            else
                INFO("Successfully unbound "PTPD_PROGNAME" from cpu core CPU core %d\n", rtOpts->cpuNumber);
        }
    }
#endif /* linux && HAVE_SCHED_H */

#ifdef HAVE_SYS_CPUSET_H
    /* Changing the CPU affinity mask */
    if (rtOpts->restartSubsystems & PTPD_CHANGE_CPUAFFINITY) {
        NOTIFY("Applying CPU binding configuration:"
               "changing selected CPU core\n");
        cpuset_t mask;
        CPU_ZERO(&mask);
        if (tmpOpts.cpuNumber < 0) {
            if (cpuset_getaffinity(CPU_LEVEL_ROOT, CPU_WHICH_CPUSET, 1,
                                   sizeof(mask), &mask) < 0)
                PERROR("Could not get affinity.");
            if (cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID,
                                   -1, sizeof(mask), &mask) < 0)
                PERROR("Could not unbind from CPU core %d",
                       rtOpts->cpuNumber);
            else
                INFO("Successfully unbound "
                     PTPD_PROGNAME" from cpu core CPU core %d\n",
                     rtOpts->cpuNumber);
        } else {
            CPU_SET(tmpOpts.cpuNumber,&mask);
            if (cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID,
                                   -1, sizeof(mask), &mask) < 0)  {
                PERROR("Could not bind to CPU core %d",
                       tmpOpts.cpuNumber);
                rtOpts->restartSubsystems = -1;
            } else {
                INFO("Successfully bound "
                     PTPD_PROGNAME" to CPU core %d\n",
                     tmpOpts.cpuNumber);
            }
        }
    }
#endif

    if(rtOpts->restartSubsystems == -1) {
        ERROR("New configuration cannot be applied - aborting reload\n");
        rtOpts->restartSubsystems = 0;
        goto cleanup;
    }


    /* Tell parseConfig to shut up - it's had its chance already */
    dictionary_set(rtOpts->candidateConfig,"%quiet%:%quiet%","Y");

    /**
     * Commit changes to rtOpts and currentConfig
     * (this should never fail as the config has already been checked if we're here)
     * However if this DOES fail, some default has been specified out of range -
     * this is the only situation where parse will succeed but commit not:
     * disable quiet mode to show what went wrong, then die.
     */
    if (rtOpts->currentConfig) {
        dictionary_del(rtOpts->currentConfig);
    }
    if ( (rtOpts->currentConfig = parseConfig(rtOpts->candidateConfig,rtOpts)) == NULL) {
        CRITICAL("************ "PTPD_PROGNAME": parseConfig returned NULL during config commit"
                 "  - this is a BUG - report the following: \n");

        dictionary_unset(rtOpts->candidateConfig,"%quiet%:%quiet%");

        if ((rtOpts->currentConfig = parseConfig(rtOpts->candidateConfig,rtOpts)) == NULL)
            CRITICAL("*****************" PTPD_PROGNAME" shutting down **********************\n");
        /*
         * Could be assert(), but this should be done any time this happens regardless of
         * compile options. Anyhow, if we're here, the daemon will no doubt segfault soon anyway
         */
        abort();
    }

    /* clean up */
cleanup:

    dictionary_del(tmpConfig);
    dictionary_del(rtOpts->candidateConfig);

end:

    if(rtOpts->recordLog.logEnabled ||
            rtOpts->eventLog.logEnabled ||
            (rtOpts->statisticsLog.logEnabled))
        INFO("Reopening log files\n");

    restartLogging(rtOpts);

    if(rtOpts->statisticsLog.logEnabled)
        ptpClock->resetStatisticsLog = TRUE;


}