1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Assorted library VTY commands
5 * Copyright (C) 1998 Kunihiro Ishiguro
6 * Copyright (C) 2016-2017 David Lamparter for NetDEF, Inc.
10 /* malloc.h is generally obsolete, however GNU Libc mallinfo wants it. */
14 #ifdef HAVE_MALLOC_MALLOC_H
15 #include <malloc/malloc.h>
27 #include "northbound_cli.h"
29 /* Looking up memory status from vty interface. */
34 #if defined(HAVE_MALLINFO2) || defined(HAVE_MALLINFO)
35 static int show_memory_mallinfo(struct vty
*vty
)
37 #if defined(HAVE_MALLINFO2)
38 struct mallinfo2 minfo
= mallinfo2();
39 #elif defined(HAVE_MALLINFO)
40 struct mallinfo minfo
= mallinfo();
42 char buf
[MTYPE_MEMSTR_LEN
];
44 vty_out(vty
, "System allocator statistics:\n");
45 vty_out(vty
, " Total heap allocated: %s\n",
46 mtype_memstr(buf
, MTYPE_MEMSTR_LEN
, minfo
.arena
));
47 vty_out(vty
, " Holding block headers: %s\n",
48 mtype_memstr(buf
, MTYPE_MEMSTR_LEN
, minfo
.hblkhd
));
49 vty_out(vty
, " Used small blocks: %s\n",
50 mtype_memstr(buf
, MTYPE_MEMSTR_LEN
, minfo
.usmblks
));
51 vty_out(vty
, " Used ordinary blocks: %s\n",
52 mtype_memstr(buf
, MTYPE_MEMSTR_LEN
, minfo
.uordblks
));
53 vty_out(vty
, " Free small blocks: %s\n",
54 mtype_memstr(buf
, MTYPE_MEMSTR_LEN
, minfo
.fsmblks
));
55 vty_out(vty
, " Free ordinary blocks: %s\n",
56 mtype_memstr(buf
, MTYPE_MEMSTR_LEN
, minfo
.fordblks
));
57 vty_out(vty
, " Ordinary blocks: %ld\n",
58 (unsigned long)minfo
.ordblks
);
59 vty_out(vty
, " Small blocks: %ld\n",
60 (unsigned long)minfo
.smblks
);
61 vty_out(vty
, " Holding blocks: %ld\n",
62 (unsigned long)minfo
.hblks
);
63 vty_out(vty
, "(see system documentation for 'mallinfo' for meaning)\n");
66 #endif /* HAVE_MALLINFO */
68 static int qmem_walker(void *arg
, struct memgroup
*mg
, struct memtype
*mt
)
70 struct vty
*vty
= arg
;
72 vty_out(vty
, "--- qmem %s ---\n", mg
->name
);
73 vty_out(vty
, "%-30s: %8s %-8s%s %8s %9s\n",
74 "Type", "Current#", " Size",
75 #ifdef HAVE_MALLOC_USABLE_SIZE
81 #ifdef HAVE_MALLOC_USABLE_SIZE
90 snprintf(size
, sizeof(size
), "%6zu", mt
->size
);
91 #ifdef HAVE_MALLOC_USABLE_SIZE
93 #define TARG , mt->total
94 #define TARG2 , mt->max_size
100 vty_out(vty
, "%-30s: %8zu %-8s"TSTR
" %8zu"TSTR
"\n",
104 : mt
->size
== SIZE_VAR
116 DEFUN_NOSH (show_memory
,
119 "Show running system information\n"
120 "Memory statistics\n")
123 show_memory_mallinfo(vty
);
124 #endif /* HAVE_MALLINFO */
126 qmem_walk(qmem_walker
, vty
);
130 DEFUN_NOSH (show_modules
,
133 "Show running system information\n"
136 struct frrmod_runtime
*plug
= frrmod_list
;
138 vty_out(vty
, "%-12s %-25s %s\n\n", "Module Name", "Version",
141 const struct frrmod_info
*i
= plug
->info
;
143 vty_out(vty
, "%-12s %-25s %s\n", i
->name
, i
->version
,
145 if (plug
->dl_handle
) {
146 #ifdef HAVE_DLINFO_ORIGIN
147 char origin
[MAXPATHLEN
] = "";
148 dlinfo(plug
->dl_handle
, RTLD_DI_ORIGIN
, &origin
);
149 #ifdef HAVE_DLINFO_LINKMAP
151 struct link_map
*lm
= NULL
;
152 dlinfo(plug
->dl_handle
, RTLD_DI_LINKMAP
, &lm
);
154 name
= strrchr(lm
->l_name
, '/');
155 name
= name
? name
+ 1 : lm
->l_name
;
156 vty_out(vty
, "\tfrom: %s/%s\n", origin
, name
);
159 vty_out(vty
, "\tfrom: %s \n", origin
, plug
->load_name
);
162 vty_out(vty
, "\tfrom: %s\n", plug
->load_name
);
168 vty_out(vty
, "pid: %u\n", (uint32_t)(getpid()));
175 "frr defaults PROFILE...",
176 "FRRouting global parameters\n"
177 "set of configuration defaults used\n"
180 char *profile
= argv_concat(argv
, argc
, 2);
181 int rv
= CMD_SUCCESS
;
183 if (!frr_defaults_profile_valid(profile
)) {
184 vty_out(vty
, "%% WARNING: profile %s is not known in this version\n",
188 frr_defaults_profile_set(profile
);
189 XFREE(MTYPE_TMP
, profile
);
195 "frr version VERSION...",
196 "FRRouting global parameters\n"
197 "version configuration was written by\n"
200 char *version
= argv_concat(argv
, argc
, 2);
202 frr_defaults_version_set(version
);
203 XFREE(MTYPE_TMP
, version
);
207 static struct call_back
{
210 void (*start_config
)(void);
211 void (*end_config
)(void);
215 DEFUN_NOSH(start_config
, start_config_cmd
, "XFRR_start_configuration",
216 "The Beginning of Configuration\n")
218 callback
.readin_time
= monotime(NULL
);
220 vty
->pending_allowed
= 1;
222 if (callback
.start_config
)
223 (*callback
.start_config
)();
228 DEFUN_NOSH(end_config
, end_config_cmd
, "XFRR_end_configuration",
229 "The End of Configuration\n")
232 char readin_time_str
[MONOTIME_STRLEN
];
235 readin_time
= monotime(NULL
);
236 readin_time
-= callback
.readin_time
;
238 frrtime_to_interval(readin_time
, readin_time_str
,
239 sizeof(readin_time_str
));
241 vty
->pending_allowed
= 0;
242 ret
= nb_cli_pending_commit_check(vty
);
244 zlog_info("Configuration Read in Took: %s", readin_time_str
);
245 zlog_debug("%s: VTY:%p, pending SET-CFG: %u", __func__
, vty
,
246 (uint32_t)vty
->mgmt_num_pending_setcfg
);
249 * If (and only if) we have sent any CLI config commands to MGMTd
250 * FE interface using vty_mgmt_send_config_data() without implicit
251 * commit before, should we need to send an explicit COMMIT-REQ now
252 * to apply all those commands at once.
254 if (vty
->mgmt_num_pending_setcfg
&& vty_mgmt_fe_enabled())
255 vty_mgmt_send_commit_config(vty
, false, false);
257 if (callback
.end_config
)
258 (*callback
.end_config
)();
263 void cmd_init_config_callbacks(void (*start_config_cb
)(void),
264 void (*end_config_cb
)(void))
266 callback
.start_config
= start_config_cb
;
267 callback
.end_config
= end_config_cb
;
271 static void defaults_autocomplete(vector comps
, struct cmd_token
*token
)
275 for (p
= frr_defaults_profiles
; *p
; p
++)
276 vector_set(comps
, XSTRDUP(MTYPE_COMPLETION
, *p
));
279 static const struct cmd_variable_handler default_var_handlers
[] = {
280 {.tokenname
= "PROFILE", .completions
= defaults_autocomplete
},
281 {.completions
= NULL
},
284 void lib_cmd_init(void)
286 cmd_variable_handler_register(default_var_handlers
);
288 install_element(CONFIG_NODE
, &frr_defaults_cmd
);
289 install_element(CONFIG_NODE
, &frr_version_cmd
);
291 install_element(VIEW_NODE
, &show_memory_cmd
);
292 install_element(VIEW_NODE
, &show_modules_cmd
);
294 install_element(CONFIG_NODE
, &start_config_cmd
);
295 install_element(CONFIG_NODE
, &end_config_cmd
);
298 /* Stats querying from users */
299 /* Return a pointer to a human friendly string describing
300 * the byte count passed in. E.g:
301 * "0 bytes", "2048 bytes", "110kB", "500MiB", "11GiB", etc.
302 * Up to 4 significant figures will be given.
303 * The pointer returned may be NULL (indicating an error)
304 * or point to the given buffer, or point to static storage.
306 const char *mtype_memstr(char *buf
, size_t len
, unsigned long bytes
)
317 * When we pass the 2gb barrier mallinfo() can no longer report
318 * correct data so it just does something odd...
319 * Reporting like Terrabytes of data. Which makes users...
320 * edgy.. yes edgy that's the term for it.
321 * So let's just give up gracefully
323 if (bytes
> 0x7fffffff)
330 if (bytes
& (1 << 19))
332 snprintf(buf
, len
, "%d MiB", m
);
334 if (bytes
& (1 << 9))
336 snprintf(buf
, len
, "%d KiB", k
);
338 snprintf(buf
, len
, "%ld bytes", bytes
);