2 * Copyright (c) 2016 Fabien Siron <fabien.siron@epita.fr>
3 * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
4 * Copyright (c) 2016-2018 The strace developers.
7 * SPDX-License-Identifier: LGPL-2.1-or-later
11 #include "netlink_route.h"
13 #include "print_fields.h"
16 #ifdef HAVE_STRUCT_GNET_STATS_BASIC
17 # include <linux/gen_stats.h>
19 #include <linux/pkt_sched.h>
20 #include <linux/rtnetlink.h>
22 #include "xlat/rtnl_tc_attrs.h"
23 #include "xlat/rtnl_tca_stab_attrs.h"
24 #include "xlat/rtnl_tca_stats_attrs.h"
27 decode_tc_stats(struct tcb *const tcp,
28 const kernel_ulong_t addr,
29 const unsigned int len,
30 const void *const opaque_data)
33 const unsigned int sizeof_tc_stats =
34 offsetofend(struct tc_stats, backlog);
36 if (len < sizeof_tc_stats)
38 else if (!umoven_or_printaddr(tcp, addr, sizeof_tc_stats, &st)) {
39 PRINT_FIELD_U("{", st, bytes);
40 PRINT_FIELD_U(", ", st, packets);
41 PRINT_FIELD_U(", ", st, drops);
42 PRINT_FIELD_U(", ", st, overlimits);
43 PRINT_FIELD_U(", ", st, bps);
44 PRINT_FIELD_U(", ", st, pps);
45 PRINT_FIELD_U(", ", st, qlen);
46 PRINT_FIELD_U(", ", st, backlog);
54 decode_tc_estimator(struct tcb *const tcp,
55 const kernel_ulong_t addr,
56 const unsigned int len,
57 const void *const opaque_data)
59 struct tc_estimator est;
61 if (len < sizeof(est))
63 else if (!umove_or_printaddr(tcp, addr, &est)) {
64 PRINT_FIELD_D("{", est, interval);
65 PRINT_FIELD_U(", ", est, ewma_log);
73 decode_gnet_stats_basic(struct tcb *const tcp,
74 const kernel_ulong_t addr,
75 const unsigned int len,
76 const void *const opaque_data)
78 #ifdef HAVE_STRUCT_GNET_STATS_BASIC
79 struct gnet_stats_basic sb;
80 const unsigned int sizeof_st_basic =
81 offsetofend(struct gnet_stats_basic, packets);
83 if (len < sizeof_st_basic)
85 else if (!umoven_or_printaddr(tcp, addr, sizeof_st_basic, &sb)) {
86 PRINT_FIELD_U("{", sb, bytes);
87 PRINT_FIELD_U(", ", sb, packets);
98 decode_gnet_stats_rate_est(struct tcb *const tcp,
99 const kernel_ulong_t addr,
100 const unsigned int len,
101 const void *const opaque_data)
103 #ifdef HAVE_STRUCT_GNET_STATS_RATE_EST
104 struct gnet_stats_rate_est est;
106 if (len < sizeof(est))
108 else if (!umove_or_printaddr(tcp, addr, &est)) {
109 PRINT_FIELD_U("{", est, bps);
110 PRINT_FIELD_U(", ", est, pps);
121 decode_gnet_stats_queue(struct tcb *const tcp,
122 const kernel_ulong_t addr,
123 const unsigned int len,
124 const void *const opaque_data)
126 #ifdef HAVE_STRUCT_GNET_STATS_QUEUE
127 struct gnet_stats_queue qstats;
129 if (len < sizeof(qstats))
131 else if (!umove_or_printaddr(tcp, addr, &qstats)) {
132 PRINT_FIELD_U("{", qstats, qlen);
133 PRINT_FIELD_U(", ", qstats, backlog);
134 PRINT_FIELD_U(", ", qstats, drops);
135 PRINT_FIELD_U(", ", qstats, requeues);
136 PRINT_FIELD_U(", ", qstats, overlimits);
147 decode_gnet_stats_rate_est64(struct tcb *const tcp,
148 const kernel_ulong_t addr,
149 const unsigned int len,
150 const void *const opaque_data)
152 #ifdef HAVE_STRUCT_GNET_STATS_RATE_EST64
153 struct gnet_stats_rate_est64 est;
155 if (len < sizeof(est))
157 else if (!umove_or_printaddr(tcp, addr, &est)) {
158 PRINT_FIELD_U("{", est, bps);
159 PRINT_FIELD_U(", ", est, pps);
169 static const nla_decoder_t tca_stats_nla_decoders[] = {
170 [TCA_STATS_BASIC] = decode_gnet_stats_basic,
171 [TCA_STATS_RATE_EST] = decode_gnet_stats_rate_est,
172 [TCA_STATS_QUEUE] = decode_gnet_stats_queue,
173 [TCA_STATS_APP] = NULL, /* unimplemented */
174 [TCA_STATS_RATE_EST64] = decode_gnet_stats_rate_est64,
175 [TCA_STATS_PAD] = NULL,
176 [TCA_STATS_BASIC_HW] = decode_gnet_stats_basic,
180 decode_nla_tc_stats(struct tcb *const tcp,
181 const kernel_ulong_t addr,
182 const unsigned int len,
183 const void *const opaque_data)
185 decode_nlattr(tcp, addr, len, rtnl_tca_stats_attrs, "TCA_STATS_???",
186 tca_stats_nla_decoders,
187 ARRAY_SIZE(tca_stats_nla_decoders), opaque_data);
193 decode_tc_sizespec(struct tcb *const tcp,
194 const kernel_ulong_t addr,
195 const unsigned int len,
196 const void *const opaque_data)
198 #ifdef HAVE_STRUCT_TC_SIZESPEC
199 struct tc_sizespec s;
203 else if (!umove_or_printaddr(tcp, addr, &s)) {
204 PRINT_FIELD_U("{", s, cell_log);
205 PRINT_FIELD_U(", ", s, size_log);
206 PRINT_FIELD_D(", ", s, cell_align);
207 PRINT_FIELD_D(", ", s, overhead);
208 PRINT_FIELD_U(", ", s, linklayer);
209 PRINT_FIELD_U(", ", s, mpu);
210 PRINT_FIELD_U(", ", s, mtu);
211 PRINT_FIELD_U(", ", s, tsize);
222 print_stab_data(struct tcb *const tcp, void *const elem_buf,
223 const size_t elem_size, void *const opaque_data)
225 tprintf("%" PRIu16, *(uint16_t *) elem_buf);
231 decode_tca_stab_data(struct tcb *const tcp,
232 const kernel_ulong_t addr,
233 const unsigned int len,
234 const void *const opaque_data)
237 const size_t nmemb = len / sizeof(data);
242 print_array(tcp, addr, nmemb, &data, sizeof(data),
243 tfetch_mem, print_stab_data, NULL);
248 static const nla_decoder_t tca_stab_nla_decoders[] = {
249 [TCA_STAB_BASE] = decode_tc_sizespec,
250 [TCA_STAB_DATA] = decode_tca_stab_data
254 decode_tca_stab(struct tcb *const tcp,
255 const kernel_ulong_t addr,
256 const unsigned int len,
257 const void *const opaque_data)
259 decode_nlattr(tcp, addr, len, rtnl_tca_stab_attrs, "TCA_STAB_???",
260 tca_stab_nla_decoders,
261 ARRAY_SIZE(tca_stab_nla_decoders), opaque_data);
266 static const nla_decoder_t tcmsg_nla_decoders[] = {
267 [TCA_KIND] = decode_nla_str,
268 [TCA_OPTIONS] = NULL, /* unimplemented */
269 [TCA_STATS] = decode_tc_stats,
270 [TCA_XSTATS] = NULL, /* unimplemented */
271 [TCA_RATE] = decode_tc_estimator,
272 [TCA_FCNT] = decode_nla_u32,
273 [TCA_STATS2] = decode_nla_tc_stats,
274 [TCA_STAB] = decode_tca_stab,
276 [TCA_DUMP_INVISIBLE] = NULL,
277 [TCA_CHAIN] = decode_nla_u32,
278 [TCA_HW_OFFLOAD] = decode_nla_u8,
279 [TCA_INGRESS_BLOCK] = decode_nla_u32,
280 [TCA_EGRESS_BLOCK] = decode_nla_u32,
283 DECL_NETLINK_ROUTE_DECODER(decode_tcmsg)
285 struct tcmsg tcmsg = { .tcm_family = family };
286 size_t offset = sizeof(tcmsg.tcm_family);
287 bool decode_nla = false;
289 PRINT_FIELD_XVAL("{", tcmsg, tcm_family, addrfams, "AF_???");
292 if (len >= sizeof(tcmsg)) {
293 if (!umoven_or_printaddr(tcp, addr + offset,
294 sizeof(tcmsg) - offset,
295 (char *) &tcmsg + offset)) {
296 PRINT_FIELD_IFINDEX("", tcmsg, tcm_ifindex);
297 PRINT_FIELD_U(", ", tcmsg, tcm_handle);
298 PRINT_FIELD_U(", ", tcmsg, tcm_parent);
299 PRINT_FIELD_U(", ", tcmsg, tcm_info);
306 offset = NLMSG_ALIGN(sizeof(tcmsg));
307 if (decode_nla && len > offset) {
309 decode_nlattr(tcp, addr + offset, len - offset,
310 rtnl_tc_attrs, "TCA_???", tcmsg_nla_decoders,
311 ARRAY_SIZE(tcmsg_nla_decoders), NULL);