proc_net_netstat.c 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "plugin_proc.h"
  3. #define RRD_TYPE_NET_NETSTAT "ip"
  4. #define PLUGIN_PROC_MODULE_NETSTAT_NAME "/proc/net/netstat"
  5. #define CONFIG_SECTION_PLUGIN_PROC_NETSTAT "plugin:" PLUGIN_PROC_CONFIG_NAME ":" PLUGIN_PROC_MODULE_NETSTAT_NAME
  6. unsigned long long tcpext_TCPSynRetrans = 0;
  7. static void parse_line_pair(procfile *ff, ARL_BASE *base, size_t header_line, size_t values_line) {
  8. size_t hwords = procfile_linewords(ff, header_line);
  9. size_t vwords = procfile_linewords(ff, values_line);
  10. size_t w;
  11. if(unlikely(vwords > hwords)) {
  12. error("File /proc/net/netstat on header line %zu has %zu words, but on value line %zu has %zu words.", header_line, hwords, values_line, vwords);
  13. vwords = hwords;
  14. }
  15. for(w = 1; w < vwords ;w++) {
  16. if(unlikely(arl_check(base, procfile_lineword(ff, header_line, w), procfile_lineword(ff, values_line, w))))
  17. break;
  18. }
  19. }
  20. int do_proc_net_netstat(int update_every, usec_t dt) {
  21. (void)dt;
  22. static int do_bandwidth = -1, do_inerrors = -1, do_mcast = -1, do_bcast = -1, do_mcast_p = -1, do_bcast_p = -1, do_ecn = -1, \
  23. do_tcpext_reorder = -1, do_tcpext_syscookies = -1, do_tcpext_ofo = -1, do_tcpext_connaborts = -1, do_tcpext_memory = -1,
  24. do_tcpext_syn_queue = -1, do_tcpext_accept_queue = -1;
  25. static uint32_t hash_ipext = 0, hash_tcpext = 0;
  26. static procfile *ff = NULL;
  27. static ARL_BASE *arl_tcpext = NULL;
  28. static ARL_BASE *arl_ipext = NULL;
  29. // --------------------------------------------------------------------
  30. // IP
  31. // IP bandwidth
  32. static unsigned long long ipext_InOctets = 0;
  33. static unsigned long long ipext_OutOctets = 0;
  34. // IP input errors
  35. static unsigned long long ipext_InNoRoutes = 0;
  36. static unsigned long long ipext_InTruncatedPkts = 0;
  37. static unsigned long long ipext_InCsumErrors = 0;
  38. // IP multicast bandwidth
  39. static unsigned long long ipext_InMcastOctets = 0;
  40. static unsigned long long ipext_OutMcastOctets = 0;
  41. // IP multicast packets
  42. static unsigned long long ipext_InMcastPkts = 0;
  43. static unsigned long long ipext_OutMcastPkts = 0;
  44. // IP broadcast bandwidth
  45. static unsigned long long ipext_InBcastOctets = 0;
  46. static unsigned long long ipext_OutBcastOctets = 0;
  47. // IP broadcast packets
  48. static unsigned long long ipext_InBcastPkts = 0;
  49. static unsigned long long ipext_OutBcastPkts = 0;
  50. // IP ECN
  51. static unsigned long long ipext_InNoECTPkts = 0;
  52. static unsigned long long ipext_InECT1Pkts = 0;
  53. static unsigned long long ipext_InECT0Pkts = 0;
  54. static unsigned long long ipext_InCEPkts = 0;
  55. // --------------------------------------------------------------------
  56. // IP TCP
  57. // IP TCP Reordering
  58. static unsigned long long tcpext_TCPRenoReorder = 0;
  59. static unsigned long long tcpext_TCPFACKReorder = 0;
  60. static unsigned long long tcpext_TCPSACKReorder = 0;
  61. static unsigned long long tcpext_TCPTSReorder = 0;
  62. // IP TCP SYN Cookies
  63. static unsigned long long tcpext_SyncookiesSent = 0;
  64. static unsigned long long tcpext_SyncookiesRecv = 0;
  65. static unsigned long long tcpext_SyncookiesFailed = 0;
  66. // IP TCP Out Of Order Queue
  67. // http://www.spinics.net/lists/netdev/msg204696.html
  68. static unsigned long long tcpext_TCPOFOQueue = 0; // Number of packets queued in OFO queue
  69. static unsigned long long tcpext_TCPOFODrop = 0; // Number of packets meant to be queued in OFO but dropped because socket rcvbuf limit hit.
  70. static unsigned long long tcpext_TCPOFOMerge = 0; // Number of packets in OFO that were merged with other packets.
  71. static unsigned long long tcpext_OfoPruned = 0; // packets dropped from out-of-order queue because of socket buffer overrun
  72. // IP TCP connection resets
  73. // https://github.com/ecki/net-tools/blob/bd8bceaed2311651710331a7f8990c3e31be9840/statistics.c
  74. static unsigned long long tcpext_TCPAbortOnData = 0; // connections reset due to unexpected data
  75. static unsigned long long tcpext_TCPAbortOnClose = 0; // connections reset due to early user close
  76. static unsigned long long tcpext_TCPAbortOnMemory = 0; // connections aborted due to memory pressure
  77. static unsigned long long tcpext_TCPAbortOnTimeout = 0; // connections aborted due to timeout
  78. static unsigned long long tcpext_TCPAbortOnLinger = 0; // connections aborted after user close in linger timeout
  79. static unsigned long long tcpext_TCPAbortFailed = 0; // times unable to send RST due to no memory
  80. // https://perfchron.com/2015/12/26/investigating-linux-network-issues-with-netstat-and-nstat/
  81. static unsigned long long tcpext_ListenOverflows = 0; // times the listen queue of a socket overflowed
  82. static unsigned long long tcpext_ListenDrops = 0; // SYNs to LISTEN sockets ignored
  83. // IP TCP memory pressures
  84. static unsigned long long tcpext_TCPMemoryPressures = 0;
  85. static unsigned long long tcpext_TCPReqQFullDrop = 0;
  86. static unsigned long long tcpext_TCPReqQFullDoCookies = 0;
  87. // shared: tcpext_TCPSynRetrans
  88. if(unlikely(!arl_ipext)) {
  89. hash_ipext = simple_hash("IpExt");
  90. hash_tcpext = simple_hash("TcpExt");
  91. do_bandwidth = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "bandwidth", CONFIG_BOOLEAN_AUTO);
  92. do_inerrors = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "input errors", CONFIG_BOOLEAN_AUTO);
  93. do_mcast = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "multicast bandwidth", CONFIG_BOOLEAN_AUTO);
  94. do_bcast = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "broadcast bandwidth", CONFIG_BOOLEAN_AUTO);
  95. do_mcast_p = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "multicast packets", CONFIG_BOOLEAN_AUTO);
  96. do_bcast_p = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "broadcast packets", CONFIG_BOOLEAN_AUTO);
  97. do_ecn = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "ECN packets", CONFIG_BOOLEAN_AUTO);
  98. do_tcpext_reorder = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "TCP reorders", CONFIG_BOOLEAN_AUTO);
  99. do_tcpext_syscookies = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "TCP SYN cookies", CONFIG_BOOLEAN_AUTO);
  100. do_tcpext_ofo = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "TCP out-of-order queue", CONFIG_BOOLEAN_AUTO);
  101. do_tcpext_connaborts = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "TCP connection aborts", CONFIG_BOOLEAN_AUTO);
  102. do_tcpext_memory = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "TCP memory pressures", CONFIG_BOOLEAN_AUTO);
  103. do_tcpext_syn_queue = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "TCP SYN queue", CONFIG_BOOLEAN_AUTO);
  104. do_tcpext_accept_queue = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "TCP accept queue", CONFIG_BOOLEAN_AUTO);
  105. arl_ipext = arl_create("netstat/ipext", NULL, 60);
  106. arl_tcpext = arl_create("netstat/tcpext", NULL, 60);
  107. // --------------------------------------------------------------------
  108. // IP
  109. if(do_bandwidth != CONFIG_BOOLEAN_NO) {
  110. arl_expect(arl_ipext, "InOctets", &ipext_InOctets);
  111. arl_expect(arl_ipext, "OutOctets", &ipext_OutOctets);
  112. }
  113. if(do_inerrors != CONFIG_BOOLEAN_NO) {
  114. arl_expect(arl_ipext, "InNoRoutes", &ipext_InNoRoutes);
  115. arl_expect(arl_ipext, "InTruncatedPkts", &ipext_InTruncatedPkts);
  116. arl_expect(arl_ipext, "InCsumErrors", &ipext_InCsumErrors);
  117. }
  118. if(do_mcast != CONFIG_BOOLEAN_NO) {
  119. arl_expect(arl_ipext, "InMcastOctets", &ipext_InMcastOctets);
  120. arl_expect(arl_ipext, "OutMcastOctets", &ipext_OutMcastOctets);
  121. }
  122. if(do_mcast_p != CONFIG_BOOLEAN_NO) {
  123. arl_expect(arl_ipext, "InMcastPkts", &ipext_InMcastPkts);
  124. arl_expect(arl_ipext, "OutMcastPkts", &ipext_OutMcastPkts);
  125. }
  126. if(do_bcast != CONFIG_BOOLEAN_NO) {
  127. arl_expect(arl_ipext, "InBcastPkts", &ipext_InBcastPkts);
  128. arl_expect(arl_ipext, "OutBcastPkts", &ipext_OutBcastPkts);
  129. }
  130. if(do_bcast_p != CONFIG_BOOLEAN_NO) {
  131. arl_expect(arl_ipext, "InBcastOctets", &ipext_InBcastOctets);
  132. arl_expect(arl_ipext, "OutBcastOctets", &ipext_OutBcastOctets);
  133. }
  134. if(do_ecn != CONFIG_BOOLEAN_NO) {
  135. arl_expect(arl_ipext, "InNoECTPkts", &ipext_InNoECTPkts);
  136. arl_expect(arl_ipext, "InECT1Pkts", &ipext_InECT1Pkts);
  137. arl_expect(arl_ipext, "InECT0Pkts", &ipext_InECT0Pkts);
  138. arl_expect(arl_ipext, "InCEPkts", &ipext_InCEPkts);
  139. }
  140. // --------------------------------------------------------------------
  141. // IP TCP
  142. if(do_tcpext_reorder != CONFIG_BOOLEAN_NO) {
  143. arl_expect(arl_tcpext, "TCPFACKReorder", &tcpext_TCPFACKReorder);
  144. arl_expect(arl_tcpext, "TCPSACKReorder", &tcpext_TCPSACKReorder);
  145. arl_expect(arl_tcpext, "TCPRenoReorder", &tcpext_TCPRenoReorder);
  146. arl_expect(arl_tcpext, "TCPTSReorder", &tcpext_TCPTSReorder);
  147. }
  148. if(do_tcpext_syscookies != CONFIG_BOOLEAN_NO) {
  149. arl_expect(arl_tcpext, "SyncookiesSent", &tcpext_SyncookiesSent);
  150. arl_expect(arl_tcpext, "SyncookiesRecv", &tcpext_SyncookiesRecv);
  151. arl_expect(arl_tcpext, "SyncookiesFailed", &tcpext_SyncookiesFailed);
  152. }
  153. if(do_tcpext_ofo != CONFIG_BOOLEAN_NO) {
  154. arl_expect(arl_tcpext, "TCPOFOQueue", &tcpext_TCPOFOQueue);
  155. arl_expect(arl_tcpext, "TCPOFODrop", &tcpext_TCPOFODrop);
  156. arl_expect(arl_tcpext, "TCPOFOMerge", &tcpext_TCPOFOMerge);
  157. arl_expect(arl_tcpext, "OfoPruned", &tcpext_OfoPruned);
  158. }
  159. if(do_tcpext_connaborts != CONFIG_BOOLEAN_NO) {
  160. arl_expect(arl_tcpext, "TCPAbortOnData", &tcpext_TCPAbortOnData);
  161. arl_expect(arl_tcpext, "TCPAbortOnClose", &tcpext_TCPAbortOnClose);
  162. arl_expect(arl_tcpext, "TCPAbortOnMemory", &tcpext_TCPAbortOnMemory);
  163. arl_expect(arl_tcpext, "TCPAbortOnTimeout", &tcpext_TCPAbortOnTimeout);
  164. arl_expect(arl_tcpext, "TCPAbortOnLinger", &tcpext_TCPAbortOnLinger);
  165. arl_expect(arl_tcpext, "TCPAbortFailed", &tcpext_TCPAbortFailed);
  166. }
  167. if(do_tcpext_memory != CONFIG_BOOLEAN_NO) {
  168. arl_expect(arl_tcpext, "TCPMemoryPressures", &tcpext_TCPMemoryPressures);
  169. }
  170. if(do_tcpext_accept_queue != CONFIG_BOOLEAN_NO) {
  171. arl_expect(arl_tcpext, "ListenOverflows", &tcpext_ListenOverflows);
  172. arl_expect(arl_tcpext, "ListenDrops", &tcpext_ListenDrops);
  173. }
  174. if(do_tcpext_syn_queue != CONFIG_BOOLEAN_NO) {
  175. arl_expect(arl_tcpext, "TCPReqQFullDrop", &tcpext_TCPReqQFullDrop);
  176. arl_expect(arl_tcpext, "TCPReqQFullDoCookies", &tcpext_TCPReqQFullDoCookies);
  177. }
  178. // shared metrics
  179. arl_expect(arl_tcpext, "TCPSynRetrans", &tcpext_TCPSynRetrans);
  180. }
  181. if(unlikely(!ff)) {
  182. char filename[FILENAME_MAX + 1];
  183. snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/netstat");
  184. ff = procfile_open(config_get(CONFIG_SECTION_PLUGIN_PROC_NETSTAT, "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
  185. if(unlikely(!ff)) return 1;
  186. }
  187. ff = procfile_readall(ff);
  188. if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time
  189. size_t lines = procfile_lines(ff), l;
  190. size_t words;
  191. arl_begin(arl_ipext);
  192. arl_begin(arl_tcpext);
  193. for(l = 0; l < lines ;l++) {
  194. char *key = procfile_lineword(ff, l, 0);
  195. uint32_t hash = simple_hash(key);
  196. if(unlikely(hash == hash_ipext && strcmp(key, "IpExt") == 0)) {
  197. size_t h = l++;
  198. words = procfile_linewords(ff, l);
  199. if(unlikely(words < 2)) {
  200. error("Cannot read /proc/net/netstat IpExt line. Expected 2+ params, read %zu.", words);
  201. continue;
  202. }
  203. parse_line_pair(ff, arl_ipext, h, l);
  204. // --------------------------------------------------------------------
  205. if(do_bandwidth == CONFIG_BOOLEAN_YES || (do_bandwidth == CONFIG_BOOLEAN_AUTO && (ipext_InOctets || ipext_OutOctets))) {
  206. do_bandwidth = CONFIG_BOOLEAN_YES;
  207. static RRDSET *st_system_ip = NULL;
  208. static RRDDIM *rd_in = NULL, *rd_out = NULL;
  209. if(unlikely(!st_system_ip)) {
  210. st_system_ip = rrdset_create_localhost(
  211. "system"
  212. , RRD_TYPE_NET_NETSTAT
  213. , NULL
  214. , "network"
  215. , NULL
  216. , "IP Bandwidth"
  217. , "kilobits/s"
  218. , PLUGIN_PROC_NAME
  219. , PLUGIN_PROC_MODULE_NETSTAT_NAME
  220. , NETDATA_CHART_PRIO_SYSTEM_IP
  221. , update_every
  222. , RRDSET_TYPE_AREA
  223. );
  224. rd_in = rrddim_add(st_system_ip, "InOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
  225. rd_out = rrddim_add(st_system_ip, "OutOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
  226. }
  227. else
  228. rrdset_next(st_system_ip);
  229. rrddim_set_by_pointer(st_system_ip, rd_in, ipext_InOctets);
  230. rrddim_set_by_pointer(st_system_ip, rd_out, ipext_OutOctets);
  231. rrdset_done(st_system_ip);
  232. }
  233. // --------------------------------------------------------------------
  234. if(do_inerrors == CONFIG_BOOLEAN_YES || (do_inerrors == CONFIG_BOOLEAN_AUTO && (ipext_InNoRoutes || ipext_InTruncatedPkts))) {
  235. do_inerrors = CONFIG_BOOLEAN_YES;
  236. static RRDSET *st_ip_inerrors = NULL;
  237. static RRDDIM *rd_noroutes = NULL, *rd_truncated = NULL, *rd_checksum = NULL;
  238. if(unlikely(!st_ip_inerrors)) {
  239. st_ip_inerrors = rrdset_create_localhost(
  240. RRD_TYPE_NET_NETSTAT
  241. , "inerrors"
  242. , NULL
  243. , "errors"
  244. , NULL
  245. , "IP Input Errors"
  246. , "packets/s"
  247. , PLUGIN_PROC_NAME
  248. , PLUGIN_PROC_MODULE_NETSTAT_NAME
  249. , NETDATA_CHART_PRIO_IP_ERRORS
  250. , update_every
  251. , RRDSET_TYPE_LINE
  252. );
  253. rrdset_flag_set(st_ip_inerrors, RRDSET_FLAG_DETAIL);
  254. rd_noroutes = rrddim_add(st_ip_inerrors, "InNoRoutes", "noroutes", 1, 1, RRD_ALGORITHM_INCREMENTAL);
  255. rd_truncated = rrddim_add(st_ip_inerrors, "InTruncatedPkts", "truncated", 1, 1, RRD_ALGORITHM_INCREMENTAL);
  256. rd_checksum = rrddim_add(st_ip_inerrors, "InCsumErrors", "checksum", 1, 1, RRD_ALGORITHM_INCREMENTAL);
  257. }
  258. else
  259. rrdset_next(st_ip_inerrors);
  260. rrddim_set_by_pointer(st_ip_inerrors, rd_noroutes, ipext_InNoRoutes);
  261. rrddim_set_by_pointer(st_ip_inerrors, rd_truncated, ipext_InTruncatedPkts);
  262. rrddim_set_by_pointer(st_ip_inerrors, rd_checksum, ipext_InCsumErrors);
  263. rrdset_done(st_ip_inerrors);
  264. }
  265. // --------------------------------------------------------------------
  266. if(do_mcast == CONFIG_BOOLEAN_YES || (do_mcast == CONFIG_BOOLEAN_AUTO && (ipext_InMcastOctets || ipext_OutMcastOctets))) {
  267. do_mcast = CONFIG_BOOLEAN_YES;
  268. static RRDSET *st_ip_mcast = NULL;
  269. static RRDDIM *rd_in = NULL, *rd_out = NULL;
  270. if(unlikely(!st_ip_mcast)) {
  271. st_ip_mcast = rrdset_create_localhost(
  272. RRD_TYPE_NET_NETSTAT
  273. , "mcast"
  274. , NULL
  275. , "multicast"
  276. , NULL
  277. , "IP Multicast Bandwidth"
  278. , "kilobits/s"
  279. , PLUGIN_PROC_NAME
  280. , PLUGIN_PROC_MODULE_NETSTAT_NAME
  281. , NETDATA_CHART_PRIO_IP_MCAST
  282. , update_every
  283. , RRDSET_TYPE_AREA
  284. );
  285. rrdset_flag_set(st_ip_mcast, RRDSET_FLAG_DETAIL);
  286. rd_in = rrddim_add(st_ip_mcast, "InMcastOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
  287. rd_out = rrddim_add(st_ip_mcast, "OutMcastOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
  288. }
  289. else
  290. rrdset_next(st_ip_mcast);
  291. rrddim_set_by_pointer(st_ip_mcast, rd_in, ipext_InMcastOctets);
  292. rrddim_set_by_pointer(st_ip_mcast, rd_out, ipext_OutMcastOctets);
  293. rrdset_done(st_ip_mcast);
  294. }
  295. // --------------------------------------------------------------------
  296. if(do_bcast == CONFIG_BOOLEAN_YES || (do_bcast == CONFIG_BOOLEAN_AUTO && (ipext_InBcastOctets || ipext_OutBcastOctets))) {
  297. do_bcast = CONFIG_BOOLEAN_YES;
  298. static RRDSET *st_ip_bcast = NULL;
  299. static RRDDIM *rd_in = NULL, *rd_out = NULL;
  300. if(unlikely(!st_ip_bcast)) {
  301. st_ip_bcast = rrdset_create_localhost(
  302. RRD_TYPE_NET_NETSTAT
  303. , "bcast"
  304. , NULL
  305. , "broadcast"
  306. , NULL
  307. , "IP Broadcast Bandwidth"
  308. , "kilobits/s"
  309. , PLUGIN_PROC_NAME
  310. , PLUGIN_PROC_MODULE_NETSTAT_NAME
  311. , NETDATA_CHART_PRIO_IP_BCAST
  312. , update_every
  313. , RRDSET_TYPE_AREA
  314. );
  315. rrdset_flag_set(st_ip_bcast, RRDSET_FLAG_DETAIL);
  316. rd_in = rrddim_add(st_ip_bcast, "InBcastOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
  317. rd_out = rrddim_add(st_ip_bcast, "OutBcastOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
  318. }
  319. else
  320. rrdset_next(st_ip_bcast);
  321. rrddim_set_by_pointer(st_ip_bcast, rd_in, ipext_InBcastOctets);
  322. rrddim_set_by_pointer(st_ip_bcast, rd_out, ipext_OutBcastOctets);
  323. rrdset_done(st_ip_bcast);
  324. }
  325. // --------------------------------------------------------------------
  326. if(do_mcast_p == CONFIG_BOOLEAN_YES || (do_mcast_p == CONFIG_BOOLEAN_AUTO && (ipext_InMcastPkts || ipext_OutMcastPkts))) {
  327. do_mcast_p = CONFIG_BOOLEAN_YES;
  328. static RRDSET *st_ip_mcastpkts = NULL;
  329. static RRDDIM *rd_in = NULL, *rd_out = NULL;
  330. if(unlikely(!st_ip_mcastpkts)) {
  331. st_ip_mcastpkts = rrdset_create_localhost(
  332. RRD_TYPE_NET_NETSTAT
  333. , "mcastpkts"
  334. , NULL
  335. , "multicast"
  336. , NULL
  337. , "IP Multicast Packets"
  338. , "packets/s"
  339. , PLUGIN_PROC_NAME
  340. , PLUGIN_PROC_MODULE_NETSTAT_NAME
  341. , NETDATA_CHART_PRIO_IP_MCAST_PACKETS
  342. , update_every
  343. , RRDSET_TYPE_LINE
  344. );
  345. rrdset_flag_set(st_ip_mcastpkts, RRDSET_FLAG_DETAIL);
  346. rd_in = rrddim_add(st_ip_mcastpkts, "InMcastPkts", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
  347. rd_out = rrddim_add(st_ip_mcastpkts, "OutMcastPkts", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL);
  348. }
  349. else rrdset_next(st_ip_mcastpkts);
  350. rrddim_set_by_pointer(st_ip_mcastpkts, rd_in, ipext_InMcastPkts);
  351. rrddim_set_by_pointer(st_ip_mcastpkts, rd_out, ipext_OutMcastPkts);
  352. rrdset_done(st_ip_mcastpkts);
  353. }
  354. // --------------------------------------------------------------------
  355. if(do_bcast_p == CONFIG_BOOLEAN_YES || (do_bcast_p == CONFIG_BOOLEAN_AUTO && (ipext_InBcastPkts || ipext_OutBcastPkts))) {
  356. do_bcast_p = CONFIG_BOOLEAN_YES;
  357. static RRDSET *st_ip_bcastpkts = NULL;
  358. static RRDDIM *rd_in = NULL, *rd_out = NULL;
  359. if(unlikely(!st_ip_bcastpkts)) {
  360. st_ip_bcastpkts = rrdset_create_localhost(
  361. RRD_TYPE_NET_NETSTAT
  362. , "bcastpkts"
  363. , NULL
  364. , "broadcast"
  365. , NULL
  366. , "IP Broadcast Packets"
  367. , "packets/s"
  368. , PLUGIN_PROC_NAME
  369. , PLUGIN_PROC_MODULE_NETSTAT_NAME
  370. , NETDATA_CHART_PRIO_IP_BCAST_PACKETS
  371. , update_every
  372. , RRDSET_TYPE_LINE
  373. );
  374. rrdset_flag_set(st_ip_bcastpkts, RRDSET_FLAG_DETAIL);
  375. rd_in = rrddim_add(st_ip_bcastpkts, "InBcastPkts", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
  376. rd_out = rrddim_add(st_ip_bcastpkts, "OutBcastPkts", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL);
  377. }
  378. else
  379. rrdset_next(st_ip_bcastpkts);
  380. rrddim_set_by_pointer(st_ip_bcastpkts, rd_in, ipext_InBcastPkts);
  381. rrddim_set_by_pointer(st_ip_bcastpkts, rd_out, ipext_OutBcastPkts);
  382. rrdset_done(st_ip_bcastpkts);
  383. }
  384. // --------------------------------------------------------------------
  385. if(do_ecn == CONFIG_BOOLEAN_YES || (do_ecn == CONFIG_BOOLEAN_AUTO && (ipext_InCEPkts || ipext_InECT0Pkts || ipext_InECT1Pkts || ipext_InNoECTPkts))) {
  386. do_ecn = CONFIG_BOOLEAN_YES;
  387. static RRDSET *st_ecnpkts = NULL;
  388. static RRDDIM *rd_cep = NULL, *rd_noectp = NULL, *rd_ectp0 = NULL, *rd_ectp1 = NULL;
  389. if(unlikely(!st_ecnpkts)) {
  390. st_ecnpkts = rrdset_create_localhost(
  391. RRD_TYPE_NET_NETSTAT
  392. , "ecnpkts"
  393. , NULL
  394. , "ecn"
  395. , NULL
  396. , "IP ECN Statistics"
  397. , "packets/s"
  398. , PLUGIN_PROC_NAME
  399. , PLUGIN_PROC_MODULE_NETSTAT_NAME
  400. , NETDATA_CHART_PRIO_IP_ECN
  401. , update_every
  402. , RRDSET_TYPE_LINE
  403. );
  404. rrdset_flag_set(st_ecnpkts, RRDSET_FLAG_DETAIL);
  405. rd_cep = rrddim_add(st_ecnpkts, "InCEPkts", "CEP", 1, 1, RRD_ALGORITHM_INCREMENTAL);
  406. rd_noectp = rrddim_add(st_ecnpkts, "InNoECTPkts", "NoECTP", -1, 1, RRD_ALGORITHM_INCREMENTAL);
  407. rd_ectp0 = rrddim_add(st_ecnpkts, "InECT0Pkts", "ECTP0", 1, 1, RRD_ALGORITHM_INCREMENTAL);
  408. rd_ectp1 = rrddim_add(st_ecnpkts, "InECT1Pkts", "ECTP1", 1, 1, RRD_ALGORITHM_INCREMENTAL);
  409. }
  410. else rrdset_next(st_ecnpkts);
  411. rrddim_set_by_pointer(st_ecnpkts, rd_cep, ipext_InCEPkts);
  412. rrddim_set_by_pointer(st_ecnpkts, rd_noectp, ipext_InNoECTPkts);
  413. rrddim_set_by_pointer(st_ecnpkts, rd_ectp0, ipext_InECT0Pkts);
  414. rrddim_set_by_pointer(st_ecnpkts, rd_ectp1, ipext_InECT1Pkts);
  415. rrdset_done(st_ecnpkts);
  416. }
  417. }
  418. else if(unlikely(hash == hash_tcpext && strcmp(key, "TcpExt") == 0)) {
  419. size_t h = l++;
  420. words = procfile_linewords(ff, l);
  421. if(unlikely(words < 2)) {
  422. error("Cannot read /proc/net/netstat TcpExt line. Expected 2+ params, read %zu.", words);
  423. continue;
  424. }
  425. parse_line_pair(ff, arl_tcpext, h, l);
  426. // --------------------------------------------------------------------
  427. if(do_tcpext_memory == CONFIG_BOOLEAN_YES || (do_tcpext_memory == CONFIG_BOOLEAN_AUTO && (tcpext_TCPMemoryPressures))) {
  428. do_tcpext_memory = CONFIG_BOOLEAN_YES;
  429. static RRDSET *st_tcpmemorypressures = NULL;
  430. static RRDDIM *rd_pressures = NULL;
  431. if(unlikely(!st_tcpmemorypressures)) {
  432. st_tcpmemorypressures = rrdset_create_localhost(
  433. RRD_TYPE_NET_NETSTAT
  434. , "tcpmemorypressures"
  435. , NULL
  436. , "tcp"
  437. , NULL
  438. , "TCP Memory Pressures"
  439. , "events/s"
  440. , PLUGIN_PROC_NAME
  441. , PLUGIN_PROC_MODULE_NETSTAT_NAME
  442. , NETDATA_CHART_PRIO_IP_TCP_MEM
  443. , update_every
  444. , RRDSET_TYPE_LINE
  445. );
  446. rd_pressures = rrddim_add(st_tcpmemorypressures, "TCPMemoryPressures", "pressures", 1, 1, RRD_ALGORITHM_INCREMENTAL);
  447. }
  448. else
  449. rrdset_next(st_tcpmemorypressures);
  450. rrddim_set_by_pointer(st_tcpmemorypressures, rd_pressures, tcpext_TCPMemoryPressures);
  451. rrdset_done(st_tcpmemorypressures);
  452. }
  453. // --------------------------------------------------------------------
  454. if(do_tcpext_connaborts == CONFIG_BOOLEAN_YES || (do_tcpext_connaborts == CONFIG_BOOLEAN_AUTO && (tcpext_TCPAbortOnData || tcpext_TCPAbortOnClose || tcpext_TCPAbortOnMemory || tcpext_TCPAbortOnTimeout || tcpext_TCPAbortOnLinger || tcpext_TCPAbortFailed))) {
  455. do_tcpext_connaborts = CONFIG_BOOLEAN_YES;
  456. static RRDSET *st_tcpconnaborts = NULL;
  457. static RRDDIM *rd_baddata = NULL, *rd_userclosed = NULL, *rd_nomemory = NULL, *rd_timeout = NULL, *rd_linger = NULL, *rd_failed = NULL;
  458. if(unlikely(!st_tcpconnaborts)) {
  459. st_tcpconnaborts = rrdset_create_localhost(
  460. RRD_TYPE_NET_NETSTAT
  461. , "tcpconnaborts"
  462. , NULL
  463. , "tcp"
  464. , NULL
  465. , "TCP Connection Aborts"
  466. , "connections/s"
  467. , PLUGIN_PROC_NAME
  468. , PLUGIN_PROC_MODULE_NETSTAT_NAME
  469. , NETDATA_CHART_PRIO_IP_TCP_CONNABORTS
  470. , update_every
  471. , RRDSET_TYPE_LINE
  472. );
  473. rd_baddata = rrddim_add(st_tcpconnaborts, "TCPAbortOnData", "baddata", 1, 1, RRD_ALGORITHM_INCREMENTAL);
  474. rd_userclosed = rrddim_add(st_tcpconnaborts, "TCPAbortOnClose", "userclosed", 1, 1, RRD_ALGORITHM_INCREMENTAL);
  475. rd_nomemory = rrddim_add(st_tcpconnaborts, "TCPAbortOnMemory", "nomemory", 1, 1, RRD_ALGORITHM_INCREMENTAL);
  476. rd_timeout = rrddim_add(st_tcpconnaborts, "TCPAbortOnTimeout", "timeout", 1, 1, RRD_ALGORITHM_INCREMENTAL);
  477. rd_linger = rrddim_add(st_tcpconnaborts, "TCPAbortOnLinger", "linger", 1, 1, RRD_ALGORITHM_INCREMENTAL);
  478. rd_failed = rrddim_add(st_tcpconnaborts, "TCPAbortFailed", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL);
  479. }
  480. else
  481. rrdset_next(st_tcpconnaborts);
  482. rrddim_set_by_pointer(st_tcpconnaborts, rd_baddata, tcpext_TCPAbortOnData);
  483. rrddim_set_by_pointer(st_tcpconnaborts, rd_userclosed, tcpext_TCPAbortOnClose);
  484. rrddim_set_by_pointer(st_tcpconnaborts, rd_nomemory, tcpext_TCPAbortOnMemory);
  485. rrddim_set_by_pointer(st_tcpconnaborts, rd_timeout, tcpext_TCPAbortOnTimeout);
  486. rrddim_set_by_pointer(st_tcpconnaborts, rd_linger, tcpext_TCPAbortOnLinger);
  487. rrddim_set_by_pointer(st_tcpconnaborts, rd_failed, tcpext_TCPAbortFailed);
  488. rrdset_done(st_tcpconnaborts);
  489. }
  490. // --------------------------------------------------------------------
  491. if(do_tcpext_reorder == CONFIG_BOOLEAN_YES || (do_tcpext_reorder == CONFIG_BOOLEAN_AUTO && (tcpext_TCPRenoReorder || tcpext_TCPFACKReorder || tcpext_TCPSACKReorder || tcpext_TCPTSReorder))) {
  492. do_tcpext_reorder = CONFIG_BOOLEAN_YES;
  493. static RRDSET *st_tcpreorders = NULL;
  494. static RRDDIM *rd_timestamp = NULL, *rd_sack = NULL, *rd_fack = NULL, *rd_reno = NULL;
  495. if(unlikely(!st_tcpreorders)) {
  496. st_tcpreorders = rrdset_create_localhost(
  497. RRD_TYPE_NET_NETSTAT
  498. , "tcpreorders"
  499. , NULL
  500. , "tcp"
  501. , NULL
  502. , "TCP Reordered Packets by Detection Method"
  503. , "packets/s"
  504. , PLUGIN_PROC_NAME
  505. , PLUGIN_PROC_MODULE_NETSTAT_NAME
  506. , NETDATA_CHART_PRIO_IP_TCP_REORDERS
  507. , update_every
  508. , RRDSET_TYPE_LINE
  509. );
  510. rd_timestamp = rrddim_add(st_tcpreorders, "TCPTSReorder", "timestamp", 1, 1, RRD_ALGORITHM_INCREMENTAL);
  511. rd_sack = rrddim_add(st_tcpreorders, "TCPSACKReorder", "sack", 1, 1, RRD_ALGORITHM_INCREMENTAL);
  512. rd_fack = rrddim_add(st_tcpreorders, "TCPFACKReorder", "fack", 1, 1, RRD_ALGORITHM_INCREMENTAL);
  513. rd_reno = rrddim_add(st_tcpreorders, "TCPRenoReorder", "reno", 1, 1, RRD_ALGORITHM_INCREMENTAL);
  514. }
  515. else
  516. rrdset_next(st_tcpreorders);
  517. rrddim_set_by_pointer(st_tcpreorders, rd_timestamp, tcpext_TCPTSReorder);
  518. rrddim_set_by_pointer(st_tcpreorders, rd_sack, tcpext_TCPSACKReorder);
  519. rrddim_set_by_pointer(st_tcpreorders, rd_fack, tcpext_TCPFACKReorder);
  520. rrddim_set_by_pointer(st_tcpreorders, rd_reno, tcpext_TCPRenoReorder);
  521. rrdset_done(st_tcpreorders);
  522. }
  523. // --------------------------------------------------------------------
  524. if(do_tcpext_ofo == CONFIG_BOOLEAN_YES || (do_tcpext_ofo == CONFIG_BOOLEAN_AUTO && (tcpext_TCPOFOQueue || tcpext_TCPOFODrop || tcpext_TCPOFOMerge))) {
  525. do_tcpext_ofo = CONFIG_BOOLEAN_YES;
  526. static RRDSET *st_ip_tcpofo = NULL;
  527. static RRDDIM *rd_inqueue = NULL, *rd_dropped = NULL, *rd_merged = NULL, *rd_pruned = NULL;
  528. if(unlikely(!st_ip_tcpofo)) {
  529. st_ip_tcpofo = rrdset_create_localhost(
  530. RRD_TYPE_NET_NETSTAT
  531. , "tcpofo"
  532. , NULL
  533. , "tcp"
  534. , NULL
  535. , "TCP Out-Of-Order Queue"
  536. , "packets/s"
  537. , PLUGIN_PROC_NAME
  538. , PLUGIN_PROC_MODULE_NETSTAT_NAME
  539. , NETDATA_CHART_PRIO_IP_TCP_OFO
  540. , update_every
  541. , RRDSET_TYPE_LINE
  542. );
  543. rd_inqueue = rrddim_add(st_ip_tcpofo, "TCPOFOQueue", "inqueue", 1, 1, RRD_ALGORITHM_INCREMENTAL);
  544. rd_dropped = rrddim_add(st_ip_tcpofo, "TCPOFODrop", "dropped", -1, 1, RRD_ALGORITHM_INCREMENTAL);
  545. rd_merged = rrddim_add(st_ip_tcpofo, "TCPOFOMerge", "merged", 1, 1, RRD_ALGORITHM_INCREMENTAL);
  546. rd_pruned = rrddim_add(st_ip_tcpofo, "OfoPruned", "pruned", -1, 1, RRD_ALGORITHM_INCREMENTAL);
  547. }
  548. else
  549. rrdset_next(st_ip_tcpofo);
  550. rrddim_set_by_pointer(st_ip_tcpofo, rd_inqueue, tcpext_TCPOFOQueue);
  551. rrddim_set_by_pointer(st_ip_tcpofo, rd_dropped, tcpext_TCPOFODrop);
  552. rrddim_set_by_pointer(st_ip_tcpofo, rd_merged, tcpext_TCPOFOMerge);
  553. rrddim_set_by_pointer(st_ip_tcpofo, rd_pruned, tcpext_OfoPruned);
  554. rrdset_done(st_ip_tcpofo);
  555. }
  556. // --------------------------------------------------------------------
  557. if(do_tcpext_syscookies == CONFIG_BOOLEAN_YES || (do_tcpext_syscookies == CONFIG_BOOLEAN_AUTO && (tcpext_SyncookiesSent || tcpext_SyncookiesRecv || tcpext_SyncookiesFailed))) {
  558. do_tcpext_syscookies = CONFIG_BOOLEAN_YES;
  559. static RRDSET *st_syncookies = NULL;
  560. static RRDDIM *rd_received = NULL, *rd_sent = NULL, *rd_failed = NULL;
  561. if(unlikely(!st_syncookies)) {
  562. st_syncookies = rrdset_create_localhost(
  563. RRD_TYPE_NET_NETSTAT
  564. , "tcpsyncookies"
  565. , NULL
  566. , "tcp"
  567. , NULL
  568. , "TCP SYN Cookies"
  569. , "packets/s"
  570. , PLUGIN_PROC_NAME
  571. , PLUGIN_PROC_MODULE_NETSTAT_NAME
  572. , NETDATA_CHART_PRIO_IP_TCP_SYNCOOKIES
  573. , update_every
  574. , RRDSET_TYPE_LINE
  575. );
  576. rd_received = rrddim_add(st_syncookies, "SyncookiesRecv", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
  577. rd_sent = rrddim_add(st_syncookies, "SyncookiesSent", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL);
  578. rd_failed = rrddim_add(st_syncookies, "SyncookiesFailed", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL);
  579. }
  580. else
  581. rrdset_next(st_syncookies);
  582. rrddim_set_by_pointer(st_syncookies, rd_received, tcpext_SyncookiesRecv);
  583. rrddim_set_by_pointer(st_syncookies, rd_sent, tcpext_SyncookiesSent);
  584. rrddim_set_by_pointer(st_syncookies, rd_failed, tcpext_SyncookiesFailed);
  585. rrdset_done(st_syncookies);
  586. }
  587. // --------------------------------------------------------------------
  588. if(do_tcpext_syn_queue == CONFIG_BOOLEAN_YES || (do_tcpext_syn_queue == CONFIG_BOOLEAN_AUTO && (tcpext_TCPReqQFullDrop || tcpext_TCPReqQFullDoCookies))) {
  589. do_tcpext_syn_queue = CONFIG_BOOLEAN_YES;
  590. static RRDSET *st_syn_queue = NULL;
  591. static RRDDIM
  592. *rd_TCPReqQFullDrop = NULL,
  593. *rd_TCPReqQFullDoCookies = NULL;
  594. if(unlikely(!st_syn_queue)) {
  595. st_syn_queue = rrdset_create_localhost(
  596. RRD_TYPE_NET_NETSTAT
  597. , "tcp_syn_queue"
  598. , NULL
  599. , "tcp"
  600. , NULL
  601. , "TCP SYN Queue Issues"
  602. , "packets/s"
  603. , PLUGIN_PROC_NAME
  604. , PLUGIN_PROC_MODULE_NETSTAT_NAME
  605. , NETDATA_CHART_PRIO_IP_TCP_SYN_QUEUE
  606. , update_every
  607. , RRDSET_TYPE_LINE
  608. );
  609. rd_TCPReqQFullDrop = rrddim_add(st_syn_queue, "TCPReqQFullDrop", "drops", 1, 1, RRD_ALGORITHM_INCREMENTAL);
  610. rd_TCPReqQFullDoCookies = rrddim_add(st_syn_queue, "TCPReqQFullDoCookies", "cookies", 1, 1, RRD_ALGORITHM_INCREMENTAL);
  611. }
  612. else
  613. rrdset_next(st_syn_queue);
  614. rrddim_set_by_pointer(st_syn_queue, rd_TCPReqQFullDrop, tcpext_TCPReqQFullDrop);
  615. rrddim_set_by_pointer(st_syn_queue, rd_TCPReqQFullDoCookies, tcpext_TCPReqQFullDoCookies);
  616. rrdset_done(st_syn_queue);
  617. }
  618. // --------------------------------------------------------------------
  619. if(do_tcpext_accept_queue == CONFIG_BOOLEAN_YES || (do_tcpext_accept_queue == CONFIG_BOOLEAN_AUTO && (tcpext_ListenOverflows || tcpext_ListenDrops))) {
  620. do_tcpext_accept_queue = CONFIG_BOOLEAN_YES;
  621. static RRDSET *st_accept_queue = NULL;
  622. static RRDDIM *rd_overflows = NULL,
  623. *rd_drops = NULL;
  624. if(unlikely(!st_accept_queue)) {
  625. st_accept_queue = rrdset_create_localhost(
  626. RRD_TYPE_NET_NETSTAT
  627. , "tcp_accept_queue"
  628. , NULL
  629. , "tcp"
  630. , NULL
  631. , "TCP Accept Queue Issues"
  632. , "packets/s"
  633. , PLUGIN_PROC_NAME
  634. , PLUGIN_PROC_MODULE_NETSTAT_NAME
  635. , NETDATA_CHART_PRIO_IP_TCP_ACCEPT_QUEUE
  636. , update_every
  637. , RRDSET_TYPE_LINE
  638. );
  639. rd_overflows = rrddim_add(st_accept_queue, "ListenOverflows", "overflows", 1, 1, RRD_ALGORITHM_INCREMENTAL);
  640. rd_drops = rrddim_add(st_accept_queue, "ListenDrops", "drops", 1, 1, RRD_ALGORITHM_INCREMENTAL);
  641. }
  642. else
  643. rrdset_next(st_accept_queue);
  644. rrddim_set_by_pointer(st_accept_queue, rd_overflows, tcpext_ListenOverflows);
  645. rrddim_set_by_pointer(st_accept_queue, rd_drops, tcpext_ListenDrops);
  646. rrdset_done(st_accept_queue);
  647. }
  648. }
  649. }
  650. return 0;
  651. }