Add netisr (softnet) charts to FreeBSD plugin
Vladimir Kobal committed
Dec 13, 2016 at 11:55 UTC
417f4106464da4b8a6fe26e42eb0ac7fbd2204e4
1 file changed
+130
-10
src/freebsd_sysctl.c
+130
-10
@@ -12,6 +12,8 @@
12
#include <sys/shm.h>
13
#include <sys/msg.h>
14
#undef _KERNEL
15
+// NEEDED BY: struct sysctl_netisr_workstream, struct sysctl_netisr_work
16
+#include <net/netisr.h>
17
// NEEDED BY: do_disk_io
18
#define RRD_TYPE_DISK "disk"
19
@@ -24,7 +26,7 @@ int do_freebsd_sysctl(int update_every, usec_t dt) {
26
static int do_cpu = -1, do_cpu_cores = -1, do_interrupts = -1, do_context = -1, do_forks = -1, do_processes = -1,
27
do_loadavg = -1, do_all_processes = -1, do_disk_io = -1, do_swap = -1, do_ram = -1, do_swapio = -1,
28
do_pgfaults = -1, do_committed = -1, do_ipc_semaphores = -1, do_ipc_shared_mem = -1, do_ipc_msg_queues = -1,
27
- do_dev_intr = -1, do_soft_intr = -1;
29
+ do_dev_intr = -1, do_soft_intr = -1, do_netisr = -1, do_netisr_per_core = -1;
30
31
if (unlikely(do_cpu == -1)) {
32
do_cpu = config_get_boolean("plugin:freebsd:sysctl", "cpu utilization", 1);
@@ -46,38 +48,43 @@ int do_freebsd_sysctl(int update_every, usec_t dt) {
48
do_ipc_semaphores = config_get_boolean("plugin:freebsd:sysctl", "ipc semaphores", 1);
49
do_ipc_shared_mem = config_get_boolean("plugin:freebsd:sysctl", "ipc shared memory", 1);
50
do_ipc_msg_queues = config_get_boolean("plugin:freebsd:sysctl", "ipc message queues", 1);
51
+ do_netisr = config_get_boolean("plugin:freebsd:sysctl", "netisr", 1);
52
+ do_netisr_per_core = config_get_boolean("plugin:freebsd:sysctl", "netisr per core", 1);
53
}
54
55
RRDSET *st;
56
57
int system_pagesize = getpagesize(); // wouldn't it be better to get value directly from hw.pagesize?
54
- int i;
58
+ int i, n;
59
+ int common_error = 0;
60
56
-// NEEDED BY: do_loadavg
61
+ // NEEDED BY: do_loadavg
62
static usec_t last_loadavg_usec = 0;
63
struct loadavg sysload;
64
60
-// NEEDED BY: do_cpu, do_cpu_cores
65
+ // NEEDED BY: do_cpu, do_cpu_cores
66
long cp_time[CPUSTATES];
67
63
-// NEEDED BY: do_cpu_cores
68
+ // NEEDED BY: du_cpu_cores, do_netisr, do_netisr_per_core
69
int ncpus;
70
+
71
+ // NEEDED BY: do_cpu_cores
72
static long *pcpu_cp_time = NULL;
73
char cpuid[8]; // no more than 4 digits expected
74
68
-// NEEDED BY: do_all_processes, do_processes
75
+ // NEEDED BY: do_all_processes, do_processes
76
struct vmtotal vmtotal_data;
77
71
-// NEEDED BY: do_context, do_forks
78
+ // NEEDED BY: do_context, do_forks
79
u_int u_int_data;
80
74
-// NEEDED BY: do_interrupts
81
+ // NEEDED BY: do_interrupts
82
size_t intrcnt_size;
83
unsigned long nintr = 0;
84
static unsigned long *intrcnt = NULL;
85
unsigned long long totalintr = 0;
86
80
-// NEEDED BY: do_disk_io
87
+ // NEEDED BY: do_disk_io
88
#define BINTIME_SCALE 5.42101086242752217003726400434970855712890625e-17 // this is 1000/2^64
89
int numdevs;
90
static void *devstat_data = NULL;
@@ -138,6 +145,20 @@ int do_freebsd_sysctl(int update_every, usec_t dt) {
145
} ipc_msq = {0, 0, 0, 0, 0};
146
static struct msqid_kernel *ipc_msq_data = NULL;
147
148
+ // NEEDED BY: do_netisr, do_netisr_per_core
149
+ size_t netisr_workstream_size;
150
+ size_t netisr_work_size;
151
+ unsigned long num_netisr_workstreams = 0, num_netisr_works = 0;
152
+ static struct sysctl_netisr_workstream *netisr_workstream = NULL;
153
+ static struct sysctl_netisr_work *netisr_work = NULL;
154
+ static struct netisr_stats {
155
+ collected_number dispatched;
156
+ collected_number hybrid_dispatched;
157
+ collected_number qdrops;
158
+ collected_number queued;
159
+ } *netisr_stats = NULL;
160
+ char netstat_cpuid[21]; // no more than 4 digits expected
161
+
162
// --------------------------------------------------------------------
163
164
if (last_loadavg_usec <= dt) {
@@ -871,7 +892,7 @@ int do_freebsd_sysctl(int update_every, usec_t dt) {
892
893
st = rrdset_find("system.ipc_msq_queues");
894
if (unlikely(!st)) {
874
- st = rrdset_create("system", "ipc_msq_queues", NULL, "ipc message queues", NULL, "Number of IPC Message Queues", "queues", 900, rrd_update_every, RRDSET_TYPE_AREA);
895
+ st = rrdset_create("system", "ipc_msq_queues", NULL, "ipc message queues", NULL, "Number of IPC Message Queues", "queues", 990, rrd_update_every, RRDSET_TYPE_AREA);
896
rrddim_add(st, "queues", NULL, 1, 1, RRDDIM_ABSOLUTE);
897
}
898
else rrdset_next(st);
@@ -909,5 +930,104 @@ int do_freebsd_sysctl(int update_every, usec_t dt) {
930
}
931
}
932
933
+ // --------------------------------------------------------------------
934
+
935
+ if (likely(do_netisr || do_netisr_per_core)) {
936
+ if (unlikely(GETSYSCTL("kern.smp.cpus", ncpus))) {
937
+ common_error = 1;
938
+ } else if (unlikely(ncpus > 9999)) {
939
+ error("FREEBSD: There are more than 4 digits in cpu cores number");
940
+ common_error = 1;
941
+ } else if (unlikely(sysctlbyname("net.isr.workstream", NULL, &netisr_workstream_size, NULL, 0) == -1)) {
942
+ error("FREEBSD: sysctl(net.isr.workstream...) failed: %s", strerror(errno));
943
+ common_error = 1;
944
+ } else if (unlikely(sysctlbyname("net.isr.work", NULL, &netisr_work_size, NULL, 0) == -1)) {
945
+ error("FREEBSD: sysctl(net.isr.work...) failed: %s", strerror(errno));
946
+ common_error = 1;
947
+ } else {
948
+ num_netisr_workstreams = netisr_workstream_size / sizeof(struct sysctl_netisr_workstream);
949
+ netisr_workstream = reallocz(netisr_workstream, num_netisr_workstreams * sizeof(struct sysctl_netisr_workstream));
950
+ if (unlikely(getsysctl("net.isr.workstream", netisr_workstream, num_netisr_workstreams * sizeof(struct sysctl_netisr_workstream)))){
951
+ common_error = 1;
952
+ } else {
953
+ num_netisr_works = netisr_work_size / sizeof(struct sysctl_netisr_work);
954
+ netisr_work = reallocz(netisr_work, num_netisr_works * sizeof(struct sysctl_netisr_work));
955
+ if (unlikely(getsysctl("net.isr.work", netisr_work, num_netisr_works * sizeof(struct sysctl_netisr_work)))){
956
+ common_error = 1;
957
+ }
958
+ }
959
+ }
960
+ if (unlikely(common_error)) {
961
+ do_netisr = 0;
962
+ error("DISABLED: system.softnet_stat");
963
+ do_netisr_per_core = 0;
964
+ error("DISABLED: system.cpuX_softnet_stat");
965
+ common_error = 0;
966
+ } else {
967
+ netisr_stats = reallocz(netisr_stats, (ncpus + 1) * sizeof(struct netisr_stats));
968
+ bzero(netisr_stats, (ncpus + 1) * sizeof(struct netisr_stats));
969
+ for (i = 0; i < num_netisr_workstreams; i++) {
970
+ for (n = 0; n < num_netisr_works; n++) {
971
+ if (netisr_workstream[i].snws_wsid == netisr_work[n].snw_wsid) {
972
+ netisr_stats[netisr_workstream[i].snws_cpu].dispatched += netisr_work[n].snw_dispatched;
973
+ netisr_stats[netisr_workstream[i].snws_cpu].hybrid_dispatched += netisr_work[n].snw_hybrid_dispatched;
974
+ netisr_stats[netisr_workstream[i].snws_cpu].qdrops += netisr_work[n].snw_qdrops;
975
+ netisr_stats[netisr_workstream[i].snws_cpu].queued += netisr_work[n].snw_queued;
976
+ }
977
+ }
978
+ }
979
+ for (i = 0; i < ncpus; i++) {
980
+ netisr_stats[ncpus].dispatched += netisr_stats[i].dispatched;
981
+ netisr_stats[ncpus].hybrid_dispatched += netisr_stats[i].hybrid_dispatched;
982
+ netisr_stats[ncpus].qdrops += netisr_stats[i].qdrops;
983
+ netisr_stats[ncpus].queued += netisr_stats[i].queued;
984
+ }
985
+ }
986
+ }
987
+
988
+ // --------------------------------------------------------------------
989
+
990
+ if (likely(do_netisr)) {
991
+ st = rrdset_find_bytype("system", "softnet_stat");
992
+ if (unlikely(!st)) {
993
+ st = rrdset_create("system", "softnet_stat", NULL, "softnet_stat", NULL, "System softnet_stat", "events/s", 955, update_every, RRDSET_TYPE_LINE);
994
+ rrddim_add(st, "dispatched", NULL, 1, 1, RRDDIM_INCREMENTAL);
995
+ rrddim_add(st, "hybrid_dispatched", NULL, 1, 1, RRDDIM_INCREMENTAL);
996
+ rrddim_add(st, "qdrops", NULL, 1, 1, RRDDIM_INCREMENTAL);
997
+ rrddim_add(st, "queued", NULL, 1, 1, RRDDIM_INCREMENTAL);
998
+ }
999
+ else rrdset_next(st);
1000
+
1001
+ rrddim_set(st, "dispatched", netisr_stats[ncpus].dispatched);
1002
+ rrddim_set(st, "hybrid_dispatched", netisr_stats[ncpus].hybrid_dispatched);
1003
+ rrddim_set(st, "qdrops", netisr_stats[ncpus].qdrops);
1004
+ rrddim_set(st, "queued", netisr_stats[ncpus].queued);
1005
+ rrdset_done(st);
1006
+ }
1007
+
1008
+ // --------------------------------------------------------------------
1009
+
1010
+ if (likely(do_netisr_per_core)) {
1011
+ for (i = 0; i < ncpus ;i++) {
1012
+ snprintfz(netstat_cpuid, 21, "cpu%d_softnet_stat", i);
1013
+
1014
+ st = rrdset_find_bytype("cpu", netstat_cpuid);
1015
+ if (unlikely(!st)) {
1016
+ st = rrdset_create("cpu", netstat_cpuid, NULL, "softnet_stat", NULL, "Per CPU netisr statistics", "events/s", 1101 + i, update_every, RRDSET_TYPE_LINE);
1017
+ rrddim_add(st, "dispatched", NULL, 1, 1, RRDDIM_INCREMENTAL);
1018
+ rrddim_add(st, "hybrid_dispatched", NULL, 1, 1, RRDDIM_INCREMENTAL);
1019
+ rrddim_add(st, "qdrops", NULL, 1, 1, RRDDIM_INCREMENTAL);
1020
+ rrddim_add(st, "queued", NULL, 1, 1, RRDDIM_INCREMENTAL);
1021
+ }
1022
+ else rrdset_next(st);
1023
+
1024
+ rrddim_set(st, "dispatched", netisr_stats[i].dispatched);
1025
+ rrddim_set(st, "hybrid_dispatched", netisr_stats[i].hybrid_dispatched);
1026
+ rrddim_set(st, "qdrops", netisr_stats[i].qdrops);
1027
+ rrddim_set(st, "queued", netisr_stats[i].queued);
1028
+ rrdset_done(st);
1029
+ }
1030
+ }
1031
+
1032
return 0;
1033
}