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