02e34b16346e7ff0fce92402c7c39b434ad418f8
[oonf.git] / src-plugins / generic / systeminfo / systeminfo.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon version 2 (olsrd2)
4  * Copyright (c) 2004-2015, the olsr.org team - see HISTORY file
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its
18  *   contributors may be used to endorse or promote products derived
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
40  */
41
42 /**
43  * @file
44  */
45
46 #include <stdio.h>
47
48 #include "common/autobuf.h"
49 #include "common/common_types.h"
50 #include "common/netaddr.h"
51 #include "common/netaddr_acl.h"
52 #include "common/string.h"
53 #include "common/template.h"
54
55 #include "core/oonf_logging.h"
56 #include "core/oonf_subsystem.h"
57 #include "subsystems/oonf_clock.h"
58 #include "subsystems/oonf_telnet.h"
59 #include "subsystems/oonf_viewer.h"
60
61 #include "systeminfo/systeminfo.h"
62
63 /* definitions */
64 #define LOG_SYSTEMINFO _oonf_systeminfo_subsystem.logging
65
66 /* prototypes */
67 static int _init(void);
68 static void _cleanup(void);
69
70 static enum oonf_telnet_result _cb_systeminfo(struct oonf_telnet_data *con);
71 static enum oonf_telnet_result _cb_systeminfo_help(struct oonf_telnet_data *con);
72
73 static void _initialize_time_values(struct oonf_viewer_template *template);
74 static void _initialize_version_values(struct oonf_viewer_template *template);
75 static void _initialize_memory_values(struct oonf_viewer_template *template, struct oonf_class *c);
76 static void _initialize_timer_values(struct oonf_viewer_template *template, struct oonf_timer_class *tc);
77 static void _initialize_socket_values(struct oonf_viewer_template *template, struct oonf_socket_entry *sock);
78 static void _initialize_logging_values(struct oonf_viewer_template *template, enum oonf_log_source source);
79
80 static int _cb_create_text_time(struct oonf_viewer_template *);
81 static int _cb_create_text_version(struct oonf_viewer_template *);
82 static int _cb_create_text_memory(struct oonf_viewer_template *);
83 static int _cb_create_text_timer(struct oonf_viewer_template *);
84 static int _cb_create_text_socket(struct oonf_viewer_template *);
85 static int _cb_create_text_logging(struct oonf_viewer_template *);
86
87 /*
88  * list of template keys and corresponding buffers for values.
89  *
90  * The keys are API, so they should not be changed after published
91  */
92
93 /*! template key for system wall-time */
94 #define KEY_TIME_SYSTEM "time_system"
95
96 /*! template key for internal OONF relative timestamp */
97 #define KEY_TIME_INTERNAL "time_internal"
98
99 /*! template key for version text */
100 #define KEY_VERSION_TEXT "version_text"
101
102 /*! template key for version git commit */
103 #define KEY_VERSION_COMMIT "version_commit"
104
105 /*! template key for statistic object name */
106 #define KEY_STATISTICS_NAME "statistics_name"
107
108 /*! template key for current memory usage */
109 #define KEY_MEMORY_USAGE "memory_usage"
110
111 /*! template key for memory freelist size */
112 #define KEY_MEMORY_FREELIST "memory_freelist"
113
114 /*! template key for total memory allocations */
115 #define KEY_MEMORY_ALLOC "memory_alloc"
116
117 /*! template key for recycled memory blocks */
118 #define KEY_MEMORY_RECYCLED "memory_recycled"
119
120 /*! template key for timer usage */
121 #define KEY_TIMER_USAGE "timer_usage"
122
123 /*! template key for timer changes */
124 #define KEY_TIMER_CHANGE "timer_change"
125
126 /*! template key for timer fired */
127 #define KEY_TIMER_FIRE "timer_fire"
128
129 /*! template key for timer long usage events*/
130 #define KEY_TIMER_LONG "timer_long"
131
132 /*! template key for socket receive events */
133 #define KEY_SOCKET_RECV "socket_recv"
134
135 /*! template key for socket send events */
136 #define KEY_SOCKET_SEND "socket_send"
137
138 /*! template key for socket long usage events */
139 #define KEY_SOCKET_LONG "socket_long"
140
141 /*! template key for name of logging source */
142 #define KEY_LOG_SOURCE "log_source"
143
144 /*! template key for number of warnings per logging source */
145 #define KEY_LOG_WARNINGS "log_warnings"
146
147 /*
148  * buffer space for values that will be assembled
149  * into the output of the plugin
150  */
151 static struct oonf_walltime_str _value_system_time;
152 static struct isonumber_str _value_internal_time;
153
154 static char _value_version_text[256];
155 static char _value_version_commit[21];
156
157 static char _value_stat_name[256];
158
159 static struct isonumber_str _value_memory_usage;
160 static struct isonumber_str _value_memory_freelist;
161 static struct isonumber_str _value_memory_alloc;
162 static struct isonumber_str _value_memory_recycled;
163
164 static struct isonumber_str _value_timer_usage;
165 static struct isonumber_str _value_timer_change;
166 static struct isonumber_str _value_timer_fire;
167 static struct isonumber_str _value_timer_long;
168
169 static struct isonumber_str _value_socket_recv;
170 static struct isonumber_str _value_socket_send;
171 static struct isonumber_str _value_socket_long;
172
173 static char _value_log_source[64];
174 static struct isonumber_str _value_log_warnings;
175
176 /* definition of the template data entries for JSON and table output */
177 static struct abuf_template_data_entry _tde_time_key[] = {
178   { KEY_TIME_SYSTEM, _value_system_time.buf, true },
179   { KEY_TIME_INTERNAL, _value_internal_time.buf, true },
180 };
181 static struct abuf_template_data_entry _tde_version_key[] = {
182   { KEY_VERSION_TEXT, _value_version_text, true },
183   { KEY_VERSION_COMMIT, _value_version_commit, true },
184 };
185 static struct abuf_template_data_entry _tde_memory_key[] = {
186   { KEY_STATISTICS_NAME, _value_stat_name, true },
187   { KEY_MEMORY_USAGE, _value_memory_usage.buf, false },
188   { KEY_MEMORY_FREELIST, _value_memory_freelist.buf, false },
189   { KEY_MEMORY_ALLOC, _value_memory_alloc.buf, false },
190   { KEY_MEMORY_RECYCLED, _value_memory_recycled.buf, false },
191 };
192 static struct abuf_template_data_entry _tde_timer_key[] = {
193   { KEY_STATISTICS_NAME, _value_stat_name, true },
194   { KEY_TIMER_USAGE, _value_timer_usage.buf, false },
195   { KEY_TIMER_CHANGE, _value_timer_change.buf, false },
196   { KEY_TIMER_FIRE, _value_timer_fire.buf, false },
197   { KEY_TIMER_LONG, _value_timer_long.buf, false },
198 };
199 static struct abuf_template_data_entry _tde_socket_key[] = {
200   { KEY_STATISTICS_NAME, _value_stat_name, true },
201   { KEY_SOCKET_RECV, _value_socket_recv.buf, false },
202   { KEY_SOCKET_SEND, _value_socket_send.buf, false },
203   { KEY_SOCKET_LONG, _value_socket_long.buf, false },
204 };
205 static struct abuf_template_data_entry _tde_logging_key[] = {
206   { KEY_LOG_SOURCE, _value_log_source, true },
207   { KEY_LOG_WARNINGS, _value_log_warnings.buf, false },
208 };
209
210 static struct abuf_template_storage _template_storage;
211
212 /* Template Data objects (contain one or more Template Data Entries) */
213 static struct abuf_template_data _td_time[] = {
214   { _tde_time_key, ARRAYSIZE(_tde_time_key) },
215 };
216 static struct abuf_template_data _td_version[] = {
217   { _tde_version_key, ARRAYSIZE(_tde_version_key) },
218 };
219 static struct abuf_template_data _td_memory[] = {
220   { _tde_memory_key, ARRAYSIZE(_tde_memory_key) },
221 };
222 static struct abuf_template_data _td_timer[] = {
223   { _tde_timer_key, ARRAYSIZE(_tde_timer_key) },
224 };
225 static struct abuf_template_data _td_socket[] = {
226   { _tde_socket_key, ARRAYSIZE(_tde_socket_key) },
227 };
228 static struct abuf_template_data _td_logging[] = {
229   { _tde_logging_key, ARRAYSIZE(_tde_logging_key) },
230 };
231
232 /* OONF viewer templates (based on Template Data arrays) */
233 static struct oonf_viewer_template _templates[] = {
234   {
235     .data = _td_time,
236     .data_size = ARRAYSIZE(_td_time),
237     .json_name = "time",
238     .cb_function = _cb_create_text_time,
239   },
240   {
241     .data = _td_version,
242     .data_size = ARRAYSIZE(_td_version),
243     .json_name = "version",
244     .cb_function = _cb_create_text_version,
245   },
246   {
247     .data = _td_memory,
248     .data_size = ARRAYSIZE(_td_memory),
249     .json_name = "memory",
250     .cb_function = _cb_create_text_memory,
251   },
252   {
253     .data = _td_timer,
254     .data_size = ARRAYSIZE(_td_timer),
255     .json_name = "timer",
256     .cb_function = _cb_create_text_timer,
257   },
258   {
259     .data = _td_socket,
260     .data_size = ARRAYSIZE(_td_socket),
261     .json_name = "socket",
262     .cb_function = _cb_create_text_socket,
263   },
264   {
265     .data = _td_logging,
266     .data_size = ARRAYSIZE(_td_logging),
267     .json_name = "logging",
268     .cb_function = _cb_create_text_logging,
269   },
270 };
271
272 /* telnet command of this plugin */
273 static struct oonf_telnet_command _telnet_commands[] = {
274   TELNET_CMD(OONF_SYSTEMINFO_SUBSYSTEM, _cb_systeminfo, "", .help_handler = _cb_systeminfo_help),
275 };
276
277 /* plugin declaration */
278 static const char *_dependencies[] = {
279   OONF_CLOCK_SUBSYSTEM,
280   OONF_TELNET_SUBSYSTEM,
281   OONF_VIEWER_SUBSYSTEM,
282 };
283
284 static struct oonf_subsystem _olsrv2_systeminfo_subsystem = {
285   .name = OONF_SYSTEMINFO_SUBSYSTEM,
286   .dependencies = _dependencies,
287   .dependencies_count = ARRAYSIZE(_dependencies),
288   .descr = "OLSRv2 system info plugin",
289   .author = "Henning Rogge",
290   .init = _init,
291   .cleanup = _cleanup,
292 };
293 DECLARE_OONF_PLUGIN(_olsrv2_systeminfo_subsystem);
294
295 /**
296  * Initialize plugin
297  * @return -1 if an error happened, 0 otherwise
298  */
299 static int
300 _init(void) {
301   oonf_telnet_add(&_telnet_commands[0]);
302   return 0;
303 }
304
305 /**
306  * Cleanup plugin
307  */
308 static void
309 _cleanup(void) {
310   oonf_telnet_remove(&_telnet_commands[0]);
311 }
312
313 /**
314  * Callback for the telnet command of this plugin
315  * @param con pointer to telnet session data
316  * @return telnet result value
317  */
318 static enum oonf_telnet_result
319 _cb_systeminfo(struct oonf_telnet_data *con) {
320   return oonf_viewer_telnet_handler(
321     con->out, &_template_storage, OONF_SYSTEMINFO_SUBSYSTEM, con->parameter, _templates, ARRAYSIZE(_templates));
322 }
323
324 /**
325  * Callback for the help output of this plugin
326  * @param con pointer to telnet session data
327  * @return telnet result value
328  */
329 static enum oonf_telnet_result
330 _cb_systeminfo_help(struct oonf_telnet_data *con) {
331   return oonf_viewer_telnet_help(
332     con->out, OONF_SYSTEMINFO_SUBSYSTEM, con->parameter, _templates, ARRAYSIZE(_templates));
333 }
334
335 /**
336  * Initialize the value buffers for the time of the system
337  */
338 static void
339 _initialize_time_values(struct oonf_viewer_template *template) {
340   oonf_log_get_walltime(&_value_system_time);
341   isonumber_from_u64(&_value_internal_time, oonf_clock_getNow(), "", 3, template->create_raw);
342 }
343
344 /**
345  * Initialize the value buffers for the version of OONF
346  */
347 static void
348 _initialize_version_values(struct oonf_viewer_template *template __attribute__((unused))) {
349   strscpy(_value_version_text, oonf_log_get_libdata()->version, sizeof(_value_version_text));
350   strscpy(_value_version_commit, oonf_log_get_libdata()->git_commit, sizeof(_value_version_commit));
351 }
352
353 /**
354  * Initialize the value buffers for a memory class
355  */
356 static void
357 _initialize_memory_values(struct oonf_viewer_template *template, struct oonf_class *cl) {
358   strscpy(_value_stat_name, cl->name, sizeof(_value_stat_name));
359
360   isonumber_from_u64(&_value_memory_usage, oonf_class_get_usage(cl), "", 0, template->create_raw);
361   isonumber_from_u64(&_value_memory_freelist, oonf_class_get_free(cl), "", 0, template->create_raw);
362   isonumber_from_u64(&_value_memory_alloc, oonf_class_get_allocations(cl), "", 0, template->create_raw);
363   isonumber_from_u64(&_value_memory_recycled, oonf_class_get_recycled(cl), "", 0, template->create_raw);
364 }
365
366 /**
367  * Initialize the value buffers for a timer class
368  */
369 static void
370 _initialize_timer_values(struct oonf_viewer_template *template, struct oonf_timer_class *tc) {
371   strscpy(_value_stat_name, tc->name, sizeof(_value_stat_name));
372
373   isonumber_from_u64(&_value_timer_usage, oonf_timer_get_usage(tc), "", 0, template->create_raw);
374   isonumber_from_u64(&_value_timer_change, oonf_timer_get_changes(tc), "", 0, template->create_raw);
375   isonumber_from_u64(&_value_timer_fire, oonf_timer_get_fired(tc), "", 0, template->create_raw);
376   isonumber_from_u64(&_value_timer_long, oonf_timer_get_long(tc), "", 0, template->create_raw);
377 }
378
379 /**
380  * Initialize the value buffers for a timer class
381  */
382 static void
383 _initialize_socket_values(struct oonf_viewer_template *template, struct oonf_socket_entry *sock) {
384   strscpy(_value_stat_name, sock->name, sizeof(_value_stat_name));
385
386   isonumber_from_u64(&_value_socket_recv, oonf_socket_get_recv(sock), "", 0, template->create_raw);
387   isonumber_from_u64(&_value_socket_send, oonf_socket_get_send(sock), "", 0, template->create_raw);
388   isonumber_from_u64(&_value_socket_long, oonf_socket_get_long(sock), "", 0, template->create_raw);
389 }
390
391 /**
392  * Initialize the value buffers for a logging source
393  * @param template viewer template
394  * @param source logging source
395  */
396 static void
397 _initialize_logging_values(struct oonf_viewer_template *template, enum oonf_log_source source) {
398   strscpy(_value_log_source, LOG_SOURCE_NAMES[source], sizeof(_value_log_source));
399   isonumber_from_u64(&_value_log_warnings, oonf_log_get_warning_count(source), "", 0, template->create_raw);
400 }
401
402 /**
403  * Callback to generate text/json description of current time
404  * @param template viewer template
405  * @return -1 if an error happened, 0 otherwise
406  */
407 static int
408 _cb_create_text_time(struct oonf_viewer_template *template) {
409   /* initialize values */
410   _initialize_time_values(template);
411
412   /* generate template output */
413   oonf_viewer_output_print_line(template);
414   return 0;
415 }
416
417 /**
418  * Callback to generate text/json description of version of OONF
419  * @param template viewer template
420  * @return -1 if an error happened, 0 otherwise
421  */
422 static int
423 _cb_create_text_version(struct oonf_viewer_template *template) {
424   /* initialize values */
425   _initialize_version_values(template);
426
427   /* generate template output */
428   oonf_viewer_output_print_line(template);
429   return 0;
430 }
431
432 /**
433  * Callback to generate text/json description of registered memory blocks
434  * @param template viewer template
435  * @return -1 if an error happened, 0 otherwise
436  */
437 static int
438 _cb_create_text_memory(struct oonf_viewer_template *template) {
439   struct oonf_class *c;
440
441   avl_for_each_element(oonf_class_get_tree(), c, _node) {
442     _initialize_memory_values(template, c);
443
444     /* generate template output */
445     oonf_viewer_output_print_line(template);
446   }
447
448   return 0;
449 }
450
451 /**
452  * Callback to generate text/json description of registered timers
453  * @param template viewer template
454  * @return -1 if an error happened, 0 otherwise
455  */
456 static int
457 _cb_create_text_timer(struct oonf_viewer_template *template) {
458   struct oonf_timer_class *tc;
459
460   list_for_each_element(oonf_timer_get_list(), tc, _node) {
461     _initialize_timer_values(template, tc);
462
463     /* generate template output */
464     oonf_viewer_output_print_line(template);
465   }
466
467   return 0;
468 }
469
470 /**
471  * Callback to generate text/json description of registered sockets
472  * @param template viewer template
473  * @return -1 if an error happened, 0 otherwise
474  */
475 static int
476 _cb_create_text_socket(struct oonf_viewer_template *template) {
477   struct oonf_socket_entry *sock;
478
479   list_for_each_element(oonf_socket_get_list(), sock, _node) {
480     _initialize_socket_values(template, sock);
481
482     /* generate template output */
483     oonf_viewer_output_print_line(template);
484   }
485
486   return 0;
487 }
488
489 /**
490  * Callback to generate text/json description for logging sources
491  * @param template viewer template
492  * @return -1 if an error happened, 0 otherwise
493  */
494 static int
495 _cb_create_text_logging(struct oonf_viewer_template *template) {
496   enum oonf_log_source source;
497
498   for (source = 0; source < oonf_log_get_sourcecount(); source++) {
499     _initialize_logging_values(template, source);
500
501     /* generate template output */
502     oonf_viewer_output_print_line(template);
503   }
504
505   return 0;
506 }