gen_stats.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. /*
  2. * net/core/gen_stats.c
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation; either version
  7. * 2 of the License, or (at your option) any later version.
  8. *
  9. * Authors: Thomas Graf <tgraf@suug.ch>
  10. * Jamal Hadi Salim
  11. * Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  12. *
  13. * See Documentation/networking/gen_stats.txt
  14. */
  15. #include <linux/types.h>
  16. #include <linux/kernel.h>
  17. #include <linux/module.h>
  18. #include <linux/interrupt.h>
  19. #include <linux/socket.h>
  20. #include <linux/rtnetlink.h>
  21. #include <linux/gen_stats.h>
  22. #include <net/netlink.h>
  23. #include <net/gen_stats.h>
  24. static inline int
  25. gnet_stats_copy(struct gnet_dump *d, int type, void *buf, int size, int padattr)
  26. {
  27. if (nla_put_64bit(d->skb, type, size, buf, padattr))
  28. goto nla_put_failure;
  29. return 0;
  30. nla_put_failure:
  31. if (d->lock)
  32. spin_unlock_bh(d->lock);
  33. kfree(d->xstats);
  34. d->xstats = NULL;
  35. d->xstats_len = 0;
  36. return -1;
  37. }
  38. /**
  39. * gnet_stats_start_copy_compat - start dumping procedure in compatibility mode
  40. * @skb: socket buffer to put statistics TLVs into
  41. * @type: TLV type for top level statistic TLV
  42. * @tc_stats_type: TLV type for backward compatibility struct tc_stats TLV
  43. * @xstats_type: TLV type for backward compatibility xstats TLV
  44. * @lock: statistics lock
  45. * @d: dumping handle
  46. * @padattr: padding attribute
  47. *
  48. * Initializes the dumping handle, grabs the statistic lock and appends
  49. * an empty TLV header to the socket buffer for use a container for all
  50. * other statistic TLVS.
  51. *
  52. * The dumping handle is marked to be in backward compatibility mode telling
  53. * all gnet_stats_copy_XXX() functions to fill a local copy of struct tc_stats.
  54. *
  55. * Returns 0 on success or -1 if the room in the socket buffer was not sufficient.
  56. */
  57. int
  58. gnet_stats_start_copy_compat(struct sk_buff *skb, int type, int tc_stats_type,
  59. int xstats_type, spinlock_t *lock,
  60. struct gnet_dump *d, int padattr)
  61. __acquires(lock)
  62. {
  63. memset(d, 0, sizeof(*d));
  64. if (type)
  65. d->tail = (struct nlattr *)skb_tail_pointer(skb);
  66. d->skb = skb;
  67. d->compat_tc_stats = tc_stats_type;
  68. d->compat_xstats = xstats_type;
  69. d->padattr = padattr;
  70. if (lock) {
  71. d->lock = lock;
  72. spin_lock_bh(lock);
  73. }
  74. if (d->tail)
  75. return gnet_stats_copy(d, type, NULL, 0, padattr);
  76. return 0;
  77. }
  78. EXPORT_SYMBOL(gnet_stats_start_copy_compat);
  79. /**
  80. * gnet_stats_start_copy - start dumping procedure in compatibility mode
  81. * @skb: socket buffer to put statistics TLVs into
  82. * @type: TLV type for top level statistic TLV
  83. * @lock: statistics lock
  84. * @d: dumping handle
  85. * @padattr: padding attribute
  86. *
  87. * Initializes the dumping handle, grabs the statistic lock and appends
  88. * an empty TLV header to the socket buffer for use a container for all
  89. * other statistic TLVS.
  90. *
  91. * Returns 0 on success or -1 if the room in the socket buffer was not sufficient.
  92. */
  93. int
  94. gnet_stats_start_copy(struct sk_buff *skb, int type, spinlock_t *lock,
  95. struct gnet_dump *d, int padattr)
  96. {
  97. return gnet_stats_start_copy_compat(skb, type, 0, 0, lock, d, padattr);
  98. }
  99. EXPORT_SYMBOL(gnet_stats_start_copy);
  100. static void
  101. __gnet_stats_copy_basic_cpu(struct gnet_stats_basic_packed *bstats,
  102. struct gnet_stats_basic_cpu __percpu *cpu)
  103. {
  104. int i;
  105. for_each_possible_cpu(i) {
  106. struct gnet_stats_basic_cpu *bcpu = per_cpu_ptr(cpu, i);
  107. unsigned int start;
  108. u64 bytes;
  109. u32 packets;
  110. do {
  111. start = u64_stats_fetch_begin_irq(&bcpu->syncp);
  112. bytes = bcpu->bstats.bytes;
  113. packets = bcpu->bstats.packets;
  114. } while (u64_stats_fetch_retry_irq(&bcpu->syncp, start));
  115. bstats->bytes += bytes;
  116. bstats->packets += packets;
  117. }
  118. }
  119. void
  120. __gnet_stats_copy_basic(const seqcount_t *running,
  121. struct gnet_stats_basic_packed *bstats,
  122. struct gnet_stats_basic_cpu __percpu *cpu,
  123. struct gnet_stats_basic_packed *b)
  124. {
  125. unsigned int seq;
  126. if (cpu) {
  127. __gnet_stats_copy_basic_cpu(bstats, cpu);
  128. return;
  129. }
  130. do {
  131. if (running)
  132. seq = read_seqcount_begin(running);
  133. bstats->bytes = b->bytes;
  134. bstats->packets = b->packets;
  135. } while (running && read_seqcount_retry(running, seq));
  136. }
  137. EXPORT_SYMBOL(__gnet_stats_copy_basic);
  138. /**
  139. * gnet_stats_copy_basic - copy basic statistics into statistic TLV
  140. * @running: seqcount_t pointer
  141. * @d: dumping handle
  142. * @cpu: copy statistic per cpu
  143. * @b: basic statistics
  144. *
  145. * Appends the basic statistics to the top level TLV created by
  146. * gnet_stats_start_copy().
  147. *
  148. * Returns 0 on success or -1 with the statistic lock released
  149. * if the room in the socket buffer was not sufficient.
  150. */
  151. int
  152. gnet_stats_copy_basic(const seqcount_t *running,
  153. struct gnet_dump *d,
  154. struct gnet_stats_basic_cpu __percpu *cpu,
  155. struct gnet_stats_basic_packed *b)
  156. {
  157. struct gnet_stats_basic_packed bstats = {0};
  158. __gnet_stats_copy_basic(running, &bstats, cpu, b);
  159. if (d->compat_tc_stats) {
  160. d->tc_stats.bytes = bstats.bytes;
  161. d->tc_stats.packets = bstats.packets;
  162. }
  163. if (d->tail) {
  164. struct gnet_stats_basic sb;
  165. memset(&sb, 0, sizeof(sb));
  166. sb.bytes = bstats.bytes;
  167. sb.packets = bstats.packets;
  168. return gnet_stats_copy(d, TCA_STATS_BASIC, &sb, sizeof(sb),
  169. TCA_STATS_PAD);
  170. }
  171. return 0;
  172. }
  173. EXPORT_SYMBOL(gnet_stats_copy_basic);
  174. /**
  175. * gnet_stats_copy_rate_est - copy rate estimator statistics into statistics TLV
  176. * @d: dumping handle
  177. * @rate_est: rate estimator
  178. *
  179. * Appends the rate estimator statistics to the top level TLV created by
  180. * gnet_stats_start_copy().
  181. *
  182. * Returns 0 on success or -1 with the statistic lock released
  183. * if the room in the socket buffer was not sufficient.
  184. */
  185. int
  186. gnet_stats_copy_rate_est(struct gnet_dump *d,
  187. struct net_rate_estimator __rcu **rate_est)
  188. {
  189. struct gnet_stats_rate_est64 sample;
  190. struct gnet_stats_rate_est est;
  191. int res;
  192. if (!gen_estimator_read(rate_est, &sample))
  193. return 0;
  194. est.bps = min_t(u64, UINT_MAX, sample.bps);
  195. /* we have some time before reaching 2^32 packets per second */
  196. est.pps = sample.pps;
  197. if (d->compat_tc_stats) {
  198. d->tc_stats.bps = est.bps;
  199. d->tc_stats.pps = est.pps;
  200. }
  201. if (d->tail) {
  202. res = gnet_stats_copy(d, TCA_STATS_RATE_EST, &est, sizeof(est),
  203. TCA_STATS_PAD);
  204. if (res < 0 || est.bps == sample.bps)
  205. return res;
  206. /* emit 64bit stats only if needed */
  207. return gnet_stats_copy(d, TCA_STATS_RATE_EST64, &sample,
  208. sizeof(sample), TCA_STATS_PAD);
  209. }
  210. return 0;
  211. }
  212. EXPORT_SYMBOL(gnet_stats_copy_rate_est);
  213. static void
  214. __gnet_stats_copy_queue_cpu(struct gnet_stats_queue *qstats,
  215. const struct gnet_stats_queue __percpu *q)
  216. {
  217. int i;
  218. for_each_possible_cpu(i) {
  219. const struct gnet_stats_queue *qcpu = per_cpu_ptr(q, i);
  220. qstats->qlen = 0;
  221. qstats->backlog += qcpu->backlog;
  222. qstats->drops += qcpu->drops;
  223. qstats->requeues += qcpu->requeues;
  224. qstats->overlimits += qcpu->overlimits;
  225. }
  226. }
  227. void __gnet_stats_copy_queue(struct gnet_stats_queue *qstats,
  228. const struct gnet_stats_queue __percpu *cpu,
  229. const struct gnet_stats_queue *q,
  230. __u32 qlen)
  231. {
  232. if (cpu) {
  233. __gnet_stats_copy_queue_cpu(qstats, cpu);
  234. } else {
  235. qstats->qlen = q->qlen;
  236. qstats->backlog = q->backlog;
  237. qstats->drops = q->drops;
  238. qstats->requeues = q->requeues;
  239. qstats->overlimits = q->overlimits;
  240. }
  241. qstats->qlen = qlen;
  242. }
  243. EXPORT_SYMBOL(__gnet_stats_copy_queue);
  244. /**
  245. * gnet_stats_copy_queue - copy queue statistics into statistics TLV
  246. * @d: dumping handle
  247. * @cpu_q: per cpu queue statistics
  248. * @q: queue statistics
  249. * @qlen: queue length statistics
  250. *
  251. * Appends the queue statistics to the top level TLV created by
  252. * gnet_stats_start_copy(). Using per cpu queue statistics if
  253. * they are available.
  254. *
  255. * Returns 0 on success or -1 with the statistic lock released
  256. * if the room in the socket buffer was not sufficient.
  257. */
  258. int
  259. gnet_stats_copy_queue(struct gnet_dump *d,
  260. struct gnet_stats_queue __percpu *cpu_q,
  261. struct gnet_stats_queue *q, __u32 qlen)
  262. {
  263. struct gnet_stats_queue qstats = {0};
  264. __gnet_stats_copy_queue(&qstats, cpu_q, q, qlen);
  265. if (d->compat_tc_stats) {
  266. d->tc_stats.drops = qstats.drops;
  267. d->tc_stats.qlen = qstats.qlen;
  268. d->tc_stats.backlog = qstats.backlog;
  269. d->tc_stats.overlimits = qstats.overlimits;
  270. }
  271. if (d->tail)
  272. return gnet_stats_copy(d, TCA_STATS_QUEUE,
  273. &qstats, sizeof(qstats),
  274. TCA_STATS_PAD);
  275. return 0;
  276. }
  277. EXPORT_SYMBOL(gnet_stats_copy_queue);
  278. /**
  279. * gnet_stats_copy_app - copy application specific statistics into statistics TLV
  280. * @d: dumping handle
  281. * @st: application specific statistics data
  282. * @len: length of data
  283. *
  284. * Appends the application specific statistics to the top level TLV created by
  285. * gnet_stats_start_copy() and remembers the data for XSTATS if the dumping
  286. * handle is in backward compatibility mode.
  287. *
  288. * Returns 0 on success or -1 with the statistic lock released
  289. * if the room in the socket buffer was not sufficient.
  290. */
  291. int
  292. gnet_stats_copy_app(struct gnet_dump *d, void *st, int len)
  293. {
  294. if (d->compat_xstats) {
  295. d->xstats = kmemdup(st, len, GFP_ATOMIC);
  296. if (!d->xstats)
  297. goto err_out;
  298. d->xstats_len = len;
  299. }
  300. if (d->tail)
  301. return gnet_stats_copy(d, TCA_STATS_APP, st, len,
  302. TCA_STATS_PAD);
  303. return 0;
  304. err_out:
  305. if (d->lock)
  306. spin_unlock_bh(d->lock);
  307. d->xstats_len = 0;
  308. return -1;
  309. }
  310. EXPORT_SYMBOL(gnet_stats_copy_app);
  311. /**
  312. * gnet_stats_finish_copy - finish dumping procedure
  313. * @d: dumping handle
  314. *
  315. * Corrects the length of the top level TLV to include all TLVs added
  316. * by gnet_stats_copy_XXX() calls. Adds the backward compatibility TLVs
  317. * if gnet_stats_start_copy_compat() was used and releases the statistics
  318. * lock.
  319. *
  320. * Returns 0 on success or -1 with the statistic lock released
  321. * if the room in the socket buffer was not sufficient.
  322. */
  323. int
  324. gnet_stats_finish_copy(struct gnet_dump *d)
  325. {
  326. if (d->tail)
  327. d->tail->nla_len = skb_tail_pointer(d->skb) - (u8 *)d->tail;
  328. if (d->compat_tc_stats)
  329. if (gnet_stats_copy(d, d->compat_tc_stats, &d->tc_stats,
  330. sizeof(d->tc_stats), d->padattr) < 0)
  331. return -1;
  332. if (d->compat_xstats && d->xstats) {
  333. if (gnet_stats_copy(d, d->compat_xstats, d->xstats,
  334. d->xstats_len, d->padattr) < 0)
  335. return -1;
  336. }
  337. if (d->lock)
  338. spin_unlock_bh(d->lock);
  339. kfree(d->xstats);
  340. d->xstats = NULL;
  341. d->xstats_len = 0;
  342. return 0;
  343. }
  344. EXPORT_SYMBOL(gnet_stats_finish_copy);