Home | History | Annotate | Line # | Download | only in altqstat
      1 /*	$NetBSD: qdisc_jobs.c,v 1.3 2006/10/28 11:43:02 peter Exp $	*/
      2 /*	$KAME: qdisc_jobs.c,v 1.2 2002/10/27 03:19:36 kjc Exp $	*/
      3 /*
      4  * Copyright (c) 2001-2002, by the Rector and Board of Visitors of the
      5  * University of Virginia.
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms,
      9  * with or without modification, are permitted provided
     10  * that the following conditions are met:
     11  *
     12  * Redistributions of source code must retain the above
     13  * copyright notice, this list of conditions and the following
     14  * disclaimer.
     15  *
     16  * Redistributions in binary form must reproduce the above
     17  * copyright notice, this list of conditions and the following
     18  * disclaimer in the documentation and/or other materials provided
     19  * with the distribution.
     20  *
     21  * Neither the name of the University of Virginia nor the names
     22  * of its contributors may be used to endorse or promote products
     23  * derived from this software without specific prior written
     24  * permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
     27  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
     28  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     29  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     30  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
     31  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
     32  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     33  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     34  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     35  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     37  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     38  * THE POSSIBILITY OF SUCH DAMAGE.
     39  */
     40 /*
     41  * JoBS - altq prototype implementation
     42  *
     43  * Author: Nicolas Christin <nicolas (at) cs.virginia.edu>
     44  *
     45  * JoBS algorithms originally devised and proposed by
     46  * Nicolas Christin and Jorg Liebeherr.
     47  * Grateful Acknowledgments to Tarek Abdelzaher for his help and
     48  * comments, and to Kenjiro Cho for some helpful advice.
     49  * Contributed by the Multimedia Networks Group at the University
     50  * of Virginia.
     51  *
     52  * http://qosbox.cs.virginia.edu
     53  *
     54  */
     55 
     56 #include <sys/param.h>
     57 #include <sys/ioctl.h>
     58 #include <sys/time.h>
     59 #include <sys/socket.h>
     60 #include <net/if.h>
     61 #include <netinet/in.h>
     62 #include <altq/altq.h>
     63 #include <altq/altq_jobs.h>
     64 
     65 #include <stdio.h>
     66 #include <stdlib.h>
     67 #include <unistd.h>
     68 #include <string.h>
     69 #include <signal.h>
     70 #include <math.h>
     71 #include <errno.h>
     72 #include <err.h>
     73 
     74 #include "quip_client.h"
     75 #include "altqstat.h"
     76 
     77 void
     78 jobs_stat_loop(int fd, const char *ifname, int count, int interval)
     79 {
     80 	struct class_stats	stats1[JOBS_MAXPRI], stats2[JOBS_MAXPRI];
     81 	char			clnames[JOBS_MAXPRI][128];
     82 	struct jobs_class_stats	get_stats;
     83 	struct class_stats	*sp, *lp, *new, *last, *tmp;
     84 	struct timeval		cur_time, last_time;
     85 	int			i;
     86 	double			sec;
     87 	int			cnt = count;
     88 	sigset_t		omask;
     89 
     90 	strlcpy(get_stats.iface.jobs_ifname, ifname,
     91 		sizeof(get_stats.iface.jobs_ifname));
     92 	new = &stats1[0];
     93 	last = &stats2[0];
     94 
     95 	/* invalidate class handles */
     96 	for (i=0; i<JOBS_MAXPRI; i++)
     97 		last[i].class_handle = JOBS_NULLCLASS_HANDLE;
     98 
     99 	for (;;) {
    100 		get_stats.stats = new;
    101 		get_stats.maxpri = JOBS_MAXPRI;
    102 		if (ioctl(fd, JOBS_GETSTATS, &get_stats) < 0)
    103 			err(1, "ioctl JOBS_GETSTATS");
    104 
    105 		gettimeofday(&cur_time, NULL);
    106 		sec = calc_interval(&cur_time, &last_time);
    107 
    108 		printf("\n%s:\n", ifname);
    109 		printf("pri\tdel\trdc\tviol\tp_i\trlc\tthru\toff_ld\tbc_e\tavg_e\tstdev_e\twc_e\tbc_d\tavg_d\tstdev_d\twc_d\tnr_en\tnr_de\n");
    110 
    111 		for (i = get_stats.maxpri; i >= 0; i--) {
    112 			sp = &new[i];
    113 			lp = &last[i];
    114 
    115 			if (sp->class_handle == JOBS_NULLCLASS_HANDLE)
    116 				continue;
    117 
    118 			if (sp->class_handle != lp->class_handle) {
    119 				quip_chandle2name(ifname, sp->class_handle,
    120 				clnames[i], sizeof(clnames[0]));
    121 				continue;
    122 			}
    123 
    124 			printf("%d\t%.0f\t%.2f\t%.3f\t%.2f\t%.2f\t%.3f\t%.2f\t%llu\t%.0f\t%.0f\t%llu\t%llu\t%.0f\t%.0f\t%llu\t%u\t%u\n",
    125 			       i,
    126 			       (sp->rout.packets == 0)?
    127 			       -1.:(double)sp->avgdel/(double)sp->rout.packets,
    128 			       (i > 0)?((sp->rout.packets > 0 && (&new[i-1])->rout.packets > 0)?
    129 					(double)(sp->avgdel*(&new[i-1])->rout.packets)/((double)sp->rout.packets*(&new[i-1])->avgdel):0):-1.0,
    130 			       (sp->arrival.packets == 0)?
    131 			       0:(double)100.*sp->adc_violations/(double)sp->arrival.packets,
    132 			       (sp->arrivalbusy.bytes == 0)?
    133 			       0:(double)(100.*sp->dropcnt.bytes/(double)(sp->arrivalbusy.bytes)),
    134 			       (i > 0)?(
    135 					(sp->arrivalbusy.bytes == 0 || (&new[i-1])->dropcnt.bytes == 0)?
    136 					0:(double)(sp->dropcnt.bytes*(&new[i-1])->arrivalbusy.bytes)
    137 					/(double)(sp->arrivalbusy.bytes*(&new[i-1])->dropcnt.bytes)):-1.0,
    138 			       (sp->rout.bytes > 0)?
    139 			       (double)calc_rate(sp->rout.bytes,
    140 						 0, sec)/1000000.:0,
    141 			       (sp->arrival.bytes-lp->arrival.bytes > 0)?
    142 			       (double)calc_rate(sp->arrival.bytes-lp->arrival.bytes,
    143 						 0, sec)/1000000.:0,
    144 			       (ull)sp->bc_cycles_enqueue,
    145 			       (sp->total_enqueued == 0)?
    146 			       -1:(double)sp->avg_cycles_enqueue/sp->total_enqueued,
    147 			       (sp->total_enqueued == 0)?
    148 			       -1.:
    149 			       sqrt((double)((u_int)((sp->avg_cycles2_enqueue/sp->total_enqueued)
    150 						     -(sp->avg_cycles_enqueue/sp->total_enqueued*sp->avg_cycles_enqueue/sp->total_enqueued)))),
    151 			       (ull)sp->wc_cycles_enqueue,
    152 			       (ull)sp->bc_cycles_dequeue,
    153 			       (sp->total_dequeued == 0)?
    154 			       -1:(double)sp->avg_cycles_dequeue/sp->total_dequeued,
    155 			       (sp->total_dequeued == 0)?
    156 			       -1.:
    157 			       sqrt((double)((u_int)((sp->avg_cycles2_dequeue/sp->total_dequeued)
    158 						     -(sp->avg_cycles_dequeue/sp->total_dequeued*sp->avg_cycles_dequeue/sp->total_dequeued)))),
    159 			       (ull)sp->wc_cycles_dequeue,
    160 			       (u_int)sp->total_enqueued,
    161 			       (u_int)sp->total_dequeued
    162 			       );
    163 		}
    164 
    165 		/* swap the buffer pointers */
    166 		tmp = last;
    167 		last = new;
    168 		new = tmp;
    169 
    170 		last_time = cur_time;
    171 
    172 		if (count != 0 && --cnt == 0)
    173 			break;
    174 
    175 		/* wait for alarm signal */
    176 		if (sigprocmask(SIG_BLOCK, NULL, &omask) == 0)
    177 			sigsuspend(&omask);
    178 	}
    179 }
    180