Esempio n. 1
0
static int rtnl_qdisc_get(struct nlmsghdr *h, 
			   int (*if_callback)(int, struct in_ifaddr *))
{
	struct rtattr *tb[IFA_MAX + 1];
	struct tcmsg *tc;
	int len;

	struct in_qdisc	qdisc;

	if (h->nlmsg_type != RTM_NEWQDISC)
		return 0;
	
	tc = NLMSG_DATA(h);
	
	len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct tcmsg));
	if (len < 0)
		return -1;

	netlink_parse_rtattr(tb, TCA_MAX, TCA_RTA(tc), len);
	
	strcpy(qdisc.name, (char *)RTA_DATA(tb[TCA_KIND]));
	qdisc.stats = *(struct tc_stats *)RTA_DATA(tb[TCA_STATS]);

	return if_callback(tc->tcm_ifindex, &qdisc);
}
Esempio n. 2
0
int print_qdisc(const struct sockaddr_nl *who,
		       struct nlmsghdr *n,
		       void *arg)
{
	FILE *fp = (FILE*)arg;
	struct tcmsg *t = NLMSG_DATA(n);
	int len = n->nlmsg_len;
	struct rtattr * tb[TCA_MAX+1];
	struct qdisc_util *q;
	char abuf[256];

	if (n->nlmsg_type != RTM_NEWQDISC && n->nlmsg_type != RTM_DELQDISC) {
		fprintf(stderr, "Not a qdisc\n");
		return 0;
	}
	len -= NLMSG_LENGTH(sizeof(*t));
	if (len < 0) {
		fprintf(stderr, "Wrong len %d\n", len);
		return -1;
	}

	if (filter_ifindex && filter_ifindex != t->tcm_ifindex)
		return 0;

	memset(tb, 0, sizeof(tb));
	parse_rtattr(tb, TCA_MAX, TCA_RTA(t), len);

	if (tb[TCA_KIND] == NULL) {
		fprintf(stderr, "print_qdisc: NULL kind\n");
		return -1;
	}

	if (n->nlmsg_type == RTM_DELQDISC)
		fprintf(fp, "deleted ");

	fprintf(fp, "qdisc %s %x: ", (char*)RTA_DATA(tb[TCA_KIND]), t->tcm_handle>>16);
	if (filter_ifindex == 0)
		fprintf(fp, "dev %s ", ll_index_to_name(t->tcm_ifindex));
	if (t->tcm_parent == TC_H_ROOT)
		fprintf(fp, "root ");
	else if (t->tcm_parent) {
		print_tc_classid(abuf, sizeof(abuf), t->tcm_parent);
		fprintf(fp, "parent %s ", abuf);
	}
	if (t->tcm_info != 1) {
		fprintf(fp, "refcnt %d ", t->tcm_info);
	}
	/* pfifo_fast is generic enough to warrant the hardcoding --JHS */

	if (0 == strcmp("pfifo_fast", RTA_DATA(tb[TCA_KIND])))
		q = get_qdisc_kind("prio");
	else
		q = get_qdisc_kind(RTA_DATA(tb[TCA_KIND]));

	if (tb[TCA_OPTIONS]) {
		if (q)
			q->print_qopt(q, fp, tb[TCA_OPTIONS]);
		else
			fprintf(fp, "[cannot parse qdisc parameters]");
	}
	fprintf(fp, "\n");
	if (show_stats) {
		struct rtattr *xstats = NULL;

		if (tb[TCA_STATS] || tb[TCA_STATS2] || tb[TCA_XSTATS]) {
			print_tcstats_attr(fp, tb, " ", &xstats);
			fprintf(fp, "\n");
		}

		if (q && xstats && q->print_xstats) {
			q->print_xstats(q, fp, xstats);
			fprintf(fp, "\n");
		}
	}
	fflush(fp);
	return 0;
}
Esempio n. 3
0
int insert_entry(struct sockaddr_nl *who, struct nlmsghdr *n, void *a)
{
	// this function extracts data from netlink message and creates object in qos_table
	extern struct qos_table table;
	qos_table *qos_table_entry;
	qos_table *temp;
	char handle[20]="unset";
	char parent[20]="unset";
	char leaf[20]="leaf";
	char optional[20]="";

	char info[256]="";
	int offset=0;
	//string info 
	
	unsigned int major,minor;
	struct tcmsg *t = NLMSG_DATA(n);
	int len = n->nlmsg_len;
	struct rtattr * tb[TCA_MAX+1];
	char abuf[256];

	len -= NLMSG_LENGTH(sizeof(*t));
	if (len < 0) {
		snmp_log(LOG_NOTICE, "insert_qdisc_entry: Wrong len of tc message:%i", len);
		return(-1);
	}

	memset(tb, 0, sizeof(tb));
	parse_rtattr(tb, TCA_MAX, TCA_RTA(t), len);

	if (tb[TCA_KIND] == NULL) {
		snmp_log(LOG_NOTICE, "insert_qdisc_entry: unknown kind\n");
		return(-1);
	}

	qos_table_entry = create_new_qos_table_entry();
	
	if(qos_table_entry==NULL) {
	    return;
	}

	strcpy(qos_table_entry->data.type,(char*)RTA_DATA(tb[TCA_KIND]));

	qos_table_entry->data.majorhandle = (t->tcm_handle >> 16) & 0x0000ffff;		//major part of handle
	qos_table_entry->data.minorhandle = t->tcm_handle & 0x0000ffff;			//minor part of handle	
	qos_table_entry->data.parent = t->tcm_parent;					//parent

	strcpy(qos_table_entry->data.dev_name, ll_index_to_name(t->tcm_ifindex));
	// sets string qosDeviceName in mib

	set_device_index_and_type(&(qos_table_entry->data.device_index),&(qos_table_entry->data.device_type),qos_table_entry->data.dev_name);
	// function takes string device name as input and separate it to device_index and device_type

	switch(t->tcm_parent) {
	    case TC_H_ROOT:
		strcpy(optional," (root)");
		break;
	    case TC_H_INGRESS:
		strcpy(optional," (ingress)");
		break;
	    default:
	    break;
	}
	minor=t->tcm_parent & 0x0000FFFF;
	major=(t->tcm_parent >> 16) & 0x0000FFFF;   
	sprintf(parent,"%x:%x%s",major,minor,optional);
	strcpy(qos_table_entry->data.text_parent,parent);
	// sets string parent info in mib

	sprintf(info+strlen(info),"%s%s","parent:",parent);
	// one line values reporting
	
	strcpy(optional,"");
	// clear temporary optional variable
		
	switch(t->tcm_handle) {
	    case TC_H_ROOT:
		strcpy(optional," (root)");
		break;
	    case TC_H_INGRESS:
		strcpy(optional," (ingress)");
		break;
	    default:
	    break;
	}
 	minor=t->tcm_handle & 0x0000FFFF;
	major=(t->tcm_handle >> 16) & 0x0000FFFF;   
    	sprintf(handle,"%x:%x%s",major,minor,optional);
	strcpy(qos_table_entry->data.text_handle,handle);
	// sets string handle info in mib
	
	sprintf(info+strlen(info),"%s%s"," handle:",handle);
	// one line values reporting

	if((t->tcm_info >> 16)!=0) {
	    minor=0;
	    major=t->tcm_info >> 16;
	    strcpy(optional," (leaf)");
	    sprintf(leaf,"%x:%x%s",major,minor,optional);
	    strcpy(qos_table_entry->data.text_leaf,leaf);
	    // sets leaf info if any
	    
	    sprintf(info+strlen(info),"%s%s"," leaf:",leaf);
	    // one line values reporting
	}
	
    
	if (tb[TCA_STATS]) {
		if (RTA_PAYLOAD(tb[TCA_STATS]) < sizeof(struct tc_stats))
			snmp_log(LOG_WARNING, "qos-ext: insert into table: statistics truncated\n");
		else {
		    struct tc_stats st;
		    unsigned long long temp;
		    unsigned long long ibytes; // for string info reporting purpose
		    memcpy(&st, RTA_DATA(tb[TCA_STATS]), sizeof(st));
		    ibytes=st.bytes;
		    temp = st.bytes & 0xFFFFFFFF00000000;
		    temp = temp >> 32;
		    temp = (st.bytes << 32) | temp;
		    // this funny action translates from host (x86) representation to network data representation (ASN1)
		    // I know it can be done in one step - but this way it's easy to understand
		    
		    qos_table_entry->data.qosBytes = temp;
		    qos_table_entry->data.qosPackets = st.packets;
		    qos_table_entry->data.qosDropped = st.drops;
		    qos_table_entry->data.qosOverlimit = st.overlimits;
		    qos_table_entry->data.qosBps = st.bps;
		    qos_table_entry->data.qosPps = st.pps;
		    qos_table_entry->data.qosQlen = st.qlen;
		    qos_table_entry->data.qosBacklog = st.backlog;
		    // all standard statistic values
		    // pps/bps value is currently (April 2004) reported only from htb classes
		    
		    sprintf(info+strlen(info),"%s%lli%s%i%s%i%s%i%s%i%s%i%s%i%s%i"," bytes:",ibytes," packets:",st.packets," drops:",st.drops,
			    " overlimit:",st.overlimits," bps:",st.bps," pps:",st.pps," qlen:",st.qlen," backlog:",st.backlog);
		    //one line values reporting (column 35)
		}	
	}
	if (tb[TCA_XSTATS]) {
		if (RTA_PAYLOAD(tb[TCA_XSTATS]) < sizeof(struct xstats)) {
		}
		else {
		    struct xstats st;
		    memcpy(&st,RTA_DATA(tb[TCA_XSTATS]),sizeof(st));
		    //check out, what type of qdisc/class it is and set appropriate values
		    if(strcmp(qos_table_entry->data.type,"red")==0 || strcmp(qos_table_entry->data.type,"gred")==0) {
			qos_table_entry->data.redEarly=st.x1;
			qos_table_entry->data.redPdrop=st.x2;
			qos_table_entry->data.redOther=st.x3;
			qos_table_entry->data.redMarked=st.x4;
			
			sprintf(info+strlen(info),"%s%i%s%i%s%i%s%i"," redearly:",st.x1," redpdrop:",st.x2," redother:",st.x3," redmarked",st.x4);
			//one line values reporting (column 35)
		    }
		    if(strcmp(qos_table_entry->data.type,"cbq")==0) {
			qos_table_entry->data.cbqBorrows=st.x1;
			qos_table_entry->data.cbqOveractions=st.x2;
			qos_table_entry->data.cbqAvgidle=st.x3;
			qos_table_entry->data.cbqUndertime=st.x4;

			sprintf(info+strlen(info),"%s%i%s%i%s%i%s%i"," cbqborrows:",st.x1," cbqoveractions:",st.x2," cbqavgidle:",st.x3," cbqundertime",st.x4);
			//one line values reporting (column 35)
		    }
		    if(strcmp(qos_table_entry->data.type,"htb")==0) {
			struct tc_htb_xstats *st_htb;
			struct rtattr *tb2[TCA_HTB_RTAB+1];
			memset(tb2,0,sizeof(tb2));
			parse_rtattr(tb2,TCA_HTB_RTAB, RTA_DATA(tb[TCA_OPTIONS]),RTA_PAYLOAD(tb[TCA_OPTIONS]));
			// extracts htb specific parameters
			
			st_htb=(struct tc_htb_xstats *)&st;
			qos_table_entry->data.htbLends=st_htb->lends;
			qos_table_entry->data.htbBorrows=st_htb->borrows;
			qos_table_entry->data.htbGiants=st_htb->giants;
			qos_table_entry->data.htbTokens=st_htb->tokens;

			sprintf(info+strlen(info),"%s%i%s%i%s%i%s%i"," htblends:",st_htb->lends," htbborrows:",st_htb->borrows,
				" htbgiants:",st_htb->giants," htbtokens:",st_htb->tokens);
			// one line values reporting (column 35)

			if(RTA_PAYLOAD(tb[TCA_XSTATS]) >= sizeof(*st_htb)) {
    		    	    qos_table_entry->data.htbCTokens=st_htb->ctokens;
			    
			    sprintf(info+strlen(info),"%s%i"," htbctokens:",st_htb->ctokens);
			    // one line values reporting (column 35)

			}
			else {
			    snmp_log(LOG_WARNING,"Ctokens value not avaiable in netlink message\n");
			}

			if(tb2[TCA_HTB_PARMS]) {
			    struct tc_htb_opt *hopt;
			    hopt = RTA_DATA(tb2[TCA_HTB_PARMS]);
			    if(RTA_PAYLOAD(tb2[TCA_HTB_PARMS]) < sizeof(*hopt)) {
				snmp_log(LOG_WARNING,"qos-ext: htb parametrs are not all\n");
			    }
			    else {
				qos_table_entry->data.htbCeil=hopt->ceil.rate;
				qos_table_entry->data.htbRate=hopt->rate.rate;
				qos_table_entry->data.htbPrio=hopt->prio;
				// htb rate, ceil and prio values
			    }
			}
		    }
		}
	}

	strcpy(qos_table_entry->data.info,info);
	// one line values reporting

	temp = get_last_entry_in_list(&table); 
	temp->next = qos_table_entry;
	// add stat structute into linked list
}
Esempio n. 4
0
int print_qdisc(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
{
	FILE *fp = (FILE*)arg;
	struct tcmsg *t = NLMSG_DATA(n);
	int len = n->nlmsg_len;
	struct rtattr * tb[TCA_MAX+1];
	struct qdisc_util *q;
	char abuf[256];

	if (n->nlmsg_type != RTM_NEWQDISC && n->nlmsg_type != RTM_DELQDISC) {
		fprintf(stderr, "Not a qdisc\n");
		return 0;
	}
	len -= NLMSG_LENGTH(sizeof(*t));
	if (len < 0) {
		fprintf(stderr, "Wrong len %d\n", len);
		return -1;
	}

	if (filter_ifindex && filter_ifindex != t->tcm_ifindex)
		return 0;

	memset(tb, 0, sizeof(tb));
	parse_rtattr(tb, TCA_MAX, TCA_RTA(t), len);

	if (tb[TCA_KIND] == NULL) {
		fprintf(stderr, "NULL kind\n");
		return -1;
	}

	if (n->nlmsg_type == RTM_DELQDISC)
		fprintf(fp, "deleted ");

	fprintf(fp, "qdisc %s %x: ", (char*)RTA_DATA(tb[TCA_KIND]), t->tcm_handle>>16);
	if (filter_ifindex == 0)
		fprintf(fp, "dev %s ", ll_index_to_name(t->tcm_ifindex));
	if (t->tcm_parent == TC_H_ROOT)
		fprintf(fp, "root ");
	else if (t->tcm_parent) {
		print_tc_classid(abuf, sizeof(abuf), t->tcm_parent);
		fprintf(fp, "parent %s ", abuf);
	}
	if (t->tcm_info != 1) {
		fprintf(fp, "refcnt %d ", t->tcm_info);
	}
	if ((q = get_qdisc_kind(RTA_DATA(tb[TCA_KIND]))) != NULL)
		q->print_qopt(q, fp, tb[TCA_OPTIONS]);
	else
		fprintf(fp, "[UNKNOWN]");
	fprintf(fp, "\n");
	if (show_stats) {
		if (tb[TCA_STATS]) {
			if (RTA_PAYLOAD(tb[TCA_STATS]) < sizeof(struct tc_stats))
				fprintf(fp, "statistics truncated");
			else {
				struct tc_stats st;
				memcpy(&st, RTA_DATA(tb[TCA_STATS]), sizeof(st));
				print_tcstats(fp, &st);
				fprintf(fp, "\n");
			}
		}
		if (q && tb[TCA_XSTATS]) {
			q->print_xstats(q, fp, tb[TCA_XSTATS]);
			fprintf(fp, "\n");
		}
		fprintf(fp, "\n ");
	}
	fflush(fp);
	return 0;
}