proc_net_softnet_stat.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "plugin_proc.h"
  3. #define PLUGIN_PROC_MODULE_NET_SOFTNET_NAME "/proc/net/softnet_stat"
  4. static inline char *softnet_column_name(size_t column) {
  5. switch(column) {
  6. // https://github.com/torvalds/linux/blob/a7fd20d1c476af4563e66865213474a2f9f473a4/net/core/net-procfs.c#L161-L166
  7. case 0: return "processed";
  8. case 1: return "dropped";
  9. case 2: return "squeezed";
  10. case 9: return "received_rps";
  11. case 10: return "flow_limit_count";
  12. default: return NULL;
  13. }
  14. }
  15. int do_proc_net_softnet_stat(int update_every, usec_t dt) {
  16. (void)dt;
  17. static procfile *ff = NULL;
  18. static int do_per_core = -1;
  19. static size_t allocated_lines = 0, allocated_columns = 0;
  20. static uint32_t *data = NULL;
  21. if(unlikely(do_per_core == -1)) do_per_core = config_get_boolean("plugin:proc:/proc/net/softnet_stat", "softnet_stat per core", 1);
  22. if(unlikely(!ff)) {
  23. char filename[FILENAME_MAX + 1];
  24. snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/softnet_stat");
  25. ff = procfile_open(config_get("plugin:proc:/proc/net/softnet_stat", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT);
  26. if(unlikely(!ff)) return 1;
  27. }
  28. ff = procfile_readall(ff);
  29. if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time
  30. size_t lines = procfile_lines(ff), l;
  31. size_t words = procfile_linewords(ff, 0), w;
  32. if(unlikely(!lines || !words)) {
  33. error("Cannot read /proc/net/softnet_stat, %zu lines and %zu columns reported.", lines, words);
  34. return 1;
  35. }
  36. if(unlikely(lines > 200)) lines = 200;
  37. if(unlikely(words > 50)) words = 50;
  38. if(unlikely(!data || lines > allocated_lines || words > allocated_columns)) {
  39. freez(data);
  40. allocated_lines = lines;
  41. allocated_columns = words;
  42. data = mallocz((allocated_lines + 1) * allocated_columns * sizeof(uint32_t));
  43. }
  44. // initialize to zero
  45. memset(data, 0, (allocated_lines + 1) * allocated_columns * sizeof(uint32_t));
  46. // parse the values
  47. for(l = 0; l < lines ;l++) {
  48. words = procfile_linewords(ff, l);
  49. if(unlikely(!words)) continue;
  50. if(unlikely(words > allocated_columns))
  51. words = allocated_columns;
  52. for(w = 0; w < words ; w++) {
  53. if(unlikely(softnet_column_name(w))) {
  54. uint32_t t = (uint32_t)strtoul(procfile_lineword(ff, l, w), NULL, 16);
  55. data[w] += t;
  56. data[((l + 1) * allocated_columns) + w] = t;
  57. }
  58. }
  59. }
  60. if(unlikely(data[(lines * allocated_columns)] == 0))
  61. lines--;
  62. RRDSET *st;
  63. // --------------------------------------------------------------------
  64. st = rrdset_find_active_bytype_localhost("system", "softnet_stat");
  65. if(unlikely(!st)) {
  66. st = rrdset_create_localhost(
  67. "system"
  68. , "softnet_stat"
  69. , NULL
  70. , "softnet_stat"
  71. , "system.softnet_stat"
  72. , "System softnet_stat"
  73. , "events/s"
  74. , PLUGIN_PROC_NAME
  75. , PLUGIN_PROC_MODULE_NET_SOFTNET_NAME
  76. , NETDATA_CHART_PRIO_SYSTEM_SOFTNET_STAT
  77. , update_every
  78. , RRDSET_TYPE_LINE
  79. );
  80. for(w = 0; w < allocated_columns ;w++)
  81. if(unlikely(softnet_column_name(w)))
  82. rrddim_add(st, softnet_column_name(w), NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
  83. }
  84. else rrdset_next(st);
  85. for(w = 0; w < allocated_columns ;w++)
  86. if(unlikely(softnet_column_name(w)))
  87. rrddim_set(st, softnet_column_name(w), data[w]);
  88. rrdset_done(st);
  89. if(do_per_core) {
  90. for(l = 0; l < lines ;l++) {
  91. char id[50+1];
  92. snprintfz(id, 50, "cpu%zu_softnet_stat", l);
  93. st = rrdset_find_active_bytype_localhost("cpu", id);
  94. if(unlikely(!st)) {
  95. char title[100+1];
  96. snprintfz(title, 100, "CPU softnet_stat");
  97. st = rrdset_create_localhost(
  98. "cpu"
  99. , id
  100. , NULL
  101. , "softnet_stat"
  102. , "cpu.softnet_stat"
  103. , title
  104. , "events/s"
  105. , PLUGIN_PROC_NAME
  106. , PLUGIN_PROC_MODULE_NET_SOFTNET_NAME
  107. , NETDATA_CHART_PRIO_SOFTNET_PER_CORE + l
  108. , update_every
  109. , RRDSET_TYPE_LINE
  110. );
  111. for(w = 0; w < allocated_columns ;w++)
  112. if(unlikely(softnet_column_name(w)))
  113. rrddim_add(st, softnet_column_name(w), NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
  114. }
  115. else rrdset_next(st);
  116. for(w = 0; w < allocated_columns ;w++)
  117. if(unlikely(softnet_column_name(w)))
  118. rrddim_set(st, softnet_column_name(w), data[((l + 1) * allocated_columns) + w]);
  119. rrdset_done(st);
  120. }
  121. }
  122. return 0;
  123. }