1 /*
2 * Copyright (c) 2016 Fabien Siron <fabien.siron@epita.fr>
3 * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
4 * Copyright (c) 2016-2023 The strace developers.
5 * All rights reserved.
6 *
7 * SPDX-License-Identifier: LGPL-2.1-or-later
8 */
9
10 #include "defs.h"
11 #include "netlink_route.h"
12 #include "nlattr.h"
13
14 #include "netlink.h"
15 #include <linux/pkt_cls.h>
16 #include <linux/rtnetlink.h>
17
18 #include "xlat/rtnl_tc_action_attrs.h"
19 #include "xlat/rtnl_tca_act_flags.h"
20 #include "xlat/rtnl_tca_act_hw_stats.h"
21 #include "xlat/rtnl_tca_root_flags.h"
22 #include "xlat/rtnl_tca_root_attrs.h"
23
24
25 static bool
26 decode_tca_act_flags(struct tcb *const tcp,
27 const kernel_ulong_t addr,
28 const unsigned int len,
29 const void *const opaque_data)
30 {
31 static const struct decode_nla_xlat_opts opts = {
32 rtnl_tca_act_flags, "TCA_ACT_FLAGS_???",
33 .size = 4,
34 };
35
36 return decode_nla_flags(tcp, addr, len, &opts);
37 }
38
39 static bool
40 decode_tca_act_hw_stats(struct tcb *const tcp,
41 const kernel_ulong_t addr,
42 const unsigned int len,
43 const void *const opaque_data)
44 {
45 static const struct decode_nla_xlat_opts opts = {
46 rtnl_tca_act_hw_stats, "TCA_ACT_HW_STATS_???",
47 .size = 4,
48 };
49
50 return decode_nla_flags(tcp, addr, len, &opts);
51 }
52
53 static const nla_decoder_t tca_act_nla_decoders[] = {
54 [TCA_ACT_KIND] = decode_nla_str,
55 [TCA_ACT_OPTIONS] = NULL, /* unimplemented */
56 [TCA_ACT_INDEX] = decode_nla_u32,
57 [TCA_ACT_STATS] = decode_nla_tc_stats,
58 [TCA_ACT_PAD] = NULL,
59 [TCA_ACT_COOKIE] = NULL, /* default parser */
60 [TCA_ACT_FLAGS] = decode_tca_act_flags,
61 [TCA_ACT_HW_STATS] = decode_tca_act_hw_stats,
62 [TCA_ACT_USED_HW_STATS] = decode_tca_act_hw_stats,
63 [TCA_ACT_IN_HW_COUNT] = decode_nla_u32,
64 };
65
66 static bool
67 decode_tca_action(struct tcb *const tcp,
68 const kernel_ulong_t addr,
69 const unsigned int len,
70 const void *const opaque_data)
71 {
72 decode_nlattr(tcp, addr, len, rtnl_tc_action_attrs, "TCA_ACT_???",
73 ARRSZ_PAIR(tca_act_nla_decoders), NULL);
74
75 return true;
76 }
77
78 static bool
79 decode_tca_root_act_tab(struct tcb *const tcp,
80 const kernel_ulong_t addr,
81 const unsigned int len,
82 const void *const opaque_data)
83 {
84 nla_decoder_t tca_action_decoder = &decode_tca_action;
85
86 /* TCA_ROOT_TAB (nee TCA_ACT_TAB) misuses nesting for array */
87 decode_nlattr(tcp, addr, len, NULL, NULL,
88 &tca_action_decoder, 0, NULL);
89
90 return true;
91 }
92
93 static bool
94 decode_tca_root_act_flags(struct tcb *const tcp,
95 const kernel_ulong_t addr,
96 const unsigned int len,
97 const void *const opaque_data)
98 {
99 static const struct decode_nla_xlat_opts opts = {
100 rtnl_tca_root_flags, "TCA_ACT_FLAG_???",
101 .size = 4,
102 };
103
104 return decode_nla_flags(tcp, addr, len, &opts);
105 }
106
107 static bool
108 decode_tca_msecs(struct tcb *const tcp,
109 const kernel_ulong_t addr,
110 const unsigned int len,
111 const void *const opaque_data)
112 {
113 uint64_t val;
114
115 if (len > sizeof(val))
116 return false;
117
118 if (!umoven_to_uint64_or_printaddr(tcp, addr, len, &val))
119 print_ticks(val, 1000, 3);
120
121 return true;
122 }
123
124 static const nla_decoder_t tcamsg_nla_decoders[] = {
125 [TCA_ROOT_UNSPEC] = NULL,
126 [TCA_ROOT_TAB] = decode_tca_root_act_tab,
127 [TCA_ROOT_FLAGS] = decode_tca_root_act_flags,
128 [TCA_ROOT_COUNT] = decode_nla_u32,
129 [TCA_ROOT_TIME_DELTA] = decode_tca_msecs,
130 [TCA_ROOT_EXT_WARN_MSG] = decode_nla_str,
131 };
132
133 DECL_NETLINK_ROUTE_DECODER(decode_tcamsg)
134 {
135 struct tcamsg tca = { .tca_family = family };
136
137 tprint_struct_begin();
138 PRINT_FIELD_XVAL(tca, tca_family, addrfams, "AF_???");
139 tprint_struct_end();
140
141 const size_t offset = NLMSG_ALIGN(sizeof(tca));
142 if (len > offset) {
143 tprint_array_next();
144 decode_nlattr(tcp, addr + offset, len - offset,
145 rtnl_tca_root_attrs, "TCA_ROOT_???",
146 tcamsg_nla_decoders,
147 ARRAY_SIZE(tcamsg_nla_decoders), NULL);
148 }
149 }