void pfctl_print_altq_node(int dev, const struct pf_altq_node *node, unsigned int level, int opts) { const struct pf_altq_node *child; if (node == NULL) return; print_altq(&node->altq, level, NULL, NULL); if (node->children != NULL) { printf("{"); for (child = node->children; child != NULL; child = child->next) { printf("%s", child->altq.qname); if (child->next != NULL) printf(", "); } printf("}"); } printf("\n"); if (opts & PF_OPT_VERBOSE) pfctl_print_altq_nodestat(dev, node); if (opts & PF_OPT_DEBUG) printf(" [ qid=%u ifname=%s ifbandwidth=%s ]\n", node->altq.qid, node->altq.ifname, rate2str((double)(node->altq.ifbandwidth))); for (child = node->children; child != NULL; child = child->next) pfctl_print_altq_node(dev, child, level + 1, opts); }
void print_hfscstats(struct queue_stats cur) { printf(" [ pkts: %10llu bytes: %10llu " "dropped pkts: %6llu bytes: %6llu ]\n", (unsigned long long)cur.data.hfsc_stats.xmit_cnt.packets, (unsigned long long)cur.data.hfsc_stats.xmit_cnt.bytes, (unsigned long long)cur.data.hfsc_stats.drop_cnt.packets, (unsigned long long)cur.data.hfsc_stats.drop_cnt.bytes); printf(" [ qlength: %3d/%3d ]\n", cur.data.hfsc_stats.qlength, cur.data.hfsc_stats.qlimit); if (cur.avgn < 2) return; printf(" [ measured: %7.1f packets/s, %s/s ]\n", cur.avg_packets / STAT_INTERVAL, rate2str((8 * cur.avg_bytes) / STAT_INTERVAL)); }
void print_cbqstats(struct queue_stats cur) { printf(" [ pkts: %10llu bytes: %10llu " "dropped pkts: %6llu bytes: %6llu ]\n", (unsigned long long)cur.data.cbq_stats.xmit_cnt.packets, (unsigned long long)cur.data.cbq_stats.xmit_cnt.bytes, (unsigned long long)cur.data.cbq_stats.drop_cnt.packets, (unsigned long long)cur.data.cbq_stats.drop_cnt.bytes); printf(" [ qlength: %3d/%3d borrows: %6u suspends: %6u ]\n", cur.data.cbq_stats.qcnt, cur.data.cbq_stats.qmax, cur.data.cbq_stats.borrows, cur.data.cbq_stats.delays); if (cur.avgn < 2) return; printf(" [ measured: %7.1f packets/s, %s/s ]\n", cur.avg_packets / STAT_INTERVAL, rate2str((8 * cur.avg_bytes) / STAT_INTERVAL)); }
int pfctl_update_qstats(int dev, struct pf_altq_node **root) { struct pf_altq_node *node; struct pfioc_altq pa; struct pfioc_qstats pq; u_int32_t mnr, nr; struct queue_stats qstats; static u_int32_t last_ticket; memset(&pa, 0, sizeof(pa)); memset(&pq, 0, sizeof(pq)); memset(&qstats, 0, sizeof(qstats)); if (ioctl(dev, DIOCGETALTQS, &pa)) { warn("DIOCGETALTQS"); return (-1); } /* if a new set is found, start over */ if (pa.ticket != last_ticket && *root != NULL) { pfctl_free_altq_node(*root); *root = NULL; } last_ticket = pa.ticket; mnr = pa.nr; for (nr = 0; nr < mnr; ++nr) { pa.nr = nr; if (ioctl(dev, DIOCGETALTQ, &pa)) { warn("DIOCGETALTQ"); return (-1); } #ifdef __FreeBSD__ if (pa.altq.qid > 0 && !(pa.altq.local_flags & PFALTQ_FLAG_IF_REMOVED)) { #else if (pa.altq.qid > 0) { #endif pq.nr = nr; pq.ticket = pa.ticket; pq.buf = &qstats.data; pq.nbytes = sizeof(qstats.data); if (ioctl(dev, DIOCGETQSTATS, &pq)) { warn("DIOCGETQSTATS"); return (-1); } if ((node = pfctl_find_altq_node(*root, pa.altq.qname, pa.altq.ifname)) != NULL) { memcpy(&node->qstats.data, &qstats.data, sizeof(qstats.data)); update_avg(node); } else { pfctl_insert_altq_node(root, pa.altq, qstats); } } #ifdef __FreeBSD__ else if (pa.altq.local_flags & PFALTQ_FLAG_IF_REMOVED) { memset(&qstats.data, 0, sizeof(qstats.data)); if ((node = pfctl_find_altq_node(*root, pa.altq.qname, pa.altq.ifname)) != NULL) { memcpy(&node->qstats.data, &qstats.data, sizeof(qstats.data)); update_avg(node); } else { pfctl_insert_altq_node(root, pa.altq, qstats); } } #endif } return (mnr); } void pfctl_insert_altq_node(struct pf_altq_node **root, const struct pf_altq altq, const struct queue_stats qstats) { struct pf_altq_node *node; node = calloc(1, sizeof(struct pf_altq_node)); if (node == NULL) err(1, "pfctl_insert_altq_node: calloc"); memcpy(&node->altq, &altq, sizeof(struct pf_altq)); memcpy(&node->qstats, &qstats, sizeof(qstats)); node->next = node->children = NULL; if (*root == NULL) *root = node; else if (!altq.parent[0]) { struct pf_altq_node *prev = *root; while (prev->next != NULL) prev = prev->next; prev->next = node; } else { struct pf_altq_node *parent; parent = pfctl_find_altq_node(*root, altq.parent, altq.ifname); if (parent == NULL) errx(1, "parent %s not found", altq.parent); if (parent->children == NULL) parent->children = node; else { struct pf_altq_node *prev = parent->children; while (prev->next != NULL) prev = prev->next; prev->next = node; } } update_avg(node); } struct pf_altq_node * pfctl_find_altq_node(struct pf_altq_node *root, const char *qname, const char *ifname) { struct pf_altq_node *node, *child; for (node = root; node != NULL; node = node->next) { if (!strcmp(node->altq.qname, qname) && !(strcmp(node->altq.ifname, ifname))) return (node); if (node->children != NULL) { child = pfctl_find_altq_node(node->children, qname, ifname); if (child != NULL) return (child); } } return (NULL); } void pfctl_print_altq_node(int dev, const struct pf_altq_node *node, unsigned int level, int opts) { const struct pf_altq_node *child; if (node == NULL) return; print_altq(&node->altq, level, NULL, NULL); if (node->children != NULL) { printf("{"); for (child = node->children; child != NULL; child = child->next) { printf("%s", child->altq.qname); if (child->next != NULL) printf(", "); } printf("}"); } printf("\n"); if (opts & PF_OPT_VERBOSE) pfctl_print_altq_nodestat(dev, node); if (opts & PF_OPT_DEBUG) printf(" [ qid=%u ifname=%s ifbandwidth=%s ]\n", node->altq.qid, node->altq.ifname, rate2str((double)(node->altq.ifbandwidth))); for (child = node->children; child != NULL; child = child->next) pfctl_print_altq_node(dev, child, level + 1, opts); } void pfctl_print_altq_nodestat(int dev, const struct pf_altq_node *a) { if (a->altq.qid == 0) return; #ifdef __FreeBSD__ if (a->altq.local_flags & PFALTQ_FLAG_IF_REMOVED) return; #endif switch (a->altq.scheduler) { case ALTQT_CBQ: print_cbqstats(a->qstats); break; case ALTQT_PRIQ: print_priqstats(a->qstats); break; case ALTQT_HFSC: print_hfscstats(a->qstats); break; } } void print_cbqstats(struct queue_stats cur) { printf(" [ pkts: %10llu bytes: %10llu " "dropped pkts: %6llu bytes: %6llu ]\n", (unsigned long long)cur.data.cbq_stats.xmit_cnt.packets, (unsigned long long)cur.data.cbq_stats.xmit_cnt.bytes, (unsigned long long)cur.data.cbq_stats.drop_cnt.packets, (unsigned long long)cur.data.cbq_stats.drop_cnt.bytes); printf(" [ qlength: %3d/%3d borrows: %6u suspends: %6u ]\n", cur.data.cbq_stats.qcnt, cur.data.cbq_stats.qmax, cur.data.cbq_stats.borrows, cur.data.cbq_stats.delays); if (cur.avgn < 2) return; printf(" [ measured: %7.1f packets/s, %s/s ]\n", cur.avg_packets / STAT_INTERVAL, rate2str((8 * cur.avg_bytes) / STAT_INTERVAL)); }
void rio_stat_loop(int fd, const char *ifname, int count, int interval) { struct rio_stats rio_stats; struct timeval cur_time, last_time; u_int64_t last_bytes[3]; double sec; int cnt = count; sigset_t omask; bzero(&rio_stats, sizeof(rio_stats)); strlcpy(rio_stats.iface.rio_ifname, ifname, sizeof(rio_stats.iface.rio_ifname)); gettimeofday(&last_time, NULL); last_time.tv_sec -= interval; while (count == 0 || cnt-- > 0) { if (ioctl(fd, RIO_GETSTATS, &rio_stats) < 0) err(1, "ioctl RIO_GETSTATS"); gettimeofday(&cur_time, NULL); sec = calc_interval(&cur_time, &last_time); printf("weight:%d q_limit:%d\n", rio_stats.weight, rio_stats.q_limit); printf("\t\t\tLOW DP\t\tMEDIUM DP\t\tHIGH DP\n"); printf("thresh (prob):\t\t[%d,%d](1/%d)\t[%d,%d](1/%d)\t\t[%d,%d](1/%d)\n", rio_stats.q_params[0].th_min, rio_stats.q_params[0].th_max, rio_stats.q_params[0].inv_pmax, rio_stats.q_params[1].th_min, rio_stats.q_params[1].th_max, rio_stats.q_params[1].inv_pmax, rio_stats.q_params[2].th_min, rio_stats.q_params[2].th_max, rio_stats.q_params[2].inv_pmax); printf("qlen (avg):\t\t%d (%.2f)\t%d (%.2f)\t\t%d (%.2f)\n", rio_stats.q_len[0], ((double)rio_stats.q_stats[0].q_avg)/(double)avg_scale, rio_stats.q_len[1], ((double)rio_stats.q_stats[1].q_avg)/(double)avg_scale, rio_stats.q_len[2], ((double)rio_stats.q_stats[2].q_avg)/(double)avg_scale); printf("xmit (drop) pkts:\t%llu (%llu)\t\t%llu (%llu)\t\t\t%llu (%llu)\n", (ull)rio_stats.q_stats[0].xmit_cnt.packets, (ull)rio_stats.q_stats[0].drop_cnt.packets, (ull)rio_stats.q_stats[1].xmit_cnt.packets, (ull)rio_stats.q_stats[1].drop_cnt.packets, (ull)rio_stats.q_stats[2].xmit_cnt.packets, (ull)rio_stats.q_stats[2].drop_cnt.packets); printf("(forced:early):\t\t(%u:%u)\t\t(%u:%u)\t\t\t(%u:%u)\n", rio_stats.q_stats[0].drop_forced, rio_stats.q_stats[0].drop_unforced, rio_stats.q_stats[1].drop_forced, rio_stats.q_stats[1].drop_unforced, rio_stats.q_stats[2].drop_forced, rio_stats.q_stats[2].drop_unforced); if (rio_stats.q_stats[0].marked_packets != 0 || rio_stats.q_stats[1].marked_packets != 0 || rio_stats.q_stats[2].marked_packets != 0) printf("marked:\t\t\t%u\t\t%u\t\t\t%u\n", rio_stats.q_stats[0].marked_packets, rio_stats.q_stats[1].marked_packets, rio_stats.q_stats[2].marked_packets); printf("throughput:\t\t%sbps\t%sbps\t\t%sbps\n\n", rate2str(calc_rate(rio_stats.q_stats[0].xmit_cnt.bytes, last_bytes[0], sec)), rate2str(calc_rate(rio_stats.q_stats[1].xmit_cnt.bytes, last_bytes[1], sec)), rate2str(calc_rate(rio_stats.q_stats[2].xmit_cnt.bytes, last_bytes[2], sec))); last_bytes[0] = rio_stats.q_stats[0].xmit_cnt.bytes; last_bytes[1] = rio_stats.q_stats[1].xmit_cnt.bytes; last_bytes[2] = rio_stats.q_stats[2].xmit_cnt.bytes; last_time = cur_time; /* wait for alarm signal */ if (sigprocmask(SIG_BLOCK, NULL, &omask) == 0) sigsuspend(&omask); } }