master
c 1,858 lines 71.4 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 _COMMON_PLUGIN_NAME "windows.plugin"
7 #define _COMMON_PLUGIN_MODULE_NAME "PerflibHyperV"
8 #include "../common-contexts/common-contexts.h"
9
10 #define HYPERV "hyperv"
11
12 static void get_and_sanitize_instance_value(
13 PERF_DATA_BLOCK *pDataBlock,
14 PERF_OBJECT_TYPE *pObjectType,
15 PERF_INSTANCE_DEFINITION *pi,
16 char *buffer,
17 size_t buffer_size)
18 {
19 // char wstr[8192];
20 if (!getInstanceName(pDataBlock, pObjectType, pi, buffer, buffer_size)) {
21 strncpyz(buffer, "[unknown]", buffer_size - 1);
22 // return;
23 }
24 // rrdlabels_sanitize_value(buffer, wstr, buffer_size);
25 }
26
27 #define DICT_PERF_OPTION (DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE)
28
29 #define DEFINE_RD(counter_name) RRDDIM(*rd_##counter_name)
30
31 #define GET_INSTANCE_COUNTER(counter) \
32 do { \
33 perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &p->counter); \
34 } while (0)
35
36 #define GET_OBJECT_COUNTER(counter) \
37 do { \
38 perflibGetObjectCounter(pDataBlock, pObjectType, &p->counter); \
39 } while (0)
40
41 #define SETP_DIM_VALUE(st, field) \
42 do { \
43 rrddim_set_by_pointer(p->st, p->rd_##field, (collected_number)p->field.current.Data); \
44 } while (0)
45
46 typedef bool (*perf_func_collect)(PERF_DATA_BLOCK *pDataBlock, int update_every, void *data);
47
48 typedef struct {
49 const char *registry_name;
50 perf_func_collect function_collect;
51 dict_cb_insert_t dict_insert_cb;
52 size_t dict_size;
53 DICTIONARY *instance;
54 } hyperv_perf_item;
55
56 struct hypervisor_memory {
57 bool collected_metadata;
58 bool charts_created;
59
60 RRDSET *st_pressure;
61 RRDSET *st_vm_memory_physical;
62 RRDSET *st_vm_memory_physical_guest_visible;
63
64 DEFINE_RD(CurrentPressure);
65 DEFINE_RD(PhysicalMemory);
66 DEFINE_RD(GuestVisiblePhysicalMemory);
67 DEFINE_RD(GuestAvailableMemory);
68
69 COUNTER_DATA CurrentPressure;
70 COUNTER_DATA PhysicalMemory;
71 COUNTER_DATA GuestVisiblePhysicalMemory;
72 COUNTER_DATA GuestAvailableMemory;
73 };
74
75 void initialize_hyperv_memory_keys(struct hypervisor_memory *p)
76 {
77 p->CurrentPressure.key = "Current Pressure";
78 p->PhysicalMemory.key = "Physical Memory";
79 p->GuestVisiblePhysicalMemory.key = "Guest Visible Physical Memory";
80 p->GuestAvailableMemory.key = "Guest Available Memory";
81 }
82
83 void dict_hyperv_memory_insert_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
84 {
85 struct hypervisor_memory *p = value;
86 initialize_hyperv_memory_keys(p);
87 }
88
89 struct hypervisor_partition {
90 bool collected_metadata;
91 bool charts_created;
92
93 RRDSET *st_vm_vid_physical_pages_allocated;
94 RRDSET *st_vm_vid_remote_physical_pages;
95
96 DEFINE_RD(PhysicalPagesAllocated);
97 DEFINE_RD(RemotePhysicalPages);
98
99 COUNTER_DATA PhysicalPagesAllocated;
100 COUNTER_DATA RemotePhysicalPages;
101 };
102
103 void initialize_hyperv_partition_keys(struct hypervisor_partition *p)
104 {
105 p->PhysicalPagesAllocated.key = "Physical Pages Allocated";
106 p->RemotePhysicalPages.key = "Remote Physical Pages";
107 }
108
109 void dict_hyperv_partition_insert_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
110 {
111 struct hypervisor_partition *p = value;
112 initialize_hyperv_partition_keys(p);
113 }
114
115 static bool do_hyperv_memory(PERF_DATA_BLOCK *pDataBlock, int update_every, void *data)
116 {
117 hyperv_perf_item *item = data;
118
119 PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, item->registry_name);
120 if (!pObjectType)
121 return false;
122
123 PERF_INSTANCE_DEFINITION *pi = NULL;
124 for (LONG i = 0; i < pObjectType->NumInstances; i++) {
125 pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
126 if (!pi)
127 break;
128
129 get_and_sanitize_instance_value(
130 pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer));
131
132 struct hypervisor_memory *p = dictionary_set(item->instance, windows_shared_buffer, NULL, sizeof(*p));
133
134 if (!p->collected_metadata) {
135 p->collected_metadata = true;
136 }
137
138 GET_INSTANCE_COUNTER(CurrentPressure);
139 GET_INSTANCE_COUNTER(PhysicalMemory);
140 GET_INSTANCE_COUNTER(GuestVisiblePhysicalMemory);
141 GET_INSTANCE_COUNTER(GuestAvailableMemory);
142
143 if (!p->charts_created) {
144 p->charts_created = true;
145 char id[RRD_ID_LENGTH_MAX + 1];
146 snprintfz(id, RRD_ID_LENGTH_MAX, "%s", windows_shared_buffer);
147 netdata_fix_chart_name(id);
148
149 if (!p->st_vm_memory_physical) {
150 p->st_vm_memory_physical = rrdset_create_localhost(
151 "vm_memory_physical",
152 id,
153 NULL,
154 HYPERV,
155 HYPERV ".vm_memory_physical",
156 "VM assigned memory",
157 "bytes",
158 _COMMON_PLUGIN_NAME,
159 _COMMON_PLUGIN_MODULE_NAME,
160 NETDATA_CHART_PRIO_WINDOWS_HYPERV_VM_MEMORY_PHYSICAL,
161 update_every,
162 RRDSET_TYPE_LINE);
163
164 p->st_vm_memory_physical_guest_visible = rrdset_create_localhost(
165 "vm_memory_physical_guest_visible",
166 windows_shared_buffer,
167 NULL,
168 HYPERV,
169 HYPERV ".vm_memory_physical_guest_visible",
170 "VM guest visible memory",
171 "bytes",
172 _COMMON_PLUGIN_NAME,
173 _COMMON_PLUGIN_MODULE_NAME,
174 NETDATA_CHART_PRIO_WINDOWS_HYPERV_VM_MEMORY_PHYSICAL_GUEST_VISIBLE,
175 update_every,
176 RRDSET_TYPE_LINE);
177
178 p->st_pressure = rrdset_create_localhost(
179 "vm_memory_pressure_current",
180 windows_shared_buffer,
181 NULL,
182 HYPERV,
183 HYPERV ".vm_memory_pressure_current",
184 "VM Memory Pressure",
185 "percentage",
186 _COMMON_PLUGIN_NAME,
187 _COMMON_PLUGIN_MODULE_NAME,
188 NETDATA_CHART_PRIO_WINDOWS_HYPERV_VM_MEMORY_PRESSURE_CURRENT,
189 update_every,
190 RRDSET_TYPE_LINE);
191
192 p->rd_CurrentPressure = rrddim_add(p->st_pressure, "pressure", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
193 p->rd_PhysicalMemory =
194 rrddim_add(p->st_vm_memory_physical, "assigned", NULL, 1024 * 1024, 1, RRD_ALGORITHM_ABSOLUTE);
195 p->rd_GuestVisiblePhysicalMemory = rrddim_add(
196 p->st_vm_memory_physical_guest_visible, "visible", NULL, 1024 * 1024, 1, RRD_ALGORITHM_ABSOLUTE);
197 p->rd_GuestAvailableMemory = rrddim_add(
198 p->st_vm_memory_physical_guest_visible, "available", NULL, 1024 * 1024, 1, RRD_ALGORITHM_ABSOLUTE);
199
200 rrdlabels_add(p->st_vm_memory_physical->rrdlabels, "vm_name", windows_shared_buffer, RRDLABEL_SRC_AUTO);
201 rrdlabels_add(p->st_pressure->rrdlabels, "vm_name", windows_shared_buffer, RRDLABEL_SRC_AUTO);
202 rrdlabels_add(
203 p->st_vm_memory_physical_guest_visible->rrdlabels,
204 "vm_name",
205 windows_shared_buffer,
206 RRDLABEL_SRC_AUTO);
207 }
208 }
209
210 SETP_DIM_VALUE(st_pressure, CurrentPressure);
211 SETP_DIM_VALUE(st_vm_memory_physical, PhysicalMemory);
212 SETP_DIM_VALUE(st_vm_memory_physical_guest_visible, GuestVisiblePhysicalMemory);
213 SETP_DIM_VALUE(st_vm_memory_physical_guest_visible, GuestAvailableMemory);
214
215 rrdset_done(p->st_pressure);
216 rrdset_done(p->st_vm_memory_physical);
217 rrdset_done(p->st_vm_memory_physical_guest_visible);
218 }
219
220 return true;
221 }
222
223 static bool do_hyperv_vid_partition(PERF_DATA_BLOCK *pDataBlock, int update_every, void *data)
224 {
225 hyperv_perf_item *item = data;
226 PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, item->registry_name);
227 if (!pObjectType)
228 return false;
229
230 PERF_INSTANCE_DEFINITION *pi = NULL;
231 for (LONG i = 0; i < pObjectType->NumInstances; i++) {
232 pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
233 if (!pi)
234 break;
235
236 get_and_sanitize_instance_value(
237 pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer));
238
239 struct hypervisor_partition *p = dictionary_set(item->instance, windows_shared_buffer, NULL, sizeof(*p));
240
241 if (!p->collected_metadata) {
242 p->collected_metadata = true;
243 }
244
245 if (strcasecmp(windows_shared_buffer, "_Total") == 0)
246 continue;
247
248 GET_INSTANCE_COUNTER(RemotePhysicalPages);
249 GET_INSTANCE_COUNTER(PhysicalPagesAllocated);
250
251 if (!p->charts_created) {
252 p->charts_created = true;
253 char id[RRD_ID_LENGTH_MAX + 1];
254 snprintfz(id, RRD_ID_LENGTH_MAX, "%s", windows_shared_buffer);
255 netdata_fix_chart_name(id);
256
257 p->st_vm_vid_physical_pages_allocated = rrdset_create_localhost(
258 "vm_vid_physical_pages_allocated",
259 id,
260 NULL,
261 HYPERV,
262 HYPERV ".vm_vid_physical_pages_allocated",
263 "VM physical pages allocated",
264 "pages",
265 _COMMON_PLUGIN_NAME,
266 _COMMON_PLUGIN_MODULE_NAME,
267 NETDATA_CHART_PRIO_WINDOWS_HYPERV_VM_VID_PHYSICAL_PAGES_ALLOCATED,
268 update_every,
269 RRDSET_TYPE_LINE);
270
271 p->st_vm_vid_remote_physical_pages = rrdset_create_localhost(
272 "vm_vid_remote_physical_pages",
273 windows_shared_buffer,
274 NULL,
275 HYPERV,
276 HYPERV ".vm_vid_remote_physical_pages",
277 "VM physical pages not allocated from the preferred NUMA node",
278 "pages",
279 _COMMON_PLUGIN_NAME,
280 _COMMON_PLUGIN_MODULE_NAME,
281 NETDATA_CHART_PRIO_WINDOWS_HYPERV_VM_VID_REMOTE_PHYSICAL_PAGES,
282 update_every,
283 RRDSET_TYPE_LINE);
284
285 p->rd_PhysicalPagesAllocated =
286 rrddim_add(p->st_vm_vid_physical_pages_allocated, "allocated", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
287 p->rd_RemotePhysicalPages =
288 rrddim_add(p->st_vm_vid_remote_physical_pages, "remote_physical", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
289
290 rrdlabels_add(
291 p->st_vm_vid_physical_pages_allocated->rrdlabels, "vm_name", windows_shared_buffer, RRDLABEL_SRC_AUTO);
292 rrdlabels_add(
293 p->st_vm_vid_remote_physical_pages->rrdlabels, "vm_name", windows_shared_buffer, RRDLABEL_SRC_AUTO);
294 }
295
296 SETP_DIM_VALUE(st_vm_vid_remote_physical_pages, RemotePhysicalPages);
297 SETP_DIM_VALUE(st_vm_vid_physical_pages_allocated, PhysicalPagesAllocated);
298
299 rrdset_done(p->st_vm_vid_physical_pages_allocated);
300 rrdset_done(p->st_vm_vid_remote_physical_pages);
301 }
302
303 return true;
304 }
305
306 // Define structure for Hyper-V Virtual Machine Health Summary
307 static struct hypervisor_health_summary {
308 bool collected_metadata;
309 bool charts_created;
310
311 RRDSET *st_health;
312
313 DEFINE_RD(HealthCritical);
314 DEFINE_RD(HealthOk);
315
316 COUNTER_DATA HealthCritical;
317 COUNTER_DATA HealthOk;
318 } health_summary = {
319 .collected_metadata = false,
320 .st_health = NULL,
321 .HealthCritical.key = "Health Critical",
322 .HealthOk.key = "Health Ok"};
323
324 // Function to handle "Hyper-V Virtual Machine Health Summary"
325 static bool do_hyperv_health_summary(PERF_DATA_BLOCK *pDataBlock, int update_every, void *data)
326 {
327 hyperv_perf_item *item = data;
328
329 PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, item->registry_name);
330 if (!pObjectType)
331 return false;
332
333 struct hypervisor_health_summary *p = &health_summary;
334
335 GET_OBJECT_COUNTER(HealthCritical);
336 GET_OBJECT_COUNTER(HealthOk);
337
338 if (!p->charts_created) {
339 p->charts_created = true;
340 p->st_health = rrdset_create_localhost(
341 "vms_health",
342 "hyperv_health_status",
343 NULL,
344 HYPERV,
345 HYPERV ".vms_health",
346 "Virtual machines health status",
347 "vms",
348 _COMMON_PLUGIN_NAME,
349 _COMMON_PLUGIN_MODULE_NAME,
350 NETDATA_CHART_PRIO_WINDOWS_HYPERV_VMS_HEALTH,
351 update_every,
352 RRDSET_TYPE_STACKED);
353
354 p->rd_HealthOk = rrddim_add(p->st_health, "ok", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
355 p->rd_HealthCritical = rrddim_add(p->st_health, "critical", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
356 }
357
358 SETP_DIM_VALUE(st_health, HealthOk);
359 SETP_DIM_VALUE(st_health, HealthCritical);
360
361 rrdset_done(p->st_health);
362 return true;
363 }
364
365 // Define structure for Hyper-V Root Partition Metrics (Device and GPA Space Pages)
366 struct hypervisor_root_partition {
367 bool collected_metadata;
368 bool charts_created;
369
370 RRDSET *st_device_space_pages;
371 RRDSET *st_gpa_space_pages;
372 RRDSET *st_gpa_space_modifications;
373 RRDSET *st_attached_devices;
374 RRDSET *st_deposited_pages;
375
376 RRDSET *st_DeviceDMAErrors;
377 RRDSET *st_DeviceInterruptErrors;
378 RRDSET *st_DeviceInterruptThrottleEvents;
379 RRDSET *st_IOTLBFlushesSec;
380 RRDSET *st_AddressSpaces;
381 RRDSET *st_VirtualTLBPages;
382 RRDSET *st_VirtualTLBFlushEntriesSec;
383
384 DEFINE_RD(DeviceSpacePages4K);
385 DEFINE_RD(DeviceSpacePages2M);
386 DEFINE_RD(DeviceSpacePages1G);
387 DEFINE_RD(GPASpacePages4K);
388 DEFINE_RD(GPASpacePages2M);
389 DEFINE_RD(GPASpacePages1G);
390 DEFINE_RD(GPASpaceModifications);
391
392 DEFINE_RD(AttachedDevices);
393 DEFINE_RD(DepositedPages);
394
395 DEFINE_RD(DeviceDMAErrors);
396 DEFINE_RD(DeviceInterruptErrors);
397 DEFINE_RD(DeviceInterruptThrottleEvents);
398 DEFINE_RD(IOTLBFlushesSec);
399 DEFINE_RD(AddressSpaces);
400 DEFINE_RD(VirtualTLBPages);
401 DEFINE_RD(VirtualTLBFlushEntriesSec);
402
403 COUNTER_DATA DeviceSpacePages4K;
404 COUNTER_DATA DeviceSpacePages2M;
405 COUNTER_DATA DeviceSpacePages1G;
406 COUNTER_DATA GPASpacePages4K;
407 COUNTER_DATA GPASpacePages2M;
408 COUNTER_DATA GPASpacePages1G;
409 COUNTER_DATA GPASpaceModifications;
410 COUNTER_DATA AttachedDevices;
411 COUNTER_DATA DepositedPages;
412 COUNTER_DATA DeviceDMAErrors;
413 COUNTER_DATA DeviceInterruptErrors;
414 COUNTER_DATA DeviceInterruptThrottleEvents;
415 COUNTER_DATA IOTLBFlushesSec;
416 COUNTER_DATA AddressSpaces;
417 COUNTER_DATA VirtualTLBPages;
418 COUNTER_DATA VirtualTLBFlushEntriesSec;
419 };
420
421 // Initialize the keys for the root partition metrics
422 void initialize_hyperv_root_partition_keys(struct hypervisor_root_partition *p)
423 {
424 p->DeviceSpacePages4K.key = "4K device pages";
425 p->DeviceSpacePages2M.key = "2M device pages";
426 p->DeviceSpacePages1G.key = "1G device pages";
427
428 p->GPASpacePages4K.key = "4K GPA pages";
429 p->GPASpacePages2M.key = "2M GPA pages";
430 p->GPASpacePages1G.key = "1G GPA pages";
431
432 p->GPASpaceModifications.key = "GPA Space Modifications/sec";
433 p->AttachedDevices.key = "Attached Devices";
434 p->DepositedPages.key = "Deposited Pages";
435
436 p->DeviceDMAErrors.key = "Device DMA Errors";
437 p->DeviceInterruptErrors.key = "Device Interrupt Errors";
438 p->DeviceInterruptThrottleEvents.key = "Device Interrupt Throttle Events";
439 p->IOTLBFlushesSec.key = "I/O TLB Flushes/sec";
440 p->AddressSpaces.key = "Address Spaces";
441 p->VirtualTLBPages.key = "Virtual TLB Pages";
442 p->VirtualTLBFlushEntriesSec.key = "Virtual TLB Flush Entries/sec";
443 }
444
445 // Callback function for inserting root partition metrics into the dictionary
446 void dict_hyperv_root_partition_insert_cb(
447 const DICTIONARY_ITEM *item __maybe_unused,
448 void *value,
449 void *data __maybe_unused)
450 {
451 struct hypervisor_root_partition *p = value;
452 initialize_hyperv_root_partition_keys(p);
453 }
454
455 // Function to handle "Hyper-V Hypervisor Root Partition" metrics (Device Space and GPA Space)
456 static bool do_hyperv_root_partition(PERF_DATA_BLOCK *pDataBlock, int update_every, void *data)
457 {
458 hyperv_perf_item *item = data;
459
460 PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, item->registry_name);
461 if (!pObjectType)
462 return false;
463
464 PERF_INSTANCE_DEFINITION *pi = NULL;
465 for (LONG i = 0; i < pObjectType->NumInstances; i++) {
466 pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
467 if (!pi)
468 break;
469
470 get_and_sanitize_instance_value(
471 pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer));
472
473 if (strcasecmp(windows_shared_buffer, "_Total") == 0)
474 continue;
475
476 struct hypervisor_root_partition *p = dictionary_set(item->instance, windows_shared_buffer, NULL, sizeof(*p));
477
478 if (!p->collected_metadata) {
479 p->collected_metadata = true;
480 }
481
482 // Fetch counters
483 GET_INSTANCE_COUNTER(DeviceSpacePages4K);
484 GET_INSTANCE_COUNTER(DeviceSpacePages2M);
485 GET_INSTANCE_COUNTER(DeviceSpacePages1G);
486 GET_INSTANCE_COUNTER(GPASpacePages4K);
487 GET_INSTANCE_COUNTER(GPASpacePages2M);
488 GET_INSTANCE_COUNTER(GPASpacePages1G);
489 GET_INSTANCE_COUNTER(GPASpaceModifications);
490 GET_INSTANCE_COUNTER(AttachedDevices);
491 GET_INSTANCE_COUNTER(DepositedPages);
492
493 GET_INSTANCE_COUNTER(DeviceDMAErrors);
494 GET_INSTANCE_COUNTER(DeviceInterruptErrors);
495 GET_INSTANCE_COUNTER(DeviceInterruptThrottleEvents);
496 GET_INSTANCE_COUNTER(IOTLBFlushesSec);
497 GET_INSTANCE_COUNTER(AddressSpaces);
498 GET_INSTANCE_COUNTER(VirtualTLBPages);
499 GET_INSTANCE_COUNTER(VirtualTLBFlushEntriesSec);
500
501 // Create charts
502 if (!p->charts_created) {
503 p->charts_created = true;
504 char id[RRD_ID_LENGTH_MAX + 1];
505 snprintfz(id, RRD_ID_LENGTH_MAX, "%s", windows_shared_buffer);
506 netdata_fix_chart_name(id);
507
508 p->st_device_space_pages = rrdset_create_localhost(
509 "root_partition_device_space_pages",
510 id,
511 NULL,
512 HYPERV,
513 HYPERV ".root_partition_device_space_pages",
514 "Root partition device space pages",
515 "pages",
516 _COMMON_PLUGIN_NAME,
517 _COMMON_PLUGIN_MODULE_NAME,
518 NETDATA_CHART_PRIO_WINDOWS_HYPERV_ROOT_PARTITION_DEVICE_SPACE_PAGES,
519 update_every,
520 RRDSET_TYPE_LINE);
521
522 p->rd_DeviceSpacePages4K = rrddim_add(p->st_device_space_pages, "4K", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
523 p->rd_DeviceSpacePages2M = rrddim_add(p->st_device_space_pages, "2M", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
524 p->rd_DeviceSpacePages1G = rrddim_add(p->st_device_space_pages, "1G", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
525
526 p->st_gpa_space_pages = rrdset_create_localhost(
527 "root_partition_gpa_space_pages",
528 windows_shared_buffer,
529 NULL,
530 HYPERV,
531 HYPERV ".root_partition_gpa_space_pages",
532 "Root partition GPA space pages",
533 "pages",
534 _COMMON_PLUGIN_NAME,
535 _COMMON_PLUGIN_MODULE_NAME,
536 NETDATA_CHART_PRIO_WINDOWS_HYPERV_ROOT_PARTITION_GPA_SPACE_PAGES,
537 update_every,
538 RRDSET_TYPE_LINE);
539
540 p->rd_GPASpacePages4K = rrddim_add(p->st_gpa_space_pages, "4K", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
541 p->rd_GPASpacePages2M = rrddim_add(p->st_gpa_space_pages, "2M", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
542 p->rd_GPASpacePages1G = rrddim_add(p->st_gpa_space_pages, "1G", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
543
544 p->st_gpa_space_modifications = rrdset_create_localhost(
545 "root_partition_gpa_space_modifications",
546 windows_shared_buffer,
547 NULL,
548 HYPERV,
549 HYPERV ".root_partition_gpa_space_modifications",
550 "Root partition GPA space modifications",
551 "modifications/s",
552 _COMMON_PLUGIN_NAME,
553 _COMMON_PLUGIN_MODULE_NAME,
554 NETDATA_CHART_PRIO_WINDOWS_HYPERV_ROOT_PARTITION_GPA_SPACE_MODIFICATIONS,
555 update_every,
556 RRDSET_TYPE_LINE);
557
558 p->rd_GPASpaceModifications =
559 rrddim_add(p->st_gpa_space_modifications, "gpa", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
560
561 p->st_attached_devices = rrdset_create_localhost(
562 "root_partition_attached_devices",
563 windows_shared_buffer,
564 NULL,
565 HYPERV,
566 HYPERV ".root_partition_attached_devices",
567 "Root partition attached devices",
568 "devices",
569 _COMMON_PLUGIN_NAME,
570 _COMMON_PLUGIN_MODULE_NAME,
571 NETDATA_CHART_PRIO_WINDOWS_HYPERV_ROOT_PARTITION_ATTACHED_DEVICES,
572 update_every,
573 RRDSET_TYPE_LINE);
574
575 p->rd_AttachedDevices = rrddim_add(p->st_attached_devices, "attached", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
576
577 p->st_deposited_pages = rrdset_create_localhost(
578 "root_partition_deposited_pages",
579 windows_shared_buffer,
580 NULL,
581 HYPERV,
582 HYPERV ".root_partition_deposited_pages",
583 "Root partition deposited pages",
584 "pages",
585 _COMMON_PLUGIN_NAME,
586 _COMMON_PLUGIN_MODULE_NAME,
587 NETDATA_CHART_PRIO_WINDOWS_HYPERV_ROOT_PARTITION_DEPOSITED_PAGES,
588 update_every,
589 RRDSET_TYPE_LINE);
590
591 p->rd_DepositedPages = rrddim_add(p->st_deposited_pages, "gpa", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
592
593 p->st_DeviceDMAErrors = rrdset_create_localhost(
594 "root_partition_device_dma_errors",
595 windows_shared_buffer,
596 NULL,
597 HYPERV,
598 HYPERV ".root_partition_device_dma_errors",
599 "Root partition illegal DMA requests",
600 "requests",
601 _COMMON_PLUGIN_NAME,
602 _COMMON_PLUGIN_MODULE_NAME,
603 NETDATA_CHART_PRIO_WINDOWS_HYPERV_ROOT_PARTITION_DEVICE_DMA_ERRORS,
604 update_every,
605 RRDSET_TYPE_LINE);
606
607 p->rd_DeviceDMAErrors =
608 rrddim_add(p->st_DeviceDMAErrors, "illegal_dma", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
609
610 p->st_DeviceInterruptErrors = rrdset_create_localhost(
611 "root_partition_device_interrupt_errors",
612 windows_shared_buffer,
613 NULL,
614 HYPERV,
615 HYPERV ".root_partition_device_interrupt_errors",
616 "Root partition illegal interrupt requests",
617 "requests",
618 _COMMON_PLUGIN_NAME,
619 _COMMON_PLUGIN_MODULE_NAME,
620 NETDATA_CHART_PRIO_WINDOWS_HYPERV_ROOT_PARTITION_DEVICE_INTERRUPT_ERRORS,
621 update_every,
622 RRDSET_TYPE_LINE);
623
624 p->rd_DeviceInterruptErrors =
625 rrddim_add(p->st_DeviceInterruptErrors, "illegal_interrupt", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
626
627 p->st_DeviceInterruptThrottleEvents = rrdset_create_localhost(
628 "root_partition_device_interrupt_throttle_events",
629 windows_shared_buffer,
630 NULL,
631 HYPERV,
632 HYPERV ".root_partition_device_interrupt_throttle_events",
633 "Root partition throttled interrupts",
634 "events",
635 _COMMON_PLUGIN_NAME,
636 _COMMON_PLUGIN_MODULE_NAME,
637 NETDATA_CHART_PRIO_WINDOWS_HYPERV_ROOT_PARTITION_DEVICE_INTERRUPT_THROTTLE_EVENTS,
638 update_every,
639 RRDSET_TYPE_LINE);
640
641 p->rd_DeviceInterruptThrottleEvents =
642 rrddim_add(p->st_DeviceInterruptThrottleEvents, "throttling", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
643
644 p->st_IOTLBFlushesSec = rrdset_create_localhost(
645 "root_partition_io_tlb_flush",
646 windows_shared_buffer,
647 NULL,
648 HYPERV,
649 HYPERV ".root_partition_io_tlb_flush",
650 "Root partition flushes of I/O TLBs",
651 "flushes/s",
652 _COMMON_PLUGIN_NAME,
653 _COMMON_PLUGIN_MODULE_NAME,
654 NETDATA_CHART_PRIO_WINDOWS_HYPERV_ROOT_PARTITION_IO_TLB_FLUSH,
655 update_every,
656 RRDSET_TYPE_LINE);
657
658 p->rd_IOTLBFlushesSec = rrddim_add(p->st_IOTLBFlushesSec, "gpa", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
659
660 p->st_AddressSpaces = rrdset_create_localhost(
661 "root_partition_address_space",
662 windows_shared_buffer,
663 NULL,
664 HYPERV,
665 HYPERV ".root_partition_address_space",
666 "Root partition address spaces in the virtual TLB",
667 "address spaces",
668 _COMMON_PLUGIN_NAME,
669 _COMMON_PLUGIN_MODULE_NAME,
670 NETDATA_CHART_PRIO_WINDOWS_HYPERV_ROOT_PARTITION_ADDRESS_SPACE,
671 update_every,
672 RRDSET_TYPE_LINE);
673
674 p->rd_AddressSpaces = rrddim_add(p->st_AddressSpaces, "address_spaces", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
675
676 p->st_VirtualTLBPages = rrdset_create_localhost(
677 "root_partition_virtual_tlb_pages",
678 windows_shared_buffer,
679 NULL,
680 HYPERV,
681 HYPERV ".root_partition_virtual_tlb_pages",
682 "Root partition pages used by the virtual TLB",
683 "pages",
684 _COMMON_PLUGIN_NAME,
685 _COMMON_PLUGIN_MODULE_NAME,
686 NETDATA_CHART_PRIO_WINDOWS_HYPERV_ROOT_PARTITION_VIRTUAL_TLB_PAGES,
687 update_every,
688 RRDSET_TYPE_LINE);
689
690 p->rd_VirtualTLBPages = rrddim_add(p->st_VirtualTLBPages, "used", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
691
692 p->st_VirtualTLBFlushEntriesSec = rrdset_create_localhost(
693 "root_partition_virtual_tlb_flush_entries",
694 windows_shared_buffer,
695 NULL,
696 HYPERV,
697 HYPERV ".root_partition_virtual_tlb_flush_entries",
698 "Root partition flushes of entire virtual TLB",
699 "flushes/s",
700 _COMMON_PLUGIN_NAME,
701 _COMMON_PLUGIN_MODULE_NAME,
702 NETDATA_CHART_PRIO_WINDOWS_HYPERV_ROOT_PARTITION_VIRTUAL_TLB_FLUSH_ENTRIES,
703 update_every,
704 RRDSET_TYPE_LINE);
705
706 p->rd_VirtualTLBFlushEntriesSec =
707 rrddim_add(p->st_VirtualTLBFlushEntriesSec, "flushes", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
708 }
709
710 // Set the data for each dimension
711
712 SETP_DIM_VALUE(st_device_space_pages, DeviceSpacePages4K);
713 SETP_DIM_VALUE(st_device_space_pages, DeviceSpacePages2M);
714 SETP_DIM_VALUE(st_device_space_pages, DeviceSpacePages1G);
715
716 SETP_DIM_VALUE(st_gpa_space_pages, GPASpacePages4K);
717 SETP_DIM_VALUE(st_gpa_space_pages, GPASpacePages2M);
718 SETP_DIM_VALUE(st_gpa_space_pages, GPASpacePages1G);
719
720 SETP_DIM_VALUE(st_gpa_space_modifications, GPASpaceModifications);
721
722 SETP_DIM_VALUE(st_attached_devices, AttachedDevices);
723 SETP_DIM_VALUE(st_deposited_pages, DepositedPages);
724
725 SETP_DIM_VALUE(st_DeviceDMAErrors, DeviceDMAErrors);
726 SETP_DIM_VALUE(st_DeviceInterruptErrors, DeviceInterruptErrors);
727 SETP_DIM_VALUE(st_DeviceInterruptThrottleEvents, DeviceInterruptThrottleEvents);
728 SETP_DIM_VALUE(st_IOTLBFlushesSec, IOTLBFlushesSec);
729 SETP_DIM_VALUE(st_AddressSpaces, AddressSpaces);
730 SETP_DIM_VALUE(st_VirtualTLBPages, VirtualTLBPages);
731 SETP_DIM_VALUE(st_VirtualTLBFlushEntriesSec, VirtualTLBFlushEntriesSec);
732
733 // Mark the charts as done
734 rrdset_done(p->st_device_space_pages);
735 rrdset_done(p->st_gpa_space_pages);
736 rrdset_done(p->st_gpa_space_modifications);
737 rrdset_done(p->st_attached_devices);
738 rrdset_done(p->st_deposited_pages);
739 rrdset_done(p->st_DeviceInterruptErrors);
740 rrdset_done(p->st_DeviceInterruptThrottleEvents);
741 rrdset_done(p->st_IOTLBFlushesSec);
742 rrdset_done(p->st_AddressSpaces);
743 rrdset_done(p->st_DeviceDMAErrors);
744 rrdset_done(p->st_VirtualTLBPages);
745 rrdset_done(p->st_VirtualTLBFlushEntriesSec);
746 }
747
748 return true;
749 }
750
751 // Storage DEVICE
752
753 struct hypervisor_storage_device {
754 bool collected_metadata;
755 bool charts_created;
756
757 RRDSET *st_operations;
758 DEFINE_RD(ReadOperationsSec);
759 DEFINE_RD(WriteOperationsSec);
760
761 RRDSET *st_bytes;
762 DEFINE_RD(ReadBytesSec);
763 DEFINE_RD(WriteBytesSec);
764
765 RRDSET *st_errors;
766 DEFINE_RD(ErrorCount);
767
768 COUNTER_DATA ReadOperationsSec;
769 COUNTER_DATA WriteOperationsSec;
770
771 COUNTER_DATA ReadBytesSec;
772 COUNTER_DATA WriteBytesSec;
773 COUNTER_DATA ErrorCount;
774 };
775
776 // Initialize the keys for the root partition metrics
777 void initialize_hyperv_storage_device_keys(struct hypervisor_storage_device *p)
778 {
779 p->ReadOperationsSec.key = "Read Operations/Sec";
780 p->WriteOperationsSec.key = "Write Operations/Sec";
781
782 p->ReadBytesSec.key = "Read Bytes/sec";
783 p->WriteBytesSec.key = "Write Bytes/sec";
784 p->ErrorCount.key = "Error Count";
785 }
786
787 // Callback function for inserting root partition metrics into the dictionary
788 void dict_hyperv_storage_device_insert_cb(
789 const DICTIONARY_ITEM *item __maybe_unused,
790 void *value,
791 void *data __maybe_unused)
792 {
793 struct hypervisor_storage_device *p = value;
794 initialize_hyperv_storage_device_keys(p);
795 }
796
797 static bool do_hyperv_storage_device(PERF_DATA_BLOCK *pDataBlock, int update_every, void *data)
798 {
799 hyperv_perf_item *item = data;
800
801 PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, item->registry_name);
802 if (!pObjectType)
803 return false;
804
805 PERF_INSTANCE_DEFINITION *pi = NULL;
806 for (LONG i = 0; i < pObjectType->NumInstances; i++) {
807 pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
808 if (!pi)
809 break;
810
811 get_and_sanitize_instance_value(
812 pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer));
813
814 if (strcasecmp(windows_shared_buffer, "_Total") == 0)
815 continue;
816
817 struct hypervisor_storage_device *p = dictionary_set(item->instance, windows_shared_buffer, NULL, sizeof(*p));
818
819 if (!p->collected_metadata) {
820 p->collected_metadata = true;
821 }
822
823 // Fetch counters
824 GET_INSTANCE_COUNTER(ReadOperationsSec);
825 GET_INSTANCE_COUNTER(WriteOperationsSec);
826
827 GET_INSTANCE_COUNTER(ReadBytesSec);
828 GET_INSTANCE_COUNTER(WriteBytesSec);
829 GET_INSTANCE_COUNTER(ErrorCount);
830
831 if (!p->charts_created) {
832 p->charts_created = true;
833 char id[RRD_ID_LENGTH_MAX + 1];
834 snprintfz(id, RRD_ID_LENGTH_MAX, "%s", windows_shared_buffer);
835 netdata_fix_chart_name(id);
836
837 if (!p->st_operations) {
838 p->st_operations = rrdset_create_localhost(
839 "vm_storage_device_operations",
840 id,
841 NULL,
842 HYPERV,
843 HYPERV ".vm_storage_device_operations",
844 "VM storage device IOPS",
845 "operations/s",
846 _COMMON_PLUGIN_NAME,
847 _COMMON_PLUGIN_MODULE_NAME,
848 NETDATA_CHART_PRIO_WINDOWS_HYPERV_VM_STORAGE_DEVICE_OPERATIONS,
849 update_every,
850 RRDSET_TYPE_LINE);
851
852 p->rd_ReadOperationsSec = rrddim_add(p->st_operations, "read", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
853 p->rd_WriteOperationsSec =
854 rrddim_add(p->st_operations, "write", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
855
856 rrdlabels_add(
857 p->st_operations->rrdlabels, "vm_storage_device", windows_shared_buffer, RRDLABEL_SRC_AUTO);
858 }
859
860 if (!p->st_bytes) {
861 p->st_bytes = rrdset_create_localhost(
862 "vm_storage_device_bytes",
863 windows_shared_buffer,
864 NULL,
865 HYPERV,
866 HYPERV ".vm_storage_device_bytes",
867 "VM storage device IO",
868 "bytes/s",
869 _COMMON_PLUGIN_NAME,
870 _COMMON_PLUGIN_MODULE_NAME,
871 NETDATA_CHART_PRIO_WINDOWS_HYPERV_VM_STORAGE_DEVICE_BYTES,
872 update_every,
873 RRDSET_TYPE_AREA);
874
875 p->rd_ReadBytesSec = rrddim_add(p->st_bytes, "read", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
876 p->rd_WriteBytesSec = rrddim_add(p->st_bytes, "write", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
877
878 rrdlabels_add(p->st_bytes->rrdlabels, "vm_storage_device", windows_shared_buffer, RRDLABEL_SRC_AUTO);
879 }
880
881 if (!p->st_errors) {
882 p->st_errors = rrdset_create_localhost(
883 "vm_storage_device_errors",
884 windows_shared_buffer,
885 NULL,
886 HYPERV,
887 HYPERV ".vm_storage_device_errors",
888 "VM storage device errors",
889 "errors/s",
890 _COMMON_PLUGIN_NAME,
891 _COMMON_PLUGIN_MODULE_NAME,
892 NETDATA_CHART_PRIO_WINDOWS_HYPERV_VM_STORAGE_DEVICE_ERRORS,
893 update_every,
894 RRDSET_TYPE_LINE);
895
896 p->rd_ErrorCount = rrddim_add(p->st_errors, "errors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
897
898 rrdlabels_add(p->st_errors->rrdlabels, "vm_storage_device", windows_shared_buffer, RRDLABEL_SRC_AUTO);
899 }
900 }
901
902 SETP_DIM_VALUE(st_operations, ReadOperationsSec);
903 SETP_DIM_VALUE(st_operations, WriteOperationsSec);
904
905 SETP_DIM_VALUE(st_bytes, ReadBytesSec);
906 SETP_DIM_VALUE(st_bytes, WriteBytesSec);
907
908 SETP_DIM_VALUE(st_errors, ErrorCount);
909
910 // Mark the charts as done
911 rrdset_done(p->st_operations);
912 rrdset_done(p->st_bytes);
913 rrdset_done(p->st_errors);
914 }
915
916 return true;
917 }
918
919 struct hypervisor_switch {
920 bool collected_metadata;
921 bool charts_created;
922
923 RRDSET *st_bytes;
924 DEFINE_RD(BytesSentSec);
925 DEFINE_RD(BytesReceivedSec);
926
927 RRDSET *st_packets;
928 DEFINE_RD(PacketsSentSec);
929 DEFINE_RD(PacketsReceivedSec);
930
931 RRDSET *st_directed_packets;
932 DEFINE_RD(DirectedPacketsSentSec);
933 DEFINE_RD(DirectedPacketsReceivedSec);
934
935 RRDSET *st_broadcast_packets;
936 DEFINE_RD(BroadcastPacketsSentSec);
937 DEFINE_RD(BroadcastPacketsReceivedSec);
938
939 RRDSET *st_multicast_packets;
940 DEFINE_RD(MulticastPacketsSentSec);
941 DEFINE_RD(MulticastPacketsReceivedSec);
942
943 RRDSET *st_dropped_packets;
944 DEFINE_RD(DroppedPacketsOutgoingSec);
945 DEFINE_RD(DroppedPacketsIncomingSec);
946
947 RRDSET *st_ext_dropped_packets;
948 DEFINE_RD(ExtensionsDroppedPacketsOutgoingSec);
949 DEFINE_RD(ExtensionsDroppedPacketsIncomingSec);
950
951 RRDSET *st_flooded;
952 DEFINE_RD(PacketsFlooded);
953
954 RRDSET *st_learned_mac;
955 DEFINE_RD(LearnedMacAddresses);
956
957 RRDSET *st_purged_mac;
958 DEFINE_RD(PurgedMacAddresses);
959
960 COUNTER_DATA BytesSentSec;
961 COUNTER_DATA BytesReceivedSec;
962
963 COUNTER_DATA PacketsSentSec;
964 COUNTER_DATA PacketsReceivedSec;
965
966 COUNTER_DATA DirectedPacketsSentSec;
967 COUNTER_DATA DirectedPacketsReceivedSec;
968
969 COUNTER_DATA BroadcastPacketsSentSec;
970 COUNTER_DATA BroadcastPacketsReceivedSec;
971
972 COUNTER_DATA MulticastPacketsSentSec;
973 COUNTER_DATA MulticastPacketsReceivedSec;
974
975 COUNTER_DATA DroppedPacketsOutgoingSec;
976 COUNTER_DATA DroppedPacketsIncomingSec;
977
978 COUNTER_DATA ExtensionsDroppedPacketsOutgoingSec;
979 COUNTER_DATA ExtensionsDroppedPacketsIncomingSec;
980
981 COUNTER_DATA PacketsFlooded;
982
983 COUNTER_DATA LearnedMacAddresses;
984
985 COUNTER_DATA PurgedMacAddresses;
986 };
987
988 // Initialize the keys for the root partition metrics
989 void initialize_hyperv_switch_keys(struct hypervisor_switch *p)
990 {
991 p->BytesSentSec.key = "Bytes Sent/sec";
992 p->BytesReceivedSec.key = "Bytes Received/sec";
993 p->PacketsSentSec.key = "Packets Sent/sec";
994 p->PacketsReceivedSec.key = "Packets Received/sec";
995
996 p->DirectedPacketsSentSec.key = "Directed Packets Sent/sec";
997 p->DirectedPacketsReceivedSec.key = "Directed Packets Received/sec";
998 p->BroadcastPacketsSentSec.key = "Broadcast Packets Sent/sec";
999 p->BroadcastPacketsReceivedSec.key = "Broadcast Packets Received/sec";
1000 p->MulticastPacketsSentSec.key = "Multicast Packets Sent/sec";
1001 p->MulticastPacketsReceivedSec.key = "Multicast Packets Received/sec";
1002 p->DroppedPacketsOutgoingSec.key = "Dropped Packets Outgoing/sec";
1003 p->DroppedPacketsIncomingSec.key = "Dropped Packets Incoming/sec";
1004 p->ExtensionsDroppedPacketsOutgoingSec.key = "Extensions Dropped Packets Outgoing/sec";
1005 p->ExtensionsDroppedPacketsIncomingSec.key = "Extensions Dropped Packets Incoming/sec";
1006 p->PacketsFlooded.key = "Packets Flooded";
1007 p->LearnedMacAddresses.key = "Learned Mac Addresses";
1008 p->PurgedMacAddresses.key = "Purged Mac Addresses";
1009 }
1010
1011 void dict_hyperv_switch_insert_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1012 {
1013 struct hypervisor_switch *p = value;
1014 initialize_hyperv_switch_keys(p);
1015 }
1016
1017 static bool do_hyperv_switch(PERF_DATA_BLOCK *pDataBlock, int update_every, void *data)
1018 {
1019 hyperv_perf_item *item = data;
1020
1021 PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, item->registry_name);
1022 if (!pObjectType)
1023 return false;
1024
1025 PERF_INSTANCE_DEFINITION *pi = NULL;
1026 for (LONG i = 0; i < pObjectType->NumInstances; i++) {
1027 pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
1028 if (!pi)
1029 break;
1030
1031 get_and_sanitize_instance_value(
1032 pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer));
1033
1034 if (strcasecmp(windows_shared_buffer, "_Total") == 0)
1035 continue;
1036
1037 struct hypervisor_switch *p = dictionary_set(item->instance, windows_shared_buffer, NULL, sizeof(*p));
1038
1039 if (!p->collected_metadata) {
1040 p->collected_metadata = true;
1041 }
1042
1043 GET_INSTANCE_COUNTER(BytesReceivedSec);
1044 GET_INSTANCE_COUNTER(BytesSentSec);
1045
1046 GET_INSTANCE_COUNTER(PacketsReceivedSec);
1047 GET_INSTANCE_COUNTER(PacketsSentSec);
1048
1049 GET_INSTANCE_COUNTER(DirectedPacketsSentSec);
1050 GET_INSTANCE_COUNTER(DirectedPacketsReceivedSec);
1051
1052 GET_INSTANCE_COUNTER(BroadcastPacketsSentSec);
1053 GET_INSTANCE_COUNTER(BroadcastPacketsReceivedSec);
1054
1055 GET_INSTANCE_COUNTER(MulticastPacketsSentSec);
1056 GET_INSTANCE_COUNTER(MulticastPacketsReceivedSec);
1057
1058 GET_INSTANCE_COUNTER(DroppedPacketsOutgoingSec);
1059 GET_INSTANCE_COUNTER(DroppedPacketsIncomingSec);
1060
1061 GET_INSTANCE_COUNTER(ExtensionsDroppedPacketsOutgoingSec);
1062 GET_INSTANCE_COUNTER(ExtensionsDroppedPacketsIncomingSec);
1063
1064 GET_INSTANCE_COUNTER(PacketsFlooded);
1065
1066 GET_INSTANCE_COUNTER(LearnedMacAddresses);
1067
1068 GET_INSTANCE_COUNTER(PurgedMacAddresses);
1069
1070 if (!p->charts_created) {
1071 p->charts_created = true;
1072 char id[RRD_ID_LENGTH_MAX + 1];
1073 snprintfz(id, RRD_ID_LENGTH_MAX, "%s", windows_shared_buffer);
1074 netdata_fix_chart_name(id);
1075
1076 p->st_bytes = rrdset_create_localhost(
1077 "vswitch_traffic",
1078 id,
1079 NULL,
1080 HYPERV,
1081 HYPERV ".vswitch_traffic",
1082 "Virtual switch traffic",
1083 "kilobits/s",
1084 _COMMON_PLUGIN_NAME,
1085 _COMMON_PLUGIN_MODULE_NAME,
1086 NETDATA_CHART_PRIO_WINDOWS_HYPERV_VSWITCH_TRAFFIC,
1087 update_every,
1088 RRDSET_TYPE_AREA);
1089
1090 p->rd_BytesReceivedSec = rrddim_add(p->st_bytes, "received", NULL, 8, 1000, RRD_ALGORITHM_INCREMENTAL);
1091 p->rd_BytesSentSec = rrddim_add(p->st_bytes, "sent", NULL, -8, 1000, RRD_ALGORITHM_INCREMENTAL);
1092 rrdlabels_add(p->st_bytes->rrdlabels, "vswitch", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1093
1094 p->st_packets = rrdset_create_localhost(
1095 "vswitch_packets",
1096 windows_shared_buffer,
1097 NULL,
1098 HYPERV,
1099 HYPERV ".vswitch_packets",
1100 "Virtual switch packets",
1101 "packets/s",
1102 _COMMON_PLUGIN_NAME,
1103 _COMMON_PLUGIN_MODULE_NAME,
1104 NETDATA_CHART_PRIO_WINDOWS_HYPERV_VSWITCH_PACKETS,
1105 update_every,
1106 RRDSET_TYPE_LINE);
1107
1108 p->rd_PacketsReceivedSec = rrddim_add(p->st_packets, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1109 p->rd_PacketsSentSec = rrddim_add(p->st_packets, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
1110 rrdlabels_add(p->st_packets->rrdlabels, "vswitch", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1111
1112 p->st_directed_packets = rrdset_create_localhost(
1113 "vswitch_directed_packets",
1114 windows_shared_buffer,
1115 NULL,
1116 HYPERV,
1117 HYPERV ".vswitch_directed_packets",
1118 "Virtual switch directed packets",
1119 "packets/s",
1120 _COMMON_PLUGIN_NAME,
1121 _COMMON_PLUGIN_MODULE_NAME,
1122 NETDATA_CHART_PRIO_WINDOWS_HYPERV_VSWITCH_DIRECTED_PACKETS,
1123 update_every,
1124 RRDSET_TYPE_LINE);
1125
1126 p->rd_DirectedPacketsReceivedSec =
1127 rrddim_add(p->st_directed_packets, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1128 p->rd_DirectedPacketsSentSec =
1129 rrddim_add(p->st_directed_packets, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
1130 rrdlabels_add(p->st_directed_packets->rrdlabels, "vswitch", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1131
1132 p->st_broadcast_packets = rrdset_create_localhost(
1133 "vswitch_broadcast_packets",
1134 windows_shared_buffer,
1135 NULL,
1136 HYPERV,
1137 HYPERV ".vswitch_broadcast_packets",
1138 "Virtual switch broadcast packets",
1139 "packets/s",
1140 _COMMON_PLUGIN_NAME,
1141 _COMMON_PLUGIN_MODULE_NAME,
1142 NETDATA_CHART_PRIO_WINDOWS_HYPERV_VSWITCH_BROADCAST_PACKETS,
1143 update_every,
1144 RRDSET_TYPE_LINE);
1145
1146 p->rd_BroadcastPacketsReceivedSec =
1147 rrddim_add(p->st_broadcast_packets, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1148 p->rd_BroadcastPacketsSentSec =
1149 rrddim_add(p->st_broadcast_packets, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
1150 rrdlabels_add(p->st_broadcast_packets->rrdlabels, "vswitch", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1151
1152 p->st_multicast_packets = rrdset_create_localhost(
1153 "vswitch_multicast_packets",
1154 windows_shared_buffer,
1155 NULL,
1156 HYPERV,
1157 HYPERV ".vswitch_multicast_packets",
1158 "Virtual switch multicast packets",
1159 "packets/s",
1160 _COMMON_PLUGIN_NAME,
1161 _COMMON_PLUGIN_MODULE_NAME,
1162 NETDATA_CHART_PRIO_WINDOWS_HYPERV_VSWITCH_MULTICAST_PACKETS,
1163 update_every,
1164 RRDSET_TYPE_LINE);
1165
1166 p->rd_MulticastPacketsReceivedSec =
1167 rrddim_add(p->st_multicast_packets, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1168 p->rd_MulticastPacketsSentSec =
1169 rrddim_add(p->st_multicast_packets, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
1170 rrdlabels_add(p->st_multicast_packets->rrdlabels, "vswitch", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1171
1172 p->st_dropped_packets = rrdset_create_localhost(
1173 "vswitch_dropped_packets",
1174 windows_shared_buffer,
1175 NULL,
1176 HYPERV,
1177 HYPERV ".vswitch_dropped_packets",
1178 "Virtual switch dropped packets",
1179 "drops/s",
1180 _COMMON_PLUGIN_NAME,
1181 _COMMON_PLUGIN_MODULE_NAME,
1182 NETDATA_CHART_PRIO_WINDOWS_HYPERV_VSWITCH_DROPPED_PACKETS,
1183 update_every,
1184 RRDSET_TYPE_LINE);
1185
1186 p->rd_DroppedPacketsIncomingSec =
1187 rrddim_add(p->st_dropped_packets, "incoming", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1188 p->rd_DroppedPacketsOutgoingSec =
1189 rrddim_add(p->st_dropped_packets, "outgoing", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
1190 rrdlabels_add(p->st_dropped_packets->rrdlabels, "vswitch", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1191
1192 p->st_ext_dropped_packets = rrdset_create_localhost(
1193 "vswitch_extensions_dropped_packets",
1194 windows_shared_buffer,
1195 NULL,
1196 HYPERV,
1197 HYPERV ".vswitch_extensions_dropped_packets",
1198 "Virtual switch extensions dropped packets",
1199 "drops/s",
1200 _COMMON_PLUGIN_NAME,
1201 _COMMON_PLUGIN_MODULE_NAME,
1202 NETDATA_CHART_PRIO_WINDOWS_HYPERV_VSWITCH_EXTENSIONS_DROPPED_PACKETS,
1203 update_every,
1204 RRDSET_TYPE_LINE);
1205
1206 p->rd_ExtensionsDroppedPacketsIncomingSec =
1207 rrddim_add(p->st_ext_dropped_packets, "incoming", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1208 p->rd_ExtensionsDroppedPacketsOutgoingSec =
1209 rrddim_add(p->st_ext_dropped_packets, "outgoing", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
1210 rrdlabels_add(p->st_ext_dropped_packets->rrdlabels, "vswitch", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1211
1212 p->st_flooded = rrdset_create_localhost(
1213 "vswitch_packets_flooded",
1214 windows_shared_buffer,
1215 NULL,
1216 HYPERV,
1217 HYPERV ".vswitch_packets_flooded",
1218 "Virtual switch flooded packets",
1219 "packets/s",
1220 _COMMON_PLUGIN_NAME,
1221 _COMMON_PLUGIN_MODULE_NAME,
1222 NETDATA_CHART_PRIO_WINDOWS_HYPERV_VSWITCH_PACKETS_FLOODED,
1223 update_every,
1224 RRDSET_TYPE_LINE);
1225
1226 p->rd_PacketsFlooded = rrddim_add(p->st_flooded, "flooded", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1227 rrdlabels_add(p->st_flooded->rrdlabels, "vswitch", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1228
1229 p->st_learned_mac = rrdset_create_localhost(
1230 "vswitch_learned_mac_addresses",
1231 windows_shared_buffer,
1232 NULL,
1233 HYPERV,
1234 HYPERV ".vswitch_learned_mac_addresses",
1235 "Virtual switch learned MAC addresses",
1236 "mac addresses/s",
1237 _COMMON_PLUGIN_NAME,
1238 _COMMON_PLUGIN_MODULE_NAME,
1239 NETDATA_CHART_PRIO_WINDOWS_HYPERV_VSWITCH_LEARNED_MAC_ADDRESSES,
1240 update_every,
1241 RRDSET_TYPE_LINE);
1242
1243 p->rd_LearnedMacAddresses = rrddim_add(p->st_learned_mac, "learned", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1244 rrdlabels_add(p->st_learned_mac->rrdlabels, "vswitch", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1245
1246 p->st_purged_mac = rrdset_create_localhost(
1247 "vswitch_purged_mac_addresses",
1248 windows_shared_buffer,
1249 NULL,
1250 HYPERV,
1251 HYPERV ".vswitch_purged_mac_addresses",
1252 "Virtual switch purged MAC addresses",
1253 "mac addresses/s",
1254 _COMMON_PLUGIN_NAME,
1255 _COMMON_PLUGIN_MODULE_NAME,
1256 NETDATA_CHART_PRIO_WINDOWS_HYPERV_VSWITCH_PURGED_MAC_ADDRESSES,
1257 update_every,
1258 RRDSET_TYPE_LINE);
1259
1260 p->rd_PurgedMacAddresses = rrddim_add(p->st_purged_mac, "purged", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1261 rrdlabels_add(p->st_purged_mac->rrdlabels, "vswitch", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1262 }
1263
1264 SETP_DIM_VALUE(st_packets, PacketsReceivedSec);
1265 SETP_DIM_VALUE(st_packets, PacketsSentSec);
1266
1267 SETP_DIM_VALUE(st_bytes, BytesReceivedSec);
1268 SETP_DIM_VALUE(st_bytes, BytesSentSec);
1269
1270 SETP_DIM_VALUE(st_directed_packets, DirectedPacketsSentSec);
1271 SETP_DIM_VALUE(st_directed_packets, DirectedPacketsReceivedSec);
1272
1273 SETP_DIM_VALUE(st_broadcast_packets, BroadcastPacketsSentSec);
1274 SETP_DIM_VALUE(st_broadcast_packets, BroadcastPacketsReceivedSec);
1275
1276 SETP_DIM_VALUE(st_multicast_packets, MulticastPacketsSentSec);
1277 SETP_DIM_VALUE(st_multicast_packets, MulticastPacketsReceivedSec);
1278
1279 SETP_DIM_VALUE(st_dropped_packets, DroppedPacketsOutgoingSec);
1280 SETP_DIM_VALUE(st_dropped_packets, DroppedPacketsIncomingSec);
1281
1282 SETP_DIM_VALUE(st_ext_dropped_packets, ExtensionsDroppedPacketsOutgoingSec);
1283 SETP_DIM_VALUE(st_ext_dropped_packets, ExtensionsDroppedPacketsIncomingSec);
1284
1285 SETP_DIM_VALUE(st_flooded, PacketsFlooded);
1286 SETP_DIM_VALUE(st_learned_mac, LearnedMacAddresses);
1287 SETP_DIM_VALUE(st_purged_mac, PurgedMacAddresses);
1288
1289 // Mark the charts as done
1290 rrdset_done(p->st_packets);
1291 rrdset_done(p->st_bytes);
1292
1293 rrdset_done(p->st_directed_packets);
1294 rrdset_done(p->st_broadcast_packets);
1295 rrdset_done(p->st_multicast_packets);
1296 rrdset_done(p->st_dropped_packets);
1297 rrdset_done(p->st_ext_dropped_packets);
1298 rrdset_done(p->st_flooded);
1299 rrdset_done(p->st_learned_mac);
1300 rrdset_done(p->st_purged_mac);
1301 }
1302 return true;
1303 }
1304
1305 struct hypervisor_network_adapter {
1306 bool collected_metadata;
1307 bool charts_created;
1308
1309 RRDSET *st_dropped_packets;
1310 DEFINE_RD(DroppedPacketsOutgoingSec);
1311 DEFINE_RD(DroppedPacketsIncomingSec);
1312
1313 RRDSET *st_send_receive_packets;
1314 DEFINE_RD(PacketsSentSec);
1315 DEFINE_RD(PacketsReceivedSec);
1316
1317 RRDSET *st_send_receive_bytes;
1318 DEFINE_RD(BytesSentSec);
1319 DEFINE_RD(BytesReceivedSec);
1320
1321 RRDSET *st_IPsecoffloadBytes;
1322 DEFINE_RD(IPsecoffloadBytesReceivedSec);
1323 DEFINE_RD(IPsecoffloadBytesSentSec);
1324
1325 RRDSET *st_DirectedPackets;
1326 DEFINE_RD(DirectedPacketsSentSec);
1327 DEFINE_RD(DirectedPacketsReceivedSec);
1328
1329 RRDSET *st_BroadcastPackets;
1330 DEFINE_RD(BroadcastPacketsSentSec);
1331 DEFINE_RD(BroadcastPacketsReceivedSec);
1332
1333 RRDSET *st_MulticastPackets;
1334 DEFINE_RD(MulticastPacketsSentSec);
1335 DEFINE_RD(MulticastPacketsReceivedSec);
1336
1337 COUNTER_DATA DroppedPacketsOutgoingSec;
1338 COUNTER_DATA DroppedPacketsIncomingSec;
1339
1340 COUNTER_DATA PacketsSentSec;
1341 COUNTER_DATA PacketsReceivedSec;
1342
1343 COUNTER_DATA BytesSentSec;
1344 COUNTER_DATA BytesReceivedSec;
1345
1346 COUNTER_DATA IPsecoffloadBytesReceivedSec;
1347 COUNTER_DATA IPsecoffloadBytesSentSec;
1348
1349 COUNTER_DATA DirectedPacketsSentSec;
1350 COUNTER_DATA DirectedPacketsReceivedSec;
1351
1352 COUNTER_DATA BroadcastPacketsSentSec;
1353 COUNTER_DATA BroadcastPacketsReceivedSec;
1354
1355 COUNTER_DATA MulticastPacketsSentSec;
1356 COUNTER_DATA MulticastPacketsReceivedSec;
1357 };
1358
1359 // Initialize the keys for the root partition metrics
1360 void initialize_hyperv_network_adapter_keys(struct hypervisor_network_adapter *p)
1361 {
1362 p->DroppedPacketsOutgoingSec.key = "Dropped Packets Outgoing/sec";
1363 p->DroppedPacketsIncomingSec.key = "Dropped Packets Incoming/sec";
1364
1365 p->PacketsSentSec.key = "Packets Sent/sec";
1366 p->PacketsReceivedSec.key = "Packets Received/sec";
1367
1368 p->BytesSentSec.key = "Bytes Sent/sec";
1369 p->BytesReceivedSec.key = "Bytes Received/sec";
1370
1371 p->IPsecoffloadBytesReceivedSec.key = "IPsec offload Bytes Receive/sec";
1372 p->IPsecoffloadBytesSentSec.key = "IPsec offload Bytes Sent/sec";
1373 p->DirectedPacketsSentSec.key = "Directed Packets Sent/sec";
1374 p->DirectedPacketsReceivedSec.key = "Directed Packets Received/sec";
1375 p->BroadcastPacketsSentSec.key = "Broadcast Packets Sent/sec";
1376 p->BroadcastPacketsReceivedSec.key = "Broadcast Packets Received/sec";
1377 p->MulticastPacketsSentSec.key = "Multicast Packets Sent/sec";
1378 p->MulticastPacketsReceivedSec.key = "Multicast Packets Received/sec";
1379 }
1380
1381 void dict_hyperv_network_adapter_insert_cb(
1382 const DICTIONARY_ITEM *item __maybe_unused,
1383 void *value,
1384 void *data __maybe_unused)
1385 {
1386 struct hypervisor_network_adapter *p = value;
1387 initialize_hyperv_network_adapter_keys(p);
1388 }
1389
1390 static bool do_hyperv_network_adapter(PERF_DATA_BLOCK *pDataBlock, int update_every, void *data)
1391 {
1392 hyperv_perf_item *item = data;
1393
1394 PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, item->registry_name);
1395 if (!pObjectType)
1396 return false;
1397
1398 PERF_INSTANCE_DEFINITION *pi = NULL;
1399 for (LONG i = 0; i < pObjectType->NumInstances; i++) {
1400 pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
1401 if (!pi)
1402 break;
1403
1404 get_and_sanitize_instance_value(
1405 pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer));
1406
1407 if (strcasecmp(windows_shared_buffer, "_Total") == 0)
1408 continue;
1409
1410 struct hypervisor_network_adapter *p = dictionary_set(item->instance, windows_shared_buffer, NULL, sizeof(*p));
1411
1412 if (!p->collected_metadata) {
1413 p->collected_metadata = true;
1414 }
1415
1416 GET_INSTANCE_COUNTER(DroppedPacketsIncomingSec);
1417 GET_INSTANCE_COUNTER(DroppedPacketsOutgoingSec);
1418
1419 GET_INSTANCE_COUNTER(PacketsReceivedSec);
1420 GET_INSTANCE_COUNTER(PacketsSentSec);
1421
1422 GET_INSTANCE_COUNTER(BytesReceivedSec);
1423 GET_INSTANCE_COUNTER(BytesSentSec);
1424
1425 GET_INSTANCE_COUNTER(IPsecoffloadBytesReceivedSec);
1426 GET_INSTANCE_COUNTER(IPsecoffloadBytesSentSec);
1427
1428 GET_INSTANCE_COUNTER(DirectedPacketsSentSec);
1429 GET_INSTANCE_COUNTER(DirectedPacketsReceivedSec);
1430
1431 GET_INSTANCE_COUNTER(BroadcastPacketsSentSec);
1432 GET_INSTANCE_COUNTER(BroadcastPacketsReceivedSec);
1433
1434 GET_INSTANCE_COUNTER(MulticastPacketsSentSec);
1435 GET_INSTANCE_COUNTER(MulticastPacketsReceivedSec);
1436
1437 if (!p->charts_created) {
1438 p->charts_created = true;
1439 char id[RRD_ID_LENGTH_MAX + 1];
1440 snprintfz(id, RRD_ID_LENGTH_MAX, "%s", windows_shared_buffer);
1441 netdata_fix_chart_name(id);
1442
1443 p->st_dropped_packets = rrdset_create_localhost(
1444 "vm_net_interface_packets_dropped",
1445 id,
1446 NULL,
1447 HYPERV,
1448 HYPERV ".vm_net_interface_packets_dropped",
1449 "VM interface packets dropped",
1450 "drops/s",
1451 _COMMON_PLUGIN_NAME,
1452 _COMMON_PLUGIN_MODULE_NAME,
1453 NETDATA_CHART_PRIO_WINDOWS_HYPERV_VM_NET_INTERFACE_PACKETS_DROPPED,
1454 update_every,
1455 RRDSET_TYPE_LINE);
1456
1457 p->rd_DroppedPacketsIncomingSec =
1458 rrddim_add(p->st_dropped_packets, "incoming", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1459 p->rd_DroppedPacketsOutgoingSec =
1460 rrddim_add(p->st_dropped_packets, "outgoing", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
1461
1462 rrdlabels_add(
1463 p->st_dropped_packets->rrdlabels, "vm_net_interface", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1464
1465 p->st_send_receive_packets = rrdset_create_localhost(
1466 "vm_net_interface_packets",
1467 windows_shared_buffer,
1468 NULL,
1469 HYPERV,
1470 HYPERV ".vm_net_interface_packets",
1471 "VM interface packets",
1472 "packets/s",
1473 _COMMON_PLUGIN_NAME,
1474 _COMMON_PLUGIN_MODULE_NAME,
1475 NETDATA_CHART_PRIO_WINDOWS_HYPERV_VM_NET_INTERFACE_PACKETS,
1476 update_every,
1477 RRDSET_TYPE_LINE);
1478
1479 p->rd_PacketsReceivedSec =
1480 rrddim_add(p->st_send_receive_packets, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1481 p->rd_PacketsSentSec =
1482 rrddim_add(p->st_send_receive_packets, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
1483
1484 rrdlabels_add(
1485 p->st_send_receive_packets->rrdlabels, "vm_net_interface", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1486
1487 p->st_send_receive_bytes = rrdset_create_localhost(
1488 "vm_net_interface_traffic",
1489 windows_shared_buffer,
1490 NULL,
1491 HYPERV,
1492 HYPERV ".vm_net_interface_traffic",
1493 "VM interface traffic",
1494 "kilobits/s",
1495 _COMMON_PLUGIN_NAME,
1496 _COMMON_PLUGIN_MODULE_NAME,
1497 NETDATA_CHART_PRIO_WINDOWS_HYPERV_VM_NET_INTERFACE_TRAFFIC,
1498 update_every,
1499 RRDSET_TYPE_AREA);
1500
1501 p->rd_BytesReceivedSec =
1502 rrddim_add(p->st_send_receive_bytes, "received", NULL, 8, 1000, RRD_ALGORITHM_INCREMENTAL);
1503 p->rd_BytesSentSec =
1504 rrddim_add(p->st_send_receive_bytes, "sent", NULL, -8, 1000, RRD_ALGORITHM_INCREMENTAL);
1505 rrdlabels_add(
1506 p->st_send_receive_bytes->rrdlabels, "vm_net_interface", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1507
1508 p->st_IPsecoffloadBytes = rrdset_create_localhost(
1509 "vm_net_interface_ipsec_traffic",
1510 windows_shared_buffer,
1511 NULL,
1512 HYPERV,
1513 HYPERV ".vm_net_interface_ipsec_traffic",
1514 "VM interface IPSec traffic",
1515 "kilobits/s",
1516 _COMMON_PLUGIN_NAME,
1517 _COMMON_PLUGIN_MODULE_NAME,
1518 NETDATA_CHART_PRIO_WINDOWS_HYPERV_VM_NET_INTERFACE_IPSEC_TRAFFIC,
1519 update_every,
1520 RRDSET_TYPE_AREA);
1521
1522 p->rd_IPsecoffloadBytesReceivedSec =
1523 rrddim_add(p->st_IPsecoffloadBytes, "received", NULL, 8, 1000, RRD_ALGORITHM_INCREMENTAL);
1524 p->rd_IPsecoffloadBytesSentSec =
1525 rrddim_add(p->st_IPsecoffloadBytes, "sent", NULL, -8, 1000, RRD_ALGORITHM_INCREMENTAL);
1526 rrdlabels_add(
1527 p->st_IPsecoffloadBytes->rrdlabels, "vm_net_interface", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1528
1529 p->st_DirectedPackets = rrdset_create_localhost(
1530 "vm_net_interface_directed_packets",
1531 windows_shared_buffer,
1532 NULL,
1533 HYPERV,
1534 HYPERV ".vm_net_interface_directed_packets",
1535 "VM interface directed packets",
1536 "packets/s",
1537 _COMMON_PLUGIN_NAME,
1538 _COMMON_PLUGIN_MODULE_NAME,
1539 NETDATA_CHART_PRIO_WINDOWS_HYPERV_VM_NET_INTERFACE_DIRECTED_PACKETS,
1540 update_every,
1541 RRDSET_TYPE_LINE);
1542
1543 p->rd_DirectedPacketsReceivedSec =
1544 rrddim_add(p->st_DirectedPackets, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1545 p->rd_DirectedPacketsSentSec =
1546 rrddim_add(p->st_DirectedPackets, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
1547 rrdlabels_add(
1548 p->st_DirectedPackets->rrdlabels, "vm_net_interface", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1549
1550 p->st_BroadcastPackets = rrdset_create_localhost(
1551 "vm_net_interface_broadcast_packets",
1552 windows_shared_buffer,
1553 NULL,
1554 HYPERV,
1555 HYPERV ".vm_net_interface_broadcast_packets",
1556 "VM interface broadcast",
1557 "packets/s",
1558 _COMMON_PLUGIN_NAME,
1559 _COMMON_PLUGIN_MODULE_NAME,
1560 NETDATA_CHART_PRIO_WINDOWS_HYPERV_VM_NET_INTERFACE_BROADCAST_PACKETS,
1561 update_every,
1562 RRDSET_TYPE_LINE);
1563
1564 p->rd_BroadcastPacketsReceivedSec =
1565 rrddim_add(p->st_BroadcastPackets, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1566 p->rd_BroadcastPacketsSentSec =
1567 rrddim_add(p->st_BroadcastPackets, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
1568 rrdlabels_add(
1569 p->st_BroadcastPackets->rrdlabels, "vm_net_interface", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1570
1571 p->st_MulticastPackets = rrdset_create_localhost(
1572 "vm_net_interface_multicast_packets",
1573 windows_shared_buffer,
1574 NULL,
1575 HYPERV,
1576 HYPERV ".vm_net_interface_multicast_packets",
1577 "VM interface multicast",
1578 "packets/s",
1579 _COMMON_PLUGIN_NAME,
1580 _COMMON_PLUGIN_MODULE_NAME,
1581 NETDATA_CHART_PRIO_WINDOWS_HYPERV_VM_NET_INTERFACE_MULTICAST_PACKETS,
1582 update_every,
1583 RRDSET_TYPE_LINE);
1584
1585 p->rd_MulticastPacketsReceivedSec =
1586 rrddim_add(p->st_MulticastPackets, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1587 p->rd_MulticastPacketsSentSec =
1588 rrddim_add(p->st_MulticastPackets, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
1589 rrdlabels_add(
1590 p->st_MulticastPackets->rrdlabels, "vm_net_interface", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1591 }
1592
1593 SETP_DIM_VALUE(st_dropped_packets, DroppedPacketsIncomingSec);
1594 SETP_DIM_VALUE(st_dropped_packets, DroppedPacketsOutgoingSec);
1595
1596 SETP_DIM_VALUE(st_send_receive_packets, PacketsReceivedSec);
1597 SETP_DIM_VALUE(st_send_receive_packets, PacketsSentSec);
1598
1599 SETP_DIM_VALUE(st_send_receive_bytes, BytesReceivedSec);
1600 SETP_DIM_VALUE(st_send_receive_bytes, BytesSentSec);
1601
1602 SETP_DIM_VALUE(st_IPsecoffloadBytes, IPsecoffloadBytesReceivedSec);
1603 SETP_DIM_VALUE(st_IPsecoffloadBytes, IPsecoffloadBytesSentSec);
1604
1605 SETP_DIM_VALUE(st_DirectedPackets, DirectedPacketsSentSec);
1606 SETP_DIM_VALUE(st_DirectedPackets, DirectedPacketsReceivedSec);
1607
1608 SETP_DIM_VALUE(st_BroadcastPackets, BroadcastPacketsSentSec);
1609 SETP_DIM_VALUE(st_BroadcastPackets, BroadcastPacketsReceivedSec);
1610
1611 SETP_DIM_VALUE(st_MulticastPackets, MulticastPacketsSentSec);
1612 SETP_DIM_VALUE(st_MulticastPackets, MulticastPacketsReceivedSec);
1613
1614 rrdset_done(p->st_IPsecoffloadBytes);
1615 rrdset_done(p->st_DirectedPackets);
1616 rrdset_done(p->st_BroadcastPackets);
1617 rrdset_done(p->st_MulticastPackets);
1618 rrdset_done(p->st_send_receive_bytes);
1619 rrdset_done(p->st_send_receive_packets);
1620 rrdset_done(p->st_dropped_packets);
1621 }
1622 return true;
1623 }
1624
1625 // Hypervisor Virtual Processor
1626 struct hypervisor_processor {
1627 bool collected_metadata;
1628 bool charts_created;
1629
1630 RRDSET *st_HypervisorProcessor;
1631
1632 DEFINE_RD(GuestRunTime);
1633 DEFINE_RD(HypervisorRunTime);
1634 DEFINE_RD(RemoteRunTime);
1635
1636 RRDSET *st_HypervisorProcessorTotal;
1637 DEFINE_RD(TotalRunTime);
1638
1639 COUNTER_DATA GuestRunTime;
1640 COUNTER_DATA HypervisorRunTime;
1641 COUNTER_DATA RemoteRunTime;
1642 COUNTER_DATA TotalRunTime;
1643 collected_number GuestRunTime_total;
1644 collected_number HypervisorRunTime_total;
1645 collected_number RemoteRunTime_total;
1646 collected_number TotalRunTime_total;
1647 };
1648
1649 void initialize_hyperv_processor_keys(struct hypervisor_processor *p)
1650 {
1651 p->GuestRunTime.key = "% Guest Run Time";
1652 p->HypervisorRunTime.key = "% Hypervisor Run Time";
1653 p->RemoteRunTime.key = "% Remote Run Time";
1654 p->TotalRunTime.key = "% Total Run Time";
1655 p->GuestRunTime_total = 0;
1656 p->HypervisorRunTime_total = 0;
1657 p->RemoteRunTime_total = 0;
1658 p->TotalRunTime_total = 0;
1659 }
1660
1661 void dict_hyperv_processor_insert_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1662 {
1663 struct hypervisor_processor *p = value;
1664 initialize_hyperv_processor_keys(p);
1665 }
1666
1667 static bool do_hyperv_processor(PERF_DATA_BLOCK *pDataBlock, int update_every, void *data)
1668 {
1669 hyperv_perf_item *item = data;
1670
1671 PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, item->registry_name);
1672 if (!pObjectType)
1673 return false;
1674
1675 PERF_INSTANCE_DEFINITION *pi = NULL;
1676 for (LONG i = 0; i < pObjectType->NumInstances; i++) {
1677 pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
1678 if (!pi)
1679 break;
1680
1681 get_and_sanitize_instance_value(
1682 pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer));
1683
1684 if (strcasecmp(windows_shared_buffer, "_Total") == 0)
1685 continue;
1686
1687 char *vm = strchr(windows_shared_buffer, ':');
1688 if (vm)
1689 *vm = '\0';
1690
1691 struct hypervisor_processor *p = dictionary_set(item->instance, windows_shared_buffer, NULL, sizeof(*p));
1692
1693 if (!p->collected_metadata) {
1694 p->collected_metadata = true;
1695 }
1696
1697 GET_INSTANCE_COUNTER(GuestRunTime);
1698 GET_INSTANCE_COUNTER(HypervisorRunTime);
1699 GET_INSTANCE_COUNTER(RemoteRunTime);
1700 GET_INSTANCE_COUNTER(TotalRunTime);
1701
1702 if (!p->charts_created) {
1703 p->charts_created = true;
1704 char id[RRD_ID_LENGTH_MAX + 1];
1705 snprintfz(id, RRD_ID_LENGTH_MAX, "%s", windows_shared_buffer);
1706 netdata_fix_chart_name(id);
1707
1708 p->st_HypervisorProcessorTotal = rrdset_create_localhost(
1709 "vm_cpu_usage",
1710 id,
1711 NULL,
1712 HYPERV,
1713 HYPERV ".vm_cpu_usage",
1714 "VM CPU usage",
1715 "percentage",
1716 _COMMON_PLUGIN_NAME,
1717 _COMMON_PLUGIN_MODULE_NAME,
1718 NETDATA_CHART_PRIO_WINDOWS_HYPERV_VM_CPU_USAGE,
1719 update_every,
1720 RRDSET_TYPE_AREA);
1721
1722 p->rd_TotalRunTime =
1723 rrddim_add(p->st_HypervisorProcessorTotal, "usage", NULL, 1, 1000000, RRD_ALGORITHM_INCREMENTAL);
1724 rrdlabels_add(
1725 p->st_HypervisorProcessorTotal->rrdlabels, "vm_name", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1726
1727 p->st_HypervisorProcessor = rrdset_create_localhost(
1728 "vm_cpu_usage_by_run_context",
1729 windows_shared_buffer,
1730 NULL,
1731 HYPERV,
1732 HYPERV ".vm_cpu_usage_by_run_context",
1733 "VM CPU usage by run context",
1734 "percentage",
1735 _COMMON_PLUGIN_NAME,
1736 _COMMON_PLUGIN_MODULE_NAME,
1737 NETDATA_CHART_PRIO_WINDOWS_HYPERV_VM_CPU_USAGE_BY_RUN_CONTEXT,
1738 update_every,
1739 RRDSET_TYPE_STACKED);
1740
1741 p->rd_GuestRunTime =
1742 rrddim_add(p->st_HypervisorProcessor, "guest", NULL, 1, 1000000, RRD_ALGORITHM_INCREMENTAL);
1743 p->rd_HypervisorRunTime =
1744 rrddim_add(p->st_HypervisorProcessor, "hypervisor", NULL, 1, 1000000, RRD_ALGORITHM_INCREMENTAL);
1745 p->rd_RemoteRunTime =
1746 rrddim_add(p->st_HypervisorProcessor, "remote", NULL, 1, 1000000, RRD_ALGORITHM_INCREMENTAL);
1747
1748 rrdlabels_add(p->st_HypervisorProcessor->rrdlabels, "vm_name", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1749 }
1750
1751 p->GuestRunTime_total += (collected_number)p->GuestRunTime.current.Data;
1752 p->HypervisorRunTime_total += (collected_number)p->HypervisorRunTime.current.Data;
1753 p->RemoteRunTime_total += (collected_number)p->RemoteRunTime.current.Data;
1754 p->TotalRunTime_total += (collected_number)p->TotalRunTime.current.Data;
1755 }
1756
1757 {
1758 struct hypervisor_processor *p;
1759 dfe_start_read(item->instance, p)
1760 {
1761 rrddim_set_by_pointer(
1762 p->st_HypervisorProcessor, p->rd_HypervisorRunTime, (collected_number)p->HypervisorRunTime_total);
1763 rrddim_set_by_pointer(
1764 p->st_HypervisorProcessor, p->rd_GuestRunTime, (collected_number)p->GuestRunTime_total);
1765 rrddim_set_by_pointer(
1766 p->st_HypervisorProcessor, p->rd_RemoteRunTime, (collected_number)p->RemoteRunTime_total);
1767 rrdset_done(p->st_HypervisorProcessor);
1768
1769 rrddim_set_by_pointer(
1770 p->st_HypervisorProcessorTotal, p->rd_TotalRunTime, (collected_number)p->TotalRunTime_total);
1771 rrdset_done(p->st_HypervisorProcessorTotal);
1772
1773 p->GuestRunTime_total = 0;
1774 p->HypervisorRunTime_total = 0;
1775 p->RemoteRunTime_total = 0;
1776 p->TotalRunTime_total = 0;
1777 }
1778 dfe_done(p);
1779 }
1780
1781 return true;
1782 }
1783
1784 hyperv_perf_item hyperv_perf_list[] = {
1785 {.registry_name = "Hyper-V Dynamic Memory VM",
1786 .function_collect = do_hyperv_memory,
1787 .dict_insert_cb = dict_hyperv_memory_insert_cb,
1788 .dict_size = sizeof(struct hypervisor_memory)},
1789
1790 {.registry_name = "Hyper-V VM Vid Partition",
1791 .function_collect = do_hyperv_vid_partition,
1792 .dict_insert_cb = dict_hyperv_partition_insert_cb,
1793 .dict_size = sizeof(struct hypervisor_partition)},
1794
1795 {
1796 .registry_name = "Hyper-V Virtual Machine Health Summary",
1797 .function_collect = do_hyperv_health_summary,
1798 },
1799
1800 {
1801 .registry_name = "Hyper-V Hypervisor Root Partition",
1802 .function_collect = do_hyperv_root_partition,
1803 .dict_insert_cb = dict_hyperv_root_partition_insert_cb,
1804 .dict_size = sizeof(struct hypervisor_root_partition),
1805 },
1806
1807 {.registry_name = "Hyper-V Virtual Storage Device",
1808 .function_collect = do_hyperv_storage_device,
1809 .dict_insert_cb = dict_hyperv_storage_device_insert_cb,
1810 .dict_size = sizeof(struct hypervisor_storage_device)},
1811
1812 {.registry_name = "Hyper-V Virtual Switch",
1813 .function_collect = do_hyperv_switch,
1814 .dict_insert_cb = dict_hyperv_switch_insert_cb,
1815 .dict_size = sizeof(struct hypervisor_switch)},
1816
1817 {.registry_name = "Hyper-V Virtual Network Adapter",
1818 .function_collect = do_hyperv_network_adapter,
1819 .dict_insert_cb = dict_hyperv_network_adapter_insert_cb,
1820 .dict_size = sizeof(struct hypervisor_network_adapter)},
1821
1822 {.registry_name = "Hyper-V Hypervisor Virtual Processor",
1823 .function_collect = do_hyperv_processor,
1824 .dict_insert_cb = dict_hyperv_processor_insert_cb,
1825 .dict_size = sizeof(struct hypervisor_processor)},
1826
1827 {.registry_name = NULL, .function_collect = NULL}};
1828
1829 int do_PerflibHyperV(int update_every, usec_t dt __maybe_unused)
1830 {
1831 static bool initialized = false;
1832
1833 if (unlikely(!initialized)) {
1834 for (int i = 0; hyperv_perf_list[i].registry_name != NULL; i++) {
1835 hyperv_perf_item *item = &hyperv_perf_list[i];
1836 if (item->dict_insert_cb) {
1837 item->instance = dictionary_create_advanced(DICT_PERF_OPTION, NULL, item->dict_size);
1838 dictionary_register_insert_callback(item->instance, item->dict_insert_cb, NULL);
1839 }
1840 }
1841 initialized = true;
1842 }
1843
1844 for (int i = 0; hyperv_perf_list[i].registry_name != NULL; i++) {
1845 // Find the registry ID using the registry name
1846 DWORD id = RegistryFindIDByName(hyperv_perf_list[i].registry_name);
1847 if (id == PERFLIB_REGISTRY_NAME_NOT_FOUND)
1848 continue;
1849
1850 // Get the performance data using the registry ID
1851 PERF_DATA_BLOCK *pDataBlock = perflibGetPerformanceData(id);
1852 if (!pDataBlock)
1853 continue;
1854
1855 hyperv_perf_list[i].function_collect(pDataBlock, update_every, &hyperv_perf_list[i]);
1856 }
1857 return 0;
1858 }