1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 **/
19
20 #include "common.h"
21 #include "sysinfo.h"
22 #include "stats.h"
23 #include "log.h"
24
SYSTEM_CPU_NUM(AGENT_REQUEST * request,AGENT_RESULT * result)25 int SYSTEM_CPU_NUM(AGENT_REQUEST *request, AGENT_RESULT *result)
26 {
27 char *tmp;
28 int name;
29 long ncpu;
30
31 if (1 < request->nparam)
32 {
33 SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
34 return SYSINFO_RET_FAIL;
35 }
36
37 tmp = get_rparam(request, 0);
38
39 if (NULL == tmp || '\0' == *tmp || 0 == strcmp(tmp, "online"))
40 name = _SC_NPROCESSORS_ONLN;
41 else if (0 == strcmp(tmp, "max"))
42 name = _SC_NPROCESSORS_CONF;
43 else
44 {
45 SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
46 return SYSINFO_RET_FAIL;
47 }
48
49 if (-1 == (ncpu = sysconf(name)))
50 {
51 SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain number of CPUs."));
52 return SYSINFO_RET_FAIL;
53 }
54
55 SET_UI64_RESULT(result, ncpu);
56
57 return SYSINFO_RET_OK;
58 }
59
SYSTEM_CPU_UTIL(AGENT_REQUEST * request,AGENT_RESULT * result)60 int SYSTEM_CPU_UTIL(AGENT_REQUEST *request, AGENT_RESULT *result)
61 {
62 char *tmp;
63 int cpu_num, state, mode;
64
65 if (3 < request->nparam)
66 {
67 SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
68 return SYSINFO_RET_FAIL;
69 }
70
71 tmp = get_rparam(request, 0);
72
73 if (NULL == tmp || '\0' == *tmp || 0 == strcmp(tmp, "all"))
74 cpu_num = ZBX_CPUNUM_ALL;
75 else if (SUCCEED != is_uint31_1(tmp, &cpu_num))
76 {
77 SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
78 return SYSINFO_RET_FAIL;
79 }
80
81 tmp = get_rparam(request, 1);
82
83 if (NULL == tmp || '\0' == *tmp || 0 == strcmp(tmp, "user"))
84 state = ZBX_CPU_STATE_USER;
85 else if (0 == strcmp(tmp, "iowait"))
86 state = ZBX_CPU_STATE_IOWAIT;
87 else if (0 == strcmp(tmp, "system"))
88 state = ZBX_CPU_STATE_SYSTEM;
89 else if (0 == strcmp(tmp, "idle"))
90 state = ZBX_CPU_STATE_IDLE;
91 else
92 {
93 SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
94 return SYSINFO_RET_FAIL;
95 }
96
97 tmp = get_rparam(request, 2);
98
99 if (NULL == tmp || '\0' == *tmp || 0 == strcmp(tmp, "avg1"))
100 mode = ZBX_AVG1;
101 else if (0 == strcmp(tmp, "avg5"))
102 mode = ZBX_AVG5;
103 else if (0 == strcmp(tmp, "avg15"))
104 mode = ZBX_AVG15;
105 else
106 {
107 SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter."));
108 return SYSINFO_RET_FAIL;
109 }
110
111 return get_cpustat(result, cpu_num, state, mode);
112 }
113
114 #if defined(HAVE_KSTAT_H) && !defined(HAVE_GETLOADAVG)
get_kstat_system_misc(char * key,int * value,char ** error)115 static int get_kstat_system_misc(char *key, int *value, char **error)
116 {
117 kstat_ctl_t *kc;
118 kstat_t *ksp;
119 kstat_named_t *kn = NULL;
120 int ret = FAIL;
121
122 if (NULL == (kc = kstat_open()))
123 {
124 *error = zbx_dsprintf(NULL, "Cannot open kernel statistics facility: %s", zbx_strerror(errno));
125 return ret;
126 }
127
128 if (NULL == (ksp = kstat_lookup(kc, "unix", 0, "system_misc")))
129 {
130 *error = zbx_dsprintf(NULL, "Cannot look up in kernel statistics facility: %s", zbx_strerror(errno));
131 goto close;
132 }
133
134 if (-1 == kstat_read(kc, ksp, NULL))
135 {
136 *error = zbx_dsprintf(NULL, "Cannot read from kernel statistics facility: %s", zbx_strerror(errno));
137 goto close;
138 }
139
140 if (NULL == (kn = (kstat_named_t *)kstat_data_lookup(ksp, key)))
141 {
142 *error = zbx_dsprintf(NULL, "Cannot look up data in kernel statistics facility: %s",
143 zbx_strerror(errno));
144 goto close;
145 }
146
147 *value = get_kstat_numeric_value(kn);
148
149 ret = SUCCEED;
150 close:
151 kstat_close(kc);
152
153 return ret;
154 }
155 #endif
156
SYSTEM_CPU_LOAD(AGENT_REQUEST * request,AGENT_RESULT * result)157 int SYSTEM_CPU_LOAD(AGENT_REQUEST *request, AGENT_RESULT *result)
158 {
159 char *tmp;
160 double value;
161 int per_cpu = 1, cpu_num;
162 #if defined(HAVE_GETLOADAVG)
163 int mode;
164 double load[ZBX_AVG_COUNT];
165 #elif defined(HAVE_KSTAT_H)
166 char *key, *error;
167 int load;
168 #endif
169 if (2 < request->nparam)
170 {
171 SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
172 return SYSINFO_RET_FAIL;
173 }
174
175 tmp = get_rparam(request, 0);
176
177 if (NULL == tmp || '\0' == *tmp || 0 == strcmp(tmp, "all"))
178 per_cpu = 0;
179 else if (0 != strcmp(tmp, "percpu"))
180 {
181 SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
182 return SYSINFO_RET_FAIL;
183 }
184
185 #if defined(HAVE_GETLOADAVG)
186 tmp = get_rparam(request, 1);
187
188 if (NULL == tmp || '\0' == *tmp || 0 == strcmp(tmp, "avg1"))
189 mode = ZBX_AVG1;
190 else if (0 == strcmp(tmp, "avg5"))
191 mode = ZBX_AVG5;
192 else if (0 == strcmp(tmp, "avg15"))
193 mode = ZBX_AVG15;
194 else
195 {
196 SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
197 return SYSINFO_RET_FAIL;
198 }
199
200 if (mode >= getloadavg(load, 3))
201 {
202 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain load average: %s", zbx_strerror(errno)));
203 return SYSINFO_RET_FAIL;
204 }
205
206 value = load[mode];
207 #elif defined(HAVE_KSTAT_H)
208 tmp = get_rparam(request, 1);
209
210 if (NULL == tmp || '\0' == *tmp || 0 == strcmp(tmp, "avg1"))
211 key = "avenrun_1min";
212 else if (0 == strcmp(tmp, "avg5"))
213 key = "avenrun_5min";
214 else if (0 == strcmp(tmp, "avg15"))
215 key = "avenrun_15min";
216 else
217 {
218 SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
219 return SYSINFO_RET_FAIL;
220 }
221
222 if (FAIL == get_kstat_system_misc(key, &load, &error))
223 {
224 SET_MSG_RESULT(result, error);
225 return SYSINFO_RET_FAIL;
226 }
227
228 value = (double)load / FSCALE;
229 #else
230 SET_MSG_RESULT(result, zbx_strdup(NULL, "Agent was compiled without support for CPU load information."));
231 return SYSINFO_RET_FAIL;
232 #endif
233 if (1 == per_cpu)
234 {
235 if (0 >= (cpu_num = sysconf(_SC_NPROCESSORS_ONLN)))
236 {
237 SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain number of CPUs."));
238 return SYSINFO_RET_FAIL;
239 }
240 value /= cpu_num;
241 }
242
243 SET_DBL_RESULT(result, value);
244
245 return SYSINFO_RET_OK;
246 }
247
SYSTEM_CPU_SWITCHES(AGENT_REQUEST * request,AGENT_RESULT * result)248 int SYSTEM_CPU_SWITCHES(AGENT_REQUEST *request, AGENT_RESULT *result)
249 {
250 kstat_ctl_t *kc;
251 kstat_t *k;
252 cpu_stat_t *cpu;
253 int cpu_count = 0;
254 double swt_count = 0.0;
255
256 if (NULL == (kc = kstat_open()))
257 {
258 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot open kernel statistics facility: %s",
259 zbx_strerror(errno)));
260 return SYSINFO_RET_FAIL;
261 }
262
263 k = kc->kc_chain;
264
265 while (NULL != k)
266 {
267 if (0 == strncmp(k->ks_name, "cpu_stat", 8) && -1 != kstat_read(kc, k, NULL))
268 {
269 cpu = (cpu_stat_t *)k->ks_data;
270 swt_count += (double)cpu->cpu_sysinfo.pswitch;
271 cpu_count += 1;
272 }
273
274 k = k->ks_next;
275 }
276
277 kstat_close(kc);
278
279 if (0 == cpu_count)
280 {
281 SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot find CPU information."));
282 return SYSINFO_RET_FAIL;
283 }
284
285 SET_UI64_RESULT(result, swt_count);
286
287 return SYSINFO_RET_OK;
288 }
289
SYSTEM_CPU_INTR(AGENT_REQUEST * request,AGENT_RESULT * result)290 int SYSTEM_CPU_INTR(AGENT_REQUEST *request, AGENT_RESULT *result)
291 {
292 kstat_ctl_t *kc;
293 kstat_t *k;
294 cpu_stat_t *cpu;
295 int cpu_count = 0;
296 double intr_count = 0.0;
297
298 if (NULL == (kc = kstat_open()))
299 {
300 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot open kernel statistics facility: %s",
301 zbx_strerror(errno)));
302 return SYSINFO_RET_FAIL;
303 }
304
305 k = kc->kc_chain;
306
307 while (NULL != k)
308 {
309 if (0 == strncmp(k->ks_name, "cpu_stat", 8) && -1 != kstat_read(kc, k, NULL))
310 {
311 cpu = (cpu_stat_t *)k->ks_data;
312 intr_count += (double)cpu->cpu_sysinfo.intr;
313 cpu_count += 1;
314 }
315
316 k = k->ks_next;
317 }
318
319 kstat_close(kc);
320
321 if (0 == cpu_count)
322 {
323 SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot find CPU information."));
324 return SYSINFO_RET_FAIL;
325 }
326
327 SET_UI64_RESULT(result, intr_count);
328
329 return SYSINFO_RET_OK;
330 }
331