parent
a2d3ff9b83
commit
e5879dc603
|
|
@ -0,0 +1,62 @@
|
|||
#ifndef __LINUX_GEN_STATS_H
|
||||
#define __LINUX_GEN_STATS_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
enum {
|
||||
TCA_STATS_UNSPEC,
|
||||
TCA_STATS_BASIC,
|
||||
TCA_STATS_RATE_EST,
|
||||
TCA_STATS_QUEUE,
|
||||
TCA_STATS_APP,
|
||||
__TCA_STATS_MAX,
|
||||
};
|
||||
#define TCA_STATS_MAX (__TCA_STATS_MAX - 1)
|
||||
|
||||
/**
|
||||
* @bytes: number of seen bytes
|
||||
* @packets: number of seen packets
|
||||
*/
|
||||
struct gnet_stats_basic
|
||||
{
|
||||
__u64 bytes;
|
||||
__u32 packets;
|
||||
};
|
||||
|
||||
/**
|
||||
* @bps: current byte rate
|
||||
* @pps: current packet rate
|
||||
*/
|
||||
struct gnet_stats_rate_est
|
||||
{
|
||||
__u32 bps;
|
||||
__u32 pps;
|
||||
};
|
||||
|
||||
/**
|
||||
* @qlen: queue length
|
||||
* @backlog: backlog size of queue
|
||||
* @drops: number of dropped packets
|
||||
* @requeues: number of requeues
|
||||
*/
|
||||
struct gnet_stats_queue
|
||||
{
|
||||
__u32 qlen;
|
||||
__u32 backlog;
|
||||
__u32 drops;
|
||||
__u32 requeues;
|
||||
__u32 overlimits;
|
||||
};
|
||||
|
||||
/**
|
||||
* @interval: sampling period
|
||||
* @ewma_log: the log of measurement window weight
|
||||
*/
|
||||
struct gnet_estimator
|
||||
{
|
||||
signed char interval;
|
||||
unsigned char ewma_log;
|
||||
};
|
||||
|
||||
|
||||
#endif /* __LINUX_GEN_STATS_H */
|
||||
|
|
@ -698,6 +698,8 @@ enum
|
|||
TCA_XSTATS,
|
||||
TCA_RATE,
|
||||
TCA_FCNT,
|
||||
TCA_STATS2,
|
||||
TCA_ACT_STATS,
|
||||
__TCA_MAX
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -261,9 +261,9 @@ tc_print_one_action(FILE * f, struct rtattr *arg)
|
|||
if (0 > err)
|
||||
return err;
|
||||
|
||||
if (show_stats && tb[TCA_STATS]) {
|
||||
fprintf(f, "\t");
|
||||
print_tcstats_attr(f, tb[TCA_STATS]);
|
||||
if (show_stats && tb[TCA_ACT_STATS]) {
|
||||
fprintf(f, "\tAction statistics:\n");
|
||||
print_tcstats2_attr(f, tb[TCA_ACT_STATS], "\t", NULL);
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -216,12 +216,14 @@ static int print_class(const struct sockaddr_nl *who,
|
|||
}
|
||||
fprintf(fp, "\n");
|
||||
if (show_stats) {
|
||||
if (tb[TCA_STATS]) {
|
||||
print_tcstats_attr(fp, tb[TCA_STATS]);
|
||||
struct rtattr *xstats = NULL;
|
||||
|
||||
if (tb[TCA_STATS] || tb[TCA_STATS2]) {
|
||||
print_tcstats_attr(fp, tb, " ", &xstats);
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
if (q && tb[TCA_XSTATS] && q->print_xstats) {
|
||||
q->print_xstats(q, fp, tb[TCA_XSTATS]);
|
||||
if (q && (xstats || tb[TCA_XSTATS]) && q->print_xstats) {
|
||||
q->print_xstats(q, fp, xstats ? : tb[TCA_XSTATS]);
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -254,8 +254,8 @@ static int print_filter(const struct sockaddr_nl *who,
|
|||
}
|
||||
fprintf(fp, "\n");
|
||||
|
||||
if (show_stats && tb[TCA_STATS]) {
|
||||
print_tcstats_attr(fp, tb[TCA_STATS]);
|
||||
if (show_stats && (tb[TCA_STATS] || tb[TCA_STATS2])) {
|
||||
print_tcstats_attr(fp, tb, " ", NULL);
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -167,39 +167,6 @@ int tc_qdisc_modify(int cmd, unsigned flags, int argc, char **argv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void print_tcstats_attr(FILE *fp, const struct rtattr *rta)
|
||||
{
|
||||
struct tc_stats st;
|
||||
SPRINT_BUF(b1);
|
||||
|
||||
/* handle case where kernel returns more/less than we know about */
|
||||
memset(&st, 0, sizeof(st));
|
||||
memcpy(&st, RTA_DATA(rta), MIN(RTA_PAYLOAD(rta), sizeof(st)));
|
||||
|
||||
fprintf(fp, " Sent %llu bytes %u pkts (dropped %u, overlimits %u) ",
|
||||
(unsigned long long)st.bytes, st.packets, st.drops,
|
||||
st.overlimits);
|
||||
|
||||
if (st.bps || st.pps || st.qlen || st.backlog) {
|
||||
fprintf(fp, "\n ");
|
||||
if (st.bps || st.pps) {
|
||||
fprintf(fp, "rate ");
|
||||
if (st.bps)
|
||||
fprintf(fp, "%s ", sprint_rate(st.bps, b1));
|
||||
if (st.pps)
|
||||
fprintf(fp, "%upps ", st.pps);
|
||||
}
|
||||
if (st.qlen || st.backlog) {
|
||||
fprintf(fp, "backlog ");
|
||||
if (st.backlog)
|
||||
fprintf(fp, "%s ", sprint_size(st.backlog, b1));
|
||||
if (st.qlen)
|
||||
fprintf(fp, "%up ", st.qlen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int filter_ifindex;
|
||||
|
||||
static int print_qdisc(const struct sockaddr_nl *who,
|
||||
|
|
@ -264,13 +231,15 @@ static int print_qdisc(const struct sockaddr_nl *who,
|
|||
}
|
||||
fprintf(fp, "\n");
|
||||
if (show_stats) {
|
||||
if (tb[TCA_STATS]) {
|
||||
print_tcstats_attr(fp, tb[TCA_STATS]);
|
||||
struct rtattr *xstats = NULL;
|
||||
|
||||
if (tb[TCA_STATS] || tb[TCA_STATS2] || tb[TCA_XSTATS]) {
|
||||
print_tcstats_attr(fp, tb, " ", &xstats);
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
|
||||
if (q && tb[TCA_XSTATS] && q->print_xstats) {
|
||||
q->print_xstats(q, fp, tb[TCA_XSTATS]);
|
||||
if (q && xstats && q->print_xstats) {
|
||||
q->print_xstats(q, fp, xstats);
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
88
tc/tc_util.c
88
tc/tc_util.c
|
|
@ -425,3 +425,91 @@ void print_tm(FILE * f, const struct tcf_t *tm)
|
|||
if (tm->expires != 0)
|
||||
fprintf(f, " expires %d sec", tm->expires/hz);
|
||||
}
|
||||
|
||||
void print_tcstats2_attr(FILE *fp, struct rtattr *rta, char *prefix, struct rtattr **xstats)
|
||||
{
|
||||
SPRINT_BUF(b1);
|
||||
struct rtattr *tbs[TCA_STATS_MAX + 1] = {0};
|
||||
|
||||
parse_rtattr(tbs, TCA_STATS_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta));
|
||||
|
||||
if (tbs[TCA_STATS_BASIC]) {
|
||||
struct gnet_stats_basic bs = {0};
|
||||
memcpy(&bs, RTA_DATA(tbs[TCA_STATS_BASIC]), MIN(RTA_PAYLOAD(tbs[TCA_STATS_BASIC]), sizeof(bs)));
|
||||
fprintf(fp, "%sSent %llu bytes %u pkt",
|
||||
prefix, bs.bytes, bs.packets);
|
||||
}
|
||||
|
||||
if (tbs[TCA_STATS_QUEUE]) {
|
||||
struct gnet_stats_queue q = {0};
|
||||
memcpy(&q, RTA_DATA(tbs[TCA_STATS_QUEUE]), MIN(RTA_PAYLOAD(tbs[TCA_STATS_QUEUE]), sizeof(q)));
|
||||
fprintf(fp, " (dropped %u, overlimits %u requeues %u) ",
|
||||
q.drops, q.overlimits, q.requeues);
|
||||
}
|
||||
|
||||
if (tbs[TCA_STATS_RATE_EST]) {
|
||||
struct gnet_stats_rate_est re = {0};
|
||||
memcpy(&re, RTA_DATA(tbs[TCA_STATS_RATE_EST]), MIN(RTA_PAYLOAD(tbs[TCA_STATS_RATE_EST]), sizeof(re)));
|
||||
fprintf(fp, "\n%srate %s %upps ",
|
||||
prefix, sprint_rate(re.bps, b1), re.pps);
|
||||
}
|
||||
|
||||
if (tbs[TCA_STATS_QUEUE]) {
|
||||
struct gnet_stats_queue q = {0};
|
||||
memcpy(&q, RTA_DATA(tbs[TCA_STATS_QUEUE]), MIN(RTA_PAYLOAD(tbs[TCA_STATS_QUEUE]), sizeof(q)));
|
||||
if (!tbs[TCA_STATS_RATE_EST])
|
||||
fprintf(fp, "\n%s", prefix);
|
||||
fprintf(fp, "backlog %s %up requeues %u ",
|
||||
sprint_size(q.backlog, b1), q.qlen, q.requeues);
|
||||
}
|
||||
|
||||
if (xstats)
|
||||
*xstats = tbs[TCA_STATS_APP] ? : NULL;
|
||||
}
|
||||
|
||||
void print_tcstats_attr(FILE *fp, struct rtattr *tb[], char *prefix, struct rtattr **xstats)
|
||||
{
|
||||
SPRINT_BUF(b1);
|
||||
|
||||
if (tb[TCA_STATS2]) {
|
||||
print_tcstats2_attr(fp, tb[TCA_STATS2], prefix, xstats);
|
||||
if (xstats && NULL == *xstats)
|
||||
goto compat_xstats;
|
||||
return;
|
||||
}
|
||||
/* backward compatibility */
|
||||
if (tb[TCA_STATS]) {
|
||||
struct tc_stats st;
|
||||
|
||||
/* handle case where kernel returns more/less than we know about */
|
||||
memset(&st, 0, sizeof(st));
|
||||
memcpy(&st, RTA_DATA(tb[TCA_STATS]), MIN(RTA_PAYLOAD(tb[TCA_STATS]), sizeof(st)));
|
||||
|
||||
fprintf(fp, "%sSent %llu bytes %u pkts (dropped %u, overlimits %u) ",
|
||||
prefix, (unsigned long long)st.bytes, st.packets, st.drops,
|
||||
st.overlimits);
|
||||
|
||||
if (st.bps || st.pps || st.qlen || st.backlog) {
|
||||
fprintf(fp, "\n%s", prefix);
|
||||
if (st.bps || st.pps) {
|
||||
fprintf(fp, "rate ");
|
||||
if (st.bps)
|
||||
fprintf(fp, "%s ", sprint_rate(st.bps, b1));
|
||||
if (st.pps)
|
||||
fprintf(fp, "%upps ", st.pps);
|
||||
}
|
||||
if (st.qlen || st.backlog) {
|
||||
fprintf(fp, "backlog ");
|
||||
if (st.backlog)
|
||||
fprintf(fp, "%s ", sprint_size(st.backlog, b1));
|
||||
if (st.qlen)
|
||||
fprintf(fp, "%up ", st.qlen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
compat_xstats:
|
||||
if (tb[TCA_XSTATS] && xstats)
|
||||
*xstats = tb[TCA_XSTATS];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#define MAX_MSG 16384
|
||||
#include <linux/pkt_sched.h>
|
||||
#include <linux/pkt_cls.h>
|
||||
#include <linux/gen_stats.h>
|
||||
#include "tc_core.h"
|
||||
|
||||
struct qdisc_util
|
||||
|
|
@ -58,7 +59,8 @@ extern char * sprint_tc_classid(__u32 h, char *buf);
|
|||
extern char * sprint_usecs(__u32 usecs, char *buf);
|
||||
extern char * sprint_percent(__u32 percent, char *buf);
|
||||
|
||||
extern void print_tcstats_attr(FILE *fp, const struct rtattr *ts);
|
||||
extern void print_tcstats_attr(FILE *fp, struct rtattr *tb[], char *prefix, struct rtattr **xstats);
|
||||
extern void print_tcstats2_attr(FILE *fp, struct rtattr *rta, char *prefix, struct rtattr **xstats);
|
||||
|
||||
extern int get_tc_classid(__u32 *h, const char *str);
|
||||
extern int print_tc_classid(char *buf, int len, __u32 h);
|
||||
|
|
|
|||
Loading…
Reference in New Issue