Commit e5879dc6 authored by ch[shemminger]!tgraf's avatar ch[shemminger]!tgraf

iproute2: gnet_stats

(Logical change 1.107)
parent a2d3ff9b
#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");
}
}
......
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment