コード例 #1
0
ファイル: plugin_tc.c プロジェクト: firehol/netdata
void *tc_main(void *ptr) {
    netdata_thread_cleanup_push(tc_main_cleanup, ptr);

    struct rusage thread;

    char command[FILENAME_MAX + 1];
    char *words[PLUGINSD_MAX_WORDS] = { NULL };

    uint32_t BEGIN_HASH = simple_hash("BEGIN");
    uint32_t END_HASH = simple_hash("END");
    uint32_t QDISC_HASH = simple_hash("qdisc");
    uint32_t CLASS_HASH = simple_hash("class");
    uint32_t SENT_HASH = simple_hash("Sent");
    uint32_t LENDED_HASH = simple_hash("lended:");
    uint32_t TOKENS_HASH = simple_hash("tokens:");
    uint32_t SETDEVICENAME_HASH = simple_hash("SETDEVICENAME");
    uint32_t SETDEVICEGROUP_HASH = simple_hash("SETDEVICEGROUP");
    uint32_t SETCLASSNAME_HASH = simple_hash("SETCLASSNAME");
    uint32_t WORKTIME_HASH = simple_hash("WORKTIME");
#ifdef DETACH_PLUGINS_FROM_NETDATA
    uint32_t MYPID_HASH = simple_hash("MYPID");
#endif
    uint32_t first_hash;

    snprintfz(command, TC_LINE_MAX, "%s/tc-qos-helper.sh", netdata_configured_primary_plugins_dir);
    char *tc_script = config_get("plugin:tc", "script to run to get tc values", command);

    while(!netdata_exit) {
        FILE *fp;
        struct tc_device *device = NULL;
        struct tc_class *class = NULL;

        snprintfz(command, TC_LINE_MAX, "exec %s %d", tc_script, localhost->rrd_update_every);
        debug(D_TC_LOOP, "executing '%s'", command);

        fp = mypopen(command, (pid_t *)&tc_child_pid);
        if(unlikely(!fp)) {
            error("TC: Cannot popen(\"%s\", \"r\").", command);
            goto cleanup;
        }

        char buffer[TC_LINE_MAX+1] = "";
        while(fgets(buffer, TC_LINE_MAX, fp) != NULL) {
            if(unlikely(netdata_exit)) break;

            buffer[TC_LINE_MAX] = '\0';
            // debug(D_TC_LOOP, "TC: read '%s'", buffer);

            tc_split_words(buffer, words, PLUGINSD_MAX_WORDS);

            if(unlikely(!words[0] || !*words[0])) {
                // debug(D_TC_LOOP, "empty line");
                continue;
            }
            // else debug(D_TC_LOOP, "First word is '%s'", words[0]);

            first_hash = simple_hash(words[0]);

            if(unlikely(device && ((first_hash == CLASS_HASH && strcmp(words[0], "class") == 0) ||  (first_hash == QDISC_HASH && strcmp(words[0], "qdisc") == 0)))) {
                // debug(D_TC_LOOP, "CLASS line on class id='%s', parent='%s', parentid='%s', leaf='%s', leafid='%s'", words[2], words[3], words[4], words[5], words[6]);

                char *type     = words[1];  // the class/qdisc type: htb, fq_codel, etc
                char *id       = words[2];  // the class/qdisc major:minor
                char *parent   = words[3];  // the word 'parent' or 'root'
                char *parentid = words[4];  // parentid
                char *leaf     = words[5];  // the word 'leaf'
                char *leafid   = words[6];  // leafid

                int parent_is_root = 0;
                int parent_is_parent = 0;
                if(likely(parent)) {
                    parent_is_parent = !strcmp(parent, "parent");

                    if(!parent_is_parent)
                        parent_is_root = !strcmp(parent, "root");
                }

                if(likely(type && id && (parent_is_root || parent_is_parent))) {
                    char qdisc = 0;

                    if(first_hash == QDISC_HASH) {
                        qdisc = 1;

                        if(!strcmp(type, "ingress")) {
                            // we don't want to get the ingress qdisc
                            // there should be an IFB interface for this

                            class = NULL;
                            continue;
                        }

                        if(parent_is_parent && parentid) {
                            // eliminate the minor number from parentid
                            // why: parentid is the id of the parent class
                            // but major: is also the id of the parent qdisc

                            char *s = parentid;
                            while(*s && *s != ':') s++;
                            if(*s == ':') s[1] = '\0';
                        }
                    }

                    if(parent_is_root) {
                        parentid = NULL;
                        leafid = NULL;
                    }
                    else if(!leaf || strcmp(leaf, "leaf") != 0)
                        leafid = NULL;

                    char leafbuf[20 + 1] = "";
                    if(leafid && leafid[strlen(leafid) - 1] == ':') {
                        strncpyz(leafbuf, leafid, 20 - 1);
                        strcat(leafbuf, "1");
                        leafid = leafbuf;
                    }

                    class = tc_class_add(device, id, qdisc, parentid, leafid);
                }
                else {
コード例 #2
0
ファイル: plugin_tc.c プロジェクト: Brainiarc7/netdata
void *tc_main(void *ptr)
{
	if(ptr) { ; }

	info("TC thread created with task id %d", gettid());

	if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
		error("Cannot set pthread cancel type to DEFERRED.");

	if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
		error("Cannot set pthread cancel state to ENABLE.");

	struct rusage thread;
	RRDSET *stcpu = NULL, *sttime = NULL;

	char buffer[TC_LINE_MAX+1] = "";
	char *words[MAX_WORDS] = { NULL };

	uint32_t BEGIN_HASH = simple_hash("BEGIN");
	uint32_t END_HASH = simple_hash("END");
	uint32_t CLASS_HASH = simple_hash("class");
	uint32_t SENT_HASH = simple_hash("Sent");
	uint32_t LENDED_HASH = simple_hash("lended:");
	uint32_t TOKENS_HASH = simple_hash("tokens:");
	uint32_t SETDEVICENAME_HASH = simple_hash("SETDEVICENAME");
	uint32_t SETDEVICEGROUP_HASH = simple_hash("SETDEVICEGROUP");
	uint32_t SETCLASSNAME_HASH = simple_hash("SETCLASSNAME");
	uint32_t WORKTIME_HASH = simple_hash("WORKTIME");
#ifdef DETACH_PLUGINS_FROM_NETDATA
	uint32_t MYPID_HASH = simple_hash("MYPID");
#endif
	uint32_t first_hash;

	for(;1;) {
		if(unlikely(netdata_exit)) break;

		FILE *fp;
		struct tc_device *device = NULL;
		struct tc_class *class = NULL;

		snprintfz(buffer, TC_LINE_MAX, "exec %s %d", config_get("plugin:tc", "script to run to get tc values", PLUGINS_DIR "/tc-qos-helper.sh"), rrd_update_every);
		debug(D_TC_LOOP, "executing '%s'", buffer);
		// fp = popen(buffer, "r");
		fp = mypopen(buffer, &tc_child_pid);
		if(!fp) {
			error("TC: Cannot popen(\"%s\", \"r\").", buffer);
			pthread_exit(NULL);
			return NULL;
		}

		while(fgets(buffer, TC_LINE_MAX, fp) != NULL) {
			if(unlikely(netdata_exit)) break;

			buffer[TC_LINE_MAX] = '\0';
			// debug(D_TC_LOOP, "TC: read '%s'", buffer);

			tc_split_words(buffer, words, MAX_WORDS);
			if(!words[0] || !*words[0]) {
				// debug(D_TC_LOOP, "empty line");
				continue;
			}
			// else debug(D_TC_LOOP, "First word is '%s'", words[0]);

			first_hash = simple_hash(words[0]);

			if(device && first_hash == CLASS_HASH && strcmp(words[0], "class") == 0) {
				// debug(D_TC_LOOP, "CLASS line on class id='%s', parent='%s', parentid='%s', leaf='%s', leafid='%s'", words[2], words[3], words[4], words[5], words[6]);

				// clear the last class
				class = NULL;

				// words[1] : class type
				// words[2] : N:XX
				// words[3] : parent or root
				if(words[1] && words[2] && words[3] && (strcmp(words[3], "parent") == 0 || strcmp(words[3], "root") == 0)) {
					//char *type     = words[1];  // the class: htb, fq_codel, etc

					// we are only interested for HTB classes
					//if(strcmp(type, "htb") != 0) continue;

					char *id       = words[2];	// the class major:minor
					char *parent   = words[3];	// 'parent' or 'root'
					char *parentid = words[4];	// the parent's id
					char *leaf     = words[5];	// 'leaf'
					char *leafid   = words[6];	// leafid

					if(strcmp(parent, "root") == 0) {
						parentid = NULL;
						leafid = NULL;
					}
					else if(!leaf || strcmp(leaf, "leaf") != 0)
						leafid = NULL;

					char leafbuf[20 + 1] = "";
					if(leafid && leafid[strlen(leafid) - 1] == ':') {
						strncpyz(leafbuf, leafid, 20 - 1);
						strcat(leafbuf, "1");
						leafid = leafbuf;
					}

					class = tc_class_add(device, id, parentid, leafid);
				}
			}
			else if(first_hash == END_HASH && strcmp(words[0], "END") == 0) {
				// debug(D_TC_LOOP, "END line");

				if(device) {
					if(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL) != 0)
						error("Cannot set pthread cancel state to DISABLE.");

					tc_device_commit(device);
					// tc_device_free(device);
					device = NULL;
					class = NULL;

					if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
						error("Cannot set pthread cancel state to ENABLE.");
				}
			}
			else if(first_hash == BEGIN_HASH && strcmp(words[0], "BEGIN") == 0) {