page-pool.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. // SPDX-License-Identifier: GPL-2.0
  2. #define _GNU_SOURCE
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <ynl.h>
  6. #include <net/if.h>
  7. #include "netdev-user.h"
  8. struct stat {
  9. unsigned int ifc;
  10. struct {
  11. unsigned int cnt;
  12. size_t refs, bytes;
  13. } live[2];
  14. size_t alloc_slow, alloc_fast, recycle_ring, recycle_cache;
  15. };
  16. struct stats_array {
  17. unsigned int i, max;
  18. struct stat *s;
  19. };
  20. static struct stat *find_ifc(struct stats_array *a, unsigned int ifindex)
  21. {
  22. unsigned int i;
  23. for (i = 0; i < a->i; i++) {
  24. if (a->s[i].ifc == ifindex)
  25. return &a->s[i];
  26. }
  27. a->i++;
  28. if (a->i == a->max) {
  29. a->max *= 2;
  30. a->s = reallocarray(a->s, a->max, sizeof(*a->s));
  31. }
  32. a->s[i].ifc = ifindex;
  33. return &a->s[i];
  34. }
  35. static void count(struct stat *s, unsigned int l,
  36. struct netdev_page_pool_get_rsp *pp)
  37. {
  38. s->live[l].cnt++;
  39. if (pp->_present.inflight)
  40. s->live[l].refs += pp->inflight;
  41. if (pp->_present.inflight_mem)
  42. s->live[l].bytes += pp->inflight_mem;
  43. }
  44. int main(int argc, char **argv)
  45. {
  46. struct netdev_page_pool_stats_get_list *pp_stats;
  47. struct netdev_page_pool_get_list *pools;
  48. struct stats_array a = {};
  49. struct ynl_error yerr;
  50. struct ynl_sock *ys;
  51. ys = ynl_sock_create(&ynl_netdev_family, &yerr);
  52. if (!ys) {
  53. fprintf(stderr, "YNL: %s\n", yerr.msg);
  54. return 1;
  55. }
  56. a.max = 128;
  57. a.s = calloc(a.max, sizeof(*a.s));
  58. if (!a.s)
  59. goto err_close;
  60. pools = netdev_page_pool_get_dump(ys);
  61. if (!pools)
  62. goto err_free;
  63. ynl_dump_foreach(pools, pp) {
  64. struct stat *s = find_ifc(&a, pp->ifindex);
  65. count(s, 1, pp);
  66. if (pp->_present.detach_time)
  67. count(s, 0, pp);
  68. }
  69. netdev_page_pool_get_list_free(pools);
  70. pp_stats = netdev_page_pool_stats_get_dump(ys);
  71. if (!pp_stats)
  72. goto err_free;
  73. ynl_dump_foreach(pp_stats, pp) {
  74. struct stat *s = find_ifc(&a, pp->info.ifindex);
  75. if (pp->_present.alloc_fast)
  76. s->alloc_fast += pp->alloc_fast;
  77. if (pp->_present.alloc_refill)
  78. s->alloc_fast += pp->alloc_refill;
  79. if (pp->_present.alloc_slow)
  80. s->alloc_slow += pp->alloc_slow;
  81. if (pp->_present.recycle_ring)
  82. s->recycle_ring += pp->recycle_ring;
  83. if (pp->_present.recycle_cached)
  84. s->recycle_cache += pp->recycle_cached;
  85. }
  86. netdev_page_pool_stats_get_list_free(pp_stats);
  87. for (unsigned int i = 0; i < a.i; i++) {
  88. char ifname[IF_NAMESIZE];
  89. struct stat *s = &a.s[i];
  90. const char *name;
  91. double recycle;
  92. if (!s->ifc) {
  93. name = "<orphan>\t";
  94. } else {
  95. name = if_indextoname(s->ifc, ifname);
  96. if (name)
  97. printf("%8s", name);
  98. printf("[%d]\t", s->ifc);
  99. }
  100. printf("page pools: %u (zombies: %u)\n",
  101. s->live[1].cnt, s->live[0].cnt);
  102. printf("\t\trefs: %zu bytes: %zu (refs: %zu bytes: %zu)\n",
  103. s->live[1].refs, s->live[1].bytes,
  104. s->live[0].refs, s->live[0].bytes);
  105. /* We don't know how many pages are sitting in cache and ring
  106. * so we will under-count the recycling rate a bit.
  107. */
  108. recycle = (double)(s->recycle_ring + s->recycle_cache) /
  109. (s->alloc_fast + s->alloc_slow) * 100;
  110. printf("\t\trecycling: %.1lf%% (alloc: %zu:%zu recycle: %zu:%zu)\n",
  111. recycle, s->alloc_slow, s->alloc_fast,
  112. s->recycle_ring, s->recycle_cache);
  113. }
  114. ynl_sock_destroy(ys);
  115. return 0;
  116. err_free:
  117. free(a.s);
  118. err_close:
  119. fprintf(stderr, "YNL: %s\n", ys->err.msg);
  120. ynl_sock_destroy(ys);
  121. return 2;
  122. }