Merge branch 'master' into mpr_rework
[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/common_types.h"
49 #include "common/autobuf.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(
76     struct oonf_viewer_template *template, struct oonf_class *c);
77 static void _initialize_timer_values(
78     struct oonf_viewer_template *template, struct oonf_timer_class *tc);
79 static void _initialize_socket_values(
80     struct oonf_viewer_template *template, struct oonf_socket_entry *sock);
81 static void _initialize_logging_values(
82     struct oonf_viewer_template *template, enum oonf_log_source source);
83
84 static int _cb_create_text_time(struct oonf_viewer_template *);
85 static int _cb_create_text_version(struct oonf_viewer_template *);
86 static int _cb_create_text_memory(struct oonf_viewer_template *);
87 static int _cb_create_text_timer(struct oonf_viewer_template *);
88 static int _cb_create_text_socket(struct oonf_viewer_template *);
89 static int _cb_create_text_logging(struct oonf_viewer_template *);
90
91 /*
92  * list of template keys and corresponding buffers for values.
93  *
94  * The keys are API, so they should not be changed after published
95  */
96
97 /*! template key for system wall-time */
98 #define KEY_TIME_SYSTEM                 "time_system"
99
100 /*! template key for internal OONF relative timestamp */
101 #define KEY_TIME_INTERNAL               "time_internal"
102
103 /*! template key for version text */
104 #define KEY_VERSION_TEXT                "version_text"
105
106 /*! template key for version git commit */
107 #define KEY_VERSION_COMMIT              "version_commit"
108
109 /*! template key for statistic object name */
110 #define KEY_STATISTICS_NAME             "statistics_name"
111
112 /*! template key for current memory usage */
113 #define KEY_MEMORY_USAGE                "memory_usage"
114
115 /*! template key for memory freelist size */
116 #define KEY_MEMORY_FREELIST             "memory_freelist"
117
118 /*! template key for total memory allocations */
119 #define KEY_MEMORY_ALLOC                "memory_alloc"
120
121 /*! template key for recycled memory blocks */
122 #define KEY_MEMORY_RECYCLED             "memory_recycled"
123
124 /*! template key for timer usage */
125 #define KEY_TIMER_USAGE                 "timer_usage"
126
127 /*! template key for timer changes */
128 #define KEY_TIMER_CHANGE                "timer_change"
129
130 /*! template key for timer fired */
131 #define KEY_TIMER_FIRE                  "timer_fire"
132
133 /*! template key for timer long usage events*/
134 #define KEY_TIMER_LONG                  "timer_long"
135
136 /*! template key for socket receive events */
137 #define KEY_SOCKET_RECV                 "socket_recv"
138
139 /*! template key for socket send events */
140 #define KEY_SOCKET_SEND                 "socket_send"
141
142 /*! template key for socket long usage events */
143 #define KEY_SOCKET_LONG                 "socket_long"
144
145 /*! template key for name of logging source */
146 #define KEY_LOG_SOURCE                  "log_source"
147
148 /*! template key for number of warnings per logging source */
149 #define KEY_LOG_WARNINGS                "log_warnings"
150
151 /*
152  * buffer space for values that will be assembled
153  * into the output of the plugin
154  */
155 static struct oonf_walltime_str         _value_system_time;
156 static struct isonumber_str             _value_internal_time;
157
158 static char                             _value_version_text[256];
159 static char                             _value_version_commit[21];
160
161 static char                             _value_stat_name[256];
162
163 static struct isonumber_str             _value_memory_usage;
164 static struct isonumber_str             _value_memory_freelist;
165 static struct isonumber_str             _value_memory_alloc;
166 static struct isonumber_str             _value_memory_recycled;
167
168 static struct isonumber_str             _value_timer_usage;
169 static struct isonumber_str             _value_timer_change;
170 static struct isonumber_str             _value_timer_fire;
171 static struct isonumber_str             _value_timer_long;
172
173 static struct isonumber_str             _value_socket_recv;
174 static struct isonumber_str             _value_socket_send;
175 static struct isonumber_str             _value_socket_long;
176
177 static char                             _value_log_source[64];
178 static struct isonumber_str             _value_log_warnings;
179
180 /* definition of the template data entries for JSON and table output */
181 static struct abuf_template_data_entry _tde_time_key[] = {
182     { KEY_TIME_SYSTEM, _value_system_time.buf, true },
183     { KEY_TIME_INTERNAL, _value_internal_time.buf, false },
184 };
185 static struct abuf_template_data_entry _tde_version_key[] = {
186     { KEY_VERSION_TEXT, _value_version_text, true },
187     { KEY_VERSION_COMMIT, _value_version_commit, true },
188 };
189 static struct abuf_template_data_entry _tde_memory_key[] = {
190     { KEY_STATISTICS_NAME, _value_stat_name, true },
191     { KEY_MEMORY_USAGE, _value_memory_usage.buf, false },
192     { KEY_MEMORY_FREELIST, _value_memory_freelist.buf, false },
193     { KEY_MEMORY_ALLOC, _value_memory_alloc.buf, false },
194     { KEY_MEMORY_RECYCLED, _value_memory_recycled.buf, false },
195 };
196 static struct abuf_template_data_entry _tde_timer_key[] = {
197     { KEY_STATISTICS_NAME, _value_stat_name, true },
198     { KEY_TIMER_USAGE, _value_timer_usage.buf, false },
199     { KEY_TIMER_CHANGE, _value_timer_change.buf, false },
200     { KEY_TIMER_FIRE, _value_timer_fire.buf, false },
201     { KEY_TIMER_LONG, _value_timer_long.buf, false },
202 };
203 static struct abuf_template_data_entry _tde_socket_key[] = {
204     { KEY_STATISTICS_NAME, _value_stat_name, true },
205     { KEY_SOCKET_RECV, _value_socket_recv.buf, false },
206     { KEY_SOCKET_SEND, _value_socket_send.buf, false },
207     { KEY_SOCKET_LONG, _value_socket_long.buf, false },
208 };
209 static struct abuf_template_data_entry _tde_logging_key[] = {
210     { KEY_LOG_SOURCE, _value_log_source, true },
211     { KEY_LOG_WARNINGS, _value_log_warnings.buf, false },
212 };
213
214 static struct abuf_template_storage _template_storage;
215
216 /* Template Data objects (contain one or more Template Data Entries) */
217 static struct abuf_template_data _td_time[] = {
218     { _tde_time_key, ARRAYSIZE(_tde_time_key) },
219 };
220 static struct abuf_template_data _td_version[] = {
221     { _tde_version_key, ARRAYSIZE(_tde_version_key) },
222 };
223 static struct abuf_template_data _td_memory[] = {
224     { _tde_memory_key, ARRAYSIZE(_tde_memory_key) },
225 };
226 static struct abuf_template_data _td_timer[] = {
227     { _tde_timer_key, ARRAYSIZE(_tde_timer_key) },
228 };
229 static struct abuf_template_data _td_socket[] = {
230     { _tde_socket_key, ARRAYSIZE(_tde_socket_key) },
231 };
232 static struct abuf_template_data _td_logging[] = {
233     { _tde_logging_key, ARRAYSIZE(_tde_logging_key) },
234 };
235
236 /* OONF viewer templates (based on Template Data arrays) */
237 static struct oonf_viewer_template _templates[] = {
238     {
239         .data = _td_time,
240         .data_size = ARRAYSIZE(_td_time),
241         .json_name = "time",
242         .cb_function = _cb_create_text_time,
243     },
244     {
245         .data = _td_version,
246         .data_size = ARRAYSIZE(_td_version),
247         .json_name = "version",
248         .cb_function = _cb_create_text_version,
249     },
250     {
251         .data = _td_memory,
252         .data_size = ARRAYSIZE(_td_memory),
253         .json_name = "memory",
254         .cb_function = _cb_create_text_memory,
255     },
256     {
257         .data = _td_timer,
258         .data_size = ARRAYSIZE(_td_timer),
259         .json_name = "timer",
260         .cb_function = _cb_create_text_timer,
261     },
262     {
263         .data = _td_socket,
264         .data_size = ARRAYSIZE(_td_socket),
265         .json_name = "socket",
266         .cb_function = _cb_create_text_socket,
267     },
268     {
269         .data = _td_logging,
270         .data_size = ARRAYSIZE(_td_logging),
271         .json_name = "logging",
272         .cb_function = _cb_create_text_logging,
273     },
274 };
275
276 /* telnet command of this plugin */
277 static struct oonf_telnet_command _telnet_commands[] = {
278     TELNET_CMD(OONF_SYSTEMINFO_SUBSYSTEM, _cb_systeminfo,
279         "", .help_handler = _cb_systeminfo_help),
280 };
281
282 /* plugin declaration */
283 static const char *_dependencies[] = {
284   OONF_CLOCK_SUBSYSTEM,
285   OONF_TELNET_SUBSYSTEM,
286   OONF_VIEWER_SUBSYSTEM,
287 };
288
289 static struct oonf_subsystem _olsrv2_systeminfo_subsystem = {
290   .name = OONF_SYSTEMINFO_SUBSYSTEM,
291   .dependencies = _dependencies,
292   .dependencies_count = ARRAYSIZE(_dependencies),
293   .descr = "OLSRv2 system info plugin",
294   .author = "Henning Rogge",
295   .init = _init,
296   .cleanup = _cleanup,
297 };
298 DECLARE_OONF_PLUGIN(_olsrv2_systeminfo_subsystem);
299
300 /**
301  * Initialize plugin
302  * @return -1 if an error happened, 0 otherwise
303  */
304 static int
305 _init(void) {
306   oonf_telnet_add(&_telnet_commands[0]);
307   return 0;
308 }
309
310 /**
311  * Cleanup plugin
312  */
313 static void
314 _cleanup(void) {
315   oonf_telnet_remove(&_telnet_commands[0]);
316 }
317
318 /**
319  * Callback for the telnet command of this plugin
320  * @param con pointer to telnet session data
321  * @return telnet result value
322  */
323 static enum oonf_telnet_result
324 _cb_systeminfo(struct oonf_telnet_data *con) {
325   return oonf_viewer_telnet_handler(con->out, &_template_storage,
326       OONF_SYSTEMINFO_SUBSYSTEM, con->parameter,
327       _templates, ARRAYSIZE(_templates));
328 }
329
330 /**
331  * Callback for the help output of this plugin
332  * @param con pointer to telnet session data
333  * @return telnet result value
334  */
335 static enum oonf_telnet_result
336 _cb_systeminfo_help(struct oonf_telnet_data *con) {
337   return oonf_viewer_telnet_help(con->out, OONF_SYSTEMINFO_SUBSYSTEM,
338       con->parameter, _templates, ARRAYSIZE(_templates));
339 }
340
341 /**
342  * Initialize the value buffers for the time of the system
343  */
344 static void
345 _initialize_time_values(struct oonf_viewer_template *template) {
346   oonf_log_get_walltime(&_value_system_time);
347   isonumber_from_u64(&_value_internal_time, oonf_clock_getNow(),
348       "", 3, false, template->create_raw);
349 }
350
351 /**
352  * Initialize the value buffers for the version of OONF
353  */
354 static void
355 _initialize_version_values(
356     struct oonf_viewer_template *template __attribute__((unused))) {
357   strscpy(_value_version_text, oonf_log_get_libdata()->version,
358       sizeof(_value_version_text));
359   strscpy(_value_version_commit, oonf_log_get_libdata()->git_commit,
360       sizeof(_value_version_commit));
361 }
362
363 /**
364  * Initialize the value buffers for a memory class
365  */
366 static void
367 _initialize_memory_values(struct oonf_viewer_template *template,
368     struct oonf_class *cl) {
369   strscpy(_value_stat_name, cl->name, sizeof(_value_stat_name));
370
371   isonumber_from_u64(&_value_memory_usage,
372       oonf_class_get_usage(cl), "", 0, false, template->create_raw);
373   isonumber_from_u64(&_value_memory_freelist,
374       oonf_class_get_free(cl), "", 0, false, template->create_raw);
375   isonumber_from_u64(&_value_memory_alloc,
376       oonf_class_get_allocations(cl), "", 0, false, template->create_raw);
377   isonumber_from_u64(&_value_memory_recycled,
378       oonf_class_get_recycled(cl), "", 0, false, template->create_raw);
379 }
380
381 /**
382  * Initialize the value buffers for a timer class
383  */
384 static void
385 _initialize_timer_values(struct oonf_viewer_template *template,
386     struct oonf_timer_class *tc) {
387   strscpy(_value_stat_name, tc->name, sizeof(_value_stat_name));
388
389   isonumber_from_u64(&_value_timer_usage,
390       oonf_timer_get_usage(tc), "", 0, false, template->create_raw);
391   isonumber_from_u64(&_value_timer_change,
392       oonf_timer_get_changes(tc), "", 0, false, template->create_raw);
393   isonumber_from_u64(&_value_timer_fire,
394       oonf_timer_get_fired(tc), "", 0, false, template->create_raw);
395   isonumber_from_u64(&_value_timer_long,
396       oonf_timer_get_long(tc), "", 0, false, template->create_raw);
397 }
398
399 /**
400  * Initialize the value buffers for a timer class
401  */
402 static void
403 _initialize_socket_values(struct oonf_viewer_template *template,
404     struct oonf_socket_entry *sock) {
405   strscpy(_value_stat_name, sock->name, sizeof(_value_stat_name));
406
407   isonumber_from_u64(&_value_socket_recv,
408       oonf_socket_get_recv(sock), "", 0, false, template->create_raw);
409   isonumber_from_u64(&_value_socket_send,
410       oonf_socket_get_send(sock), "", 0, false, template->create_raw);
411   isonumber_from_u64(&_value_socket_long,
412       oonf_socket_get_long(sock), "", 0, false, template->create_raw);
413 }
414
415 /**
416  * Initialize the value buffers for a logging source
417  * @param template
418  * @param source
419  */
420 static void _initialize_logging_values(
421     struct oonf_viewer_template *template, enum oonf_log_source source) {
422   strscpy(_value_log_source, LOG_SOURCE_NAMES[source],
423       sizeof(_value_log_source));
424   isonumber_from_u64(&_value_log_warnings,
425       oonf_log_get_warning_count(source), "", 0, false, template->create_raw);
426 }
427
428 /**
429  * Callback to generate text/json description of current time
430  * @param template viewer template
431  * @return -1 if an error happened, 0 otherwise
432  */
433 static int
434 _cb_create_text_time(struct oonf_viewer_template *template) {
435   /* initialize values */
436   _initialize_time_values(template);
437
438   /* generate template output */
439   oonf_viewer_output_print_line(template);
440   return 0;
441 }
442
443 /**
444  * Callback to generate text/json description of version of OONF
445  * @param template viewer template
446  * @return -1 if an error happened, 0 otherwise
447  */
448 static int
449 _cb_create_text_version(struct oonf_viewer_template *template) {
450   /* initialize values */
451   _initialize_version_values(template);
452
453   /* generate template output */
454   oonf_viewer_output_print_line(template);
455   return 0;
456 }
457
458 /**
459  * Callback to generate text/json description of registered memory blocks
460  * @param template viewer template
461  * @return -1 if an error happened, 0 otherwise
462  */
463 static int
464 _cb_create_text_memory(struct oonf_viewer_template *template) {
465   struct oonf_class *c;
466
467   avl_for_each_element(oonf_class_get_tree(), c, _node) {
468     _initialize_memory_values(template, c);
469
470     /* generate template output */
471     oonf_viewer_output_print_line(template);
472   }
473
474   return 0;
475 }
476
477 /**
478  * Callback to generate text/json description of registered timers
479  * @param template viewer template
480  * @return -1 if an error happened, 0 otherwise
481  */
482 static int
483 _cb_create_text_timer(struct oonf_viewer_template *template) {
484   struct oonf_timer_class *tc;
485
486   list_for_each_element(oonf_timer_get_list(), tc, _node) {
487     _initialize_timer_values(template, tc);
488
489     /* generate template output */
490     oonf_viewer_output_print_line(template);
491   }
492
493   return 0;
494 }
495
496 /**
497  * Callback to generate text/json description of registered sockets
498  * @param template viewer template
499  * @return -1 if an error happened, 0 otherwise
500  */
501 static int
502 _cb_create_text_socket(struct oonf_viewer_template *template) {
503   struct oonf_socket_entry *sock;
504
505   list_for_each_element(oonf_socket_get_list(), sock, _node) {
506     _initialize_socket_values(template, sock);
507
508     /* generate template output */
509     oonf_viewer_output_print_line(template);
510   }
511
512   return 0;
513 }
514
515 /**
516  * Callback to generate text/json description for logging sources
517  * @param template viewer template
518  * @return -1 if an error happened, 0 otherwise
519  */
520 static int
521 _cb_create_text_logging(struct oonf_viewer_template *template) {
522   enum oonf_log_source source;
523
524   for (source = 0; source < oonf_log_get_sourcecount(); source++) {
525     _initialize_logging_values(template, source);
526
527     /* generate template output */
528     oonf_viewer_output_print_line(template);
529   }
530
531   return 0;
532 }