gen_stats.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * net/core/gen_stats.c
  4. *
  5. * Authors: Thomas Graf <tgraf@suug.ch>
  6. * Jamal Hadi Salim
  7. * Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  8. *
  9. * See Documentation/networking/gen_stats.rst
  10. */
  11. #include <linux/types.h>
  12. #include <linux/kernel.h>
  13. #include <linux/module.h>
  14. #include <linux/interrupt.h>
  15. #include <linux/socket.h>
  16. #include <linux/rtnetlink.h>
  17. #include <linux/gen_stats.h>
  18. #include <net/netlink.h>
  19. #include <net/gen_stats.h>
  20. #include <net/sch_generic.h>
  21. static inline int
  22. gnet_stats_copy(struct gnet_dump *d, int type, void *buf, int size, int padattr)
  23. {
  24. if (nla_put_64bit(d->skb, type, size, buf, padattr))
  25. goto nla_put_failure;
  26. return 0;
  27. nla_put_failure:
  28. if (d->lock)
  29. spin_unlock_bh(d->lock);
  30. kfree(d->xstats);
  31. d->xstats = NULL;
  32. d->xstats_len = 0;
  33. return -1;
  34. }
  35. /**
  36. * gnet_stats_start_copy_compat - start dumping procedure in compatibility mode
  37. * @skb: socket buffer to put statistics TLVs into
  38. * @type: TLV type for top level statistic TLV
  39. * @tc_stats_type: TLV type for backward compatibility struct tc_stats TLV
  40. * @xstats_type: TLV type for backward compatibility xstats TLV
  41. * @lock: statistics lock
  42. * @d: dumping handle
  43. * @padattr: padding attribute
  44. *
  45. * Initializes the dumping handle, grabs the statistic lock and appends
  46. * an empty TLV header to the socket buffer for use a container for all
  47. * other statistic TLVS.
  48. *
  49. * The dumping handle is marked to be in backward compatibility mode telling
  50. * all gnet_stats_copy_XXX() functions to fill a local copy of struct tc_stats.
  51. *
  52. * Returns 0 on success or -1 if the room in the socket buffer was not sufficient.
  53. */
  54. int
  55. gnet_stats_start_copy_compat(struct sk_buff *skb, int type, int tc_stats_type,
  56. int xstats_type, spinlock_t *lock,
  57. struct gnet_dump *d, int padattr)
  58. __acquires(lock)
  59. {
  60. memset(d, 0, sizeof(*d));
  61. if (type)
  62. d->tail = (struct nlattr *)skb_tail_pointer(skb);
  63. d->skb = skb;
  64. d->compat_tc_stats = tc_stats_type;
  65. d->compat_xstats = xstats_type;
  66. d->padattr = padattr;
  67. if (lock) {
  68. d->lock = lock;
  69. spin_lock_bh(lock);
  70. }
  71. if (d->tail) {
  72. int ret = gnet_stats_copy(d, type, NULL, 0, padattr);
  73. /* The initial attribute added in gnet_stats_copy() may be
  74. * preceded by a padding attribute, in which case d->tail will
  75. * end up pointing at the padding instead of the real attribute.
  76. * Fix this so gnet_stats_finish_copy() adjusts the length of
  77. * the right attribute.
  78. */
  79. if (ret == 0 && d->tail->nla_type == padattr)
  80. d->tail = (struct nlattr *)((char *)d->tail +
  81. NLA_ALIGN(d->tail->nla_len));
  82. return ret;
  83. }
  84. return 0;
  85. }
  86. EXPORT_SYMBOL(gnet_stats_start_copy_compat);
  87. /**
  88. * gnet_stats_start_copy - start dumping procedure in compatibility mode
  89. * @skb: socket buffer to put statistics TLVs into
  90. * @type: TLV type for top level statistic TLV
  91. * @lock: statistics lock
  92. * @d: dumping handle
  93. * @padattr: padding attribute
  94. *
  95. * Initializes the dumping handle, grabs the statistic lock and appends
  96. * an empty TLV header to the socket buffer for use a container for all
  97. * other statistic TLVS.
  98. *
  99. * Returns 0 on success or -1 if the room in the socket buffer was not sufficient.
  100. */
  101. int
  102. gnet_stats_start_copy(struct sk_buff *skb, int type, spinlock_t *lock,
  103. struct gnet_dump *d, int padattr)
  104. {
  105. return gnet_stats_start_copy_compat(skb, type, 0, 0, lock, d, padattr);
  106. }
  107. EXPORT_SYMBOL(gnet_stats_start_copy);
  108. /* Must not be inlined, due to u64_stats seqcount_t lockdep key */
  109. void gnet_stats_basic_sync_init(struct gnet_stats_basic_sync *b)
  110. {
  111. u64_stats_set(&b->bytes, 0);
  112. u64_stats_set(&b->packets, 0);
  113. u64_stats_init(&b->syncp);
  114. }
  115. EXPORT_SYMBOL(gnet_stats_basic_sync_init);
  116. static void gnet_stats_add_basic_cpu(struct gnet_stats_basic_sync *bstats,
  117. struct gnet_stats_basic_sync __percpu *cpu)
  118. {
  119. u64 t_bytes = 0, t_packets = 0;
  120. int i;
  121. for_each_possible_cpu(i) {
  122. struct gnet_stats_basic_sync *bcpu = per_cpu_ptr(cpu, i);
  123. unsigned int start;
  124. u64 bytes, packets;
  125. do {
  126. start = u64_stats_fetch_begin(&bcpu->syncp);
  127. bytes = u64_stats_read(&bcpu->bytes);
  128. packets = u64_stats_read(&bcpu->packets);
  129. } while (u64_stats_fetch_retry(&bcpu->syncp, start));
  130. t_bytes += bytes;
  131. t_packets += packets;
  132. }
  133. _bstats_update(bstats, t_bytes, t_packets);
  134. }
  135. void gnet_stats_add_basic(struct gnet_stats_basic_sync *bstats,
  136. struct gnet_stats_basic_sync __percpu *cpu,
  137. struct gnet_stats_basic_sync *b, bool running)
  138. {
  139. unsigned int start;
  140. u64 bytes = 0;
  141. u64 packets = 0;
  142. WARN_ON_ONCE((cpu || running) && in_hardirq());
  143. if (cpu) {
  144. gnet_stats_add_basic_cpu(bstats, cpu);
  145. return;
  146. }
  147. do {
  148. if (running)
  149. start = u64_stats_fetch_begin(&b->syncp);
  150. bytes = u64_stats_read(&b->bytes);
  151. packets = u64_stats_read(&b->packets);
  152. } while (running && u64_stats_fetch_retry(&b->syncp, start));
  153. _bstats_update(bstats, bytes, packets);
  154. }
  155. EXPORT_SYMBOL(gnet_stats_add_basic);
  156. static void gnet_stats_read_basic(u64 *ret_bytes, u64 *ret_packets,
  157. struct gnet_stats_basic_sync __percpu *cpu,
  158. struct gnet_stats_basic_sync *b, bool running)
  159. {
  160. unsigned int start;
  161. if (cpu) {
  162. u64 t_bytes = 0, t_packets = 0;
  163. int i;
  164. for_each_possible_cpu(i) {
  165. struct gnet_stats_basic_sync *bcpu = per_cpu_ptr(cpu, i);
  166. unsigned int start;
  167. u64 bytes, packets;
  168. do {
  169. start = u64_stats_fetch_begin(&bcpu->syncp);
  170. bytes = u64_stats_read(&bcpu->bytes);
  171. packets = u64_stats_read(&bcpu->packets);
  172. } while (u64_stats_fetch_retry(&bcpu->syncp, start));
  173. t_bytes += bytes;
  174. t_packets += packets;
  175. }
  176. *ret_bytes = t_bytes;
  177. *ret_packets = t_packets;
  178. return;
  179. }
  180. do {
  181. if (running)
  182. start = u64_stats_fetch_begin(&b->syncp);
  183. *ret_bytes = u64_stats_read(&b->bytes);
  184. *ret_packets = u64_stats_read(&b->packets);
  185. } while (running && u64_stats_fetch_retry(&b->syncp, start));
  186. }
  187. static int
  188. ___gnet_stats_copy_basic(struct gnet_dump *d,
  189. struct gnet_stats_basic_sync __percpu *cpu,
  190. struct gnet_stats_basic_sync *b,
  191. int type, bool running)
  192. {
  193. u64 bstats_bytes, bstats_packets;
  194. gnet_stats_read_basic(&bstats_bytes, &bstats_packets, cpu, b, running);
  195. if (d->compat_tc_stats && type == TCA_STATS_BASIC) {
  196. d->tc_stats.bytes = bstats_bytes;
  197. d->tc_stats.packets = bstats_packets;
  198. }
  199. if (d->tail) {
  200. struct gnet_stats_basic sb;
  201. int res;
  202. memset(&sb, 0, sizeof(sb));
  203. sb.bytes = bstats_bytes;
  204. sb.packets = bstats_packets;
  205. res = gnet_stats_copy(d, type, &sb, sizeof(sb), TCA_STATS_PAD);
  206. if (res < 0 || sb.packets == bstats_packets)
  207. return res;
  208. /* emit 64bit stats only if needed */
  209. return gnet_stats_copy(d, TCA_STATS_PKT64, &bstats_packets,
  210. sizeof(bstats_packets), TCA_STATS_PAD);
  211. }
  212. return 0;
  213. }
  214. /**
  215. * gnet_stats_copy_basic - copy basic statistics into statistic TLV
  216. * @d: dumping handle
  217. * @cpu: copy statistic per cpu
  218. * @b: basic statistics
  219. * @running: true if @b represents a running qdisc, thus @b's
  220. * internal values might change during basic reads.
  221. * Only used if @cpu is NULL
  222. *
  223. * Context: task; must not be run from IRQ or BH contexts
  224. *
  225. * Appends the basic statistics to the top level TLV created by
  226. * gnet_stats_start_copy().
  227. *
  228. * Returns 0 on success or -1 with the statistic lock released
  229. * if the room in the socket buffer was not sufficient.
  230. */
  231. int
  232. gnet_stats_copy_basic(struct gnet_dump *d,
  233. struct gnet_stats_basic_sync __percpu *cpu,
  234. struct gnet_stats_basic_sync *b,
  235. bool running)
  236. {
  237. return ___gnet_stats_copy_basic(d, cpu, b, TCA_STATS_BASIC, running);
  238. }
  239. EXPORT_SYMBOL(gnet_stats_copy_basic);
  240. /**
  241. * gnet_stats_copy_basic_hw - copy basic hw statistics into statistic TLV
  242. * @d: dumping handle
  243. * @cpu: copy statistic per cpu
  244. * @b: basic statistics
  245. * @running: true if @b represents a running qdisc, thus @b's
  246. * internal values might change during basic reads.
  247. * Only used if @cpu is NULL
  248. *
  249. * Context: task; must not be run from IRQ or BH contexts
  250. *
  251. * Appends the basic statistics to the top level TLV created by
  252. * gnet_stats_start_copy().
  253. *
  254. * Returns 0 on success or -1 with the statistic lock released
  255. * if the room in the socket buffer was not sufficient.
  256. */
  257. int
  258. gnet_stats_copy_basic_hw(struct gnet_dump *d,
  259. struct gnet_stats_basic_sync __percpu *cpu,
  260. struct gnet_stats_basic_sync *b,
  261. bool running)
  262. {
  263. return ___gnet_stats_copy_basic(d, cpu, b, TCA_STATS_BASIC_HW, running);
  264. }
  265. EXPORT_SYMBOL(gnet_stats_copy_basic_hw);
  266. /**
  267. * gnet_stats_copy_rate_est - copy rate estimator statistics into statistics TLV
  268. * @d: dumping handle
  269. * @rate_est: rate estimator
  270. *
  271. * Appends the rate estimator statistics to the top level TLV created by
  272. * gnet_stats_start_copy().
  273. *
  274. * Returns 0 on success or -1 with the statistic lock released
  275. * if the room in the socket buffer was not sufficient.
  276. */
  277. int
  278. gnet_stats_copy_rate_est(struct gnet_dump *d,
  279. struct net_rate_estimator __rcu **rate_est)
  280. {
  281. struct gnet_stats_rate_est64 sample;
  282. struct gnet_stats_rate_est est;
  283. int res;
  284. if (!gen_estimator_read(rate_est, &sample))
  285. return 0;
  286. est.bps = min_t(u64, UINT_MAX, sample.bps);
  287. /* we have some time before reaching 2^32 packets per second */
  288. est.pps = sample.pps;
  289. if (d->compat_tc_stats) {
  290. d->tc_stats.bps = est.bps;
  291. d->tc_stats.pps = est.pps;
  292. }
  293. if (d->tail) {
  294. res = gnet_stats_copy(d, TCA_STATS_RATE_EST, &est, sizeof(est),
  295. TCA_STATS_PAD);
  296. if (res < 0 || est.bps == sample.bps)
  297. return res;
  298. /* emit 64bit stats only if needed */
  299. return gnet_stats_copy(d, TCA_STATS_RATE_EST64, &sample,
  300. sizeof(sample), TCA_STATS_PAD);
  301. }
  302. return 0;
  303. }
  304. EXPORT_SYMBOL(gnet_stats_copy_rate_est);
  305. static void gnet_stats_add_queue_cpu(struct gnet_stats_queue *qstats,
  306. const struct gnet_stats_queue __percpu *q)
  307. {
  308. int i;
  309. for_each_possible_cpu(i) {
  310. const struct gnet_stats_queue *qcpu = per_cpu_ptr(q, i);
  311. qstats->qlen += qcpu->qlen;
  312. qstats->backlog += qcpu->backlog;
  313. qstats->drops += qcpu->drops;
  314. qstats->requeues += qcpu->requeues;
  315. qstats->overlimits += qcpu->overlimits;
  316. }
  317. }
  318. void gnet_stats_add_queue(struct gnet_stats_queue *qstats,
  319. const struct gnet_stats_queue __percpu *cpu,
  320. const struct gnet_stats_queue *q)
  321. {
  322. if (cpu) {
  323. gnet_stats_add_queue_cpu(qstats, cpu);
  324. } else {
  325. qstats->qlen += q->qlen;
  326. qstats->backlog += q->backlog;
  327. qstats->drops += q->drops;
  328. qstats->requeues += q->requeues;
  329. qstats->overlimits += q->overlimits;
  330. }
  331. }
  332. EXPORT_SYMBOL(gnet_stats_add_queue);
  333. /**
  334. * gnet_stats_copy_queue - copy queue statistics into statistics TLV
  335. * @d: dumping handle
  336. * @cpu_q: per cpu queue statistics
  337. * @q: queue statistics
  338. * @qlen: queue length statistics
  339. *
  340. * Appends the queue statistics to the top level TLV created by
  341. * gnet_stats_start_copy(). Using per cpu queue statistics if
  342. * they are available.
  343. *
  344. * Returns 0 on success or -1 with the statistic lock released
  345. * if the room in the socket buffer was not sufficient.
  346. */
  347. int
  348. gnet_stats_copy_queue(struct gnet_dump *d,
  349. struct gnet_stats_queue __percpu *cpu_q,
  350. struct gnet_stats_queue *q, __u32 qlen)
  351. {
  352. struct gnet_stats_queue qstats = {0};
  353. gnet_stats_add_queue(&qstats, cpu_q, q);
  354. qstats.qlen = qlen;
  355. if (d->compat_tc_stats) {
  356. d->tc_stats.drops = qstats.drops;
  357. d->tc_stats.qlen = qstats.qlen;
  358. d->tc_stats.backlog = qstats.backlog;
  359. d->tc_stats.overlimits = qstats.overlimits;
  360. }
  361. if (d->tail)
  362. return gnet_stats_copy(d, TCA_STATS_QUEUE,
  363. &qstats, sizeof(qstats),
  364. TCA_STATS_PAD);
  365. return 0;
  366. }
  367. EXPORT_SYMBOL(gnet_stats_copy_queue);
  368. /**
  369. * gnet_stats_copy_app - copy application specific statistics into statistics TLV
  370. * @d: dumping handle
  371. * @st: application specific statistics data
  372. * @len: length of data
  373. *
  374. * Appends the application specific statistics to the top level TLV created by
  375. * gnet_stats_start_copy() and remembers the data for XSTATS if the dumping
  376. * handle is in backward compatibility mode.
  377. *
  378. * Returns 0 on success or -1 with the statistic lock released
  379. * if the room in the socket buffer was not sufficient.
  380. */
  381. int
  382. gnet_stats_copy_app(struct gnet_dump *d, void *st, int len)
  383. {
  384. if (d->compat_xstats) {
  385. d->xstats = kmemdup(st, len, GFP_ATOMIC);
  386. if (!d->xstats)
  387. goto err_out;
  388. d->xstats_len = len;
  389. }
  390. if (d->tail)
  391. return gnet_stats_copy(d, TCA_STATS_APP, st, len,
  392. TCA_STATS_PAD);
  393. return 0;
  394. err_out:
  395. if (d->lock)
  396. spin_unlock_bh(d->lock);
  397. d->xstats_len = 0;
  398. return -1;
  399. }
  400. EXPORT_SYMBOL(gnet_stats_copy_app);
  401. /**
  402. * gnet_stats_finish_copy - finish dumping procedure
  403. * @d: dumping handle
  404. *
  405. * Corrects the length of the top level TLV to include all TLVs added
  406. * by gnet_stats_copy_XXX() calls. Adds the backward compatibility TLVs
  407. * if gnet_stats_start_copy_compat() was used and releases the statistics
  408. * lock.
  409. *
  410. * Returns 0 on success or -1 with the statistic lock released
  411. * if the room in the socket buffer was not sufficient.
  412. */
  413. int
  414. gnet_stats_finish_copy(struct gnet_dump *d)
  415. {
  416. if (d->tail)
  417. d->tail->nla_len = skb_tail_pointer(d->skb) - (u8 *)d->tail;
  418. if (d->compat_tc_stats)
  419. if (gnet_stats_copy(d, d->compat_tc_stats, &d->tc_stats,
  420. sizeof(d->tc_stats), d->padattr) < 0)
  421. return -1;
  422. if (d->compat_xstats && d->xstats) {
  423. if (gnet_stats_copy(d, d->compat_xstats, d->xstats,
  424. d->xstats_len, d->padattr) < 0)
  425. return -1;
  426. }
  427. if (d->lock)
  428. spin_unlock_bh(d->lock);
  429. kfree(d->xstats);
  430. d->xstats = NULL;
  431. d->xstats_len = 0;
  432. return 0;
  433. }
  434. EXPORT_SYMBOL(gnet_stats_finish_copy);