* configure.ac (AC_CHECK_TYPES): Check for gnet_stats_basic, gnet_stats_queue, gnet_stats_rate_est, and gnet_stats_rate_est64 structures in <linux/gen_stats.h>. And check for struct tc_sizespec in <linux/pkt_sched.h>. * nlattr.h (tc_stats): New prototype. * rtnl_tc.c: Include <linux/gen_stats.h>, <linux/pkt_sched.h>, "xlat/rtnl_tca_stab_attrs.h" and "xlat/rtnl_tca_stats_attrs.h". (decode_tc_stats, decode_tc_estimator, decode_gnet_stats_basic, decode_gnet_stats_rate_est, decode_gnet_stats_queue, decode_gnet_stats_rate_est64, decode_nla_tc_stats, decode_tc_sizespec, print_stab_data, decode_tca_stab_data, decode_tca_stab): New functions. (tca_stats_nla_decoders, tca_stab_nla_decoders, tcmsg_nla_decoders): New arrays. (decode_tcmsg): Use tcmsg_nla_decoders. * xlat/rtnl_tca_stab_attrs.in: New file. * xlat/rtnl_tca_stats_attrs.in: Likewise. --- configure.ac | 9 ++ nlattr.h | 1 + rtnl_tc.c | 262 ++++++++++++++++++++++++++++++++++++++++++- xlat/rtnl_tca_stab_attrs.in | 3 + xlat/rtnl_tca_stats_attrs.in | 7 ++ 5 files changed, 281 insertions(+), 1 deletion(-) create mode 100644 xlat/rtnl_tca_stab_attrs.in create mode 100644 xlat/rtnl_tca_stats_attrs.in
diff --git a/configure.ac b/configure.ac index 8a50755..52a18fe 100644 --- a/configure.ac +++ b/configure.ac @@ -474,6 +474,15 @@ AC_CHECK_MEMBERS(m4_normalize([ struct rtnl_link_stats64.rx_nohandler ]),,, [#include <linux/if_link.h>]) +AC_CHECK_TYPES(m4_normalize([ + struct gnet_stats_basic, + struct gnet_stats_queue, + struct gnet_stats_rate_est, + struct gnet_stats_rate_est64 +]),,, [#include <linux/gen_stats.h>]) + +AC_CHECK_TYPES([struct tc_sizespec],,, [#include <linux/pkt_sched.h>]) + AC_CHECK_TYPES([struct fib_rule_uid_range],,, [#include <linux/fib_rules.h>]) AC_CHECK_TYPES([struct statfs], [ diff --git a/nlattr.h b/nlattr.h index 6e7d1a7..323f1d6 100644 --- a/nlattr.h +++ b/nlattr.h @@ -63,5 +63,6 @@ DECL_NLA(strn); DECL_NLA(ifindex); DECL_NLA(meminfo); DECL_NLA(rt_class); +DECL_NLA(tc_stats); #endif /* !STRACE_NLATTR_H */ diff --git a/rtnl_tc.c b/rtnl_tc.c index 74d9df2..e1bda75 100644 --- a/rtnl_tc.c +++ b/rtnl_tc.c @@ -33,9 +33,268 @@ #include "print_fields.h" #include "netlink.h" +#ifdef HAVE_STRUCT_GNET_STATS_BASIC +# include <linux/gen_stats.h> +#endif +#include <linux/pkt_sched.h> #include <linux/rtnetlink.h> #include "xlat/rtnl_tc_attrs.h" +#include "xlat/rtnl_tca_stab_attrs.h" +#include "xlat/rtnl_tca_stats_attrs.h" + +static bool +decode_tc_stats(struct tcb *const tcp, + const kernel_ulong_t addr, + const unsigned int len, + const void *const opaque_data) +{ + struct tc_stats st; + const unsigned int sizeof_tc_stats = + offsetofend(struct tc_stats, backlog); + + if (len < sizeof_tc_stats) + return false; + else if (!umoven_or_printaddr(tcp, addr, sizeof_tc_stats, &st)) { + PRINT_FIELD_U("{", st, bytes); + PRINT_FIELD_U(", ", st, packets); + PRINT_FIELD_U(", ", st, drops); + PRINT_FIELD_U(", ", st, overlimits); + PRINT_FIELD_U(", ", st, bps); + PRINT_FIELD_U(", ", st, pps); + PRINT_FIELD_U(", ", st, qlen); + PRINT_FIELD_U(", ", st, backlog); + tprints("}"); + } + + return true; +} + +static bool +decode_tc_estimator(struct tcb *const tcp, + const kernel_ulong_t addr, + const unsigned int len, + const void *const opaque_data) +{ + struct tc_estimator est; + + if (len < sizeof(est)) + return false; + else if (!umove_or_printaddr(tcp, addr, &est)) { + PRINT_FIELD_D("{", est, interval); + PRINT_FIELD_U(", ", est, ewma_log); + tprints("}"); + } + + return true; +} + +static bool +decode_gnet_stats_basic(struct tcb *const tcp, + const kernel_ulong_t addr, + const unsigned int len, + const void *const opaque_data) +{ +#ifdef HAVE_STRUCT_GNET_STATS_BASIC + struct gnet_stats_basic sb; + const unsigned int sizeof_st_basic = + offsetofend(struct gnet_stats_basic, packets); + + if (len < sizeof_st_basic) + return false; + else if (!umoven_or_printaddr(tcp, addr, sizeof_st_basic, &sb)) { + PRINT_FIELD_U("{", sb, bytes); + PRINT_FIELD_U(", ", sb, packets); + tprints("}"); + } + + return true; +#else + return false; +#endif +} + +static bool +decode_gnet_stats_rate_est(struct tcb *const tcp, + const kernel_ulong_t addr, + const unsigned int len, + const void *const opaque_data) +{ +#ifdef HAVE_STRUCT_GNET_STATS_RATE_EST + struct gnet_stats_rate_est est; + + if (len < sizeof(est)) + return false; + else if (!umove_or_printaddr(tcp, addr, &est)) { + PRINT_FIELD_U("{", est, bps); + PRINT_FIELD_U(", ", est, pps); + tprints("}"); + } + + return true; +#else + return false; +#endif +} + +static bool +decode_gnet_stats_queue(struct tcb *const tcp, + const kernel_ulong_t addr, + const unsigned int len, + const void *const opaque_data) +{ +#ifdef HAVE_STRUCT_GNET_STATS_QUEUE + struct gnet_stats_queue qstats; + + if (len < sizeof(qstats)) + return false; + else if (!umove_or_printaddr(tcp, addr, &qstats)) { + PRINT_FIELD_U("{", qstats, qlen); + PRINT_FIELD_U(", ", qstats, backlog); + PRINT_FIELD_U(", ", qstats, drops); + PRINT_FIELD_U(", ", qstats, requeues); + PRINT_FIELD_U(", ", qstats, overlimits); + tprints("}"); + } + + return true; +#else + return false; +#endif +} + +static bool +decode_gnet_stats_rate_est64(struct tcb *const tcp, + const kernel_ulong_t addr, + const unsigned int len, + const void *const opaque_data) +{ +#ifdef HAVE_STRUCT_GNET_STATS_RATE_EST64 + struct gnet_stats_rate_est64 est; + + if (len < sizeof(est)) + return false; + else if (!umove_or_printaddr(tcp, addr, &est)) { + PRINT_FIELD_U("{", est, bps); + PRINT_FIELD_U(", ", est, pps); + tprints("}"); + } + + return true; +#else + return false; +#endif +} + +static const nla_decoder_t tca_stats_nla_decoders[] = { + [TCA_STATS_BASIC] = decode_gnet_stats_basic, + [TCA_STATS_RATE_EST] = decode_gnet_stats_rate_est, + [TCA_STATS_QUEUE] = decode_gnet_stats_queue, + [TCA_STATS_APP] = NULL, /* unimplemented */ + [TCA_STATS_RATE_EST64] = decode_gnet_stats_rate_est64, + [TCA_STATS_PAD] = NULL, +}; + +bool +decode_nla_tc_stats(struct tcb *const tcp, + const kernel_ulong_t addr, + const unsigned int len, + const void *const opaque_data) +{ + decode_nlattr(tcp, addr, len, rtnl_tca_stats_attrs, "TCA_STATS_???", + tca_stats_nla_decoders, + ARRAY_SIZE(tca_stats_nla_decoders), opaque_data); + + return true; +} + +static bool +decode_tc_sizespec(struct tcb *const tcp, + const kernel_ulong_t addr, + const unsigned int len, + const void *const opaque_data) +{ +#ifdef HAVE_STRUCT_TC_SIZESPEC + struct tc_sizespec s; + + if (len < sizeof(s)) + return false; + else if (!umove_or_printaddr(tcp, addr, &s)) { + PRINT_FIELD_U("{", s, cell_log); + PRINT_FIELD_U(", ", s, size_log); + PRINT_FIELD_D(", ", s, cell_align); + PRINT_FIELD_D(", ", s, overhead); + PRINT_FIELD_U(", ", s, linklayer); + PRINT_FIELD_U(", ", s, mpu); + PRINT_FIELD_U(", ", s, mtu); + PRINT_FIELD_U(", ", s, tsize); + tprints("}"); + } + + return true; +#else + return false; +#endif +} + +static bool +print_stab_data(struct tcb *const tcp, void *const elem_buf, + const size_t elem_size, void *const opaque_data) +{ + tprintf("%" PRIu16, *(uint16_t *) elem_buf); + + return true; +} + +static bool +decode_tca_stab_data(struct tcb *const tcp, + const kernel_ulong_t addr, + const unsigned int len, + const void *const opaque_data) +{ + uint16_t data; + const size_t nmemb = len / sizeof(data); + + if (!nmemb) + return false; + + print_array(tcp, addr, nmemb, &data, sizeof(data), + umoven_or_printaddr, print_stab_data, NULL); + + return true; +} + +static const nla_decoder_t tca_stab_nla_decoders[] = { + [TCA_STAB_BASE] = decode_tc_sizespec, + [TCA_STAB_DATA] = decode_tca_stab_data +}; + +static bool +decode_tca_stab(struct tcb *const tcp, + const kernel_ulong_t addr, + const unsigned int len, + const void *const opaque_data) +{ + decode_nlattr(tcp, addr, len, rtnl_tca_stab_attrs, "TCA_STAB_???", + tca_stab_nla_decoders, + ARRAY_SIZE(tca_stab_nla_decoders), opaque_data); + + return true; +} + +static const nla_decoder_t tcmsg_nla_decoders[] = { + [TCA_KIND] = decode_nla_str, + [TCA_OPTIONS] = NULL, /* unimplemented */ + [TCA_STATS] = decode_tc_stats, + [TCA_XSTATS] = NULL, /* unimplemented */ + [TCA_RATE] = decode_tc_estimator, + [TCA_FCNT] = decode_nla_u32, + [TCA_STATS2] = decode_nla_tc_stats, + [TCA_STAB] = decode_tca_stab, + [TCA_PAD] = NULL, + [TCA_DUMP_INVISIBLE] = NULL, + [TCA_CHAIN] = decode_nla_u32 +}; DECL_NETLINK_ROUTE_DECODER(decode_tcmsg) { @@ -64,6 +323,7 @@ DECL_NETLINK_ROUTE_DECODER(decode_tcmsg) if (decode_nla && len > offset) { tprints(", "); decode_nlattr(tcp, addr + offset, len - offset, - rtnl_tc_attrs, "TCA_???", NULL, 0, NULL); + rtnl_tc_attrs, "TCA_???", tcmsg_nla_decoders, + ARRAY_SIZE(tcmsg_nla_decoders), NULL); } } diff --git a/xlat/rtnl_tca_stab_attrs.in b/xlat/rtnl_tca_stab_attrs.in new file mode 100644 index 0000000..dd3d6ef --- /dev/null +++ b/xlat/rtnl_tca_stab_attrs.in @@ -0,0 +1,3 @@ +TCA_STAB_UNSPEC 0 +TCA_STAB_BASE 1 +TCA_STAB_DATA 2 diff --git a/xlat/rtnl_tca_stats_attrs.in b/xlat/rtnl_tca_stats_attrs.in new file mode 100644 index 0000000..807e7fe --- /dev/null +++ b/xlat/rtnl_tca_stats_attrs.in @@ -0,0 +1,7 @@ +TCA_STATS_UNSPEC 0 +TCA_STATS_BASIC 1 +TCA_STATS_RATE_EST 2 +TCA_STATS_QUEUE 3 +TCA_STATS_APP 4 +TCA_STATS_RATE_EST64 5 +TCA_STATS_PAD 6 -- 2.7.4 ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ Strace-devel mailing list Strace-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/strace-devel