]> git.proxmox.com Git - mirror_frr.git/blame - lib/lib_vty.c
Merge pull request #8008 from chiragshah6/yang_nb5
[mirror_frr.git] / lib / lib_vty.c
CommitLineData
718e3744 1/*
1c0d8808 2 * Assorted library VTY commands
718e3744 3 *
b249c083
DL
4 * Copyright (C) 1998 Kunihiro Ishiguro
5 * Copyright (C) 2016-2017 David Lamparter for NetDEF, Inc.
718e3744 6 *
b249c083
DL
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
718e3744 11 *
b249c083
DL
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
718e3744 16 *
896014f4
DL
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
718e3744 20 */
21
22#include <zebra.h>
d09552d0 23/* malloc.h is generally obsolete, however GNU Libc mallinfo wants it. */
fa896a1d 24#ifdef HAVE_MALLOC_H
41be32bf 25#include <malloc.h>
fa896a1d
DL
26#endif
27#ifdef HAVE_MALLOC_MALLOC_H
28#include <malloc/malloc.h>
29#endif
b249c083 30#include <dlfcn.h>
7b90f00c 31#ifdef HAVE_LINK_H
b249c083 32#include <link.h>
7b90f00c 33#endif
718e3744 34
35#include "log.h"
36#include "memory.h"
b249c083 37#include "module.h"
ac4adef4 38#include "defaults.h"
1c0d8808 39#include "lib_vty.h"
6b0655a2 40
718e3744 41/* Looking up memory status from vty interface. */
42#include "vector.h"
43#include "vty.h"
44#include "command.h"
45
51ab4dba 46#if defined(HAVE_MALLINFO2) || defined(HAVE_MALLINFO)
d62a17ae 47static int show_memory_mallinfo(struct vty *vty)
41be32bf 48{
51ab4dba
QY
49#if defined(HAVE_MALLINFO2)
50 struct mallinfo2 minfo = mallinfo2();
51#elif defined(HAVE_MALLINFO)
d62a17ae 52 struct mallinfo minfo = mallinfo();
51ab4dba 53#endif
d62a17ae 54 char buf[MTYPE_MEMSTR_LEN];
55
56 vty_out(vty, "System allocator statistics:\n");
57 vty_out(vty, " Total heap allocated: %s\n",
58 mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.arena));
59 vty_out(vty, " Holding block headers: %s\n",
60 mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.hblkhd));
61 vty_out(vty, " Used small blocks: %s\n",
62 mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.usmblks));
63 vty_out(vty, " Used ordinary blocks: %s\n",
64 mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.uordblks));
65 vty_out(vty, " Free small blocks: %s\n",
66 mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.fsmblks));
67 vty_out(vty, " Free ordinary blocks: %s\n",
68 mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.fordblks));
69 vty_out(vty, " Ordinary blocks: %ld\n",
70 (unsigned long)minfo.ordblks);
71 vty_out(vty, " Small blocks: %ld\n",
72 (unsigned long)minfo.smblks);
73 vty_out(vty, " Holding blocks: %ld\n",
74 (unsigned long)minfo.hblks);
75 vty_out(vty, "(see system documentation for 'mallinfo' for meaning)\n");
76 return 1;
41be32bf
PJ
77}
78#endif /* HAVE_MALLINFO */
79
3b4cd783
DL
80static int qmem_walker(void *arg, struct memgroup *mg, struct memtype *mt)
81{
82 struct vty *vty = arg;
13f1ba41 83 if (!mt) {
d62a17ae 84 vty_out(vty, "--- qmem %s ---\n", mg->name);
13f1ba41
LB
85 vty_out(vty, "%-30s: %8s %-8s%s %8s %9s\n",
86 "Type", "Current#", " Size",
87#ifdef HAVE_MALLOC_USABLE_SIZE
88 " Total",
89#else
90 "",
91#endif
92 "Max#",
93#ifdef HAVE_MALLOC_USABLE_SIZE
94 "MaxBytes"
95#else
96 ""
97#endif
98 );
99 } else {
a0c5e446 100 if (mt->n_max != 0) {
3694c43a
DS
101 char size[32];
102 snprintf(size, sizeof(size), "%6zu", mt->size);
602a6584
DL
103#ifdef HAVE_MALLOC_USABLE_SIZE
104#define TSTR " %9zu"
105#define TARG , mt->total
13f1ba41 106#define TARG2 , mt->max_size
602a6584
DL
107#else
108#define TSTR ""
109#define TARG
13f1ba41 110#define TARG2
602a6584 111#endif
13f1ba41
LB
112 vty_out(vty, "%-30s: %8zu %-8s"TSTR" %8zu"TSTR"\n",
113 mt->name,
d62a17ae 114 mt->n_alloc,
115 mt->size == 0 ? ""
116 : mt->size == SIZE_VAR
13f1ba41 117 ? "variable"
602a6584 118 : size
13f1ba41
LB
119 TARG,
120 mt->n_max
121 TARG2);
3694c43a 122 }
3b4cd783
DL
123 }
124 return 0;
125}
126
127
1c0d8808
DL
128DEFUN_NOSH (show_memory,
129 show_memory_cmd,
130 "show memory",
131 "Show running system information\n"
132 "Memory statistics\n")
718e3744 133{
41be32bf 134#ifdef HAVE_MALLINFO
d62a17ae 135 show_memory_mallinfo(vty);
41be32bf 136#endif /* HAVE_MALLINFO */
fc7948fa 137
d62a17ae 138 qmem_walk(qmem_walker, vty);
139 return CMD_SUCCESS;
718e3744 140}
141
1c0d8808
DL
142DEFUN_NOSH (show_modules,
143 show_modules_cmd,
144 "show modules",
145 "Show running system information\n"
146 "Loaded modules\n")
b249c083 147{
d62a17ae 148 struct frrmod_runtime *plug = frrmod_list;
b249c083 149
d62a17ae 150 vty_out(vty, "%-12s %-25s %s\n\n", "Module Name", "Version",
151 "Description");
152 while (plug) {
153 const struct frrmod_info *i = plug->info;
b249c083 154
d62a17ae 155 vty_out(vty, "%-12s %-25s %s\n", i->name, i->version,
156 i->description);
157 if (plug->dl_handle) {
b249c083 158#ifdef HAVE_DLINFO_ORIGIN
d62a17ae 159 char origin[MAXPATHLEN] = "";
160 dlinfo(plug->dl_handle, RTLD_DI_ORIGIN, &origin);
161#ifdef HAVE_DLINFO_LINKMAP
162 const char *name;
163 struct link_map *lm = NULL;
164 dlinfo(plug->dl_handle, RTLD_DI_LINKMAP, &lm);
165 if (lm) {
166 name = strrchr(lm->l_name, '/');
167 name = name ? name + 1 : lm->l_name;
168 vty_out(vty, "\tfrom: %s/%s\n", origin, name);
169 }
b249c083 170#else
d62a17ae 171 vty_out(vty, "\tfrom: %s \n", origin, plug->load_name);
b249c083 172#endif
d62a17ae 173#else
174 vty_out(vty, "\tfrom: %s\n", plug->load_name);
175#endif
176 }
177 plug = plug->next;
178 }
bfae97a6
MS
179
180 vty_out(vty, "pid: %u\n", (uint32_t)(getpid()));
181
d62a17ae 182 return CMD_SUCCESS;
b249c083
DL
183}
184
ac4adef4
DL
185DEFUN (frr_defaults,
186 frr_defaults_cmd,
187 "frr defaults PROFILE...",
188 "FRRouting global parameters\n"
189 "set of configuration defaults used\n"
190 "profile string\n")
191{
192 char *profile = argv_concat(argv, argc, 2);
193 int rv = CMD_SUCCESS;
194
195 if (!frr_defaults_profile_valid(profile)) {
196 vty_out(vty, "%% WARNING: profile %s is not known in this version\n",
197 profile);
198 rv = CMD_WARNING;
199 }
200 frr_defaults_profile_set(profile);
201 XFREE(MTYPE_TMP, profile);
202 return rv;
203}
204
205DEFUN (frr_version,
206 frr_version_cmd,
207 "frr version VERSION...",
208 "FRRouting global parameters\n"
209 "version configuration was written by\n"
210 "version string\n")
211{
212 char *version = argv_concat(argv, argc, 2);
213
214 frr_defaults_version_set(version);
215 XFREE(MTYPE_TMP, version);
216 return CMD_SUCCESS;
217}
218
f8e6ada8 219static struct call_back {
16ae941f
DS
220 time_t readin_time;
221
f8e6ada8
DS
222 void (*start_config)(void);
223 void (*end_config)(void);
224} callback;
225
16ae941f 226
f8e6ada8
DS
227DEFUN_HIDDEN (start_config,
228 start_config_cmd,
8de2b3d9 229 "XFRR_start_configuration",
f8e6ada8
DS
230 "The Beginning of Configuration\n")
231{
16ae941f
DS
232 callback.readin_time = monotime(NULL);
233
f8e6ada8
DS
234 if (callback.start_config)
235 (*callback.start_config)();
236
237 return CMD_SUCCESS;
238}
239
240DEFUN_HIDDEN (end_config,
241 end_config_cmd,
8de2b3d9 242 "XFRR_end_configuration",
f8e6ada8
DS
243 "The End of Configuration\n")
244{
16ae941f
DS
245 time_t readin_time;
246 char readin_time_str[MONOTIME_STRLEN];
247
248 readin_time = monotime(NULL);
249 readin_time -= callback.readin_time;
250
251 frrtime_to_interval(readin_time, readin_time_str,
252 sizeof(readin_time_str));
253
254 zlog_info("Configuration Read in Took: %s", readin_time_str);
255
f8e6ada8
DS
256 if (callback.end_config)
257 (*callback.end_config)();
258
259 return CMD_SUCCESS;
260}
261
62b43962
IR
262void cmd_init_config_callbacks(void (*start_config_cb)(void),
263 void (*end_config_cb)(void))
f8e6ada8 264{
62b43962
IR
265 callback.start_config = start_config_cb;
266 callback.end_config = end_config_cb;
f8e6ada8
DS
267}
268
269
ac4adef4
DL
270static void defaults_autocomplete(vector comps, struct cmd_token *token)
271{
272 const char **p;
273
274 for (p = frr_defaults_profiles; *p; p++)
275 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, *p));
276}
277
278static const struct cmd_variable_handler default_var_handlers[] = {
279 {.tokenname = "PROFILE", .completions = defaults_autocomplete},
280 {.completions = NULL},
281};
282
1c0d8808 283void lib_cmd_init(void)
718e3744 284{
ac4adef4
DL
285 cmd_variable_handler_register(default_var_handlers);
286
287 install_element(CONFIG_NODE, &frr_defaults_cmd);
288 install_element(CONFIG_NODE, &frr_version_cmd);
289
d62a17ae 290 install_element(VIEW_NODE, &show_memory_cmd);
291 install_element(VIEW_NODE, &show_modules_cmd);
f8e6ada8
DS
292
293 install_element(CONFIG_NODE, &start_config_cmd);
294 install_element(CONFIG_NODE, &end_config_cmd);
718e3744 295}
6b0655a2 296
41be32bf
PJ
297/* Stats querying from users */
298/* Return a pointer to a human friendly string describing
299 * the byte count passed in. E.g:
300 * "0 bytes", "2048 bytes", "110kB", "500MiB", "11GiB", etc.
301 * Up to 4 significant figures will be given.
302 * The pointer returned may be NULL (indicating an error)
303 * or point to the given buffer, or point to static storage.
304 */
d62a17ae 305const char *mtype_memstr(char *buf, size_t len, unsigned long bytes)
41be32bf 306{
d62a17ae 307 unsigned int m, k;
308
309 /* easy cases */
310 if (!bytes)
311 return "0 bytes";
312 if (bytes == 1)
313 return "1 byte";
314
315 /*
316 * When we pass the 2gb barrier mallinfo() can no longer report
317 * correct data so it just does something odd...
318 * Reporting like Terrabytes of data. Which makes users...
319 * edgy.. yes edgy that's the term for it.
320 * So let's just give up gracefully
321 */
322 if (bytes > 0x7fffffff)
323 return "> 2GB";
324
325 m = bytes >> 20;
326 k = bytes >> 10;
327
328 if (m > 10) {
329 if (bytes & (1 << 19))
330 m++;
331 snprintf(buf, len, "%d MiB", m);
332 } else if (k > 10) {
333 if (bytes & (1 << 9))
334 k++;
335 snprintf(buf, len, "%d KiB", k);
336 } else
337 snprintf(buf, len, "%ld bytes", bytes);
338
339 return buf;
41be32bf 340}