]>
Commit | Line | Data |
---|---|---|
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 | ||
41be32bf | 46 | #ifdef HAVE_MALLINFO |
d62a17ae | 47 | static int show_memory_mallinfo(struct vty *vty) |
41be32bf | 48 | { |
d62a17ae | 49 | struct mallinfo minfo = mallinfo(); |
50 | char buf[MTYPE_MEMSTR_LEN]; | |
51 | ||
52 | vty_out(vty, "System allocator statistics:\n"); | |
53 | vty_out(vty, " Total heap allocated: %s\n", | |
54 | mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.arena)); | |
55 | vty_out(vty, " Holding block headers: %s\n", | |
56 | mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.hblkhd)); | |
57 | vty_out(vty, " Used small blocks: %s\n", | |
58 | mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.usmblks)); | |
59 | vty_out(vty, " Used ordinary blocks: %s\n", | |
60 | mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.uordblks)); | |
61 | vty_out(vty, " Free small blocks: %s\n", | |
62 | mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.fsmblks)); | |
63 | vty_out(vty, " Free ordinary blocks: %s\n", | |
64 | mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.fordblks)); | |
65 | vty_out(vty, " Ordinary blocks: %ld\n", | |
66 | (unsigned long)minfo.ordblks); | |
67 | vty_out(vty, " Small blocks: %ld\n", | |
68 | (unsigned long)minfo.smblks); | |
69 | vty_out(vty, " Holding blocks: %ld\n", | |
70 | (unsigned long)minfo.hblks); | |
71 | vty_out(vty, "(see system documentation for 'mallinfo' for meaning)\n"); | |
72 | return 1; | |
41be32bf PJ |
73 | } |
74 | #endif /* HAVE_MALLINFO */ | |
75 | ||
3b4cd783 DL |
76 | static int qmem_walker(void *arg, struct memgroup *mg, struct memtype *mt) |
77 | { | |
78 | struct vty *vty = arg; | |
13f1ba41 | 79 | if (!mt) { |
d62a17ae | 80 | vty_out(vty, "--- qmem %s ---\n", mg->name); |
13f1ba41 LB |
81 | vty_out(vty, "%-30s: %8s %-8s%s %8s %9s\n", |
82 | "Type", "Current#", " Size", | |
83 | #ifdef HAVE_MALLOC_USABLE_SIZE | |
84 | " Total", | |
85 | #else | |
86 | "", | |
87 | #endif | |
88 | "Max#", | |
89 | #ifdef HAVE_MALLOC_USABLE_SIZE | |
90 | "MaxBytes" | |
91 | #else | |
92 | "" | |
93 | #endif | |
94 | ); | |
95 | } else { | |
3694c43a DS |
96 | if (mt->n_alloc != 0) { |
97 | char size[32]; | |
98 | snprintf(size, sizeof(size), "%6zu", mt->size); | |
602a6584 DL |
99 | #ifdef HAVE_MALLOC_USABLE_SIZE |
100 | #define TSTR " %9zu" | |
101 | #define TARG , mt->total | |
13f1ba41 | 102 | #define TARG2 , mt->max_size |
602a6584 DL |
103 | #else |
104 | #define TSTR "" | |
105 | #define TARG | |
13f1ba41 | 106 | #define TARG2 |
602a6584 | 107 | #endif |
13f1ba41 LB |
108 | vty_out(vty, "%-30s: %8zu %-8s"TSTR" %8zu"TSTR"\n", |
109 | mt->name, | |
d62a17ae | 110 | mt->n_alloc, |
111 | mt->size == 0 ? "" | |
112 | : mt->size == SIZE_VAR | |
13f1ba41 | 113 | ? "variable" |
602a6584 | 114 | : size |
13f1ba41 LB |
115 | TARG, |
116 | mt->n_max | |
117 | TARG2); | |
3694c43a | 118 | } |
3b4cd783 DL |
119 | } |
120 | return 0; | |
121 | } | |
122 | ||
123 | ||
1c0d8808 DL |
124 | DEFUN_NOSH (show_memory, |
125 | show_memory_cmd, | |
126 | "show memory", | |
127 | "Show running system information\n" | |
128 | "Memory statistics\n") | |
718e3744 | 129 | { |
41be32bf | 130 | #ifdef HAVE_MALLINFO |
d62a17ae | 131 | show_memory_mallinfo(vty); |
41be32bf | 132 | #endif /* HAVE_MALLINFO */ |
fc7948fa | 133 | |
d62a17ae | 134 | qmem_walk(qmem_walker, vty); |
135 | return CMD_SUCCESS; | |
718e3744 | 136 | } |
137 | ||
1c0d8808 DL |
138 | DEFUN_NOSH (show_modules, |
139 | show_modules_cmd, | |
140 | "show modules", | |
141 | "Show running system information\n" | |
142 | "Loaded modules\n") | |
b249c083 | 143 | { |
d62a17ae | 144 | struct frrmod_runtime *plug = frrmod_list; |
b249c083 | 145 | |
d62a17ae | 146 | vty_out(vty, "%-12s %-25s %s\n\n", "Module Name", "Version", |
147 | "Description"); | |
148 | while (plug) { | |
149 | const struct frrmod_info *i = plug->info; | |
b249c083 | 150 | |
d62a17ae | 151 | vty_out(vty, "%-12s %-25s %s\n", i->name, i->version, |
152 | i->description); | |
153 | if (plug->dl_handle) { | |
b249c083 | 154 | #ifdef HAVE_DLINFO_ORIGIN |
d62a17ae | 155 | char origin[MAXPATHLEN] = ""; |
156 | dlinfo(plug->dl_handle, RTLD_DI_ORIGIN, &origin); | |
157 | #ifdef HAVE_DLINFO_LINKMAP | |
158 | const char *name; | |
159 | struct link_map *lm = NULL; | |
160 | dlinfo(plug->dl_handle, RTLD_DI_LINKMAP, &lm); | |
161 | if (lm) { | |
162 | name = strrchr(lm->l_name, '/'); | |
163 | name = name ? name + 1 : lm->l_name; | |
164 | vty_out(vty, "\tfrom: %s/%s\n", origin, name); | |
165 | } | |
b249c083 | 166 | #else |
d62a17ae | 167 | vty_out(vty, "\tfrom: %s \n", origin, plug->load_name); |
b249c083 | 168 | #endif |
d62a17ae | 169 | #else |
170 | vty_out(vty, "\tfrom: %s\n", plug->load_name); | |
171 | #endif | |
172 | } | |
173 | plug = plug->next; | |
174 | } | |
bfae97a6 MS |
175 | |
176 | vty_out(vty, "pid: %u\n", (uint32_t)(getpid())); | |
177 | ||
d62a17ae | 178 | return CMD_SUCCESS; |
b249c083 DL |
179 | } |
180 | ||
ac4adef4 DL |
181 | DEFUN (frr_defaults, |
182 | frr_defaults_cmd, | |
183 | "frr defaults PROFILE...", | |
184 | "FRRouting global parameters\n" | |
185 | "set of configuration defaults used\n" | |
186 | "profile string\n") | |
187 | { | |
188 | char *profile = argv_concat(argv, argc, 2); | |
189 | int rv = CMD_SUCCESS; | |
190 | ||
191 | if (!frr_defaults_profile_valid(profile)) { | |
192 | vty_out(vty, "%% WARNING: profile %s is not known in this version\n", | |
193 | profile); | |
194 | rv = CMD_WARNING; | |
195 | } | |
196 | frr_defaults_profile_set(profile); | |
197 | XFREE(MTYPE_TMP, profile); | |
198 | return rv; | |
199 | } | |
200 | ||
201 | DEFUN (frr_version, | |
202 | frr_version_cmd, | |
203 | "frr version VERSION...", | |
204 | "FRRouting global parameters\n" | |
205 | "version configuration was written by\n" | |
206 | "version string\n") | |
207 | { | |
208 | char *version = argv_concat(argv, argc, 2); | |
209 | ||
210 | frr_defaults_version_set(version); | |
211 | XFREE(MTYPE_TMP, version); | |
212 | return CMD_SUCCESS; | |
213 | } | |
214 | ||
215 | static void defaults_autocomplete(vector comps, struct cmd_token *token) | |
216 | { | |
217 | const char **p; | |
218 | ||
219 | for (p = frr_defaults_profiles; *p; p++) | |
220 | vector_set(comps, XSTRDUP(MTYPE_COMPLETION, *p)); | |
221 | } | |
222 | ||
223 | static const struct cmd_variable_handler default_var_handlers[] = { | |
224 | {.tokenname = "PROFILE", .completions = defaults_autocomplete}, | |
225 | {.completions = NULL}, | |
226 | }; | |
227 | ||
1c0d8808 | 228 | void lib_cmd_init(void) |
718e3744 | 229 | { |
ac4adef4 DL |
230 | cmd_variable_handler_register(default_var_handlers); |
231 | ||
232 | install_element(CONFIG_NODE, &frr_defaults_cmd); | |
233 | install_element(CONFIG_NODE, &frr_version_cmd); | |
234 | ||
d62a17ae | 235 | install_element(VIEW_NODE, &show_memory_cmd); |
236 | install_element(VIEW_NODE, &show_modules_cmd); | |
718e3744 | 237 | } |
6b0655a2 | 238 | |
41be32bf PJ |
239 | /* Stats querying from users */ |
240 | /* Return a pointer to a human friendly string describing | |
241 | * the byte count passed in. E.g: | |
242 | * "0 bytes", "2048 bytes", "110kB", "500MiB", "11GiB", etc. | |
243 | * Up to 4 significant figures will be given. | |
244 | * The pointer returned may be NULL (indicating an error) | |
245 | * or point to the given buffer, or point to static storage. | |
246 | */ | |
d62a17ae | 247 | const char *mtype_memstr(char *buf, size_t len, unsigned long bytes) |
41be32bf | 248 | { |
d62a17ae | 249 | unsigned int m, k; |
250 | ||
251 | /* easy cases */ | |
252 | if (!bytes) | |
253 | return "0 bytes"; | |
254 | if (bytes == 1) | |
255 | return "1 byte"; | |
256 | ||
257 | /* | |
258 | * When we pass the 2gb barrier mallinfo() can no longer report | |
259 | * correct data so it just does something odd... | |
260 | * Reporting like Terrabytes of data. Which makes users... | |
261 | * edgy.. yes edgy that's the term for it. | |
262 | * So let's just give up gracefully | |
263 | */ | |
264 | if (bytes > 0x7fffffff) | |
265 | return "> 2GB"; | |
266 | ||
267 | m = bytes >> 20; | |
268 | k = bytes >> 10; | |
269 | ||
270 | if (m > 10) { | |
271 | if (bytes & (1 << 19)) | |
272 | m++; | |
273 | snprintf(buf, len, "%d MiB", m); | |
274 | } else if (k > 10) { | |
275 | if (bytes & (1 << 9)) | |
276 | k++; | |
277 | snprintf(buf, len, "%d KiB", k); | |
278 | } else | |
279 | snprintf(buf, len, "%ld bytes", bytes); | |
280 | ||
281 | return buf; | |
41be32bf | 282 | } |