source: rtems-libbsd/freebsd/contrib/pf/pfctl/pfctl_qstats.c @ 4831944

4.11
Last change on this file since 4831944 was 4831944, checked in by Christian Mauderer <Christian.Mauderer@…>, on 07/05/16 at 14:31:43

pfctl: Adapt for RTEMS.

  • Property mode set to 100644
File size: 11.2 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3/*      $OpenBSD: pfctl_qstats.c,v 1.30 2004/04/27 21:47:32 kjc Exp $ */
4
5/*
6 * Copyright (c) Henning Brauer <henning@openbsd.org>
7 *
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 */
20
21#ifdef __rtems__
22#include <machine/rtems-bsd-program.h>
23#endif /* __rtems__ */
24#include <sys/cdefs.h>
25__FBSDID("$FreeBSD$");
26
27#include <rtems/bsd/sys/types.h>
28#include <sys/ioctl.h>
29#include <sys/socket.h>
30
31#include <net/if.h>
32#include <netinet/in.h>
33#include <net/pfvar.h>
34#include <arpa/inet.h>
35
36#include <err.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40#include <unistd.h>
41
42#include <altq/altq.h>
43#include <altq/altq_cbq.h>
44#include <altq/altq_priq.h>
45#include <altq/altq_hfsc.h>
46
47#include "pfctl.h"
48#include "pfctl_parser.h"
49
50union class_stats {
51        class_stats_t           cbq_stats;
52        struct priq_classstats  priq_stats;
53        struct hfsc_classstats  hfsc_stats;
54};
55
56#define AVGN_MAX        8
57#define STAT_INTERVAL   5
58
59struct queue_stats {
60        union class_stats        data;
61        int                      avgn;
62        double                   avg_bytes;
63        double                   avg_packets;
64        u_int64_t                prev_bytes;
65        u_int64_t                prev_packets;
66};
67
68struct pf_altq_node {
69        struct pf_altq           altq;
70        struct pf_altq_node     *next;
71        struct pf_altq_node     *children;
72        struct queue_stats       qstats;
73};
74
75#ifdef __rtems__
76static  u_int32_t        last_ticket;
77
78#endif /* __rtems__ */
79int                      pfctl_update_qstats(int, struct pf_altq_node **);
80void                     pfctl_insert_altq_node(struct pf_altq_node **,
81                            const struct pf_altq, const struct queue_stats);
82struct pf_altq_node     *pfctl_find_altq_node(struct pf_altq_node *,
83                            const char *, const char *);
84void                     pfctl_print_altq_node(int, const struct pf_altq_node *,
85                            unsigned, int);
86void                     print_cbqstats(struct queue_stats);
87void                     print_priqstats(struct queue_stats);
88void                     print_hfscstats(struct queue_stats);
89void                     pfctl_free_altq_node(struct pf_altq_node *);
90void                     pfctl_print_altq_nodestat(int,
91                            const struct pf_altq_node *);
92
93void                     update_avg(struct pf_altq_node *);
94
95int
96pfctl_show_altq(int dev, const char *iface, int opts, int verbose2)
97{
98        struct pf_altq_node     *root = NULL, *node;
99        int                      nodes, dotitle = (opts & PF_OPT_SHOWALL);
100
101#ifdef __FreeBSD__
102        if (!altqsupport)
103                return (-1);
104#endif
105
106        if ((nodes = pfctl_update_qstats(dev, &root)) < 0)
107                return (-1);
108
109        if (nodes == 0)
110                printf("No queue in use\n");
111        for (node = root; node != NULL; node = node->next) {
112                if (iface != NULL && strcmp(node->altq.ifname, iface))
113                        continue;
114                if (dotitle) {
115                        pfctl_print_title("ALTQ:");
116                        dotitle = 0;
117                }
118                pfctl_print_altq_node(dev, node, 0, opts);
119        }
120
121        while (verbose2 && nodes > 0) {
122                printf("\n");
123                fflush(stdout);
124                sleep(STAT_INTERVAL);
125                if ((nodes = pfctl_update_qstats(dev, &root)) == -1)
126                        return (-1);
127                for (node = root; node != NULL; node = node->next) {
128                        if (iface != NULL && strcmp(node->altq.ifname, iface))
129                                continue;
130#ifdef __FreeBSD__
131                        if (node->altq.local_flags & PFALTQ_FLAG_IF_REMOVED)
132                                continue;
133#endif
134                        pfctl_print_altq_node(dev, node, 0, opts);
135                }
136        }
137        pfctl_free_altq_node(root);
138        return (0);
139}
140
141int
142pfctl_update_qstats(int dev, struct pf_altq_node **root)
143{
144        struct pf_altq_node     *node;
145        struct pfioc_altq        pa;
146        struct pfioc_qstats      pq;
147        u_int32_t                mnr, nr;
148        struct queue_stats       qstats;
149#ifndef __rtems__
150        static  u_int32_t        last_ticket;
151#endif /* __rtems__ */
152
153        memset(&pa, 0, sizeof(pa));
154        memset(&pq, 0, sizeof(pq));
155        memset(&qstats, 0, sizeof(qstats));
156        if (ioctl(dev, DIOCGETALTQS, &pa)) {
157                warn("DIOCGETALTQS");
158                return (-1);
159        }
160
161        /* if a new set is found, start over */
162        if (pa.ticket != last_ticket && *root != NULL) {
163                pfctl_free_altq_node(*root);
164                *root = NULL;
165        }
166        last_ticket = pa.ticket;
167
168        mnr = pa.nr;
169        for (nr = 0; nr < mnr; ++nr) {
170                pa.nr = nr;
171                if (ioctl(dev, DIOCGETALTQ, &pa)) {
172                        warn("DIOCGETALTQ");
173                        return (-1);
174                }
175#ifdef __FreeBSD__
176                if (pa.altq.qid > 0 &&
177                    !(pa.altq.local_flags & PFALTQ_FLAG_IF_REMOVED)) {
178#else
179                if (pa.altq.qid > 0) {
180#endif
181                        pq.nr = nr;
182                        pq.ticket = pa.ticket;
183                        pq.buf = &qstats.data;
184                        pq.nbytes = sizeof(qstats.data);
185                        if (ioctl(dev, DIOCGETQSTATS, &pq)) {
186                                warn("DIOCGETQSTATS");
187                                return (-1);
188                        }
189                        if ((node = pfctl_find_altq_node(*root, pa.altq.qname,
190                            pa.altq.ifname)) != NULL) {
191                                memcpy(&node->qstats.data, &qstats.data,
192                                    sizeof(qstats.data));
193                                update_avg(node);
194                        } else {
195                                pfctl_insert_altq_node(root, pa.altq, qstats);
196                        }
197                }
198#ifdef __FreeBSD__
199                else if (pa.altq.local_flags & PFALTQ_FLAG_IF_REMOVED) {
200                        memset(&qstats.data, 0, sizeof(qstats.data));
201                        if ((node = pfctl_find_altq_node(*root, pa.altq.qname,
202                            pa.altq.ifname)) != NULL) {
203                                memcpy(&node->qstats.data, &qstats.data,
204                                    sizeof(qstats.data));
205                                update_avg(node);
206                        } else {
207                                pfctl_insert_altq_node(root, pa.altq, qstats);
208                        }
209                }
210#endif
211        }
212        return (mnr);
213}
214
215void
216pfctl_insert_altq_node(struct pf_altq_node **root,
217    const struct pf_altq altq, const struct queue_stats qstats)
218{
219        struct pf_altq_node     *node;
220
221        node = calloc(1, sizeof(struct pf_altq_node));
222        if (node == NULL)
223                err(1, "pfctl_insert_altq_node: calloc");
224        memcpy(&node->altq, &altq, sizeof(struct pf_altq));
225        memcpy(&node->qstats, &qstats, sizeof(qstats));
226        node->next = node->children = NULL;
227
228        if (*root == NULL)
229                *root = node;
230        else if (!altq.parent[0]) {
231                struct pf_altq_node     *prev = *root;
232
233                while (prev->next != NULL)
234                        prev = prev->next;
235                prev->next = node;
236        } else {
237                struct pf_altq_node     *parent;
238
239                parent = pfctl_find_altq_node(*root, altq.parent, altq.ifname);
240                if (parent == NULL)
241                        errx(1, "parent %s not found", altq.parent);
242                if (parent->children == NULL)
243                        parent->children = node;
244                else {
245                        struct pf_altq_node *prev = parent->children;
246
247                        while (prev->next != NULL)
248                                prev = prev->next;
249                        prev->next = node;
250                }
251        }
252        update_avg(node);
253}
254
255struct pf_altq_node *
256pfctl_find_altq_node(struct pf_altq_node *root, const char *qname,
257    const char *ifname)
258{
259        struct pf_altq_node     *node, *child;
260
261        for (node = root; node != NULL; node = node->next) {
262                if (!strcmp(node->altq.qname, qname)
263                    && !(strcmp(node->altq.ifname, ifname)))
264                        return (node);
265                if (node->children != NULL) {
266                        child = pfctl_find_altq_node(node->children, qname,
267                            ifname);
268                        if (child != NULL)
269                                return (child);
270                }
271        }
272        return (NULL);
273}
274
275void
276pfctl_print_altq_node(int dev, const struct pf_altq_node *node,
277    unsigned int level, int opts)
278{
279        const struct pf_altq_node       *child;
280
281        if (node == NULL)
282                return;
283
284        print_altq(&node->altq, level, NULL, NULL);
285
286        if (node->children != NULL) {
287                printf("{");
288                for (child = node->children; child != NULL;
289                    child = child->next) {
290                        printf("%s", child->altq.qname);
291                        if (child->next != NULL)
292                                printf(", ");
293                }
294                printf("}");
295        }
296        printf("\n");
297
298        if (opts & PF_OPT_VERBOSE)
299                pfctl_print_altq_nodestat(dev, node);
300
301        if (opts & PF_OPT_DEBUG)
302                printf("  [ qid=%u ifname=%s ifbandwidth=%s ]\n",
303                    node->altq.qid, node->altq.ifname,
304                    rate2str((double)(node->altq.ifbandwidth)));
305
306        for (child = node->children; child != NULL;
307            child = child->next)
308                pfctl_print_altq_node(dev, child, level + 1, opts);
309}
310
311void
312pfctl_print_altq_nodestat(int dev, const struct pf_altq_node *a)
313{
314        if (a->altq.qid == 0)
315                return;
316
317#ifdef __FreeBSD__
318        if (a->altq.local_flags & PFALTQ_FLAG_IF_REMOVED)
319                return;
320#endif
321        switch (a->altq.scheduler) {
322        case ALTQT_CBQ:
323                print_cbqstats(a->qstats);
324                break;
325        case ALTQT_PRIQ:
326                print_priqstats(a->qstats);
327                break;
328        case ALTQT_HFSC:
329                print_hfscstats(a->qstats);
330                break;
331        }
332}
333
334void
335print_cbqstats(struct queue_stats cur)
336{
337        printf("  [ pkts: %10llu  bytes: %10llu  "
338            "dropped pkts: %6llu bytes: %6llu ]\n",
339            (unsigned long long)cur.data.cbq_stats.xmit_cnt.packets,
340            (unsigned long long)cur.data.cbq_stats.xmit_cnt.bytes,
341            (unsigned long long)cur.data.cbq_stats.drop_cnt.packets,
342            (unsigned long long)cur.data.cbq_stats.drop_cnt.bytes);
343        printf("  [ qlength: %3d/%3d  borrows: %6u  suspends: %6u ]\n",
344            cur.data.cbq_stats.qcnt, cur.data.cbq_stats.qmax,
345            cur.data.cbq_stats.borrows, cur.data.cbq_stats.delays);
346
347        if (cur.avgn < 2)
348                return;
349
350        printf("  [ measured: %7.1f packets/s, %s/s ]\n",
351            cur.avg_packets / STAT_INTERVAL,
352            rate2str((8 * cur.avg_bytes) / STAT_INTERVAL));
353}
354
355void
356print_priqstats(struct queue_stats cur)
357{
358        printf("  [ pkts: %10llu  bytes: %10llu  "
359            "dropped pkts: %6llu bytes: %6llu ]\n",
360            (unsigned long long)cur.data.priq_stats.xmitcnt.packets,
361            (unsigned long long)cur.data.priq_stats.xmitcnt.bytes,
362            (unsigned long long)cur.data.priq_stats.dropcnt.packets,
363            (unsigned long long)cur.data.priq_stats.dropcnt.bytes);
364        printf("  [ qlength: %3d/%3d ]\n",
365            cur.data.priq_stats.qlength, cur.data.priq_stats.qlimit);
366
367        if (cur.avgn < 2)
368                return;
369
370        printf("  [ measured: %7.1f packets/s, %s/s ]\n",
371            cur.avg_packets / STAT_INTERVAL,
372            rate2str((8 * cur.avg_bytes) / STAT_INTERVAL));
373}
374
375void
376print_hfscstats(struct queue_stats cur)
377{
378        printf("  [ pkts: %10llu  bytes: %10llu  "
379            "dropped pkts: %6llu bytes: %6llu ]\n",
380            (unsigned long long)cur.data.hfsc_stats.xmit_cnt.packets,
381            (unsigned long long)cur.data.hfsc_stats.xmit_cnt.bytes,
382            (unsigned long long)cur.data.hfsc_stats.drop_cnt.packets,
383            (unsigned long long)cur.data.hfsc_stats.drop_cnt.bytes);
384        printf("  [ qlength: %3d/%3d ]\n",
385            cur.data.hfsc_stats.qlength, cur.data.hfsc_stats.qlimit);
386
387        if (cur.avgn < 2)
388                return;
389
390        printf("  [ measured: %7.1f packets/s, %s/s ]\n",
391            cur.avg_packets / STAT_INTERVAL,
392            rate2str((8 * cur.avg_bytes) / STAT_INTERVAL));
393}
394
395void
396pfctl_free_altq_node(struct pf_altq_node *node)
397{
398        while (node != NULL) {
399                struct pf_altq_node     *prev;
400
401                if (node->children != NULL)
402                        pfctl_free_altq_node(node->children);
403                prev = node;
404                node = node->next;
405                free(prev);
406        }
407}
408
409void
410update_avg(struct pf_altq_node *a)
411{
412        struct queue_stats      *qs;
413        u_int64_t                b, p;
414        int                      n;
415
416        if (a->altq.qid == 0)
417                return;
418
419        qs = &a->qstats;
420        n = qs->avgn;
421
422        switch (a->altq.scheduler) {
423        case ALTQT_CBQ:
424                b = qs->data.cbq_stats.xmit_cnt.bytes;
425                p = qs->data.cbq_stats.xmit_cnt.packets;
426                break;
427        case ALTQT_PRIQ:
428                b = qs->data.priq_stats.xmitcnt.bytes;
429                p = qs->data.priq_stats.xmitcnt.packets;
430                break;
431        case ALTQT_HFSC:
432                b = qs->data.hfsc_stats.xmit_cnt.bytes;
433                p = qs->data.hfsc_stats.xmit_cnt.packets;
434                break;
435        default:
436                b = 0;
437                p = 0;
438                break;
439        }
440
441        if (n == 0) {
442                qs->prev_bytes = b;
443                qs->prev_packets = p;
444                qs->avgn++;
445                return;
446        }
447
448        if (b >= qs->prev_bytes)
449                qs->avg_bytes = ((qs->avg_bytes * (n - 1)) +
450                    (b - qs->prev_bytes)) / n;
451
452        if (p >= qs->prev_packets)
453                qs->avg_packets = ((qs->avg_packets * (n - 1)) +
454                    (p - qs->prev_packets)) / n;
455
456        qs->prev_bytes = b;
457        qs->prev_packets = p;
458        if (n < AVGN_MAX)
459                qs->avgn++;
460}
461#ifdef __rtems__
462#include "pfctl_qstats-data.h"
463#endif /* __rtems__ */
Note: See TracBrowser for help on using the repository browser.