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

4.11
Last change on this file since d112679 was d112679, checked in by Christian Mauderer <Christian.Mauderer@…>, on 07/06/16 at 07:50:51

pfctl: Add const and move static variables.

Note: This should be upstreamed into BSD.

Make everything constant that can be constant and move static variables
out of their functions.

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