proc_net_softnet_stat.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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)) {
  22. do_per_core =
  23. config_get_boolean("plugin:proc:/proc/net/softnet_stat", "softnet_stat per core", CONFIG_BOOLEAN_NO);
  24. }
  25. if(unlikely(!ff)) {
  26. char filename[FILENAME_MAX + 1];
  27. snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/softnet_stat");
  28. ff = procfile_open(config_get("plugin:proc:/proc/net/softnet_stat", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT);
  29. if(unlikely(!ff)) return 1;
  30. }
  31. ff = procfile_readall(ff);
  32. if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time
  33. size_t lines = procfile_lines(ff), l;
  34. size_t words = procfile_linewords(ff, 0), w;
  35. if(unlikely(!lines || !words)) {
  36. collector_error("Cannot read /proc/net/softnet_stat, %zu lines and %zu columns reported.", lines, words);
  37. return 1;
  38. }
  39. if(unlikely(lines > 200)) lines = 200;
  40. if(unlikely(words > 50)) words = 50;
  41. if(unlikely(!data || lines > allocated_lines || words > allocated_columns)) {
  42. freez(data);
  43. allocated_lines = lines;
  44. allocated_columns = words;
  45. data = mallocz((allocated_lines + 1) * allocated_columns * sizeof(uint32_t));
  46. }
  47. // initialize to zero
  48. memset(data, 0, (allocated_lines + 1) * allocated_columns * sizeof(uint32_t));
  49. // parse the values
  50. for(l = 0; l < lines ;l++) {
  51. words = procfile_linewords(ff, l);
  52. if(unlikely(!words)) continue;
  53. if(unlikely(words > allocated_columns))
  54. words = allocated_columns;
  55. for(w = 0; w < words ; w++) {
  56. if(unlikely(softnet_column_name(w))) {
  57. uint32_t t = (uint32_t)strtoul(procfile_lineword(ff, l, w), NULL, 16);
  58. data[w] += t;
  59. data[((l + 1) * allocated_columns) + w] = t;
  60. }
  61. }
  62. }
  63. if(unlikely(data[(lines * allocated_columns)] == 0))
  64. lines--;
  65. RRDSET *st;
  66. // --------------------------------------------------------------------
  67. st = rrdset_find_active_bytype_localhost("system", "softnet_stat");
  68. if(unlikely(!st)) {
  69. st = rrdset_create_localhost(
  70. "system"
  71. , "softnet_stat"
  72. , NULL
  73. , "softnet_stat"
  74. , "system.softnet_stat"
  75. , "System softnet_stat"
  76. , "events/s"
  77. , PLUGIN_PROC_NAME
  78. , PLUGIN_PROC_MODULE_NET_SOFTNET_NAME
  79. , NETDATA_CHART_PRIO_SYSTEM_SOFTNET_STAT
  80. , update_every
  81. , RRDSET_TYPE_LINE
  82. );
  83. for(w = 0; w < allocated_columns ;w++)
  84. if(unlikely(softnet_column_name(w)))
  85. rrddim_add(st, softnet_column_name(w), NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
  86. }
  87. for(w = 0; w < allocated_columns ;w++)
  88. if(unlikely(softnet_column_name(w)))
  89. rrddim_set(st, softnet_column_name(w), data[w]);
  90. rrdset_done(st);
  91. if(do_per_core) {
  92. for(l = 0; l < lines ;l++) {
  93. char id[50+1];
  94. snprintfz(id, sizeof(id) - 1,"cpu%zu_softnet_stat", l);
  95. st = rrdset_find_active_bytype_localhost("cpu", id);
  96. if(unlikely(!st)) {
  97. char title[100+1];
  98. snprintfz(title, sizeof(title) - 1, "CPU softnet_stat");
  99. st = rrdset_create_localhost(
  100. "cpu"
  101. , id
  102. , NULL
  103. , "softnet_stat"
  104. , "cpu.softnet_stat"
  105. , title
  106. , "events/s"
  107. , PLUGIN_PROC_NAME
  108. , PLUGIN_PROC_MODULE_NET_SOFTNET_NAME
  109. , NETDATA_CHART_PRIO_SOFTNET_PER_CORE + l
  110. , update_every
  111. , RRDSET_TYPE_LINE
  112. );
  113. for(w = 0; w < allocated_columns ;w++)
  114. if(unlikely(softnet_column_name(w)))
  115. rrddim_add(st, softnet_column_name(w), NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
  116. }
  117. for(w = 0; w < allocated_columns ;w++)
  118. if(unlikely(softnet_column_name(w)))
  119. rrddim_set(st, softnet_column_name(w), data[((l + 1) * allocated_columns) + w]);
  120. rrdset_done(st);
  121. }
  122. }
  123. return 0;
  124. }