Mirror of strace – the linux syscall tracer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

rtnl_tc.c 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /*
  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.
  5. * All rights reserved.
  6. *
  7. * SPDX-License-Identifier: LGPL-2.1-or-later
  8. */
  9. #include "defs.h"
  10. #include "netlink_route.h"
  11. #include "nlattr.h"
  12. #include "print_fields.h"
  13. #include "netlink.h"
  14. #ifdef HAVE_STRUCT_GNET_STATS_BASIC
  15. # include <linux/gen_stats.h>
  16. #endif
  17. #include <linux/pkt_sched.h>
  18. #include <linux/rtnetlink.h>
  19. #include "xlat/rtnl_tc_attrs.h"
  20. #include "xlat/rtnl_tca_stab_attrs.h"
  21. #include "xlat/rtnl_tca_stats_attrs.h"
  22. static bool
  23. decode_tc_stats(struct tcb *const tcp,
  24. const kernel_ulong_t addr,
  25. const unsigned int len,
  26. const void *const opaque_data)
  27. {
  28. struct tc_stats st;
  29. const unsigned int sizeof_tc_stats =
  30. offsetofend(struct tc_stats, backlog);
  31. if (len < sizeof_tc_stats)
  32. return false;
  33. else if (!umoven_or_printaddr(tcp, addr, sizeof_tc_stats, &st)) {
  34. PRINT_FIELD_U("{", st, bytes);
  35. PRINT_FIELD_U(", ", st, packets);
  36. PRINT_FIELD_U(", ", st, drops);
  37. PRINT_FIELD_U(", ", st, overlimits);
  38. PRINT_FIELD_U(", ", st, bps);
  39. PRINT_FIELD_U(", ", st, pps);
  40. PRINT_FIELD_U(", ", st, qlen);
  41. PRINT_FIELD_U(", ", st, backlog);
  42. tprints("}");
  43. }
  44. return true;
  45. }
  46. static bool
  47. decode_tc_estimator(struct tcb *const tcp,
  48. const kernel_ulong_t addr,
  49. const unsigned int len,
  50. const void *const opaque_data)
  51. {
  52. struct tc_estimator est;
  53. if (len < sizeof(est))
  54. return false;
  55. else if (!umove_or_printaddr(tcp, addr, &est)) {
  56. PRINT_FIELD_D("{", est, interval);
  57. PRINT_FIELD_U(", ", est, ewma_log);
  58. tprints("}");
  59. }
  60. return true;
  61. }
  62. static bool
  63. decode_gnet_stats_basic(struct tcb *const tcp,
  64. const kernel_ulong_t addr,
  65. const unsigned int len,
  66. const void *const opaque_data)
  67. {
  68. #ifdef HAVE_STRUCT_GNET_STATS_BASIC
  69. struct gnet_stats_basic sb;
  70. const unsigned int sizeof_st_basic =
  71. offsetofend(struct gnet_stats_basic, packets);
  72. if (len < sizeof_st_basic)
  73. return false;
  74. else if (!umoven_or_printaddr(tcp, addr, sizeof_st_basic, &sb)) {
  75. PRINT_FIELD_U("{", sb, bytes);
  76. PRINT_FIELD_U(", ", sb, packets);
  77. tprints("}");
  78. }
  79. return true;
  80. #else
  81. return false;
  82. #endif
  83. }
  84. static bool
  85. decode_gnet_stats_rate_est(struct tcb *const tcp,
  86. const kernel_ulong_t addr,
  87. const unsigned int len,
  88. const void *const opaque_data)
  89. {
  90. #ifdef HAVE_STRUCT_GNET_STATS_RATE_EST
  91. struct gnet_stats_rate_est est;
  92. if (len < sizeof(est))
  93. return false;
  94. else if (!umove_or_printaddr(tcp, addr, &est)) {
  95. PRINT_FIELD_U("{", est, bps);
  96. PRINT_FIELD_U(", ", est, pps);
  97. tprints("}");
  98. }
  99. return true;
  100. #else
  101. return false;
  102. #endif
  103. }
  104. static bool
  105. decode_gnet_stats_queue(struct tcb *const tcp,
  106. const kernel_ulong_t addr,
  107. const unsigned int len,
  108. const void *const opaque_data)
  109. {
  110. #ifdef HAVE_STRUCT_GNET_STATS_QUEUE
  111. struct gnet_stats_queue qstats;
  112. if (len < sizeof(qstats))
  113. return false;
  114. else if (!umove_or_printaddr(tcp, addr, &qstats)) {
  115. PRINT_FIELD_U("{", qstats, qlen);
  116. PRINT_FIELD_U(", ", qstats, backlog);
  117. PRINT_FIELD_U(", ", qstats, drops);
  118. PRINT_FIELD_U(", ", qstats, requeues);
  119. PRINT_FIELD_U(", ", qstats, overlimits);
  120. tprints("}");
  121. }
  122. return true;
  123. #else
  124. return false;
  125. #endif
  126. }
  127. static bool
  128. decode_gnet_stats_rate_est64(struct tcb *const tcp,
  129. const kernel_ulong_t addr,
  130. const unsigned int len,
  131. const void *const opaque_data)
  132. {
  133. #ifdef HAVE_STRUCT_GNET_STATS_RATE_EST64
  134. struct gnet_stats_rate_est64 est;
  135. if (len < sizeof(est))
  136. return false;
  137. else if (!umove_or_printaddr(tcp, addr, &est)) {
  138. PRINT_FIELD_U("{", est, bps);
  139. PRINT_FIELD_U(", ", est, pps);
  140. tprints("}");
  141. }
  142. return true;
  143. #else
  144. return false;
  145. #endif
  146. }
  147. static const nla_decoder_t tca_stats_nla_decoders[] = {
  148. [TCA_STATS_BASIC] = decode_gnet_stats_basic,
  149. [TCA_STATS_RATE_EST] = decode_gnet_stats_rate_est,
  150. [TCA_STATS_QUEUE] = decode_gnet_stats_queue,
  151. [TCA_STATS_APP] = NULL, /* unimplemented */
  152. [TCA_STATS_RATE_EST64] = decode_gnet_stats_rate_est64,
  153. [TCA_STATS_PAD] = NULL,
  154. [TCA_STATS_BASIC_HW] = decode_gnet_stats_basic,
  155. };
  156. bool
  157. decode_nla_tc_stats(struct tcb *const tcp,
  158. const kernel_ulong_t addr,
  159. const unsigned int len,
  160. const void *const opaque_data)
  161. {
  162. decode_nlattr(tcp, addr, len, rtnl_tca_stats_attrs, "TCA_STATS_???",
  163. tca_stats_nla_decoders,
  164. ARRAY_SIZE(tca_stats_nla_decoders), opaque_data);
  165. return true;
  166. }
  167. static bool
  168. decode_tc_sizespec(struct tcb *const tcp,
  169. const kernel_ulong_t addr,
  170. const unsigned int len,
  171. const void *const opaque_data)
  172. {
  173. #ifdef HAVE_STRUCT_TC_SIZESPEC
  174. struct tc_sizespec s;
  175. if (len < sizeof(s))
  176. return false;
  177. else if (!umove_or_printaddr(tcp, addr, &s)) {
  178. PRINT_FIELD_U("{", s, cell_log);
  179. PRINT_FIELD_U(", ", s, size_log);
  180. PRINT_FIELD_D(", ", s, cell_align);
  181. PRINT_FIELD_D(", ", s, overhead);
  182. PRINT_FIELD_U(", ", s, linklayer);
  183. PRINT_FIELD_U(", ", s, mpu);
  184. PRINT_FIELD_U(", ", s, mtu);
  185. PRINT_FIELD_U(", ", s, tsize);
  186. tprints("}");
  187. }
  188. return true;
  189. #else
  190. return false;
  191. #endif
  192. }
  193. static bool
  194. print_stab_data(struct tcb *const tcp, void *const elem_buf,
  195. const size_t elem_size, void *const opaque_data)
  196. {
  197. tprintf("%" PRIu16, *(uint16_t *) elem_buf);
  198. return true;
  199. }
  200. static bool
  201. decode_tca_stab_data(struct tcb *const tcp,
  202. const kernel_ulong_t addr,
  203. const unsigned int len,
  204. const void *const opaque_data)
  205. {
  206. uint16_t data;
  207. const size_t nmemb = len / sizeof(data);
  208. if (!nmemb)
  209. return false;
  210. print_array(tcp, addr, nmemb, &data, sizeof(data),
  211. tfetch_mem, print_stab_data, NULL);
  212. return true;
  213. }
  214. static const nla_decoder_t tca_stab_nla_decoders[] = {
  215. [TCA_STAB_BASE] = decode_tc_sizespec,
  216. [TCA_STAB_DATA] = decode_tca_stab_data
  217. };
  218. static bool
  219. decode_tca_stab(struct tcb *const tcp,
  220. const kernel_ulong_t addr,
  221. const unsigned int len,
  222. const void *const opaque_data)
  223. {
  224. decode_nlattr(tcp, addr, len, rtnl_tca_stab_attrs, "TCA_STAB_???",
  225. tca_stab_nla_decoders,
  226. ARRAY_SIZE(tca_stab_nla_decoders), opaque_data);
  227. return true;
  228. }
  229. static const nla_decoder_t tcmsg_nla_decoders[] = {
  230. [TCA_KIND] = decode_nla_str,
  231. [TCA_OPTIONS] = NULL, /* unimplemented */
  232. [TCA_STATS] = decode_tc_stats,
  233. [TCA_XSTATS] = NULL, /* unimplemented */
  234. [TCA_RATE] = decode_tc_estimator,
  235. [TCA_FCNT] = decode_nla_u32,
  236. [TCA_STATS2] = decode_nla_tc_stats,
  237. [TCA_STAB] = decode_tca_stab,
  238. [TCA_PAD] = NULL,
  239. [TCA_DUMP_INVISIBLE] = NULL,
  240. [TCA_CHAIN] = decode_nla_u32,
  241. [TCA_HW_OFFLOAD] = decode_nla_u8,
  242. [TCA_INGRESS_BLOCK] = decode_nla_u32,
  243. [TCA_EGRESS_BLOCK] = decode_nla_u32,
  244. };
  245. DECL_NETLINK_ROUTE_DECODER(decode_tcmsg)
  246. {
  247. struct tcmsg tcmsg = { .tcm_family = family };
  248. size_t offset = sizeof(tcmsg.tcm_family);
  249. bool decode_nla = false;
  250. PRINT_FIELD_XVAL("{", tcmsg, tcm_family, addrfams, "AF_???");
  251. tprints(", ");
  252. if (len >= sizeof(tcmsg)) {
  253. if (!umoven_or_printaddr(tcp, addr + offset,
  254. sizeof(tcmsg) - offset,
  255. (char *) &tcmsg + offset)) {
  256. PRINT_FIELD_IFINDEX("", tcmsg, tcm_ifindex);
  257. PRINT_FIELD_U(", ", tcmsg, tcm_handle);
  258. PRINT_FIELD_U(", ", tcmsg, tcm_parent);
  259. PRINT_FIELD_U(", ", tcmsg, tcm_info);
  260. decode_nla = true;
  261. }
  262. } else
  263. tprints("...");
  264. tprints("}");
  265. offset = NLMSG_ALIGN(sizeof(tcmsg));
  266. if (decode_nla && len > offset) {
  267. tprints(", ");
  268. decode_nlattr(tcp, addr + offset, len - offset,
  269. rtnl_tc_attrs, "TCA_???", tcmsg_nla_decoders,
  270. ARRAY_SIZE(tcmsg_nla_decoders), NULL);
  271. }
  272. }