123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313 |
- /*
- * Copyright (c) 2016 Fabien Siron <fabien.siron@epita.fr>
- * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
- * Copyright (c) 2016-2018 The strace developers.
- * All rights reserved.
- *
- * SPDX-License-Identifier: LGPL-2.1-or-later
- */
-
- #include "defs.h"
- #include "netlink_route.h"
- #include "nlattr.h"
- #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,
- [TCA_STATS_BASIC_HW] = decode_gnet_stats_basic,
- };
-
- 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),
- tfetch_mem, 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,
- [TCA_HW_OFFLOAD] = decode_nla_u8,
- [TCA_INGRESS_BLOCK] = decode_nla_u32,
- [TCA_EGRESS_BLOCK] = decode_nla_u32,
- };
-
- DECL_NETLINK_ROUTE_DECODER(decode_tcmsg)
- {
- struct tcmsg tcmsg = { .tcm_family = family };
- size_t offset = sizeof(tcmsg.tcm_family);
- bool decode_nla = false;
-
- PRINT_FIELD_XVAL("{", tcmsg, tcm_family, addrfams, "AF_???");
-
- tprints(", ");
- if (len >= sizeof(tcmsg)) {
- if (!umoven_or_printaddr(tcp, addr + offset,
- sizeof(tcmsg) - offset,
- (char *) &tcmsg + offset)) {
- PRINT_FIELD_IFINDEX("", tcmsg, tcm_ifindex);
- PRINT_FIELD_U(", ", tcmsg, tcm_handle);
- PRINT_FIELD_U(", ", tcmsg, tcm_parent);
- PRINT_FIELD_U(", ", tcmsg, tcm_info);
- decode_nla = true;
- }
- } else
- tprints("...");
- tprints("}");
-
- offset = NLMSG_ALIGN(sizeof(tcmsg));
- if (decode_nla && len > offset) {
- tprints(", ");
- decode_nlattr(tcp, addr + offset, len - offset,
- rtnl_tc_attrs, "TCA_???", tcmsg_nla_decoders,
- ARRAY_SIZE(tcmsg_nla_decoders), NULL);
- }
- }
|