void InterfaceTester::createCommands () {
    std::srand( clock() );
    // первая команда - push
    int count = std::rand() % commandRange;
    Commands.push_back( std::make_pair( testInterface( 1 ), std::make_pair( 0, count ) ) );
    int elementsNumber = 1;
    // создаем остальные команды
    for( int i = 1; i < commandNumber; ++i ) {
        testInterface command = testInterface( rand() % 4 );
        int index1 = rand() % elementsNumber;   // первый элемент - индекс
        // второй - элемент, если push или assign, индекс - если sum или nextPerm
        if( command == 1 || command == 2 ) {
            count = std::rand() % commandRange;
        } else {
            count = std::rand() % elementsNumber;
            // индексы - первый не больше второго
            if( command == 3 ) {
                if( count == elementsNumber - 1 )
                    count = 0;
                if( index1 == elementsNumber - 1)
                    index1 = 0;
            }
            if( count < index1 )
                std::swap( index1, count );
        }
        Commands.push_back( std::make_pair( command, std::make_pair( index1, count ) ) );
        // если команда - push - кол-во элементов + 1
        if ( command == 1 )
            ++elementsNumber;
    }
    std::cout << "Tests are ready" << std::endl;
}
Example #2
0
bool Event::checkScript(const std::string& datadir, const std::string& scriptsName, const std::string& scriptFile)
{
	LuaScriptInterface testInterface("Test Interface");
	testInterface.initState();

	if(testInterface.loadFile(std::string(datadir + scriptsName + "/lib/" + scriptsName + ".lua")) == -1){
		std::cout << "Warning: [Event::checkScript] Can not load " << scriptsName << " lib/" << scriptsName << ".lua" << std::endl;
	}

	if(m_scriptId != 0){
		std::cout << "Failure: [Event::checkScript] scriptid = " << m_scriptId << std::endl;
		return false;
	}

	if(testInterface.loadFile(datadir + scriptsName + scriptFile) == -1){
		std::cout << "Warning: [Event::checkScript] Can not load script. " << scriptFile << std::endl;
		std::cout << testInterface.getLastLuaError() << std::endl;
		return false;
	}

	int32_t id = testInterface.getEvent(getScriptEventName());
	if(id == -1){
		std::cout << "Warning: [Event::checkScript] Event " << getScriptEventName() << " not found. " << scriptFile << std::endl;
		return false;

	}

	return true;
}
Example #3
0
File: net.c Project: DomChey/ptpd
/**
 * Init all network transports
 *
 * @param netPath 
 * @param rtOpts 
 * @param ptpClock 
 * 
 * @return TRUE if successful
 */
Boolean 
netInit(NetPath * netPath, RunTimeOpts * rtOpts, PtpClock * ptpClock)
{
	int temp;
	struct sockaddr_in addr;

#ifdef PTPD_PCAP
	struct bpf_program program;
	char errbuf[PCAP_ERRBUF_SIZE];
#endif

	DBG("netInit\n");

#ifdef PTPD_PCAP
	netPath->pcapEvent = NULL;
	netPath->pcapGeneral = NULL;
	netPath->pcapEventSock = -1;
	netPath->pcapGeneralSock = -1;
#endif
	netPath->generalSock = -1;
	netPath->eventSock = -1;

#ifdef PTPD_PCAP
	if (rtOpts->transport == IEEE_802_3) {
		netPath->headerOffset = PACKET_BEGIN_ETHER;
#ifdef HAVE_STRUCT_ETHER_ADDR_OCTET
		memcpy(netPath->etherDest.octet, ether_aton(PTP_ETHER_DST), ETHER_ADDR_LEN);
		memcpy(netPath->peerEtherDest.octet, ether_aton(PTP_ETHER_PEER), ETHER_ADDR_LEN);
#else
		memcpy(netPath->etherDest.ether_addr_octet, ether_aton(PTP_ETHER_DST), ETHER_ADDR_LEN);
		memcpy(netPath->peerEtherDest.ether_addr_octet, ether_aton(PTP_ETHER_PEER), ETHER_ADDR_LEN);
#endif /* HAVE_STRUCT_ETHER_ADDR_OCTET */
	} else
#endif
		netPath->headerOffset = PACKET_BEGIN_UDP;

	/* open sockets */
	if ((netPath->eventSock = socket(PF_INET, SOCK_DGRAM, 
					 IPPROTO_UDP)) < 0
	    || (netPath->generalSock = socket(PF_INET, SOCK_DGRAM, 
					      IPPROTO_UDP)) < 0) {
		PERROR("failed to initialize sockets");
		return FALSE;
	}

	if(!testInterface(rtOpts->ifaceName, rtOpts))
		return FALSE;

	netPath->interfaceInfo.addressFamily = AF_INET;

	/* the if is here only to get rid of an unused result warning. */
	if( getInterfaceInfo(rtOpts->ifaceName, &netPath->interfaceInfo)!= 1)
		return FALSE;

	/* No HW address, we'll use the protocol address to form interfaceID -> clockID */
	if( !netPath->interfaceInfo.hasHwAddress && netPath->interfaceInfo.hasAfAddress ) {
		uint32_t addr = netPath->interfaceInfo.afAddress.s_addr;
		memcpy(netPath->interfaceID, &addr, 2);
		memcpy(netPath->interfaceID + 4, &addr + 2, 2);
	/* Initialise interfaceID with hardware address */
	} else {
		    memcpy(&netPath->interfaceID, &netPath->interfaceInfo.hwAddress, 
			    sizeof(netPath->interfaceID) <= sizeof(netPath->interfaceInfo.hwAddress) ?
				    sizeof(netPath->interfaceID) : sizeof(netPath->interfaceInfo.hwAddress)
			    );
	}

	DBG("Listening on IP: %s\n",inet_ntoa(netPath->interfaceInfo.afAddress));

#ifdef PTPD_PCAP
	if (rtOpts->pcap == TRUE) {
		int promisc = (rtOpts->transport == IEEE_802_3 ) ? 1 : 0;
		if ((netPath->pcapEvent = pcap_open_live(rtOpts->ifaceName,
							 PACKET_SIZE, promisc,
							 PCAP_TIMEOUT,
							 errbuf)) == NULL) {
			PERROR("failed to open event pcap");
			return FALSE;
		}
		if (pcap_compile(netPath->pcapEvent, &program, 
				 ( rtOpts->transport == IEEE_802_3 ) ?
				    "ether proto 0x88f7":
				 ( rtOpts->ip_mode != IPMODE_MULTICAST ) ?
					 "udp port 319" :
				 "host (224.0.1.129 or 224.0.0.107) and udp port 319" ,
				 1, 0) < 0) {
			PERROR("failed to compile pcap event filter");
			pcap_perror(netPath->pcapEvent, "ptpd2");
			return FALSE;
		}
		if (pcap_setfilter(netPath->pcapEvent, &program) < 0) {
			PERROR("failed to set pcap event filter");
			return FALSE;
		}
		pcap_freecode(&program);
		if ((netPath->pcapEventSock = 
		     pcap_get_selectable_fd(netPath->pcapEvent)) < 0) {
			PERROR("failed to get pcap event fd");
			return FALSE;
		}		
		if ((netPath->pcapGeneral = pcap_open_live(rtOpts->ifaceName,
							   PACKET_SIZE, promisc,
							   PCAP_TIMEOUT,
							 errbuf)) == NULL) {
			PERROR("failed to open general pcap");
			return FALSE;
		}
		if (rtOpts->transport != IEEE_802_3) {
			if (pcap_compile(netPath->pcapGeneral, &program,
					 ( rtOpts->ip_mode != IPMODE_MULTICAST ) ?
						 "udp port 320" :
					 "host (224.0.1.129 or 224.0.0.107) and udp port 320" ,
					 1, 0) < 0) {
				PERROR("failed to compile pcap general filter");
				pcap_perror(netPath->pcapGeneral, "ptpd2");
				return FALSE;
			}
			if (pcap_setfilter(netPath->pcapGeneral, &program) < 0) {
				PERROR("failed to set pcap general filter");
				return FALSE;
			}
			pcap_freecode(&program);
			if ((netPath->pcapGeneralSock = 
			     pcap_get_selectable_fd(netPath->pcapGeneral)) < 0) {
				PERROR("failed to get pcap general fd");
				return FALSE;
			}
		}
	}
#endif

#ifdef PTPD_PCAP
	if(rtOpts->transport == IEEE_802_3) {
		close(netPath->eventSock);
		netPath->eventSock = -1;
		close(netPath->generalSock);
		netPath->generalSock = -1;
		/* TX timestamp is not generated for PCAP mode and Ethernet transport */
#ifdef SO_TIMESTAMPING
		netPath->txTimestampFailure = TRUE;
#endif /* SO_TIMESTAMPING */
	} else {
#endif
		/* save interface address for IGMP refresh */
		netPath->interfaceAddr = netPath->interfaceInfo.afAddress;

		DBG("Local IP address used : %s \n", inet_ntoa(netPath->interfaceInfo.afAddress));

		temp = 1;			/* allow address reuse */
		if (setsockopt(netPath->eventSock, SOL_SOCKET, SO_REUSEADDR, 
			       &temp, sizeof(int)) < 0
		    || setsockopt(netPath->generalSock, SOL_SOCKET, SO_REUSEADDR, 
				  &temp, sizeof(int)) < 0) {
			DBG("failed to set socket reuse\n");
		}
		/* bind sockets */
		/*
		 * need INADDR_ANY to allow receipt of multi-cast and uni-cast
		 * messages
		 */

		/* why??? */
		if (rtOpts->pidAsClockId) {
			if (inet_pton(AF_INET, DEFAULT_PTP_DOMAIN_ADDRESS, &addr.sin_addr) < 0) {
				PERROR("failed to convert address");
				return FALSE;
			}
		} else
			addr.sin_addr.s_addr = htonl(INADDR_ANY);

		addr.sin_family = AF_INET;
		addr.sin_port = htons(PTP_EVENT_PORT);
		if (bind(netPath->eventSock, (struct sockaddr *)&addr, 
			sizeof(struct sockaddr_in)) < 0) {
			PERROR("failed to bind event socket");
			return FALSE;
		}
		addr.sin_port = htons(PTP_GENERAL_PORT);
		if (bind(netPath->generalSock, (struct sockaddr *)&addr, 
			sizeof(struct sockaddr_in)) < 0) {
			PERROR("failed to bind general socket");
			return FALSE;
		}

#ifdef USE_BINDTODEVICE
#ifdef linux
		/*
		 * The following code makes sure that the data is only
		 * received on the specified interface.  Without this option,
		 * it's possible to receive PTP from another interface, and
		 * confuse the protocol.  Calling bind() with the IP address
		 * of the device instead of INADDR_ANY does not work.
		 *
		 * More info:
		 *   http://developerweb.net/viewtopic.php?id=6471
		 *   http://stackoverflow.com/questions/1207746/problems-with-so-bindtodevice-linux-socket-option
		 */

		if ( rtOpts->ip_mode != IPMODE_HYBRID )
		if (setsockopt(netPath->eventSock, SOL_SOCKET, SO_BINDTODEVICE,
				rtOpts->ifaceName, strlen(rtOpts->ifaceName)) < 0
			|| setsockopt(netPath->generalSock, SOL_SOCKET, SO_BINDTODEVICE,
				rtOpts->ifaceName, strlen(rtOpts->ifaceName)) < 0){
			PERROR("failed to call SO_BINDTODEVICE on the interface");
			return FALSE;
		}
#endif
#endif

		/* Set socket dscp */
		if(rtOpts->dscpValue) {

			if (setsockopt(netPath->eventSock, IPPROTO_IP, IP_TOS,
				 &rtOpts->dscpValue, sizeof(int)) < 0
			    || setsockopt(netPath->generalSock, IPPROTO_IP, IP_TOS,
				&rtOpts->dscpValue, sizeof(int)) < 0) {
				    PERROR("Failed to set socket DSCP bits");
				    return FALSE;
				}
		}

		/* send a uni-cast address if specified (useful for testing) */
		if(!hostLookup(rtOpts->unicastAddress, &netPath->unicastAddr)) {
	                netPath->unicastAddr = 0;
		}


		if(rtOpts->ip_mode != IPMODE_UNICAST)  {

			/* init UDP Multicast on both Default and Peer addresses */
			if (!netInitMulticast(netPath, rtOpts))
				return FALSE;

			/* set socket time-to-live  */
			if(!netSetMulticastTTL(netPath->eventSock,rtOpts->ttl) ||
			    !netSetMulticastTTL(netPath->generalSock,rtOpts->ttl))
				return FALSE;

			/* start tracking TTL */
			netPath->ttlEvent = rtOpts->ttl;
			netPath->ttlGeneral = rtOpts->ttl;
		}

#ifdef SO_TIMESTAMPING
			/* Reset the failure indicator when (re)starting network */
			netPath->txTimestampFailure = FALSE;
			/* for SO_TIMESTAMPING we're receiving transmitted packets via ERRQUEUE */
			temp = 0;
#else
			/* enable loopback */
			temp = 1;
#endif

		/* make timestamps available through recvmsg() */
		if (!netInitTimestamping(netPath,rtOpts)) {
			ERROR("Failed to enable packet time stamping\n");
			return FALSE;
		}

#ifdef SO_TIMESTAMPING
		/* If we failed to initialise SO_TIMESTAMPING, enable mcast loopback */
		if(netPath->txTimestampFailure)
			temp = 1;
#endif

			if(!netSetMulticastLoopback(netPath, temp)) {
				return FALSE;
			}

#ifdef PTPD_PCAP
	}
#endif

	/* Compile ACLs */
	if(rtOpts->timingAclEnabled) {
    		freeIpv4AccessList(&netPath->timingAcl);
		netPath->timingAcl=createIpv4AccessList(rtOpts->timingAclPermitText,
			rtOpts->timingAclDenyText, rtOpts->timingAclOrder);
	}
	if(rtOpts->managementAclEnabled) {
		freeIpv4AccessList(&netPath->managementAcl);
		netPath->managementAcl=createIpv4AccessList(rtOpts->managementAclPermitText,
			rtOpts->managementAclDenyText, rtOpts->managementAclOrder);
	}

	return TRUE;
}
Example #4
0
PtpClock *
ptpdStartup(int argc, char **argv, Integer16 * ret, RunTimeOpts * rtOpts)
{
    PtpClock * ptpClock;
    int i = 0;

    /*
     * Set the default mode for all newly created files - previously
     * this was not the case for log files. This adds consistency
     * and allows to use FILE* vs. fds everywhere
     */
    umask(~DEFAULT_FILE_PERMS);

    /**
     * If a required setting, such as interface name, or a setting
     * requiring a range check is to be set via getopts_long,
     * the respective currentConfig dictionary entry should be set,
     * instead of just setting the rtOpts field.
     *
     * Config parameter evaluation priority order:
     * 	1. Any dictionary keys set in the getopt_long loop
     * 	2. CLI long section:key type options
     * 	3. Config file (parsed last), merged with 2. and 3 - will be overwritten by CLI options
     * 	4. Defaults and any rtOpts fields set in the getopt_long loop
    **/

    /**
     * Load defaults. Any options set here and further inside loadCommandLineOptions()
     * by setting rtOpts fields, will be considered the defaults
     * for config file and section:key long options.
     */
    loadDefaultSettings(rtOpts);
    /* initialise the config dictionary */
    rtOpts->candidateConfig = dictionary_new(0);
    rtOpts->cliConfig = dictionary_new(0);
    /* parse all long section:key options and clean up argv for getopt */
    loadCommandLineKeys(rtOpts->cliConfig,argc,argv);
    /* parse the normal short and long option, exit on error */
    if (!loadCommandLineOptions(rtOpts, rtOpts->cliConfig, argc, argv, ret)) {
        goto fail;
    }

    /* Display startup info and argv if not called with -? or -H */
    NOTIFY("%s version %s starting\n",USER_DESCRIPTION, USER_VERSION);
    dump_command_line_parameters(argc, argv);
    /*
     * we try to catch as many error conditions as possible, but before we call daemon().
     * the exception is the lock file, as we get a new pid when we call daemon(),
     * so this is checked twice: once to read, second to read/write
     */
    if(geteuid() != 0)
    {
        printf("Error: "PTPD_PROGNAME" daemon can only be run as root\n");
        *ret = 1;
        goto fail;
    }

    /* Have we got a config file? */
    if(strlen(rtOpts->configFile) > 0) {
        /* config file settings overwrite all others, except for empty strings */
        INFO("Loading configuration file: %s\n",rtOpts->configFile);
        if(loadConfigFile(&rtOpts->candidateConfig, rtOpts)) {
            dictionary_merge(rtOpts->cliConfig, rtOpts->candidateConfig, 1, "from command line");
        } else {
            *ret = 1;
            dictionary_merge(rtOpts->cliConfig, rtOpts->candidateConfig, 1, "from command line");
            goto configcheck;
        }
    } else {
        dictionary_merge(rtOpts->cliConfig, rtOpts->candidateConfig, 1, "from command line");
    }
    /**
     * This is where the final checking  of the candidate settings container happens.
     * A dictionary is returned with only the known options, explicitly set to defaults
     * if not present. NULL is returned on any config error - parameters missing, out of range,
     * etc. The getopt loop in loadCommandLineOptions() only sets keys verified here.
     */
    if( ( rtOpts->currentConfig = parseConfig(rtOpts->candidateConfig,rtOpts)) == NULL ) {
        *ret = 1;
        dictionary_del(rtOpts->candidateConfig);
        goto configcheck;
    }

    /* we've been told to print the lock file and exit cleanly */
    if(rtOpts->printLockFile) {
        printf("%s\n", rtOpts->lockFile);
        *ret = 0;
        goto fail;
    }

    /* we don't need the candidate config any more */
    dictionary_del(rtOpts->candidateConfig);

    /* Check network before going into background */
    if(!testInterface(rtOpts->ifaceName, rtOpts)) {
        ERROR("Error: Cannot use %s interface\n",rtOpts->ifaceName);
        *ret = 1;
        goto configcheck;
    }

configcheck:
    /*
     * We've been told to check config only - clean exit before checking locks
     */
    if(rtOpts->checkConfigOnly) {
        if(*ret != 0) {
            printf("Configuration has errors\n");
            *ret = 1;
        }
        else
            printf("Configuration OK\n");
        return 0;
    }

    /* Previous errors - exit */
    if(*ret !=0)
        return 0;

    /* First lock check, just to be user-friendly to the operator */
    if(!rtOpts->ignore_daemon_lock) {
        if(!writeLockFile(rtOpts)) {
            /* check and create Lock */
            ERROR("Error: file lock failed (use -L or global:ignore_lock to ignore lock file)\n");
            *ret = 3;
            return 0;
        }
        /* check for potential conflicts when automatic lock files are used */
        if(!checkOtherLocks(rtOpts)) {
            *ret = 3;
            return 0;
        }
    }

    /* Manage log files: stats, log, status and quality file */
    restartLogging(rtOpts);

    /* Allocate memory after we're done with other checks but before going into daemon */
    ptpClock = (PtpClock *) calloc(1, sizeof(PtpClock));
    if (!ptpClock) {
        PERROR("Error: Failed to allocate memory for protocol engine data");
        *ret = 2;
        return 0;
    } else {
        DBG("allocated %d bytes for protocol engine data\n",
            (int)sizeof(PtpClock));
        ptpClock->foreign = (ForeignMasterRecord *)
                            calloc(rtOpts->max_foreign_records,
                                   sizeof(ForeignMasterRecord));
        if (!ptpClock->foreign) {
            PERROR("failed to allocate memory for foreign "
                   "master data");
            *ret = 2;
            free(ptpClock);
            return 0;
        } else {
            DBG("allocated %d bytes for foreign master data\n",
                (int)(rtOpts->max_foreign_records *
                      sizeof(ForeignMasterRecord)));
        }

        ptpClock->owd_filt = FilterCreate(FILTER_EXPONENTIAL_SMOOTH, "owd");
        ptpClock->ofm_filt = FilterCreate(FILTER_MOVING_AVERAGE, "ofm");
    }

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

    /* Init to 0 net buffer */
    memset(ptpClock->msgIbuf, 0, PACKET_SIZE);
    memset(ptpClock->msgObuf, 0, PACKET_SIZE);

    /* Init user_description */
    memset(ptpClock->user_description, 0, sizeof(ptpClock->user_description));
    memcpy(ptpClock->user_description, &USER_DESCRIPTION, sizeof(USER_DESCRIPTION));

    /* Init outgoing management message */
    ptpClock->outgoingManageTmp.tlv = NULL;


    /*  DAEMON */
#ifdef PTPD_NO_DAEMON
    if(!rtOpts->nonDaemon) {
        rtOpts->nonDaemon=TRUE;
    }
#endif

    if(!rtOpts->nonDaemon) {
        /*
         * fork to daemon - nochdir non-zero to preserve the working directory:
         * allows relative paths to be used for log files, config files etc.
         * Always redirect stdout/err to /dev/null
         */
        if (daemon(1,0) == -1) {
            PERROR("Failed to start as daemon");
            *ret = 3;
            return 0;
        }
        INFO("  Info:    Now running as a daemon\n");
        /*
         * Wait for the parent process to terminate, but not forever.
         * On some systems this happened after we tried re-acquiring
         * the lock, so the lock would fail. Hence, we wait.
         */
        for (i = 0; i < 1000000; i++) {
            /* Once we've been reaped by init, parent PID will be 1 */
            if(getppid() == 1)
                break;
            usleep(1);
        }
    }

    /* Second lock check, to replace the contents with our own new PID and re-acquire the advisory lock */
    if(!rtOpts->nonDaemon && !rtOpts->ignore_daemon_lock) {
        /* check and create Lock */
        if(!writeLockFile(rtOpts)) {
            ERROR("Error: file lock failed (use -L or global:ignore_lock to ignore lock file)\n");
            *ret = 3;
            return 0;
        }
    }

#if defined(linux) && defined(HAVE_SCHED_H)
    /* Try binding to a single CPU core if configured to do so */

    if(rtOpts->cpuNumber > -1) {

        cpu_set_t mask;
        CPU_ZERO(&mask);
        CPU_SET(rtOpts->cpuNumber,&mask);
        if(sched_setaffinity(0, sizeof(mask), &mask) < 0) {
            PERROR("Could not bind to CPU core %d", rtOpts->cpuNumber);
        } else {
            INFO("Successfully bound "PTPD_PROGNAME" to CPU core %d\n", rtOpts->cpuNumber);
        }
    }
#endif /* linux && HAVE_SCHED_H */

#ifdef HAVE_SYS_CPUSET_H

    /* Try binding to a single CPU core if configured to do so */

    if(rtOpts->cpuNumber > -1) {
        cpuset_t mask;
        CPU_ZERO(&mask);
        CPU_SET(rtOpts->cpuNumber,&mask);
        if(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID,
                              -1, sizeof(mask), &mask) < 0) {
            PERROR("Could not bind to CPU core %d",
                   rtOpts->cpuNumber);
        } else {
            INFO("Successfully bound "PTPD_PROGNAME" to CPU core %d\n",
                 rtOpts->cpuNumber);
        }
    }
#endif /* HAVE_SYS_CPUSET_H */

    /* use new synchronous signal handlers */
    signal(SIGINT,  catchSignals);
    signal(SIGTERM, catchSignals);
    signal(SIGHUP,  catchSignals);

    signal(SIGUSR1, catchSignals);
    signal(SIGUSR2, catchSignals);

#if defined PTPD_SNMP
    /* Start SNMP subsystem */
    if (rtOpts->snmp_enabled)
        snmpInit(rtOpts, ptpClock);
#endif



    NOTICE(USER_DESCRIPTION" started successfully on %s using \"%s\" preset (PID %d)\n",
           rtOpts->ifaceName,
           (getPtpPreset(rtOpts->selectedPreset,rtOpts)).presetName,
           getpid());
    ptpClock->resetStatisticsLog = TRUE;

#ifdef PTPD_STATISTICS
    if (rtOpts->delayMSOutlierFilterEnabled) {
        ptpClock->delayMSRawStats = createDoubleMovingStdDev(rtOpts->delayMSOutlierFilterCapacity);
        strncpy(ptpClock->delayMSRawStats->identifier, "delayMS", 10);
        ptpClock->delayMSFiltered = createDoubleMovingMean(rtOpts->delayMSOutlierFilterCapacity);
    } else {
        ptpClock->delayMSRawStats = NULL;
        ptpClock->delayMSFiltered = NULL;
    }

    if (rtOpts->delaySMOutlierFilterEnabled) {
        ptpClock->delaySMRawStats = createDoubleMovingStdDev(rtOpts->delaySMOutlierFilterCapacity);
        strncpy(ptpClock->delaySMRawStats->identifier, "delaySM", 10);
        ptpClock->delaySMFiltered = createDoubleMovingMean(rtOpts->delaySMOutlierFilterCapacity);
    } else {
        ptpClock->delaySMRawStats = NULL;
        ptpClock->delaySMFiltered = NULL;
    }
#endif

    *ret = 0;
    return ptpClock;

fail:
    dictionary_del(rtOpts->candidateConfig);
    return 0;
}
Example #5
0
/**
 * 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;


}
Example #6
0
void
applyConfig(dictionary *baseConfig, RunTimeOpts *rtOpts, PtpClock *ptpClock)
{

	Boolean reloadSuccessful = TRUE;


	/* 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(CFGOP_PARSE, NULL, baseConfig, &tmpOpts)) == NULL ) {
	    WARNING("Configuration has errors, reload aborted\n");
	    return;
	}

	/* 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, rtOpts);

	/* 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)) {
		reloadSuccessful = FALSE;
	}

	/* If the network configuration has changed, check if the interface is OK */
	if(rtOpts->restartSubsystems & PTPD_RESTART_NETWORK) {
		INFO("Network configuration changed - checking interface(s)\n");
		if(!testInterface(tmpOpts.primaryIfaceName, &tmpOpts)) {
		    reloadSuccessful = FALSE;
		    ERROR("Error: Cannot use %s interface\n",tmpOpts.primaryIfaceName);
		}
		if(rtOpts->backupIfaceEnabled && !testInterface(tmpOpts.backupIfaceName, &tmpOpts)) {
		    rtOpts->restartSubsystems = -1;
		    ERROR("Error: Cannot use %s interface as backup\n",tmpOpts.backupIfaceName);
		}
	}
#if (defined(linux) && defined(HAVE_SCHED_H)) || defined(HAVE_SYS_CPUSET_H) || defined(__QNXNTO__)
        /* Changing the CPU affinity mask */
        if(rtOpts->restartSubsystems & PTPD_CHANGE_CPUAFFINITY) {
                NOTIFY("Applying CPU binding configuration: changing selected CPU core\n");

                if(setCpuAffinity(tmpOpts.cpuNumber) < 0) {
                        if(tmpOpts.cpuNumber == -1) {
                                ERROR("Could not unbind from CPU core %d\n", rtOpts->cpuNumber);
                        } else {
                                ERROR("Could bind to CPU core %d\n", tmpOpts.cpuNumber);
                        }
			reloadSuccessful = FALSE;
                } 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

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


		/**
		 * 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(CFGOP_PARSE_QUIET, NULL, rtOpts->candidateConfig,rtOpts)) == NULL) {
			CRITICAL("************ "PTPD_PROGNAME": parseConfig returned NULL during config commit"
				 "  - this is a BUG - report the following: \n");

			if ((rtOpts->currentConfig = parseConfig(CFGOP_PARSE, NULL, 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(&rtOpts->candidateConfig);
}