master
c 1,085 lines 44 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "windows_plugin.h"
4 #include "windows-internals.h"
5
6 #define ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, counter) \
7 do { \
8 if ((p)->packets.counter.key) { \
9 packets += perflibGetObjectCounter((pDataBlock), (pObjectType), &(p)->packets.counter) ? 1 : 0; \
10 } \
11 } while (0)
12
13 #define SET_DIM_IF_KEY_AND_UPDATED(p, field) \
14 do { \
15 if ((p)->packets.field.key && (p)->packets.field.updated) { \
16 rrddim_set_by_pointer( \
17 (p)->packets.st, (p)->packets.rd_##field, (collected_number)(p)->packets.field.current.Data); \
18 } \
19 } while (0)
20
21 #define ADD_RRD_DIM_IF_KEY(packet_field, id, name, multiplier, algorithm) \
22 do { \
23 if (p->packets.packet_field.key) \
24 p->packets.rd_##packet_field = rrddim_add(st, id, name, multiplier, 1, algorithm); \
25 } while (0)
26
27 // --------------------------------------------------------------------------------------------------------------------
28 // network protocols
29
30 struct network_protocol {
31 const char *protocol;
32
33 struct {
34 COUNTER_DATA received;
35 COUNTER_DATA sent;
36 COUNTER_DATA delivered;
37 COUNTER_DATA forwarded;
38
39 COUNTER_DATA InDiscards;
40 COUNTER_DATA OutDiscards;
41 COUNTER_DATA InHdrErrors;
42 COUNTER_DATA InAddrErrors;
43 COUNTER_DATA InUnknownProtos;
44 COUNTER_DATA InTooBigErrors;
45 COUNTER_DATA InTruncatedPkts;
46 COUNTER_DATA InNoRoutes;
47 COUNTER_DATA OutNoRoutes;
48
49 COUNTER_DATA InEchoReps;
50 COUNTER_DATA OutEchoReps;
51 COUNTER_DATA InDestUnreachs;
52 COUNTER_DATA OutDestUnreachs;
53 COUNTER_DATA InRedirects;
54 COUNTER_DATA OutRedirects;
55 COUNTER_DATA InEchos;
56 COUNTER_DATA OutEchos;
57 COUNTER_DATA InRouterAdvert;
58 COUNTER_DATA OutRouterAdvert;
59 COUNTER_DATA InRouterSelect;
60 COUNTER_DATA OutRouterSelect;
61 COUNTER_DATA InTimeExcds;
62 COUNTER_DATA OutTimeExcds;
63 COUNTER_DATA InParmProbs;
64 COUNTER_DATA OutParmProbs;
65 COUNTER_DATA InTimestamps;
66 COUNTER_DATA OutTimestamps;
67 COUNTER_DATA InTimestampReps;
68 COUNTER_DATA OutTimestampReps;
69
70 RRDSET *st;
71 RRDDIM *rd_received;
72 RRDDIM *rd_sent;
73 RRDDIM *rd_forwarded;
74 RRDDIM *rd_delivered;
75
76 RRDDIM *rd_InDiscards;
77 RRDDIM *rd_OutDiscards;
78 RRDDIM *rd_InHdrErrors;
79 RRDDIM *rd_InAddrErrors;
80 RRDDIM *rd_InUnknownProtos;
81 RRDDIM *rd_InTooBigErrors;
82 RRDDIM *rd_InTruncatedPkts;
83 RRDDIM *rd_InNoRoutes;
84 RRDDIM *rd_OutNoRoutes;
85
86 RRDDIM *rd_InEchoReps;
87 RRDDIM *rd_OutEchoReps;
88 RRDDIM *rd_InDestUnreachs;
89 RRDDIM *rd_OutDestUnreachs;
90 RRDDIM *rd_InRedirects;
91 RRDDIM *rd_OutRedirects;
92 RRDDIM *rd_InEchos;
93 RRDDIM *rd_OutEchos;
94 RRDDIM *rd_InRouterAdvert;
95 RRDDIM *rd_OutRouterAdvert;
96 RRDDIM *rd_InRouterSelect;
97 RRDDIM *rd_OutRouterSelect;
98 RRDDIM *rd_InTimeExcds;
99 RRDDIM *rd_OutTimeExcds;
100 RRDDIM *rd_InParmProbs;
101 RRDDIM *rd_OutParmProbs;
102 RRDDIM *rd_InTimestamps;
103 RRDDIM *rd_OutTimestamps;
104 RRDDIM *rd_InTimestampReps;
105 RRDDIM *rd_OutTimestampReps;
106
107 const char *type;
108 const char *id;
109 const char *family;
110 const char *context;
111 const char *title;
112 long priority;
113 } packets;
114
115 } networks[] = {
116 {
117 .protocol = "IPv4",
118 .packets =
119 {
120 .received = {.key = "Datagrams Received/sec"},
121 .sent = {.key = "Datagrams Sent/sec"},
122 .delivered = {.key = "Datagrams Received Delivered/sec"},
123 .forwarded = {.key = "Datagrams Forwarded/sec"},
124 .type = "ipv4",
125 .id = "packets",
126 .family = "packets",
127 .context = "ipv4.packets",
128 .title = "IPv4 Packets",
129 .priority = NETDATA_CHART_PRIO_IPV4_PACKETS,
130 },
131 },
132 {
133 .protocol = "IPv6",
134 .packets =
135 {
136 .received = {.key = "Datagrams Received/sec"},
137 .sent = {.key = "Datagrams Sent/sec"},
138 .delivered = {.key = "Datagrams Received Delivered/sec"},
139 .forwarded = {.key = "Datagrams Forwarded/sec"},
140 .type = "ipv6",
141 .id = "packets",
142 .family = "packets",
143 .context = "ip6.packets",
144 .title = "IPv6 Packets",
145 .priority = NETDATA_CHART_PRIO_IPV6_PACKETS,
146 },
147 },
148 {
149 .protocol = "TCPv4",
150 .packets =
151 {
152 .received = {.key = "Segments Received/sec"},
153 .sent = {.key = "Segments Sent/sec"},
154 .type = "ipv4",
155 .id = "tcppackets",
156 .family = "tcp",
157 .context = "ipv4.tcppackets",
158 .title = "IPv4 TCP Packets",
159 .priority = NETDATA_CHART_PRIO_IPV4_TCP_PACKETS,
160 },
161 },
162 {
163 .protocol = "TCPv6",
164 .packets =
165 {
166 .received = {.key = "Segments Received/sec"},
167 .sent = {.key = "Segments Sent/sec"},
168 .type = "ipv6",
169 .id = "tcppackets",
170 .family = "tcp6",
171 .context = "ipv6.tcppackets",
172 .title = "IPv6 TCP Packets",
173 .priority = NETDATA_CHART_PRIO_IPV6_TCP_PACKETS,
174 },
175 },
176 {
177 .protocol = "UDPv4",
178 .packets =
179 {
180 .received = {.key = "Datagrams Received/sec"},
181 .sent = {.key = "Datagrams Sent/sec"},
182 .type = "ipv4",
183 .id = "udppackets",
184 .family = "udp",
185 .context = "ipv4.udppackets",
186 .title = "IPv4 UDP Packets",
187 .priority = NETDATA_CHART_PRIO_IPV4_UDP_PACKETS,
188 },
189 },
190 {
191 .protocol = "UDPv6",
192 .packets =
193 {
194 .received = {.key = "Datagrams Received/sec"},
195 .sent = {.key = "Datagrams Sent/sec"},
196 .type = "ipv6",
197 .id = "udppackets",
198 .family = "udp6",
199 .context = "ipv6.udppackets",
200 .title = "IPv6 UDP Packets",
201 .priority = NETDATA_CHART_PRIO_IPV6_UDP_PACKETS,
202 },
203 },
204 {
205 .protocol = "ICMP",
206 .packets =
207 {
208 .received = {.key = "Messages Received/sec"},
209 .sent = {.key = "Messages Sent/sec"},
210 .type = "ipv4",
211 .id = "icmp",
212 .family = "icmp",
213 .context = "ipv4.icmp",
214 .title = "IPv4 ICMP Packets",
215 .priority = NETDATA_CHART_PRIO_IPV4_ICMP_PACKETS,
216 },
217 },
218 {
219 .protocol = "ICMPv6",
220 .packets =
221 {
222 .received = {.key = "Messages Received/sec"},
223 .sent = {.key = "Messages Sent/sec"},
224 .type = "ipv6",
225 .id = "icmp",
226 .family = "icmp6",
227 .context = "ipv6.icmp",
228 .title = "IPv6 ICMP Packets",
229 .priority = NETDATA_CHART_PRIO_IPV6_ICMP_PACKETS,
230 },
231 },
232
233 {
234 .protocol = "IPv4",
235 .packets =
236 {
237 .InDiscards = {.key = "Datagrams Received Discarded"},
238 .OutDiscards = {.key = "Datagrams Outbound Discarded"},
239 .OutNoRoutes = {.key = "Datagrams Outbound No Route"},
240 .InAddrErrors = {.key = "Datagrams Received Address Errors"},
241 .InHdrErrors = {.key = "Datagrams Received Header Errors"},
242 .InUnknownProtos = {.key = "Datagrams Received Unknown Protocol"},
243 .type = "ipv4",
244 .id = "errors",
245 .family = "errors",
246 .context = "ipv4.errors",
247 .title = "IPv4 errors",
248 .priority = NETDATA_CHART_PRIO_IPV4_ERRORS,
249 },
250 },
251 {
252 .protocol = "IPv6",
253 .packets =
254 {
255 .InDiscards = {.key = "Datagrams Received Discarded"},
256 .OutDiscards = {.key = "Datagrams Outbound Discarded"},
257 .OutNoRoutes = {.key = "Datagrams Outbound No Route"},
258 .InAddrErrors = {.key = "Datagrams Received Address Errors"},
259 .InHdrErrors = {.key = "Datagrams Received Header Errors"},
260 .InUnknownProtos = {.key = "Datagrams Received Unknown Protocol"},
261 .type = "ipv6",
262 .id = "errors",
263 .family = "errors",
264 .context = "ipv6.errors",
265 .title = "IPv6 errors",
266 .priority = NETDATA_CHART_PRIO_IPV6_ERRORS,
267 },
268 },
269 {
270 .protocol = "ICMP",
271 .packets =
272 {
273 .InEchoReps = {.key = "Received Echo Reply/sec"},
274 .OutEchoReps = {.key = "Sent Echo Reply/sec"},
275 .InDestUnreachs = {.key = "Received Dest. Unreachable"},
276 .OutDestUnreachs = {.key = "Sent Destination Unreachable"},
277 .InRedirects = {.key = "Received Redirect/sec"},
278 .OutRedirects = {.key = "Sent Redirect/sec"},
279 .InEchos = {.key = "Received Echo/sec"},
280 .OutEchos = {.key = "Sent Echo/sec"},
281 .InRouterAdvert = {.key = NULL},
282 .OutRouterAdvert = {.key = NULL},
283 .InRouterSelect = {.key = NULL},
284 .OutRouterSelect = {.key = NULL},
285 .InTimeExcds = {.key = "Received Time Exceeded"},
286 .OutTimeExcds = {.key = "Sent Time Exceeded"},
287 .InParmProbs = {.key = "Received Parameter Problem"},
288 .OutParmProbs = {.key = "Sent Parameter Problem"},
289 .InTimestamps = {.key = "Received Timestamp/sec"},
290 .OutTimestamps = {.key = "Sent Timestamp/sec"},
291 .InTimestampReps = {.key = "Received Timestamp Reply/sec"},
292 .OutTimestampReps = {.key = "Sent Timestamp Reply/sec"},
293
294 .type = "ipv4",
295 .id = "icmpmsg",
296 .family = "icmp",
297 .context = "ipv4.icmpmsg",
298 .title = "IPv4 ICMP Packets",
299 .priority = NETDATA_CHART_PRIO_IPV4_ICMP_MESSAGES,
300 },
301 },
302 {
303 .protocol = "ICMPv6",
304 .packets =
305 {
306 .InEchoReps = {.key = "Received Echo Reply/sec"},
307 .OutEchoReps = {.key = "Sent Echo Reply/sec"},
308 .InDestUnreachs = {.key = "Received Dest. Unreachable"},
309 .OutDestUnreachs = {.key = "Sent Destination Unreachable"},
310 .InRedirects = {.key = "Received Redirect/sec"},
311 .OutRedirects = {.key = "Sent Redirect/sec"},
312 .InEchos = {.key = "Received Echo/sec"},
313 .OutEchos = {.key = "Sent Echo/sec"},
314 .InRouterAdvert = {.key = NULL},
315 .OutRouterAdvert = {.key = NULL},
316 .InRouterSelect = {.key = NULL},
317 .OutRouterSelect = {.key = NULL},
318 .InTimeExcds = {.key = "Received Time Exceeded"},
319 .OutTimeExcds = {.key = "Sent Time Exceeded"},
320 .InParmProbs = {.key = "Received Parameter Problem"},
321 .OutParmProbs = {.key = "Sent Parameter Problem"},
322 .InTimestamps = {.key = "Received Timestamp/sec"},
323 .OutTimestamps = {.key = "Sent Timestamp/sec"},
324 .InTimestampReps = {.key = "Received Timestamp Reply/sec"},
325 .OutTimestampReps = {.key = "Sent Timestamp Reply/sec"},
326
327 .type = "ipv6",
328 .id = "icmpmsg",
329 .family = "icmp",
330 .context = "ipv6.icmpmsg",
331 .title = "IPv6 ICMP Packets",
332 .priority = NETDATA_CHART_PRIO_IPV6_ICMP_MESSAGES,
333 },
334 },
335
336 // terminator
337 {
338 .protocol = NULL,
339 }};
340
341 struct network_protocol tcp46 = {
342 .packets = {
343 .type = "ip",
344 .id = "tcppackets",
345 .family = "tcp",
346 .context = "ip.tcppackets",
347 .title = "TCP Packets",
348 .priority = NETDATA_CHART_PRIO_IP_TCP_PACKETS,
349 }};
350
351 static void protocol_packets_chart_update(struct network_protocol *p, int update_every)
352 {
353 if (!p->packets.st) {
354 p->packets.st = rrdset_create_localhost(
355 p->packets.type,
356 p->packets.id,
357 NULL,
358 p->packets.family,
359 NULL,
360 p->packets.title,
361 "packets/s",
362 PLUGIN_WINDOWS_NAME,
363 "PerflibNetwork",
364 p->packets.priority,
365 update_every,
366 RRDSET_TYPE_AREA);
367
368 RRDSET *st = p->packets.st;
369
370 ADD_RRD_DIM_IF_KEY(received, "received", NULL, 1, RRD_ALGORITHM_INCREMENTAL);
371 ADD_RRD_DIM_IF_KEY(sent, "sent", NULL, -1, RRD_ALGORITHM_INCREMENTAL);
372 ADD_RRD_DIM_IF_KEY(forwarded, "forwarded", NULL, -1, RRD_ALGORITHM_INCREMENTAL);
373 ADD_RRD_DIM_IF_KEY(delivered, "delivered", NULL, 1, RRD_ALGORITHM_INCREMENTAL);
374 ADD_RRD_DIM_IF_KEY(InDiscards, "InDiscards", NULL, 1, RRD_ALGORITHM_INCREMENTAL);
375 ADD_RRD_DIM_IF_KEY(OutDiscards, "OutDiscards", NULL, -1, RRD_ALGORITHM_INCREMENTAL);
376 ADD_RRD_DIM_IF_KEY(InHdrErrors, "InHdrErrors", NULL, 1, RRD_ALGORITHM_INCREMENTAL);
377 ADD_RRD_DIM_IF_KEY(InAddrErrors, "InAddrErrors", NULL, 1, RRD_ALGORITHM_INCREMENTAL);
378 ADD_RRD_DIM_IF_KEY(InUnknownProtos, "InUnknownProtos", NULL, 1, RRD_ALGORITHM_INCREMENTAL);
379 ADD_RRD_DIM_IF_KEY(InTooBigErrors, "InTooBigErrors", NULL, 1, RRD_ALGORITHM_INCREMENTAL);
380 ADD_RRD_DIM_IF_KEY(InTruncatedPkts, "InTruncatedPkts", NULL, 1, RRD_ALGORITHM_INCREMENTAL);
381 ADD_RRD_DIM_IF_KEY(InNoRoutes, "InNoRoutes", NULL, 1, RRD_ALGORITHM_INCREMENTAL);
382 ADD_RRD_DIM_IF_KEY(OutNoRoutes, "OutNoRoutes", NULL, -1, RRD_ALGORITHM_INCREMENTAL);
383 ADD_RRD_DIM_IF_KEY(InEchoReps, "InType0", "InEchoReps", 1, RRD_ALGORITHM_INCREMENTAL);
384 ADD_RRD_DIM_IF_KEY(OutEchoReps, "OutType0", "OutEchoReps", -1, RRD_ALGORITHM_INCREMENTAL);
385 ADD_RRD_DIM_IF_KEY(InDestUnreachs, "InType3", "InDestUnreachs", 1, RRD_ALGORITHM_INCREMENTAL);
386 ADD_RRD_DIM_IF_KEY(OutDestUnreachs, "OutType3", "OutDestUnreachs", -1, RRD_ALGORITHM_INCREMENTAL);
387 ADD_RRD_DIM_IF_KEY(InRedirects, "InType5", "InRedirects", 1, RRD_ALGORITHM_INCREMENTAL);
388 ADD_RRD_DIM_IF_KEY(OutRedirects, "OutType5", "OutRedirects", -1, RRD_ALGORITHM_INCREMENTAL);
389 ADD_RRD_DIM_IF_KEY(InEchos, "InType8", "InEchos", 1, RRD_ALGORITHM_INCREMENTAL);
390 ADD_RRD_DIM_IF_KEY(OutEchos, "OutType8", "OutEchos", -1, RRD_ALGORITHM_INCREMENTAL);
391 ADD_RRD_DIM_IF_KEY(InRouterAdvert, "InType9", "InRouterAdvert", 1, RRD_ALGORITHM_INCREMENTAL);
392 ADD_RRD_DIM_IF_KEY(OutRouterAdvert, "OutType9", "OutRouterAdvert", -1, RRD_ALGORITHM_INCREMENTAL);
393 ADD_RRD_DIM_IF_KEY(InRouterSelect, "InType10", "InRouterSelect", 1, RRD_ALGORITHM_INCREMENTAL);
394 ADD_RRD_DIM_IF_KEY(OutRouterSelect, "OutType10", "OutRouterSelect", -1, RRD_ALGORITHM_INCREMENTAL);
395 ADD_RRD_DIM_IF_KEY(InTimeExcds, "InType11", "InTimeExcds", 1, RRD_ALGORITHM_INCREMENTAL);
396 ADD_RRD_DIM_IF_KEY(OutTimeExcds, "OutType11", "OutTimeExcds", -1, RRD_ALGORITHM_INCREMENTAL);
397 ADD_RRD_DIM_IF_KEY(InParmProbs, "InType12", "InParmProbs", 1, RRD_ALGORITHM_INCREMENTAL);
398 ADD_RRD_DIM_IF_KEY(OutParmProbs, "OutType12", "OutParmProbs", -1, RRD_ALGORITHM_INCREMENTAL);
399 ADD_RRD_DIM_IF_KEY(InTimestamps, "InType13", "InTimestamps", 1, RRD_ALGORITHM_INCREMENTAL);
400 ADD_RRD_DIM_IF_KEY(OutTimestamps, "OutType13", "OutTimestamps", -1, RRD_ALGORITHM_INCREMENTAL);
401 ADD_RRD_DIM_IF_KEY(InTimestampReps, "InType14", "InTimestampReps", 1, RRD_ALGORITHM_INCREMENTAL);
402 ADD_RRD_DIM_IF_KEY(OutTimestampReps, "OutType14", "OutTimestampReps", -1, RRD_ALGORITHM_INCREMENTAL);
403 }
404
405 SET_DIM_IF_KEY_AND_UPDATED(p, received);
406 SET_DIM_IF_KEY_AND_UPDATED(p, sent);
407
408 SET_DIM_IF_KEY_AND_UPDATED(p, forwarded);
409 SET_DIM_IF_KEY_AND_UPDATED(p, delivered);
410 SET_DIM_IF_KEY_AND_UPDATED(p, InDiscards);
411 SET_DIM_IF_KEY_AND_UPDATED(p, OutDiscards);
412 SET_DIM_IF_KEY_AND_UPDATED(p, InHdrErrors);
413 SET_DIM_IF_KEY_AND_UPDATED(p, InAddrErrors);
414 SET_DIM_IF_KEY_AND_UPDATED(p, InUnknownProtos);
415 SET_DIM_IF_KEY_AND_UPDATED(p, InTooBigErrors);
416 SET_DIM_IF_KEY_AND_UPDATED(p, InTruncatedPkts);
417 SET_DIM_IF_KEY_AND_UPDATED(p, InNoRoutes);
418 SET_DIM_IF_KEY_AND_UPDATED(p, OutNoRoutes);
419 SET_DIM_IF_KEY_AND_UPDATED(p, InEchoReps);
420 SET_DIM_IF_KEY_AND_UPDATED(p, OutEchoReps);
421 SET_DIM_IF_KEY_AND_UPDATED(p, InDestUnreachs);
422 SET_DIM_IF_KEY_AND_UPDATED(p, OutDestUnreachs);
423 SET_DIM_IF_KEY_AND_UPDATED(p, InRedirects);
424 SET_DIM_IF_KEY_AND_UPDATED(p, OutRedirects);
425 SET_DIM_IF_KEY_AND_UPDATED(p, InEchos);
426 SET_DIM_IF_KEY_AND_UPDATED(p, OutEchos);
427 SET_DIM_IF_KEY_AND_UPDATED(p, InRouterAdvert);
428 SET_DIM_IF_KEY_AND_UPDATED(p, OutRouterAdvert);
429 SET_DIM_IF_KEY_AND_UPDATED(p, InRouterSelect);
430 SET_DIM_IF_KEY_AND_UPDATED(p, OutRouterSelect);
431 SET_DIM_IF_KEY_AND_UPDATED(p, InTimeExcds);
432 SET_DIM_IF_KEY_AND_UPDATED(p, OutTimeExcds);
433 SET_DIM_IF_KEY_AND_UPDATED(p, InParmProbs);
434 SET_DIM_IF_KEY_AND_UPDATED(p, OutParmProbs);
435 SET_DIM_IF_KEY_AND_UPDATED(p, InTimestamps);
436 SET_DIM_IF_KEY_AND_UPDATED(p, OutTimestamps);
437 SET_DIM_IF_KEY_AND_UPDATED(p, InTimestampReps);
438 SET_DIM_IF_KEY_AND_UPDATED(p, OutTimestampReps);
439
440 rrdset_done(p->packets.st);
441 }
442
443 static bool do_network_protocol(PERF_DATA_BLOCK *pDataBlock, int update_every, struct network_protocol *p)
444 {
445 if (!p || !p->protocol)
446 return false;
447
448 PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, p->protocol);
449 if (!pObjectType)
450 return false;
451
452 size_t packets = 0;
453 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, received);
454 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, sent);
455 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, delivered);
456 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, forwarded);
457
458 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, InDiscards);
459 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, OutDiscards);
460 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, InHdrErrors);
461 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, InAddrErrors);
462 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, InUnknownProtos);
463 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, InTooBigErrors);
464 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, InTruncatedPkts);
465 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, InNoRoutes);
466 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, OutNoRoutes);
467 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, InEchoReps);
468 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, OutEchoReps);
469 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, InDestUnreachs);
470 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, OutDestUnreachs);
471
472 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, InRedirects);
473 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, OutRedirects);
474 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, InEchos);
475 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, OutEchos);
476 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, InRouterAdvert);
477 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, OutRouterAdvert);
478 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, InRouterSelect);
479 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, OutRouterSelect);
480 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, InTimeExcds);
481 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, OutTimeExcds);
482 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, InParmProbs);
483 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, OutParmProbs);
484 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, InTimestamps);
485 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, OutTimestamps);
486 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, InTimestampReps);
487 ADD_PACKET_IF_KEY(p, packets, pDataBlock, pObjectType, OutTimestampReps);
488
489 if (packets)
490 protocol_packets_chart_update(p, update_every);
491
492 return true;
493 }
494
495 // --------------------------------------------------------------------------------------------------------------------
496 // network interfaces
497
498 struct network_interface {
499 usec_t last_collected;
500 bool collected_metadata;
501
502 struct {
503 COUNTER_DATA received;
504 COUNTER_DATA sent;
505
506 RRDSET *st;
507 RRDDIM *rd_received;
508 RRDDIM *rd_sent;
509 } packets;
510
511 struct {
512 const RRDVAR_ACQUIRED *chart_var_speed;
513
514 COUNTER_DATA received;
515 COUNTER_DATA sent;
516
517 RRDSET *st;
518 RRDDIM *rd_received;
519 RRDDIM *rd_sent;
520 } traffic;
521
522 struct {
523 COUNTER_DATA current_bandwidth;
524 RRDSET *st;
525 RRDDIM *rd;
526 } speed;
527
528 struct {
529 COUNTER_DATA received;
530 COUNTER_DATA outbound;
531
532 RRDSET *st;
533 RRDDIM *rd_received;
534 RRDDIM *rd_outbound;
535 } discards;
536
537 struct {
538 COUNTER_DATA received;
539 COUNTER_DATA outbound;
540
541 RRDSET *st;
542 RRDDIM *rd_received;
543 RRDDIM *rd_outbound;
544 } errors;
545
546 struct {
547 COUNTER_DATA length;
548 RRDSET *st;
549 RRDDIM *rd;
550 } queue;
551
552 struct {
553 COUNTER_DATA connections;
554 RRDSET *st;
555 RRDDIM *rd;
556 } chimney;
557
558 struct {
559 COUNTER_DATA connections;
560 COUNTER_DATA packets;
561 COUNTER_DATA exceptions;
562 COUNTER_DATA average_packet_size;
563
564 RRDSET *st_connections;
565 RRDDIM *rd_connections;
566
567 RRDSET *st_packets;
568 RRDDIM *rd_packets;
569
570 RRDSET *st_exceptions;
571 RRDDIM *rd_exceptions;
572
573 RRDSET *st_average_packet_size;
574 RRDDIM *rd_average_packet_size;
575 } rsc;
576 };
577
578 static DICTIONARY *physical_interfaces = NULL, *virtual_interfaces = NULL;
579
580 static void network_interface_init(struct network_interface *d)
581 {
582 d->packets.received.key = "Packets Received/sec";
583 d->packets.sent.key = "Packets Sent/sec";
584 d->traffic.received.key = "Bytes Received/sec";
585 d->traffic.sent.key = "Bytes Sent/sec";
586 d->speed.current_bandwidth.key = "Current Bandwidth";
587 d->discards.received.key = "Packets Received Discarded";
588 d->discards.outbound.key = "Packets Outbound Discarded";
589 d->errors.received.key = "Packets Received Errors";
590 d->errors.outbound.key = "Packets Outbound Errors";
591 d->queue.length.key = "Output Queue Length";
592 d->chimney.connections.key = "Offloaded Connections";
593 d->rsc.connections.key = "TCP Active RSC Connections";
594 d->rsc.packets.key = "TCP RSC Coalesced Packets/sec";
595 d->rsc.exceptions.key = "TCP RSC Exceptions/sec";
596 d->rsc.average_packet_size.key = "TCP RSC Average Packet Size";
597 }
598
599 static void network_interface_cleanup(struct network_interface *d)
600 {
601 rrdvar_chart_variable_release(d->traffic.st, d->traffic.chart_var_speed);
602 d->traffic.chart_var_speed = NULL;
603 rrdset_is_obsolete___safe_from_collector_thread(d->packets.st);
604 rrdset_is_obsolete___safe_from_collector_thread(d->traffic.st);
605 rrdset_is_obsolete___safe_from_collector_thread(d->speed.st);
606 rrdset_is_obsolete___safe_from_collector_thread(d->discards.st);
607 rrdset_is_obsolete___safe_from_collector_thread(d->errors.st);
608 rrdset_is_obsolete___safe_from_collector_thread(d->queue.st);
609 rrdset_is_obsolete___safe_from_collector_thread(d->chimney.st);
610 rrdset_is_obsolete___safe_from_collector_thread(d->rsc.st_connections);
611 rrdset_is_obsolete___safe_from_collector_thread(d->rsc.st_packets);
612 rrdset_is_obsolete___safe_from_collector_thread(d->rsc.st_exceptions);
613 rrdset_is_obsolete___safe_from_collector_thread(d->rsc.st_average_packet_size);
614 }
615
616 void dict_interface_insert_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
617 {
618 struct network_interface *ni = value;
619 network_interface_init(ni);
620 }
621
622 static void initialize(void)
623 {
624 physical_interfaces = dictionary_create_advanced(
625 DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct network_interface));
626
627 virtual_interfaces = dictionary_create_advanced(
628 DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct network_interface));
629
630 dictionary_register_insert_callback(physical_interfaces, dict_interface_insert_cb, NULL);
631 dictionary_register_insert_callback(virtual_interfaces, dict_interface_insert_cb, NULL);
632 }
633
634 static void add_interface_labels(RRDSET *st, const char *name, bool physical)
635 {
636 rrdlabels_add(st->rrdlabels, "device", name, RRDLABEL_SRC_AUTO);
637 rrdlabels_add(st->rrdlabels, "interface_type", physical ? "real" : "virtual", RRDLABEL_SRC_AUTO);
638 }
639
640 static bool is_physical_interface(const char *name)
641 {
642 void *d = dictionary_get(physical_interfaces, name);
643 return d ? true : false;
644 }
645
646 static bool do_network_interface(PERF_DATA_BLOCK *pDataBlock, int update_every, bool physical, usec_t now_ut)
647 {
648 DICTIONARY *dict = physical ? physical_interfaces : virtual_interfaces;
649
650 PERF_OBJECT_TYPE *pObjectType =
651 perflibFindObjectTypeByName(pDataBlock, physical ? "Network Interface" : "Network Adapter");
652 if (!pObjectType)
653 return false;
654
655 uint64_t total_received = 0, total_sent = 0;
656
657 PERF_INSTANCE_DEFINITION *pi = NULL;
658 for (LONG i = 0; i < pObjectType->NumInstances; i++) {
659 pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
660 if (!pi)
661 break;
662
663 if (!getInstanceName(pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer)))
664 strncpyz(windows_shared_buffer, "[unknown]", sizeof(windows_shared_buffer) - 1);
665
666 if (strcasecmp(windows_shared_buffer, "_Total") == 0)
667 continue;
668
669 if (!physical && is_physical_interface(windows_shared_buffer))
670 // this virtual interface is already reported as physical interface
671 continue;
672
673 struct network_interface *d = dictionary_set(dict, windows_shared_buffer, NULL, sizeof(*d));
674 d->last_collected = now_ut;
675
676 if (!d->collected_metadata) {
677 // TODO - get metadata about the network interface
678 d->collected_metadata = true;
679 }
680
681 if (perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &d->traffic.received) &&
682 perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &d->traffic.sent)) {
683 if (d->traffic.received.current.Data == 0 && d->traffic.sent.current.Data == 0)
684 // this interface has not received or sent any traffic yet
685 continue;
686
687 if (unlikely(!d->traffic.st)) {
688 d->traffic.st = rrdset_create_localhost(
689 "net",
690 windows_shared_buffer,
691 NULL,
692 windows_shared_buffer,
693 "net.net",
694 "Bandwidth",
695 "kilobits/s",
696 PLUGIN_WINDOWS_NAME,
697 "PerflibNetwork",
698 NETDATA_CHART_PRIO_FIRST_NET_IFACE,
699 update_every,
700 RRDSET_TYPE_AREA);
701
702 add_interface_labels(d->traffic.st, windows_shared_buffer, physical);
703
704 d->traffic.rd_received =
705 rrddim_add(d->traffic.st, "received", NULL, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
706 d->traffic.rd_sent =
707 rrddim_add(d->traffic.st, "sent", NULL, -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
708
709 d->traffic.chart_var_speed = rrdvar_chart_variable_add_and_acquire(d->traffic.st, "nic_speed_max");
710 rrdvar_chart_variable_set(d->traffic.st, d->traffic.chart_var_speed, NAN);
711 }
712
713 total_received += d->traffic.received.current.Data;
714 total_sent += d->traffic.sent.current.Data;
715
716 rrddim_set_by_pointer(
717 d->traffic.st, d->traffic.rd_received, (collected_number)d->traffic.received.current.Data);
718 rrddim_set_by_pointer(d->traffic.st, d->traffic.rd_sent, (collected_number)d->traffic.sent.current.Data);
719 rrdset_done(d->traffic.st);
720 }
721
722 if (perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &d->packets.received) &&
723 perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &d->packets.sent)) {
724 if (unlikely(!d->packets.st)) {
725 d->packets.st = rrdset_create_localhost(
726 "net_packets",
727 windows_shared_buffer,
728 NULL,
729 windows_shared_buffer,
730 "net.packets",
731 "Packets",
732 "packets/s",
733 PLUGIN_WINDOWS_NAME,
734 "PerflibNetwork",
735 NETDATA_CHART_PRIO_FIRST_NET_IFACE + 1,
736 update_every,
737 RRDSET_TYPE_LINE);
738
739 add_interface_labels(d->packets.st, windows_shared_buffer, physical);
740
741 d->packets.rd_received = rrddim_add(d->packets.st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
742 d->packets.rd_sent = rrddim_add(d->packets.st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
743 }
744
745 rrddim_set_by_pointer(
746 d->packets.st, d->packets.rd_received, (collected_number)d->packets.received.current.Data);
747 rrddim_set_by_pointer(d->packets.st, d->packets.rd_sent, (collected_number)d->packets.sent.current.Data);
748 rrdset_done(d->packets.st);
749 }
750
751 if (perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &d->speed.current_bandwidth)) {
752 if (unlikely(!d->speed.st)) {
753 d->speed.st = rrdset_create_localhost(
754 "net_speed",
755 windows_shared_buffer,
756 NULL,
757 windows_shared_buffer,
758 "net.speed",
759 "Interface Speed",
760 "kilobits/s",
761 PLUGIN_WINDOWS_NAME,
762 "PerflibNetwork",
763 NETDATA_CHART_PRIO_FIRST_NET_IFACE + 10,
764 update_every,
765 RRDSET_TYPE_LINE);
766
767 add_interface_labels(d->speed.st, windows_shared_buffer, physical);
768
769 d->speed.rd = rrddim_add(d->speed.st, "speed", NULL, 1, BITS_IN_A_KILOBIT, RRD_ALGORITHM_ABSOLUTE);
770 }
771
772 rrddim_set_by_pointer(d->speed.st, d->speed.rd, (collected_number)d->speed.current_bandwidth.current.Data);
773 rrdset_done(d->speed.st);
774
775 rrdvar_chart_variable_set(
776 d->traffic.st,
777 d->traffic.chart_var_speed,
778 (NETDATA_DOUBLE)d->speed.current_bandwidth.current.Data / BITS_IN_A_KILOBIT);
779 }
780
781 if (perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &d->errors.received) &&
782 perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &d->errors.outbound)) {
783 if (unlikely(!d->errors.st)) {
784 d->errors.st = rrdset_create_localhost(
785 "net_errors",
786 windows_shared_buffer,
787 NULL,
788 windows_shared_buffer,
789 "net.errors",
790 "Interface Errors",
791 "errors/s",
792 PLUGIN_WINDOWS_NAME,
793 "PerflibNetwork",
794 NETDATA_CHART_PRIO_FIRST_NET_IFACE + 3,
795 update_every,
796 RRDSET_TYPE_LINE);
797
798 add_interface_labels(d->errors.st, windows_shared_buffer, physical);
799
800 d->errors.rd_received = rrddim_add(d->errors.st, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
801 d->errors.rd_outbound = rrddim_add(d->errors.st, "outbound", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
802 }
803
804 rrddim_set_by_pointer(
805 d->errors.st, d->errors.rd_received, (collected_number)d->errors.received.current.Data);
806 rrddim_set_by_pointer(
807 d->errors.st, d->errors.rd_outbound, (collected_number)d->errors.outbound.current.Data);
808 rrdset_done(d->errors.st);
809 }
810
811 if (perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &d->discards.received) &&
812 perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &d->discards.outbound)) {
813 if (unlikely(!d->discards.st)) {
814 d->discards.st = rrdset_create_localhost(
815 "net_drops",
816 windows_shared_buffer,
817 NULL,
818 windows_shared_buffer,
819 "net.drops",
820 "Interface Drops",
821 "drops/s",
822 PLUGIN_WINDOWS_NAME,
823 "PerflibNetwork",
824 NETDATA_CHART_PRIO_FIRST_NET_IFACE + 4,
825 update_every,
826 RRDSET_TYPE_LINE);
827
828 add_interface_labels(d->discards.st, windows_shared_buffer, physical);
829
830 d->discards.rd_received = rrddim_add(d->discards.st, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
831 d->discards.rd_outbound =
832 rrddim_add(d->discards.st, "outbound", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
833 }
834
835 rrddim_set_by_pointer(
836 d->discards.st, d->discards.rd_received, (collected_number)d->discards.received.current.Data);
837 rrddim_set_by_pointer(
838 d->discards.st, d->discards.rd_outbound, (collected_number)d->discards.outbound.current.Data);
839 rrdset_done(d->discards.st);
840 }
841
842 if (perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &d->queue.length)) {
843 if (unlikely(!d->queue.st)) {
844 d->queue.st = rrdset_create_localhost(
845 "net_queue_length",
846 windows_shared_buffer,
847 NULL,
848 windows_shared_buffer,
849 "net.queue_length",
850 "Interface Output Queue Length",
851 "packets",
852 PLUGIN_WINDOWS_NAME,
853 "PerflibNetwork",
854 NETDATA_CHART_PRIO_FIRST_NET_IFACE + 5,
855 update_every,
856 RRDSET_TYPE_LINE);
857
858 add_interface_labels(d->queue.st, windows_shared_buffer, physical);
859
860 d->queue.rd = rrddim_add(d->queue.st, "length", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
861 }
862
863 rrddim_set_by_pointer(d->queue.st, d->queue.rd, (collected_number)d->queue.length.current.Data);
864 rrdset_done(d->queue.st);
865 }
866
867 if (perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &d->rsc.connections)) {
868 if (unlikely(!d->rsc.st_connections)) {
869 d->rsc.st_connections = rrdset_create_localhost(
870 "net_rsc_connections",
871 windows_shared_buffer,
872 NULL,
873 windows_shared_buffer,
874 "net.rsc_connections",
875 "Active TCP Connections Offloaded by RSC",
876 "connections",
877 PLUGIN_WINDOWS_NAME,
878 "PerflibNetwork",
879 NETDATA_CHART_PRIO_FIRST_NET_IFACE + 6,
880 update_every,
881 RRDSET_TYPE_LINE);
882
883 add_interface_labels(d->rsc.st_connections, windows_shared_buffer, physical);
884
885 d->rsc.rd_connections =
886 rrddim_add(d->rsc.st_connections, "connections", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
887 }
888
889 rrddim_set_by_pointer(
890 d->rsc.st_connections, d->rsc.rd_connections, (collected_number)d->rsc.connections.current.Data);
891 rrdset_done(d->rsc.st_connections);
892 }
893
894 if (perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &d->rsc.packets)) {
895 if (unlikely(!d->rsc.st_packets)) {
896 d->rsc.st_packets = rrdset_create_localhost(
897 "net_rsc_packets",
898 windows_shared_buffer,
899 NULL,
900 windows_shared_buffer,
901 "net.rsc_packets",
902 "TCP RSC Coalesced Packets",
903 "packets/s",
904 PLUGIN_WINDOWS_NAME,
905 "PerflibNetwork",
906 NETDATA_CHART_PRIO_FIRST_NET_IFACE + 7,
907 update_every,
908 RRDSET_TYPE_LINE);
909
910 add_interface_labels(d->rsc.st_packets, windows_shared_buffer, physical);
911
912 d->rsc.rd_packets = rrddim_add(d->rsc.st_packets, "packets", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
913 }
914
915 rrddim_set_by_pointer(d->rsc.st_packets, d->rsc.rd_packets, (collected_number)d->rsc.packets.current.Data);
916 rrdset_done(d->rsc.st_packets);
917 }
918
919 if (perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &d->rsc.exceptions)) {
920 if (unlikely(!d->rsc.st_exceptions)) {
921 d->rsc.st_exceptions = rrdset_create_localhost(
922 "net_rsc_exceptions",
923 windows_shared_buffer,
924 NULL,
925 windows_shared_buffer,
926 "net.rsc_exceptions",
927 "TCP RSC Exceptions",
928 "exceptions/s",
929 PLUGIN_WINDOWS_NAME,
930 "PerflibNetwork",
931 NETDATA_CHART_PRIO_FIRST_NET_IFACE + 8,
932 update_every,
933 RRDSET_TYPE_LINE);
934
935 add_interface_labels(d->rsc.st_exceptions, windows_shared_buffer, physical);
936
937 d->rsc.rd_exceptions =
938 rrddim_add(d->rsc.st_exceptions, "exceptions", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
939 }
940
941 rrddim_set_by_pointer(
942 d->rsc.st_exceptions, d->rsc.rd_exceptions, (collected_number)d->rsc.exceptions.current.Data);
943 rrdset_done(d->rsc.st_exceptions);
944 }
945
946 if (perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &d->rsc.average_packet_size)) {
947 if (unlikely(!d->rsc.st_average_packet_size)) {
948 d->rsc.st_average_packet_size = rrdset_create_localhost(
949 "net_rsc_average_packet_size",
950 windows_shared_buffer,
951 NULL,
952 windows_shared_buffer,
953 "net.rsc_average_packet_size",
954 "TCP RSC Average Packet Size",
955 "bytes",
956 PLUGIN_WINDOWS_NAME,
957 "PerflibNetwork",
958 NETDATA_CHART_PRIO_FIRST_NET_IFACE + 9,
959 update_every,
960 RRDSET_TYPE_LINE);
961
962 add_interface_labels(d->rsc.st_average_packet_size, windows_shared_buffer, physical);
963
964 d->rsc.rd_average_packet_size =
965 rrddim_add(d->rsc.st_average_packet_size, "average", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
966 }
967
968 rrddim_set_by_pointer(
969 d->rsc.st_average_packet_size,
970 d->rsc.rd_average_packet_size,
971 (collected_number)d->rsc.average_packet_size.current.Data);
972 rrdset_done(d->rsc.st_average_packet_size);
973 }
974
975 if (perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &d->chimney.connections)) {
976 if (unlikely(!d->chimney.st)) {
977 d->chimney.st = rrdset_create_localhost(
978 "net_chimney_connections",
979 windows_shared_buffer,
980 NULL,
981 windows_shared_buffer,
982 "net.chimney_connections",
983 "Active TCP Connections Offloaded with Chimney",
984 "connections",
985 PLUGIN_WINDOWS_NAME,
986 "PerflibNetwork",
987 NETDATA_CHART_PRIO_FIRST_NET_IFACE + 10,
988 update_every,
989 RRDSET_TYPE_LINE);
990
991 add_interface_labels(d->chimney.st, windows_shared_buffer, physical);
992
993 d->chimney.rd = rrddim_add(d->chimney.st, "connections", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
994 }
995
996 rrddim_set_by_pointer(d->chimney.st, d->chimney.rd, (collected_number)d->chimney.connections.current.Data);
997 rrdset_done(d->chimney.st);
998 }
999 }
1000
1001 if (physical) {
1002 static RRDSET *st = NULL;
1003 static RRDDIM *rd_received = NULL, *rd_sent = NULL;
1004
1005 if (unlikely(!st)) {
1006 st = rrdset_create_localhost(
1007 "system",
1008 "net",
1009 NULL,
1010 "network",
1011 "system.net",
1012 "Physical Network Interfaces Aggregated Bandwidth",
1013 "kilobits/s",
1014 PLUGIN_WINDOWS_NAME,
1015 "PerflibNetwork",
1016 NETDATA_CHART_PRIO_SYSTEM_NET,
1017 update_every,
1018 RRDSET_TYPE_AREA);
1019
1020 rd_received = rrddim_add(st, "received", NULL, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
1021 rd_sent = rrddim_add(st, "sent", NULL, -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
1022 }
1023
1024 rrddim_set_by_pointer(st, rd_received, (collected_number)total_received);
1025 rrddim_set_by_pointer(st, rd_sent, (collected_number)total_sent);
1026 rrdset_done(st);
1027 }
1028
1029 // cleanup
1030 {
1031 struct network_interface *d;
1032 dfe_start_write(dict, d)
1033 {
1034 if (d->last_collected < now_ut) {
1035 network_interface_cleanup(d);
1036 dictionary_del(dict, d_dfe.name);
1037 }
1038 }
1039 dfe_done(d);
1040 dictionary_garbage_collect(dict);
1041 }
1042
1043 return true;
1044 }
1045
1046 int do_PerflibNetwork(int update_every, usec_t dt __maybe_unused)
1047 {
1048 static bool initialized = false;
1049
1050 if (unlikely(!initialized)) {
1051 initialize();
1052 initialized = true;
1053 }
1054
1055 DWORD id = RegistryFindIDByName("Network Interface");
1056 if (id == PERFLIB_REGISTRY_NAME_NOT_FOUND)
1057 return -1;
1058
1059 PERF_DATA_BLOCK *pDataBlock = perflibGetPerformanceData(id);
1060 if (!pDataBlock)
1061 return -1;
1062
1063 usec_t now_ut = now_monotonic_usec();
1064 do_network_interface(pDataBlock, update_every, true, now_ut);
1065 do_network_interface(pDataBlock, update_every, false, now_ut);
1066
1067 struct network_protocol *tcp4 = NULL, *tcp6 = NULL;
1068 for (size_t i = 0; networks[i].protocol; i++) {
1069 do_network_protocol(pDataBlock, update_every, &networks[i]);
1070
1071 if (!tcp4 && strcmp(networks[i].protocol, "TCPv4") == 0)
1072 tcp4 = &networks[i];
1073 if (!tcp6 && strcmp(networks[i].protocol, "TCPv6") == 0)
1074 tcp6 = &networks[i];
1075 }
1076
1077 if (tcp4 && tcp6) {
1078 tcp46.packets.received = tcp4->packets.received;
1079 tcp46.packets.sent = tcp4->packets.sent;
1080 tcp46.packets.received.current.Data += tcp6->packets.received.current.Data;
1081 tcp46.packets.sent.current.Data += tcp6->packets.sent.current.Data;
1082 protocol_packets_chart_update(&tcp46, update_every);
1083 }
1084 return 0;
1085 }