1 /* $KAME: qdisc_wfq.c,v 1.2 2000/10/18 09:15:17 kjc Exp $ */ 2 /* 3 * Copyright (C) 1999-2000 4 * Sony Computer Science Laboratories, Inc. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/param.h> 29 #include <sys/ioctl.h> 30 #include <sys/time.h> 31 #include <sys/socket.h> 32 #include <net/if.h> 33 #include <netinet/in.h> 34 #include <altq/altq.h> 35 #include <altq/altq_wfq.h> 36 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <unistd.h> 40 #include <string.h> 41 #include <math.h> 42 #include <errno.h> 43 #include <err.h> 44 #ifndef NO_CURSES 45 #include <curses.h> 46 #endif 47 48 #include "altqstat.h" 49 50 struct wfqinfo { 51 int qid; 52 queue_stats stats; 53 u_quad_t last_bytes; 54 double bps; 55 }; 56 57 #define NTOP 10 58 static int ntop = NTOP; 59 60 void 61 wfq_stat_loop(int fd, const char *ifname, int count, int interval) 62 { 63 struct wfq_getstats wfq_stats; 64 struct timeval cur_time, last_time; 65 int i, j, k, nqueues; 66 double sec; 67 struct wfqinfo *qinfo, **top; 68 int cnt = count; 69 70 strcpy(wfq_stats.iface.wfq_ifacename, ifname); 71 72 /* 73 * first, find out how many queues are available 74 */ 75 for (i = 0; i < MAX_QSIZE; i++) { 76 wfq_stats.qid = i; 77 if (ioctl(fd, WFQ_GET_STATS, &wfq_stats) < 0) 78 break; 79 } 80 nqueues = i; 81 printf("wfq on %s: %d queues are used\n", ifname, nqueues); 82 83 if ((qinfo = malloc(nqueues * sizeof(struct wfqinfo))) == NULL) 84 err(1, "malloc failed!"); 85 if ((top = malloc(ntop * sizeof(struct wfqinfo *))) == NULL) 86 err(1, "malloc failed!"); 87 88 #ifndef NO_CURSES 89 sleep(2); /* wait a bit before clearing the screen */ 90 91 initscr(); 92 #endif 93 94 gettimeofday(&last_time, NULL); 95 last_time.tv_sec -= interval; 96 97 while (count == 0 || cnt-- > 0) { 98 99 for (j = 0; j < ntop; j++) 100 top[j] = NULL; 101 102 for (i = 0; i < nqueues; i++) { 103 wfq_stats.qid = i; 104 if (ioctl(fd, WFQ_GET_STATS, &wfq_stats) < 0) 105 err(1, "ioctl WFQ_GET_STATS"); 106 107 qinfo[i].qid = i; 108 qinfo[i].stats = wfq_stats.stats; 109 } 110 111 gettimeofday(&cur_time, NULL); 112 sec = calc_interval(&cur_time, &last_time); 113 114 /* 115 * calculate the throughput of each queue 116 */ 117 for (i = 0; i < nqueues; i++) { 118 qinfo[i].bps = calc_rate(qinfo[i].stats.xmit_cnt.bytes, 119 qinfo[i].last_bytes, sec); 120 qinfo[i].last_bytes = qinfo[i].stats.xmit_cnt.bytes; 121 122 for (j = 0; j < ntop; j++) { 123 if (top[j] == NULL) { 124 top[j] = &qinfo[i]; 125 break; 126 } 127 if (top[j]->bps < qinfo[i].bps || 128 (top[j]->bps == qinfo[i].bps && 129 top[j]->stats.xmit_cnt.packets < 130 qinfo[i].stats.xmit_cnt.packets)) { 131 for (k = ntop-1; k > j; k--) 132 top[k] = top[k-1]; 133 top[j] = &qinfo[i]; 134 break; 135 } 136 } 137 } 138 139 /* 140 * display top 141 */ 142 printf("[QID] WEIGHT QSIZE(KB) SENT(pkts) (KB) DROP(pkts) (KB) bps\n\r"); 143 144 for (j = 0; j < ntop; j++) { 145 if (top[j] != NULL) 146 printf("[%4d] %4d %4d %10llu %14llu %10llu %14llu %9s\n\r", 147 top[j]->qid, 148 top[j]->stats.weight, 149 top[j]->stats.bytes / 1024, 150 (ull)top[j]->stats.xmit_cnt.packets, 151 (ull)top[j]->stats.xmit_cnt.bytes /1024, 152 (ull)top[j]->stats.drop_cnt.packets, 153 (ull)top[j]->stats.drop_cnt.bytes /1024, 154 rate2str(top[j]->bps)); 155 else 156 printf("\n"); 157 } 158 #ifndef NO_CURSES 159 refresh(); 160 mvcur(ntop+1, 0, 0, 0); 161 #endif 162 163 last_time = cur_time; 164 sleep(interval); 165 } 166 167 } 168