proc_net_sockstat6.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "plugin_proc.h"
  3. #define PLUGIN_PROC_MODULE_NET_SOCKSTAT6_NAME "/proc/net/sockstat6"
  4. static struct proc_net_sockstat6 {
  5. kernel_uint_t tcp6_inuse;
  6. kernel_uint_t udp6_inuse;
  7. kernel_uint_t udplite6_inuse;
  8. kernel_uint_t raw6_inuse;
  9. kernel_uint_t frag6_inuse;
  10. } sockstat6_root = { 0 };
  11. int do_proc_net_sockstat6(int update_every, usec_t dt) {
  12. (void)dt;
  13. static procfile *ff = NULL;
  14. static uint32_t hash_raw = 0,
  15. hash_frag = 0,
  16. hash_tcp = 0,
  17. hash_udp = 0,
  18. hash_udplite = 0;
  19. static ARL_BASE *arl_tcp = NULL;
  20. static ARL_BASE *arl_udp = NULL;
  21. static ARL_BASE *arl_udplite = NULL;
  22. static ARL_BASE *arl_raw = NULL;
  23. static ARL_BASE *arl_frag = NULL;
  24. static int do_tcp_sockets = -1, do_udp_sockets = -1, do_udplite_sockets = -1, do_raw_sockets = -1, do_frag_sockets = -1;
  25. static char *keys[6] = { NULL };
  26. static uint32_t hashes[6] = { 0 };
  27. static ARL_BASE *bases[6] = { NULL };
  28. if(unlikely(!arl_tcp)) {
  29. do_tcp_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat6", "ipv6 TCP sockets", CONFIG_BOOLEAN_AUTO);
  30. do_udp_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat6", "ipv6 UDP sockets", CONFIG_BOOLEAN_AUTO);
  31. do_udplite_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat6", "ipv6 UDPLITE sockets", CONFIG_BOOLEAN_AUTO);
  32. do_raw_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat6", "ipv6 RAW sockets", CONFIG_BOOLEAN_AUTO);
  33. do_frag_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat6", "ipv6 FRAG sockets", CONFIG_BOOLEAN_AUTO);
  34. arl_tcp = arl_create("sockstat6/TCP6", arl_callback_str2kernel_uint_t, 60);
  35. arl_expect(arl_tcp, "inuse", &sockstat6_root.tcp6_inuse);
  36. arl_udp = arl_create("sockstat6/UDP6", arl_callback_str2kernel_uint_t, 60);
  37. arl_expect(arl_udp, "inuse", &sockstat6_root.udp6_inuse);
  38. arl_udplite = arl_create("sockstat6/UDPLITE6", arl_callback_str2kernel_uint_t, 60);
  39. arl_expect(arl_udplite, "inuse", &sockstat6_root.udplite6_inuse);
  40. arl_raw = arl_create("sockstat6/RAW6", arl_callback_str2kernel_uint_t, 60);
  41. arl_expect(arl_raw, "inuse", &sockstat6_root.raw6_inuse);
  42. arl_frag = arl_create("sockstat6/FRAG6", arl_callback_str2kernel_uint_t, 60);
  43. arl_expect(arl_frag, "inuse", &sockstat6_root.frag6_inuse);
  44. hash_tcp = simple_hash("TCP6");
  45. hash_udp = simple_hash("UDP6");
  46. hash_udplite = simple_hash("UDPLITE6");
  47. hash_raw = simple_hash("RAW6");
  48. hash_frag = simple_hash("FRAG6");
  49. keys[0] = "TCP6"; hashes[0] = hash_tcp; bases[0] = arl_tcp;
  50. keys[1] = "UDP6"; hashes[1] = hash_udp; bases[1] = arl_udp;
  51. keys[2] = "UDPLITE6"; hashes[2] = hash_udplite; bases[2] = arl_udplite;
  52. keys[3] = "RAW6"; hashes[3] = hash_raw; bases[3] = arl_raw;
  53. keys[4] = "FRAG6"; hashes[4] = hash_frag; bases[4] = arl_frag;
  54. keys[5] = NULL; // terminator
  55. }
  56. if(unlikely(!ff)) {
  57. char filename[FILENAME_MAX + 1];
  58. snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/sockstat6");
  59. ff = procfile_open(config_get("plugin:proc:/proc/net/sockstat6", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
  60. if(unlikely(!ff)) return 1;
  61. }
  62. ff = procfile_readall(ff);
  63. if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time
  64. size_t lines = procfile_lines(ff), l;
  65. for(l = 0; l < lines ;l++) {
  66. size_t words = procfile_linewords(ff, l);
  67. char *key = procfile_lineword(ff, l, 0);
  68. uint32_t hash = simple_hash(key);
  69. int k;
  70. for(k = 0; keys[k] ; k++) {
  71. if(unlikely(hash == hashes[k] && strcmp(key, keys[k]) == 0)) {
  72. // fprintf(stderr, "KEY: '%s', l=%zu, w=1, words=%zu\n", key, l, words);
  73. ARL_BASE *arl = bases[k];
  74. arl_begin(arl);
  75. size_t w = 1;
  76. while(w + 1 < words) {
  77. char *name = procfile_lineword(ff, l, w); w++;
  78. char *value = procfile_lineword(ff, l, w); w++;
  79. // fprintf(stderr, " > NAME '%s', VALUE '%s', l=%zu, w=%zu, words=%zu\n", name, value, l, w, words);
  80. if(unlikely(arl_check(arl, name, value) != 0))
  81. break;
  82. }
  83. break;
  84. }
  85. }
  86. }
  87. // ------------------------------------------------------------------------
  88. if(do_tcp_sockets == CONFIG_BOOLEAN_YES || (do_tcp_sockets == CONFIG_BOOLEAN_AUTO &&
  89. (sockstat6_root.tcp6_inuse ||
  90. netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) {
  91. do_tcp_sockets = CONFIG_BOOLEAN_YES;
  92. static RRDSET *st = NULL;
  93. static RRDDIM *rd_inuse = NULL;
  94. if(unlikely(!st)) {
  95. st = rrdset_create_localhost(
  96. "ipv6"
  97. , "sockstat6_tcp_sockets"
  98. , NULL
  99. , "tcp6"
  100. , NULL
  101. , "IPv6 TCP Sockets"
  102. , "sockets"
  103. , PLUGIN_PROC_NAME
  104. , PLUGIN_PROC_MODULE_NET_SOCKSTAT6_NAME
  105. , NETDATA_CHART_PRIO_IPV6_TCP
  106. , update_every
  107. , RRDSET_TYPE_LINE
  108. );
  109. rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
  110. }
  111. else rrdset_next(st);
  112. rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat6_root.tcp6_inuse);
  113. rrdset_done(st);
  114. }
  115. // ------------------------------------------------------------------------
  116. if(do_udp_sockets == CONFIG_BOOLEAN_YES || (do_udp_sockets == CONFIG_BOOLEAN_AUTO &&
  117. (sockstat6_root.udp6_inuse ||
  118. netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) {
  119. do_udp_sockets = CONFIG_BOOLEAN_YES;
  120. static RRDSET *st = NULL;
  121. static RRDDIM *rd_inuse = NULL;
  122. if(unlikely(!st)) {
  123. st = rrdset_create_localhost(
  124. "ipv6"
  125. , "sockstat6_udp_sockets"
  126. , NULL
  127. , "udp6"
  128. , NULL
  129. , "IPv6 UDP Sockets"
  130. , "sockets"
  131. , PLUGIN_PROC_NAME
  132. , PLUGIN_PROC_MODULE_NET_SOCKSTAT6_NAME
  133. , NETDATA_CHART_PRIO_IPV6_UDP
  134. , update_every
  135. , RRDSET_TYPE_LINE
  136. );
  137. rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
  138. }
  139. else rrdset_next(st);
  140. rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat6_root.udp6_inuse);
  141. rrdset_done(st);
  142. }
  143. // ------------------------------------------------------------------------
  144. if(do_udplite_sockets == CONFIG_BOOLEAN_YES || (do_udplite_sockets == CONFIG_BOOLEAN_AUTO &&
  145. (sockstat6_root.udplite6_inuse ||
  146. netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) {
  147. do_udplite_sockets = CONFIG_BOOLEAN_YES;
  148. static RRDSET *st = NULL;
  149. static RRDDIM *rd_inuse = NULL;
  150. if(unlikely(!st)) {
  151. st = rrdset_create_localhost(
  152. "ipv6"
  153. , "sockstat6_udplite_sockets"
  154. , NULL
  155. , "udplite6"
  156. , NULL
  157. , "IPv6 UDPLITE Sockets"
  158. , "sockets"
  159. , PLUGIN_PROC_NAME
  160. , PLUGIN_PROC_MODULE_NET_SOCKSTAT6_NAME
  161. , NETDATA_CHART_PRIO_IPV6_UDPLITE
  162. , update_every
  163. , RRDSET_TYPE_LINE
  164. );
  165. rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
  166. }
  167. else rrdset_next(st);
  168. rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat6_root.udplite6_inuse);
  169. rrdset_done(st);
  170. }
  171. // ------------------------------------------------------------------------
  172. if(do_raw_sockets == CONFIG_BOOLEAN_YES || (do_raw_sockets == CONFIG_BOOLEAN_AUTO &&
  173. (sockstat6_root.raw6_inuse ||
  174. netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) {
  175. do_raw_sockets = CONFIG_BOOLEAN_YES;
  176. static RRDSET *st = NULL;
  177. static RRDDIM *rd_inuse = NULL;
  178. if(unlikely(!st)) {
  179. st = rrdset_create_localhost(
  180. "ipv6"
  181. , "sockstat6_raw_sockets"
  182. , NULL
  183. , "raw6"
  184. , NULL
  185. , "IPv6 RAW Sockets"
  186. , "sockets"
  187. , PLUGIN_PROC_NAME
  188. , PLUGIN_PROC_MODULE_NET_SOCKSTAT6_NAME
  189. , NETDATA_CHART_PRIO_IPV6_RAW
  190. , update_every
  191. , RRDSET_TYPE_LINE
  192. );
  193. rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
  194. }
  195. else rrdset_next(st);
  196. rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat6_root.raw6_inuse);
  197. rrdset_done(st);
  198. }
  199. // ------------------------------------------------------------------------
  200. if(do_frag_sockets == CONFIG_BOOLEAN_YES || (do_frag_sockets == CONFIG_BOOLEAN_AUTO &&
  201. (sockstat6_root.frag6_inuse ||
  202. netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) {
  203. do_frag_sockets = CONFIG_BOOLEAN_YES;
  204. static RRDSET *st = NULL;
  205. static RRDDIM *rd_inuse = NULL;
  206. if(unlikely(!st)) {
  207. st = rrdset_create_localhost(
  208. "ipv6"
  209. , "sockstat6_frag_sockets"
  210. , NULL
  211. , "fragments6"
  212. , NULL
  213. , "IPv6 FRAG Sockets"
  214. , "fragments"
  215. , PLUGIN_PROC_NAME
  216. , PLUGIN_PROC_MODULE_NET_SOCKSTAT6_NAME
  217. , NETDATA_CHART_PRIO_IPV6_FRAGMENTS
  218. , update_every
  219. , RRDSET_TYPE_LINE
  220. );
  221. rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
  222. }
  223. else rrdset_next(st);
  224. rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat6_root.frag6_inuse);
  225. rrdset_done(st);
  226. }
  227. return 0;
  228. }